summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Baier <hansfbaier@googlemail.com>2008-08-04 22:37:24 +0000
committerHans Baier <hansfbaier@googlemail.com>2008-08-04 22:37:24 +0000
commited990de6040215412baf8f448b1876d78bd9cc19 (patch)
tree196c6552040b0ad1c9c402cba2b4543ae39536ef
parent44fd104ada0fbd8b76d34150e941d85d6de6f81b (diff)
* first implementation of MIDI Clock Slave support
git-svn-id: svn://localhost/ardour2/branches/3.0@3652 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/ardour.menus1
-rw-r--r--gtk2_ardour/ardour_ui.h61
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc58
-rw-r--r--gtk2_ardour/ardour_ui_options.cc58
-rw-r--r--gtk2_ardour/option_editor.cc171
-rw-r--r--gtk2_ardour/option_editor.h11
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/ardour/ardour.h7
-rw-r--r--libs/ardour/ardour/configuration_vars.h6
-rw-r--r--libs/ardour/ardour/session.h188
-rw-r--r--libs/ardour/ardour/slave.h92
-rw-r--r--libs/ardour/ardour/types.h45
-rw-r--r--libs/ardour/enums.cc35
-rw-r--r--libs/ardour/globals.cc75
-rw-r--r--libs/ardour/session.cc664
-rw-r--r--libs/ardour/session_midi.cc221
-rw-r--r--libs/ardour/session_transport.cc210
-rw-r--r--libs/ardour/utils.cc65
-rw-r--r--libs/midi++2/midi++/midnam_patch.h50
-rw-r--r--libs/midi++2/midnam_patch.cc53
20 files changed, 1169 insertions, 903 deletions
diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus
index 66584fe79b..e9b4800ae9 100644
--- a/gtk2_ardour/ardour.menus
+++ b/gtk2_ardour/ardour.menus
@@ -393,6 +393,7 @@
<menuitem action='SendMTC'/>
<menuitem action='SendMMC'/>
<menuitem action='UseMMC'/>
+ <menuitem action='UseMIDIClock'/>
</menu>
<menu action="TempoMenu">
<menuitem action='set-tempo-from-region'/>
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 556a7e9b8c..442d319f77 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1999-2002 Paul Davis
+ Copyright (C) 1999-2002 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
@@ -110,18 +110,18 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void show ();
bool shown() { return shown_flag; }
-
+
void show_splash ();
void hide_splash ();
void show_about ();
void hide_about ();
-
+
void idle_load (const Glib::ustring& path);
int load_session (const Glib::ustring& path, const Glib::ustring& snapshot, Glib::ustring mix_template = Glib::ustring());
bool session_loaded;
- int build_session (const Glib::ustring& path, const Glib::ustring& snapshot,
- uint32_t ctl_chns,
+ int build_session (const Glib::ustring& path, const Glib::ustring& snapshot,
+ uint32_t ctl_chns,
uint32_t master_chns,
ARDOUR::AutoConnectOption input_connect,
ARDOUR::AutoConnectOption output_connect,
@@ -145,10 +145,10 @@ class ARDOUR_UI : public Gtkmm2ext::UI
int load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session);
int build_session_from_nsd (const Glib::ustring& session_name, const Glib::ustring& session_path);
bool ask_about_loading_existing_session (const Glib::ustring& session_path);
-
+
/// @return true if session was successfully unloaded.
int unload_session (bool hide_stuff = false);
- void close_session();
+ void close_session();
int save_state_canfail (string state_name = "");
void save_state (const string & state_name = "");
@@ -212,7 +212,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void restore_clock_modes ();
void add_route (Gtk::Window* float_window);
-
+
void session_add_audio_track (int input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many) {
session_add_audio_route (true, input_channels, output_channels, mode, how_many);
}
@@ -260,7 +260,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_click ();
void toggle_session_auto_loop ();
-
+
void toggle_options_window ();
private:
@@ -295,7 +295,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void goto_editor_window ();
void goto_mixer_window ();
-
+
Gtk::Table adjuster_table;
Gtk::Frame adjuster_frame;
Gtk::Fixed adjuster_base;
@@ -334,7 +334,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void queue_transport_change ();
void map_transport_state ();
int32_t do_engine_start ();
-
+
void engine_halted ();
void engine_stopped ();
void engine_running ();
@@ -359,7 +359,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void stop_clocking ();
void manage_window (Gtk::Window&);
-
+
AudioClock big_clock;
Gtk::Frame big_clock_frame;
Gtk::Window* big_clock_window;
@@ -399,15 +399,15 @@ class ARDOUR_UI : public Gtkmm2ext::UI
AutoLoop,
PlaySelection,
ShuttleControl
-
+
};
-
+
TransportControllable (std::string name, ARDOUR_UI&, ToggleType);
void set_value (float);
float get_value (void) const;
-
+
void set_id (const std::string&);
-
+
ARDOUR_UI& ui;
ToggleType type;
};
@@ -505,7 +505,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
Gtk::Menu* session_popup_menu;
struct RecentSessionModelColumns : public Gtk::TreeModel::ColumnRecord {
- RecentSessionModelColumns() {
+ RecentSessionModelColumns() {
add (visible_name);
add (fullpath);
}
@@ -519,7 +519,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
ArdourDialog* session_selector_window;
Gtk::FileChooserDialog* open_session_selector;
-
+
void build_session_selector();
void redisplay_recent_sessions();
void recent_session_row_activated (const Gtk::TreePath& path, Gtk::TreeViewColumn* col);
@@ -574,7 +574,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
bool _will_create_new_session_automatically;
NewSessionDialog* new_session_dialog;
-
+
void open_session ();
void open_recent_session ();
void save_template ();
@@ -593,7 +593,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void transport_stop_and_forget_capture ();
void transport_record (bool roll);
void transport_roll ();
- void transport_play_selection();
+ void transport_play_selection();
void transport_forward (int option);
void transport_rewind (int option);
void transport_loop ();
@@ -607,16 +607,16 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void connect_to_session (ARDOUR::Session *);
void connect_dependents_to_session (ARDOUR::Session *);
void we_have_dependents ();
-
+
void setup_session_options ();
-
+
guint32 last_key_press_time;
void snapshot_session ();
Mixer_UI *mixer;
int create_mixer ();
-
+
PublicEditor *editor;
int create_editor ();
@@ -641,15 +641,15 @@ class ARDOUR_UI : public Gtkmm2ext::UI
KeyEditor *key_editor;
/* Options window */
-
+
OptionEditor *option_editor;
-
+
/* route dialog */
AddRouteDialog *add_route_dialog;
-
+
/* Keyboard Handling */
-
+
Keyboard* keyboard;
/* Keymap handling */
@@ -689,7 +689,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void session_dialog (std::string);
int pending_state_dialog ();
int sr_mismatch_dialog (nframes_t, nframes_t);
-
+
void disconnect_from_jack ();
void reconnect_to_jack ();
void set_jack_buffer_size (nframes_t);
@@ -711,6 +711,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_use_mmc ();
void toggle_send_mmc ();
void toggle_send_mtc ();
+ void toggle_use_midi_clock ();
void toggle_use_osc ();
@@ -774,11 +775,11 @@ class ARDOUR_UI : public Gtkmm2ext::UI
bool check_audioengine();
void audioengine_setup ();
- void display_message (const char *prefix, gint prefix_len,
+ void display_message (const char *prefix, gint prefix_len,
Glib::RefPtr<Gtk::TextBuffer::Tag> ptag, Glib::RefPtr<Gtk::TextBuffer::Tag> mtag, const char *msg);
Gtk::Label status_bar_label;
Gtk::ToggleButton error_log_button;
-
+
void loading_message (const std::string& msg);
void end_loading_messages ();
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index 95e6dd6906..7eb13892ee 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 20002-2004 Paul Davis
+ Copyright (C) 20002-2004 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
@@ -112,11 +112,11 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_action (main_actions, X_("Close"), _("Close"), mem_fun(*this, &ARDOUR_UI::close_session));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (main_actions, X_("AddTrackBus"), _("Add Track/Bus"),
+ act = ActionManager::register_action (main_actions, X_("AddTrackBus"), _("Add Track/Bus"),
bind (mem_fun(*this, &ARDOUR_UI::add_route), (Gtk::Window*) 0));
ActionManager::session_sensitive_actions.push_back (act);
-
+
#ifdef WITH_CMT
sys::path anicomp_file_path;
@@ -152,7 +152,7 @@ ARDOUR_UI::install_actions ()
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("FlushWastebasket"), _("Flush wastebasket"), mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::flush_trash));
ActionManager::session_sensitive_actions.push_back (act);
-
+
/* JACK actions for controlling ... JACK */
Glib::RefPtr<ActionGroup> jack_actions = ActionGroup::create (X_("JACK"));
@@ -164,9 +164,9 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_action (jack_actions, X_("JACKDisconnect"), _("Disconnect"), mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::disconnect_from_jack));
ActionManager::jack_sensitive_actions.push_back (act);
-
+
RadioAction::Group jack_latency_group;
-
+
act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency32"), X_("32"), bind (mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (nframes_t) 32));
ActionManager::jack_sensitive_actions.push_back (act);
act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency64"), X_("64"), bind (mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (nframes_t) 64));
@@ -185,9 +185,9 @@ ARDOUR_UI::install_actions ()
ActionManager::jack_sensitive_actions.push_back (act);
act = ActionManager::register_radio_action (jack_actions, jack_latency_group, X_("JACKLatency8192"), X_("8192"), bind (mem_fun(*this, &ARDOUR_UI::set_jack_buffer_size), (nframes_t) 8192));
ActionManager::jack_sensitive_actions.push_back (act);
-
+
/* these actions are intended to be shared across all windows */
-
+
common_actions = ActionGroup::create (X_("Common"));
ActionManager::register_action (main_actions, X_("WindowMenu"), _("Window"));
ActionManager::register_action (common_actions, X_("Quit"), _("Quit"), (mem_fun(*this, &ARDOUR_UI::finish)));
@@ -211,7 +211,7 @@ ARDOUR_UI::install_actions ()
ActionManager::register_toggle_action (common_actions, X_("ToggleThemeManager"), _("Theme Manager"), mem_fun(*this, &ARDOUR_UI::toggle_theme_manager));
ActionManager::register_toggle_action (common_actions, X_("ToggleKeyEditor"), _("Keybindings"), mem_fun(*this, &ARDOUR_UI::toggle_key_editor));
ActionManager::register_toggle_action (common_actions, X_("ToggleBundleManager"), _("Bundle Manager"), mem_fun(*this, &ARDOUR_UI::toggle_bundle_manager));
-
+
act = ActionManager::register_action (common_actions, X_("AddAudioTrack"), _("Add Audio Track"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_track), 1, 1, ARDOUR::Normal, 1));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (common_actions, X_("AddAudioBus"), _("Add Audio Bus"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_bus), 1, 1, 1));
@@ -234,7 +234,7 @@ ARDOUR_UI::install_actions ()
/* these two are not used by key bindings, instead use ToggleRoll for that. these two do show up in
menus and via button proxies.
*/
-
+
act = ActionManager::register_action (transport_actions, X_("Stop"), _("Stop"), mem_fun(*this, &ARDOUR_UI::transport_stop));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::transport_sensitive_actions.push_back (act);
@@ -418,7 +418,7 @@ ARDOUR_UI::install_actions ()
ActionManager::session_sensitive_actions.push_back (act);
Glib::RefPtr<ActionGroup> shuttle_actions = ActionGroup::create ("ShuttleActions");
-
+
shuttle_actions->add (Action::create (X_("SetShuttleUnitsPercentage"), _("Percentage")), hide_return (bind (mem_fun (*Config, &Configuration::set_shuttle_units), Percentage)));
shuttle_actions->add (Action::create (X_("SetShuttleUnitsSemitones"), _("Semitones")), hide_return (bind (mem_fun (*Config, &Configuration::set_shuttle_units), Semitones)));
@@ -430,6 +430,8 @@ ARDOUR_UI::install_actions ()
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (option_actions, X_("UseMMC"), _("Use MMC"), mem_fun (*this, &ARDOUR_UI::toggle_use_mmc));
ActionManager::session_sensitive_actions.push_back (act);
+ act = ActionManager::register_toggle_action (option_actions, X_("UseMIDIClock"), _("Use MIDI Clock"), mem_fun (*this, &ARDOUR_UI::toggle_use_midi_clock));
+ ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (option_actions, X_("SendMIDIfeedback"), _("Send MIDI feedback"), mem_fun (*this, &ARDOUR_UI::toggle_send_midi_feedback));
ActionManager::session_sensitive_actions.push_back (act);
@@ -451,7 +453,7 @@ ARDOUR_UI::install_actions ()
ActionManager::register_toggle_action (option_actions, X_("LatchedRecordEnable"), _("Rec-enable stays engaged at stop"), mem_fun (*this, &ARDOUR_UI::toggle_LatchedRecordEnable));
ActionManager::register_toggle_action (option_actions, X_("RegionEquivalentsOverlap"), _("Region equivalents overlap"), mem_fun (*this, &ARDOUR_UI::toggle_RegionEquivalentsOverlap));
ActionManager::register_toggle_action (option_actions, X_("PrimaryClockDeltaEditCursor"), _("Primary Clock delta to edit point"), mem_fun (*this, &ARDOUR_UI::toggle_PrimaryClockDeltaEditCursor));
- ActionManager::register_toggle_action (option_actions, X_("SecondaryClockDeltaEditCursor"), _("Secondary Clock delta to edit point"), mem_fun (*this, &ARDOUR_UI::toggle_SecondaryClockDeltaEditCursor));
+ ActionManager::register_toggle_action (option_actions, X_("SecondaryClockDeltaEditCursor"), _("Secondary Clock delta to edit point"), mem_fun (*this, &ARDOUR_UI::toggle_SecondaryClockDeltaEditCursor));
ActionManager::register_toggle_action (option_actions, X_("ShowTrackMeters"), _("Enable Editor Meters"), mem_fun (*this, &ARDOUR_UI::toggle_ShowTrackMeters));
ActionManager::register_toggle_action (option_actions, X_("OnlyCopyImportedFiles"), _("Always copy imported files"), mem_fun (*this, &ARDOUR_UI::toggle_only_copy_imported_files));
ActionManager::register_toggle_action (option_actions, X_("RubberbandingSnapsToGrid"), _("Rubberbanding Snaps to Grid"), mem_fun (*this, &ARDOUR_UI::toggle_rubberbanding_snaps_to_grid));
@@ -500,7 +502,7 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_toggle_action (option_actions, X_("DoNotRunPluginsWhileRecording"), _("Do not run plugins while recording"), mem_fun (*this, &ARDOUR_UI::toggle_DoNotRunPluginsWhileRecording));
ActionManager::session_sensitive_actions.push_back (act);
-
+
act = ActionManager::register_toggle_action (option_actions, X_("LatchedSolo"), _("Latched solo"), mem_fun (*this, &ARDOUR_UI::toggle_LatchedSolo));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (option_actions, X_("ShowSoloMutes"), _("Show solo muting"), mem_fun (*this, &ARDOUR_UI::toggle_ShowSoloMutes));
@@ -547,7 +549,7 @@ ARDOUR_UI::install_actions ()
RadioAction::Group monitoring_group;
- /* it would be nice not to even show this item, but that messes up the
+ /* it would be nice not to even show this item, but that messes up the
menus which are not dynamically modified at runtime. so we make it
sensitive only if it makes sense.
*/
@@ -717,20 +719,20 @@ ARDOUR_UI::build_control_surface_menu ()
string action_name = "Toggle";
action_name += legalize_for_path ((*i)->name);
action_name += "Surface";
-
+
string action_label = (*i)->name;
-
+
Glib::RefPtr<Action> act = ActionManager::register_toggle_action (editor->editor_actions, action_name.c_str(), action_label.c_str(),
(bind (mem_fun (*this, &ARDOUR_UI::toggle_control_protocol), *i)));
-
+
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
with_feedback = false;
-
+
if ((*i)->protocol || (*i)->requested) {
tact->set_active ();
}
-
+
ui += "<menuitem action='";
ui += action_name;
ui += "'/>\n";
@@ -738,7 +740,7 @@ ARDOUR_UI::build_control_surface_menu ()
if ((*i)->supports_feedback) {
string submenu_name = action_name;
-
+
submenu_name += "SubMenu";
ActionManager::register_action (editor->editor_actions, submenu_name.c_str(), _("Controls"));
@@ -746,17 +748,17 @@ ARDOUR_UI::build_control_surface_menu ()
action_name += "Feedback";
Glib::RefPtr<Action> act = ActionManager::register_toggle_action (editor->editor_actions, action_name.c_str(), _("Feedback"),
- (bind (mem_fun (*this, &ARDOUR_UI::toggle_control_protocol_feedback),
- *i,
+ (bind (mem_fun (*this, &ARDOUR_UI::toggle_control_protocol_feedback),
+ *i,
"Editor",
action_name)));
-
+
ui += "<menu action='";
ui += submenu_name;
ui += "'>\n<menuitem action='";
ui += action_name;
ui += "'/>\n</menu>\n";
-
+
if ((*i)->protocol) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
tact->set_active ((*i)->protocol->get_feedback ());
@@ -786,7 +788,7 @@ ARDOUR_UI::build_menu_bar ()
* when the first menu instance is created.
*/
// XXX bug in gtkmm causes this to popup an error message
- // Gtk::Settings::get_default()->property_gtk_can_change_accels() = true;
+ // Gtk::Settings::get_default()->property_gtk_can_change_accels() = true;
// so use this instead ...
gtk_settings_set_long_property (gtk_settings_get_default(), "gtk-can-change-accels", 1, "Ardour:designers");
@@ -817,7 +819,7 @@ ARDOUR_UI::build_menu_bar ()
#endif
if (!Profile->get_small_screen()) {
-#ifndef GTKOSX
+#ifndef GTKOSX
// OSX provides its own wallclock, thank you very much
menu_hbox.pack_end (wall_clock_box, false, false, 2);
#endif
@@ -846,9 +848,9 @@ void
ARDOUR_UI::setup_clock ()
{
ARDOUR_UI::Clock.connect (bind (mem_fun (big_clock, &AudioClock::set), false));
-
+
big_clock_window = new Window (WINDOW_TOPLEVEL);
-
+
big_clock_window->set_keep_above (true);
big_clock_window->set_border_width (0);
big_clock_window->add (big_clock);
diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc
index fca80f1e3e..75d33d9416 100644
--- a/gtk2_ardour/ardour_ui_options.cc
+++ b/gtk2_ardour/ardour_ui_options.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2005 Paul Davis
+ Copyright (C) 2005 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
@@ -68,6 +68,12 @@ ARDOUR_UI::toggle_use_mmc ()
}
void
+ARDOUR_UI::toggle_use_midi_clock ()
+{
+ ActionManager::toggle_config_state ("options", "UseMIDIClock", &Configuration::set_midi_clock_control, &Configuration::get_midi_clock_control);
+}
+
+void
ARDOUR_UI::toggle_use_osc ()
{
ActionManager::toggle_config_state ("options", "UseOSC", &Configuration::set_use_osc, &Configuration::get_use_osc);
@@ -121,7 +127,7 @@ ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
break;
default:
fatal << string_compose (_("programming error: %1"), "illegal file header format in ::set_native_file_header_format") << endmsg;
- /*NOTREACHED*/
+ /*NOTREACHED*/
}
Glib::RefPtr<Action> act = ActionManager::get_action ("options", action);
@@ -168,7 +174,7 @@ void
ARDOUR_UI::set_input_auto_connect (AutoConnectOption option)
{
const char* action;
-
+
switch (option) {
case AutoConnectPhysical:
action = X_("InputAutoConnectPhysical");
@@ -192,7 +198,7 @@ void
ARDOUR_UI::set_output_auto_connect (AutoConnectOption option)
{
const char* action;
-
+
switch (option) {
case AutoConnectPhysical:
action = X_("OutputAutoConnectPhysical");
@@ -224,7 +230,7 @@ ARDOUR_UI::set_solo_model (SoloModel model)
case SoloBus:
action = X_("SoloViaBus");
break;
-
+
case InverseMute:
action = X_("SoloInPlace");
break;
@@ -287,7 +293,7 @@ ARDOUR_UI::set_monitor_model (MonitorModel model)
case HardwareMonitoring:
action = X_("UseHardwareMonitoring");
break;
-
+
case SoftwareMonitoring:
action = X_("UseSoftwareMonitoring");
break;
@@ -325,7 +331,7 @@ ARDOUR_UI::set_denormal_model (DenormalModel model)
case DenormalFTZ:
action = X_("DenormalFTZ");
break;
-
+
case DenormalDAZ:
action = X_("DenormalDAZ");
break;
@@ -395,7 +401,7 @@ void
ARDOUR_UI::unset_dual_punch ()
{
Glib::RefPtr<Action> action = ActionManager::get_action ("Transport", "TogglePunch");
-
+
if (action) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(action);
if (tact) {
@@ -597,6 +603,7 @@ void
ARDOUR_UI::mtc_port_changed ()
{
bool have_mtc;
+ bool have_midi_clock;
if (session) {
if (session->mtc_port()) {
@@ -604,8 +611,14 @@ ARDOUR_UI::mtc_port_changed ()
} else {
have_mtc = false;
}
+ if (session->midi_clock_port()) {
+ have_midi_clock = true;
+ } else {
+ have_midi_clock = false;
+ }
} else {
have_mtc = false;
+ have_midi_clock = false;
}
positional_sync_strings.clear ();
@@ -613,8 +626,11 @@ ARDOUR_UI::mtc_port_changed ()
if (have_mtc) {
positional_sync_strings.push_back (slave_source_to_string (MTC));
}
+ if (have_midi_clock) {
+ positional_sync_strings.push_back (slave_source_to_string (MIDIClock));
+ }
positional_sync_strings.push_back (slave_source_to_string (JACK));
-
+
set_popdown_strings (sync_option_combo, positional_sync_strings);
}
@@ -776,7 +792,7 @@ ARDOUR_UI::map_file_header_format ()
break;
default:
- fatal << string_compose (_("programming error: unknown file header format passed to ARDOUR_UI::map_file_data_format: %1"),
+ fatal << string_compose (_("programming error: unknown file header format passed to ARDOUR_UI::map_file_data_format: %1"),
Config->get_native_file_header_format()) << endmsg;
/*NOTREACHED*/
}
@@ -812,7 +828,7 @@ ARDOUR_UI::map_file_data_format ()
break;
default:
- fatal << string_compose (_("programming error: unknown file data format passed to ARDOUR_UI::map_file_data_format: %1"),
+ fatal << string_compose (_("programming error: unknown file data format passed to ARDOUR_UI::map_file_data_format: %1"),
Config->get_native_file_data_format()) << endmsg;
/*NOTREACHED*/
}
@@ -866,7 +882,7 @@ ARDOUR_UI::map_output_auto_connect ()
Glib::RefPtr<Action> act = ActionManager::get_action ("options", on);
if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
-
+
if (tact && !tact->get_active()) {
tact->set_active (true);
}
@@ -965,7 +981,7 @@ ARDOUR_UI::map_meter_hold ()
}
}
-void
+void
ARDOUR_UI::set_meter_hold (MeterHold val)
{
const char* action = 0;
@@ -989,7 +1005,7 @@ ARDOUR_UI::set_meter_hold (MeterHold val)
}
Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), action);
-
+
if (act) {
Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
if (ract && ract->get_active() && Config->get_meter_hold() != fval) {
@@ -1046,11 +1062,11 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
ENSURE_GUI_THREAD (bind (mem_fun (*this, &ARDOUR_UI::parameter_changed), parameter_name));
#define PARAM_IS(x) (!strcmp (parameter_name, (x)))
-
+
if (PARAM_IS ("slave-source")) {
sync_option_combo.set_active_text (slave_source_to_string (Config->get_slave_source()));
-
+
switch (Config->get_slave_source()) {
case None:
ActionManager::get_action ("Transport", "ToggleAutoPlay")->set_sensitive (true);
@@ -1070,7 +1086,6 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
} else if (PARAM_IS ("send-mmc")) {
-
ActionManager::map_some_state ("options", "SendMMC", &Configuration::get_send_mmc);
} else if (PARAM_IS ("use-osc")) {
@@ -1084,10 +1099,11 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
#endif
ActionManager::map_some_state ("options", "UseOSC", &Configuration::get_use_osc);
-
+
} else if (PARAM_IS ("mmc-control")) {
ActionManager::map_some_state ("options", "UseMMC", &Configuration::get_mmc_control);
-
+ } else if (PARAM_IS ("midi-clock-control")) {
+ ActionManager::map_some_state ("options", "UseMIDIClock", &Configuration::get_midi_clock_control);
} else if (PARAM_IS ("midi-feedback")) {
ActionManager::map_some_state ("options", "SendMIDIfeedback", &Configuration::get_midi_feedback);
} else if (PARAM_IS ("do-not-record-plugins")) {
@@ -1170,7 +1186,7 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
}
} else if (PARAM_IS ("shuttle-units")) {
-
+
switch (Config->get_shuttle_units()) {
case Percentage:
shuttle_units_button.set_label("% ");
@@ -1216,7 +1232,7 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
ActionManager::map_some_state ("options", "RubberbandingSnapsToGrid", &Configuration::get_rubberbanding_snaps_to_grid);
}
-
+
#undef PARAM_IS
}
diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc
index fd5c35e186..2dfa63080d 100644
--- a/gtk2_ardour/option_editor.cc
+++ b/gtk2_ardour/option_editor.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2001-2006 Paul Davis
+ Copyright (C) 2001-2006 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
@@ -89,7 +89,7 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
/* MIDI */
- midi_port_table (4, 11),
+ midi_port_table (4, 12),
mmc_receive_device_id_adjustment (0.0, 0.0, (double) 0x7f, 1.0, 16.0),
mmc_receive_device_id_spinner (mmc_receive_device_id_adjustment),
mmc_send_device_id_adjustment (0.0, 0.0, (double) 0x7f, 1.0, 16.0),
@@ -109,14 +109,14 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
delete_button_spin (delete_button_adjustment),
edit_button_adjustment (3, 1, 5),
edit_button_spin (edit_button_adjustment)
-
+
{
using namespace Notebook_Helpers;
click_io_selector = 0;
auditioner_io_selector = 0;
session = 0;
-
+
WindowTitle title(Glib::get_application_name());
title += _("Preferences");
set_title(title.get_string());
@@ -126,7 +126,7 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
set_name ("Preferences");
add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
-
+
VBox *vbox = get_vbox();
set_border_width (3);
@@ -288,7 +288,7 @@ OptionEditor::setup_misc_options ()
label = manage (new Label (_("Short crossfade length (msecs)")));
label->set_name ("OptionsLabel");
-
+
hbox = manage (new HBox);
hbox->set_border_width (5);
hbox->set_spacing (10);
@@ -300,14 +300,14 @@ OptionEditor::setup_misc_options ()
label = manage (new Label (_("Destructive crossfade length (msecs)")));
label->set_name ("OptionsLabel");
-
+
hbox = manage (new HBox);
hbox->set_border_width (5);
hbox->set_spacing (10);
hbox->pack_start (*label, false, false);
hbox->pack_start (destructo_xfade_slider, true, true);
misc_packer.pack_start (*hbox, false, false);
-
+
destructo_xfade_adjustment.signal_value_changed().connect (mem_fun(*this, &OptionEditor::destructo_xfade_adjustment_changed));
@@ -347,7 +347,7 @@ OptionEditor::setup_misc_options ()
hbox->pack_start (*label, false, false);
hbox->pack_start (saved_history_depth_spinner, false, false);
misc_packer.pack_start (*hbox, false, false);
-
+
short_xfade_slider.set_update_policy (UPDATE_DISCONTINUOUS);
destructo_xfade_slider.set_update_policy (UPDATE_DISCONTINUOUS);
@@ -360,7 +360,7 @@ void
OptionEditor::limit_history_toggled ()
{
bool x = limit_history_button.get_active();
-
+
if (!x) {
Config->set_history_depth (0);
history_depth_spinner.set_sensitive (false);
@@ -401,9 +401,9 @@ OptionEditor::short_xfade_adjustment_changed ()
{
if (session) {
float val = short_xfade_adjustment.get_value();
-
+
/* val is in msecs */
-
+
Crossfade::set_short_xfade_length ((nframes_t) floor (session->frame_rate() * (val / 1000.0)));
}
}
@@ -415,12 +415,12 @@ OptionEditor::destructo_xfade_adjustment_changed ()
/* val is in msecs */
-
+
Config->set_destructive_xfade_msecs ((uint32_t) floor (val));
if (session) {
SndFileSource::setup_standard_crossfades (session->frame_rate());
- }
+ }
}
void
@@ -431,14 +431,14 @@ OptionEditor::setup_sync_options ()
smpte_offset_clock.set_mode (AudioClock::SMPTE);
smpte_offset_clock.ValueChanged.connect (mem_fun(*this, &OptionEditor::smpte_offset_chosen));
-
+
smpte_offset_negative_button.set_name ("OptionEditorToggleButton");
smpte_offset_negative_button.unset_flags (Gtk::CAN_FOCUS);
Label *smpte_offset_label = manage (new Label (_("SMPTE Offset")));
smpte_offset_label->set_name("OptionsLabel");
-
+
hbox = manage (new HBox);
hbox->set_border_width (5);
hbox->set_spacing (10);
@@ -510,17 +510,17 @@ OptionEditor::setup_midi_options ()
hbox = manage (new HBox);
hbox->set_border_width (6);
hbox->set_spacing (6);
- label = (manage (new Label (_("Inbound MMC Device ID"))));
+ label = (manage (new Label (_("Inbound MMC Device ID"))));
hbox->pack_start (mmc_receive_device_id_spinner, false, false);
hbox->pack_start (*label, false, false);
- midi_packer.pack_start (*hbox, false, false);
+ midi_packer.pack_start (*hbox, false, false);
mmc_receive_device_id_spinner.set_value(Config->get_mmc_receive_device_id ());
hbox = manage (new HBox);
hbox->set_border_width (6);
hbox->set_spacing (6);
- label = (manage (new Label (_("Outbound MMC Device ID"))));
+ label = (manage (new Label (_("Outbound MMC Device ID"))));
hbox->pack_start (mmc_send_device_id_spinner, false, false);
hbox->pack_start (*label, false, false);
midi_packer.pack_start (*hbox, false, false);
@@ -548,52 +548,60 @@ OptionEditor::redisplay_midi_ports ()
midi_port_table_widgets.clear ();
- midi_port_table.resize (ports.size() + 4, 11);
+ midi_port_table.resize (ports.size() + 4, 12);
Gtk::Label* label;
- label = (manage (new Label (_("Port"))));
+ label = (manage (new Label (_("Port"))));
label->show ();
midi_port_table_widgets.push_back (label);
midi_port_table.attach (*label, 0, 1, 0, 1);
- label = (manage (new Label (_("Offline"))));
+ label = (manage (new Label (_("Offline"))));
label->show ();
midi_port_table_widgets.push_back (label);
midi_port_table.attach (*label, 1, 2, 0, 1);
- label = (manage (new Label (_("Trace\nInput"))));
+ label = (manage (new Label (_("Trace\nInput"))));
label->show ();
midi_port_table_widgets.push_back (label);
midi_port_table.attach (*label, 2, 3, 0, 1);
- label = (manage (new Label (_("Trace\nOutput"))));
+ label = (manage (new Label (_("Trace\nOutput"))));
label->show ();
midi_port_table_widgets.push_back (label);
midi_port_table.attach (*label, 3, 4, 0, 1);
- label = (manage (new Label (_("MTC"))));
+ label = (manage (new Label (_("MTC"))));
label->show ();
midi_port_table_widgets.push_back (label);
midi_port_table.attach (*label, 4, 5, 0, 1);
- label = (manage (new Label (_("MMC"))));
+ label = (manage (new Label (_("MIDI\nClock"))));
label->show ();
midi_port_table_widgets.push_back (label);
midi_port_table.attach (*label, 6, 7, 0, 1);
- label = (manage (new Label (_("MIDI Parameter\nControl"))));
+ label = (manage (new Label (_("MMC"))));
label->show ();
midi_port_table_widgets.push_back (label);
midi_port_table.attach (*label, 8, 9, 0, 1);
+ label = (manage (new Label (_("MIDI Parameter\nControl"))));
+ label->show ();
+ midi_port_table_widgets.push_back (label);
+ midi_port_table.attach (*label, 10, 11, 0, 1);
- Gtk::HSeparator* hsep = (manage (new HSeparator()));
+ Gtk::HSeparator* hsep = (manage (new HSeparator()));
hsep->show ();
midi_port_table_widgets.push_back (hsep);
- midi_port_table.attach (*hsep, 0, 9, 1, 2);
- Gtk::VSeparator* vsep = (manage (new VSeparator()));
+ midi_port_table.attach (*hsep, 0, 11, 1, 2);
+ Gtk::VSeparator* vsep = (manage (new VSeparator()));
vsep->show ();
midi_port_table_widgets.push_back (vsep);
midi_port_table.attach (*vsep, 5, 6, 0, 8);
- vsep = (manage (new VSeparator()));
+ vsep = (manage (new VSeparator()));
vsep->show ();
midi_port_table_widgets.push_back (vsep);
midi_port_table.attach (*vsep, 7, 8, 0, 8);
-
+ vsep = (manage (new VSeparator()));
+ vsep->show ();
+ midi_port_table_widgets.push_back (vsep);
+ midi_port_table.attach (*vsep, 9, 10, 0, 8);
+
for (n = 0, i = ports.begin(); i != ports.end(); ++n, ++i) {
ToggleButton* tb;
@@ -601,20 +609,20 @@ OptionEditor::redisplay_midi_ports ()
Button* bb;
/* the remove button. create early so we can pass it to various callbacks */
-
+
bb = manage (new Button (Stock::REMOVE));
bb->set_name ("OptionEditorToggleButton");
bb->show ();
midi_port_table_widgets.push_back (bb);
- midi_port_table.attach (*bb, 9, 10, n+2, n+3, FILL|EXPAND, FILL);
+ midi_port_table.attach (*bb, 11, 12, n+2, n+3, FILL|EXPAND, FILL);
bb->signal_clicked().connect (bind (mem_fun(*this, &OptionEditor::remove_midi_port), i->second));
bb->set_sensitive (port_removable (i->second));
- label = (manage (new Label (i->first)));
+ label = (manage (new Label (i->first)));
label->show ();
midi_port_table_widgets.push_back (label);
midi_port_table.attach (*label, 0, 1, n+2, n+3,FILL|EXPAND, FILL );
-
+
tb = manage (new ToggleButton (_("online")));
tb->set_name ("OptionEditorToggleButton");
@@ -637,6 +645,7 @@ OptionEditor::redisplay_midi_ports ()
midi_port_table_widgets.push_back (tb);
midi_port_table.attach (*tb, 1, 2, n+2, n+3, FILL|EXPAND, FILL);
+ // Trace MIDI Input
tb = manage (new ToggleButton ());
tb->set_name ("OptionEditorToggleButton");
tb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::port_trace_in_toggled), (*i).second, tb));
@@ -645,6 +654,7 @@ OptionEditor::redisplay_midi_ports ()
midi_port_table_widgets.push_back (tb);
midi_port_table.attach (*tb, 2, 3, n+2, n+3, FILL|EXPAND, FILL);
+ // Trace MIDI Output
tb = manage (new ToggleButton ());
tb->set_name ("OptionEditorToggleButton");
tb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::port_trace_out_toggled), (*i).second, tb));
@@ -653,13 +663,13 @@ OptionEditor::redisplay_midi_ports ()
midi_port_table_widgets.push_back (tb);
midi_port_table.attach (*tb, 3, 4, n+2, n+3, FILL|EXPAND, FILL);
+ // MTC Radio Button
rb = manage (new RadioButton ());
rb->set_name ("OptionEditorToggleButton");
if (n == 0) {
mtc_button_group = rb->get_group();
} else {
rb->set_group (mtc_button_group);
-
}
rb->show ();
midi_port_table_widgets.push_back (rb);
@@ -669,7 +679,24 @@ OptionEditor::redisplay_midi_ports ()
if (session && i->second == session->mtc_port()) {
rb->set_active (true);
}
-
+
+ // MIDI Clock Radio Button
+ rb = manage (new RadioButton ());
+ rb->set_name ("OptionEditorToggleButton");
+ if (n == 0) {
+ midi_clock_button_group = rb->get_group();
+ } else {
+ rb->set_group (midi_clock_button_group);
+ }
+ rb->show ();
+ midi_port_table_widgets.push_back (rb);
+ midi_port_table.attach (*rb, 6, 7, n+2, n+3, FILL|EXPAND, FILL);
+ rb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::midi_clock_port_chosen), (*i).second, rb, bb));
+
+ if (session && i->second == session->midi_clock_port()) {
+ rb->set_active (true);
+ }
+
rb = manage (new RadioButton ());
rb->set_name ("OptionEditorToggleButton");
if (n == 0) {
@@ -679,7 +706,7 @@ OptionEditor::redisplay_midi_ports ()
}
rb->show ();
midi_port_table_widgets.push_back (rb);
- midi_port_table.attach (*rb, 6, 7, n+2, n+3, FILL|EXPAND, FILL);
+ midi_port_table.attach (*rb, 8, 9, n+2, n+3, FILL|EXPAND, FILL);
rb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::mmc_port_chosen), (*i).second, rb, bb));
if (session && i->second == session->mmc_port()) {
@@ -695,7 +722,7 @@ OptionEditor::redisplay_midi_ports ()
}
rb->show ();
midi_port_table_widgets.push_back (rb);
- midi_port_table.attach (*rb, 8, 9, n+2, n+3, FILL|EXPAND, FILL);
+ midi_port_table.attach (*rb, 10, 11, n+2, n+3, FILL|EXPAND, FILL);
rb->signal_toggled().connect (bind (mem_fun(*this, &OptionEditor::midi_port_chosen), (*i).second, rb, bb));
if (session && i->second == session->midi_port()) {
@@ -774,7 +801,7 @@ OptionEditor::port_removable (MIDI::Port *port)
}
void
-OptionEditor::mtc_port_chosen (MIDI::Port *port, Gtk::RadioButton* rb, Gtk::Button* bb)
+OptionEditor::mtc_port_chosen (MIDI::Port *port, Gtk::RadioButton* rb, Gtk::Button* bb)
{
if (session) {
if (rb->get_active()) {
@@ -816,6 +843,20 @@ OptionEditor::midi_port_chosen (MIDI::Port* port, Gtk::RadioButton* rb, Gtk::But
}
void
+OptionEditor::midi_clock_port_chosen (MIDI::Port *port, Gtk::RadioButton* rb, Gtk::Button* bb)
+{
+ if (session) {
+ if (rb->get_active()) {
+ session->set_midi_clock_port (port->name());
+ Config->set_midi_clock_port_name (port->name());
+ } else {
+ session->set_midi_clock_port ("");
+ }
+ bb->set_sensitive (port_removable (port));
+ }
+}
+
+void
OptionEditor::port_online_toggled (MIDI::Port* port, ToggleButton* tb)
{
bool wanted = tb->get_active();
@@ -823,7 +864,7 @@ OptionEditor::port_online_toggled (MIDI::Port* port, ToggleButton* tb)
if (port->input()) {
if (wanted != port->input()->offline()) {
port->input()->set_offline (wanted);
- }
+ }
}
}
@@ -831,7 +872,7 @@ void
OptionEditor::map_port_online (MIDI::Port* port, ToggleButton* tb)
{
bool bstate = tb->get_active ();
-
+
if (port->input()) {
if (bstate != port->input()->offline()) {
if (port->input()->offline()) {
@@ -911,12 +952,12 @@ void
OptionEditor::click_browse_clicked ()
{
SoundFileChooser sfdb (*this, _("Choose Click"), session);
-
+
sfdb.show_all ();
sfdb.present ();
int result = sfdb.run ();
-
+
if (result == Gtk::RESPONSE_OK) {
click_chosen(sfdb.get_filename());
}
@@ -946,7 +987,7 @@ OptionEditor::click_emphasis_browse_clicked ()
void
OptionEditor::click_emphasis_chosen (const string & path)
-{
+{
click_emphasis_path_entry.set_text (path);
click_emphasis_sound_changed ();
}
@@ -1015,7 +1056,7 @@ OptionEditor::setup_click_editor ()
click_path_entry.set_name ("OptionsEntry");
click_emphasis_path_entry.set_name ("OptionsEntry");
-
+
click_path_entry.signal_activate().connect (mem_fun(*this, &OptionEditor::click_sound_changed));
click_emphasis_path_entry.signal_activate().connect (mem_fun(*this, &OptionEditor::click_emphasis_sound_changed));
@@ -1034,13 +1075,13 @@ OptionEditor::setup_click_editor ()
click_gpm = new GainMeter (session->click_io(), *session);
click_table.set_col_spacings (10);
-
+
label = manage(new Label(_("Click audio file")));
label->set_name ("OptionsLabel");
click_table.attach (*label, 0, 1, 0, 1, FILL|EXPAND, FILL);
click_table.attach (click_path_entry, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, FILL);
click_table.attach (click_browse_button, 2, 3, 0, 1, FILL|EXPAND, FILL);
-
+
label = manage(new Label(_("Click emphasis audiofile")));
label->set_name ("OptionsLabel");
click_table.attach (*label, 0, 1, 1, 2, FILL|EXPAND, FILL);
@@ -1082,7 +1123,7 @@ OptionEditor::setup_auditioner_editor ()
"for listening to specific regions outside the context\n"
"of the overall mix. It can be connected just like any\n"
"other mixer strip."));
-
+
audition_packer.pack_start (audition_label, false, false, 10);
audition_packer.pack_start (audition_hpacker, false, false);
}
@@ -1101,7 +1142,7 @@ OptionEditor::connect_audition_editor ()
}
bool
-OptionEditor::focus_out_event_handler (GdkEventFocus* ev, void (OptionEditor::*pmf)())
+OptionEditor::focus_out_event_handler (GdkEventFocus* ev, void (OptionEditor::*pmf)())
{
(this->*pmf)();
return false;
@@ -1112,7 +1153,7 @@ static const struct {
guint modifier;
} modifiers[] = {
-#ifdef GTKOSX
+#ifdef GTKOSX
/* Command = Meta
Option/Alt = Mod1
@@ -1172,13 +1213,13 @@ OptionEditor::setup_keyboard_options ()
label = manage (new Label (_("Edit using")));
label->set_name ("OptionsLabel");
label->set_alignment (1.0, 0.5);
-
+
keyboard_mouse_table.attach (*label, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, FILL);
keyboard_mouse_table.attach (edit_modifier_combo, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, FILL);
label = manage (new Label (_("+ button")));
label->set_name ("OptionsLabel");
-
+
keyboard_mouse_table.attach (*label, 3, 4, 0, 1, Gtk::FILL|Gtk::EXPAND, FILL);
keyboard_mouse_table.attach (edit_button_spin, 4, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, FILL);
@@ -1199,7 +1240,7 @@ OptionEditor::setup_keyboard_options ()
label = manage (new Label (_("Delete using")));
label->set_name ("OptionsLabel");
label->set_alignment (1.0, 0.5);
-
+
keyboard_mouse_table.attach (*label, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, FILL);
keyboard_mouse_table.attach (delete_modifier_combo, 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, FILL);
@@ -1215,7 +1256,7 @@ OptionEditor::setup_keyboard_options ()
set_popdown_strings (snap_modifier_combo, dumb);
snap_modifier_combo.signal_changed().connect (mem_fun(*this, &OptionEditor::snap_modifier_chosen));
-
+
for (int x = 0; modifiers[x].name; ++x) {
if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
snap_modifier_combo.set_active_text (_(modifiers[x].name));
@@ -1226,16 +1267,16 @@ OptionEditor::setup_keyboard_options ()
label = manage (new Label (_("Ignore snap using")));
label->set_name ("OptionsLabel");
label->set_alignment (1.0, 0.5);
-
+
keyboard_mouse_table.attach (*label, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, FILL);
keyboard_mouse_table.attach (snap_modifier_combo, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, FILL);
vector<string> strs;
-
+
for (std::map<std::string,std::string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
strs.push_back (bf->first);
}
-
+
set_popdown_strings (keyboard_layout_selector, strs);
keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
keyboard_layout_selector.signal_changed().connect (mem_fun (*this, &OptionEditor::bindings_changed));
@@ -1252,7 +1293,7 @@ void
OptionEditor::bindings_changed ()
{
string txt;
-
+
txt = keyboard_layout_selector.get_active_text();
for (std::map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
@@ -1268,7 +1309,7 @@ void
OptionEditor::edit_modifier_chosen ()
{
string txt;
-
+
txt = edit_modifier_combo.get_active_text();
for (int i = 0; modifiers[i].name; ++i) {
@@ -1283,7 +1324,7 @@ void
OptionEditor::delete_modifier_chosen ()
{
string txt;
-
+
txt = delete_modifier_combo.get_active_text();
for (int i = 0; modifiers[i].name; ++i) {
@@ -1298,7 +1339,7 @@ void
OptionEditor::snap_modifier_chosen ()
{
string txt;
-
+
txt = snap_modifier_combo.get_active_text();
for (int i = 0; modifiers[i].name; ++i) {
@@ -1356,12 +1397,12 @@ OptionEditor::parameter_changed (const char* parameter_name)
ENSURE_GUI_THREAD (bind (mem_fun (*this, &OptionEditor::parameter_changed), parameter_name));
#define PARAM_IS(x) (!strcmp (parameter_name, (x)))
-
+
if (PARAM_IS ("timecode-source-is-synced")) {
synced_timecode_button.set_active (Config->get_timecode_source_is_synced());
} else if (PARAM_IS ("history-depth")) {
int32_t depth = Config->get_history_depth();
-
+
history_depth.set_value (depth);
history_depth_spinner.set_sensitive (depth != 0);
limit_history_button.set_active (depth != 0);
diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h
index 45fe092eab..c6f13049b0 100644
--- a/gtk2_ardour/option_editor.h
+++ b/gtk2_ardour/option_editor.h
@@ -2,7 +2,7 @@
#define __gtk_ardour_option_editor_h__
/*
- Copyright (C) 2001 Paul Davis
+ Copyright (C) 2001 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
@@ -128,6 +128,7 @@ class OptionEditor : public ArdourDialog
Gtk::RadioButton::Group mtc_button_group;
Gtk::RadioButton::Group mmc_button_group;
Gtk::RadioButton::Group midi_button_group;
+ Gtk::RadioButton::Group midi_clock_button_group;
Gtk::Table midi_port_table;
std::vector<Gtk::Widget*> midi_port_table_widgets;
@@ -144,10 +145,11 @@ class OptionEditor : public ArdourDialog
void port_online_toggled (MIDI::Port*,Gtk::ToggleButton*);
void port_trace_in_toggled (MIDI::Port*,Gtk::ToggleButton*);
void port_trace_out_toggled (MIDI::Port*,Gtk::ToggleButton*);
-
+
void mmc_port_chosen (MIDI::Port*,Gtk::RadioButton*, Gtk::Button*);
void mtc_port_chosen (MIDI::Port*,Gtk::RadioButton*, Gtk::Button*);
void midi_port_chosen (MIDI::Port*,Gtk::RadioButton*, Gtk::Button*);
+ void midi_clock_port_chosen (MIDI::Port*,Gtk::RadioButton*, Gtk::Button*);
bool port_removable (MIDI::Port*);
void mmc_receive_device_id_adjusted ();
@@ -160,7 +162,8 @@ class OptionEditor : public ArdourDialog
enum PortIndex {
MtcIndex = 0,
MmcIndex = 1,
- MidiIndex = 2
+ MidiIndex = 2,
+ MidiClockIndex = 3
};
std::map<MIDI::Port*,std::vector<Gtk::RadioButton*> > port_toggle_buttons;
@@ -185,7 +188,7 @@ class OptionEditor : public ArdourDialog
void click_browse_clicked ();
void click_emphasis_browse_clicked ();
-
+
void click_sound_changed ();
void click_emphasis_sound_changed ();
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index b50aecbcb3..44f4718384 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -92,6 +92,7 @@ midi_stretch.cc
midi_track.cc
mix.cc
mtc_slave.cc
+midi_clock_slave.cc
named_selection.cc
note.cc
panner.cc
diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h
index 6f653f10bf..fecd0fcf4e 100644
--- a/libs/ardour/ardour/ardour.h
+++ b/libs/ardour/ardour/ardour.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1999 Paul Davis
+ Copyright (C) 1999 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
@@ -51,9 +51,9 @@ namespace ARDOUR {
int cleanup ();
std::string get_ardour_revision ();
-
+
void find_bindings_files (std::map<std::string,std::string>&);
-
+
const layer_t max_layer = UCHAR_MAX;
microseconds_t get_microseconds ();
@@ -82,6 +82,7 @@ namespace ARDOUR {
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;
#endif /* __ardour_ardour_h__ */
diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
index 4e2a14c07b..7a7a2ce419 100644
--- a/libs/ardour/ardour/configuration_vars.h
+++ b/libs/ardour/ardour/configuration_vars.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000-2007 Paul Davis
+ Copyright (C) 2000-2007 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
@@ -30,11 +30,13 @@ CONFIG_VARIABLE (std::string, auditioner_output_right, "auditioner-output-right"
CONFIG_VARIABLE (std::string, mtc_port_name, "mtc-port-name", "default")
CONFIG_VARIABLE (std::string, mmc_port_name, "mmc-port-name", "default")
CONFIG_VARIABLE (std::string, midi_port_name, "midi-port-name", "default")
+CONFIG_VARIABLE (std::string, midi_clock_port_name, "midi-clock-port-name", "default")
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)
CONFIG_VARIABLE (bool, send_mmc, "send-mmc", true)
CONFIG_VARIABLE (bool, mmc_control, "mmc-control", true)
+CONFIG_VARIABLE (bool, midi_clock_control, "midi-clock-control", false)
CONFIG_VARIABLE (bool, midi_feedback, "midi-feedback", false)
CONFIG_VARIABLE (uint8_t, mmc_receive_device_id, "mmc-receive-device-id", 0)
CONFIG_VARIABLE (uint8_t, mmc_send_device_id, "mmc-send-device-id", 0)
@@ -139,7 +141,7 @@ CONFIG_VARIABLE (nframes_t, over_length_short, "over-length-short", 2)
CONFIG_VARIABLE (nframes_t, over_length_long, "over-length-long", 10)
/* miscellany */
-
+
CONFIG_VARIABLE (bool, hiding_groups_deactivates_groups, "hiding-groups-deactivates-groups", true)
CONFIG_VARIABLE (bool, verify_remove_last_capture, "verify-remove-last-capture", true)
CONFIG_VARIABLE (bool, no_new_session_dialog, "no-new-session-dialog", false)
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index b718d751b4..00cbc9922e 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000 Paul Davis
+ Copyright (C) 2000 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
@@ -46,8 +46,8 @@
#include <midi++/types.h>
#include <midi++/mmc.h>
-#include <pbd/stateful.h>
-#include <pbd/destructible.h>
+#include <pbd/stateful.h>
+#include <pbd/destructible.h>
#include <ardour/ardour.h>
#include <ardour/configuration.h>
@@ -150,7 +150,7 @@ class Session : public PBD::StatefulDestructible
InputConfigurationChange,
SetAudioRange,
SetPlayRange,
-
+
/* only one of each of these events
can be queued at any one time
*/
@@ -165,7 +165,7 @@ class Session : public PBD::StatefulDestructible
Replace,
Clear
};
-
+
Type type;
Action action;
nframes_t action_frame;
@@ -186,14 +186,14 @@ class Session : public PBD::StatefulDestructible
list<MusicRange> music_range;
Event(Type t, Action a, nframes_t when, nframes_t where, float spd, bool yn = false)
- : type (t),
+ : type (t),
action (a),
action_frame (when),
target_frame (where),
speed (spd),
yes_or_no (yn) {}
- void set_ptr (void* p) {
+ void set_ptr (void* p) {
ptr = p;
}
@@ -242,7 +242,7 @@ class Session : public PBD::StatefulDestructible
uint32_t n_physical_in,
uint32_t n_physical_out,
nframes_t initial_length);
-
+
virtual ~Session ();
string path() const { return _path; }
@@ -265,20 +265,20 @@ class Session : public PBD::StatefulDestructible
static sigc::signal<void> AutoBindingOff;
static sigc::signal<void,std::string> Dialog;
-
+
std::string sound_dir (bool with_path = true) const;
std::string peak_dir () const;
std::string dead_sound_dir () const;
std::string automation_dir () const;
std::string analysis_dir() const;
-
+
int ensure_subdirs ();
Glib::ustring peak_path (Glib::ustring) const;
static string change_audio_path_by_name (string oldpath, string oldname, string newname, bool destructive);
static string change_midi_path_by_name (string oldpath, string oldname, string newname, bool destructive);
-
+
string peak_path_from_audio_path (string) const;
string audio_path_from_name (string, uint32_t nchans, uint32_t chan, bool destructive);
string midi_path_from_name (string);
@@ -288,7 +288,7 @@ class Session : public PBD::StatefulDestructible
BufferSet& get_silent_buffers (ChanCount count = ChanCount::ZERO);
BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO);
BufferSet& get_mix_buffers (ChanCount count = ChanCount::ZERO);
-
+
void add_diskstream (boost::shared_ptr<Diskstream>);
boost::shared_ptr<Diskstream> diskstream_by_id (const PBD::ID& id);
boost::shared_ptr<Diskstream> diskstream_by_name (string name);
@@ -298,17 +298,17 @@ class Session : public PBD::StatefulDestructible
void refill_all_diskstream_buffers ();
uint32_t audio_diskstream_buffer_size() const { return audio_dstream_buffer_size; }
uint32_t midi_diskstream_buffer_size() const { return midi_dstream_buffer_size; }
-
+
uint32_t get_next_diskstream_id() const { return n_diskstreams(); }
uint32_t n_diskstreams() const;
-
+
typedef std::list<boost::shared_ptr<Diskstream> > DiskstreamList;
- typedef std::list<boost::shared_ptr<Route> > RouteList;
-
+ typedef std::list<boost::shared_ptr<Route> > RouteList;
+
boost::shared_ptr<RouteList> get_routes() const {
return routes.reader ();
}
-
+
uint32_t nroutes() const { return routes.reader()->size(); }
uint32_t ntracks () const;
uint32_t nbusses () const;
@@ -316,7 +316,7 @@ class Session : public PBD::StatefulDestructible
struct RoutePublicOrderSorter {
bool operator() (boost::shared_ptr<Route>, boost::shared_ptr<Route> b);
};
-
+
template<class T> void foreach_route (T *obj, void (T::*func)(Route&));
template<class T> void foreach_route (T *obj, void (T::*func)(boost::shared_ptr<Route>));
template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg);
@@ -327,7 +327,7 @@ class Session : public PBD::StatefulDestructible
bool route_name_unique (string) const;
- bool get_record_enabled() const {
+ bool get_record_enabled() const {
return (record_status () >= Enabled);
}
@@ -343,7 +343,7 @@ class Session : public PBD::StatefulDestructible
void maybe_enable_record ();
void disable_record (bool rt_context, bool force = false);
void step_back_from_record ();
-
+
void maybe_write_autosave ();
/* Proxy signal for region hidden changes */
@@ -351,9 +351,9 @@ class Session : public PBD::StatefulDestructible
sigc::signal<void,boost::shared_ptr<Region> > RegionHiddenChange;
/* Emitted when all i/o connections are complete */
-
+
sigc::signal<void> IOConnectionsComplete;
-
+
/* Record status signals */
sigc::signal<void> RecordStateChanged;
@@ -442,10 +442,10 @@ class Session : public PBD::StatefulDestructible
void remove_state (string snapshot_name);
void rename_state (string old_name, string new_name);
void remove_pending_capture_state ();
-
+
sigc::signal<void,string> StateSaved;
sigc::signal<void> StateReady;
-
+
vector<string*>* possible_states() const;
static vector<string*>* possible_states(string path);
@@ -499,14 +499,14 @@ class Session : public PBD::StatefulDestructible
std::list<boost::shared_ptr<AudioTrack> > new_audio_track (int input_channels, int output_channels, TrackMode mode = Normal, uint32_t how_many = 1);
RouteList new_audio_route (int input_channels, int output_channels, uint32_t how_many);
-
+
std::list<boost::shared_ptr<MidiTrack> > new_midi_track (TrackMode mode = Normal, uint32_t how_many = 1);
//boost::shared_ptr<Route> new_midi_route (uint32_t how_many = 1);
void remove_route (boost::shared_ptr<Route>);
void resort_routes ();
void resort_routes_using (boost::shared_ptr<RouteList>);
-
+
void set_remote_control_ids();
AudioEngine & engine() { return _engine; }
@@ -563,18 +563,18 @@ class Session : public PBD::StatefulDestructible
float transport_speed() const { return _transport_speed; }
bool transport_stopped() const { return _transport_speed == 0.0f; }
bool transport_rolling() const { return _transport_speed != 0.0f; }
-
+
void set_silent (bool yn);
bool silent () { return _silent; }
int jack_slave_sync (nframes_t);
TempoMap& tempo_map() { return *_tempo_map; }
-
+
/* region info */
void add_regions (std::vector<boost::shared_ptr<Region> >&);
-
+
sigc::signal<void,boost::weak_ptr<Region> > RegionAdded;
sigc::signal<void,std::vector<boost::weak_ptr<Region> >& > RegionsAdded;
sigc::signal<void,boost::weak_ptr<Region> > RegionRemoved;
@@ -584,7 +584,7 @@ class Session : public PBD::StatefulDestructible
string path_from_region_name (DataType type, string name, string identifier);
boost::shared_ptr<Region> find_whole_file_parent (boost::shared_ptr<Region const>);
-
+
void find_equivalent_playlist_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >& result);
boost::shared_ptr<Region> XMLRegionFactory (const XMLNode&, bool full);
@@ -597,16 +597,16 @@ class Session : public PBD::StatefulDestructible
struct import_status : public InterThreadInfo {
string doing_what;
-
+
/* control info */
SrcQuality quality;
volatile bool freeze;
std::vector<Glib::ustring> paths;
bool replace_existing_source;
-
+
/* result */
SourceList sources;
-
+
};
void import_audiofiles (import_status&);
@@ -640,7 +640,7 @@ class Session : public PBD::StatefulDestructible
"yes, delete this playlist" and 1 for "no, don't delete
this playlist.
*/
-
+
sigc::signal<int,boost::shared_ptr<ARDOUR::Playlist> > AskAboutPlaylistDeletion;
/* handlers should return 0 for "ignore the rate mismatch"
@@ -654,7 +654,7 @@ class Session : public PBD::StatefulDestructible
*/
static sigc::signal<int> AskAboutPendingState;
-
+
boost::shared_ptr<AudioFileSource> create_audio_source_for_session (ARDOUR::AudioDiskstream&, uint32_t which_channel, bool destructive);
boost::shared_ptr<MidiSource> create_midi_source_for_session (ARDOUR::MidiDiskstream&);
@@ -687,7 +687,7 @@ class Session : public PBD::StatefulDestructible
/* Curves and AutomationLists (TODO when they go away) */
void add_curve(Curve*);
void add_automation_list(AutomationList*);
-
+
/* fade curves */
float get_default_fade_length () const { return default_fade_msecs; }
@@ -701,7 +701,7 @@ class Session : public PBD::StatefulDestructible
void audition_region (boost::shared_ptr<Region>);
void cancel_audition ();
bool is_auditioning () const;
-
+
sigc::signal<void,bool> AuditionActive;
/* flattening stuff */
@@ -712,7 +712,7 @@ class Session : public PBD::StatefulDestructible
int freeze (InterThreadInfo&);
/* session-wide solo/mute/rec-enable */
-
+
bool soloing() const { return currently_soloing; }
void set_all_solo (bool);
@@ -720,7 +720,7 @@ class Session : public PBD::StatefulDestructible
sigc::signal<void,bool> SoloActive;
sigc::signal<void> SoloChanged;
-
+
void record_disenable_all ();
void record_enable_all ();
@@ -730,15 +730,15 @@ class Session : public PBD::StatefulDestructible
boost::shared_ptr<IO> master_out() const { return _master_out; }
/* insert/send management */
-
+
uint32_t n_port_inserts() const { return _port_inserts.size(); }
uint32_t n_plugin_inserts() const { return _plugin_inserts.size(); }
uint32_t n_sends() const { return _sends.size(); }
-
- static void set_disable_all_loaded_plugins (bool yn) {
+
+ static void set_disable_all_loaded_plugins (bool yn) {
_disable_all_loaded_plugins = yn;
}
- static bool get_disable_all_loaded_plugins() {
+ static bool get_disable_all_loaded_plugins() {
return _disable_all_loaded_plugins;
}
@@ -748,7 +748,7 @@ class Session : public PBD::StatefulDestructible
void mark_insert_id (uint32_t);
/* s/w "RAID" management */
-
+
nframes_t available_capture_duration();
/* I/O bundles */
@@ -767,23 +767,26 @@ class Session : public PBD::StatefulDestructible
int set_mtc_port (string port_tag);
int set_mmc_port (string port_tag);
int set_midi_port (string port_tag);
+ int set_midi_clock_port (string port_tag);
MIDI::Port *mtc_port() const { return _mtc_port; }
MIDI::Port *mmc_port() const { return _mmc_port; }
MIDI::Port *midi_port() const { return _midi_port; }
+ MIDI::Port *midi_clock_port() const { return _midi_clock_port; }
sigc::signal<void> MTC_PortChanged;
sigc::signal<void> MMC_PortChanged;
sigc::signal<void> MIDI_PortChanged;
+ sigc::signal<void> 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);
-
+
void set_mmc_receive_device_id (uint32_t id);
void set_mmc_send_device_id (uint32_t id);
-
+
/* Scrubbing */
void start_scrub (nframes_t where);
@@ -806,7 +809,7 @@ class Session : public PBD::StatefulDestructible
}
UndoHistory& history() { return _history; }
-
+
uint32_t undo_depth() const { return _history.undo_depth(); }
uint32_t redo_depth() const { return _history.redo_depth(); }
string next_undo() const { return _history.next_undo(); }
@@ -839,7 +842,7 @@ class Session : public PBD::StatefulDestructible
GlobalRouteBooleanState before, after;
Session& sess;
void* src;
-
+
};
class GlobalSoloStateCommand : public GlobalRouteStateCommand
@@ -896,7 +899,7 @@ class Session : public PBD::StatefulDestructible
/* clicking */
boost::shared_ptr<IO> click_io() { return _click_io; }
-
+
/* disk, buffer loads */
uint32_t playback_load ();
@@ -906,7 +909,7 @@ class Session : public PBD::StatefulDestructible
void reset_playback_load_min ();
void reset_capture_load_min ();
-
+
float read_data_rate () const;
float write_data_rate () const;
@@ -929,7 +932,7 @@ class Session : public PBD::StatefulDestructible
TransportContext,
ExportContext
};
-
+
/* VST support */
static long vst_callback (AEffect* effect,
@@ -938,7 +941,7 @@ class Session : public PBD::StatefulDestructible
long value,
void* ptr,
float opt);
-
+
typedef float (*compute_peak_t) (Sample *, nframes_t, float);
typedef void (*find_peaks_t) (Sample *, nframes_t, float *, float*);
typedef void (*apply_gain_to_buffer_t) (Sample *, nframes_t, float);
@@ -974,11 +977,11 @@ class Session : public PBD::StatefulDestructible
friend class Route;
void schedule_curve_reallocation ();
void update_latency_compensation (bool, bool);
-
+
private:
int create (bool& new_session, const string& mix_template, nframes_t initial_length);
void destroy ();
-
+
nframes_t compute_initial_length ();
enum SubState {
@@ -995,7 +998,7 @@ class Session : public PBD::StatefulDestructible
*/
typedef void (Session::*process_function_type)(nframes_t);
-
+
AudioEngine& _engine;
mutable gint processing_prohibited;
process_function_type process_function;
@@ -1039,13 +1042,13 @@ class Session : public PBD::StatefulDestructible
void update_latency_compensation_proxy (void* ignored);
void ensure_buffers (ChanCount howmany);
-
+
void process_scrub (nframes_t);
void process_without_events (nframes_t);
void process_with_events (nframes_t);
void process_audition (nframes_t);
int process_export (nframes_t, ARDOUR::ExportSpecification*);
-
+
/* slave tracking */
static const int delta_accumulator_size = 25;
@@ -1054,13 +1057,13 @@ class Session : public PBD::StatefulDestructible
long average_slave_delta;
int average_dir;
bool have_first_delta_accumulator;
-
+
enum SlaveState {
Stopped,
Waiting,
Running
};
-
+
SlaveState slave_state;
nframes_t slave_wait_end;
@@ -1116,6 +1119,7 @@ class Session : public PBD::StatefulDestructible
MIDI::Port* _mmc_port;
MIDI::Port* _mtc_port;
MIDI::Port* _midi_port;
+ MIDI::Port* _midi_clock_port;
string _path;
string _name;
bool session_send_mmc;
@@ -1153,7 +1157,7 @@ class Session : public PBD::StatefulDestructible
bool pending_locate_flush;
bool pending_abort;
bool pending_auto_loop;
-
+
Sample* butler_mixdown_buffer;
float* butler_gain_buffer;
pthread_t butler_thread;
@@ -1164,7 +1168,7 @@ class Session : public PBD::StatefulDestructible
int butler_request_pipe[2];
inline bool transport_work_requested() const { return g_atomic_int_get(&butler_should_do_transport_work); }
-
+
struct ButlerRequest {
enum Type {
Wake,
@@ -1191,8 +1195,8 @@ class Session : public PBD::StatefulDestructible
PostTransportInputChange = 0x20000,
PostTransportCurveRealloc = 0x40000
};
-
- static const PostTransportWork ProcessCannotProceedMask =
+
+ static const PostTransportWork ProcessCannotProceedMask =
PostTransportWork (PostTransportInputChange|
PostTransportSpeed|
PostTransportReverse|
@@ -1201,7 +1205,7 @@ class Session : public PBD::StatefulDestructible
PostTransportAudition|
PostTransportLocate|
PostTransportStop);
-
+
PostTransportWork post_transport_work;
void summon_butler ();
@@ -1264,7 +1268,7 @@ class Session : public PBD::StatefulDestructible
int midi_read (MIDI::Port *);
void enable_record ();
-
+
void increment_transport_position (uint32_t val) {
if (max_frames - val < _transport_frame) {
_transport_frame = max_frames;
@@ -1297,6 +1301,10 @@ class Session : public PBD::StatefulDestructible
void spp_continue (MIDI::Parser&);
void spp_stop (MIDI::Parser&);
+ void midi_clock_start (MIDI::Parser&);
+ void midi_clock_continue (MIDI::Parser&);
+ void midi_clock_stop (MIDI::Parser&);
+
void mmc_deferred_play (MIDI::MachineControl &);
void mmc_stop (MIDI::MachineControl &);
void mmc_step (MIDI::MachineControl &, int);
@@ -1327,7 +1335,7 @@ class Session : public PBD::StatefulDestructible
nframes_t outbound_mtc_smpte_frame;
SMPTE::Time transmitting_smpte_time;
int next_quarter_frame_to_send;
-
+
double _frames_per_smpte_frame; /* has to be floating point because of drop frame */
nframes_t _frames_per_hour;
nframes_t _smpte_frames_per_hour;
@@ -1339,28 +1347,28 @@ class Session : public PBD::StatefulDestructible
bool last_smpte_valid;
nframes_t last_smpte_when;
SMPTE::Time last_smpte;
-
+
bool _send_smpte_update; ///< Flag to send a full frame (SMPTE) MTC message this cycle
int send_full_time_code(nframes_t nframes);
int send_midi_time_code_for_cycle(nframes_t nframes);
nframes_t adjust_apparent_position (nframes_t frames);
-
+
void reset_record_status ();
-
+
int no_roll (nframes_t nframes, nframes_t offset);
-
+
bool non_realtime_work_pending() const { return static_cast<bool>(post_transport_work); }
bool process_can_proceed() const { return !(post_transport_work & ProcessCannotProceedMask); }
struct MIDIRequest {
-
+
enum Type {
PortChange,
Quit
};
-
+
Type type;
MIDIRequest () {}
@@ -1419,7 +1427,7 @@ class Session : public PBD::StatefulDestructible
/* disk-streams */
- SerializedRCUManager<DiskstreamList> diskstreams;
+ SerializedRCUManager<DiskstreamList> diskstreams;
uint32_t audio_dstream_buffer_size;
uint32_t midi_dstream_buffer_size;
@@ -1439,7 +1447,7 @@ class Session : public PBD::StatefulDestructible
bool solo_update_disabled;
bool currently_soloing;
-
+
void route_mute_changed (void *src);
void route_solo_changed (void *src, boost::weak_ptr<Route>);
void catch_up_on_solo ();
@@ -1452,7 +1460,7 @@ class Session : public PBD::StatefulDestructible
mutable Glib::Mutex region_lock;
typedef map<PBD::ID,boost::shared_ptr<Region> > RegionList;
RegionList regions;
-
+
void add_region (boost::shared_ptr<Region>);
void region_changed (Change, boost::weak_ptr<Region>);
void remove_region (boost::weak_ptr<Region>);
@@ -1460,7 +1468,7 @@ class Session : public PBD::StatefulDestructible
int load_regions (const XMLNode& node);
/* SOURCES */
-
+
mutable Glib::Mutex source_lock;
typedef std::map<PBD::ID,boost::shared_ptr<Source> > SourceMap;
@@ -1468,7 +1476,7 @@ class Session : public PBD::StatefulDestructible
public:
SourceMap get_sources() { return sources; }
-
+
private:
@@ -1478,7 +1486,7 @@ class Session : public PBD::StatefulDestructible
boost::shared_ptr<Source> XMLSourceFactory (const XMLNode&);
/* PLAYLISTS */
-
+
mutable Glib::Mutex playlist_lock;
typedef set<boost::shared_ptr<Playlist> > PlaylistList;
PlaylistList playlists;
@@ -1529,7 +1537,7 @@ class Session : public PBD::StatefulDestructible
int flatten_one_track (AudioTrack&, nframes_t start, nframes_t cnt);
/* INSERT AND SEND MANAGEMENT */
-
+
list<PortInsert *> _port_inserts;
list<PluginInsert *> _plugin_inserts;
list<Send *> _sends;
@@ -1547,8 +1555,8 @@ class Session : public PBD::StatefulDestructible
struct space_and_path {
uint32_t blocks; /* 4kB blocks */
string path;
-
- space_and_path() {
+
+ space_and_path() {
blocks = 0;
}
};
@@ -1558,14 +1566,14 @@ class Session : public PBD::StatefulDestructible
return a.blocks > b.blocks;
}
};
-
+
void setup_raid_path (string path);
vector<space_and_path> session_dirs;
vector<space_and_path>::iterator last_rr_session_dir;
uint32_t _total_free_4k_blocks;
Glib::Mutex space_lock;
-
+
string get_best_session_directory_for_new_source ();
void refresh_disk_space ();
@@ -1612,9 +1620,9 @@ class Session : public PBD::StatefulDestructible
nframes_t offset;
const Sample *data;
- Click (nframes_t s, nframes_t d, const Sample *b)
+ Click (nframes_t s, nframes_t d, const Sample *b)
: start (s), duration (d), data (b) { offset = 0; }
-
+
void *operator new(size_t ignored) {
return pool.alloc ();
};
@@ -1626,7 +1634,7 @@ class Session : public PBD::StatefulDestructible
private:
static Pool pool;
};
-
+
typedef list<Click*> Clicks;
Clicks clicks;
@@ -1649,7 +1657,7 @@ class Session : public PBD::StatefulDestructible
void click (nframes_t start, nframes_t nframes, nframes_t offset);
vector<Route*> master_outs;
-
+
/* range playback */
list<AudioRange> current_audio_range;
@@ -1659,7 +1667,7 @@ class Session : public PBD::StatefulDestructible
/* main outs */
uint32_t main_outs;
-
+
boost::shared_ptr<IO> _master_out;
boost::shared_ptr<IO> _control_out;
@@ -1702,10 +1710,10 @@ class Session : public PBD::StatefulDestructible
void config_changed (const char*);
XMLNode& get_control_protocol_state ();
-
+
void set_history_depth (uint32_t depth);
void sync_order_keys ();
-
+
static bool _disable_all_loaded_plugins;
};
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h
index 509f8fa9d2..9df8574430 100644
--- a/libs/ardour/ardour/slave.h
+++ b/libs/ardour/ardour/slave.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002 Paul Davis
+ Copyright (C) 2002 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
@@ -50,6 +50,18 @@ class Slave {
virtual bool is_always_synced() const { return false; }
};
+struct SafeTime {
+ int guard1;
+ nframes_t position;
+ nframes_t timestamp;
+ int guard2;
+
+ SafeTime() {
+ guard1 = 0;
+ guard2 = 0;
+ timestamp = 0;
+ }
+};
class MTC_Slave : public Slave, public sigc::trackable {
public:
@@ -59,9 +71,9 @@ class MTC_Slave : public Slave, public sigc::trackable {
void rebind (MIDI::Port&);
bool speed_and_position (float&, nframes_t&);
- bool locked() const;
- bool ok() const;
- void handle_locate (const MIDI::byte*);
+ bool locked() const;
+ bool ok() const;
+ void handle_locate (const MIDI::byte*);
nframes_t resolution() const;
bool requires_seekahead () const { return true; }
@@ -72,27 +84,11 @@ class MTC_Slave : public Slave, public sigc::trackable {
std::vector<sigc::connection> connections;
bool can_notify_on_unknown_rate;
- struct SafeTime {
-
-
- int guard1;
- //SMPTE_Time mtc;
- nframes_t position;
- nframes_t timestamp;
- int guard2;
-
- SafeTime() {
- guard1 = 0;
- guard2 = 0;
- timestamp = 0;
- }
- };
-
- SafeTime current;
+ SafeTime current;
nframes_t mtc_frame; /* current time */
nframes_t last_inbound_frame; /* when we got it; audio clocked */
- float mtc_speed;
+ float mtc_speed;
nframes_t first_mtc_frame;
nframes_t first_mtc_time;
@@ -108,12 +104,56 @@ class MTC_Slave : public Slave, public sigc::trackable {
void read_current (SafeTime *) const;
};
-class ADAT_Slave : public Slave
+class MIDIClock_Slave : public Slave, public sigc::trackable {
+ public:
+ MIDIClock_Slave (Session&, MIDI::Port&, int ppqn = 24);
+ ~MIDIClock_Slave ();
+
+ void rebind (MIDI::Port&);
+ bool speed_and_position (float&, nframes_t&);
+
+ bool locked() const;
+ bool ok() const;
+ bool starting() const { return _starting; }
+
+ nframes_t resolution() const;
+ bool requires_seekahead () const { return true; }
+
+ private:
+ Session& session;
+ MIDI::Port* port;
+ std::vector<sigc::connection> connections;
+
+ int ppqn;
+ double one_ppqn_in_frames;
+
+ SafeTime current;
+ nframes_t midi_clock_frame; /* current time */
+ nframes_t last_inbound_frame; /* when we got it; audio clocked */
+
+ float midi_clock_speed;
+ nframes_t first_midi_clock_frame;
+ nframes_t first_midi_clock_time;
+
+ static const int32_t accumulator_size = 128;
+ float accumulator[accumulator_size];
+ int32_t accumulator_index;
+ bool have_first_accumulated_speed;
+
+ void reset ();
+ void start (MIDI::Parser& parser);
+ void stop (MIDI::Parser& parser);
+ void update_midi_clock (MIDI::Parser& parser);
+ void read_current (SafeTime *) const;
+ bool _starting;
+};
+
+class ADAT_Slave : public Slave
{
public:
ADAT_Slave () {}
~ADAT_Slave () {}
-
+
bool speed_and_position (float& speed, nframes_t& pos) {
speed = 0;
pos = 0;
@@ -126,12 +166,12 @@ class ADAT_Slave : public Slave
bool requires_seekahead () const { return true; }
};
-class JACK_Slave : public Slave
+class JACK_Slave : public Slave
{
public:
JACK_Slave (jack_client_t*);
~JACK_Slave ();
-
+
bool speed_and_position (float& speed, nframes_t& pos);
bool starting() const { return _starting; }
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 9bfd93cdbf..d94683f427 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002 Paul Davis
+ Copyright (C) 2002 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
@@ -41,7 +41,7 @@
typedef int intptr_t;
#endif
-/* eventually, we'd like everything (including JACK) to
+/* eventually, we'd like everything (including JACK) to
move to this. for now, its a dedicated type.
*/
@@ -69,7 +69,7 @@ namespace ARDOUR {
OverlapNone, // no overlap
OverlapInternal, // the overlap is 100% with the object
OverlapStart, // overlap covers start, but ends within
- OverlapEnd, // overlap begins within and covers end
+ OverlapEnd, // overlap begins within and covers end
OverlapExternal // overlap extends to (at least) begin+end
};
@@ -128,12 +128,12 @@ namespace ARDOUR {
Normal,
Destructive
};
-
+
enum NoteMode {
Sustained,
Percussive
};
-
+
enum ChannelMode {
AllChannels = 0, ///< Pass through all channel information unmodified
FilterChannels, ///< Ignore events on certain channels
@@ -144,7 +144,7 @@ namespace ARDOUR {
Frames,
Beats
};
-
+
struct BBT_Time {
uint32_t bars;
uint32_t beats;
@@ -157,12 +157,12 @@ namespace ARDOUR {
}
/* we can't define arithmetic operators for BBT_Time, because
- the results depend on a TempoMap, but we can define
+ the results depend on a TempoMap, but we can define
a useful check on the less-than condition.
*/
bool operator< (const BBT_Time& other) const {
- return bars < other.bars ||
+ return bars < other.bars ||
(bars == other.bars && beats < other.beats) ||
(bars == other.bars && beats == other.beats && ticks < other.ticks);
}
@@ -170,7 +170,7 @@ namespace ARDOUR {
bool operator== (const BBT_Time& other) const {
return bars == other.bars && beats == other.beats && ticks == other.ticks;
}
-
+
};
enum SmpteFormat {
smpte_23976,
@@ -198,7 +198,7 @@ namespace ARDOUR {
SMPTE::Time smpte;
BBT_Time bbt;
- union {
+ union {
nframes_t frames;
double seconds;
};
@@ -210,10 +210,10 @@ namespace ARDOUR {
nframes_t start;
nframes_t end;
uint32_t id;
-
+
AudioRange (nframes_t s, nframes_t e, uint32_t i) : start (s), end (e) , id (i) {}
-
- nframes_t length() { return end - start + 1; }
+
+ nframes_t length() { return end - start + 1; }
bool operator== (const AudioRange& other) const {
return start == other.start && end == other.end && id == other.id;
@@ -227,12 +227,12 @@ namespace ARDOUR {
return ARDOUR::coverage (start, end, s, e);
}
};
-
+
struct MusicRange {
BBT_Time start;
BBT_Time end;
uint32_t id;
-
+
MusicRange (BBT_Time& s, BBT_Time& e, uint32_t i)
: start (s), end (e), id (i) {}
@@ -273,7 +273,7 @@ namespace ARDOUR {
Lock
};
- enum RegionPoint {
+ enum RegionPoint {
Start,
End,
SyncPoint
@@ -312,7 +312,7 @@ namespace ARDOUR {
FullCrossfade,
ShortCrossfade
};
-
+
enum LayerModel {
LaterHigher,
MoveAddHigher,
@@ -355,11 +355,11 @@ namespace ARDOUR {
struct PeakData {
typedef Sample PeakDatum;
-
+
PeakDatum min;
PeakDatum max;
};
-
+
enum PluginType {
AudioUnit,
LADSPA,
@@ -370,7 +370,8 @@ namespace ARDOUR {
enum SlaveSource {
None = 0,
MTC,
- JACK
+ JACK,
+ MIDIClock
};
enum ShuttleBehaviour {
@@ -399,8 +400,8 @@ namespace ARDOUR {
float time_fraction;
float pitch_fraction;
/* SoundTouch */
- bool quick_seek;
- bool antialias;
+ bool quick_seek;
+ bool antialias;
/* RubberBand */
int opts; // really RubberBandStretcher::Options
};
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 71b699396b..0781f8c8e1 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000-2007 Paul Davis
+ Copyright (C) 2000-2007 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
@@ -103,7 +103,7 @@ setup_enum_writer ()
REGISTER_ENUM (OverlapEnd);
REGISTER_ENUM (OverlapExternal);
REGISTER (_OverlapType);
-
+
REGISTER_ENUM (GainAutomation);
REGISTER_ENUM (PanAutomation);
REGISTER_ENUM (PluginAutomation);
@@ -126,22 +126,22 @@ setup_enum_writer ()
REGISTER_BITS (_AutoStyle);
REGISTER_ENUM (CaptureTime);
- REGISTER_ENUM (ExistingMaterial);
+ REGISTER_ENUM (ExistingMaterial);
REGISTER (_AlignStyle);
REGISTER_ENUM (MeterInput);
REGISTER_ENUM (MeterPreFader);
- REGISTER_ENUM (MeterPostFader);
+ REGISTER_ENUM (MeterPostFader);
REGISTER (_MeterPoint);
REGISTER_ENUM (Normal);
REGISTER_ENUM (Destructive);
REGISTER (_TrackMode);
-
+
REGISTER_ENUM (Sustained);
REGISTER_ENUM (Percussive);
REGISTER (_NoteMode);
-
+
REGISTER_ENUM (AllChannels);
REGISTER_ENUM (FilterChannels);
REGISTER_ENUM (ForceChannel);
@@ -155,7 +155,7 @@ setup_enum_writer ()
REGISTER_ENUM (MeterFalloffFaster);
REGISTER_ENUM (MeterFalloffFastest);
REGISTER (_MeterFalloff);
-
+
REGISTER_ENUM (MeterHoldOff);
REGISTER_ENUM (MeterHoldShort);
REGISTER_ENUM (MeterHoldMedium);
@@ -163,12 +163,12 @@ setup_enum_writer ()
REGISTER (_MeterHold);
REGISTER_ENUM (Slide);
- REGISTER_ENUM (Splice);
+ REGISTER_ENUM (Splice);
REGISTER (_EditMode);
REGISTER_ENUM (Start);
REGISTER_ENUM (End);
- REGISTER_ENUM (SyncPoint);
+ REGISTER_ENUM (SyncPoint);
REGISTER (_RegionPoint);
REGISTER_ENUM (PreFader);
@@ -197,11 +197,11 @@ setup_enum_writer ()
REGISTER_ENUM (LaterHigher);
REGISTER_ENUM (MoveAddHigher);
- REGISTER_ENUM (AddHigher);
+ REGISTER_ENUM (AddHigher);
REGISTER (_LayerModel);
REGISTER_ENUM (InverseMute);
- REGISTER_ENUM (SoloBus);
+ REGISTER_ENUM (SoloBus);
REGISTER (_SoloModel);
REGISTER_ENUM (AutoConnectPhysical);
@@ -219,7 +219,7 @@ setup_enum_writer ()
REGISTER_ENUM (CAF);
REGISTER_ENUM (AIFF);
REGISTER_ENUM (iXML);
- REGISTER_ENUM (RF64);
+ REGISTER_ENUM (RF64);
REGISTER (_HeaderFormat);
REGISTER_ENUM (AudioUnit);
@@ -229,15 +229,16 @@ setup_enum_writer ()
REGISTER_ENUM (None);
REGISTER_ENUM (MTC);
- REGISTER_ENUM (JACK);
+ REGISTER_ENUM (JACK);
+ REGISTER_ENUM (MIDIClock);
REGISTER (_SlaveSource);
REGISTER_ENUM (Sprung);
- REGISTER_ENUM (Wheel);
+ REGISTER_ENUM (Wheel);
REGISTER (_ShuttleBehaviour);
REGISTER_ENUM (Percentage);
- REGISTER_ENUM (Semitones);
+ REGISTER_ENUM (Semitones);
REGISTER (_ShuttleUnits);
REGISTER_CLASS_ENUM (Session, Disabled);
@@ -379,10 +380,10 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Track, Frozen);
REGISTER_CLASS_ENUM (Track, UnFrozen);
REGISTER (_Track_FreezeState);
-
+
REGISTER_CLASS_ENUM (AutomationList, Discrete);
REGISTER_CLASS_ENUM (AutomationList, Linear);
REGISTER_CLASS_ENUM (AutomationList, Curved);
REGISTER (_AutomationList_InterpolationStyle);
-
+
}
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index 02c4a5ced6..1397a7d959 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000 Paul Davis
+ Copyright (C) 2000 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
@@ -73,7 +73,7 @@
#if defined (__APPLE__)
#include <Carbon/Carbon.h> // For Gestalt
#endif
-
+
#include "i18n.h"
ARDOUR::Configuration* ARDOUR::Config = 0;
@@ -91,6 +91,7 @@ using namespace PBD;
MIDI::Port *default_mmc_port = 0;
MIDI::Port *default_mtc_port = 0;
MIDI::Port *default_midi_port = 0;
+MIDI::Port *default_midi_clock_port = 0;
Change ARDOUR::StartChanged = ARDOUR::new_change ();
Change ARDOUR::LengthChanged = ARDOUR::new_change ();
@@ -111,11 +112,11 @@ static int
setup_osc ()
{
/* no real cost to creating this object, and it avoids
- conditionals anywhere that uses it
+ conditionals anywhere that uses it
*/
-
+
osc = new OSC (Config->get_osc_port());
-
+
if (Config->get_use_osc ()) {
BootMessage (_("Starting OSC"));
return osc->start ();
@@ -125,7 +126,7 @@ setup_osc ()
}
#endif
-int
+int
setup_midi ()
{
if (Config->midi_ports.size() == 0) {
@@ -150,16 +151,20 @@ setup_midi ()
if (Config->get_mmc_port_name() != N_("default")) {
default_mmc_port = MIDI::Manager::instance()->port (Config->get_mmc_port_name());
- }
+ }
if (Config->get_mtc_port_name() != N_("default")) {
default_mtc_port = MIDI::Manager::instance()->port (Config->get_mtc_port_name());
- }
+ }
if (Config->get_midi_port_name() != N_("default")) {
default_midi_port = MIDI::Manager::instance()->port (Config->get_midi_port_name());
- }
-
+ }
+
+ if (Config->get_midi_clock_port_name() != N_("default")) {
+ default_midi_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) {
@@ -173,7 +178,11 @@ setup_midi ()
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.begin()->second;
@@ -183,21 +192,27 @@ setup_midi ()
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())
+ warning << string_compose (_("No MMC control (MIDI port \"%1\" not available)"), Config->get_mmc_port_name())
<< endmsg;
return 0;
- }
+ }
if (default_mtc_port == 0) {
- warning << string_compose (_("No MTC support (MIDI port \"%1\" not available)"), Config->get_mtc_port_name())
+ 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())
+ 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;
}
@@ -331,7 +346,7 @@ ARDOUR::init (bool use_vst, bool try_optimization)
return -1;
}
#endif
-
+
/* Make VAMP look in our library ahead of anything else */
char *p = getenv ("VAMP_PATH");
@@ -339,7 +354,7 @@ ARDOUR::init (bool use_vst, bool try_optimization)
if (p) {
vamppath += ':';
vamppath += p;
- }
+ }
setenv ("VAMP_PATH", vamppath.c_str(), 1);
@@ -350,7 +365,7 @@ ARDOUR::init (bool use_vst, bool try_optimization)
/* singleton - first object is "it" */
new PluginManager ();
-
+
/* singleton - first object is "it" */
new ControlProtocolManager ();
ControlProtocolManager::instance().discover_control_protocols ();
@@ -359,7 +374,7 @@ ARDOUR::init (bool use_vst, bool try_optimization)
if ((node = Config->control_protocol_state()) != 0) {
ControlProtocolManager::instance().set_state (*node);
}
-
+
BoundsChanged = Change (StartChanged|PositionChanged|LengthChanged);
return 0;
@@ -430,7 +445,7 @@ ARDOUR::find_bindings_files (map<string,string>& files)
if (found.empty()) {
return;
}
-
+
for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
sys::path path = *x;
pair<string,string> namepath;
@@ -445,7 +460,7 @@ ARDOUR::LocaleGuard::LocaleGuard (const char* str)
old = strdup (setlocale (LC_NUMERIC, NULL));
if (strcmp (old, str)) {
setlocale (LC_NUMERIC, str);
- }
+ }
}
ARDOUR::LocaleGuard::~LocaleGuard ()
@@ -472,7 +487,7 @@ ARDOUR::setup_fpu ()
/* XXX use real code to determine if the processor supports
DenormalsAreZero and FlushToZero
*/
-
+
if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
return;
}
@@ -496,7 +511,7 @@ ARDOUR::setup_fpu ()
MXCSR |= 0x8000;
}
break;
-
+
case DenormalFTZDAZ:
if (fpu.has_flush_to_zero()) {
if (fpu.has_denormals_are_zero()) {
@@ -514,7 +529,7 @@ ARDOUR::setup_fpu ()
}
ARDOUR::OverlapType
-ARDOUR::coverage (nframes_t sa, nframes_t ea,
+ARDOUR::coverage (nframes_t sa, nframes_t ea,
nframes_t sb, nframes_t eb)
{
/* OverlapType returned reflects how the second (B)
@@ -539,7 +554,7 @@ ARDOUR::coverage (nframes_t sa, nframes_t ea,
|-----------------| B
- "B is internal to A"
+ "B is internal to A"
*/
#ifdef OLD_COVERAGE
@@ -555,7 +570,7 @@ ARDOUR::coverage (nframes_t sa, nframes_t ea,
----| B
-----------------------| B
--| B
-
+
"B overlaps the start of A"
*/
@@ -563,13 +578,13 @@ ARDOUR::coverage (nframes_t sa, nframes_t ea,
if ((eb >= sa) && (eb <= ea)) {
return OverlapStart;
}
- /*
+ /*
|---------------------| A
|----------------- B
- |----------------------- B
+ |----------------------- B
|- B
- "B overlaps the end of A"
+ "B overlaps the end of A"
*/
if ((sb > sa) && (sb <= ea)) {
@@ -577,7 +592,7 @@ ARDOUR::coverage (nframes_t sa, nframes_t ea,
}
/*
|--------------------| A
- -------------------------- B
+ -------------------------- B
|----------------------- B
----------------------| B
|--------------------| B
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index ff269cc931..1124b8960f 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1999-2004 Paul Davis
+ Copyright (C) 1999-2004 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
@@ -131,11 +131,12 @@ Session::Session (AudioEngine &eng,
_mmc_port (default_mmc_port),
_mtc_port (default_mtc_port),
_midi_port (default_midi_port),
+ _midi_clock_port (default_midi_clock_port),
_session_dir (new SessionDirectory(fullpath)),
pending_events (2048),
post_transport_work((PostTransportWork)0),
_send_smpte_update (false),
- midi_requests (128),
+ midi_requests (128),
diskstreams (new DiskstreamList),
routes (new RouteList),
auditioner ((Auditioner*) 0),
@@ -148,7 +149,7 @@ Session::Session (AudioEngine &eng,
if (!eng.connected()) {
throw failed_constructor();
}
-
+
cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl;
n_physical_outputs = _engine.n_physical_outputs();
@@ -164,14 +165,14 @@ Session::Session (AudioEngine &eng,
throw failed_constructor ();
}
}
-
+
if (second_stage_init (new_session)) {
destroy ();
throw failed_constructor ();
}
-
+
store_recent_sessions(_name, _path);
-
+
bool was_dirty = dirty();
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
@@ -201,6 +202,7 @@ Session::Session (AudioEngine &eng,
_mmc_port (default_mmc_port),
_mtc_port (default_mtc_port),
_midi_port (default_midi_port),
+ _midi_clock_port (default_midi_clock_port),
_session_dir ( new SessionDirectory(fullpath)),
pending_events (2048),
post_transport_work((PostTransportWork)0),
@@ -244,31 +246,31 @@ Session::Session (AudioEngine &eng,
{
/* set up Master Out and Control Out if necessary */
-
+
RouteList rl;
int control_id = 1;
-
+
if (control_out_channels) {
shared_ptr<Route> r (new Route (*this, _("monitor"), -1, control_out_channels, -1, control_out_channels, Route::ControlOut));
r->set_remote_control_id (control_id++);
-
+
rl.push_back (r);
}
-
+
if (master_out_channels) {
shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
r->set_remote_control_id (control_id);
-
+
rl.push_back (r);
} else {
/* prohibit auto-connect to master, because there isn't one */
output_ac = AutoConnectOption (output_ac & ~AutoConnectMaster);
}
-
+
if (!rl.empty()) {
add_routes (rl, false);
}
-
+
}
Config->set_input_auto_connect (input_ac);
@@ -278,9 +280,9 @@ Session::Session (AudioEngine &eng,
destroy ();
throw failed_constructor ();
}
-
+
store_recent_sessions (_name, _path);
-
+
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
@@ -305,7 +307,7 @@ Session::destroy ()
_engine.remove_session ();
GoingAway (); /* EMIT SIGNAL */
-
+
/* do this */
notify_callbacks ();
@@ -315,14 +317,14 @@ Session::destroy ()
_history.clear ();
/* clear state tree so that no references to objects are held any more */
-
+
if (state_tree) {
delete state_tree;
}
terminate_butler_thread ();
//terminate_midi_thread ();
-
+
if (click_data && click_data != default_click) {
delete [] click_data;
}
@@ -338,9 +340,9 @@ Session::destroy ()
delete _mix_buffers;
AudioDiskstream::free_working_buffers();
-
+
Route::SyncOrderKeys.clear();
-
+
#undef TRACK_DESTRUCTION
#ifdef TRACK_DESTRUCTION
cerr << "delete named selections\n";
@@ -365,10 +367,10 @@ Session::destroy ()
++tmp;
(*i)->drop_references ();
-
+
i = tmp;
}
-
+
for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ) {
PlaylistList::iterator tmp;
@@ -376,17 +378,17 @@ Session::destroy ()
++tmp;
(*i)->drop_references ();
-
+
i = tmp;
}
-
+
playlists.clear ();
unused_playlists.clear ();
#ifdef TRACK_DESTRUCTION
cerr << "delete regions\n";
#endif /* TRACK_DESTRUCTION */
-
+
for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
RegionList::iterator tmp;
@@ -436,13 +438,13 @@ Session::destroy ()
tmp = i;
++tmp;
-
+
i->second->drop_references ();
-
+
i = tmp;
}
sources.clear ();
-
+
#ifdef TRACK_DESTRUCTION
cerr << "delete mix groups\n";
#endif /* TRACK_DESTRUCTION */
@@ -462,7 +464,7 @@ Session::destroy ()
#endif /* TRACK_DESTRUCTION */
for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ) {
list<RouteGroup*>::iterator tmp;
-
+
tmp = i;
++tmp;
@@ -470,7 +472,7 @@ Session::destroy ()
i = tmp;
}
-
+
if (butler_mixdown_buffer) {
delete [] butler_mixdown_buffer;
}
@@ -497,7 +499,7 @@ Session::set_worst_io_latencies ()
}
boost::shared_ptr<RouteList> r = routes.reader ();
-
+
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
_worst_output_latency = max (_worst_output_latency, (*i)->output_latency());
_worst_input_latency = max (_worst_input_latency, (*i)->input_latency());
@@ -536,15 +538,15 @@ Session::when_engine_running ()
try {
XMLNode* child = 0;
-
+
_click_io.reset (new ClickIO (*this, "click", 0, 0, -1, -1));
if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
/* existing state for Click */
-
+
if (_click_io->set_state (*child->children().front()) == 0) {
-
+
_clicking = Config->get_clicking ();
} else {
@@ -554,7 +556,7 @@ Session::when_engine_running ()
}
} else {
-
+
/* default state for Click */
first_physical_output = _engine.get_nth_physical_output (DataType::AUDIO, 0);
@@ -642,24 +644,24 @@ Session::when_engine_running ()
if (_master_out) {
/* create master/control ports */
-
+
if (_master_out) {
uint32_t n;
/* force the master to ignore any later call to this */
-
+
if (_master_out->pending_state_node) {
_master_out->ports_became_legal();
}
/* no panner resets till we are through */
-
+
_master_out->defer_pan_reset ();
-
+
while (_master_out->n_inputs().n_audio()
< _master_out->input_maximum().n_audio()) {
if (_master_out->add_input_port ("", this, DataType::AUDIO)) {
- error << _("cannot setup master inputs")
+ error << _("cannot setup master inputs")
<< endmsg;
break;
}
@@ -676,7 +678,7 @@ Session::when_engine_running ()
}
_master_out->allow_pan_reset ();
-
+
}
shared_ptr<AutoBundle> c (new AutoBundle (_("Master Out"), true));
@@ -686,8 +688,8 @@ Session::when_engine_running ()
c->set_port (n, _master_out->input(n)->name());
}
add_bundle (c);
- }
-
+ }
+
BootMessage (_("Setup signal flow and plugins"));
hookup_io ();
@@ -697,7 +699,7 @@ Session::when_engine_running ()
BootMessage (_("Catch up with send/insert state"));
insert_cnt = 0;
-
+
for (list<PortInsert*>::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) {
uint32_t id;
@@ -712,7 +714,7 @@ Session::when_engine_running ()
for (list<Send*>::iterator i = _sends.begin(); i != _sends.end(); ++i) {
uint32_t id;
-
+
if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
if (id > send_cnt) {
send_cnt = id;
@@ -720,7 +722,7 @@ Session::when_engine_running ()
}
}
-
+
_state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
/* hook us up to the engine */
@@ -736,7 +738,7 @@ Session::when_engine_running ()
osc->set_session (*this);
#endif
-
+
}
void
@@ -750,16 +752,16 @@ Session::hookup_io ()
if (auditioner == 0) {
-
+
/* we delay creating the auditioner till now because
it makes its own connections to ports.
the engine has to be running for this to work.
*/
-
+
try {
auditioner.reset (new Auditioner (*this));
}
-
+
catch (failed_constructor& err) {
warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
}
@@ -797,7 +799,7 @@ Session::hookup_io ()
cports.push_back (_control_out->input(n)->name());
}
- boost::shared_ptr<RouteList> r = routes.reader ();
+ boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
(*x)->set_control_outs (cports);
@@ -808,7 +810,7 @@ Session::hookup_io ()
if (_bundle_xml_node) {
load_bundles (*_bundle_xml_node);
delete _bundle_xml_node;
- }
+ }
/* Tell all IO objects to connect themselves together */
@@ -839,10 +841,10 @@ Session::hookup_io ()
void
Session::playlist_length_changed ()
{
- /* we can't just increase end_location->end() if pl->get_maximum_extent()
+ /* we can't just increase end_location->end() if pl->get_maximum_extent()
if larger. if the playlist used to be the longest playlist,
and its now shorter, we have to decrease end_location->end(). hence,
- we have to iterate over all diskstreams and check the
+ we have to iterate over all diskstreams and check the
playlists currently in use.
*/
find_current_end ();
@@ -856,7 +858,7 @@ Session::diskstream_playlist_changed (boost::shared_ptr<Diskstream> dstream)
if ((playlist = dstream->playlist()) != 0) {
playlist->LengthChanged.connect (mem_fun (this, &Session::playlist_length_changed));
}
-
+
/* see comment in playlist_length_changed () */
find_current_end ();
}
@@ -909,7 +911,7 @@ Session::auto_punch_start_changed (Location* location)
/* capture start has been changed, so save new pending state */
save_state ("", true);
}
-}
+}
void
Session::auto_punch_end_changed (Location* location)
@@ -917,7 +919,7 @@ Session::auto_punch_end_changed (Location* location)
nframes_t when_to_stop = location->end();
// when_to_stop += _worst_output_latency + _worst_input_latency;
replace_event (Event::PunchOut, when_to_stop);
-}
+}
void
Session::auto_punch_changed (Location* location)
@@ -927,7 +929,7 @@ Session::auto_punch_changed (Location* location)
replace_event (Event::PunchIn, location->start());
//when_to_stop += _worst_output_latency + _worst_input_latency;
replace_event (Event::PunchOut, when_to_stop);
-}
+}
void
Session::auto_loop_changed (Location* location)
@@ -941,12 +943,12 @@ Session::auto_loop_changed (Location* location)
if (_transport_frame > location->end()) {
// relocate to beginning of loop
clear_events (Event::LocateRoll);
-
+
request_locate (location->start(), true);
}
else if (Config->get_seamless_loop() && !loop_changing) {
-
+
// schedule a locate-roll to refill the diskstreams at the
// previous loop end
loop_changing = true;
@@ -958,7 +960,7 @@ Session::auto_loop_changed (Location* location)
}
}
- }
+ }
last_loopend = location->end();
}
@@ -983,7 +985,7 @@ Session::set_auto_punch_location (Location* location)
if (location == 0) {
return;
}
-
+
if (location->end() <= location->start()) {
error << _("Session: you can't use that location for auto punch (start <= end)") << endmsg;
return;
@@ -992,7 +994,7 @@ Session::set_auto_punch_location (Location* location)
auto_punch_start_changed_connection.disconnect();
auto_punch_end_changed_connection.disconnect();
auto_punch_changed_connection.disconnect();
-
+
auto_punch_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_punch_start_changed));
auto_punch_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_punch_end_changed));
auto_punch_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_punch_changed));
@@ -1018,7 +1020,7 @@ Session::set_auto_loop_location (Location* location)
remove_event (existing->end(), Event::AutoLoop);
auto_loop_location_changed (0);
}
-
+
set_dirty();
if (location == 0) {
@@ -1031,11 +1033,11 @@ Session::set_auto_loop_location (Location* location)
}
last_loopend = location->end();
-
+
auto_loop_start_changed_connection.disconnect();
auto_loop_end_changed_connection.disconnect();
auto_loop_changed_connection.disconnect();
-
+
auto_loop_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_loop_changed));
auto_loop_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_loop_changed));
auto_loop_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_loop_changed));
@@ -1083,7 +1085,7 @@ Session::handle_locations_changed (Locations::LocationList& locations)
set_auto_loop_location (location);
set_loop = true;
}
-
+
}
if (!set_loop) {
@@ -1094,7 +1096,7 @@ Session::handle_locations_changed (Locations::LocationList& locations)
}
set_dirty();
-}
+}
void
Session::enable_record ()
@@ -1109,7 +1111,7 @@ Session::enable_record ()
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
- (*i)->monitor_input (true);
+ (*i)->monitor_input (true);
}
}
}
@@ -1141,14 +1143,14 @@ Session::disable_record (bool rt_context, bool force)
if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
-
+
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
- (*i)->monitor_input (false);
+ (*i)->monitor_input (false);
}
}
}
-
+
RecordStateChanged (); /* emit signal */
if (!rt_context) {
@@ -1166,11 +1168,11 @@ Session::step_back_from_record ()
if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
-
+
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
- (*i)->monitor_input (false);
+ (*i)->monitor_input (false);
}
}
}
@@ -1191,7 +1193,7 @@ Session::maybe_enable_record ()
if (_transport_speed) {
if (!Config->get_punch_in()) {
enable_record ();
- }
+ }
} else {
deliver_mmc (MIDI::MachineControl::cmdRecordPause, _transport_frame);
RecordStateChanged (); /* EMIT SIGNAL */
@@ -1208,7 +1210,7 @@ Session::audible_frame () const
nframes_t tf;
/* the first of these two possible settings for "offset"
- mean that the audible frame is stationary until
+ mean that the audible frame is stationary until
audio emerges from the latency compensation
"pseudo-pipeline".
@@ -1221,7 +1223,7 @@ Session::audible_frame () const
if (offset > current_block_size) {
offset -= current_block_size;
- } else {
+ } else {
/* XXX is this correct? if we have no external
physical connections and everything is internal
then surely this is zero? still, how
@@ -1251,7 +1253,7 @@ Session::audible_frame () const
/* MOVING */
/* take latency into account */
-
+
ret -= offset;
}
@@ -1262,7 +1264,7 @@ void
Session::set_frame_rate (nframes_t frames_per_second)
{
/** \fn void Session::set_frame_size(nframes_t)
- the AudioEngine object that calls this guarantees
+ the AudioEngine object that calls this guarantees
that it will not be called while we are also in
::process(). Its fine to do things that block
here.
@@ -1275,7 +1277,7 @@ Session::set_frame_rate (nframes_t frames_per_second)
Automatable::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * (0.001 * Config->get_automation_interval())));
clear_clicks ();
-
+
// XXX we need some equivalent to this, somehow
// SndFileSource::setup_standard_crossfades (frames_per_second);
@@ -1287,14 +1289,14 @@ Session::set_frame_rate (nframes_t frames_per_second)
void
Session::set_block_size (nframes_t nframes)
{
- /* the AudioEngine guarantees
+ /* the AudioEngine guarantees
that it will not be called while we are also in
::process(). It is therefore fine to do things that block
here.
*/
- {
-
+ {
+
current_block_size = nframes;
ensure_buffers(_scratch_buffers->available());
@@ -1311,7 +1313,7 @@ Session::set_block_size (nframes_t nframes)
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->set_block_size (nframes);
}
-
+
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->set_block_size (nframes);
@@ -1326,18 +1328,18 @@ Session::set_default_fade (float steepness, float fade_msecs)
{
#if 0
nframes_t fade_frames;
-
+
/* Don't allow fade of less 1 frame */
-
+
if (fade_msecs < (1000.0 * (1.0/_current_frame_rate))) {
fade_msecs = 0;
fade_frames = 0;
} else {
-
+
fade_frames = (nframes_t) floor (fade_msecs * _current_frame_rate * 0.001);
-
+
}
default_fade_msecs = fade_msecs;
@@ -1352,7 +1354,7 @@ Session::set_default_fade (float steepness, float fade_msecs)
set_dirty();
/* XXX have to do this at some point */
- /* foreach region using default fade, reset, then
+ /* foreach region using default fade, reset, then
refill_all_diskstream_buffers ();
*/
#endif
@@ -1388,7 +1390,7 @@ trace_terminal (shared_ptr<Route> r1, shared_ptr<Route> rbase)
if ((r1->fed_by.find (rbase) != r1->fed_by.end()) && (rbase->fed_by.find (r1) != rbase->fed_by.end())) {
info << string_compose(_("feedback loop setup between %1 and %2"), r1->name(), rbase->name()) << endmsg;
return;
- }
+ }
/* make a copy of the existing list of routes that feed r1 */
@@ -1452,45 +1454,45 @@ void
Session::resort_routes_using (shared_ptr<RouteList> r)
{
RouteList::iterator i, j;
-
+
for (i = r->begin(); i != r->end(); ++i) {
-
+
(*i)->fed_by.clear ();
-
+
for (j = r->begin(); j != r->end(); ++j) {
-
+
/* although routes can feed themselves, it will
cause an endless recursive descent if we
detect it. so don't bother checking for
self-feeding.
*/
-
+
if (*j == *i) {
continue;
}
-
+
if ((*j)->feeds (*i)) {
(*i)->fed_by.insert (*j);
- }
+ }
}
}
-
+
for (i = r->begin(); i != r->end(); ++i) {
trace_terminal (*i, *i);
}
-
+
RouteSorter cmp;
r->sort (cmp);
-
+
#if 0
cerr << "finished route resort\n";
-
+
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
cerr << " " << (*i)->name() << " signal order = " << (*i)->order_key ("signal") << endl;
}
cerr << endl;
#endif
-
+
}
list<boost::shared_ptr<MidiTrack> >
@@ -1505,7 +1507,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
//uint32_t control_id;
// FIXME: need physical I/O and autoconnect stuff for MIDI
-
+
/* count existing midi tracks */
{
@@ -1539,7 +1541,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
save, close,restart,add new route - first named route is now
Audio2)
*/
-
+
do {
++track_id;
@@ -1549,7 +1551,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
if (route_by_name (track_name) == 0) {
break;
}
-
+
} while (track_id < (UINT_MAX-1));
/*
@@ -1558,7 +1560,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
} else {
nphysical_in = 0;
}
-
+
if (Config->get_output_auto_connect() & AutoConnectPhysical) {
nphysical_out = min (n_physical_outputs, (uint32_t) physinputs.size());
} else {
@@ -1567,10 +1569,10 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
*/
shared_ptr<MidiTrack> track;
-
+
try {
track = boost::shared_ptr<MidiTrack>((new MidiTrack (*this, track_name, Route::Flag (0), mode)));
-
+
if (track->ensure_io (ChanCount(DataType::MIDI, 1), ChanCount(DataType::AUDIO, 1), false, this)) {
error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
goto failed;
@@ -1579,23 +1581,23 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
/*
if (nphysical_in) {
for (uint32_t x = 0; x < track->n_inputs().n_midi() && x < nphysical_in; ++x) {
-
+
port = "";
-
+
if (Config->get_input_auto_connect() & AutoConnectPhysical) {
port = physinputs[(channels_used+x)%nphysical_in];
- }
-
+ }
+
if (port.length() && track->connect_input (track->input (x), port, this)) {
break;
}
}
}
-
+
for (uint32_t x = 0; x < track->n_outputs().n_midi(); ++x) {
-
+
port = "";
-
+
if (nphysical_out && (Config->get_output_auto_connect() & AutoConnectPhysical)) {
port = physoutputs[(channels_used+x)%nphysical_out];
} else if (Config->get_output_auto_connect() & AutoConnectMaster) {
@@ -1603,18 +1605,18 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
port = _master_out->input (x%_master_out->n_inputs().n_midi())->name();
}
}
-
+
if (port.length() && track->connect_output (track->output (x), port, this)) {
break;
}
}
-
+
channels_used += track->n_inputs ().n_midi();
*/
track->midi_diskstream()->non_realtime_input_change();
-
+
track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
//track->set_remote_control_id (control_id);
@@ -1629,7 +1631,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
/* we need to get rid of this, since the track failed to be created */
/* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
- {
+ {
RCUWriter<DiskstreamList> writer (diskstreams);
boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->remove (track->midi_diskstream());
@@ -1647,7 +1649,7 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
/* we need to get rid of this, since the track failed to be created */
/* XXX arguably, MidiTrack::MidiTrack should not do the Session::add_diskstream() */
- {
+ {
RCUWriter<DiskstreamList> writer (diskstreams);
boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->remove (track->midi_diskstream());
@@ -1712,7 +1714,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
save, close,restart,add new route - first named route is now
Audio2)
*/
-
+
do {
++track_id;
@@ -1722,7 +1724,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
if (route_by_name (track_name) == 0) {
break;
}
-
+
} while (track_id < (UINT_MAX-1));
if (Config->get_input_auto_connect() & AutoConnectPhysical) {
@@ -1730,7 +1732,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
} else {
nphysical_in = 0;
}
-
+
if (Config->get_output_auto_connect() & AutoConnectPhysical) {
nphysical_out = min (n_physical_outputs, (uint32_t) physinputs.size());
} else {
@@ -1738,10 +1740,10 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
}
shared_ptr<AudioTrack> track;
-
+
try {
track = boost::shared_ptr<AudioTrack>((new AudioTrack (*this, track_name, Route::Flag (0), mode)));
-
+
if (track->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
@@ -1751,23 +1753,23 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
if (nphysical_in) {
for (uint32_t x = 0; x < track->n_inputs().n_audio() && x < nphysical_in; ++x) {
-
+
port = "";
-
+
if (Config->get_input_auto_connect() & AutoConnectPhysical) {
port = physinputs[(channels_used+x)%nphysical_in];
- }
-
+ }
+
if (port.length() && track->connect_input (track->input (x), port, this)) {
break;
}
}
}
-
+
for (uint32_t x = 0; x < track->n_outputs().n_midi(); ++x) {
-
+
port = "";
-
+
if (nphysical_out && (Config->get_output_auto_connect() & AutoConnectPhysical)) {
port = physoutputs[(channels_used+x)%nphysical_out];
} else if (Config->get_output_auto_connect() & AutoConnectMaster) {
@@ -1775,16 +1777,16 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
port = _master_out->input (x%_master_out->n_inputs().n_audio())->name();
}
}
-
+
if (port.length() && track->connect_output (track->output (x), port, this)) {
break;
}
}
-
+
channels_used += track->n_inputs ().n_audio();
track->audio_diskstream()->non_realtime_input_change();
-
+
track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
track->set_remote_control_id (control_id);
++control_id;
@@ -1800,7 +1802,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
/* we need to get rid of this, since the track failed to be created */
/* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
- {
+ {
RCUWriter<DiskstreamList> writer (diskstreams);
boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->remove (track->audio_diskstream());
@@ -1818,7 +1820,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
/* we need to get rid of this, since the track failed to be created */
/* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
- {
+ {
RCUWriter<DiskstreamList> writer (diskstreams);
boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->remove (track->audio_diskstream());
@@ -1847,14 +1849,14 @@ Session::set_remote_control_ids ()
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if ( MixerOrdered == m) {
+ if ( MixerOrdered == m) {
long order = (*i)->order_key(N_("signal"));
(*i)->set_remote_control_id( order+1 );
} else if ( EditorOrdered == m) {
long order = (*i)->order_key(N_("editor"));
(*i)->set_remote_control_id( order+1 );
} else if ( UserOrdered == m) {
- //do nothing ... only changes to remote id's are initiated by user
+ //do nothing ... only changes to remote id's are initiated by user
}
}
}
@@ -1906,31 +1908,31 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
try {
shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
-
+
if (bus->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
<< endmsg;
goto failure;
}
-
+
for (uint32_t x = 0; n_physical_inputs && x < bus->n_inputs().n_audio(); ++x) {
-
+
port = "";
if (Config->get_input_auto_connect() & AutoConnectPhysical) {
port = physinputs[((n+x)%n_physical_inputs)];
- }
-
+ }
+
if (port.length() && bus->connect_input (bus->input (x), port, this)) {
break;
}
}
-
+
for (uint32_t x = 0; n_physical_outputs && x < bus->n_outputs().n_audio(); ++x) {
-
+
port = "";
-
+
if (Config->get_output_auto_connect() & AutoConnectPhysical) {
port = physoutputs[((n+x)%n_physical_outputs)];
} else if (Config->get_output_auto_connect() & AutoConnectMaster) {
@@ -1938,18 +1940,18 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
port = _master_out->input (x%_master_out->n_inputs().n_audio())->name();
}
}
-
+
if (port.length() && bus->connect_output (bus->output (x), port, this)) {
break;
}
}
-
+
bus->set_remote_control_id (control_id);
++control_id;
ret.push_back (bus);
}
-
+
catch (failed_constructor &err) {
error << _("Session: could not create new audio route.") << endmsg;
@@ -1977,7 +1979,7 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
void
Session::add_routes (RouteList& new_routes, bool save)
{
- {
+ {
RCUWriter<RouteList> writer (routes);
shared_ptr<RouteList> r = writer.get_copy ();
r->insert (r->end(), new_routes.begin(), new_routes.end());
@@ -1985,18 +1987,18 @@ Session::add_routes (RouteList& new_routes, bool save)
}
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
-
+
boost::weak_ptr<Route> wpr (*x);
(*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr));
(*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
(*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
(*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false));
-
+
if ((*x)->is_master()) {
_master_out = (*x);
}
-
+
if ((*x)->is_control()) {
_control_out = (*x);
}
@@ -2017,7 +2019,7 @@ Session::add_routes (RouteList& new_routes, bool save)
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
(*x)->set_control_outs (cports);
}
- }
+ }
set_dirty();
@@ -2033,7 +2035,7 @@ Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
{
/* need to do this in case we're rolling at the time, to prevent false underruns */
dstream->do_refill_with_alloc ();
-
+
dstream->set_block_size (current_block_size);
{
@@ -2041,7 +2043,7 @@ Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->push_back (dstream);
/* writer goes out of scope, copies ds back to main */
- }
+ }
dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream));
/* this will connect to future changes, and check the current length */
@@ -2054,10 +2056,10 @@ Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
void
Session::remove_route (shared_ptr<Route> route)
{
- {
+ {
RCUWriter<RouteList> writer (routes);
shared_ptr<RouteList> rs = writer.get_copy ();
-
+
rs->remove (route);
/* deleting the master out seems like a dumb
@@ -2082,17 +2084,17 @@ Session::remove_route (shared_ptr<Route> route)
}
update_route_solo_state ();
-
+
/* writer goes out of scope, forces route list update */
}
Track* t;
boost::shared_ptr<Diskstream> ds;
-
+
if ((t = dynamic_cast<Track*>(route.get())) != 0) {
ds = t->diskstream();
}
-
+
if (ds) {
{
@@ -2103,12 +2105,12 @@ Session::remove_route (shared_ptr<Route> route)
}
find_current_end ();
-
- // We need to disconnect the routes inputs and outputs
+
+ // We need to disconnect the routes inputs and outputs
route->disconnect_inputs (0);
route->disconnect_outputs (0);
-
+
update_latency_compensation (false, false);
set_dirty();
@@ -2127,7 +2129,7 @@ Session::remove_route (shared_ptr<Route> route)
if (save_state (_current_snapshot_name)) {
save_history (_current_snapshot_name);
}
-}
+}
void
Session::route_mute_changed (void* src)
@@ -2137,12 +2139,12 @@ Session::route_mute_changed (void* src)
void
Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
-{
+{
if (solo_update_disabled) {
// We know already
return;
}
-
+
bool is_track;
boost::shared_ptr<Route> route = wpr.lock ();
@@ -2153,46 +2155,46 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
}
is_track = (boost::dynamic_pointer_cast<AudioTrack>(route) != 0);
-
+
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-
+
/* soloing a track mutes all other tracks, soloing a bus mutes all other busses */
-
+
if (is_track) {
-
+
/* don't mess with busses */
-
+
if (dynamic_cast<Track*>((*i).get()) == 0) {
continue;
}
-
+
} else {
-
+
/* don't mess with tracks */
-
+
if (dynamic_cast<Track*>((*i).get()) != 0) {
continue;
}
}
-
+
if ((*i) != route &&
((*i)->mix_group () == 0 ||
(*i)->mix_group () != route->mix_group () ||
!route->mix_group ()->is_active())) {
-
+
if ((*i)->soloed()) {
-
+
/* if its already soloed, and solo latching is enabled,
then leave it as it is.
*/
-
+
if (Config->get_solo_latched()) {
continue;
- }
+ }
}
-
+
/* do it */
solo_update_disabled = true;
@@ -2200,7 +2202,7 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
solo_update_disabled = false;
}
}
-
+
bool something_soloed = false;
bool same_thing_soloed = false;
bool signal = false;
@@ -2222,12 +2224,12 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
break;
}
}
-
+
if (something_soloed != currently_soloing) {
signal = true;
currently_soloing = something_soloed;
}
-
+
modify_solo_mute (is_track, same_thing_soloed);
if (signal) {
@@ -2251,7 +2253,7 @@ Session::update_route_solo_state ()
/* this is where we actually implement solo by changing
the solo mute setting of each track.
*/
-
+
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
@@ -2276,7 +2278,7 @@ Session::update_route_solo_state ()
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->set_solo_mute (false);
}
-
+
if (signal) {
SoloActive (false);
}
@@ -2297,11 +2299,11 @@ Session::modify_solo_mute (bool is_track, bool mute)
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-
+
if (is_track) {
-
+
/* only alter track solo mute */
-
+
if (dynamic_cast<Track*>((*i).get())) {
if ((*i)->soloed()) {
(*i)->set_solo_mute (!mute);
@@ -2325,7 +2327,7 @@ Session::modify_solo_mute (bool is_track, bool mute)
/* don't mute master or control outs
in response to another bus solo
*/
-
+
if ((*i) != _master_out &&
(*i) != _control_out) {
(*i)->set_solo_mute (mute);
@@ -2335,7 +2337,7 @@ Session::modify_solo_mute (bool is_track, bool mute)
}
}
-}
+}
void
@@ -2347,8 +2349,8 @@ Session::catch_up_on_solo ()
has.
*/
update_route_solo_state();
-}
-
+}
+
shared_ptr<Route>
Session::route_by_name (string name)
{
@@ -2411,7 +2413,7 @@ nframes_t
Session::get_maximum_extent () const
{
nframes_t max = 0;
- nframes_t me;
+ nframes_t me;
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
@@ -2464,7 +2466,7 @@ Session::new_region_name (string old)
char buf[len];
if ((last_period = old.find_last_of ('.')) == string::npos) {
-
+
/* no period present - add one explicitly */
old += '.';
@@ -2492,7 +2494,7 @@ Session::new_region_name (string old)
break;
}
}
-
+
if (i == regions.end()) {
break;
}
@@ -2500,7 +2502,7 @@ Session::new_region_name (string old)
if (number != (UINT_MAX-1)) {
return buf;
- }
+ }
error << string_compose (_("cannot create new name for region \"%1\""), old) << endmsg;
return old;
@@ -2515,19 +2517,19 @@ Session::region_name (string& result, string base, bool newlevel) const
assert(base.find("/") == string::npos);
if (base == "") {
-
+
Glib::Mutex::Lock lm (region_lock);
snprintf (buf, sizeof (buf), "%d", (int)regions.size() + 1);
-
+
result = "region.";
result += buf;
} else {
/* XXX this is going to be slow. optimize me later */
-
+
if (newlevel) {
subbase = base;
} else {
@@ -2542,38 +2544,38 @@ Session::region_name (string& result, string base, bool newlevel) const
}
bool name_taken = true;
-
+
{
Glib::Mutex::Lock lm (region_lock);
-
+
for (int n = 1; n < 5000; ++n) {
-
+
result = subbase;
snprintf (buf, sizeof (buf), ".%d", n);
result += buf;
-
+
name_taken = false;
-
+
for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
if (i->second->name() == result) {
name_taken = true;
break;
}
}
-
+
if (!name_taken) {
break;
}
}
}
-
+
if (name_taken) {
fatal << string_compose(_("too many regions with names like %1"), base) << endmsg;
/*NOTREACHED*/
}
}
return 0;
-}
+}
void
Session::add_region (boost::shared_ptr<Region> region)
@@ -2582,49 +2584,49 @@ Session::add_region (boost::shared_ptr<Region> region)
v.push_back (region);
add_regions (v);
}
-
+
void
Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions)
{
bool added = false;
- {
+ {
Glib::Mutex::Lock lm (region_lock);
for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) {
-
+
boost::shared_ptr<Region> region = *ii;
-
+
if (region == 0) {
error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
} else {
-
+
RegionList::iterator x;
-
+
for (x = regions.begin(); x != regions.end(); ++x) {
-
+
if (region->region_list_equivalent (x->second)) {
break;
}
}
-
+
if (x == regions.end()) {
-
+
pair<RegionList::key_type,RegionList::mapped_type> entry;
-
+
entry.first = region->id();
entry.second = region;
-
+
pair<RegionList::iterator,bool> x = regions.insert (entry);
-
+
if (!x.second) {
return;
}
-
+
added = true;
- }
+ }
}
}
}
@@ -2632,9 +2634,9 @@ Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions)
/* mark dirty because something has changed even if we didn't
add the region to the region list.
*/
-
+
set_dirty();
-
+
if (added) {
vector<boost::weak_ptr<Region> > v;
@@ -2659,7 +2661,7 @@ Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions)
region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region)));
region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region)));
}
-
+
if (!v.empty()) {
RegionsAdded (v); /* EMIT SIGNAL */
}
@@ -2693,7 +2695,7 @@ Session::remove_region (boost::weak_ptr<Region> weak_region)
bool removed = false;
- {
+ {
Glib::Mutex::Lock lm (region_lock);
if ((i = regions.find (region->id())) != regions.end()) {
@@ -2718,7 +2720,7 @@ Session::find_whole_file_parent (boost::shared_ptr<Region const> child)
{
RegionList::iterator i;
boost::shared_ptr<Region> region;
-
+
Glib::Mutex::Lock lm (region_lock);
for (i = regions.begin(); i != regions.end(); ++i) {
@@ -2731,10 +2733,10 @@ Session::find_whole_file_parent (boost::shared_ptr<Region const> child)
return region;
}
}
- }
+ }
return boost::shared_ptr<Region> ();
-}
+}
void
Session::find_equivalent_playlist_regions (boost::shared_ptr<Region> region, vector<boost::shared_ptr<Region> >& result)
@@ -2747,12 +2749,12 @@ int
Session::destroy_region (boost::shared_ptr<Region> region)
{
vector<boost::shared_ptr<Source> > srcs;
-
+
{
if (region->playlist()) {
region->playlist()->destroy_region (region);
}
-
+
for (uint32_t n = 0; n < region->n_channels(); ++n) {
srcs.push_back (region->source (n));
}
@@ -2764,7 +2766,7 @@ Session::destroy_region (boost::shared_ptr<Region> region)
(*i)->mark_for_remove ();
(*i)->drop_references ();
-
+
cerr << "source was not used by any playlist\n";
}
@@ -2784,12 +2786,12 @@ int
Session::remove_last_capture ()
{
list<boost::shared_ptr<Region> > r;
-
+
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
-
+
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
list<boost::shared_ptr<Region> >& l = (*i)->last_capture_regions();
-
+
if (!l.empty()) {
r.insert (r.end(), l.begin(), l.end());
l.clear ();
@@ -2819,7 +2821,7 @@ Session::add_source (boost::shared_ptr<Source> source)
entry.first = source->id();
entry.second = source;
-
+
{
Glib::Mutex::Lock lm (source_lock);
result = sources.insert (entry);
@@ -2829,14 +2831,14 @@ Session::add_source (boost::shared_ptr<Source> source)
source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source)));
set_dirty();
}
-
+
boost::shared_ptr<AudioFileSource> afs;
if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
if (Config->get_auto_analyse_audio()) {
Analyser::queue_source_for_analysis (source, false);
}
- }
+ }
}
void
@@ -2847,22 +2849,22 @@ Session::remove_source (boost::weak_ptr<Source> src)
if (!source) {
return;
- }
+ }
- {
+ {
Glib::Mutex::Lock lm (source_lock);
if ((i = sources.find (source->id())) != sources.end()) {
sources.erase (i);
- }
+ }
}
-
+
if (!_state_of_the_state & InCleanup) {
-
+
/* save state so we don't end up with a session file
referring to non-existent sources.
*/
-
+
save_state (_current_snapshot_name);
}
}
@@ -2893,8 +2895,8 @@ Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn)
if (afs && afs->path() == path && chn == afs->channel()) {
return afs;
- }
-
+ }
+
}
return boost::shared_ptr<Source>();
}
@@ -2917,14 +2919,14 @@ Session::change_audio_path_by_name (string path, string oldname, string newname,
/* note: we know (or assume) the old path is already valid */
if (destructive) {
-
+
/* destructive file sources have a name of the form:
/path/to/Tnnnn-NAME(%[LR])?.wav
-
+
the task here is to replace NAME with the new name.
*/
-
+
/* find last slash */
string dir;
@@ -2951,16 +2953,16 @@ Session::change_audio_path_by_name (string path, string oldname, string newname,
path += '-';
path += new_legalized;
path += ".wav"; /* XXX gag me with a spoon */
-
+
} else {
-
+
/* non-destructive file sources have a name of the form:
/path/to/NAME-nnnnn(%[LR])?.wav
-
+
the task here is to replace NAME with the new name.
*/
-
+
string dir;
string suffix;
string::size_type slash;
@@ -2982,7 +2984,7 @@ Session::change_audio_path_by_name (string path, string oldname, string newname,
}
suffix = path.substr (dash+1);
-
+
// Suffix is now everything after the dash. Now we need to eliminate
// the nnnnn part, which is done by either finding a '%' or a '.'
@@ -3085,7 +3087,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
if (sys::exists(buf)) {
existing++;
- }
+ }
}
@@ -3112,7 +3114,7 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
spath += '/';
string::size_type pos = foo.find_last_of ('/');
-
+
if (pos == string::npos) {
spath += foo;
} else {
@@ -3141,14 +3143,14 @@ Session::change_midi_path_by_name (string path, string oldname, string newname,
/* note: we know (or assume) the old path is already valid */
if (destructive) {
-
+
/* destructive file sources have a name of the form:
/path/to/Tnnnn-NAME(%[LR])?.wav
-
+
the task here is to replace NAME with the new name.
*/
-
+
/* find last slash */
string dir;
@@ -3175,16 +3177,16 @@ Session::change_midi_path_by_name (string path, string oldname, string newname,
path += '-';
path += new_legalized;
path += ".mid"; /* XXX gag me with a spoon */
-
+
} else {
-
+
/* non-destructive file sources have a name of the form:
/path/to/NAME-nnnnn(%[LR])?.wav
-
+
the task here is to replace NAME with the new name.
*/
-
+
string dir;
string suffix;
string::size_type slash;
@@ -3206,7 +3208,7 @@ Session::change_midi_path_by_name (string path, string oldname, string newname,
}
suffix = path.substr (dash+1);
-
+
// Suffix is now everything after the dash. Now we need to eliminate
// the nnnnn part, which is done by either finding a '%' or a '.'
@@ -3269,7 +3271,7 @@ Session::midi_path_from_name (string name)
for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
SessionDirectory sdir((*i).path);
-
+
sys::path p = sdir.midi_path();
p /= legalized;
@@ -3280,7 +3282,7 @@ Session::midi_path_from_name (string name)
if (sys::exists (buf)) {
existing++;
- }
+ }
}
if (existing == 0) {
@@ -3305,7 +3307,7 @@ Session::midi_path_from_name (string name)
spath += '/';
string::size_type pos = foo.find_last_of ('/');
-
+
if (pos == string::npos) {
spath += foo;
} else {
@@ -3314,12 +3316,12 @@ Session::midi_path_from_name (string name)
return spath;
}
-
+
boost::shared_ptr<MidiSource>
Session::create_midi_source_for_session (MidiDiskstream& ds)
{
string mpath = midi_path_from_name (ds.name());
-
+
return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, *this, mpath, false, frame_rate()));
}
@@ -3351,7 +3353,7 @@ Session::add_playlist (boost::shared_ptr<Playlist> playlist)
return;
}
- {
+ {
Glib::Mutex::Lock lm (playlist_lock);
if (find (playlists.begin(), playlists.end(), playlist) == playlists.end()) {
playlists.insert (playlists.begin(), playlist);
@@ -3368,7 +3370,7 @@ Session::add_playlist (boost::shared_ptr<Playlist> playlist)
void
Session::get_playlists (vector<boost::shared_ptr<Playlist> >& s)
{
- {
+ {
Glib::Mutex::Lock lm (playlist_lock);
for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
s.push_back (*i);
@@ -3395,22 +3397,22 @@ Session::track_playlist (bool inuse, boost::weak_ptr<Playlist> wpl)
return;
}
- {
+ {
Glib::Mutex::Lock lm (playlist_lock);
if (!inuse) {
unused_playlists.insert (pl);
-
+
if ((x = playlists.find (pl)) != playlists.end()) {
playlists.erase (x);
}
-
+
} else {
playlists.insert (pl);
-
+
if ((x = unused_playlists.find (pl)) != unused_playlists.end()) {
unused_playlists.erase (x);
}
@@ -3431,7 +3433,7 @@ Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
return;
}
- {
+ {
Glib::Mutex::Lock lm (playlist_lock);
PlaylistList::iterator i;
@@ -3445,7 +3447,7 @@ Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
if (i != unused_playlists.end()) {
unused_playlists.erase (i);
}
-
+
}
set_dirty();
@@ -3453,7 +3455,7 @@ Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
PlaylistRemoved (playlist); /* EMIT SIGNAL */
}
-void
+void
Session::set_audition (boost::shared_ptr<Region> r)
{
pending_audition_region = r;
@@ -3510,7 +3512,7 @@ Session::remove_empty_sounds ()
vector<string> audio_filenames;
get_files_in_directory (_session_dir->sound_path(), audio_filenames);
-
+
Glib::Mutex::Lock lm (source_lock);
TapeFileMatcher tape_file_matcher;
@@ -3523,7 +3525,7 @@ Session::remove_empty_sounds ()
sys::path audio_file_path (_session_dir->sound_path());
audio_file_path /= *i;
-
+
if (AudioFileSource::is_empty (*this, audio_file_path.to_string())) {
try
@@ -3534,7 +3536,7 @@ Session::remove_empty_sounds ()
}
catch (const sys::filesystem_error& err)
{
- error << err.what() << endmsg;
+ error << err.what() << endmsg;
}
}
}
@@ -3555,7 +3557,7 @@ void
Session::set_all_solo (bool yn)
{
shared_ptr<RouteList> r = routes.reader ();
-
+
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (!(*i)->is_hidden()) {
(*i)->set_solo (yn, this);
@@ -3564,12 +3566,12 @@ Session::set_all_solo (bool yn)
set_dirty();
}
-
+
void
Session::set_all_mute (bool yn)
{
shared_ptr<RouteList> r = routes.reader ();
-
+
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (!(*i)->is_hidden()) {
(*i)->set_mute (yn, this);
@@ -3578,7 +3580,7 @@ Session::set_all_mute (bool yn)
set_dirty();
}
-
+
uint32_t
Session::n_diskstreams () const
{
@@ -3604,7 +3606,7 @@ Session::graph_reordered ()
if (_state_of_the_state & InitialConnecting) {
return;
}
-
+
/* every track/bus asked for this to be handled but it was deferred because
we were connecting. do it now.
*/
@@ -3613,10 +3615,10 @@ Session::graph_reordered ()
resort_routes ();
- /* force all diskstreams to update their capture offset values to
+ /* force all diskstreams to update their capture offset values to
reflect any changes in latencies within the graph.
*/
-
+
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
@@ -3640,7 +3642,7 @@ void
Session::record_enable_change_all (bool yn)
{
shared_ptr<RouteList> r = routes.reader ();
-
+
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
Track* at;
@@ -3648,7 +3650,7 @@ Session::record_enable_change_all (bool yn)
at->set_record_enable (yn, this);
}
}
-
+
/* since we don't keep rec-enable state, don't mark session dirty */
}
@@ -3681,7 +3683,7 @@ Session::remove_processor (Processor* processor)
Send* send;
PortInsert* port_insert;
PluginInsert* plugin_insert;
-
+
if ((port_insert = dynamic_cast<PortInsert *> (processor)) != 0) {
list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
if (x != _port_inserts.end()) {
@@ -3722,7 +3724,7 @@ Session::available_capture_duration ()
sample_bytes_on_disk = 2.0;
break;
- default:
+ default:
/* impossible, but keep some gcc versions happy */
fatal << string_compose (_("programming error: %1"),
X_("illegal native file data format"))
@@ -3735,7 +3737,7 @@ Session::available_capture_duration ()
if (_total_free_4k_blocks * scale > (double) max_frames) {
return max_frames;
}
-
+
return (nframes_t) floor (_total_free_4k_blocks * scale);
}
@@ -3746,7 +3748,7 @@ Session::add_bundle (shared_ptr<Bundle> bundle)
Glib::Mutex::Lock guard (bundle_lock);
_bundles.push_back (bundle);
}
-
+
BundleAdded (bundle); /* EMIT SIGNAL */
set_dirty();
@@ -3760,7 +3762,7 @@ Session::remove_bundle (shared_ptr<Bundle> bundle)
{
Glib::Mutex::Lock guard (bundle_lock);
BundleList::iterator i = find (_bundles.begin(), _bundles.end(), bundle);
-
+
if (i != _bundles.end()) {
_bundles.erase (i);
removed = true;
@@ -3792,7 +3794,7 @@ void
Session::tempo_map_changed (Change ignored)
{
clear_clicks ();
-
+
for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
(*i)->update_after_tempo_map_change ();
}
@@ -3812,7 +3814,7 @@ Session::ensure_buffers (ChanCount howmany)
{
if (current_block_size == 0)
return; // too early? (is this ok?)
-
+
// We need at least 2 MIDI scratch buffers to mix/merge
if (howmany.n_midi() < 2)
howmany.set_midi(2);
@@ -3822,7 +3824,7 @@ Session::ensure_buffers (ChanCount howmany)
_scratch_buffers->ensure_buffers(howmany, current_block_size);
_mix_buffers->ensure_buffers(howmany, current_block_size);
_silent_buffers->ensure_buffers(howmany, current_block_size);
-
+
allocate_pan_automation_buffers (current_block_size, howmany.n_audio(), false);
}
@@ -3836,10 +3838,10 @@ Session::next_insert_id ()
if (!insert_bitset[n]) {
insert_bitset[n] = true;
return n;
-
+
}
}
-
+
/* none available, so resize and try again */
insert_bitset.resize (insert_bitset.size() + 16, false);
@@ -3856,10 +3858,10 @@ Session::next_send_id ()
if (!send_bitset[n]) {
send_bitset[n] = true;
return n;
-
+
}
}
-
+
/* none available, so resize and try again */
send_bitset.resize (send_bitset.size() + 16, false);
@@ -3907,7 +3909,7 @@ Session::named_selection_by_name (string name)
void
Session::add_named_selection (NamedSelection* named_selection)
{
- {
+ {
Glib::Mutex::Lock lm (named_selection_lock);
named_selections.insert (named_selections.begin(), named_selection);
}
@@ -3926,7 +3928,7 @@ Session::remove_named_selection (NamedSelection* named_selection)
{
bool removed = false;
- {
+ {
Glib::Mutex::Lock lm (named_selection_lock);
NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection);
@@ -3958,13 +3960,13 @@ bool
Session::route_name_unique (string n) const
{
shared_ptr<RouteList> r = routes.reader ();
-
+
for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
if ((*i)->name() == n) {
return false;
}
}
-
+
return true;
}
@@ -3992,7 +3994,7 @@ Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, b
}
_pan_automation_buffer = new pan_t*[howmany];
-
+
for (uint32_t i = 0; i < howmany; ++i) {
_pan_automation_buffer[i] = new pan_t[nframes];
}
@@ -4021,7 +4023,7 @@ Session::freeze (InterThreadInfo& itt)
}
int
-Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t len,
+Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t len,
bool overwrite, vector<boost::shared_ptr<Source> >& srcs, InterThreadInfo& itt)
{
int ret = -1;
@@ -4041,9 +4043,9 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
const nframes_t chunk_size = (128 * 1024)/4;
g_atomic_int_set (&processing_prohibited, 1);
-
+
/* call tree *MUST* hold route_lock */
-
+
if ((playlist = track.diskstream()->playlist()) == 0) {
goto out;
}
@@ -4062,17 +4064,17 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
break;
}
}
-
+
if (x == 99999) {
error << string_compose (_("too many bounced versions of playlist \"%1\""), playlist->name()) << endmsg;
goto out;
}
-
+
try {
fsource = boost::dynamic_pointer_cast<AudioFileSource> (
SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
}
-
+
catch (failed_constructor& err) {
error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg;
goto out;
@@ -4082,7 +4084,7 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
}
/* XXX need to flush all redirects */
-
+
position = start;
to_do = len;
@@ -4095,11 +4097,11 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
if (afs)
afs->prepare_for_peakfile_writes ();
}
-
+
while (to_do && !itt.cancel) {
-
+
this_chunk = min (to_do, chunk_size);
-
+
if (track.export_stuff (buffers, start, this_chunk)) {
goto out;
}
@@ -4107,45 +4109,45 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
uint32_t n = 0;
for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
-
+
if (afs) {
if (afs->write (buffers.get_audio(n).data(), this_chunk) != this_chunk) {
goto out;
}
}
}
-
+
start += this_chunk;
to_do -= this_chunk;
-
+
itt.progress = (float) (1.0 - ((double) to_do / len));
}
if (!itt.cancel) {
-
+
time_t now;
struct tm* xnow;
time (&now);
xnow = localtime (&now);
-
+
for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
-
+
if (afs) {
afs->update_header (position, *xnow, now);
afs->flush_header ();
}
}
-
+
/* construct a region to represent the bounced material */
- boost::shared_ptr<Region> aregion = RegionFactory::create (srcs, 0, srcs.front()->length(),
+ boost::shared_ptr<Region> aregion = RegionFactory::create (srcs, 0, srcs.front()->length(),
region_name_from_path (srcs.front()->name(), true));
ret = 0;
}
-
+
out:
if (ret) {
for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
@@ -4161,7 +4163,7 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
} else {
for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
-
+
if (afs)
afs->done_with_peakfile_writes ();
}
@@ -4183,7 +4185,7 @@ Session::get_silent_buffers (ChanCount count)
_silent_buffers->get(*t, i).clear();
}
}
-
+
return *_silent_buffers;
}
@@ -4203,7 +4205,7 @@ Session::get_mix_buffers (ChanCount count)
return *_mix_buffers;
}
-uint32_t
+uint32_t
Session::ntracks () const
{
uint32_t n = 0;
@@ -4218,7 +4220,7 @@ Session::ntracks () const
return n;
}
-uint32_t
+uint32_t
Session::nbusses () const
{
uint32_t n = 0;
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index b4938636a2..a807c5e98b 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -1,6 +1,6 @@
/*
- Copyright (C) 1999-2002 Paul Davis
+ Copyright (C) 1999-2002 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
@@ -94,8 +94,14 @@ Session::use_config_midi_ports ()
set_midi_port ("");
}
+ if (default_midi_clock_port) {
+ set_midi_clock_port (default_midi_clock_port->name());
+ } else {
+ set_midi_clock_port ("");
+ }
+
return 0;
-}
+}
/***********************************************************************
@@ -190,7 +196,7 @@ Session::set_mmc_port (string port_tag)
delete mmc;
}
- mmc = new MIDI::MachineControl (*_mmc_port, 1.0,
+ mmc = new MIDI::MachineControl (*_mmc_port, 1.0,
MMC_CommandSignature,
MMC_ResponseSignature);
@@ -199,29 +205,29 @@ Session::set_mmc_port (string port_tag)
mmc->set_send_device_id (old_send_device_id);
}
- mmc->Play.connect
+ mmc->Play.connect
(mem_fun (*this, &Session::mmc_deferred_play));
- mmc->DeferredPlay.connect
+ mmc->DeferredPlay.connect
(mem_fun (*this, &Session::mmc_deferred_play));
- mmc->Stop.connect
+ mmc->Stop.connect
(mem_fun (*this, &Session::mmc_stop));
- mmc->FastForward.connect
+ mmc->FastForward.connect
(mem_fun (*this, &Session::mmc_fast_forward));
- mmc->Rewind.connect
+ mmc->Rewind.connect
(mem_fun (*this, &Session::mmc_rewind));
- mmc->Pause.connect
+ mmc->Pause.connect
(mem_fun (*this, &Session::mmc_pause));
- mmc->RecordPause.connect
+ mmc->RecordPause.connect
(mem_fun (*this, &Session::mmc_record_pause));
- mmc->RecordStrobe.connect
+ mmc->RecordStrobe.connect
(mem_fun (*this, &Session::mmc_record_strobe));
- mmc->RecordExit.connect
+ mmc->RecordExit.connect
(mem_fun (*this, &Session::mmc_record_exit));
- mmc->Locate.connect
+ mmc->Locate.connect
(mem_fun (*this, &Session::mmc_locate));
- mmc->Step.connect
+ mmc->Step.connect
(mem_fun (*this, &Session::mmc_step));
- mmc->Shuttle.connect
+ mmc->Shuttle.connect
(mem_fun (*this, &Session::mmc_shuttle));
mmc->TrackRecordStatusChange.connect
(mem_fun (*this, &Session::mmc_record_enable));
@@ -232,7 +238,7 @@ Session::set_mmc_port (string port_tag)
_mmc_port->input()->start.connect (mem_fun (*this, &Session::spp_start));
_mmc_port->input()->contineu.connect (mem_fun (*this, &Session::spp_continue));
_mmc_port->input()->stop.connect (mem_fun (*this, &Session::spp_stop));
-
+
Config->set_mmc_port_name (port_tag);
out:
@@ -261,9 +267,9 @@ Session::set_midi_port (string port_tag)
}
_midi_port = port;
-
+
/* XXX need something to forward this to control protocols ? or just
- use the signal below
+ use the signal below
*/
Config->set_midi_port_name (port_tag);
@@ -276,6 +282,52 @@ Session::set_midi_port (string port_tag)
return 0;
}
+int
+Session::set_midi_clock_port (string port_tag)
+{
+ MIDIClock_Slave *ms;
+
+ if (port_tag.length() == 0) {
+
+ if (_slave && ((ms = dynamic_cast<MIDIClock_Slave*> (_slave)) != 0)) {
+ error << _("Ardour is slaved to MIDI Clock - port cannot be reset") << 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<MIDIClock_Slave*> (_slave)) != 0)) {
+ ms->rebind (*port);
+ }
+
+ Config->set_midi_clock_port_name (port_tag);
+
+ _midi_clock_port->input()->start.connect (mem_fun (*this, &Session::midi_clock_start));
+ _midi_clock_port->input()->contineu.connect (mem_fun (*this, &Session::midi_clock_continue));
+ _midi_clock_port->input()->stop.connect (mem_fun (*this, &Session::midi_clock_stop));
+
+ out:
+ MIDIClock_PortChanged(); /* EMIT SIGNAL */
+ change_midi_ports ();
+ set_dirty();
+ return 0;
+}
+
void
Session::set_trace_midi_input (bool yn, MIDI::Port* port)
{
@@ -292,7 +344,7 @@ Session::set_trace_midi_input (bool yn, MIDI::Port* port)
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: ");
@@ -324,7 +376,7 @@ Session::set_trace_midi_output (bool yn, MIDI::Port* port)
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: ");
@@ -357,7 +409,7 @@ Session::get_trace_midi_input(MIDI::Port *port)
return input_parser->tracing();
}
}
-
+
if (_mtc_port) {
if ((input_parser = _mtc_port->input()) != 0) {
return input_parser->tracing();
@@ -389,7 +441,7 @@ Session::get_trace_midi_output(MIDI::Port *port)
return output_parser->tracing();
}
}
-
+
if (_mtc_port) {
if ((output_parser = _mtc_port->output()) != 0) {
return output_parser->tracing();
@@ -414,14 +466,14 @@ Session::setup_midi_control ()
next_quarter_frame_to_send = 0;
/* setup the MMC buffer */
-
+
mmc_buffer[0] = 0xf0; // SysEx
mmc_buffer[1] = 0x7f; // Real Time SysEx ID for MMC
mmc_buffer[2] = (mmc ? mmc->send_device_id() : 0x7f);
mmc_buffer[3] = 0x6; // MCC
/* Set up the qtr frame message */
-
+
mtc_msg[0] = 0xf1;
mtc_msg[2] = 0xf1;
mtc_msg[4] = 0xf1;
@@ -455,6 +507,28 @@ Session::spp_stop (Parser& ignored)
}
void
+Session::midi_clock_start (Parser& ignored)
+{
+ if (Config->get_midi_clock_control() && (Config->get_slave_source() == MIDIClock)) {
+ request_transport_speed (1.0);
+ }
+}
+
+void
+Session::midi_clock_continue (Parser& ignored)
+{
+ midi_clock_start (ignored);
+}
+
+void
+Session::midi_clock_stop (Parser& ignored)
+{
+ if (Config->get_midi_clock_control()) {
+ request_stop ();
+ }
+}
+
+void
Session::mmc_deferred_play (MIDI::MachineControl &mmc)
{
if (Config->get_mmc_control() && (Config->get_slave_source() != MTC)) {
@@ -473,7 +547,7 @@ Session::mmc_record_pause (MIDI::MachineControl &mmc)
void
Session::mmc_record_strobe (MIDI::MachineControl &mmc)
{
- if (!Config->get_mmc_control())
+ if (!Config->get_mmc_control())
return;
/* record strobe does an implicit "Play" command */
@@ -485,11 +559,11 @@ Session::mmc_record_strobe (MIDI::MachineControl &mmc)
its not the same as maybe_enable_record() though, because
that *can* switch to Recording, which we do not want.
*/
-
+
save_state ("", true);
g_atomic_int_set (&_record_status, Enabled);
RecordStateChanged (); /* EMIT SIGNAL */
-
+
request_transport_speed (1.0);
} else {
@@ -545,7 +619,7 @@ Session::mmc_step (MIDI::MachineControl &mmc, int steps)
struct timeval diff = { 0, 0 };
gettimeofday (&now, 0);
-
+
timersub (&now, &last_mmc_step, &diff);
gettimeofday (&now, 0);
@@ -554,10 +628,10 @@ Session::mmc_step (MIDI::MachineControl &mmc, int steps)
if (last_mmc_step.tv_sec != 0 && (diff.tv_usec + (diff.tv_sec * 1000000)) < _engine.usecs_per_cycle()) {
return;
}
-
+
double diff_secs = diff.tv_sec + (diff.tv_usec / 1000000.0);
double cur_speed = (((steps * 0.5) * smpte_frames_per_second()) / diff_secs) / smpte_frames_per_second();
-
+
if (_transport_speed == 0 || cur_speed * _transport_speed < 0) {
/* change direction */
step_speed = cur_speed;
@@ -568,13 +642,13 @@ Session::mmc_step (MIDI::MachineControl &mmc, int steps)
step_speed *= 0.25;
#if 0
- cerr << "delta = " << diff_secs
+ cerr << "delta = " << diff_secs
<< " ct = " << _transport_speed
<< " steps = " << steps
- << " new speed = " << cur_speed
+ << " new speed = " << cur_speed
<< " speed = " << step_speed
<< endl;
-#endif
+#endif
request_transport_speed (step_speed);
last_mmc_step = now;
@@ -617,10 +691,10 @@ Session::mmc_locate (MIDI::MachineControl &mmc, const MIDI::byte* mmc_tc)
smpte.frames = mmc_tc[3];
smpte.rate = smpte_frames_per_second();
smpte.drop = smpte_drop_frames();
-
+
// Also takes smpte offset into account:
smpte_to_sample( smpte, target_frame, true /* use_offset */, false /* use_subframes */ );
-
+
if (target_frame > max_frames) {
target_frame = max_frames;
}
@@ -667,7 +741,7 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled)
RouteList::iterator i;
boost::shared_ptr<RouteList> r = routes.reader();
-
+
for (i = r->begin(); i != r->end(); ++i) {
AudioTrack *at;
@@ -710,7 +784,7 @@ Session::send_full_time_code(nframes_t nframes)
if (_mtc_port == 0 || !session_send_mtc) {
return 0;
}
-
+
// Get smpte time for this transport frame
sample_to_smpte(_transport_frame, smpte, true /* use_offset */, false /* no subframes */);
@@ -763,31 +837,31 @@ Session::send_full_time_code(nframes_t nframes)
*/
int
Session::send_midi_time_code_for_cycle(nframes_t nframes)
-{
+{
assert (next_quarter_frame_to_send >= 0);
assert (next_quarter_frame_to_send <= 7);
-
+
if (_mtc_port == 0 || !session_send_mtc || transmitting_smpte_time.negative
/*|| (next_quarter_frame_to_send < 0)*/ ) {
// cerr << "(MTC) Not sending MTC\n";
return 0;
}
-
+
/* Duration of one quarter frame */
nframes_t quarter_frame_duration = ((long) _frames_per_smpte_frame) >> 2;
-
+
// cerr << "(MTC) TR: " << _transport_frame << " - SF: " << outbound_mtc_smpte_frame
// << " - NQ: " << next_quarter_frame_to_send << " - FD" << quarter_frame_duration << endl;
-
+
// FIXME: this should always be true
//assert((outbound_mtc_smpte_frame + (next_quarter_frame_to_send * quarter_frame_duration))
// > _transport_frame);
-
+
// Send quarter frames for this cycle
while (_transport_frame + nframes > (outbound_mtc_smpte_frame +
(next_quarter_frame_to_send * quarter_frame_duration))) {
-
+
// cerr << "(MTC) Next frame to send: " << next_quarter_frame_to_send << endl;
switch (next_quarter_frame_to_send) {
@@ -815,11 +889,11 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes)
case 7:
mtc_msg[1] = 0x70 | (((mtc_smpte_bits|transmitting_smpte_time.hours) & 0xf0) >> 4);
break;
- }
-
+ }
+
const nframes_t msg_time = (outbound_mtc_smpte_frame
+ (quarter_frame_duration * next_quarter_frame_to_send));
-
+
// This message must fall within this block or something is broken
assert(msg_time >= _transport_frame);
assert(msg_time < _transport_frame + nframes);
@@ -828,7 +902,7 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes)
assert(out_stamp < nframes);
if (_mtc_port->midimsg (mtc_msg, 2, out_stamp)) {
- error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno))
+ error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno))
<< endmsg;
return -1;
}
@@ -840,7 +914,7 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes)
<< ", qfm = " << next_quarter_frame_to_send
<< ", stamp = " << out_stamp
<< ", delta = " << _transport_frame + out_stamp - last_time << endl;*/
-
+
// Increment quarter frame counter
next_quarter_frame_to_send++;
@@ -849,7 +923,7 @@ Session::send_midi_time_code_for_cycle(nframes_t nframes)
next_quarter_frame_to_send = 0;
// Increment smpte time twice
SMPTE::increment( transmitting_smpte_time );
- SMPTE::increment( transmitting_smpte_time );
+ SMPTE::increment( transmitting_smpte_time );
// Re-calculate timing of first quarter frame
//smpte_to_sample( transmitting_smpte_time, outbound_mtc_smpte_frame, true /* use_offset */, false );
outbound_mtc_smpte_frame += 8 * quarter_frame_duration;
@@ -880,7 +954,7 @@ Session::deliver_mmc (MIDI::MachineControl::Command cmd, nframes_t where)
mmc_buffer[nbytes++] = cmd;
// cerr << "delivering MMC, cmd = " << hex << (int) cmd << dec << endl;
-
+
switch (cmd) {
case MachineControl::cmdLocate:
smpte_time_subframes (where, smpte);
@@ -925,7 +999,7 @@ Session::deliver_mmc (MIDI::MachineControl::Command cmd, nframes_t where)
if (_mmc_port->midimsg (mmc_buffer, nbytes, 0)) {
error << string_compose(_("MMC: cannot send command %1%2%3"), &hex, cmd, &dec) << endmsg;
- }
+ }
}
}
@@ -959,7 +1033,7 @@ Session::mmc_step_timeout ()
}
/*---------------------------------------------------------------------------
- MIDI THREAD
+ MIDI THREAD
---------------------------------------------------------------------------*/
int
@@ -995,9 +1069,9 @@ Session::terminate_midi_thread ()
MIDIRequest* request = new MIDIRequest;
void* status;
-
+
request->type = MIDIRequest::Quit;
-
+
midi_requests.write (&request, 1);
poke_midi_thread ();
@@ -1042,14 +1116,14 @@ Session::midi_thread_work ()
memset (&rtparam, 0, sizeof (rtparam));
rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
-
+
if ((x = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
// do we care? not particularly.
- }
+ }
- /* set up the port vector; 4 is the largest possible size for now */
+ /* set up the port vector; 5 is the largest possible size for now */
- ports.assign (4, (MIDI::Port*) 0);
+ ports.assign (5, (MIDI::Port*) 0);
while (1) {
@@ -1078,6 +1152,15 @@ Session::midi_thread_work ()
nfds++;
}
+ cerr << "before handling midi clock port" << endl;
+ if (_midi_clock_port && (_midi_clock_port != _mmc_port || !Config->get_mmc_control()) && _midi_clock_port->selectable() >= 0) {
+ cerr << "inside handling midi clock port" << endl;
+ pfd[nfds].fd = _midi_clock_port->selectable();
+ pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
+ ports[nfds] = _midi_clock_port;
+ nfds++;
+ }
+
/* if we are using MMC control, we obviously have to listen
the relevant port.
*/
@@ -1088,7 +1171,7 @@ Session::midi_thread_work ()
ports[nfds] = _midi_port;
nfds++;
}
-
+
if (!midi_timeouts.empty()) {
timeout = 100; /* 10msecs */
} else {
@@ -1121,7 +1204,7 @@ Session::midi_thread_work ()
if (pfd[0].revents & POLLIN) {
char foo[16];
-
+
// cerr << "MIDI request FIFO ready\n";
fds_ready++;
@@ -1154,13 +1237,13 @@ Session::midi_thread_work ()
// cerr << "rebind\n";
restart = true;
break;
-
+
case MIDIRequest::Quit:
delete request;
pthread_exit_pbd (0);
/*NOTREACHED*/
break;
-
+
default:
break;
}
@@ -1169,7 +1252,7 @@ Session::midi_thread_work ()
delete request;
}
- }
+ }
if (restart) {
continue;
@@ -1182,7 +1265,7 @@ Session::midi_thread_work ()
// error << string_compose(_("Transport: error polling MIDI port %1 (revents =%2%3%4"), p, &hex, pfd[p].revents, &dec) << endmsg;
break;
}
-
+
if (pfd[p].revents & POLLIN) {
fds_ready++;
ports[p]->parse ();
@@ -1190,19 +1273,19 @@ Session::midi_thread_work ()
}
/* timeout driven */
-
+
if (fds_ready < 2 && timeout != -1) {
for (MidiTimeoutList::iterator i = midi_timeouts.begin(); i != midi_timeouts.end(); ) {
-
+
MidiTimeoutList::iterator tmp;
tmp = i;
++tmp;
-
+
if (!(*i)()) {
midi_timeouts.erase (i);
}
-
+
i = tmp;
}
}
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index c86a868e56..61a741d0fb 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1999-2003 Paul Davis
+ Copyright (C) 1999-2003 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
@@ -55,7 +55,7 @@ Session::request_input_change_handling ()
if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
queue_event (ev);
- }
+ }
}
void
@@ -112,7 +112,7 @@ Session::force_locate (nframes_t target_frame, bool with_roll)
void
Session::request_play_loop (bool yn)
{
- Event* ev;
+ Event* ev;
Location *location = _locations.auto_loop_location();
if (location == 0 && yn) {
@@ -135,7 +135,7 @@ void
Session::realtime_stop (bool abort)
{
/* assume that when we start, we'll be moving forwards */
-
+
// FIXME: where should this really be? [DR]
//send_full_time_code();
deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame);
@@ -174,7 +174,7 @@ Session::realtime_stop (bool abort)
disable_record (true);
reset_slave_state ();
-
+
_transport_speed = 0;
if (Config->get_use_video_sync()) {
@@ -221,7 +221,7 @@ Session::butler_transport_work ()
/* don't seek if locate will take care of that in non_realtime_stop() */
if (!(post_transport_work & PostTransportLocate)) {
-
+
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
@@ -239,7 +239,7 @@ Session::butler_transport_work ()
}
}
}
-
+
if (post_transport_work & PostTransportLocate) {
non_realtime_locate ();
}
@@ -263,7 +263,7 @@ Session::butler_transport_work ()
if (post_transport_work & PostTransportAudition) {
non_realtime_set_audition ();
}
-
+
g_atomic_int_dec_and_test (&butler_should_do_transport_work);
}
@@ -293,7 +293,7 @@ Session::non_realtime_overwrite (int on_entry, bool& finished)
}
}
-
+
void
Session::non_realtime_locate ()
{
@@ -317,7 +317,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
saved = false;
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
-
+
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->get_captured_frames () != 0) {
did_record = true;
@@ -326,7 +326,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
}
/* stop and locate are merged here because they share a lot of common stuff */
-
+
time (&xnow);
now = localtime (&xnow);
@@ -340,10 +340,10 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
if (did_record) {
begin_reversible_command ("capture");
-
+
Location* loc = _locations.end_location();
bool change_end = false;
-
+
if (_transport_frame < loc->end()) {
/* stopped recording before current end */
@@ -353,15 +353,15 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
/* first capture for this session, move end back to where we are */
change_end = true;
- }
+ }
} else if (_transport_frame > loc->end()) {
-
+
/* stopped recording after the current end, extend it */
change_end = true;
}
-
+
if (change_end) {
XMLNode &before = loc->get_state();
loc->set_end(_transport_frame);
@@ -376,7 +376,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->transport_stopped (*now, xnow, abort);
}
-
+
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
@@ -384,25 +384,25 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
(*i)->set_pending_declick (0);
}
}
-
+
if (did_record) {
commit_reversible_command ();
- }
-
+ }
+
if (_engine.running()) {
update_latency_compensation (true, abort);
}
- if ((Config->get_slave_source() == None && Config->get_auto_return()) ||
- (post_transport_work & PostTransportLocate) ||
+ if ((Config->get_slave_source() == None && Config->get_auto_return()) ||
+ (post_transport_work & PostTransportLocate) ||
(_requested_return_frame >= 0) ||
synced_to_jack()) {
-
+
if (pending_locate_flush) {
flush_all_inserts ();
}
-
- if (((Config->get_slave_source() == None && Config->get_auto_return()) ||
+
+ if (((Config->get_slave_source() == None && Config->get_auto_return()) ||
synced_to_jack() ||
_requested_return_frame >= 0) &&
!(post_transport_work & PostTransportLocate)) {
@@ -421,12 +421,12 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
if (synced_to_jack() && !play_loop) {
do_locate = true;
}
-
+
if (do_locate) {
// cerr << "non-realtimestop: transport locate to " << _transport_frame << endl;
_engine.transport_locate (_transport_frame);
}
- }
+ }
#ifndef LEAVE_TRANSPORT_UNADJUSTED
}
@@ -475,7 +475,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
RecordStateChanged (); /* emit signal */
#endif
}
-
+
if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
/* capture start has been changed, so save pending state */
save_state ("", true);
@@ -485,7 +485,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
/* always try to get rid of this */
remove_pending_capture_state ();
-
+
/* save the current state of things if appropriate */
if (did_record && !saved) {
@@ -496,11 +496,11 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
DurationChanged (); /* EMIT SIGNAL */
}
- if (post_transport_work & PostTransportStop) {
+ if (post_transport_work & PostTransportStop) {
_play_range = false;
/* do not turn off autoloop on stop */
-
+
}
nframes_t tf = _transport_frame;
@@ -524,7 +524,7 @@ Session::check_declick_out ()
/* this is called after a process() iteration. if PendingDeclickOut was set,
it means that we were waiting to declick the output (which has just been
done) before doing something else. this is where we do that "something else".
-
+
note: called from the audio thread.
*/
@@ -544,11 +544,11 @@ void
Session::set_play_loop (bool yn)
{
/* Called from event-handling context */
-
+
if ((actively_recording() && yn) || _locations.auto_loop_location() == 0) {
return;
}
-
+
set_dirty();
if (yn && Config->get_seamless_loop() && synced_to_jack()) {
@@ -558,12 +558,12 @@ Session::set_play_loop (bool yn)
return;
}
-
+
if ((play_loop = yn)) {
Location *loc;
-
+
if ((loc = _locations.auto_loop_location()) != 0) {
if (Config->get_seamless_loop()) {
@@ -584,9 +584,9 @@ Session::set_play_loop (bool yn)
}
}
}
-
+
/* stick in the loop event */
-
+
Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
merge_event (event);
@@ -614,7 +614,7 @@ Session::set_play_loop (bool yn)
(*i)->set_loop (0);
}
}
-
+
}
}
@@ -689,17 +689,17 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
pending_locate_roll = with_roll;
pending_locate_flush = with_flush;
return;
- }
+ }
}
if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
realtime_stop (false);
- }
+ }
if ( !with_loop || loop_changing) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
-
+
if (with_roll) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
}
@@ -711,13 +711,13 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
/* this is functionally what clear_clicks() does but with a tentative lock */
Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
-
+
if (clickm.locked()) {
-
+
for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
delete *i;
}
-
+
clicks.clear ();
}
}
@@ -752,7 +752,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
/* cancel looped playback if transport pos outside of loop range */
if (play_loop) {
Location* al = _locations.auto_loop_location();
-
+
if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
// cancel looping directly, this is called from event handling context
set_play_loop (false);
@@ -762,7 +762,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
// this is only necessary for seamless looping
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
-
+
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
// tell it we've looped, so it can deal with the record state
@@ -774,7 +774,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
TransportLooped(); // EMIT SIGNAL
}
}
-
+
loop_changing = false;
_send_smpte_update = true;
@@ -808,7 +808,7 @@ Session::set_transport_speed (float speed, bool abort)
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
- (*i)->monitor_input (true);
+ (*i)->monitor_input (true);
}
}
}
@@ -818,7 +818,7 @@ Session::set_transport_speed (float speed, bool abort)
} else {
stop_transport (abort);
}
-
+
} else if (transport_stopped() && speed == 1.0) {
/* we are stopped and we want to start rolling at speed 1 */
@@ -834,7 +834,7 @@ Session::set_transport_speed (float speed, bool abort)
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (Config->get_auto_input() && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
- (*i)->monitor_input (false);
+ (*i)->monitor_input (false);
}
}
}
@@ -868,7 +868,7 @@ Session::set_transport_speed (float speed, bool abort)
if (speed < 0.0f && _transport_frame == 0) {
return;
}
-
+
clear_clicks ();
/* if we are reversing relative to the current speed, or relative to the speed
@@ -878,17 +878,17 @@ Session::set_transport_speed (float speed, bool abort)
if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
}
-
+
_last_transport_speed = _transport_speed;
_transport_speed = speed;
-
+
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
}
}
-
+
if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
schedule_butler_transport_work ();
}
@@ -903,11 +903,11 @@ Session::stop_transport (bool abort)
if (_transport_speed == 0.0f) {
return;
}
-
- if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
- _worst_output_latency > current_block_size)
+
+ if (actively_recording() && !(transport_sub_state & StopPendingCapture) &&
+ _worst_output_latency > current_block_size)
{
-
+
/* we need to capture the audio that has still not yet been received by the system
at the time the stop is requested, so we have to roll past that time.
@@ -915,16 +915,16 @@ Session::stop_transport (bool abort)
block before the actual end. we'll declick in the subsequent block,
and then we'll really be stopped.
*/
-
- Event *ev = new Event (Event::StopOnce, Event::Replace,
+
+ Event *ev = new Event (Event::StopOnce, Event::Replace,
_transport_frame + _worst_output_latency - current_block_size,
0, 0, abort);
-
+
merge_event (ev);
transport_sub_state |= StopPendingCapture;
pending_abort = abort;
return;
- }
+ }
if ((transport_sub_state & PendingDeclickOut) == 0) {
@@ -944,7 +944,7 @@ Session::start_transport ()
_last_roll_location = _transport_frame;
/* if record status is Enabled, move it to Recording. if its
- already Recording, move it to Disabled.
+ already Recording, move it to Disabled.
*/
switch (record_status()) {
@@ -978,7 +978,7 @@ Session::actually_start_transport ()
transport_sub_state |= PendingDeclickIn;
_transport_speed = 1.0;
-
+
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->realtime_set_speed ((*i)->speed(), true);
@@ -1012,7 +1012,7 @@ Session::post_transport ()
if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
start_transport ();
-
+
} else {
transport_sub_state = 0;
}
@@ -1057,7 +1057,7 @@ Session::set_slave_source (SlaveSource src)
// if (src == JACK && Config->get_jack_time_master()) {
// return;
// }
-
+
if (_slave) {
delete _slave;
_slave = 0;
@@ -1071,7 +1071,7 @@ Session::set_slave_source (SlaveSource src)
case None:
stop_transport ();
break;
-
+
case MTC:
if (_mtc_port) {
try {
@@ -1088,15 +1088,33 @@ Session::set_slave_source (SlaveSource src)
}
_desired_transport_speed = _transport_speed;
break;
-
+
+ case MIDIClock:
+ if (_midi_clock_port) {
+ try {
+ _slave = new MIDIClock_Slave (*this, *_midi_clock_port, 24);
+ }
+
+ catch (failed_constructor& err) {
+ return;
+ }
+
+ } else {
+ error << _("No MIDI Clock port defined: MIDI Clock slaving is impossible.") << endmsg;
+ return;
+ }
+ _desired_transport_speed = _transport_speed;
+ break;
+
case JACK:
_slave = new JACK_Slave (_engine.jack());
_desired_transport_speed = _transport_speed;
break;
+
};
Config->set_slave_source (src);
-
+
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
@@ -1174,7 +1192,7 @@ Session::setup_auto_play ()
/* Called from event-processing context */
Event* ev;
-
+
_clear_event_type (Event::RangeStop);
_clear_event_type (Event::RangeLocate);
@@ -1183,48 +1201,48 @@ Session::setup_auto_play ()
}
list<AudioRange>::size_type sz = current_audio_range.size();
-
+
if (sz > 1) {
-
- list<AudioRange>::iterator i = current_audio_range.begin();
+
+ list<AudioRange>::iterator i = current_audio_range.begin();
list<AudioRange>::iterator next;
-
+
while (i != current_audio_range.end()) {
-
+
next = i;
++next;
-
+
/* locating/stopping is subject to delays for declicking.
*/
-
+
nframes_t requested_frame = (*i).end;
-
+
if (requested_frame > current_block_size) {
requested_frame -= current_block_size;
} else {
requested_frame = 0;
}
-
+
if (next == current_audio_range.end()) {
ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
} else {
ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
}
-
+
merge_event (ev);
-
+
i = next;
}
-
+
} else if (sz == 1) {
-
+
ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
merge_event (ev);
-
- }
+
+ }
/* now start rolling at the right place */
-
+
ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
merge_event (ev);
}
@@ -1254,14 +1272,14 @@ Session::engine_halted ()
/* there will be no more calls to process(), so
we'd better clean up for ourselves, right now.
- but first, make sure the butler is out of
+ but first, make sure the butler is out of
the picture.
*/
g_atomic_int_set (&butler_should_do_transport_work, 0);
post_transport_work = PostTransportWork (0);
stop_butler ();
-
+
realtime_stop (false);
non_realtime_stop (false, 0, ignored);
transport_sub_state = 0;
@@ -1282,7 +1300,7 @@ Session::xrun_recovery ()
*/
engine_halted();
- }
+ }
}
void
@@ -1299,15 +1317,15 @@ Session::update_latency_compensation (bool with_stop, bool abort)
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-
+
if (with_stop) {
- (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
+ (*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
(!(post_transport_work & PostTransportLocate) || pending_locate_flush));
}
-
+
nframes_t old_latency = (*i)->signal_latency ();
nframes_t track_latency = (*i)->update_total_latency ();
-
+
if (old_latency != track_latency) {
(*i)->update_port_total_latencies ();
update_jack = true;
@@ -1316,7 +1334,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
if (!(*i)->is_hidden() && ((*i)->active())) {
_worst_track_latency = max (_worst_track_latency, track_latency);
}
- }
+ }
if (update_jack) {
_engine.update_total_latencies ();
@@ -1330,7 +1348,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
/* reflect any changes in latencies into capture offsets
*/
-
+
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc
index f30f568f9d..58443bd005 100644
--- a/libs/ardour/utils.cc
+++ b/libs/ardour/utils.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000-2003 Paul Davis
+ Copyright (C) 2000-2003 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
@@ -50,7 +50,7 @@ using namespace std;
using namespace PBD;
using Glib::ustring;
-ustring
+ustring
legalize_for_path (ustring str)
{
ustring::size_type pos;
@@ -97,7 +97,7 @@ string bump_name_once(std::string name)
char buf[32];
snprintf (buf, sizeof(buf), "%ld", version+1);
-
+
newname = name.substr (0, period+1);
newname += buf;
}
@@ -140,7 +140,7 @@ cmp_nocase (const string& s, const string& s2)
{
string::const_iterator p = s.begin();
string::const_iterator p2 = s2.begin();
-
+
while (p != s.end() && p2 != s2.end()) {
if (toupper(*p) != toupper(*p2)) {
return (toupper(*p) < toupper(*p2)) ? -1 : 1;
@@ -148,7 +148,7 @@ cmp_nocase (const string& s, const string& s2)
++p;
++p2;
}
-
+
return (s2.size() == s.size()) ? 0 : (s.size() < s2.size()) ? -1 : 1;
}
@@ -171,12 +171,12 @@ region_name_from_path (ustring path, bool strip_channels, bool add_channel_suffi
if (strip_channels) {
/* remove any "?R", "?L" or "?[a-z]" channel identifier */
-
+
ustring::size_type len = path.length();
-
- if (len > 3 && (path[len-2] == '%' || path[len-2] == '?' || path[len-2] == '.') &&
+
+ if (len > 3 && (path[len-2] == '%' || path[len-2] == '?' || path[len-2] == '.') &&
(path[len-1] == 'R' || path[len-1] == 'L' || (islower (path[len-1])))) {
-
+
path = path.substr (0, path.length() - 2);
}
}
@@ -184,7 +184,7 @@ region_name_from_path (ustring path, bool strip_channels, bool add_channel_suffi
if (add_channel_suffix) {
path += '%';
-
+
if (total > 2) {
path += (char) ('a' + this_one);
} else {
@@ -193,7 +193,7 @@ region_name_from_path (ustring path, bool strip_channels, bool add_channel_suffi
}
return path;
-}
+}
bool
path_is_paired (ustring path, ustring& pair_base)
@@ -207,7 +207,7 @@ path_is_paired (ustring path, ustring& pair_base)
}
/* remove filename suffixes etc. */
-
+
if ((pos = path.find_last_of ('.')) != string::npos) {
path = path.substr (0, pos);
}
@@ -216,13 +216,13 @@ path_is_paired (ustring path, ustring& pair_base)
/* look for possible channel identifier: "?R", "%R", ".L" etc. */
- if (len > 3 && (path[len-2] == '%' || path[len-2] == '?' || path[len-2] == '.') &&
+ if (len > 3 && (path[len-2] == '%' || path[len-2] == '?' || path[len-2] == '.') &&
(path[len-1] == 'R' || path[len-1] == 'L' || (islower (path[len-1])))) {
-
+
pair_base = path.substr (0, len-2);
return true;
- }
+ }
return false;
}
@@ -253,20 +253,20 @@ path_expand (ustring path)
wordfree (&expansion);
return ret;
-#else
+#else
return path;
#endif
}
#if defined(HAVE_COREAUDIO) || defined(HAVE_AUDIOUNITS)
-string
+string
CFStringRefToStdString(CFStringRef stringRef)
{
- CFIndex size =
- CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef) ,
+ CFIndex size =
+ CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef) ,
kCFStringEncodingUTF8);
char *buf = new char[size];
-
+
std::string result;
if(CFStringGetCString(stringRef, buf, size, kCFStringEncodingUTF8)) {
@@ -285,11 +285,11 @@ compute_equal_power_fades (nframes_t nframes, float* in, float* out)
step = 1.0/nframes;
in[0] = 0.0f;
-
+
for (nframes_t i = 1; i < nframes - 1; ++i) {
in[i] = in[i-1] + step;
}
-
+
in[nframes-1] = 1.0;
const float pan_law_attenuation = -3.0f;
@@ -340,11 +340,15 @@ string_to_slave_source (string str)
if (str == _("Internal")) {
return None;
}
-
+
if (str == _("MTC")) {
return MTC;
}
+ if (str == _("MIDI Clock")) {
+ return MIDIClock;
+ }
+
if (str == _("JACK")) {
return JACK;
}
@@ -363,11 +367,14 @@ slave_source_to_string (SlaveSource src)
case MTC:
return _("MTC");
-
+
+ case MIDIClock:
+ return _("MIDI Clock");
+
default:
case None:
return _("Internal");
-
+
}
}
@@ -449,7 +456,7 @@ meter_hold_to_float (MeterHold hold)
}
}
-AutoState
+AutoState
ARDOUR::string_to_auto_state (std::string str)
{
if (str == X_("Off")) {
@@ -467,7 +474,7 @@ ARDOUR::string_to_auto_state (std::string str)
return Touch;
}
-string
+string
ARDOUR::auto_state_to_string (AutoState as)
{
/* to be used only for XML serialization, no i18n done */
@@ -491,7 +498,7 @@ ARDOUR::auto_state_to_string (AutoState as)
return "";
}
-AutoStyle
+AutoStyle
ARDOUR::string_to_auto_style (std::string str)
{
if (str == X_("Absolute")) {
@@ -505,7 +512,7 @@ ARDOUR::string_to_auto_style (std::string str)
return Trim;
}
-string
+string
ARDOUR::auto_style_to_string (AutoStyle as)
{
/* to be used only for XML serialization, no i18n done */
diff --git a/libs/midi++2/midi++/midnam_patch.h b/libs/midi++2/midi++/midnam_patch.h
index 492eacd897..50c51b317f 100644
--- a/libs/midi++2/midi++/midnam_patch.h
+++ b/libs/midi++2/midi++/midnam_patch.h
@@ -19,22 +19,22 @@ class Patch : public PBD::Stateful
{
public:
typedef std::list<MIDI::Event> PatchMidiCommands;
-
+
Patch() {};
Patch(string a_number, string a_name) : _number(a_number), _name(a_name) {};
~Patch() {};
-
+
const string& name() const { return _name; }
void set_name(const string a_name) { _name = a_name; }
-
+
const string& number() const { return _number; }
void set_number(const string a_number) { _number = a_number; }
-
+
const PatchMidiCommands& patch_midi_commands() const { return _patch_midi_commands; }
-
+
XMLNode& get_state (void);
int set_state (const XMLNode& a_node);
-
+
private:
string _number;
string _name;
@@ -45,19 +45,19 @@ class PatchBank : public PBD::Stateful
{
public:
typedef std::list<Patch> PatchNameList;
-
+
PatchBank() {};
virtual ~PatchBank() {};
PatchBank(string a_name) : _name(a_name) {};
-
+
const string& name() const { return _name; }
- void set_name(const string a_name) { _name = a_name; }
-
+ void set_name(const string a_name) { _name = a_name; }
+
const PatchNameList& patch_name_list() const { return _patch_name_list; }
-
+
XMLNode& get_state (void);
int set_state (const XMLNode& a_node);
-
+
private:
string _name;
PatchNameList _patch_name_list;
@@ -68,29 +68,41 @@ class ChannelNameSet : public PBD::Stateful
public:
typedef std::set<uint8_t> AvailableForChannels;
typedef std::list<PatchBank> PatchBanks;
-
+
ChannelNameSet() {};
virtual ~ChannelNameSet() {};
ChannelNameSet(string a_name) : _name(a_name) {};
-
+
const string& name() const { return _name; }
- void set_name(const string a_name) { _name = a_name; }
-
+ void set_name(const string a_name) { _name = a_name; }
+
const AvailableForChannels& available_for_channels() const { return _available_for_channels; }
const PatchBanks& patch_banks() const { return _patch_banks; }
-
+
XMLNode& get_state (void);
int set_state (const XMLNode& a_node);
-
+
private:
string _name;
AvailableForChannels _available_for_channels;
PatchBanks _patch_banks;
};
+class MIDINameDocument : public PBD::Stateful
+{
+public:
+ MIDINameDocument() {};
+ virtual ~MIDINameDocument() {};
-}
+ XMLNode& get_state (void);
+ int set_state (const XMLNode& a_node);
+
+private:
+ string _author;
+
+};
}
+}
#endif /*MIDNAM_PATCH_H_*/
diff --git a/libs/midi++2/midnam_patch.cc b/libs/midi++2/midnam_patch.cc
index c103237d99..f149f2884b 100644
--- a/libs/midi++2/midnam_patch.cc
+++ b/libs/midi++2/midnam_patch.cc
@@ -7,19 +7,19 @@ namespace MIDI
namespace Name
{
-XMLNode&
+XMLNode&
Patch::get_state (void)
{
XMLNode* node = new XMLNode("Patch");
node->add_property("Number", _number);
node->add_property("Name", _name);
XMLNode* commands = node->add_child("PatchMIDICommands");
- for (PatchMidiCommands::const_iterator event = _patch_midi_commands.begin();
+ for (PatchMidiCommands::const_iterator event = _patch_midi_commands.begin();
event != _patch_midi_commands.end();
++event) {
commands->add_child_copy(*(event->to_xml()));
}
-
+
return *node;
}
@@ -35,22 +35,22 @@ Patch::set_state (const XMLNode& node)
for (XMLNodeList::const_iterator i = events.begin(); i != events.end(); ++i) {
_patch_midi_commands.push_back(*(new Event(*(*i))));
}
-
+
return 0;
}
-XMLNode&
+XMLNode&
PatchBank::get_state (void)
{
XMLNode* node = new XMLNode("PatchBank");
node->add_property("Name", _name);
XMLNode* patch_name_list = node->add_child("PatchNameList");
- for (PatchNameList::iterator patch = _patch_name_list.begin();
+ for (PatchNameList::iterator patch = _patch_name_list.begin();
patch != _patch_name_list.end();
++patch) {
patch_name_list->add_child_nocopy(patch->get_state());
}
-
+
return *node;
}
@@ -67,38 +67,38 @@ PatchBank::set_state (const XMLNode& node)
patch.set_state(*(*i));
_patch_name_list.push_back(patch);
}
-
+
return 0;
}
-XMLNode&
+XMLNode&
ChannelNameSet::get_state (void)
{
XMLNode* node = new XMLNode("ChannelNameSet");
node->add_property("Name", _name);
-
+
XMLNode* available_for_channels = node->add_child("AvailableForChannels");
assert(available_for_channels);
-
+
for (uint8_t channel = 0; channel < 16; ++channel) {
XMLNode* available_channel = available_for_channels->add_child("AvailableChannel");
assert(available_channel);
-
+
available_channel->add_property("Channel", (long) channel);
-
+
if (_available_for_channels.find(channel) != _available_for_channels.end()) {
- available_channel->add_property("Available", "true");
+ available_channel->add_property("Available", "true");
} else {
- available_channel->add_property("Available", "false");
+ available_channel->add_property("Available", "false");
}
}
-
- for (PatchBanks::iterator patch_bank = _patch_banks.begin();
+
+ for (PatchBanks::iterator patch_bank = _patch_banks.begin();
patch_bank != _patch_banks.end();
++patch_bank) {
node->add_child_nocopy(patch_bank->get_state());
}
-
+
return *node;
}
@@ -120,17 +120,28 @@ ChannelNameSet::set_state (const XMLNode& node)
_available_for_channels.insert(atoi((*i)->attribute_value().c_str()));
}
}
-
+
if (node->name() == "PatchBank") {
PatchBank bank;
bank.set_state(*node);
_patch_banks.push_back(bank);
- }
+ }
}
-
+
return 0;
}
+int
+MIDINameDocument::set_state(const XMLNode & a_node)
+{
+}
+
+XMLNode&
+MIDINameDocument::get_state(void)
+{
+}
+
+
} //namespace Name
} //namespace MIDI