X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession_state.cc;h=8a49636941e5c4327cff48bae548caf58019c31c;hb=41d8747e9d4bbf10f848d907b879ba2211c89b8e;hp=18c5721f7ab54c5bb61283e18d956efdc3874409;hpb=f2c8ae66c09d2caffa44743eef0a0ab873024d9a;p=ardour.git diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 18c5721f7a..8a49636941 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -84,6 +84,8 @@ #include #include +#include + #include "i18n.h" #include @@ -99,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] != '/') { @@ -114,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); @@ -132,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; @@ -154,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; @@ -164,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); @@ -177,48 +168,38 @@ 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); - _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; @@ -231,34 +212,18 @@ Session::first_stage_init (string fullpath, string snapshot_name) _current_frame_rate = 48000; _base_frame_rate = 48000; - smpte_frames_per_second = 30; - video_pullup = 0.0; - smpte_drop_frames = false; 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 = 0.375f; // XXX unknown units: refresh_rate - max_level = 0; - min_level = 0; - /* slave stuff */ average_slave_delta = 1800; @@ -266,11 +231,6 @@ 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); - set_video_pullup (0.0); - _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered)); /* These are all static "per-class" signals */ @@ -283,8 +243,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) 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)); @@ -302,7 +261,6 @@ Session::second_stage_init (bool new_session) if (!new_session) { if (load_state (_current_snapshot_name)) { - cerr << "load state failed\n"; return -1; } remove_empty_sounds (); @@ -316,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, @@ -380,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) { @@ -481,12 +435,10 @@ 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; - new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)); - 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; @@ -520,66 +472,57 @@ Session::create (bool& new_session, string* mix_template, jack_nframes_t initial 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; @@ -771,232 +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, "video-pullup")) != 0) { - if ((prop = child->property ("val")) != 0) { - set_video_pullup( 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) { @@ -1004,243 +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); - - 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); + XMLNode& option_root = Config->get_variables (mem_fun (*this, &Session::save_config_options_predicate)); - snprintf (buf, sizeof(buf)-1, "%.4f", video_pullup); - child = opthead->add_child ("video-pullup"); - 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& @@ -1460,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); } @@ -1467,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) { @@ -1482,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); @@ -1511,7 +1039,7 @@ Session::set_state (const XMLNode& node) MIDI Path extra - Options + Options/Config Sources AudioRegions AudioDiskstreams @@ -1521,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) { @@ -1621,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; @@ -1657,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 ... */ @@ -1667,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 (); @@ -1678,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; } @@ -1765,6 +1283,11 @@ Session::XMLRegionFactory (const XMLNode& node, bool full) 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) { @@ -1884,7 +1407,6 @@ Session::load_sources (const XMLNode& node) boost::shared_ptr Session::XMLSourceFactory (const XMLNode& node) { - if (node.name() != "Source") { return boost::shared_ptr(); } @@ -2251,17 +1773,21 @@ Session::sound_dir (bool with_path) const /* support old session structure */ struct stat statbuf; - string old; + string old_nopath; + string old_withpath; - if (with_path) { - old = _path; - } - - old += sound_dir_name; - old += '/'; + old_nopath += old_sound_dir_name; + old_nopath += '/'; + + old_withpath = _path; + old_withpath += old_sound_dir_name; + old_withpath += '/'; - if (stat (old.c_str(), &statbuf) == 0) { - return old; + if (stat (old_withpath.c_str(), &statbuf) == 0) { + if (with_path) + return old_withpath; + + return old_nopath; } string res; @@ -2540,21 +2066,6 @@ 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) { @@ -2915,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; @@ -2951,7 +2456,7 @@ 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). */ @@ -3231,7 +2736,7 @@ void Session::add_controllable (Controllable* c) { Glib::Mutex::Lock lm (controllables_lock); - controllables.push_back (c); + controllables.insert (c); } void @@ -3242,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* @@ -3339,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 = 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") - { - 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 + +}