* first implementation of MIDI Clock Slave support

git-svn-id: svn://localhost/ardour2/branches/3.0@3652 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Hans Baier 2008-08-04 22:37:24 +00:00
parent 44fd104ada
commit ed990de604
20 changed files with 1169 additions and 903 deletions

View File

@ -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'/>

View File

@ -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 ();

View File

@ -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);

View File

@ -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
@ -67,6 +67,12 @@ ARDOUR_UI::toggle_use_mmc ()
ActionManager::toggle_config_state ("options", "UseMMC", &Configuration::set_mmc_control, &Configuration::get_mmc_control);
}
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 ()
{
@ -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
}

View File

@ -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()) {
@ -815,6 +842,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)
{
@ -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);

View File

@ -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 ();

View File

@ -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

View File

@ -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__ */

View File

@ -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)

View File

@ -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;
};

View File

@ -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; }

View File

@ -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
};

View File

@ -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);
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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;
@ -454,6 +506,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)
{
@ -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;
}
}

View File

@ -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) {

View File

@ -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 */

View File

@ -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_*/

View File

@ -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