X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession_state.cc;h=8a49636941e5c4327cff48bae548caf58019c31c;hb=41d8747e9d4bbf10f848d907b879ba2211c89b8e;hp=6f2ad965b41e9e43502d98f3736be2d4917cb243;hpb=3c3a204ad32cfa167efa193b472a7b8103734613;p=ardour.git diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 6f2ad965b4..8a49636941 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -81,6 +81,10 @@ #include #include #include +#include +#include + +#include #include "i18n.h" #include @@ -97,10 +101,11 @@ Session::first_stage_init (string fullpath, string snapshot_name) } char buf[PATH_MAX+1]; - if (!realpath(fullpath.c_str(), buf) && (errno != ENOENT)) { + if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) { error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg; throw failed_constructor(); } + _path = string(buf); if (_path[_path.length()-1] != '/') { @@ -112,7 +117,6 @@ Session::first_stage_init (string fullpath, string snapshot_name) */ _name = _current_snapshot_name = snapshot_name; - setup_raid_path (_path); _current_frame_rate = _engine.frame_rate (); _tempo_map = new TempoMap (_current_frame_rate); @@ -130,16 +134,8 @@ Session::first_stage_init (string fullpath, string snapshot_name) start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart))); _end_location_is_free = true; g_atomic_int_set (&_record_status, Disabled); - auto_play = false; - punch_in = false; - punch_out = false; - auto_loop = false; - seamless_loop = false; loop_changing = false; - auto_input = true; - crossfades_active = false; - all_safe = false; - auto_return = false; + play_loop = false; _last_roll_location = 0; _last_record_location = 0; pending_locate_frame = 0; @@ -152,8 +148,6 @@ Session::first_stage_init (string fullpath, string snapshot_name) outbound_mtc_smpte_frame = 0; next_quarter_frame_to_send = -1; current_block_size = 0; - _solo_latched = true; - _solo_model = InverseMute; solo_update_disabled = false; currently_soloing = false; _have_captured = false; @@ -162,12 +156,11 @@ Session::first_stage_init (string fullpath, string snapshot_name) _worst_track_latency = 0; _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading); _slave = 0; - _slave_type = None; butler_mixdown_buffer = 0; butler_gain_buffer = 0; - mmc_control = false; - midi_control = true; mmc = 0; + session_send_mmc = false; + session_send_mtc = false; post_transport_work = PostTransportWork (0); g_atomic_int_set (&butler_should_do_transport_work, 0); g_atomic_int_set (&butler_active, 0); @@ -175,76 +168,62 @@ Session::first_stage_init (string fullpath, string snapshot_name) g_atomic_int_set (&_capture_load, 100); g_atomic_int_set (&_playback_load_min, 100); g_atomic_int_set (&_capture_load_min, 100); - pending_audition_region = 0; - _edit_mode = Slide; - pending_edit_mode = _edit_mode; _play_range = false; - input_auto_connect = AutoConnectOption (0); - output_auto_connect = AutoConnectOption (0); waiting_to_start = false; _exporting = false; _gain_automation_buffer = 0; _pan_automation_buffer = 0; _npan_buffers = 0; pending_abort = false; - layer_model = MoveAddHigher; - xfade_model = ShortCrossfade; destructive_index = 0; + current_trans = 0; + first_file_data_format_reset = true; + first_file_header_format_reset = true; AudioDiskstream::allocate_working_buffers(); /* default short fade = 15ms */ - Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0)); + Crossfade::set_short_xfade_length ((nframes_t) floor (Config->get_short_xfade_seconds() * frame_rate())); DestructiveFileSource::setup_standard_crossfades (frame_rate()); last_mmc_step.tv_sec = 0; last_mmc_step.tv_usec = 0; step_speed = 0.0; - preroll.type = AnyTime::Frames; - preroll.frames = 0; - postroll.type = AnyTime::Frames; - postroll.frames = 0; - /* click sounds are unset by default, which causes us to internal waveforms for clicks. */ - _clicking = false; - click_requested = false; click_data = 0; click_emphasis_data = 0; click_length = 0; click_emphasis_length = 0; + _clicking = false; process_function = &Session::process_with_events; + if (Config->get_use_video_sync()) { + waiting_for_sync_offset = true; + } else { + waiting_for_sync_offset = false; + } + + _current_frame_rate = 48000; + _base_frame_rate = 48000; + last_smpte_when = 0; _smpte_offset = 0; _smpte_offset_negative = true; last_smpte_valid = false; + sync_time_vars (); + last_rr_session_dir = session_dirs.begin(); refresh_disk_space (); // set_default_fade (0.2, 5.0); /* steepness, millisecs */ - /* default configuration */ - - do_not_record_plugins = false; - over_length_short = 2; - over_length_long = 10; - send_midi_timecode = false; - send_midi_machine_control = false; - shuttle_speed_factor = 1.0; - shuttle_speed_threshold = 5; - rf_speed = 2.0; - _meter_hold = 100; // XXX unknown units: number of calls to meter::set() - _meter_falloff = 1.5f; // XXX unknown units: refresh_rate - max_level = 0; - min_level = 0; - /* slave stuff */ average_slave_delta = 1800; @@ -252,24 +231,19 @@ Session::first_stage_init (string fullpath, string snapshot_name) delta_accumulator_cnt = 0; slave_state = Stopped; - /* default SMPTE type is 30 FPS, non-drop */ - - set_smpte_type (30.0, false); - _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered)); /* These are all static "per-class" signals */ - Region::CheckNewRegion.connect (mem_fun (*this, &Session::add_region)); - AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source)); + RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region)); + SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source)); Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist)); Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect)); NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection)); Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve)); AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list)); - Controllable::Created.connect (mem_fun (*this, &Session::add_controllable)); - Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable)); + Controllable::Destroyed.connect (mem_fun (*this, &Session::remove_controllable)); IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers)); @@ -300,10 +274,14 @@ Session::second_stage_init (bool new_session) return -1; } + // set_state() will call setup_raid_path(), but if it's a new session we need + // to call setup_raid_path() here. if (state_tree) { if (set_state (*state_tree->root())) { return -1; } + } else { + setup_raid_path(_path); } /* we can't save till after ::when_engine_running() is called, @@ -348,7 +326,6 @@ Session::second_stage_init (bool new_session) _end_location_is_free = false; } - restore_history(_current_snapshot_name); return 0; } @@ -365,14 +342,6 @@ Session::raid_path () const return path.substr (0, path.length() - 1); // drop final colon } -void -Session::set_raid_path (string path) -{ - /* public-access to setup_raid_path() */ - - setup_raid_path (path); -} - void Session::setup_raid_path (string path) { @@ -413,16 +382,7 @@ Session::setup_raid_path (string path) if (fspath[fspath.length()-1] != '/') { fspath += '/'; } - fspath += sound_dir_name; - fspath += ':'; - - /* tape dir */ - - fspath += sp.path; - if (fspath[fspath.length()-1] != '/') { - fspath += '/'; - } - fspath += tape_dir_name; + fspath += sound_dir (false); AudioFileSource::set_search_path (fspath); @@ -443,16 +403,7 @@ Session::setup_raid_path (string path) if (fspath[fspath.length()-1] != '/') { fspath += '/'; } - fspath += sound_dir_name; - fspath += ':'; - - /* add tape dir to file search path */ - - fspath += sp.path; - if (fspath[fspath.length()-1] != '/') { - fspath += '/'; - } - fspath += tape_dir_name; + fspath += sound_dir (false); fspath += ':'; remaining = remaining.substr (colon+1); @@ -468,15 +419,9 @@ Session::setup_raid_path (string path) if (fspath[fspath.length()-1] != '/') { fspath += '/'; } - fspath += sound_dir_name; + fspath += sound_dir (false); fspath += ':'; - fspath += sp.path; - if (fspath[fspath.length()-1] != '/') { - fspath += '/'; - } - fspath += tape_dir_name; - session_dirs.push_back (sp); } @@ -490,126 +435,94 @@ Session::setup_raid_path (string path) } int -Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length) +Session::create (bool& new_session, string* mix_template, nframes_t initial_length) { string dir; - - if (mkdir (_path.c_str(), 0755) < 0) { - if (errno == EEXIST) { - new_session = false; - } else { - error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg; - return -1; - } - } else { - new_session = true; + + if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) { + error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg; + return -1; } dir = peak_dir (); - if (mkdir (dir.c_str(), 0755) < 0) { - if (errno != EEXIST) { - error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; - return -1; - } + if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { + error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; + return -1; } dir = sound_dir (); - if (mkdir (dir.c_str(), 0755) < 0) { - if (errno != EEXIST) { - error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; - return -1; - } - } - - dir = tape_dir (); - - if (mkdir (dir.c_str(), 0755) < 0) { - if (errno != EEXIST) { - error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; - return -1; - } + if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { + error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; + return -1; } dir = dead_sound_dir (); - if (mkdir (dir.c_str(), 0755) < 0) { - if (errno != EEXIST) { - error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; - return -1; - } + if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { + error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; + return -1; } dir = automation_dir (); - if (mkdir (dir.c_str(), 0755) < 0) { - if (errno != EEXIST) { - error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; - return -1; - } + if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { + error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg; + return -1; } - + /* check new_session so we don't overwrite an existing one */ - + if (mix_template) { - if (new_session){ - std::string in_path = *mix_template; + std::string in_path = *mix_template; + + ifstream in(in_path.c_str()); + + if (in){ + string out_path = _path; + out_path += _name; + out_path += _statefile_suffix; + + ofstream out(out_path.c_str()); + + if (out){ + out << in.rdbuf(); + + // okay, session is set up. Treat like normal saved + // session from now on. + + new_session = false; + return 0; - ifstream in(in_path.c_str()); - - if (in){ - string out_path = _path; - out_path += _name; - out_path += _statefile_suffix; - - ofstream out(out_path.c_str()); - - if (out){ - out << in.rdbuf(); - - // okay, session is set up. Treat like normal saved - // session from now on. - - new_session = false; - return 0; - - } else { - error << string_compose (_("Could not open %1 for writing mix template"), out_path) - << endmsg; - return -1; - } - } else { - error << string_compose (_("Could not open mix template %1 for reading"), in_path) - << endmsg; + error << string_compose (_("Could not open %1 for writing mix template"), out_path) + << endmsg; return -1; } - - + } else { - warning << _("Session already exists. Not overwriting") << endmsg; + error << string_compose (_("Could not open mix template %1 for reading"), in_path) + << endmsg; return -1; } + } - if (new_session) { + /* set initial start + end point */ - /* set initial start + end point */ + start_location->set_end (0); + _locations.add (start_location); - start_location->set_end (0); - _locations.add (start_location); + end_location->set_end (initial_length); + _locations.add (end_location); - end_location->set_end (initial_length); - _locations.add (end_location); - - _state_of_the_state = Clean; + _state_of_the_state = Clean; - if (save_state (_current_snapshot_name)) { - save_history (_current_snapshot_name); - return -1; - } + if (save_state (_current_snapshot_name)) { + save_history (_current_snapshot_name); + return -1; } return 0; @@ -693,6 +606,8 @@ Session::save_state (string snapshot_name, bool pending) } + cerr << "actually writing state\n"; + if (!tree.write (xml_path)) { error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg; @@ -799,227 +714,9 @@ Session::load_options (const XMLNode& node) { XMLNode* child; XMLProperty* prop; - bool have_fade_msecs = false; - bool have_fade_steepness = false; - float fade_msecs = 0; - float fade_steepness = 0; - SlaveSource slave_src = None; - int x; LocaleGuard lg (X_("POSIX")); - - if ((child = find_named_node (node, "input-auto-connect")) != 0) { - if ((prop = child->property ("val")) != 0) { - sscanf (prop->value().c_str(), "%x", &x); - input_auto_connect = AutoConnectOption (x); - } - } - if ((child = find_named_node (node, "output-auto-connect")) != 0) { - if ((prop = child->property ("val")) != 0) { - sscanf (prop->value().c_str(), "%x", &x); - output_auto_connect = AutoConnectOption (x); - } - } - - if ((child = find_named_node (node, "slave")) != 0) { - if ((prop = child->property ("type")) != 0) { - if (prop->value() == "none") { - slave_src = None; - } else if (prop->value() == "mtc") { - slave_src = MTC; - } else if (prop->value() == "jack") { - slave_src = JACK; - } - set_slave_source (slave_src, 0); - } - } - - /* we cannot set edit mode if we are loading a session, - because it might destroy the playlist's positioning - */ - - if ((child = find_named_node (node, "edit-mode")) != 0) { - if ((prop = child->property ("val")) != 0) { - if (prop->value() == "slide") { - pending_edit_mode = Slide; - } else if (prop->value() == "splice") { - pending_edit_mode = Splice; - } - } - } - - if ((child = find_named_node (node, "send-midi-timecode")) != 0) { - if ((prop = child->property ("val")) != 0) { - bool x = (prop->value() == "yes"); - send_mtc = !x; /* force change in value */ - set_send_mtc (x); - } - } - if ((child = find_named_node (node, "send-midi-machine-control")) != 0) { - if ((prop = child->property ("val")) != 0) { - bool x = (prop->value() == "yes"); - send_mmc = !x; /* force change in value */ - set_send_mmc (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "max-level")) != 0) { - if ((prop = child->property ("val")) != 0) { - max_level = atoi (prop->value().c_str()); - } - } - if ((child = find_named_node (node, "min-level")) != 0) { - if ((prop = child->property ("val")) != 0) { - min_level = atoi (prop->value().c_str()); - } - } - if ((child = find_named_node (node, "meter-hold")) != 0) { - if ((prop = child->property ("val")) != 0) { - _meter_hold = atof (prop->value().c_str()); - } - } - if ((child = find_named_node (node, "meter-falloff")) != 0) { - if ((prop = child->property ("val")) != 0) { - _meter_falloff = atof (prop->value().c_str()); - } - } - if ((child = find_named_node (node, "long-over-length")) != 0) { - if ((prop = child->property ("val")) != 0) { - over_length_long = atoi (prop->value().c_str()); - } - } - if ((child = find_named_node (node, "short-over-length")) != 0) { - if ((prop = child->property ("val")) != 0) { - over_length_short = atoi (prop->value().c_str()); - } - } - if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) { - if ((prop = child->property ("val")) != 0) { - shuttle_speed_factor = atof (prop->value().c_str()); - } - } - if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) { - if ((prop = child->property ("val")) != 0) { - shuttle_speed_threshold = atof (prop->value().c_str()); - } - } - if ((child = find_named_node (node, "rf-speed")) != 0) { - if ((prop = child->property ("val")) != 0) { - rf_speed = atof (prop->value().c_str()); - } - } - if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames ); - } - } - if ((child = find_named_node (node, "smpte-drop-frames")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") ); - } - } - if ((child = find_named_node (node, "smpte-offset")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_smpte_offset( atoi (prop->value().c_str()) ); - } - } - if ((child = find_named_node (node, "smpte-offset-negative")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_smpte_offset_negative( (prop->value() == "yes") ); - } - } - if ((child = find_named_node (node, "click-sound")) != 0) { - if ((prop = child->property ("val")) != 0) { - click_sound = prop->value(); - } - } - if ((child = find_named_node (node, "click-emphasis-sound")) != 0) { - if ((prop = child->property ("val")) != 0) { - click_emphasis_sound = prop->value(); - } - } - - if ((child = find_named_node (node, "solo-model")) != 0) { - if ((prop = child->property ("val")) != 0) { - if (prop->value() == "SoloBus") - _solo_model = SoloBus; - else - _solo_model = InverseMute; - } - } - - /* BOOLEAN OPTIONS */ - - if ((child = find_named_node (node, "auto-play")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_auto_play (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "auto-input")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_auto_input (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "seamless-loop")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_seamless_loop (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "punch-in")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_punch_in (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "punch-out")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_punch_out (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "auto-return")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_auto_return (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "send-mtc")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_send_mtc (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "mmc-control")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_mmc_control (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "midi-control")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_midi_control (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "midi-feedback")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_midi_feedback (prop->value() == "yes"); - } - } - // Legacy support for - if ((child = find_named_node (node, "recording-plugins")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_do_not_record_plugins (prop->value() == "no"); - } - } - if ((child = find_named_node (node, "do-not-record-plugins")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_do_not_record_plugins (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "crossfades-active")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_crossfades_active (prop->value() == "yes"); - } - } - if ((child = find_named_node (node, "audible-click")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_clicking (prop->value() == "yes"); - } - } + Config->set_variables (node, ConfigVariableBase::Session); if ((child = find_named_node (node, "end-marker-is-free")) != 0) { if ((prop = child->property ("val")) != 0) { @@ -1027,239 +724,30 @@ Session::load_options (const XMLNode& node) } } - if ((child = find_named_node (node, "layer-model")) != 0) { - if ((prop = child->property ("val")) != 0) { - if (prop->value() == X_("LaterHigher")) { - set_layer_model (LaterHigher); - } else if (prop->value() == X_("AddHigher")) { - set_layer_model (AddHigher); - } else { - set_layer_model (MoveAddHigher); - } - } - } - - if ((child = find_named_node (node, "xfade-model")) != 0) { - if ((prop = child->property ("val")) != 0) { - if (prop->value() == X_("Short")) { - set_xfade_model (ShortCrossfade); - } else { - set_xfade_model (FullCrossfade); - } - } - } - - if ((child = find_named_node (node, "short-xfade-length")) != 0) { - if ((prop = child->property ("val")) != 0) { - /* value is stored as a fractional seconds */ - float secs = atof (prop->value().c_str()); - Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate())); - } - } - - if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) { - if ((prop = child->property ("val")) != 0) { - crossfades_active = (prop->value() == "yes"); - } - } - - /* TIED OPTIONS */ - - if ((child = find_named_node (node, "default-fade-steepness")) != 0) { - if ((prop = child->property ("val")) != 0) { - fade_steepness = atof (prop->value().c_str()); - have_fade_steepness = true; - } - } - if ((child = find_named_node (node, "default-fade-msec")) != 0) { - if ((prop = child->property ("val")) != 0) { - fade_msecs = atof (prop->value().c_str()); - have_fade_msecs = true; - } - } + return 0; +} - if (have_fade_steepness || have_fade_msecs) { - // set_default_fade (fade_steepness, fade_msecs); - } +bool +Session::save_config_options_predicate (ConfigVariableBase::Owner owner) const +{ + const ConfigVariableBase::Owner modified_by_session_or_user = (ConfigVariableBase::Owner) + (ConfigVariableBase::Session|ConfigVariableBase::Interface); - return 0; + return owner & modified_by_session_or_user; } XMLNode& Session::get_options () const { - XMLNode* opthead; XMLNode* child; - char buf[32]; LocaleGuard lg (X_("POSIX")); - opthead = new XMLNode ("Options"); - - SlaveSource src = slave_source (); - string src_string; - switch (src) { - case None: - src_string = "none"; - break; - case MTC: - src_string = "mtc"; - break; - case JACK: - src_string = "jack"; - break; - } - child = opthead->add_child ("slave"); - child->add_property ("type", src_string); - - child = opthead->add_child ("send-midi-timecode"); - child->add_property ("val", send_midi_timecode?"yes":"no"); - - child = opthead->add_child ("send-midi-machine-control"); - child->add_property ("val", send_midi_machine_control?"yes":"no"); - - snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect); - child = opthead->add_child ("input-auto-connect"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect); - child = opthead->add_child ("output-auto-connect"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%d", max_level); - child = opthead->add_child ("max-level"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%d", min_level); - child = opthead->add_child ("min-level"); - child->add_property ("val", buf); + XMLNode& option_root = Config->get_variables (mem_fun (*this, &Session::save_config_options_predicate)); - snprintf (buf, sizeof(buf)-1, "%f", _meter_hold); - child = opthead->add_child ("meter-hold"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff); - child = opthead->add_child ("meter-falloff"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%u", over_length_long); - child = opthead->add_child ("long-over-length"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%u", over_length_short); - child = opthead->add_child ("short-over-length"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor); - child = opthead->add_child ("shuttle-speed-factor"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold); - child = opthead->add_child ("shuttle-speed-threshold"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%f", rf_speed); - child = opthead->add_child ("rf-speed"); - child->add_property ("val", buf); - - snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second); - child = opthead->add_child ("smpte-frames-per-second"); - child->add_property ("val", buf); - - child = opthead->add_child ("smpte-drop-frames"); - child->add_property ("val", smpte_drop_frames ? "yes" : "no"); - - snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ()); - child = opthead->add_child ("smpte-offset"); - child->add_property ("val", buf); - - child = opthead->add_child ("smpte-offset-negative"); - child->add_property ("val", smpte_offset_negative () ? "yes" : "no"); - - child = opthead->add_child ("edit-mode"); - switch (_edit_mode) { - case Splice: - child->add_property ("val", "splice"); - break; - - case Slide: - child->add_property ("val", "slide"); - break; - } - - child = opthead->add_child ("auto-play"); - child->add_property ("val", get_auto_play () ? "yes" : "no"); - child = opthead->add_child ("auto-input"); - child->add_property ("val", get_auto_input () ? "yes" : "no"); - child = opthead->add_child ("seamless-loop"); - child->add_property ("val", get_seamless_loop () ? "yes" : "no"); - child = opthead->add_child ("punch-in"); - child->add_property ("val", get_punch_in () ? "yes" : "no"); - child = opthead->add_child ("punch-out"); - child->add_property ("val", get_punch_out () ? "yes" : "no"); - child = opthead->add_child ("all-safe"); - child->add_property ("val", get_all_safe () ? "yes" : "no"); - child = opthead->add_child ("auto-return"); - child->add_property ("val", get_auto_return () ? "yes" : "no"); - child = opthead->add_child ("mmc-control"); - child->add_property ("val", get_mmc_control () ? "yes" : "no"); - child = opthead->add_child ("midi-control"); - child->add_property ("val", get_midi_control () ? "yes" : "no"); - child = opthead->add_child ("midi-feedback"); - child->add_property ("val", get_midi_feedback () ? "yes" : "no"); - child = opthead->add_child ("do-not-record-plugins"); - child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no"); - child = opthead->add_child ("auto-crossfade"); - child->add_property ("val", get_crossfades_active () ? "yes" : "no"); - child = opthead->add_child ("audible-click"); - child->add_property ("val", get_clicking () ? "yes" : "no"); - child = opthead->add_child ("end-marker-is-free"); + child = option_root.add_child ("end-marker-is-free"); child->add_property ("val", _end_location_is_free ? "yes" : "no"); - if (click_sound.length()) { - child = opthead->add_child ("click-sound"); - child->add_property ("val", click_sound); - } - - if (click_emphasis_sound.length()) { - child = opthead->add_child ("click-emphasis-sound"); - child->add_property ("val", click_emphasis_sound); - } - - child = opthead->add_child ("solo-model"); - child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute"); - - child = opthead->add_child ("layer-model"); - switch (layer_model) { - case LaterHigher: - child->add_property ("val", X_("LaterHigher")); - break; - case MoveAddHigher: - child->add_property ("val", X_("MoveAddHigher")); - break; - case AddHigher: - child->add_property ("val", X_("AddHigher")); - break; - } - - child = opthead->add_child ("xfade-model"); - switch (xfade_model) { - case FullCrossfade: - child->add_property ("val", X_("Full")); - break; - case ShortCrossfade: - child->add_property ("val", X_("Short")); - } - - child = opthead->add_child ("short-xfade-length"); - /* store as fractions of a second */ - snprintf (buf, sizeof(buf)-1, "%f", - (float) Crossfade::short_xfade_length() / frame_rate()); - child->add_property ("val", buf); - - child = opthead->add_child ("full-xfades-unmuted"); - child->add_property ("val", crossfades_active ? "yes" : "no"); - - return *opthead; + return option_root; } XMLNode& @@ -1348,10 +836,10 @@ Session::state(bool full_state) /* Don't save information about AudioFileSources that are empty */ - AudioFileSource* fs; + boost::shared_ptr fs; - if ((fs = dynamic_cast (siter->second)) != 0) { - DestructiveFileSource* dfs = dynamic_cast (fs); + if ((fs = boost::dynamic_pointer_cast (siter->second)) != 0) { + boost::shared_ptr dfs = boost::dynamic_pointer_cast (fs); /* destructive file sources are OK if they are empty, because we will re-use them every time. @@ -1479,6 +967,8 @@ Session::state(bool full_state) node->add_child_nocopy (_tempo_map->get_state()); + node->add_child_nocopy (get_control_protocol_state()); + if (_extra_xml) { node->add_child_copy (*_extra_xml); } @@ -1486,6 +976,25 @@ Session::state(bool full_state) return *node; } +XMLNode& +Session::get_control_protocol_state () +{ + ControlProtocolManager& cpm (ControlProtocolManager::instance()); + XMLNode* node = new XMLNode (X_("ControlProtocols")); + + cpm.foreach_known_protocol (bind (mem_fun (*this, &Session::add_control_protocol), node)); + + return *node; +} + +void +Session::add_control_protocol (const ControlProtocolInfo* const cpi, XMLNode* node) +{ + if (cpi->protocol) { + node->add_child_nocopy (cpi->protocol->get_state()); + } +} + int Session::set_state (const XMLNode& node) { @@ -1501,12 +1010,12 @@ Session::set_state (const XMLNode& node) return -1; } - StateManager::prohibit_save (); - if ((prop = node.property ("name")) != 0) { _name = prop->value (); } + setup_raid_path(_path); + if ((prop = node.property (X_("id-counter"))) != 0) { uint64_t x; sscanf (prop->value().c_str(), "%" PRIu64, &x); @@ -1530,7 +1039,7 @@ Session::set_state (const XMLNode& node) MIDI Path extra - Options + Options/Config Sources AudioRegions AudioDiskstreams @@ -1540,26 +1049,22 @@ Session::set_state (const XMLNode& node) EditGroups MixGroups Click + ControlProtocols */ if (use_config_midi_ports ()) { } - if ((child = find_named_node (node, "Path")) != 0) { - /* XXX this XML content stuff horrible API design */ - string raid_path = _path + ':' + child->children().front()->content(); - setup_raid_path (raid_path); - } else { - /* the path is already set */ - } - if ((child = find_named_node (node, "extra")) != 0) { _extra_xml = new XMLNode (*child); } - if ((child = find_named_node (node, "Options")) == 0) { + if (((child = find_named_node (node, "Options")) != 0)) { /* old style */ + load_options (*child); + } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */ + load_options (*child); + } else { error << _("Session: XML state has no options section") << endmsg; - } else if (load_options (*child)) { } if ((child = find_named_node (node, "Sources")) == 0) { @@ -1640,8 +1145,6 @@ Session::set_state (const XMLNode& node) start_location = location; } - _locations.save_state (_("initial state")); - if ((child = find_named_node (node, "EditGroups")) == 0) { error << _("Session: XML state has no edit groups section") << endmsg; goto out; @@ -1676,9 +1179,9 @@ Session::set_state (const XMLNode& node) _click_io->set_state (*child); } - /* OK, now we can set edit mode */ - - set_edit_mode (pending_edit_mode); + if ((child = find_named_node (node, "ControlProtocols")) != 0) { + ControlProtocolManager::instance().set_protocol_states (*child); + } /* here beginneth the second phase ... */ @@ -1686,8 +1189,6 @@ Session::set_state (const XMLNode& node) _state_of_the_state = Clean; - StateManager::allow_save (_("initial state"), true); - if (state_was_pending) { save_state (_current_snapshot_name); remove_pending_capture_state (); @@ -1697,8 +1198,6 @@ Session::set_state (const XMLNode& node) return 0; out: - /* we failed, re-enable state saving but don't actually save internal state */ - StateManager::allow_save (X_("ignored"), false); return ret; } @@ -1751,7 +1250,7 @@ Session::load_regions (const XMLNode& node) { XMLNodeList nlist; XMLNodeConstIterator niter; - AudioRegion* region; + boost::shared_ptr region; nlist = node.children(); @@ -1762,32 +1261,38 @@ Session::load_regions (const XMLNode& node) error << _("Session: cannot create Region from XML description.") << endmsg; } } + return 0; } -AudioRegion * +boost::shared_ptr Session::XMLRegionFactory (const XMLNode& node, bool full) { const XMLProperty* prop; - Source* source; - AudioSource* as; - AudioRegion::SourceList sources; + boost::shared_ptr source; + boost::shared_ptr as; + SourceList sources; uint32_t nchans = 1; char buf[128]; if (node.name() != X_("Region")) { - return 0; + return boost::shared_ptr(); } if ((prop = node.property (X_("channels"))) != 0) { nchans = atoi (prop->value().c_str()); } + + if ((prop = node.property ("name")) == 0) { + cerr << "no name for this region\n"; + abort (); + } if ((prop = node.property (X_("source-0"))) == 0) { if ((prop = node.property ("source")) == 0) { error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg; - return 0; + return boost::shared_ptr(); } } @@ -1795,13 +1300,13 @@ Session::XMLRegionFactory (const XMLNode& node, bool full) if ((source = source_by_id (s_id)) == 0) { error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg; - return 0; + return boost::shared_ptr(); } - - as = dynamic_cast(source); + + as = boost::dynamic_pointer_cast(source); if (!as) { error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg; - return 0; + return boost::shared_ptr(); } sources.push_back (as); @@ -1816,24 +1321,26 @@ Session::XMLRegionFactory (const XMLNode& node, bool full) if ((source = source_by_id (id2)) == 0) { error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg; - return 0; + return boost::shared_ptr(); } - as = dynamic_cast(source); + as = boost::dynamic_pointer_cast(source); if (!as) { error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg; - return 0; + return boost::shared_ptr(); } sources.push_back (as); } } try { - return new AudioRegion (sources, node); + boost::shared_ptr region (boost::dynamic_pointer_cast (RegionFactory::create (sources, node))); + return region; + } catch (failed_constructor& err) { - return 0; + return boost::shared_ptr(); } } @@ -1881,7 +1388,7 @@ Session::load_sources (const XMLNode& node) { XMLNodeList nlist; XMLNodeConstIterator niter; - Source* source; + boost::shared_ptr source; nlist = node.children(); @@ -1897,25 +1404,21 @@ Session::load_sources (const XMLNode& node) return 0; } -Source * +boost::shared_ptr Session::XMLSourceFactory (const XMLNode& node) { - Source *src = 0; - if (node.name() != "Source") { - return 0; + return boost::shared_ptr(); } try { - src = AudioFileSource::create (node); + return SourceFactory::create (*this, node); } catch (failed_constructor& err) { error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg; - return 0; + return boost::shared_ptr(); } - - return src; } int @@ -1934,7 +1437,7 @@ Session::save_template (string template_name) if ((dp = opendir (dir.c_str()))) { closedir (dp); } else { - if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) { + if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg; return -1; } @@ -2014,11 +1517,9 @@ Session::ensure_sound_dir (string path, string& result) /* Ensure that the parent directory exists */ - if (mkdir (path.c_str(), 0775)) { - if (errno != EEXIST) { - error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg; - return -1; - } + if (g_mkdir_with_parents (path.c_str(), 0775)) { + error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg; + return -1; } /* Ensure that the sounds directory exists */ @@ -2027,33 +1528,27 @@ Session::ensure_sound_dir (string path, string& result) result += '/'; result += sound_dir_name; - if (mkdir (result.c_str(), 0775)) { - if (errno != EEXIST) { - error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg; - return -1; - } + if (g_mkdir_with_parents (result.c_str(), 0775)) { + error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg; + return -1; } dead = path; dead += '/'; dead += dead_sound_dir_name; - if (mkdir (dead.c_str(), 0775)) { - if (errno != EEXIST) { - error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg; - return -1; - } + if (g_mkdir_with_parents (dead.c_str(), 0775)) { + error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg; + return -1; } peak = path; peak += '/'; peak += peak_dir_name; - if (mkdir (peak.c_str(), 0775)) { - if (errno != EEXIST) { - error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg; - return -1; - } + if (g_mkdir_with_parents (peak.c_str(), 0775)) { + error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg; + return -1; } /* callers expect this to be terminated ... */ @@ -2068,12 +1563,6 @@ Session::discover_best_sound_dir (bool destructive) vector::iterator i; string result; - /* destructive files all go into the same place */ - - if (destructive) { - return tape_dir(); - } - /* handle common case without system calls */ if (session_dirs.size() == 1) { @@ -2279,20 +1768,41 @@ Session::dead_sound_dir () const } string -Session::sound_dir () const +Session::sound_dir (bool with_path) const { - string res = _path; + /* support old session structure */ + + struct stat statbuf; + string old_nopath; + string old_withpath; + + old_nopath += old_sound_dir_name; + old_nopath += '/'; + + old_withpath = _path; + old_withpath += old_sound_dir_name; + old_withpath += '/'; + + if (stat (old_withpath.c_str(), &statbuf) == 0) { + if (with_path) + return old_withpath; + + return old_nopath; + } + + string res; + + if (with_path) { + res = _path; + } + + res += interchange_dir_name; + res += '/'; + res += legalize_for_path (_name); + res += '/'; res += sound_dir_name; res += '/'; - return res; -} -string -Session::tape_dir () const -{ - string res = _path; - res += tape_dir_name; - res += '/'; return res; } @@ -2556,26 +2066,11 @@ Session::edit_group_by_name (string name) return 0; } -void -Session::set_meter_hold (float val) -{ - _meter_hold = val; - MeterHoldChanged(); // emit -} - -void -Session::set_meter_falloff (float val) -{ - _meter_falloff = val; - MeterFalloffChanged(); // emit -} - - void Session::begin_reversible_command (string name) { - current_trans.clear (); - current_trans.set_name (name); + current_trans = new UndoTransaction; + current_trans->set_name (name); } void @@ -2584,11 +2079,11 @@ Session::commit_reversible_command (Command *cmd) struct timeval now; if (cmd) { - current_trans.add_command (cmd); + current_trans->add_command (cmd); } gettimeofday (&now, 0); - current_trans.set_timestamp (now); + current_trans->set_timestamp (now); history.add (current_trans); } @@ -2882,7 +2377,7 @@ Session::find_all_sources_across_snapshots (set& result, bool exclude_th int Session::cleanup_sources (Session::cleanup_report& rep) { - vector dead_sources; + vector > dead_sources; vector playlists_tbd; PathScanner scanner; string sound_path; @@ -2931,13 +2426,7 @@ Session::cleanup_sources (Session::cleanup_report& rep) delete *x; } - /* step 2: clear the undo/redo history for all playlists */ - - for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) { - (*x)->drop_all_states (); - } - - /* step 3: find all un-referenced sources */ + /* step 2: find all un-referenced sources */ rep.paths.clear (); rep.space = 0; @@ -2954,7 +2443,7 @@ Session::cleanup_sources (Session::cleanup_report& rep) capture files. */ - if (i->second->use_cnt() == 0 && i->second->length() > 0) { + if (i->second.use_count() == 1 && i->second->length() > 0) { dead_sources.push_back (i->second); /* remove this source from our own list to avoid us @@ -2967,16 +2456,16 @@ Session::cleanup_sources (Session::cleanup_report& rep) i = tmp; } - /* Step 4: get rid of all regions in the region list that use any dead sources + /* Step 3: get rid of all regions in the region list that use any dead sources in case the sources themselves don't go away (they might be referenced in other snapshots). */ - for (vector::iterator i = dead_sources.begin(); i != dead_sources.end();++i) { + for (vector >::iterator i = dead_sources.begin(); i != dead_sources.end();++i) { for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) { AudioRegionList::iterator tmp; - AudioRegion* ar; + boost::shared_ptr ar; tmp = r; ++tmp; @@ -2984,7 +2473,7 @@ Session::cleanup_sources (Session::cleanup_report& rep) ar = r->second; for (uint32_t n = 0; n < ar->n_channels(); ++n) { - if (&ar->source (n) == (*i)) { + if (ar->source (n) == (*i)) { /* this region is dead */ remove_region (ar); } @@ -3032,9 +2521,9 @@ Session::cleanup_sources (Session::cleanup_report& rep) */ for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) { - AudioFileSource* fs; + boost::shared_ptr fs; - if ((fs = dynamic_cast (i->second)) != 0) { + if ((fs = boost::dynamic_pointer_cast (i->second)) != 0) { all_sources.insert (fs->path()); } } @@ -3247,7 +2736,7 @@ void Session::add_controllable (Controllable* c) { Glib::Mutex::Lock lm (controllables_lock); - controllables.push_back (c); + controllables.insert (c); } void @@ -3258,7 +2747,12 @@ Session::remove_controllable (Controllable* c) } Glib::Mutex::Lock lm (controllables_lock); - controllables.remove (c); + + Controllables::iterator x = controllables.find (c); + + if (x != controllables.end()) { + controllables.erase (x); + } } Controllable* @@ -3289,8 +2783,7 @@ Session::save_history (string snapshot_name) XMLTree tree; string xml_path; string bak_path; - - + tree.set_root (&history.get_state()); if (snapshot_name.empty()) { @@ -3298,7 +2791,6 @@ Session::save_history (string snapshot_name) } xml_path = _path + snapshot_name + ".history"; - cerr << "Saving history to " << xml_path << endmsg; bak_path = xml_path + ".bak"; @@ -3309,6 +2801,8 @@ Session::save_history (string snapshot_name) return -1; } + cerr << "actually writing history\n"; + if (!tree.write (xml_path)) { error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg; @@ -3355,42 +2849,215 @@ Session::restore_history (string snapshot_name) /* replace history */ history.clear(); - for (XMLNodeConstIterator it = tree.root()->children().begin(); - it != tree.root()->children().end(); - it++) - { - XMLNode *t = *it; - UndoTransaction ut; - struct timeval tv; - - ut.set_name(t->property("name")->value()); - stringstream ss(t->property("tv_sec")->value()); - ss >> tv.tv_sec; - ss.str(t->property("tv_usec")->value()); - ss >> tv.tv_usec; - ut.set_timestamp(tv); - - for (XMLNodeConstIterator child_it = t->children().begin(); - child_it != t->children().end(); - child_it++) - { - XMLNode *n = *child_it; - Command *c; - if (n->name() == "MementoCommand" || - n->name() == "MementoUndoCommand" || - n->name() == "MementoRedoCommand") - { - c = memento_command_factory(n); - if (c) - ut.add_command(c); - } - else - { - error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg; - } - } - history.add(ut); + + for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) { + + XMLNode *t = *it; + UndoTransaction* ut = new UndoTransaction (); + struct timeval tv; + + ut->set_name(t->property("name")->value()); + stringstream ss(t->property("tv_sec")->value()); + ss >> tv.tv_sec; + ss.str(t->property("tv_usec")->value()); + ss >> tv.tv_usec; + ut->set_timestamp(tv); + + for (XMLNodeConstIterator child_it = t->children().begin(); + child_it != t->children().end(); + child_it++) + { + XMLNode *n = *child_it; + Command *c; + + if (n->name() == "MementoCommand" || + n->name() == "MementoUndoCommand" || + n->name() == "MementoRedoCommand") { + if ((c = memento_command_factory(n))) { + ut->add_command(c); + } + } else { + error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg; + } + } + + history.add (ut); } return 0; } + +void +Session::config_changed (const char* parameter_name) +{ +#define PARAM_IS(x) (!strcmp (parameter_name, (x))) + + if (PARAM_IS ("seamless-loop")) { + + } else if (PARAM_IS ("rf-speed")) { + + } else if (PARAM_IS ("auto-loop")) { + + } else if (PARAM_IS ("auto-input")) { + + if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) { + /* auto-input only makes a difference if we're rolling */ + + boost::shared_ptr dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { + if ((*i)->record_enabled ()) { + //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; + (*i)->monitor_input (!Config->get_auto_input()); + } + } + } + + } else if (PARAM_IS ("punch-in")) { + + Location* location; + + if ((location = _locations.auto_punch_location()) != 0) { + + if (Config->get_punch_in ()) { + replace_event (Event::PunchIn, location->start()); + } else { + remove_event (location->start(), Event::PunchIn); + } + } + + } else if (PARAM_IS ("punch-out")) { + + Location* location; + + if ((location = _locations.auto_punch_location()) != 0) { + + if (Config->get_punch_out()) { + replace_event (Event::PunchOut, location->end()); + } else { + clear_events (Event::PunchOut); + } + } + + } else if (PARAM_IS ("edit-mode")) { + + Glib::Mutex::Lock lm (playlist_lock); + + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { + (*i)->set_edit_mode (Config->get_edit_mode ()); + } + + } else if (PARAM_IS ("use-video-sync")) { + + if (transport_stopped()) { + if (Config->get_use_video_sync()) { + waiting_for_sync_offset = true; + } + } + + } else if (PARAM_IS ("mmc-control")) { + + poke_midi_thread (); + + } else if (PARAM_IS ("midi-control")) { + + poke_midi_thread (); + + } else if (PARAM_IS ("raid-path")) { + + setup_raid_path (Config->get_raid_path()); + + } else if (PARAM_IS ("smpte-frames-per-second") || PARAM_IS ("smpte-drop-frames")) { + + sync_time_vars (); + + } else if (PARAM_IS ("video-pullup")) { + + sync_time_vars (); + + } else if (PARAM_IS ("seamless-loop")) { + + if (play_loop && transport_rolling()) { + // to reset diskstreams etc + request_play_loop (true); + } + + } else if (PARAM_IS ("rf-speed")) { + + cumulative_rf_motion = 0; + reset_rf_scale (0); + + } else if (PARAM_IS ("click-sound")) { + + setup_click_sounds (1); + + } else if (PARAM_IS ("click-emphasis-sound")) { + + setup_click_sounds (-1); + + } else if (PARAM_IS ("clicking")) { + + if (Config->get_clicking()) { + if (_click_io && click_data) { // don't require emphasis data + _clicking = true; + } + } else { + _clicking = false; + } + + } else if (PARAM_IS ("send-mtc")) { + + /* only set the internal flag if we have + a port. + */ + + if (_mtc_port != 0) { + session_send_mtc = Config->get_send_mtc(); + } + + } else if (PARAM_IS ("send-mmc")) { + + /* only set the internal flag if we have + a port. + */ + + if (_mmc_port != 0) { + session_send_mmc = Config->get_send_mmc(); + } + + } else if (PARAM_IS ("midi-feedback")) { + + /* only set the internal flag if we have + a port. + */ + + if (_mtc_port != 0) { + session_midi_feedback = Config->get_midi_feedback(); + } + + } else if (PARAM_IS ("jack-time-master")) { + + engine().reset_timebase (); + + } else if (PARAM_IS ("native-file-header-format")) { + + if (!first_file_header_format_reset) { + reset_native_file_format (); + } + + first_file_header_format_reset = false; + + } else if (PARAM_IS ("native-file-data-format")) { + + if (!first_file_data_format_reset) { + reset_native_file_format (); + } + + first_file_data_format_reset = false; + } + + set_dirty (); + +#undef PARAM_IS + +}