1 /*
2  * Copyright (C) 1999-2019 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
5  * Copyright (C) 2006-2016 Tim Mayberry <mojofunk@gmail.com>
6  * Copyright (C) 2006 Jesse Chappell <jesse@essej.net>
7  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
8  * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
9  * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
10  * Copyright (C) 2013-2016 John Emmas <john@creativepost.co.uk>
11  * Copyright (C) 2013-2017 Nick Mainsbridge <mainsbridge@gmail.com>
12  * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
13  * Copyright (C) 2017 Johannes Mueller <github@johannes-mueller.org>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28  */
29 
30 
31 #ifdef WAF_BUILD
32 #include "libardour-config.h"
33 #endif
34 
35 #include <stdint.h>
36 
37 #include <algorithm>
38 #include <string>
39 #include <cerrno>
40 #include <cstdio> /* snprintf(3) ... grrr */
41 #include <cmath>
42 
43 #include <unistd.h>
44 #include <climits>
45 #include <signal.h>
46 #include <sys/time.h>
47 /* for open(2) */
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <fcntl.h>
51 
52 #ifdef HAVE_SYS_VFS_H
53 #include <sys/vfs.h>
54 #endif
55 
56 #if defined(__APPLE__) || defined(__FreeBSD__)
57 #include <sys/param.h>
58 #include <sys/mount.h>
59 #endif
60 
61 #ifdef HAVE_SYS_STATVFS_H
62 #include <sys/statvfs.h>
63 #endif
64 
65 #include <glib.h>
66 #include "pbd/gstdio_compat.h"
67 #include "pbd/locale_guard.h"
68 
69 #include <glibmm.h>
70 #include <glibmm/threads.h>
71 #include <glibmm/fileutils.h>
72 
73 #include <boost/algorithm/string.hpp>
74 
75 #include "midi++/mmc.h"
76 #include "midi++/port.h"
77 
78 #include "evoral/SMF.h"
79 
80 #include "pbd/basename.h"
81 #include "pbd/debug.h"
82 #include "pbd/enumwriter.h"
83 #include "pbd/error.h"
84 #include "pbd/file_utils.h"
85 #include "pbd/pathexpand.h"
86 #include "pbd/pthread_utils.h"
87 #include "pbd/scoped_file_descriptor.h"
88 #include "pbd/types_convert.h"
89 #include "pbd/localtime_r.h"
90 #include "pbd/unwind.h"
91 
92 #include "ardour/amp.h"
93 #include "ardour/async_midi_port.h"
94 #include "ardour/audio_track.h"
95 #include "ardour/audioengine.h"
96 #include "ardour/audiofilesource.h"
97 #include "ardour/audioregion.h"
98 #include "ardour/auditioner.h"
99 #include "ardour/automation_control.h"
100 #include "ardour/boost_debug.h"
101 #include "ardour/butler.h"
102 #include "ardour/control_protocol_manager.h"
103 #include "ardour/directory_names.h"
104 #include "ardour/disk_reader.h"
105 #include "ardour/filename_extensions.h"
106 #include "ardour/graph.h"
107 #include "ardour/location.h"
108 #include "ardour/lv2_plugin.h"
109 #include "ardour/midi_model.h"
110 #include "ardour/midi_region.h"
111 #include "ardour/midi_scene_changer.h"
112 #include "ardour/midi_source.h"
113 #include "ardour/midi_track.h"
114 #include "ardour/playlist_factory.h"
115 #include "ardour/playlist_source.h"
116 #include "ardour/port.h"
117 #include "ardour/processor.h"
118 #include "ardour/progress.h"
119 #include "ardour/profile.h"
120 #include "ardour/proxy_controllable.h"
121 #include "ardour/recent_sessions.h"
122 #include "ardour/region_factory.h"
123 #include "ardour/revision.h"
124 #include "ardour/route_group.h"
125 #include "ardour/send.h"
126 #include "ardour/selection.h"
127 #include "ardour/session.h"
128 #include "ardour/session_directory.h"
129 #include "ardour/session_metadata.h"
130 #include "ardour/session_playlists.h"
131 #include "ardour/session_state_utils.h"
132 #include "ardour/silentfilesource.h"
133 #include "ardour/smf_source.h"
134 #include "ardour/sndfilesource.h"
135 #include "ardour/source_factory.h"
136 #include "ardour/speakers.h"
137 #include "ardour/template_utils.h"
138 #include "ardour/tempo.h"
139 #include "ardour/ticker.h"
140 #include "ardour/transport_master_manager.h"
141 #include "ardour/types_convert.h"
142 #include "ardour/user_bundle.h"
143 #include "ardour/vca.h"
144 #include "ardour/vca_manager.h"
145 
146 #include "control_protocol/control_protocol.h"
147 
148 #include "LuaBridge/LuaBridge.h"
149 
150 #include "pbd/i18n.h"
151 #include <locale.h>
152 
153 using namespace std;
154 using namespace ARDOUR;
155 using namespace PBD;
156 
157 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
158 
159 void
pre_engine_init(string fullpath)160 Session::pre_engine_init (string fullpath)
161 {
162 	if (fullpath.empty()) {
163 		destroy ();
164 		throw failed_constructor();
165 	}
166 
167 	/* discover canonical fullpath */
168 
169 	_path = canonical_path(fullpath);
170 
171 	/* is it new ? */
172 
173 	_is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
174 
175 	/* finish initialization that can't be done in a normal C++ constructor
176 	   definition.
177 	*/
178 
179 	timerclear (&last_mmc_step);
180 	g_atomic_int_set (&_processing_prohibited, 0);
181 	g_atomic_int_set (&_record_status, Disabled);
182 	g_atomic_int_set (&_playback_load, 100);
183 	g_atomic_int_set (&_capture_load, 100);
184 	set_next_event ();
185 	_all_route_group->set_active (true, this);
186 
187 	if (config.get_use_video_sync()) {
188 		waiting_for_sync_offset = true;
189 	} else {
190 		waiting_for_sync_offset = false;
191 	}
192 
193 	last_rr_session_dir = session_dirs.begin();
194 
195 	set_history_depth (Config->get_history_depth());
196 
197 	/* default: assume simple stereo speaker configuration */
198 
199 	_speakers->setup_default_speakers (2);
200 
201 	_solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
202 				boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
203 				boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
204 	add_controllable (_solo_cut_control);
205 
206 	/* These are all static "per-class" signals */
207 
208 	SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
209 	PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
210 	AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
211 	IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
212 
213 	/* stop IO objects from doing stuff until we're ready for them */
214 
215 	Delivery::disable_panners ();
216 	IO::disable_connecting ();
217 }
218 
219 int
post_engine_init()220 Session::post_engine_init ()
221 {
222 	BootMessage (_("Set block size and sample rate"));
223 
224 	set_block_size (_engine.samples_per_cycle());
225 	set_sample_rate (_engine.sample_rate());
226 
227 	BootMessage (_("Using configuration"));
228 
229 	_midi_ports = new MidiPortManager;
230 
231 	MIDISceneChanger* msc;
232 
233 	_scene_changer = msc = new MIDISceneChanger (*this);
234 	msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
235 	msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
236 
237 	boost::function<samplecnt_t(void)> timer_func (boost::bind (&Session::audible_sample, this, (bool*)(0)));
238 	boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
239 
240 	setup_midi_machine_control ();
241 
242 	/* setup MTC generator */
243 	mtc_tx_resync_latency (true);
244 	LatencyUpdated.connect_same_thread (*this, boost::bind (&Session::mtc_tx_resync_latency, this, _1));
245 
246 	if (_butler->start_thread()) {
247 		error << _("Butler did not start") << endmsg;
248 		return -1;
249 	}
250 
251 	if (start_midi_thread ()) {
252 		error << _("MIDI I/O thread did not start") << endmsg;
253 		return -1;
254 	}
255 
256 	setup_click_sounds (0);
257 	setup_midi_control ();
258 
259 	_engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
260 	_engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
261 
262 	try {
263 		/* tempo map requires sample rate knowledge */
264 
265 		delete _tempo_map;
266 		_tempo_map = new TempoMap (_current_sample_rate);
267 		_tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
268 		_tempo_map->MetricPositionChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
269 	} catch (std::exception const & e) {
270 		error << _("Unexpected exception during session setup: ") << e.what() << endmsg;
271 		return -2;
272 	} catch (...) {
273 		error << _("Unknown exception during session setup") << endmsg;
274 		return -3;
275 	}
276 
277 	try {
278 		/* MidiClock requires a tempo map */
279 
280 		delete midi_clock;
281 		midi_clock = new MidiClockTicker (this);
282 
283 		/* crossfades require sample rate knowledge */
284 
285 		_engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this, true));
286 		_engine.MidiSelectionPortsChanged.connect_same_thread (*this, boost::bind (&Session::rewire_midi_selection_ports, this));
287 
288 		DiskReader::allocate_working_buffers();
289 		refresh_disk_space ();
290 
291 		/* we're finally ready to call set_state() ... all objects have
292 		 * been created, the engine is running.
293 		 */
294 
295 		if (state_tree) {
296 			try {
297 				if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
298 					error << _("Could not set session state from XML") << endmsg;
299 					return -4;
300 				}
301 			} catch (PBD::unknown_enumeration& e) {
302 				error << _("Session state: ") << e.what() << endmsg;
303 				return -4;
304 			}
305 		} else {
306 			// set_state() will call setup_raid_path(), but if it's a new session we need
307 			// to call setup_raid_path() here.
308 			setup_raid_path (_path);
309 		}
310 
311 		/* ENGINE */
312 
313 		boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
314 		boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
315 
316 		Config->map_parameters (ff);
317 		config.map_parameters (ft);
318 		_butler->map_parameters ();
319 
320 		/* Configure all processors; now that the
321 		 * engine is running, ports are re-established,
322 		 * and IOChange are complete.
323 		 */
324 		{
325 			Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
326 			ProcessorChangeBlocker pcb (this);
327 			boost::shared_ptr<RouteList> r = routes.reader ();
328 			for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
329 				(*i)->configure_processors (0);
330 			}
331 			/* release process-lock, ProcessorChangeBlocker may trigger
332 			 * latency-callback from non-rt thread which may take the lock */
333 			lx.release ();
334 		}
335 
336 		/* Reset all panners */
337 
338 		Delivery::reset_panners ();
339 
340 		/* this will cause the CPM to instantiate any protocols that are in use
341 		 * (or mandatory), which will pass it this Session, and then call
342 		 * set_state() on each instantiated protocol to match stored state.
343 		 */
344 
345 		ControlProtocolManager::instance().set_session (this);
346 
347 		/* This must be done after the ControlProtocolManager set_session above,
348 		   as it will set states for ports which the ControlProtocolManager creates.
349 		*/
350 
351 		// XXX set state of MIDI::Port's
352 		// MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
353 
354 		/* And this must be done after the MIDI::Manager::set_port_states as
355 		 * it will try to make connections whose details are loaded by set_port_states.
356 		 */
357 
358 		hookup_io ();
359 
360 		/* Let control protocols know that we are now all connected, so they
361 		 * could start talking to surfaces if they want to.
362 		 */
363 
364 		ControlProtocolManager::instance().midi_connectivity_established ();
365 
366 		if (_is_new && !no_auto_connect()) {
367 			Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
368 			auto_connect_master_bus ();
369 		}
370 
371 		_state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave | Dirty));
372 
373 		/* update latencies */
374 
375 		initialize_latencies ();
376 
377 		_locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
378 		_locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
379 		_locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
380 
381 		if (synced_to_engine()) {
382 			_engine.transport_stop ();
383 		}
384 
385 		// send_full_time_code (0);
386 
387 	} catch (AudioEngine::PortRegistrationFailure& err) {
388 		error << err.what() << endmsg;
389 		return -5;
390 	} catch (std::exception const & e) {
391 		error << _("Unexpected exception during session setup: ") << e.what() << endmsg;
392 		return -6;
393 	} catch (...) {
394 		error << _("Unknown exception during session setup") << endmsg;
395 		return -7;
396 	}
397 
398 	BootMessage (_("Reset Remote Controls"));
399 
400 	send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
401 	send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
402 
403 	ltc_tx_initialize();
404 
405 	Port::set_connecting_blocked (false);
406 
407 	set_clean ();
408 
409 	/* Now, finally, we can fill the playback buffers */
410 
411 	BootMessage (_("Filling playback buffers"));
412 
413 	boost::shared_ptr<RouteList> rl = routes.reader();
414 	for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
415 		boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
416 		if (trk && !trk->is_private_route()) {
417 			trk->seek (_transport_sample, true);
418 		}
419 	}
420 
421 	reset_xrun_count ();
422 	return 0;
423 }
424 
425 void
session_loaded()426 Session::session_loaded ()
427 {
428 	SessionLoaded();
429 
430 	set_clean ();
431 
432 	if (_is_new) {
433 		save_state ("");
434 	} else if (state_was_pending) {
435 		save_state ("");
436 		state_was_pending = false;
437 	}
438 
439 	/* Now, finally, we can fill the playback buffers */
440 
441 	BootMessage (_("Filling playback buffers"));
442 	force_locate (_transport_sample, MustStop);
443 	reset_xrun_count ();
444 }
445 
446 string
raid_path() const447 Session::raid_path () const
448 {
449 	Searchpath raid_search_path;
450 
451 	for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
452 		raid_search_path += (*i).path;
453 	}
454 
455 	return raid_search_path.to_string ();
456 }
457 
458 void
setup_raid_path(string path)459 Session::setup_raid_path (string path)
460 {
461 	if (path.empty()) {
462 		return;
463 	}
464 
465 	space_and_path sp;
466 	string fspath;
467 
468 	session_dirs.clear ();
469 
470 	Searchpath search_path(path);
471 	Searchpath sound_search_path;
472 	Searchpath midi_search_path;
473 
474 	for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
475 		sp.path = *i;
476 		sp.blocks = 0; // not needed
477 		session_dirs.push_back (sp);
478 
479 		SessionDirectory sdir(sp.path);
480 
481 		sound_search_path += sdir.sound_path ();
482 		midi_search_path += sdir.midi_path ();
483 	}
484 
485 	// reset the round-robin soundfile path thingie
486 	last_rr_session_dir = session_dirs.begin();
487 }
488 
489 bool
path_is_within_session(const std::string & path)490 Session::path_is_within_session (const std::string& path)
491 {
492 	for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
493 		if (PBD::path_is_within (i->path, path)) {
494 			return true;
495 		}
496 	}
497 	return false;
498 }
499 
500 int
ensure_subdirs()501 Session::ensure_subdirs ()
502 {
503 	string dir;
504 
505 	dir = session_directory().peak_path();
506 
507 	if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
508 		error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
509 		return -1;
510 	}
511 
512 	dir = session_directory().sound_path();
513 
514 	if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
515 		error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
516 		return -1;
517 	}
518 
519 	dir = session_directory().midi_path();
520 
521 	if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
522 		error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
523 		return -1;
524 	}
525 
526 	dir = session_directory().dead_path();
527 
528 	if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
529 		error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
530 		return -1;
531 	}
532 
533 	dir = session_directory().export_path();
534 
535 	if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
536 		error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
537 		return -1;
538 	}
539 
540 	if(Profile->get_mixbus()) {
541 		dir = session_directory().backup_path();
542 
543 		if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
544 			error << string_compose(_("Session: cannot create session backup folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
545 			return -1;
546 		}
547 	}
548 
549 	dir = analysis_dir ();
550 
551 	if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
552 		error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
553 		return -1;
554 	}
555 
556 	dir = plugins_dir ();
557 
558 	if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
559 		error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
560 		return -1;
561 	}
562 
563 	dir = externals_dir ();
564 
565 	if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
566 		error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
567 		return -1;
568 	}
569 
570 	return 0;
571 }
572 
573 /** @param session_template directory containing session template, or empty.
574  *  Caller must not hold process lock.
575  */
576 int
create(const string & session_template,BusProfile const * bus_profile,bool unnamed)577 Session::create (const string& session_template, BusProfile const * bus_profile, bool unnamed)
578 {
579 	if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
580 		error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
581 		return -1;
582 	}
583 
584 	if (unnamed) {
585 		PBD::ScopedFileDescriptor fd = g_open (unnamed_file_name().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666);
586 	}
587 
588 	if (ensure_subdirs ()) {
589 		return -1;
590 	}
591 
592 	_writable = exists_and_writable (_path);
593 
594 	if (!session_template.empty()) {
595 		string in_path = session_template_dir_to_file (session_template);
596 
597 		FILE* in = g_fopen (in_path.c_str(), "rb");
598 
599 		if (in) {
600 			/* no need to call legalize_for_path() since the string
601 			 * in session_template is already a legal path name
602 			 */
603 			string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
604 
605 			FILE* out = g_fopen (out_path.c_str(), "wb");
606 
607 			if (out) {
608 				char buf[1024];
609 				stringstream new_session;
610 
611 				while (!feof (in)) {
612 					size_t charsRead = fread (buf, sizeof(char), 1024, in);
613 
614 					if (ferror (in)) {
615 						error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
616 						fclose (in);
617 						fclose (out);
618 						return -1;
619 					}
620 					if (charsRead == 0) {
621 						break;
622 					}
623 					new_session.write (buf, charsRead);
624 				}
625 				fclose (in);
626 
627 				string file_contents = new_session.str();
628 				size_t writeSize = file_contents.length();
629 				if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
630 					error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
631 					fclose (out);
632 					return -1;
633 				}
634 				fclose (out);
635 
636 				_is_new = false;
637 
638 				/* Copy plugin state files from template to new session */
639 				std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
640 				copy_recurse (template_plugins, plugins_dir ());
641 
642 				return 0;
643 
644 			} else {
645 				error << string_compose (_("Could not open %1 for writing session template"), out_path)
646 					<< endmsg;
647 				fclose(in);
648 				return -1;
649 			}
650 
651 		} else {
652 			error << string_compose (_("Could not open session template %1 for reading"), in_path)
653 				<< endmsg;
654 			return -1;
655 		}
656 
657 	}
658 
659 	/* set up Master Out and Monitor Out if necessary */
660 
661 	if (bus_profile) {
662 		RouteList rl;
663 		ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
664 		if (bus_profile->master_out_channels) {
665 			int rv = add_master_bus (count);
666 
667 			if (rv) {
668 				return rv;
669 			}
670 
671 			if (Config->get_use_monitor_bus())
672 				add_monitor_section ();
673 		}
674 	}
675 
676 	set_clean ();
677 	reset_xrun_count ();
678 
679 	return 0;
680 }
681 
682 void
maybe_write_autosave()683 Session::maybe_write_autosave()
684 {
685 	if (dirty() && record_status() != Recording) {
686 		save_state("", true);
687 	}
688 }
689 
690 void
remove_pending_capture_state()691 Session::remove_pending_capture_state ()
692 {
693 	std::string pending_state_file_path(_session_dir->root_path());
694 
695 	pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
696 
697 	if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) {
698 		return;
699 	}
700 
701 	if (::g_unlink (pending_state_file_path.c_str()) != 0) {
702 		error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
703 				pending_state_file_path, g_strerror (errno)) << endmsg;
704 	}
705 #ifndef NDEBUG
706 	else {
707 		cerr << "removed " << pending_state_file_path << endl;
708 	}
709 #endif
710 }
711 
712 /** Rename a state file.
713  *  @param old_name Old snapshot name.
714  *  @param new_name New snapshot name.
715  */
716 void
rename_state(string old_name,string new_name)717 Session::rename_state (string old_name, string new_name)
718 {
719 	if (old_name == _current_snapshot_name || old_name == _name) {
720 		/* refuse to rename the current snapshot or the "main" one */
721 		return;
722 	}
723 
724 	const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
725 	const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
726 
727 	const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
728 	const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
729 
730 	if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
731 		error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
732 				old_name, new_name, g_strerror(errno)) << endmsg;
733 	}
734 }
735 
736 /** Remove a state file.
737  *  @param snapshot_name Snapshot name.
738  */
739 void
remove_state(string snapshot_name)740 Session::remove_state (string snapshot_name)
741 {
742 	if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
743 		// refuse to remove the current snapshot or the "main" one
744 		return;
745 	}
746 
747 	std::string xml_path(_session_dir->root_path());
748 
749 	xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
750 
751 	if (!create_backup_file (xml_path)) {
752 		// don't remove it if a backup can't be made
753 		// create_backup_file will log the error.
754 		return;
755 	}
756 
757 	// and delete it
758 	if (g_remove (xml_path.c_str()) != 0) {
759 		error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
760 				xml_path, g_strerror (errno)) << endmsg;
761 	}
762 
763 	StateSaved (snapshot_name); /* EMIT SIGNAL */
764 }
765 
766 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
767 int
save_state(string snapshot_name,bool pending,bool switch_to_snapshot,bool template_only,bool for_archive,bool only_used_assets)768 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only, bool for_archive, bool only_used_assets)
769 {
770 	DEBUG_TRACE (DEBUG::Locale, string_compose ("Session::save_state locale '%1'\n", setlocale (LC_NUMERIC, NULL)));
771 
772 	/* only_used_assets is only possible when archiving */
773 	assert (!only_used_assets || for_archive);
774 	/* template and archive are exclusive */
775 	assert (!template_only || !for_archive);
776 	/* switch_to_snapshot needs a new name and can't be pending */
777 	assert (!switch_to_snapshot || (!snapshot_name.empty () && snapshot_name != _current_snapshot_name && !pending && !template_only && !for_archive));
778 	/* pending saves are for current snapshot only */
779 	assert (!pending || ((snapshot_name.empty () || snapshot_name == _current_snapshot_name) && !template_only && !for_archive));
780 
781 	XMLTree tree;
782 	std::string xml_path(_session_dir->root_path());
783 
784 	/* prevent concurrent saves from different threads */
785 
786 	Glib::Threads::Mutex::Lock lm (save_state_lock);
787 	Glib::Threads::Mutex::Lock lx (save_source_lock, Glib::Threads::NOT_LOCK);
788 	if (!for_archive) {
789 		lx.acquire ();
790 	}
791 
792 	if (!_writable || cannot_save()) {
793 		return 1;
794 	}
795 
796 	if (g_atomic_int_get(&_suspend_save)) {
797 		/* StateProtector cannot be used for templates or save-as */
798 		assert (!template_only && !switch_to_snapshot && !for_archive && (snapshot_name.empty () || snapshot_name == _current_snapshot_name));
799 		if (pending) {
800 			_save_queued_pending = true;
801 		} else {
802 			_save_queued = true;
803 		}
804 		return 1;
805 	}
806 	if (pending) {
807 		_save_queued_pending = false;
808 	} else {
809 		_save_queued = false;
810 	}
811 
812 	snapshot_t fork_state = NormalSave;
813 	if (!snapshot_name.empty() && snapshot_name != _current_snapshot_name && !template_only && !pending && !for_archive) {
814 		/* snapshot, close midi */
815 		fork_state = switch_to_snapshot ? SwitchToSnapshot : SnapshotKeep;
816 	}
817 
818 #ifndef NDEBUG
819 	const int64_t save_start_time = g_get_monotonic_time();
820 #endif
821 
822 	/* tell sources we're saving first, in case they write out to a new file
823 	 * which should be saved with the state rather than the old one */
824 	for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
825 		try {
826 			i->second->session_saved();
827 		} catch (Evoral::SMF::FileError& e) {
828 			error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
829 		}
830 	}
831 
832 	PBD::Unwinder<bool> uw (LV2Plugin::force_state_save, for_archive);
833 
834 	SessionSaveUnderway (); /* EMIT SIGNAL */
835 
836 	bool mark_as_clean = true;
837 	if (!snapshot_name.empty() && !switch_to_snapshot) {
838 		mark_as_clean = false;
839 	}
840 
841 	if (template_only) {
842 		mark_as_clean = false;
843 		tree.set_root (&get_template());
844 	} else {
845 		tree.set_root (&state (false, fork_state, only_used_assets));
846 	}
847 
848 	if (snapshot_name.empty()) {
849 		snapshot_name = _current_snapshot_name;
850 	} else if (switch_to_snapshot) {
851 		set_snapshot_name (snapshot_name);
852 	}
853 
854 	assert (!snapshot_name.empty());
855 
856 	if (!pending) {
857 
858 		/* proper save: use statefile_suffix (.ardour in English) */
859 
860 		xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
861 
862 		/* make a backup copy of the old file */
863 
864 		if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
865 			// create_backup_file will log the error
866 			return -1;
867 		}
868 
869 	} else {
870 		assert (snapshot_name == _current_snapshot_name);
871 		/* pending save: use pending_suffix (.pending in English) */
872 		xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
873 	}
874 
875 	std::string tmp_path(_session_dir->root_path());
876 	tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
877 
878 #ifndef NDEBUG
879 	cerr << "actually writing state to " << tmp_path << endl;
880 #endif
881 
882 	if (!tree.write (tmp_path)) {
883 		error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
884 		if (g_remove (tmp_path.c_str()) != 0) {
885 			error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
886 					tmp_path, g_strerror (errno)) << endmsg;
887 		}
888 		return -1;
889 
890 	} else {
891 
892 #ifndef NDEBUG
893 		cerr << "renaming state to " << xml_path << endl;
894 #endif
895 
896 		if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
897 			error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
898 					tmp_path, xml_path, g_strerror(errno)) << endmsg;
899 			if (g_remove (tmp_path.c_str()) != 0) {
900 				error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
901 						tmp_path, g_strerror (errno)) << endmsg;
902 			}
903 			return -1;
904 		}
905 	}
906 
907 	//Mixbus auto-backup mechanism
908 	if(Profile->get_mixbus()) {
909 		if (pending) {  //"pending" save means it's a backup, or some other non-user-initiated save;  a good time to make a backup
910 			// make a serialized safety backup
911 			// (will make one periodically but only one per hour is left on disk)
912 			// these backup files go into a separated folder
913 			char timebuf[128];
914 			time_t n;
915 			struct tm local_time;
916 			time (&n);
917 			localtime_r (&n, &local_time);
918 			strftime (timebuf, sizeof(timebuf), "%y-%m-%d.%H", &local_time);
919 			std::string save_path(session_directory().backup_path());
920 			save_path += G_DIR_SEPARATOR;
921 			save_path += legalize_for_path(_current_snapshot_name);
922 			save_path += "-";
923 			save_path += timebuf;
924 			save_path += statefile_suffix;
925 			if (!copy_file (xml_path, save_path)) {
926 					error << string_compose(_("Could not save backup file at path \"%1\" (%2)"),
927 							save_path, g_strerror (errno)) << endmsg;
928 			}
929 		}
930 	}
931 
932 	if (!pending && !for_archive) {
933 
934 		save_history (snapshot_name);
935 
936 		if (mark_as_clean) {
937 			unset_dirty (/* EMIT SIGNAL */ true);
938 		}
939 
940 		StateSaved (snapshot_name); /* EMIT SIGNAL */
941 	}
942 
943 #ifndef NDEBUG
944 	const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
945 	cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
946 #endif
947 
948 	if (!pending && !for_archive && ! template_only) {
949 		remove_pending_capture_state ();
950 	}
951 
952 	return 0;
953 }
954 
955 int
restore_state(string snapshot_name)956 Session::restore_state (string snapshot_name)
957 {
958 	try {
959 		if (load_state (snapshot_name) == 0) {
960 			set_state (*state_tree->root(), Stateful::loading_state_version);
961 		}
962 	} catch (...) {
963 		// SessionException
964 		// unknown_enumeration
965 		return -1;
966 	}
967 
968 	return 0;
969 }
970 
971 int
load_state(string snapshot_name,bool from_template)972 Session::load_state (string snapshot_name, bool from_template)
973 {
974 	delete state_tree;
975 	state_tree = 0;
976 
977 	state_was_pending = false;
978 
979 	/* check for leftover pending state from a crashed capture attempt */
980 
981 	std::string xmlpath(_session_dir->root_path());
982 	xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
983 
984 	if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
985 
986 		/* there is pending state from a crashed capture attempt */
987 
988 		boost::optional<int> r = AskAboutPendingState();
989 		if (r.value_or (1)) {
990 			state_was_pending = true;
991 		}
992 	}
993 
994 	if (!state_was_pending) {
995 		xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
996 	}
997 
998 	if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
999 		xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
1000 		if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
1001 			error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
1002 			return 1;
1003 		}
1004 	}
1005 
1006 	state_tree = new XMLTree;
1007 
1008 	set_dirty();
1009 
1010 	_writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
1011 
1012 	if (!state_tree->read (xmlpath)) {
1013 		error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
1014 		delete state_tree;
1015 		state_tree = 0;
1016 		return -1;
1017 	}
1018 
1019 	XMLNode const & root (*state_tree->root());
1020 
1021 	if (root.name() != X_("Session")) {
1022 		error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
1023 		delete state_tree;
1024 		state_tree = 0;
1025 		return -1;
1026 	}
1027 
1028 	std::string version;
1029 	root.get_property ("version", version);
1030 	Stateful::loading_state_version = parse_stateful_loading_version (version);
1031 
1032 	if ((Stateful::loading_state_version / 1000L) > (CURRENT_SESSION_FILE_VERSION / 1000L)) {
1033 		cerr << "Session-version: " << Stateful::loading_state_version << " is not supported. Current: " << CURRENT_SESSION_FILE_VERSION << "\n";
1034 		throw SessionException (string_compose (_("Incompatible Session Version. That session was created with a newer version of %1"), PROGRAM_NAME));
1035 	}
1036 
1037 	if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable && !from_template) {
1038 
1039 		std::string backup_path(_session_dir->root_path());
1040 		std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
1041 		backup_path = Glib::build_filename (backup_path, backup_filename);
1042 
1043 		// only create a backup for a given statefile version once
1044 
1045 		if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
1046 
1047 			VersionMismatch (xmlpath, backup_path);
1048 
1049 			if (!copy_file (xmlpath, backup_path)) {;
1050 				return -1;
1051 			}
1052 		}
1053 	}
1054 
1055 	save_snapshot_name (snapshot_name);
1056 
1057 	return 0;
1058 }
1059 
1060 int
load_options(const XMLNode & node)1061 Session::load_options (const XMLNode& node)
1062 {
1063 	config.set_variables (node);
1064 	return 0;
1065 }
1066 
1067 bool
save_default_options()1068 Session::save_default_options ()
1069 {
1070 	return config.save_state();
1071 }
1072 
1073 XMLNode&
get_state()1074 Session::get_state ()
1075 {
1076 	/* this is not directly called, but required by PBD::Stateful */
1077 	assert (0);
1078 	return state (false, NormalSave);
1079 }
1080 
1081 XMLNode&
get_template()1082 Session::get_template ()
1083 {
1084 	/* if we don't disable rec-enable, diskstreams
1085 	   will believe they need to store their capture
1086 	   sources in their state node.
1087 	*/
1088 
1089 	disable_record (false);
1090 
1091 	return state (true, NormalSave);
1092 }
1093 
1094 typedef std::set<boost::shared_ptr<Playlist> > PlaylistSet;
1095 typedef std::set<boost::shared_ptr<Source> > SourceSet;
1096 
1097 bool
export_track_state(boost::shared_ptr<RouteList> rl,const string & path)1098 Session::export_track_state (boost::shared_ptr<RouteList> rl, const string& path)
1099 {
1100 	if (Glib::file_test (path, Glib::FILE_TEST_EXISTS))  {
1101 		return false;
1102 	}
1103 	if (g_mkdir_with_parents (path.c_str(), 0755) != 0) {
1104 		return false;
1105 	}
1106 
1107 	PBD::Unwinder<std::string> uw (_template_state_dir, path);
1108 
1109 	LocaleGuard lg;
1110 	XMLNode* node = new XMLNode("TrackState"); // XXX
1111 	XMLNode* child;
1112 
1113 	PlaylistSet playlists; // SessionPlaylists
1114 	SourceSet sources;
1115 
1116 	// these will work with  new_route_from_template()
1117 	// TODO: LV2 plugin-state-dir needs to be relative (on load?)
1118 	child = node->add_child ("Routes");
1119 	for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1120 		if ((*i)->is_auditioner()) {
1121 			continue;
1122 		}
1123 		if ((*i)->is_master() || (*i)->is_monitor()) {
1124 			continue;
1125 		}
1126 		child->add_child_nocopy ((*i)->get_state());
1127 		boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (*i);
1128 		if (track) {
1129 			playlists.insert (track->playlist ());
1130 		}
1131 	}
1132 
1133 	// on load, Regions in the playlists need to resolve and map Source-IDs
1134 	// also playlist needs to be merged or created with new-name..
1135 	// ... and Diskstream in tracks adjusted to use the correct playlist
1136 	child = node->add_child ("Playlists"); // SessionPlaylists::add_state
1137 	for (PlaylistSet::const_iterator i = playlists.begin(); i != playlists.end(); ++i) {
1138 		child->add_child_nocopy ((*i)->get_state ());
1139 		boost::shared_ptr<RegionList> prl = (*i)->region_list ();
1140 		for (RegionList::const_iterator s = prl->begin(); s != prl->end(); ++s) {
1141 			const Region::SourceList& sl = (*s)->sources ();
1142 			for (Region::SourceList::const_iterator sli = sl.begin(); sli != sl.end(); ++sli) {
1143 				sources.insert (*sli);
1144 			}
1145 		}
1146 	}
1147 
1148 	child = node->add_child ("Sources");
1149 	for (SourceSet::const_iterator i = sources.begin(); i != sources.end(); ++i) {
1150 		child->add_child_nocopy ((*i)->get_state ());
1151 		boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (*i);
1152 		if (fs) {
1153 #ifdef PLATFORM_WINDOWS
1154 			fs->close ();
1155 #endif
1156 			string p = fs->path ();
1157 			PBD::copy_file (p, Glib::build_filename (path, Glib::path_get_basename (p)));
1158 		}
1159 	}
1160 
1161 	std::string sn = Glib::build_filename (path, "share.axml");
1162 
1163 	XMLTree tree;
1164 	tree.set_root (node);
1165 	return tree.write (sn.c_str());
1166 }
1167 
1168 static void
merge_all_sources(boost::shared_ptr<const Playlist> pl,std::set<boost::shared_ptr<Source>> * all_sources)1169 merge_all_sources (boost::shared_ptr<const Playlist> pl, std::set<boost::shared_ptr<Source> >* all_sources)
1170 {
1171 	pl->deep_sources (*all_sources);
1172 }
1173 
1174 namespace
1175 {
1176 struct route_id_compare {
1177 	bool
operator ()__anon16706f6d0111::route_id_compare1178 	operator() (const boost::shared_ptr<Route>& r1, const boost::shared_ptr<Route>& r2)
1179 	{
1180 		return r1->id () < r2->id ();
1181 	}
1182 };
1183 } // anon namespace
1184 
1185 XMLNode&
state(bool save_template,snapshot_t snapshot_type,bool only_used_assets)1186 Session::state (bool save_template, snapshot_t snapshot_type, bool only_used_assets)
1187 {
1188 	LocaleGuard lg;
1189 	XMLNode* node = new XMLNode("Session");
1190 	XMLNode* child;
1191 
1192 	PBD::Unwinder<bool> uw (Automatable::skip_saving_automation, save_template);
1193 
1194 	node->set_property("version", CURRENT_SESSION_FILE_VERSION);
1195 
1196 	child = node->add_child ("ProgramVersion");
1197 	child->set_property("created-with", created_with);
1198 
1199 	std::string modified_with = string_compose ("%1 %2", PROGRAM_NAME, revision);
1200 	child->set_property("modified-with", modified_with);
1201 
1202 	/* store configuration settings */
1203 
1204 	if (!save_template) {
1205 
1206 		node->set_property ("name", _name);
1207 		node->set_property ("sample-rate", _base_sample_rate);
1208 
1209 		/* store the last engine device we we can avoid autostarting on a different device with wrong i/o count */
1210 		boost::shared_ptr<AudioBackend> backend = _engine.current_backend();
1211 		if (_engine.running () && backend && _engine.setup_required ()) {
1212 			child = node->add_child ("EngineHints");
1213 			child->set_property ("backend", backend-> name ());
1214 			if (backend->use_separate_input_and_output_devices()) {
1215 				child->set_property ("input-device", backend->input_device_name ());
1216 				child->set_property ("output-device", backend->output_device_name ());
1217 			} else {
1218 				child->set_property ("input-device", backend->device_name ());
1219 				child->set_property ("output-device", backend->device_name ());
1220 			}
1221 		}
1222 
1223 		if (session_dirs.size() > 1) {
1224 
1225 			string p;
1226 
1227 			vector<space_and_path>::iterator i = session_dirs.begin();
1228 			vector<space_and_path>::iterator next;
1229 
1230 			++i; /* skip the first one */
1231 			next = i;
1232 			++next;
1233 
1234 			while (i != session_dirs.end()) {
1235 
1236 				p += (*i).path;
1237 
1238 				if (next != session_dirs.end()) {
1239 					p += G_SEARCHPATH_SEPARATOR;
1240 				} else {
1241 					break;
1242 				}
1243 
1244 				++next;
1245 				++i;
1246 			}
1247 
1248 			child = node->add_child ("Path");
1249 			child->add_content (p);
1250 		}
1251 		node->set_property ("end-is-free", _session_range_is_free);  //deprecated, but keep storing this value for compatibility with prior v5.
1252 		node->set_property ("session-range-is-free", _session_range_is_free);
1253 	}
1254 
1255 	/* save the ID counter */
1256 
1257 	node->set_property ("id-counter", ID::counter());
1258 
1259 	node->set_property ("name-counter", name_id_counter ());
1260 
1261 	/* save the event ID counter */
1262 
1263 	node->set_property ("event-counter", Evoral::event_id_counter());
1264 
1265 	/* save the VCA counter */
1266 
1267 	node->set_property ("vca-counter", VCA::get_next_vca_number());
1268 
1269 	/* various options */
1270 
1271 	list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1272 	if (!midi_port_nodes.empty()) {
1273 		XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1274 		for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1275 			midi_port_stuff->add_child_nocopy (**n);
1276 		}
1277 		node->add_child_nocopy (*midi_port_stuff);
1278 	}
1279 
1280 	XMLNode& cfgxml (config.get_variables ());
1281 	if (save_template) {
1282 		/* exclude search-paths from template */
1283 		cfgxml.remove_nodes_and_delete ("name", "audio-search-path");
1284 		cfgxml.remove_nodes_and_delete ("name", "midi-search-path");
1285 		cfgxml.remove_nodes_and_delete ("name", "raid-path");
1286 	}
1287 	node->add_child_nocopy (cfgxml);
1288 
1289 	node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1290 
1291 	child = node->add_child ("Sources");
1292 
1293 	if (!save_template) {
1294 		Glib::Threads::Mutex::Lock sl (source_lock);
1295 
1296 		set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
1297 
1298 		if (only_used_assets) {
1299 			_playlists->sync_all_regions_with_regions ();
1300 			_playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot), false);
1301 		}
1302 
1303 		for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1304 
1305 			/* Don't save information about non-file Sources, or
1306 			 * about file sources that are empty
1307 			 * and unused by any regions.
1308 			 */
1309 			boost::shared_ptr<FileSource> fs;
1310 
1311 			if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) == 0) {
1312 				continue;
1313 			}
1314 
1315 			if (fs->empty() && !fs->used()) {
1316 				continue;
1317 			}
1318 
1319 			if (only_used_assets) {
1320 				/* skip only unused audio files */
1321 				boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (fs);
1322 				if (afs && !afs->used()) {
1323 					continue;
1324 				}
1325 				if (afs && sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
1326 					continue;
1327 				}
1328 			}
1329 
1330 			if (snapshot_type != NormalSave && fs->within_session ()) {
1331 				/* copy MIDI sources to new file
1332 				 *
1333 				 * We cannot replace the midi-source and MidiRegion::clobber_sources,
1334 				 * because the GUI (midi_region) has a direct pointer to the midi-model
1335 				 * of the source, as does UndoTransaction.
1336 				 *
1337 				 * On the upside, .mid files are not kept open. The file is only open
1338 				 * when reading the model initially and when flushing the model to disk:
1339 				 * source->session_saved () or export.
1340 				 *
1341 				 * We can change the _path of the existing source under the hood, keeping
1342 				 * all IDs, references and pointers intact.
1343 				 * */
1344 				boost::shared_ptr<SMFSource> ms;
1345 				if ((ms = boost::dynamic_pointer_cast<SMFSource> (siter->second)) != 0) {
1346 					const std::string ancestor_name = ms->ancestor_name();
1347 					const std::string base          = PBD::basename_nosuffix(ancestor_name);
1348 					const string path               = new_midi_source_path (base, false);
1349 
1350 					/* Session::save_state() will already have called
1351 					 * ms->session_saved ();
1352 					 */
1353 
1354 					/* use SMF-API to clone data (use the midi_model, not data on disk) */
1355 					boost::shared_ptr<SMFSource> newsrc (new SMFSource (*this, path, ms->flags()));
1356 					Source::Lock lm (ms->mutex());
1357 
1358 					if (!ms->model()) {
1359 						ms->load_model (lm);
1360 					}
1361 					/* write_to() calls newsrc->flush_midi () to write the file to disk */
1362 					if (ms->write_to (lm, newsrc, Temporal::Beats(), std::numeric_limits<Temporal::Beats>::max())) {
1363 						error << string_compose (_("Session-Save: Failed to copy MIDI Source '%1' for snapshot"), ancestor_name) << endmsg;
1364 					} else {
1365 						newsrc->session_saved (); /*< this sohuld be a no-op */
1366 
1367 						if (snapshot_type == SnapshotKeep) {
1368 							/* keep working on current session.
1369 							 *
1370 							 * Save snapshot-state with the original filename.
1371 							 * Switch to use new path for future saves of the main session.
1372 							 */
1373 							child->add_child_nocopy (ms->get_state());
1374 						}
1375 
1376 						/* swap file-paths.
1377 						 * ~SMFSource unlinks removable() files.
1378 						 */
1379 						std::string npath (ms->path ());
1380 						ms->replace_file (newsrc->path ());
1381 						newsrc->replace_file (npath);
1382 
1383 						if (snapshot_type == SwitchToSnapshot) {
1384 							/* save and switch to snapshot.
1385 							 *
1386 							 * Leave the old file in place (as is).
1387 							 * Snapshot uses new source directly
1388 							 */
1389 							child->add_child_nocopy (ms->get_state());
1390 						}
1391 					}
1392 					continue;
1393 				}
1394 			}
1395 			child->add_child_nocopy (siter->second->get_state());
1396 		}
1397 	}
1398 
1399 	child = node->add_child ("Regions");
1400 
1401 	if (!save_template) {
1402 		Glib::Threads::Mutex::Lock rl (region_lock);
1403 
1404 		if (!only_used_assets) {
1405 			const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1406 			for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1407 				boost::shared_ptr<Region> r = i->second;
1408 				/* regions must have sources */
1409 				assert (r->sources().size() > 0 && r->master_sources().size() > 0);
1410 				/* only store regions not attached to playlists */
1411 				if (r->playlist() == 0) {
1412 					if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1413 						child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1414 					} else {
1415 						child->add_child_nocopy (r->get_state ());
1416 					}
1417 				}
1418 			}
1419 		}
1420 
1421 		RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1422 
1423 		if (!cassocs.empty()) {
1424 			XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1425 
1426 			for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1427 				if (i->first->playlist () == 0 && only_used_assets) {
1428 					continue;
1429 				}
1430 				XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1431 				can->set_property (X_("copy"), i->first->id());
1432 				can->set_property (X_("original"), i->second->id());
1433 				ca->add_child_nocopy (*can);
1434 				/* see above, child is still "Regions" here  */
1435 				if (i->second->playlist() == 0 && only_used_assets) {
1436 					if (boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>( i->second)) {
1437 						child->add_child_nocopy (ar->get_basic_state ());
1438 					} else {
1439 						child->add_child_nocopy (ar->get_state ());
1440 					}
1441 				}
1442 			}
1443 		}
1444 	}
1445 
1446 	if (!save_template) {
1447 
1448 		node->add_child_nocopy (_selection->get_state());
1449 
1450 		if (_locations) {
1451 			node->add_child_nocopy (_locations->get_state());
1452 		}
1453 	} else {
1454 		Locations loc (*this);
1455 		const bool was_dirty = dirty();
1456 		// for a template, just create a new Locations, populate it
1457 		// with the default start and end, and get the state for that.
1458 		Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange, 0);
1459 		range->set (max_samplepos, 0);
1460 		loc.add (range);
1461 		XMLNode& locations_state = loc.get_state();
1462 
1463 		node->add_child_nocopy (locations_state);
1464 
1465 		/* adding a location above will have marked the session
1466 		 * dirty. This is an artifact, so fix it if the session wasn't
1467 		 * already dirty
1468 		 */
1469 
1470 		if (!was_dirty) {
1471 			unset_dirty ();
1472 		}
1473 	}
1474 
1475 	child = node->add_child ("Bundles");
1476 	{
1477 		boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1478 		for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1479 			boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1480 			if (b) {
1481 				child->add_child_nocopy (b->get_state());
1482 			}
1483 		}
1484 	}
1485 
1486 	node->add_child_nocopy (_vca_manager->get_state());
1487 
1488 	child = node->add_child ("Routes");
1489 	{
1490 		boost::shared_ptr<RouteList> r = routes.reader ();
1491 
1492 		route_id_compare cmp;
1493 		RouteList xml_node_order (*r);
1494 		xml_node_order.sort (cmp);
1495 
1496 		for (RouteList::const_iterator i = xml_node_order.begin(); i != xml_node_order.end(); ++i) {
1497 			if (!(*i)->is_auditioner()) {
1498 				if (save_template) {
1499 					child->add_child_nocopy ((*i)->get_template());
1500 				} else {
1501 					child->add_child_nocopy ((*i)->get_state());
1502 				}
1503 			}
1504 		}
1505 	}
1506 
1507 	_playlists->add_state (node, save_template, !only_used_assets);
1508 
1509 	child = node->add_child ("RouteGroups");
1510 	for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1511 		child->add_child_nocopy ((*i)->get_state());
1512 	}
1513 
1514 	if (_click_io) {
1515 		XMLNode* gain_child = node->add_child ("Click");
1516 		gain_child->add_child_nocopy (_click_io->get_state ());
1517 		gain_child->add_child_nocopy (_click_gain->get_state ());
1518 	}
1519 
1520 	node->add_child_nocopy (_speakers->get_state());
1521 	node->add_child_nocopy (_tempo_map->get_state());
1522 	node->add_child_nocopy (get_control_protocol_state());
1523 
1524 	if (_extra_xml) {
1525 		node->add_child_copy (*_extra_xml);
1526 	}
1527 
1528 	{
1529 		Glib::Threads::Mutex::Lock lm (lua_lock);
1530 		std::string saved;
1531 		{
1532 			luabridge::LuaRef savedstate ((*_lua_save)());
1533 			saved = savedstate.cast<std::string>();
1534 		}
1535 		lua.collect_garbage ();
1536 		lm.release ();
1537 
1538 		gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1539 		std::string b64s (b64);
1540 		g_free (b64);
1541 
1542 		XMLNode* script_node = new XMLNode (X_("Script"));
1543 		script_node->set_property (X_("lua"), LUA_VERSION);
1544 		script_node->add_content (b64s);
1545 		node->add_child_nocopy (*script_node);
1546 	}
1547 
1548 	return *node;
1549 }
1550 
1551 XMLNode&
get_control_protocol_state()1552 Session::get_control_protocol_state ()
1553 {
1554 	return ControlProtocolManager::instance().get_state ();
1555 }
1556 
1557 int
set_state(const XMLNode & node,int version)1558 Session::set_state (const XMLNode& node, int version)
1559 {
1560 	LocaleGuard lg;
1561 	XMLNodeList nlist;
1562 	XMLNode* child;
1563 	int ret = -1;
1564 
1565 	_state_of_the_state = StateOfTheState (_state_of_the_state | CannotSave);
1566 
1567 	if (node.name() != X_("Session")) {
1568 		fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1569 		goto out;
1570 	}
1571 
1572 	node.get_property ("name", _name);
1573 
1574 	if (node.get_property (X_("sample-rate"), _base_sample_rate)) {
1575 
1576 		_nominal_sample_rate = _base_sample_rate;
1577 
1578 		assert (AudioEngine::instance()->running ());
1579 		if (_base_sample_rate != AudioEngine::instance()->sample_rate ()) {
1580 			boost::optional<int> r = AskAboutSampleRateMismatch (_base_sample_rate, _current_sample_rate);
1581 			if (r.value_or (0)) {
1582 				goto out;
1583 			}
1584 		}
1585 	}
1586 
1587 	created_with = "unknown";
1588 	if ((child = find_named_node (node, "ProgramVersion")) != 0) {
1589 		child->get_property (X_("created-with"), created_with);
1590 	}
1591 
1592 	setup_raid_path(_session_dir->root_path());
1593 
1594 	node.get_property (X_("end-is-free"), _session_range_is_free);  //deprectated, but use old values if they are in the config
1595 
1596 	node.get_property (X_("session-range-is-free"), _session_range_is_free);
1597 
1598 	uint64_t counter;
1599 	if (node.get_property (X_("id-counter"), counter)) {
1600 		ID::init_counter (counter);
1601 	} else {
1602 		/* old sessions used a timebased counter, so fake
1603 		 * the startup ID counter based on a standard
1604 		 * timestamp.
1605 		 */
1606 		time_t now;
1607 		time (&now);
1608 		ID::init_counter (now);
1609 	}
1610 
1611 	if (node.get_property (X_("name-counter"), counter)) {
1612 		init_name_id_counter (counter);
1613 	}
1614 
1615 	if (node.get_property (X_("event-counter"), counter)) {
1616 		Evoral::init_event_id_counter (counter);
1617 	}
1618 
1619 	if (node.get_property (X_("vca-counter"), counter)) {
1620 		VCA::set_next_vca_number (counter);
1621 	} else {
1622 		VCA::set_next_vca_number (1);
1623 	}
1624 
1625 	if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1626 		_midi_ports->set_midi_port_states (child->children());
1627 	}
1628 
1629 	IO::disable_connecting ();
1630 
1631 	Stateful::save_extra_xml (node);
1632 
1633 	if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1634 		load_options (*child);
1635 	} else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1636 		load_options (*child);
1637 	} else {
1638 		error << _("Session: XML state has no options section") << endmsg;
1639 	}
1640 
1641 	if (version >= 3000) {
1642 		if ((child = find_named_node (node, "Metadata")) == 0) {
1643 			warning << _("Session: XML state has no metadata section") << endmsg;
1644 		} else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1645 			goto out;
1646 		}
1647 	}
1648 
1649 	if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1650 		_speakers->set_state (*child, version);
1651 	}
1652 
1653 	if ((child = find_named_node (node, "Sources")) == 0) {
1654 		error << _("Session: XML state has no sources section") << endmsg;
1655 		goto out;
1656 	} else if (load_sources (*child)) {
1657 		goto out;
1658 	}
1659 
1660 	if ((child = find_named_node (node, "TempoMap")) == 0) {
1661 		error << _("Session: XML state has no Tempo Map section") << endmsg;
1662 		goto out;
1663 	} else if (_tempo_map->set_state (*child, version)) {
1664 		goto out;
1665 	}
1666 
1667 	if ((child = find_named_node (node, "Locations")) == 0) {
1668 		error << _("Session: XML state has no locations section") << endmsg;
1669 		goto out;
1670 	} else if (_locations->set_state (*child, version)) {
1671 		goto out;
1672 	}
1673 
1674 	locations_changed ();
1675 
1676 	if (_session_range_location) {
1677 		AudioFileSource::set_header_position_offset (_session_range_location->start());
1678 	}
1679 
1680 	if ((child = find_named_node (node, "Regions")) == 0) {
1681 		error << _("Session: XML state has no Regions section") << endmsg;
1682 		goto out;
1683 	} else if (load_regions (*child)) {
1684 		goto out;
1685 	}
1686 
1687 	if ((child = find_named_node (node, "Playlists")) == 0) {
1688 		error << _("Session: XML state has no playlists section") << endmsg;
1689 		goto out;
1690 	} else if (_playlists->load (*this, *child)) {
1691 		goto out;
1692 	}
1693 
1694 	if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1695 		// this is OK
1696 	} else if (_playlists->load_unused (*this, *child)) {
1697 		goto out;
1698 	}
1699 
1700 	if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1701 		if (load_compounds (*child)) {
1702 			goto out;
1703 		}
1704 	}
1705 
1706 	if (version >= 3000) {
1707 		if ((child = find_named_node (node, "Bundles")) == 0) {
1708 			warning << _("Session: XML state has no bundles section") << endmsg;
1709 			//goto out;
1710 		} else {
1711 			/* We can't load Bundles yet as they need to be able
1712 			 * to convert from port names to Port objects, which can't happen until
1713 			 * later */
1714 			_bundle_xml_node = new XMLNode (*child);
1715 		}
1716 	}
1717 
1718 	if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
1719 		_vca_manager->set_state (*child, version);
1720 	}
1721 
1722 	if (version < 3000) {
1723 		if ((child = find_named_node (node, "DiskStreams"))) {
1724 			for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1725 				if ((*n)->name() == "AudioDiskstream" || (*n)->name() == "DiskStream") {
1726 					std::string diskstream_id;
1727 					std::string playlist_name;
1728 					if ((*n)->get_property ("playlist", playlist_name) && (*n)->get_property ("id", diskstream_id)) {
1729 						_diskstreams_2X [PBD::ID(diskstream_id)] = playlist_name;
1730 					}
1731 				}
1732 			}
1733 		}
1734 	}
1735 
1736 	if ((child = find_named_node (node, "Routes")) == 0) {
1737 		error << _("Session: XML state has no routes section") << endmsg;
1738 		goto out;
1739 	} else if (load_routes (*child, version)) {
1740 		goto out;
1741 	}
1742 
1743 	/* Now that we Tracks have been loaded and playlists are assigned */
1744 	_playlists->update_tracking ();
1745 
1746 	_diskstreams_2X.clear ();
1747 
1748 	/* Now that we have Routes and masters loaded, connect them if appropriate */
1749 
1750 	Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
1751 
1752 	if (version >= 3000) {
1753 
1754 		if ((child = find_named_node (node, "RouteGroups")) == 0) {
1755 			error << _("Session: XML state has no route groups section") << endmsg;
1756 			goto out;
1757 		} else if (load_route_groups (*child, version)) {
1758 			goto out;
1759 		}
1760 
1761 	} else if (version < 3000) {
1762 
1763 		if ((child = find_named_node (node, "EditGroups")) == 0) {
1764 			error << _("Session: XML state has no edit groups section") << endmsg;
1765 			goto out;
1766 		} else if (load_route_groups (*child, version)) {
1767 			goto out;
1768 		}
1769 
1770 		if ((child = find_named_node (node, "MixGroups")) == 0) {
1771 			error << _("Session: XML state has no mix groups section") << endmsg;
1772 			goto out;
1773 		} else if (load_route_groups (*child, version)) {
1774 			goto out;
1775 		}
1776 	}
1777 
1778 	if ((child = find_named_node (node, "Click")) == 0) {
1779 		warning << _("Session: XML state has no click section") << endmsg;
1780 	} else if (_click_io) {
1781 		setup_click_state (&node);
1782 	}
1783 
1784 	if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1785 		ControlProtocolManager::instance().set_state (*child, 1 /* here: session-specific state */);
1786 	}
1787 
1788 	if ((child = find_named_node (node, "Script"))) {
1789 		for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1790 			if (!(*n)->is_content ()) { continue; }
1791 			gsize size;
1792 			guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1793 			try {
1794 				Glib::Threads::Mutex::Lock lm (lua_lock);
1795 				(*_lua_load)(std::string ((const char*)buf, size));
1796 			} catch (luabridge::LuaException const& e) {
1797 #ifndef NDEBUG
1798 				cerr << "LuaException:" << e.what () << endl;
1799 #endif
1800 				warning << "LuaException: " << e.what () << endmsg;
1801 			} catch (...) { }
1802 			g_free (buf);
1803 		}
1804 	}
1805 
1806 	if ((child = find_named_node (node, X_("Selection")))) {
1807 		_selection->set_state (*child, version);
1808 	}
1809 
1810 	update_route_record_state ();
1811 
1812 	/* here beginneth the second phase ... */
1813 	set_snapshot_name (_current_snapshot_name);
1814 
1815 	StateReady (); /* EMIT SIGNAL */
1816 
1817 	delete state_tree;
1818 	state_tree = 0;
1819 	return 0;
1820 
1821 out:
1822 	delete state_tree;
1823 	state_tree = 0;
1824 	return ret;
1825 }
1826 
1827 int
load_routes(const XMLNode & node,int version)1828 Session::load_routes (const XMLNode& node, int version)
1829 {
1830 	XMLNodeList nlist;
1831 	XMLNodeConstIterator niter;
1832 	RouteList new_routes;
1833 
1834 	nlist = node.children();
1835 
1836 	set_dirty();
1837 
1838 	for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1839 
1840 		boost::shared_ptr<Route> route;
1841 
1842 		if (version < 3000) {
1843 			route = XMLRouteFactory_2X (**niter, version);
1844 		} else if (version < 5000) {
1845 			route = XMLRouteFactory_3X (**niter, version);
1846 		} else {
1847 			route = XMLRouteFactory (**niter, version);
1848 		}
1849 
1850 		if (route == 0) {
1851 			error << _("Session: cannot create track/bus from XML description.") << endmsg;
1852 			return -1;
1853 		}
1854 
1855 		BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1856 
1857 		new_routes.push_back (route);
1858 	}
1859 
1860 	BootMessage (_("Tracks/busses loaded;  Adding to Session"));
1861 
1862 	add_routes (new_routes, false, false, PresentationInfo::max_order);
1863 
1864 	/* re-subscribe to MIDI connection handler */
1865 	for (RouteList::iterator r = new_routes.begin(); r != new_routes.end(); ++r) {
1866 		boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (*r);
1867 		bool is_midi_route = (*r)->n_inputs().n_midi() > 0 && (*r)->n_inputs().n_midi() > 0;
1868 		if (mt || is_midi_route) {
1869 			(*r)->output()->changed.connect_same_thread (*this, boost::bind (&Session::midi_output_change_handler, this, _1, _2, boost::weak_ptr<Route>(*r)));
1870 		}
1871 	}
1872 
1873 
1874 	BootMessage (_("Finished adding tracks/busses"));
1875 
1876 	return 0;
1877 }
1878 
1879 boost::shared_ptr<Route>
XMLRouteFactory(const XMLNode & node,int version)1880 Session::XMLRouteFactory (const XMLNode& node, int version)
1881 {
1882 	boost::shared_ptr<Route> ret;
1883 
1884 	if (node.name() != "Route") {
1885 		return ret;
1886 	}
1887 
1888 	XMLProperty const * pl_prop = node.property (X_("audio-playlist"));
1889 
1890 	if (!pl_prop) {
1891 		pl_prop = node.property (X_("midi-playlist"));
1892 	}
1893 
1894 	DataType type = DataType::AUDIO;
1895 	node.get_property("default-type", type);
1896 
1897 	assert (type != DataType::NIL);
1898 
1899 	if (pl_prop) {
1900 
1901 		/* has at least 1 playlist, therefore a track ... */
1902 
1903 		boost::shared_ptr<Track> track;
1904 
1905 		if (type == DataType::AUDIO) {
1906 			track.reset (new AudioTrack (*this));
1907 		} else {
1908 			track.reset (new MidiTrack (*this));
1909 		}
1910 
1911 		if (track->init()) {
1912 			return ret;
1913 		}
1914 
1915 		if (track->set_state (node, version)) {
1916 			return ret;
1917 		}
1918 
1919 		BOOST_MARK_TRACK (track);
1920 		ret = track;
1921 
1922 	} else {
1923 		PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1924 		boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1925 
1926 		if (r->init () == 0 && r->set_state (node, version) == 0) {
1927 			BOOST_MARK_ROUTE (r);
1928 			ret = r;
1929 		}
1930 	}
1931 
1932 	return ret;
1933 }
1934 
1935 boost::shared_ptr<Route>
XMLRouteFactory_3X(const XMLNode & node,int version)1936 Session::XMLRouteFactory_3X (const XMLNode& node, int version)
1937 {
1938 	boost::shared_ptr<Route> ret;
1939 
1940 	if (node.name() != "Route") {
1941 		return ret;
1942 	}
1943 
1944 	XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1945 
1946 	DataType type = DataType::AUDIO;
1947 	node.get_property("default-type", type);
1948 
1949 	assert (type != DataType::NIL);
1950 
1951 	if (ds_child) {
1952 
1953 		boost::shared_ptr<Track> track;
1954 
1955 		if (type == DataType::AUDIO) {
1956 			track.reset (new AudioTrack (*this));
1957 		} else {
1958 			track.reset (new MidiTrack (*this));
1959 		}
1960 
1961 		if (track->init()) {
1962 			return ret;
1963 		}
1964 
1965 		if (track->set_state (node, version)) {
1966 			return ret;
1967 		}
1968 
1969 		BOOST_MARK_TRACK (track);
1970 		ret = track;
1971 
1972 	} else {
1973 		PresentationInfo::Flag flags = PresentationInfo::get_flags2X3X (node);
1974 		boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1975 
1976 		if (r->init () == 0 && r->set_state (node, version) == 0) {
1977 			BOOST_MARK_ROUTE (r);
1978 			ret = r;
1979 		}
1980 	}
1981 
1982 	return ret;
1983 }
1984 
1985 boost::shared_ptr<Route>
XMLRouteFactory_2X(const XMLNode & node,int version)1986 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1987 {
1988 	boost::shared_ptr<Route> ret;
1989 
1990 	if (node.name() != "Route") {
1991 		return ret;
1992 	}
1993 
1994 	XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1995 	if (!ds_prop) {
1996 		ds_prop = node.property (X_("diskstream"));
1997 	}
1998 
1999 	DataType type = DataType::AUDIO;
2000 	node.get_property("default-type", type);
2001 
2002 	assert (type != DataType::NIL);
2003 
2004 	if (ds_prop) {
2005 
2006 		PBD::ID ds_id (ds_prop->value ());
2007 		std::string playlist_name = _diskstreams_2X[ds_id];
2008 
2009 		boost::shared_ptr<Playlist> pl = playlists()->by_name (playlist_name);
2010 
2011 		if (playlist_name.empty () || !pl) {
2012 			warning << string_compose (_("Could not find diskstream for diskstream-id: '%1', playlist: '%2'"), ds_prop->value (), playlist_name) << endmsg;
2013 		}
2014 
2015 		boost::shared_ptr<Track> track;
2016 
2017 		if (type == DataType::AUDIO) {
2018 			track.reset (new AudioTrack (*this));
2019 		} else {
2020 			track.reset (new MidiTrack (*this));
2021 		}
2022 
2023 		if (track->init()) {
2024 			return ret;
2025 		}
2026 
2027 		if (pl) {
2028 			track->use_playlist (DataType::AUDIO, pl);
2029 		} else {
2030 			track->use_new_playlist (DataType::AUDIO);
2031 		}
2032 
2033 		if (track->set_state (node, version)) {
2034 			return ret;
2035 		}
2036 
2037 		if (pl) {
2038 			pl->set_orig_track_id (track->id());
2039 			playlists()->update_orig_2X (ds_id, track->id());
2040 		}
2041 
2042 		BOOST_MARK_TRACK (track);
2043 		ret = track;
2044 
2045 	} else {
2046 		PresentationInfo::Flag flags = PresentationInfo::get_flags2X3X (node);
2047 		boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
2048 
2049 		if (r->init () == 0 && r->set_state (node, version) == 0) {
2050 			BOOST_MARK_ROUTE (r);
2051 			ret = r;
2052 		}
2053 	}
2054 
2055 	return ret;
2056 }
2057 
2058 int
load_regions(const XMLNode & node)2059 Session::load_regions (const XMLNode& node)
2060 {
2061 	XMLNodeList nlist;
2062 	XMLNodeConstIterator niter;
2063 	boost::shared_ptr<Region> region;
2064 
2065 	nlist = node.children();
2066 
2067 	set_dirty();
2068 
2069 	for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2070 		if ((region = XMLRegionFactory (**niter, false)) == 0) {
2071 			error << _("Session: cannot create Region from XML description.");
2072 			XMLProperty const * name = (**niter).property("name");
2073 
2074 			if (name) {
2075 				error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
2076 			}
2077 
2078 			error << endmsg;
2079 		}
2080 	}
2081 
2082 	return 0;
2083 }
2084 
2085 int
load_compounds(const XMLNode & node)2086 Session::load_compounds (const XMLNode& node)
2087 {
2088 	XMLNodeList calist = node.children();
2089 	XMLNodeConstIterator caiter;
2090 	XMLProperty const * caprop;
2091 
2092 	for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
2093 		XMLNode* ca = *caiter;
2094 		ID orig_id;
2095 		ID copy_id;
2096 
2097 		if ((caprop = ca->property (X_("original"))) == 0) {
2098 			continue;
2099 		}
2100 		orig_id = caprop->value();
2101 
2102 		if ((caprop = ca->property (X_("copy"))) == 0) {
2103 			continue;
2104 		}
2105 		copy_id = caprop->value();
2106 
2107 		boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
2108 		boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
2109 
2110 		if (!orig || !copy) {
2111 			warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
2112 						   orig_id, copy_id)
2113 				<< endmsg;
2114 			continue;
2115 		}
2116 
2117 		RegionFactory::add_compound_association (orig, copy);
2118 	}
2119 
2120 	return 0;
2121 }
2122 
2123 void
load_nested_sources(const XMLNode & node)2124 Session::load_nested_sources (const XMLNode& node)
2125 {
2126 	XMLNodeList nlist;
2127 	XMLNodeConstIterator niter;
2128 
2129 	nlist = node.children();
2130 
2131 	for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2132 		if ((*niter)->name() == "Source") {
2133 
2134 			/* it may already exist, so don't recreate it unnecessarily
2135 			 */
2136 
2137 			XMLProperty const * prop = (*niter)->property (X_("id"));
2138 			if (!prop) {
2139 				error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
2140 				continue;
2141 			}
2142 
2143 			ID source_id (prop->value());
2144 
2145 			if (!source_by_id (source_id)) {
2146 
2147 				try {
2148 					SourceFactory::create (*this, **niter, true);
2149 				}
2150 				catch (failed_constructor& err) {
2151 					error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
2152 				}
2153 			}
2154 		}
2155 	}
2156 }
2157 
2158 boost::shared_ptr<Region>
XMLRegionFactory(const XMLNode & node,bool full)2159 Session::XMLRegionFactory (const XMLNode& node, bool full)
2160 {
2161 	XMLProperty const * type = node.property("type");
2162 
2163 	try {
2164 
2165 		const XMLNodeList& nlist = node.children();
2166 
2167 		for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
2168 			XMLNode *child = (*niter);
2169 			if (child->name() == "NestedSource") {
2170 				load_nested_sources (*child);
2171 			}
2172 		}
2173 
2174 		if (!type || type->value() == "audio") {
2175 			return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
2176 		} else if (type->value() == "midi") {
2177 			return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
2178 		}
2179 
2180 	} catch (failed_constructor& err) {
2181 		return boost::shared_ptr<Region> ();
2182 	}
2183 
2184 	return boost::shared_ptr<Region> ();
2185 }
2186 
2187 boost::shared_ptr<AudioRegion>
XMLAudioRegionFactory(const XMLNode & node,bool)2188 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
2189 {
2190 	XMLProperty const * prop;
2191 	boost::shared_ptr<Source> source;
2192 	boost::shared_ptr<AudioSource> as;
2193 	SourceList sources;
2194 	SourceList master_sources;
2195 	uint32_t nchans = 1;
2196 	char buf[128];
2197 
2198 	if (node.name() != X_("Region")) {
2199 		return boost::shared_ptr<AudioRegion>();
2200 	}
2201 
2202 	node.get_property (X_("channels"), nchans);
2203 
2204 	if ((prop = node.property ("name")) == 0) {
2205 		cerr << "no name for this region\n";
2206 		abort ();
2207 	}
2208 
2209 	if ((prop = node.property (X_("source-0"))) == 0) {
2210 		if ((prop = node.property ("source")) == 0) {
2211 			error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
2212 			return boost::shared_ptr<AudioRegion>();
2213 		}
2214 	}
2215 
2216 	PBD::ID s_id (prop->value());
2217 
2218 	if ((source = source_by_id (s_id)) == 0) {
2219 		error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
2220 		return boost::shared_ptr<AudioRegion>();
2221 	}
2222 
2223 	as = boost::dynamic_pointer_cast<AudioSource>(source);
2224 	if (!as) {
2225 		error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
2226 		return boost::shared_ptr<AudioRegion>();
2227 	}
2228 
2229 	sources.push_back (as);
2230 
2231 	/* pickup other channels */
2232 
2233 	for (uint32_t n=1; n < nchans; ++n) {
2234 		snprintf (buf, sizeof(buf), X_("source-%d"), n);
2235 		if ((prop = node.property (buf)) != 0) {
2236 
2237 			PBD::ID id2 (prop->value());
2238 
2239 			if ((source = source_by_id (id2)) == 0) {
2240 				error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
2241 				return boost::shared_ptr<AudioRegion>();
2242 			}
2243 
2244 			as = boost::dynamic_pointer_cast<AudioSource>(source);
2245 			if (!as) {
2246 				error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
2247 				return boost::shared_ptr<AudioRegion>();
2248 			}
2249 			sources.push_back (as);
2250 		}
2251 	}
2252 
2253 	for (uint32_t n = 0; n < nchans; ++n) {
2254 		snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
2255 		if ((prop = node.property (buf)) != 0) {
2256 
2257 			PBD::ID id2 (prop->value());
2258 
2259 			if ((source = source_by_id (id2)) == 0) {
2260 				error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
2261 				return boost::shared_ptr<AudioRegion>();
2262 			}
2263 
2264 			as = boost::dynamic_pointer_cast<AudioSource>(source);
2265 			if (!as) {
2266 				error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
2267 				return boost::shared_ptr<AudioRegion>();
2268 			}
2269 			master_sources.push_back (as);
2270 		}
2271 	}
2272 
2273 	try {
2274 		boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
2275 
2276 		/* a final detail: this is the one and only place that we know how long missing files are */
2277 
2278 		if (region->whole_file()) {
2279 			for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2280 				boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2281 				if (sfp) {
2282 					sfp->set_length (region->length());
2283 				}
2284 			}
2285 		}
2286 
2287 		if (!master_sources.empty()) {
2288 			if (master_sources.size() != nchans) {
2289 				error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
2290 			} else {
2291 				region->set_master_sources (master_sources);
2292 			}
2293 		}
2294 
2295 		return region;
2296 
2297 	}
2298 
2299 	catch (failed_constructor& err) {
2300 		return boost::shared_ptr<AudioRegion>();
2301 	}
2302 }
2303 
2304 boost::shared_ptr<MidiRegion>
XMLMidiRegionFactory(const XMLNode & node,bool)2305 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
2306 {
2307 	XMLProperty const * prop;
2308 	boost::shared_ptr<Source> source;
2309 	boost::shared_ptr<MidiSource> ms;
2310 	SourceList sources;
2311 
2312 	if (node.name() != X_("Region")) {
2313 		return boost::shared_ptr<MidiRegion>();
2314 	}
2315 
2316 	if ((prop = node.property ("name")) == 0) {
2317 		cerr << "no name for this region\n";
2318 		abort ();
2319 	}
2320 
2321 	if ((prop = node.property (X_("source-0"))) == 0) {
2322 		if ((prop = node.property ("source")) == 0) {
2323 			error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
2324 			return boost::shared_ptr<MidiRegion>();
2325 		}
2326 	}
2327 
2328 	PBD::ID s_id (prop->value());
2329 
2330 	if ((source = source_by_id (s_id)) == 0) {
2331 		error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2332 		return boost::shared_ptr<MidiRegion>();
2333 	}
2334 
2335 	ms = boost::dynamic_pointer_cast<MidiSource>(source);
2336 	if (!ms) {
2337 		error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2338 		return boost::shared_ptr<MidiRegion>();
2339 	}
2340 
2341 	sources.push_back (ms);
2342 
2343 	try {
2344 		boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2345 		/* a final detail: this is the one and only place that we know how long missing files are */
2346 
2347 		if (region->whole_file()) {
2348 			for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2349 				boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2350 				if (sfp) {
2351 					sfp->set_length (region->length());
2352 				}
2353 			}
2354 		}
2355 
2356 		return region;
2357 	}
2358 
2359 	catch (failed_constructor& err) {
2360 		return boost::shared_ptr<MidiRegion>();
2361 	}
2362 }
2363 
2364 XMLNode&
get_sources_as_xml()2365 Session::get_sources_as_xml ()
2366 
2367 {
2368 	XMLNode* node = new XMLNode (X_("Sources"));
2369 	Glib::Threads::Mutex::Lock lm (source_lock);
2370 
2371 	for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
2372 		node->add_child_nocopy (i->second->get_state());
2373 	}
2374 
2375 	return *node;
2376 }
2377 
2378 void
reset_write_sources(bool mark_write_complete,bool force)2379 Session::reset_write_sources (bool mark_write_complete, bool force)
2380 {
2381 	boost::shared_ptr<RouteList> rl = routes.reader();
2382 	for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2383 		boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2384 		if (tr) {
2385 			_state_of_the_state = StateOfTheState (_state_of_the_state | InCleanup);
2386 			tr->reset_write_sources(mark_write_complete, force);
2387 			_state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2388 		}
2389 	}
2390 }
2391 
2392 int
load_sources(const XMLNode & node)2393 Session::load_sources (const XMLNode& node)
2394 {
2395 	XMLNodeList nlist;
2396 	XMLNodeConstIterator niter;
2397 	/* don't need this but it stops some
2398 	 * versions of gcc complaining about
2399 	 * discarded return values.
2400 	 */
2401 	boost::shared_ptr<Source> source;
2402 
2403 	nlist = node.children();
2404 
2405 	set_dirty();
2406 	std::map<std::string, std::string> relocation;
2407 
2408 	for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2409 #ifdef PLATFORM_WINDOWS
2410 		int old_mode = 0;
2411 #endif
2412 
2413 		XMLNode srcnode (**niter);
2414 		bool try_replace_abspath = true;
2415 
2416 retry:
2417 		try {
2418 #ifdef PLATFORM_WINDOWS
2419 			// do not show "insert media" popups (files embedded from removable media).
2420 			old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
2421 #endif
2422 			if ((source = XMLSourceFactory (srcnode)) == 0) {
2423 				error << _("Session: cannot create Source from XML description.") << endmsg;
2424 			}
2425 #ifdef PLATFORM_WINDOWS
2426 			SetErrorMode(old_mode);
2427 #endif
2428 
2429 		} catch (MissingSource& err) {
2430 #ifdef PLATFORM_WINDOWS
2431 			SetErrorMode(old_mode);
2432 #endif
2433 
2434 			/* try previous abs path replacements first */
2435 			if (try_replace_abspath && Glib::path_is_absolute (err.path)) {
2436 				std::string dir = Glib::path_get_dirname (err.path);
2437 				std::map<std::string, std::string>::const_iterator rl = relocation.find (dir);
2438 				if (rl != relocation.end ()) {
2439 					std::string newpath = Glib::build_filename (rl->second, Glib::path_get_basename (err.path));
2440 					if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2441 						srcnode.set_property ("origin", newpath);
2442 						try_replace_abspath = false;
2443 						goto retry;
2444 					}
2445 				}
2446 			}
2447 
2448 			int user_choice;
2449 			_missing_file_replacement = "";
2450 
2451 			if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2452 				error << string_compose (_("An external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2453 						PROGRAM_NAME) << endmsg;
2454 				return -1;
2455 			}
2456 
2457 			if (!no_questions_about_missing_files) {
2458 				user_choice = MissingFile (this, err.path, err.type).value_or (-1);
2459 			} else {
2460 				user_choice = -2;
2461 			}
2462 
2463 			switch (user_choice) {
2464 				case 0:
2465 					/* user added a new search location
2466 					 * or selected a new absolute path,
2467 					 * so try again */
2468 					if (Glib::path_is_absolute (err.path)) {
2469 						if (!_missing_file_replacement.empty ()) {
2470 							/* replace origin, in XML */
2471 							std::string newpath = Glib::build_filename (
2472 									_missing_file_replacement, Glib::path_get_basename (err.path));
2473 							srcnode.set_property ("origin", newpath);
2474 							relocation[Glib::path_get_dirname (err.path)] = _missing_file_replacement;
2475 							_missing_file_replacement = "";
2476 						}
2477 					}
2478 					goto retry;
2479 
2480 
2481 				case 1:
2482 					/* user asked to quit the entire session load */
2483 					return -1;
2484 
2485 				case 2:
2486 					no_questions_about_missing_files = true;
2487 					goto retry;
2488 
2489 				case 3:
2490 					no_questions_about_missing_files = true;
2491 					/* fallthrough */
2492 
2493 				case -1:
2494 				default:
2495 					switch (err.type) {
2496 
2497 						case DataType::AUDIO:
2498 							source = SourceFactory::createSilent (*this, **niter, max_samplecnt, _current_sample_rate);
2499 							break;
2500 
2501 						case DataType::MIDI:
2502 							/* The MIDI file is actually missing so
2503 							 * just create a new one in the same
2504 							 * location. Do not announce its
2505 							 */
2506 							string fullpath;
2507 
2508 							if (!Glib::path_is_absolute (err.path)) {
2509 								fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2510 							} else {
2511 								/* this should be an unrecoverable error: we would be creating a MIDI file outside
2512 								 * the session tree.
2513 								 */
2514 								return -1;
2515 							}
2516 							/* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2517 							source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, _current_sample_rate, false, false);
2518 							/* reset ID to match the missing one */
2519 							source->set_id (**niter);
2520 							/* Now we can announce it */
2521 							SourceFactory::SourceCreated (source);
2522 							break;
2523 					}
2524 					break;
2525 			}
2526 		}
2527 	}
2528 
2529 	return 0;
2530 }
2531 
2532 boost::shared_ptr<Source>
XMLSourceFactory(const XMLNode & node)2533 Session::XMLSourceFactory (const XMLNode& node)
2534 {
2535 	if (node.name() != "Source") {
2536 		return boost::shared_ptr<Source>();
2537 	}
2538 
2539 	try {
2540 		/* note: do peak building in another thread when loading session state */
2541 		return SourceFactory::create (*this, node, true);
2542 	}
2543 
2544 	catch (failed_constructor& err) {
2545 		error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2546 		return boost::shared_ptr<Source>();
2547 	}
2548 }
2549 
2550 int
save_template(const string & template_name,const string & description,bool replace_existing)2551 Session::save_template (const string& template_name, const string& description, bool replace_existing)
2552 {
2553 	if (cannot_save () || template_name.empty ()) {
2554 		return -1;
2555 	}
2556 
2557 	bool absolute_path = Glib::path_is_absolute (template_name);
2558 
2559 	/* directory to put the template in */
2560 	std::string template_dir_path;
2561 
2562 	if (!absolute_path) {
2563 		std::string user_template_dir(user_template_directory());
2564 
2565 		if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2566 			error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2567 					user_template_dir, g_strerror (errno)) << endmsg;
2568 			return -1;
2569 		}
2570 
2571 		template_dir_path = Glib::build_filename (user_template_dir, template_name);
2572 	} else {
2573 		template_dir_path = template_name;
2574 	}
2575 
2576 	if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2577 		warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2578 		                          template_dir_path) << endmsg;
2579 		return -2;
2580 	}
2581 
2582 	if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2583 		error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2584 		                        template_dir_path, g_strerror (errno)) << endmsg;
2585 		return -1;
2586 	}
2587 
2588 	/* file to write */
2589 	std::string template_file_path;
2590 
2591 	if (absolute_path) {
2592 		template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2593 	} else {
2594 		template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2595 	}
2596 
2597 	SessionSaveUnderway (); /* EMIT SIGNAL */
2598 
2599 	XMLTree tree;
2600 	XMLNode* root;
2601 	{
2602 		PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2603 		root = &get_template ();
2604 	}
2605 
2606 	root->remove_nodes_and_delete (X_("description"));
2607 
2608 	if (!description.empty()) {
2609 		XMLNode* desc = new XMLNode (X_("description"));
2610 		XMLNode* desc_cont = new XMLNode (X_("content"), description);
2611 		desc->add_child_nocopy (*desc_cont);
2612 
2613 		root->add_child_nocopy (*desc);
2614 	}
2615 
2616 	tree.set_root (root);
2617 
2618 	if (!tree.write (template_file_path)) {
2619 		error << _("template not saved") << endmsg;
2620 		return -1;
2621 	}
2622 
2623 	store_recent_templates (template_file_path);
2624 
2625 	return 0;
2626 }
2627 
2628 void
refresh_disk_space()2629 Session::refresh_disk_space ()
2630 {
2631 #if __APPLE__ || __FreeBSD__ || __NetBSD__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2632 
2633 	Glib::Threads::Mutex::Lock lm (space_lock);
2634 
2635 	/* get freespace on every FS that is part of the session path */
2636 
2637 	_total_free_4k_blocks = 0;
2638 	_total_free_4k_blocks_uncertain = false;
2639 
2640 	for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2641 #if defined(__NetBSD__)
2642 		struct statvfs statfsbuf;
2643 
2644 		statvfs (i->path.c_str(), &statfsbuf);
2645 #else
2646 		struct statfs statfsbuf;
2647 
2648 		statfs (i->path.c_str(), &statfsbuf);
2649 #endif
2650 		double const scale = statfsbuf.f_bsize / 4096.0;
2651 
2652 		/* See if this filesystem is read-only */
2653 		struct statvfs statvfsbuf;
2654 		statvfs (i->path.c_str(), &statvfsbuf);
2655 
2656 		/* f_bavail can be 0 if it is undefined for whatever
2657 		   filesystem we are looking at; Samba shares mounted
2658 		   via GVFS are an example of this.
2659 		*/
2660 		if (statfsbuf.f_bavail == 0) {
2661 			/* block count unknown */
2662 			i->blocks = 0;
2663 			i->blocks_unknown = true;
2664 		} else if (statvfsbuf.f_flag & ST_RDONLY) {
2665 			/* read-only filesystem */
2666 			i->blocks = 0;
2667 			i->blocks_unknown = false;
2668 		} else {
2669 			/* read/write filesystem with known space */
2670 			i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2671 			i->blocks_unknown = false;
2672 		}
2673 
2674 		_total_free_4k_blocks += i->blocks;
2675 		if (i->blocks_unknown) {
2676 			_total_free_4k_blocks_uncertain = true;
2677 		}
2678 	}
2679 #elif defined PLATFORM_WINDOWS
2680 	vector<string> scanned_volumes;
2681 	vector<string>::iterator j;
2682 	vector<space_and_path>::iterator i;
2683 	DWORD nSectorsPerCluster, nBytesPerSector,
2684 	      nFreeClusters, nTotalClusters;
2685 	char disk_drive[4];
2686 	bool volume_found;
2687 
2688 	_total_free_4k_blocks = 0;
2689 
2690 	for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2691 		strncpy (disk_drive, (*i).path.c_str(), 3);
2692 		disk_drive[3] = 0;
2693 		strupr(disk_drive);
2694 
2695 		volume_found = false;
2696 		if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2697 		{
2698 			int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2699 			int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2700 			i->blocks = (uint32_t)(nFreeBytes / 4096);
2701 
2702 			for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2703 				if (0 == j->compare(disk_drive)) {
2704 					volume_found = true;
2705 					break;
2706 				}
2707 			}
2708 
2709 			if (!volume_found) {
2710 				scanned_volumes.push_back(disk_drive);
2711 				_total_free_4k_blocks += i->blocks;
2712 			}
2713 		}
2714 	}
2715 
2716 	if (0 == _total_free_4k_blocks) {
2717 		strncpy (disk_drive, path().c_str(), 3);
2718 		disk_drive[3] = 0;
2719 
2720 		if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2721 		{
2722 			int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2723 			int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2724 			_total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2725 		}
2726 	}
2727 #endif
2728 }
2729 
2730 string
get_best_session_directory_for_new_audio()2731 Session::get_best_session_directory_for_new_audio ()
2732 {
2733 	vector<space_and_path>::iterator i;
2734 	string result = _session_dir->root_path();
2735 
2736 	/* handle common case without system calls */
2737 
2738 	if (session_dirs.size() == 1) {
2739 		return result;
2740 	}
2741 
2742 	/* OK, here's the algorithm we're following here:
2743 
2744 	We want to select which directory to use for
2745 	the next file source to be created. Ideally,
2746 	we'd like to use a round-robin process so as to
2747 	get maximum performance benefits from splitting
2748 	the files across multiple disks.
2749 
2750 	However, in situations without much diskspace, an
2751 	RR approach may end up filling up a filesystem
2752 	with new files while others still have space.
2753 	Its therefore important to pay some attention to
2754 	the freespace in the filesystem holding each
2755 	directory as well. However, if we did that by
2756 	itself, we'd keep creating new files in the file
2757 	system with the most space until it was as full
2758 	as all others, thus negating any performance
2759 	benefits of this RAID-1 like approach.
2760 
2761 	So, we use a user-configurable space threshold. If
2762 	there are at least 2 filesystems with more than this
2763 	much space available, we use RR selection between them.
2764 	If not, then we pick the filesystem with the most space.
2765 
2766 	This gets a good balance between the two
2767 	approaches.
2768 	*/
2769 
2770 	refresh_disk_space ();
2771 
2772 	int free_enough = 0;
2773 
2774 	for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2775 		if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2776 			free_enough++;
2777 		}
2778 	}
2779 
2780 	if (free_enough >= 2) {
2781 		/* use RR selection process, ensuring that the one
2782 		   picked works OK.
2783 		*/
2784 
2785 		i = last_rr_session_dir;
2786 
2787 		do {
2788 			if (++i == session_dirs.end()) {
2789 				i = session_dirs.begin();
2790 			}
2791 
2792 			if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2793 				SessionDirectory sdir(i->path);
2794 				if (sdir.create ()) {
2795 					result = (*i).path;
2796 					last_rr_session_dir = i;
2797 					return result;
2798 				}
2799 			}
2800 
2801 		} while (i != last_rr_session_dir);
2802 
2803 	} else {
2804 
2805 		/* pick FS with the most freespace (and that
2806 		   seems to actually work ...)
2807 		*/
2808 
2809 		vector<space_and_path> sorted;
2810 		space_and_path_ascending_cmp cmp;
2811 
2812 		sorted = session_dirs;
2813 		sort (sorted.begin(), sorted.end(), cmp);
2814 
2815 		for (i = sorted.begin(); i != sorted.end(); ++i) {
2816 			SessionDirectory sdir(i->path);
2817 			if (sdir.create ()) {
2818 				result = (*i).path;
2819 				last_rr_session_dir = i;
2820 				return result;
2821 			}
2822 		}
2823 	}
2824 
2825 	return result;
2826 }
2827 
2828 string
automation_dir() const2829 Session::automation_dir () const
2830 {
2831 	return Glib::build_filename (_path, automation_dir_name);
2832 }
2833 
2834 string
analysis_dir() const2835 Session::analysis_dir () const
2836 {
2837 	return Glib::build_filename (_path, analysis_dir_name);
2838 }
2839 
2840 string
plugins_dir() const2841 Session::plugins_dir () const
2842 {
2843 	return Glib::build_filename (_path, plugins_dir_name);
2844 }
2845 
2846 string
externals_dir() const2847 Session::externals_dir () const
2848 {
2849 	return Glib::build_filename (_path, externals_dir_name);
2850 }
2851 
2852 int
load_bundles(XMLNode const & node)2853 Session::load_bundles (XMLNode const & node)
2854 {
2855 	XMLNodeList nlist = node.children();
2856 	XMLNodeConstIterator niter;
2857 
2858 	set_dirty();
2859 
2860 	for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2861 		if ((*niter)->name() == "InputBundle") {
2862 			add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2863 		} else if ((*niter)->name() == "OutputBundle") {
2864 			add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2865 		} else {
2866 			error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2867 			return -1;
2868 		}
2869 	}
2870 
2871 	return 0;
2872 }
2873 
2874 int
load_route_groups(const XMLNode & node,int version)2875 Session::load_route_groups (const XMLNode& node, int version)
2876 {
2877 	XMLNodeList nlist = node.children();
2878 	XMLNodeConstIterator niter;
2879 
2880 	set_dirty ();
2881 
2882 	if (version >= 3000) {
2883 
2884 		for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2885 			if ((*niter)->name() == "RouteGroup") {
2886 				RouteGroup* rg = new RouteGroup (*this, "");
2887 				add_route_group (rg);
2888 				rg->set_state (**niter, version);
2889 			}
2890 		}
2891 
2892 	} else if (version < 3000) {
2893 
2894 		for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2895 			if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2896 				RouteGroup* rg = new RouteGroup (*this, "");
2897 				add_route_group (rg);
2898 				rg->set_state (**niter, version);
2899 			}
2900 		}
2901 	}
2902 
2903 	return 0;
2904 }
2905 
2906 static bool
state_file_filter(const string & str,void *)2907 state_file_filter (const string &str, void* /*arg*/)
2908 {
2909 	return (str.length() > strlen(statefile_suffix) &&
2910 		str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2911 }
2912 
2913 static string
remove_end(string state)2914 remove_end(string state)
2915 {
2916 	string statename(state);
2917 
2918 	string::size_type start,end;
2919 	if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2920 		statename = statename.substr (start+1);
2921 	}
2922 
2923 	if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2924 		end = statename.length();
2925 	}
2926 
2927 	return string(statename.substr (0, end));
2928 }
2929 
2930 vector<string>
possible_states(string path)2931 Session::possible_states (string path)
2932 {
2933 	vector<string> states;
2934 	find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2935 
2936 	transform(states.begin(), states.end(), states.begin(), remove_end);
2937 
2938 	sort (states.begin(), states.end());
2939 
2940 	return states;
2941 }
2942 
2943 vector<string>
possible_states() const2944 Session::possible_states () const
2945 {
2946 	return possible_states(_path);
2947 }
2948 
2949 RouteGroup*
new_route_group(const std::string & name)2950 Session::new_route_group (const std::string& name)
2951 {
2952 	RouteGroup* rg = NULL;
2953 
2954 	for (std::list<RouteGroup*>::const_iterator i = _route_groups.begin (); i != _route_groups.end (); ++i) {
2955 		if ((*i)->name () == name) {
2956 			rg = *i;
2957 			break;
2958 		}
2959 	}
2960 
2961 	if (!rg) {
2962 		rg = new RouteGroup (*this, name);
2963 		add_route_group (rg);
2964 	}
2965 	return (rg);
2966 }
2967 
2968 void
add_route_group(RouteGroup * g)2969 Session::add_route_group (RouteGroup* g)
2970 {
2971 	_route_groups.push_back (g);
2972 	route_group_added (g); /* EMIT SIGNAL */
2973 
2974 	g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2975 	g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2976 	g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2977 
2978 	set_dirty ();
2979 }
2980 
2981 void
remove_route_group(RouteGroup & rg)2982 Session::remove_route_group (RouteGroup& rg)
2983 {
2984 	list<RouteGroup*>::iterator i;
2985 
2986 	if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2987 		_route_groups.erase (i);
2988 		delete &rg;
2989 
2990 		route_group_removed (); /* EMIT SIGNAL */
2991 	}
2992 }
2993 
2994 /** Set a new order for our route groups, without adding or removing any.
2995  *  @param groups Route group list in the new order.
2996  */
2997 void
reorder_route_groups(list<RouteGroup * > groups)2998 Session::reorder_route_groups (list<RouteGroup*> groups)
2999 {
3000 	_route_groups = groups;
3001 
3002 	route_groups_reordered (); /* EMIT SIGNAL */
3003 	set_dirty ();
3004 }
3005 
3006 
3007 RouteGroup *
route_group_by_name(string name)3008 Session::route_group_by_name (string name)
3009 {
3010 	list<RouteGroup *>::iterator i;
3011 
3012 	for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
3013 		if ((*i)->name() == name) {
3014 			return* i;
3015 		}
3016 	}
3017 	return 0;
3018 }
3019 
3020 RouteGroup&
all_route_group() const3021 Session::all_route_group() const
3022 {
3023 	return *_all_route_group;
3024 }
3025 
3026 void
add_commands(vector<Command * > const & cmds)3027 Session::add_commands (vector<Command*> const & cmds)
3028 {
3029 	for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
3030 		add_command (*i);
3031 	}
3032 }
3033 
3034 void
add_command(Command * const cmd)3035 Session::add_command (Command* const cmd)
3036 {
3037 	assert (_current_trans);
3038 	DEBUG_UNDO_HISTORY (
3039 	    string_compose ("Current Undo Transaction %1, adding command: %2",
3040 	                    _current_trans->name (),
3041 	                    cmd->name ()));
3042 	_current_trans->add_command (cmd);
3043 }
3044 
3045 PBD::StatefulDiffCommand*
add_stateful_diff_command(boost::shared_ptr<PBD::StatefulDestructible> sfd)3046 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
3047 {
3048 	PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
3049 	add_command (cmd);
3050 	return cmd;
3051 }
3052 
3053 void
begin_reversible_command(const string & name)3054 Session::begin_reversible_command (const string& name)
3055 {
3056 	begin_reversible_command (g_quark_from_string (name.c_str ()));
3057 }
3058 
3059 /** Begin a reversible command using a GQuark to identify it.
3060  *  begin_reversible_command() and commit_reversible_command() calls may be nested,
3061  *  but there must be as many begin...()s as there are commit...()s.
3062  */
3063 void
begin_reversible_command(GQuark q)3064 Session::begin_reversible_command (GQuark q)
3065 {
3066 	/* If nested begin/commit pairs are used, we create just one UndoTransaction
3067 	   to hold all the commands that are committed.  This keeps the order of
3068 	   commands correct in the history.
3069 	*/
3070 
3071 	if (_current_trans == 0) {
3072 		DEBUG_UNDO_HISTORY (string_compose (
3073 		    "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
3074 
3075 		/* start a new transaction */
3076 		assert (_current_trans_quarks.empty ());
3077 		_current_trans = new UndoTransaction();
3078 		_current_trans->set_name (g_quark_to_string (q));
3079 	} else {
3080 		DEBUG_UNDO_HISTORY (
3081 		    string_compose ("Begin Reversible Command, current transaction: %1",
3082 		                    _current_trans->name ()));
3083 	}
3084 
3085 	_current_trans_quarks.push_front (q);
3086 }
3087 
3088 void
abort_reversible_command()3089 Session::abort_reversible_command ()
3090 {
3091 	if (_current_trans != 0) {
3092 		DEBUG_UNDO_HISTORY (
3093 		    string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
3094 		_current_trans->clear();
3095 		delete _current_trans;
3096 		_current_trans = 0;
3097 		_current_trans_quarks.clear();
3098 	}
3099 }
3100 
3101 bool
abort_empty_reversible_command()3102 Session::abort_empty_reversible_command ()
3103 {
3104 	if (!collected_undo_commands ()) {
3105 		abort_reversible_command ();
3106 		return true;
3107 	}
3108 	return false;
3109 }
3110 
3111 void
commit_reversible_command(Command * cmd)3112 Session::commit_reversible_command (Command *cmd)
3113 {
3114 	assert (_current_trans);
3115 	assert (!_current_trans_quarks.empty ());
3116 
3117 	struct timeval now;
3118 
3119 	if (cmd) {
3120 		DEBUG_UNDO_HISTORY (
3121 		    string_compose ("Current Undo Transaction %1, adding command: %2",
3122 		                    _current_trans->name (),
3123 		                    cmd->name ()));
3124 		_current_trans->add_command (cmd);
3125 	}
3126 
3127 	DEBUG_UNDO_HISTORY (
3128 	    string_compose ("Commit Reversible Command, current transaction: %1",
3129 	                    _current_trans->name ()));
3130 
3131 	_current_trans_quarks.pop_front ();
3132 
3133 	if (!_current_trans_quarks.empty ()) {
3134 		DEBUG_UNDO_HISTORY (
3135 		    string_compose ("Commit Reversible Command, transaction is not "
3136 		                    "top-level, current transaction: %1",
3137 		                    _current_trans->name ()));
3138 		/* the transaction we're committing is not the top-level one */
3139 		return;
3140 	}
3141 
3142 	if (_current_trans->empty()) {
3143 		/* no commands were added to the transaction, so just get rid of it */
3144 		DEBUG_UNDO_HISTORY (
3145 		    string_compose ("Commit Reversible Command, No commands were "
3146 		                    "added to current transaction: %1",
3147 		                    _current_trans->name ()));
3148 		delete _current_trans;
3149 		_current_trans = 0;
3150 		return;
3151 	}
3152 
3153 	gettimeofday (&now, 0);
3154 	_current_trans->set_timestamp (now);
3155 
3156 	_history.add (_current_trans);
3157 	_current_trans = 0;
3158 }
3159 
3160 static bool
accept_all_audio_files(const string & path,void *)3161 accept_all_audio_files (const string& path, void* /*arg*/)
3162 {
3163 	if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
3164 		return false;
3165 	}
3166 
3167 	if (!AudioFileSource::safe_audio_file_extension (path)) {
3168 		return false;
3169 	}
3170 
3171 	return true;
3172 }
3173 
3174 static bool
accept_all_midi_files(const string & path,void *)3175 accept_all_midi_files (const string& path, void* /*arg*/)
3176 {
3177 	if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
3178 		return false;
3179 	}
3180 
3181 	return (   (path.length() > 4 && path.find (".mid") != (path.length() - 4))
3182 	        || (path.length() > 4 && path.find (".smf") != (path.length() - 4))
3183 	        || (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
3184 }
3185 
3186 static bool
accept_all_state_files(const string & path,void *)3187 accept_all_state_files (const string& path, void* /*arg*/)
3188 {
3189 	if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
3190 		return false;
3191 	}
3192 
3193 	std::string const statefile_ext (statefile_suffix);
3194 	if (path.length() >= statefile_ext.length()) {
3195 		return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
3196 	} else {
3197 		return false;
3198 	}
3199 }
3200 
3201 int
find_all_sources(string path,set<string> & result)3202 Session::find_all_sources (string path, set<string>& result)
3203 {
3204 	XMLTree tree;
3205 	XMLNode* node;
3206 
3207 	if (!tree.read (path)) {
3208 		return -1;
3209 	}
3210 
3211 	if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
3212 		return -2;
3213 	}
3214 
3215 	XMLNodeList nlist;
3216 	XMLNodeConstIterator niter;
3217 
3218 	nlist = node->children();
3219 
3220 	set_dirty();
3221 
3222 	for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
3223 
3224 		XMLProperty const * prop;
3225 
3226 		if ((prop = (*niter)->property (X_("type"))) == 0) {
3227 			continue;
3228 		}
3229 
3230 		DataType type (prop->value());
3231 
3232 		if ((prop = (*niter)->property (X_("name"))) == 0) {
3233 			continue;
3234 		}
3235 
3236 		if (Glib::path_is_absolute (prop->value())) {
3237 			/* external file, ignore */
3238 			continue;
3239 		}
3240 
3241 		string found_path;
3242 		bool is_new;
3243 		uint16_t chan;
3244 
3245 		if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
3246 			result.insert (found_path);
3247 		}
3248 	}
3249 
3250 	return 0;
3251 }
3252 
3253 int
find_all_sources_across_snapshots(set<string> & result,bool exclude_this_snapshot)3254 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
3255 {
3256 	vector<string> state_files;
3257 	string ripped;
3258 	string this_snapshot_path;
3259 
3260 	result.clear ();
3261 
3262 	ripped = _path;
3263 
3264 	if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
3265 		ripped = ripped.substr (0, ripped.length() - 1);
3266 	}
3267 
3268 	find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
3269 
3270 	if (state_files.empty()) {
3271 		/* impossible! */
3272 		return 0;
3273 	}
3274 
3275 	this_snapshot_path = Glib::build_filename (_path, legalize_for_path (_current_snapshot_name));
3276 	this_snapshot_path += statefile_suffix;
3277 
3278 	for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
3279 
3280 		cerr << "Looking at snapshot " << (*i) << " ( with this = [" << this_snapshot_path << "])\n";
3281 
3282 		if (exclude_this_snapshot && *i == this_snapshot_path) {
3283 			cerr << "\texcluded\n";
3284 			continue;
3285 
3286 		}
3287 
3288 		if (find_all_sources (*i, result) < 0) {
3289 			return -1;
3290 		}
3291 	}
3292 
3293 	return 0;
3294 }
3295 
3296 struct RegionCounter {
3297 	typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
3298 	AudioSourceList::iterator iter;
3299 	boost::shared_ptr<Region> region;
3300 	uint32_t count;
3301 
RegionCounterRegionCounter3302 	RegionCounter() : count (0) {}
3303 };
3304 
3305 int
ask_about_playlist_deletion(boost::shared_ptr<Playlist> p)3306 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
3307 {
3308 	boost::optional<int> r = AskAboutPlaylistDeletion (p);
3309 	return r.value_or (1);
3310 }
3311 
3312 void
cleanup_regions()3313 Session::cleanup_regions ()
3314 {
3315 	bool removed = false;
3316 	const RegionFactory::RegionMap& regions (RegionFactory::regions());
3317 
3318 	for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
3319 
3320 		uint32_t used = _playlists->region_use_count (i->second);
3321 
3322 		if (used == 0 && !i->second->automatic ()) {
3323 			boost::weak_ptr<Region> w = i->second;
3324 			++i;
3325 			removed = true;
3326 			RegionFactory::map_remove (w);
3327 		} else {
3328 			++i;
3329 		}
3330 	}
3331 
3332 	if (removed) {
3333 		// re-check to remove parent references of compound regions
3334 		for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
3335 			if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
3336 				++i;
3337 				continue;
3338 			}
3339 			assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
3340 			if (0 == _playlists->region_use_count (i->second)) {
3341 				boost::weak_ptr<Region> w = i->second;
3342 				++i;
3343 				RegionFactory::map_remove (w);
3344 			} else {
3345 				++i;
3346 			}
3347 		}
3348 	}
3349 }
3350 
3351 bool
can_cleanup_peakfiles() const3352 Session::can_cleanup_peakfiles () const
3353 {
3354 	if (deletion_in_progress()) {
3355 		return false;
3356 	}
3357 	if (!_writable || cannot_save ()) {
3358 		warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
3359 		return false;
3360 	}
3361 	if (record_status() == Recording) {
3362 		error << _("Cannot cleanup peak-files while recording") << endmsg;
3363 		return false;
3364 	}
3365 	return true;
3366 }
3367 
3368 int
cleanup_peakfiles()3369 Session::cleanup_peakfiles ()
3370 {
3371 	Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
3372 	if (!lm.locked()) {
3373 		return -1;
3374 	}
3375 
3376 	assert (can_cleanup_peakfiles ());
3377 	assert (!peaks_cleanup_in_progres());
3378 
3379 	_state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
3380 
3381 	int timeout = 5000; // 5 seconds
3382 	while (!SourceFactory::files_with_peaks.empty()) {
3383 		Glib::usleep (1000);
3384 		if (--timeout < 0) {
3385 			warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
3386 			_state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3387 			return -1;
3388 		}
3389 	}
3390 
3391 	for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3392 		boost::shared_ptr<AudioSource> as;
3393 		if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3394 			as->close_peakfile();
3395 		}
3396 	}
3397 
3398 	PBD::clear_directory (session_directory().peak_path());
3399 
3400 	_state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3401 
3402 	for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3403 		boost::shared_ptr<AudioSource> as;
3404 		if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3405 			SourceFactory::setup_peakfile(as, true);
3406 		}
3407 	}
3408 	return 0;
3409 }
3410 
3411 int
cleanup_sources(CleanupReport & rep)3412 Session::cleanup_sources (CleanupReport& rep)
3413 {
3414 	// FIXME: needs adaptation to midi
3415 
3416 	SourceList dead_sources;
3417 	string audio_path;
3418 	string midi_path;
3419 	vector<string> candidates;
3420 	vector<string> unused;
3421 	set<string> sources_used_by_all_snapshots;
3422 	string spath;
3423 	int ret = -1;
3424 	string tmppath1;
3425 	string tmppath2;
3426 	Searchpath asp;
3427 	Searchpath msp;
3428 	set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
3429 
3430 	_state_of_the_state = StateOfTheState (_state_of_the_state | InCleanup);
3431 
3432 	Glib::Threads::Mutex::Lock ls (source_lock, Glib::Threads::NOT_LOCK);
3433 
3434 	/* this is mostly for windows which doesn't allow file
3435 	 * renaming if the file is in use. But we don't special
3436 	 * case it because we need to know if this causes
3437 	 * problems, and the easiest way to notice that is to
3438 	 * keep it in place for all platforms.
3439 	 */
3440 
3441 	request_stop (false);
3442 	_butler->summon ();
3443 	_butler->wait_until_finished ();
3444 
3445 	/* consider deleting all unused playlists */
3446 
3447 	if (_playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3448 		ret = 0;
3449 		goto out;
3450 	}
3451 
3452 	/* sync the "all regions" property of each playlist with its current state */
3453 
3454 	_playlists->sync_all_regions_with_regions ();
3455 
3456 	/* find all un-used sources */
3457 
3458 	rep.paths.clear ();
3459 	rep.space = 0;
3460 
3461 	ls.acquire ();
3462 	for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3463 
3464 		SourceMap::iterator tmp;
3465 
3466 		tmp = i;
3467 		++tmp;
3468 
3469 		/* do not bother with files that are zero size, otherwise we remove the current "nascent"
3470 		 * capture files.
3471 		 */
3472 
3473 		if (!i->second->used() && (i->second->length(i->second->natural_position()) > 0)) {
3474 			dead_sources.push_back (i->second);
3475 		}
3476 
3477 		i = tmp;
3478 	}
3479 	ls.release ();
3480 
3481 	/* build a list of all the possible audio directories for the session */
3482 
3483 	for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3484 		SessionDirectory sdir ((*i).path);
3485 		asp += sdir.sound_path();
3486 	}
3487 	audio_path += asp.to_string();
3488 
3489 
3490 	/* build a list of all the possible midi directories for the session */
3491 
3492 	for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3493 		SessionDirectory sdir ((*i).path);
3494 		msp += sdir.midi_path();
3495 	}
3496 	midi_path += msp.to_string();
3497 
3498 	find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3499 	find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3500 
3501 	/* add sources from all other snapshots as "used", but don't use this
3502 		 snapshot because the state file on disk still references sources we
3503 		 may have already dropped.
3504 		 */
3505 
3506 	find_all_sources_across_snapshots (sources_used_by_all_snapshots, true);
3507 
3508 	/* Although the region factory has a list of all regions ever created
3509 	 * for this session, we're only interested in regions actually in
3510 	 * playlists right now. So merge all playlist regions lists together.
3511 	 *
3512 	 * This will include the playlists used within compound regions.
3513 	 */
3514 
3515 	_playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot));
3516 
3517 	/*  add our current source list
3518 	*/
3519 
3520 	ls.acquire ();
3521 	for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3522 		boost::shared_ptr<FileSource> fs;
3523 		SourceMap::iterator tmp = i;
3524 		++tmp;
3525 
3526 		if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) == 0) {
3527 			/* not a file */
3528 			i = tmp;
3529 			continue;
3530 		}
3531 
3532 		/* this is mostly for windows which doesn't allow file
3533 		 * renaming if the file is in use. But we do not special
3534 		 * case it because we need to know if this causes
3535 		 * problems, and the easiest way to notice that is to
3536 		 * keep it in place for all platforms.
3537 		 */
3538 
3539 		fs->close ();
3540 
3541 		if (!fs->is_stub()) {
3542 
3543 			/* Note that we're checking a list of all
3544 			 * sources across all snapshots with the list
3545 			 * of sources used by this snapshot.
3546 			 */
3547 
3548 			if (sources_used_by_this_snapshot.find (i->second) != sources_used_by_this_snapshot.end()) {
3549 				/* this source is in use by this snapshot */
3550 				sources_used_by_all_snapshots.insert (fs->path());
3551 				cerr << "Source from source list found in used_by_this_snapshot (" << fs->path() << ")\n";
3552 			} else {
3553 				cerr << "Source from source list NOT found in used_by_this_snapshot (" << fs->path() << ")\n";
3554 				/* this source is NOT in use by this snapshot */
3555 
3556 				/* remove all related regions from RegionFactory master list */
3557 
3558 				RegionFactory::remove_regions_using_source (i->second);
3559 
3560 				/* remove from our current source list
3561 				 * also. We may not remove it from
3562 				 * disk, because it may be used by
3563 				 * other snapshots, but it isn't used inside this
3564 				 * snapshot anymore, so we don't need a
3565 				 * reference to it.
3566 				 */
3567 
3568 				dead_sources.push_back (i->second);
3569 				sources.erase (i);
3570 			}
3571 		}
3572 
3573 		i = tmp;
3574 	}
3575 	ls.release ();
3576 
3577 	for (SourceList::iterator i = dead_sources.begin(); i != dead_sources.end(); ++i) {
3578 		/* The following triggers Region::source_deleted (), which
3579 		 * causes regions to drop the given source */
3580 		(*i)->drop_references ();
3581 		SourceRemoved (*i); /* EMIT SIGNAL */
3582 	}
3583 
3584 	/* now check each candidate source to see if it exists in the list of
3585 	 * sources_used_by_all_snapshots. If it doesn't, put it into "unused".
3586 	 */
3587 
3588 	cerr << "Candidates: " << candidates.size() << endl;
3589 	cerr << "Used by others: " << sources_used_by_all_snapshots.size() << endl;
3590 
3591 	for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3592 
3593 		bool used = false;
3594 		spath = *x;
3595 
3596 		for (set<string>::iterator i = sources_used_by_all_snapshots.begin(); i != sources_used_by_all_snapshots.end(); ++i) {
3597 
3598 			tmppath1 = canonical_path (spath);
3599 			tmppath2 = canonical_path ((*i));
3600 
3601 			cerr << "\t => " << tmppath2 << endl;
3602 
3603 			if (tmppath1 == tmppath2) {
3604 				used = true;
3605 				break;
3606 			}
3607 		}
3608 
3609 		if (!used) {
3610 			unused.push_back (spath);
3611 		}
3612 	}
3613 
3614 	cerr << "Actually unused: " << unused.size() << endl;
3615 
3616 	if (unused.empty()) {
3617 		/* Nothing to do */
3618 		ret = 0;
3619 		goto out;
3620 	}
3621 
3622 	/* now try to move all unused files into the "dead" directory(ies) */
3623 
3624 	for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3625 		GStatBuf statbuf;
3626 
3627 		string newpath;
3628 
3629 		/* don't move the file across filesystems, just
3630 		 * stick it in the `dead_dir_name' directory
3631 		 * on whichever filesystem it was already on.
3632 		 */
3633 
3634 		if ((*x).find ("/sounds/") != string::npos) {
3635 
3636 			/* old school, go up 1 level */
3637 
3638 			newpath = Glib::path_get_dirname (*x);      // "sounds"
3639 			newpath = Glib::path_get_dirname (newpath); // "session-name"
3640 
3641 		} else {
3642 
3643 			/* new school, go up 4 levels */
3644 
3645 			newpath = Glib::path_get_dirname (*x);      // "audiofiles" or "midifiles"
3646 			newpath = Glib::path_get_dirname (newpath); // "session-name"
3647 			newpath = Glib::path_get_dirname (newpath); // "interchange"
3648 			newpath = Glib::path_get_dirname (newpath); // "session-dir"
3649 		}
3650 
3651 		newpath = Glib::build_filename (newpath, dead_dir_name);
3652 
3653 		if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3654 			error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3655 			return -1;
3656 		}
3657 
3658 		newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3659 
3660 		if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3661 
3662 			/* the new path already exists, try versioning */
3663 
3664 			char buf[PATH_MAX+1];
3665 			int version = 1;
3666 			string newpath_v;
3667 
3668 			snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3669 			newpath_v = buf;
3670 
3671 			while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3672 				snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3673 				newpath_v = buf;
3674 			}
3675 
3676 			if (version == 999) {
3677 				error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3678 						newpath)
3679 					<< endmsg;
3680 			} else {
3681 				newpath = newpath_v;
3682 			}
3683 
3684 		}
3685 
3686 		if ((g_stat ((*x).c_str(), &statbuf) != 0) || (::g_rename ((*x).c_str(), newpath.c_str()) != 0)) {
3687 			error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"), (*x),
3688 					newpath, g_strerror (errno)) << endmsg;
3689 			continue;
3690 		}
3691 
3692 		/* see if there an easy to find peakfile for this file, and remove it.  */
3693 
3694 		string base = Glib::path_get_basename (*x);
3695 		base += "%A"; /* this is what we add for the channel suffix of all native files,
3696 									 * or for the first channel of embedded files. it will miss
3697 									 * some peakfiles for other channels
3698 									 */
3699 		string peakpath = construct_peak_filepath (base);
3700 
3701 		if (Glib::file_test (peakpath.c_str (), Glib::FILE_TEST_EXISTS)) {
3702 			if (::g_unlink (peakpath.c_str ()) != 0) {
3703 				error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"), peakpath, _path,
3704 						g_strerror (errno)) << endmsg;
3705 				/* try to back out */
3706 				::g_rename (newpath.c_str (), _path.c_str ());
3707 				goto out;
3708 			}
3709 		}
3710 
3711 		rep.paths.push_back (*x);
3712 		rep.space += statbuf.st_size;
3713 	}
3714 
3715 	/* drop last Source references */
3716 	dead_sources.clear ();
3717 
3718 	/* dump the history list, remove references */
3719 
3720 	_history.clear ();
3721 
3722 	/* save state so we don't end up a session file
3723 	 * referring to non-existent sources.
3724 	 */
3725 
3726 	save_state ();
3727 	ret = 0;
3728 
3729 out:
3730 	_state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
3731 
3732 	return ret;
3733 }
3734 
3735 int
cleanup_trash_sources(CleanupReport & rep)3736 Session::cleanup_trash_sources (CleanupReport& rep)
3737 {
3738 	// FIXME: needs adaptation for MIDI
3739 
3740 	vector<space_and_path>::iterator i;
3741 	string dead_dir;
3742 
3743 	for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3744 
3745 		dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3746 
3747 		clear_directory (dead_dir, &rep.space, &rep.paths);
3748 	}
3749 
3750 	return 0;
3751 }
3752 
3753 void
set_dirty()3754 Session::set_dirty ()
3755 {
3756 	/* return early if there's nothing to do */
3757 	if (dirty ()) {
3758 		return;
3759 	}
3760 
3761 	/* never mark session dirty during loading */
3762 	if (loading () || deletion_in_progress ()) {
3763 		return;
3764 	}
3765 
3766 	_state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3767 	DirtyChanged(); /* EMIT SIGNAL */
3768 }
3769 
3770 void
set_clean()3771 Session::set_clean ()
3772 {
3773 	bool was_dirty = dirty();
3774 
3775 	_state_of_the_state = Clean;
3776 
3777 	if (was_dirty) {
3778 		DirtyChanged(); /* EMIT SIGNAL */
3779 	}
3780 }
3781 
3782 void
unset_dirty(bool emit_dirty_changed)3783 Session::unset_dirty (bool emit_dirty_changed)
3784 {
3785 	bool was_dirty = dirty();
3786 
3787 	_state_of_the_state = StateOfTheState (_state_of_the_state & (~Dirty));
3788 
3789 	if (was_dirty && emit_dirty_changed) {
3790 		DirtyChanged (); /* EMIT SIGNAL */
3791 	}
3792 }
3793 
3794 void
set_deletion_in_progress()3795 Session::set_deletion_in_progress ()
3796 {
3797 	_state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3798 }
3799 
3800 void
clear_deletion_in_progress()3801 Session::clear_deletion_in_progress ()
3802 {
3803 	_state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3804 }
3805 
3806 void
add_controllable(boost::shared_ptr<Controllable> c)3807 Session::add_controllable (boost::shared_ptr<Controllable> c)
3808 {
3809 	/* this adds a controllable to the list managed by the Session.
3810 	   this is a subset of those managed by the Controllable class
3811 	   itself, and represents the only ones whose state will be saved
3812 	   as part of the session.
3813 	*/
3814 
3815 	Glib::Threads::Mutex::Lock lm (controllables_lock);
3816 	controllables.insert (c);
3817 }
3818 
3819 boost::shared_ptr<Controllable>
controllable_by_id(const PBD::ID & id)3820 Session::controllable_by_id (const PBD::ID& id)
3821 {
3822 	Glib::Threads::Mutex::Lock lm (controllables_lock);
3823 
3824 	for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3825 		if ((*i)->id() == id) {
3826 			return *i;
3827 		}
3828 	}
3829 
3830 	return boost::shared_ptr<Controllable>();
3831 }
3832 
3833 boost::shared_ptr<AutomationControl>
automation_control_by_id(const PBD::ID & id)3834 Session::automation_control_by_id (const PBD::ID& id)
3835 {
3836 	return boost::dynamic_pointer_cast<AutomationControl> (controllable_by_id (id));
3837 }
3838 
3839 void
add_instant_xml(XMLNode & node,bool write_to_config)3840 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3841 {
3842 	if (_writable) {
3843 		Stateful::add_instant_xml (node, _path);
3844 	}
3845 
3846 	if (write_to_config) {
3847 		Config->add_instant_xml (node);
3848 	}
3849 }
3850 
3851 XMLNode*
instant_xml(const string & node_name)3852 Session::instant_xml (const string& node_name)
3853 {
3854 #ifdef MIXBUS // "Safe Mode" (shift + click open) -> also ignore instant.xml
3855 	if (get_disable_all_loaded_plugins ()) {
3856 		return NULL;
3857 	}
3858 #endif
3859 	return Stateful::instant_xml (node_name, _path);
3860 }
3861 
3862 int
save_history(string snapshot_name)3863 Session::save_history (string snapshot_name)
3864 {
3865 	XMLTree tree;
3866 
3867 	if (!_writable) {
3868 	        return 0;
3869 	}
3870 
3871 	if (snapshot_name.empty()) {
3872 		snapshot_name = _current_snapshot_name;
3873 	}
3874 
3875 	const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3876 	const string backup_filename = history_filename + backup_suffix;
3877 	const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3878 	const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3879 
3880 	if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3881 		if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3882 			error << _("could not backup old history file, current history not saved") << endmsg;
3883 			return -1;
3884 		}
3885 	}
3886 
3887 	if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3888 	    (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3889 		return 0;
3890 	}
3891 
3892 	tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3893 
3894 	if (!tree.write (xml_path))
3895 	{
3896 		error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3897 
3898 		if (g_remove (xml_path.c_str()) != 0) {
3899 			error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3900 					xml_path, g_strerror (errno)) << endmsg;
3901 		}
3902 		if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3903 			error << string_compose (_("could not restore history file from backup %1 (%2)"),
3904 					backup_path, g_strerror (errno)) << endmsg;
3905 		}
3906 
3907 		return -1;
3908 	}
3909 
3910 	return 0;
3911 }
3912 
3913 int
restore_history(string snapshot_name)3914 Session::restore_history (string snapshot_name)
3915 {
3916 	XMLTree tree;
3917 
3918 	if (snapshot_name.empty()) {
3919 		snapshot_name = _current_snapshot_name;
3920 	}
3921 
3922 	const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3923 	const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3924 
3925 	info << "Loading history from " << xml_path << endmsg;
3926 
3927 	if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3928 		info << string_compose (_("%1: no history file \"%2\" for this session."),
3929 				_name, xml_path) << endmsg;
3930 		return 1;
3931 	}
3932 
3933 	if (!tree.read (xml_path)) {
3934 		error << string_compose (_("Could not understand session history file \"%1\""),
3935 				xml_path) << endmsg;
3936 		return -1;
3937 	}
3938 
3939 	// replace history
3940 	_history.clear();
3941 
3942 	for (XMLNodeConstIterator it  = tree.root()->children().begin(); it != tree.root()->children().end(); ++it) {
3943 
3944 		XMLNode *t = *it;
3945 
3946 		std::string name;
3947 		int64_t tv_sec;
3948 		int64_t tv_usec;
3949 
3950 		if (!t->get_property ("name", name) || !t->get_property ("tv-sec", tv_sec) ||
3951 		    !t->get_property ("tv-usec", tv_usec)) {
3952 			continue;
3953 		}
3954 
3955 		UndoTransaction* ut = new UndoTransaction ();
3956 		ut->set_name (name);
3957 
3958 		struct timeval tv;
3959 		tv.tv_sec = tv_sec;
3960 		tv.tv_usec = tv_usec;
3961 		ut->set_timestamp(tv);
3962 
3963 		for (XMLNodeConstIterator child_it  = t->children().begin();
3964 				child_it != t->children().end(); child_it++)
3965 		{
3966 			XMLNode *n = *child_it;
3967 			Command *c;
3968 
3969 			if (n->name() == "MementoCommand" ||
3970 					n->name() == "MementoUndoCommand" ||
3971 					n->name() == "MementoRedoCommand") {
3972 
3973 				if ((c = memento_command_factory(n))) {
3974 					ut->add_command(c);
3975 				}
3976 
3977 			} else if (n->name() == "NoteDiffCommand") {
3978 				PBD::ID id (n->property("midi-source")->value());
3979 				boost::shared_ptr<MidiSource> midi_source =
3980 					boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3981 				if (midi_source) {
3982 					ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3983 				} else {
3984 					error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3985 				}
3986 
3987 			} else if (n->name() == "SysExDiffCommand") {
3988 
3989 				PBD::ID id (n->property("midi-source")->value());
3990 				boost::shared_ptr<MidiSource> midi_source =
3991 					boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3992 				if (midi_source) {
3993 					ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3994 				} else {
3995 					error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3996 				}
3997 
3998 			} else if (n->name() == "PatchChangeDiffCommand") {
3999 
4000 				PBD::ID id (n->property("midi-source")->value());
4001 				boost::shared_ptr<MidiSource> midi_source =
4002 					boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
4003 				if (midi_source) {
4004 					ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
4005 				} else {
4006 					error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
4007 				}
4008 
4009 			} else if (n->name() == "StatefulDiffCommand") {
4010 				if ((c = stateful_diff_command_factory (n))) {
4011 					ut->add_command (c);
4012 				}
4013 			} else {
4014 				error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
4015 			}
4016 		}
4017 
4018 		_history.add (ut);
4019 	}
4020 
4021 	return 0;
4022 }
4023 
4024 void
config_changed(std::string p,bool ours)4025 Session::config_changed (std::string p, bool ours)
4026 {
4027 	if (ours) {
4028 		set_dirty ();
4029 	}
4030 
4031 	if (p == "auto-loop") {
4032 
4033 	} else if (p == "session-monitoring") {
4034 
4035 	} else if (p == "auto-input") {
4036 
4037 		if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
4038 			/* auto-input only makes a difference if we're rolling */
4039 			set_track_monitor_input_status (!config.get_auto_input());
4040 		}
4041 
4042 	} else if (p == "punch-in") {
4043 
4044 		if (!punch_is_possible ()) {
4045 			if (config.get_punch_in ()) {
4046 				/* force off */
4047 				config.set_punch_in (false);
4048 				return;
4049 			}
4050 		}
4051 
4052 		Location* location;
4053 		if ((location = _locations->auto_punch_location()) != 0) {
4054 
4055 			if (config.get_punch_in ()) {
4056 				auto_punch_start_changed (location);
4057 			} else {
4058 				clear_events (SessionEvent::PunchIn);
4059 			}
4060 		}
4061 
4062 	} else if (p == "punch-out") {
4063 
4064 		if (!punch_is_possible ()) {
4065 			if (config.get_punch_out ()) {
4066 				/* force off */
4067 				config.set_punch_out (false);
4068 				return;
4069 			}
4070 		}
4071 
4072 		Location* location;
4073 		if ((location = _locations->auto_punch_location()) != 0) {
4074 
4075 			if (config.get_punch_out()) {
4076 				auto_punch_end_changed (location);
4077 			} else {
4078 				clear_events (SessionEvent::PunchOut);
4079 			}
4080 		}
4081 
4082 	} else if (p == "edit-mode") {
4083 
4084 		Glib::Threads::Mutex::Lock lm (_playlists->lock);
4085 
4086 		for (SessionPlaylists::List::iterator i = _playlists->playlists.begin(); i != _playlists->playlists.end(); ++i) {
4087 			(*i)->set_edit_mode (Config->get_edit_mode ());
4088 		}
4089 
4090 	} else if (p == "use-video-sync") {
4091 
4092 		waiting_for_sync_offset = config.get_use_video_sync();
4093 
4094 	} else if (p == "mmc-control") {
4095 
4096 		//poke_midi_thread ();
4097 
4098 	} else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
4099 
4100 		_mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
4101 
4102 	} else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
4103 
4104 		_mmc->set_send_device_id (Config->get_mmc_send_device_id());
4105 
4106 	} else if (p == "midi-control") {
4107 
4108 		//poke_midi_thread ();
4109 
4110 	} else if (p == "raid-path") {
4111 
4112 		setup_raid_path (config.get_raid_path());
4113 
4114 	} else if (p == "timecode-format") {
4115 
4116 		sync_time_vars ();
4117 
4118 	} else if (p == "video-pullup") {
4119 
4120 		sync_time_vars ();
4121 
4122 	} else if (p == "seamless-loop") {
4123 
4124 		if (play_loop && transport_rolling()) {
4125 			// to reset diskstreams etc
4126 			request_play_loop (true);
4127 		}
4128 
4129 	} else if (p == "click-sound") {
4130 
4131 		setup_click_sounds (1);
4132 
4133 	} else if (p == "click-emphasis-sound") {
4134 
4135 		setup_click_sounds (-1);
4136 
4137 	} else if (p == "clicking") {
4138 
4139 		if (Config->get_clicking()) {
4140 			if (_click_io && click_data) { // don't require emphasis data
4141 				_clicking = true;
4142 			}
4143 		} else {
4144 			_clicking = false;
4145 		}
4146 
4147 	} else if (p == "click-record-only") {
4148 
4149 			_click_rec_only = Config->get_click_record_only();
4150 
4151 	} else if (p == "click-gain") {
4152 
4153 		if (_click_gain) {
4154 			_click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
4155 		}
4156 
4157 	} else if (p == "send-mtc") {
4158 
4159 		if (Config->get_send_mtc ()) {
4160 			/* mark us ready to send */
4161 			next_quarter_frame_to_send = 0;
4162 		}
4163 
4164 	} else if (p == "send-mmc") {
4165 
4166 		_mmc->enable_send (Config->get_send_mmc ());
4167 		if (Config->get_send_mmc ()) {
4168 			/* re-initialize MMC */
4169 			send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
4170 			send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
4171 		}
4172 
4173 	} else if (p == "jack-time-master") {
4174 
4175 		engine().reset_timebase ();
4176 
4177 	} else if (p == "native-file-header-format") {
4178 
4179 		if (!first_file_header_format_reset) {
4180 			reset_native_file_format ();
4181 		}
4182 
4183 		first_file_header_format_reset = false;
4184 
4185 	} else if (p == "native-file-data-format") {
4186 
4187 		if (!first_file_data_format_reset) {
4188 			reset_native_file_format ();
4189 		}
4190 
4191 		first_file_data_format_reset = false;
4192 
4193 	} else if (p == "external-sync") {
4194 		request_sync_source (TransportMasterManager::instance().current());
4195 	}  else if (p == "denormal-model") {
4196 		setup_fpu ();
4197 	} else if (p == "history-depth") {
4198 		set_history_depth (Config->get_history_depth());
4199 	} else if (p == "remote-model") {
4200 		/* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
4201 		   TO SET REMOTE ID'S
4202 		*/
4203 	} else if (p == "initial-program-change") {
4204 
4205 		if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
4206 			MIDI::byte buf[2];
4207 
4208 			buf[0] = MIDI::program; // channel zero by default
4209 			buf[1] = (Config->get_initial_program_change() & 0x7f);
4210 
4211 			_mmc->output_port()->midimsg (buf, sizeof (buf), 0);
4212 		}
4213 	} else if (p == "solo-mute-override") {
4214 		// catch_up_on_solo_mute_override ();
4215 	} else if (p == "listen-position" || p == "pfl-position" || p == "afl-position") {
4216 		listen_position_changed ();
4217 	} else if (p == "solo-control-is-listen-control") {
4218 		solo_control_mode_changed ();
4219 	} else if (p == "solo-mute-gain") {
4220 		_solo_cut_control->Changed (true, Controllable::NoGroup);
4221 	} else if (p == "timecode-offset" || p == "timecode-offset-negative") {
4222 		last_timecode_valid = false;
4223 	} else if (p == "ltc-sink-port") {
4224 		reconnect_ltc_output ();
4225 	} else if (p == "timecode-generator-offset") {
4226 		ltc_tx_parse_offset();
4227 	} else if (p == "auto-return-target-list") {
4228 		if (!loading()) {
4229 			follow_playhead_priority ();
4230 		}
4231 	} else if (p == "use-monitor-bus") {
4232 		/* NB. This is always called when constructing a session,
4233 		 * after restoring session state (if any),
4234 		 * via post_engine_init() -> Config->map_parameters()
4235 		 */
4236 		bool want_ms = Config->get_use_monitor_bus();
4237 		bool have_ms = _monitor_out ? true : false;
4238 		if (loading ()) {
4239 			/* When loading an existing session, the config "use-monitor-bus"
4240 			 * is ignored. Instead the sesion-state (xml) will have added the
4241 			 * "monitor-route" and restored its state (and connections)
4242 			 * if the session has a monitor-section.
4243 			 * Update the config to reflect this.
4244 			 */
4245 			if (want_ms != have_ms) {
4246 				Config->set_use_monitor_bus (have_ms);
4247 			}
4248 			MonitorBusAddedOrRemoved (); /* EMIT SIGNAL */
4249 		} else  {
4250 			/* Otherwise, Config::set_use_monitor_bus() does
4251 			 * control the the presence of the monitor-section
4252 			 * (new sessions, user initiated change)
4253 			 */
4254 			if (want_ms && !have_ms) {
4255 				add_monitor_section ();
4256 			} else if (!want_ms && have_ms) {
4257 				remove_monitor_section ();
4258 			}
4259 		}
4260 	} else if (p == "loop-fade-choice") {
4261 		last_loopend = 0; /* force locate to refill buffers with new loop boundary data */
4262 		auto_loop_changed (_locations->auto_loop_location());
4263 	} else if (p == "use-master-volume") {
4264 		if (master_volume () && !Config->get_use_master_volume ()) {
4265 			_master_out->set_volume_applies_to_output (true);
4266 			master_volume ()->set_value (GAIN_COEFF_UNITY, Controllable::NoGroup);
4267 		}
4268 	}
4269 
4270 	set_dirty ();
4271 }
4272 
4273 void
set_history_depth(uint32_t d)4274 Session::set_history_depth (uint32_t d)
4275 {
4276 	_history.set_depth (d);
4277 }
4278 
4279 /** Connect things to the MMC object */
4280 void
setup_midi_machine_control()4281 Session::setup_midi_machine_control ()
4282 {
4283 	_mmc = new MIDI::MachineControl;
4284 
4285 	boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
4286 	boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
4287 
4288 	if (!async_out || !async_out) {
4289 		return;
4290 	}
4291 
4292 	/* XXXX argh, passing raw pointers back into libmidi++ */
4293 
4294 	MIDI::Port* mmc_in = async_in.get();
4295 	MIDI::Port* mmc_out = async_out.get();
4296 
4297 	_mmc->set_ports (mmc_in, mmc_out);
4298 
4299 	_mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
4300 	_mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
4301 	_mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
4302 	_mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
4303 	_mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
4304 	_mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
4305 	_mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
4306 	_mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
4307 	_mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
4308 	_mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
4309 	_mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
4310 	_mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
4311 	_mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
4312 
4313 	/* also handle MIDI SPP because its so common */
4314 
4315 	_mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
4316 	_mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
4317 	_mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
4318 }
4319 
4320 boost::shared_ptr<Controllable>
solo_cut_control() const4321 Session::solo_cut_control() const
4322 {
4323 	/* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
4324 	 * controls in Ardour that currently get presented to the user in the GUI that require
4325 	 * access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
4326 	 *
4327 	 * its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
4328 	 * it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
4329 	 * parameter.
4330 	 */
4331 	return _solo_cut_control;
4332 }
4333 
4334 void
save_snapshot_name(const std::string & n)4335 Session::save_snapshot_name (const std::string & n)
4336 {
4337 	/* assure Stateful::_instant_xml is loaded
4338 	 * add_instant_xml() only adds to existing data and defaults
4339 	 * to use an empty Tree otherwise
4340 	 */
4341 	instant_xml ("LastUsedSnapshot");
4342 
4343 	XMLNode last_used_snapshot ("LastUsedSnapshot");
4344 	last_used_snapshot.set_property ("name", n);
4345 	add_instant_xml (last_used_snapshot, false);
4346 }
4347 
4348 void
set_snapshot_name(const std::string & n)4349 Session::set_snapshot_name (const std::string & n)
4350 {
4351 	_current_snapshot_name = n;
4352 	save_snapshot_name (n);
4353 }
4354 
4355 int
rename(const std::string & new_name)4356 Session::rename (const std::string& new_name)
4357 {
4358 	string legal_name = legalize_for_path (new_name);
4359 	string new_path;
4360 	string oldstr;
4361 	string newstr;
4362 	bool first = true;
4363 
4364 	string const old_sources_root = _session_dir->sources_root();
4365 
4366 	if (!_writable || cannot_save ()) {
4367 		error << _("Cannot rename read-only session.") << endmsg;
4368 		return 0; // don't show "messed up" warning
4369 	}
4370 	if (record_status() == Recording) {
4371 		error << _("Cannot rename session while recording") << endmsg;
4372 		return 0; // don't show "messed up" warning
4373 	}
4374 
4375 	StateProtector stp (this);
4376 
4377 	/* Rename:
4378 
4379 	 * session directory
4380 	 * interchange subdirectory
4381 	 * session file
4382 	 * session history
4383 
4384 	 * Backup files are left unchanged and not renamed.
4385 	 */
4386 
4387 	/* Windows requires that we close all files before attempting the
4388 	 * rename. This works on other platforms, but isn't necessary there.
4389 	 * Leave it in place for all platforms though, since it may help
4390 	 * catch issues that could arise if the way Source files work ever
4391 	 * change (since most developers are not using Windows).
4392 	 */
4393 
4394 	for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4395 		boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4396 		if (fs) {
4397 			fs->close ();
4398 		}
4399 	}
4400 
4401 	/* pass one: not 100% safe check that the new directory names don't
4402 	 * already exist ...
4403 	 */
4404 
4405 	for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4406 
4407 		oldstr = (*i).path;
4408 
4409 		/* this is a stupid hack because Glib::path_get_dirname() is
4410 		 * lexical-only, and so passing it /a/b/c/ gives a different
4411 		 * result than passing it /a/b/c ...
4412 		 */
4413 
4414 		if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4415 			oldstr = oldstr.substr (0, oldstr.length() - 1);
4416 		}
4417 
4418 		string base = Glib::path_get_dirname (oldstr);
4419 
4420 		newstr = Glib::build_filename (base, legal_name);
4421 
4422 		cerr << "Looking for " << newstr << endl;
4423 
4424 		if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4425 			cerr << " exists\n";
4426 			return -1;
4427 		}
4428 	}
4429 
4430 	/* Session dirs */
4431 
4432 	first = true;
4433 
4434 	for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4435 
4436 		vector<string> v;
4437 
4438 		oldstr = (*i).path;
4439 
4440 		/* this is a stupid hack because Glib::path_get_dirname() is
4441 		 * lexical-only, and so passing it /a/b/c/ gives a different
4442 		 * result than passing it /a/b/c ...
4443 		 */
4444 
4445 		if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4446 			oldstr = oldstr.substr (0, oldstr.length() - 1);
4447 		}
4448 
4449 		string base = Glib::path_get_dirname (oldstr);
4450 		newstr = Glib::build_filename (base, legal_name);
4451 
4452 		cerr << "for " << oldstr << " new dir = " << newstr << endl;
4453 
4454 		cerr << "Rename " << oldstr << " => " << newstr << endl;
4455 		if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4456 			cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4457 			error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4458 			return 1;
4459 		}
4460 
4461 		/* Reset path in "session dirs" */
4462 
4463 		(*i).path = newstr;
4464 		(*i).blocks = 0;
4465 
4466 		/* reset primary SessionDirectory object */
4467 
4468 		if (first) {
4469 			(*_session_dir) = newstr;
4470 			new_path = newstr;
4471 			first = false;
4472 		}
4473 
4474 		/* now rename directory below session_dir/interchange */
4475 
4476 		string old_interchange_dir;
4477 		string new_interchange_dir;
4478 
4479 		/* use newstr here because we renamed the path
4480 		 * (folder/directory) that used to be oldstr to newstr above
4481 		 */
4482 
4483 		v.push_back (newstr);
4484 		v.push_back (interchange_dir_name);
4485 		v.push_back (Glib::path_get_basename (oldstr));
4486 
4487 		old_interchange_dir = Glib::build_filename (v);
4488 
4489 		v.clear ();
4490 		v.push_back (newstr);
4491 		v.push_back (interchange_dir_name);
4492 		v.push_back (legal_name);
4493 
4494 		new_interchange_dir = Glib::build_filename (v);
4495 
4496 		cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4497 
4498 		if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4499 			cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4500 			                        old_interchange_dir, new_interchange_dir,
4501 			                        g_strerror (errno))
4502 			     << endl;
4503 			error << string_compose (_("renaming %s as %2 failed (%3)"),
4504 			                         old_interchange_dir, new_interchange_dir,
4505 			                         g_strerror (errno))
4506 			      << endmsg;
4507 			return 1;
4508 		}
4509 	}
4510 
4511 	/* state file */
4512 
4513 	oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4514 	newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4515 
4516 	cerr << "Rename " << oldstr << " => " << newstr << endl;
4517 
4518 	if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4519 		cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4520 		error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4521 		return 1;
4522 	}
4523 
4524 	/* history file */
4525 
4526 	oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4527 
4528 	if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS))  {
4529 		newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4530 
4531 		cerr << "Rename " << oldstr << " => " << newstr << endl;
4532 
4533 		if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4534 			cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4535 			error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4536 			return 1;
4537 		}
4538 	}
4539 
4540 	/* remove old name from recent sessions */
4541 	remove_recent_sessions (_path);
4542 	_path = new_path;
4543 
4544 	/* update file source paths */
4545 
4546 	for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4547 		boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4548 		if (fs) {
4549 			string p = fs->path ();
4550 			boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4551 			fs->set_path (p);
4552 			SourceFactory::setup_peakfile(i->second, true);
4553 		}
4554 	}
4555 
4556 	set_snapshot_name (new_name);
4557 	_name = new_name;
4558 
4559 	set_dirty ();
4560 
4561 	/* save state again to get everything just right */
4562 
4563 	save_state (_current_snapshot_name);
4564 
4565 	/* add to recent sessions */
4566 
4567 	store_recent_sessions (new_name, _path);
4568 
4569 	/* remove unnamed file name, if any (it's not an error if it doesn't exist) */
4570 	::g_unlink (unnamed_file_name().c_str());
4571 
4572 	return 0;
4573 }
4574 
4575 int
parse_stateful_loading_version(const std::string & version)4576 Session::parse_stateful_loading_version (const std::string& version)
4577 {
4578 	if (version.empty ()) {
4579 		/* no version implies very old version of Ardour */
4580 		return 1000;
4581 	}
4582 
4583 	if (version.find ('.') != string::npos) {
4584 		/* old school version format */
4585 		if (version[0] == '2') {
4586 			return 2000;
4587 		} else {
4588 			return 3000;
4589 		}
4590 	} else {
4591 		return string_to<int32_t>(version);
4592 	}
4593 }
4594 
4595 int
get_info_from_path(const string & xmlpath,float & sample_rate,SampleFormat & data_format,std::string & program_version,XMLNode * engine_hints)4596 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format, std::string& program_version, XMLNode* engine_hints)
4597 {
4598 	bool found_sr = false;
4599 	bool found_data_format = false;
4600 	std::string version;
4601 	program_version = "";
4602 
4603 	if (engine_hints) {
4604 		/* clear existing properties */
4605 		*engine_hints = XMLNode ("EngineHints");
4606 	}
4607 
4608 	if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4609 		return -1;
4610 	}
4611 
4612 	xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
4613 	if (ctxt == NULL) {
4614 		return -1;
4615 	}
4616 	xmlDocPtr doc = xmlCtxtReadFile (ctxt, xmlpath.c_str(), NULL, XML_PARSE_HUGE);
4617 
4618 	if (doc == NULL) {
4619 		xmlFreeParserCtxt(ctxt);
4620 		return -1;
4621 	}
4622 
4623 	xmlNodePtr node = xmlDocGetRootElement(doc);
4624 
4625 	if (node == NULL) {
4626 		xmlFreeParserCtxt(ctxt);
4627 		xmlFreeDoc (doc);
4628 		return -1;
4629 	}
4630 
4631 	/* sample rate & version*/
4632 
4633 	xmlAttrPtr attr;
4634 	for (attr = node->properties; attr; attr = attr->next) {
4635 		if (!strcmp ((const char*)attr->name, "version") && attr->children) {
4636 			version = std::string ((char*)attr->children->content);
4637 		}
4638 		if (!strcmp ((const char*)attr->name, "sample-rate") && attr->children) {
4639 			sample_rate = atoi ((char*)attr->children->content);
4640 			found_sr = true;
4641 		}
4642 	}
4643 
4644 	if ((parse_stateful_loading_version(version) / 1000L) > (CURRENT_SESSION_FILE_VERSION / 1000L)) {
4645 		return -1;
4646 	}
4647 
4648 	if ((parse_stateful_loading_version(version) / 1000L) <= 2) {
4649 		/* sample-format '0' is implicit */
4650 		data_format = FormatFloat;
4651 		found_data_format = true;
4652 	}
4653 
4654 	node = node->children;
4655 	while (node != NULL) {
4656 		 if (!strcmp((const char*) node->name, "ProgramVersion")) {
4657 			 xmlChar* val = xmlGetProp (node, (const xmlChar*)"modified-with");
4658 			 if (val) {
4659 				 program_version = string ((const char*)val);
4660 				 size_t sep = program_version.find_first_of("-");
4661 				 if (sep != string::npos) {
4662 					 program_version = program_version.substr (0, sep);
4663 				 }
4664 			 }
4665 			 xmlFree (val);
4666 		 }
4667 		 if (engine_hints && strcmp((const char*) node->name, "EngineHints") == 0)  {
4668 			 xmlChar* val = xmlGetProp (node, (const xmlChar*)"backend");
4669 			 if (val) {
4670 				 engine_hints->set_property ("backend", (const char*)val);
4671 			 }
4672 			 xmlFree (val);
4673 			 val = xmlGetProp (node, (const xmlChar*)"input-device");
4674 			 if (val) {
4675 				 engine_hints->set_property ("input-device", (const char*)val);
4676 			 }
4677 			 xmlFree (val);
4678 			 val = xmlGetProp (node, (const xmlChar*)"output-device");
4679 			 if (val) {
4680 				 engine_hints->set_property ("output-device", (const char*)val);
4681 			 }
4682 			 xmlFree (val);
4683 		 }
4684 
4685 		 if (strcmp((const char*) node->name, "Config")) {
4686 			 node = node->next;
4687 			 continue;
4688 		 }
4689 		 for (node = node->children; node; node = node->next) {
4690 			 xmlChar* pv = xmlGetProp (node, (const xmlChar*)"name");
4691 			 if (pv && !strcmp ((const char*)pv, "native-file-data-format")) {
4692 				 xmlFree (pv);
4693 				 xmlChar* val = xmlGetProp (node, (const xmlChar*)"value");
4694 				 if (val) {
4695 					 try {
4696 						 SampleFormat fmt = (SampleFormat) string_2_enum (string ((const char*)val), fmt);
4697 						 data_format = fmt;
4698 						 found_data_format = true;
4699 					 } catch (PBD::unknown_enumeration& e) {}
4700 				 }
4701 				 xmlFree (val);
4702 				 break;
4703 			 }
4704 			 xmlFree (pv);
4705 		 }
4706 		 break;
4707 	}
4708 
4709 	xmlFreeParserCtxt(ctxt);
4710 	xmlFreeDoc (doc);
4711 
4712 	return (found_sr && found_data_format) ? 0 : 1;
4713 }
4714 
4715 std::string
get_snapshot_from_instant(const std::string & session_dir)4716 Session::get_snapshot_from_instant (const std::string& session_dir)
4717 {
4718 	std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4719 
4720 	if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4721 		return "";
4722 	}
4723 
4724 	XMLTree tree;
4725 	if (!tree.read (instant_xml_path)) {
4726 		return "";
4727 	}
4728 
4729 	XMLProperty const * prop;
4730 	XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4731 	if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4732 		return prop->value();
4733 	}
4734 
4735 	return "";
4736 }
4737 
4738 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4739 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4740 
4741 int
bring_all_sources_into_session(boost::function<void (uint32_t,uint32_t,string)> callback)4742 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4743 {
4744 	uint32_t total = 0;
4745 	uint32_t n = 0;
4746 	SourcePathMap source_path_map;
4747 	string new_path;
4748 	boost::shared_ptr<AudioFileSource> afs;
4749 	int ret = 0;
4750 
4751 	{
4752 
4753 		Glib::Threads::Mutex::Lock lm (source_lock);
4754 
4755 		cerr << " total sources = " << sources.size();
4756 
4757 		for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4758 			boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4759 
4760 			if (!fs) {
4761 				continue;
4762 			}
4763 
4764 			if (fs->within_session()) {
4765 				continue;
4766 			}
4767 
4768 			if (source_path_map.find (fs->path()) != source_path_map.end()) {
4769 				source_path_map[fs->path()].push_back (fs);
4770 			} else {
4771 				SeveralFileSources v;
4772 				v.push_back (fs);
4773 				source_path_map.insert (make_pair (fs->path(), v));
4774 			}
4775 
4776 			total++;
4777 		}
4778 
4779 		cerr << " fsources = " << total << endl;
4780 
4781 		for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4782 
4783 			/* tell caller where we are */
4784 
4785 			string old_path = i->first;
4786 
4787 			callback (n, total, old_path);
4788 
4789 			cerr << old_path << endl;
4790 
4791 			new_path.clear ();
4792 
4793 			switch (i->second.front()->type()) {
4794 			case DataType::AUDIO:
4795 				new_path = new_audio_source_path_for_embedded (old_path);
4796 				break;
4797 
4798 			case DataType::MIDI:
4799 				/* XXX not implemented yet */
4800 				break;
4801 			}
4802 
4803 			if (new_path.empty()) {
4804 				continue;
4805 			}
4806 
4807 			cerr << "Move " << old_path << " => " << new_path << endl;
4808 
4809 			if (!copy_file (old_path, new_path)) {
4810 				cerr << "failed !\n";
4811 				ret = -1;
4812 			}
4813 
4814 			/* make sure we stop looking in the external
4815 			   dir/folder. Remember, this is an all-or-nothing
4816 			   operations, it doesn't merge just some files.
4817 			*/
4818 			remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4819 
4820 			for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4821 				(*f)->set_path (new_path);
4822 			}
4823 		}
4824 	}
4825 
4826 	save_state ();
4827 
4828 	return ret;
4829 }
4830 
4831 static
accept_all_files(string const &,void *)4832 bool accept_all_files (string const &, void *)
4833 {
4834 	return true;
4835 }
4836 
4837 void
save_as_bring_callback(uint32_t,uint32_t,string)4838 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4839 {
4840 	/* It would be good if this did something useful vis-a-vis save-as, but the arguments doesn't provide the correct information right now to do this.
4841 	*/
4842 }
4843 
4844 static string
make_new_media_path(string old_path,string new_session_folder,string new_session_name)4845 make_new_media_path (string old_path, string new_session_folder, string new_session_name)
4846 {
4847 	// old_path must be in within_session ()
4848 	string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4849 	vector<string> v;
4850 	v.push_back (new_session_folder); /* full path */
4851 	v.push_back (interchange_dir_name);
4852 	v.push_back (new_session_name);   /* just one directory/folder */
4853 	v.push_back (typedir);
4854 	v.push_back (Glib::path_get_basename (old_path));
4855 
4856 	return Glib::build_filename (v);
4857 }
4858 
4859 static string
make_new_audio_path(string filename,string new_session_folder,string new_session_name)4860 make_new_audio_path (string filename, string new_session_folder, string new_session_name)
4861 {
4862 	vector<string> v;
4863 	v.push_back (new_session_folder); /* full path */
4864 	v.push_back (interchange_dir_name);
4865 	v.push_back (new_session_name);
4866 	v.push_back (ARDOUR::sound_dir_name);
4867 	v.push_back (filename);
4868 
4869 	return Glib::build_filename (v);
4870 }
4871 
4872 int
save_as(SaveAs & saveas)4873 Session::save_as (SaveAs& saveas)
4874 {
4875 	vector<string> files;
4876 	string current_folder = Glib::path_get_dirname (_path);
4877 	string new_folder = legalize_for_path (saveas.new_name);
4878 	string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4879 	int64_t total_bytes = 0;
4880 	int64_t copied = 0;
4881 	int64_t cnt = 0;
4882 	int64_t all = 0;
4883 	int32_t internal_file_cnt = 0;
4884 
4885 	vector<string> do_not_copy_extensions;
4886 	do_not_copy_extensions.push_back (statefile_suffix);
4887 	do_not_copy_extensions.push_back (pending_suffix);
4888 	do_not_copy_extensions.push_back (backup_suffix);
4889 	do_not_copy_extensions.push_back (temp_suffix);
4890 	do_not_copy_extensions.push_back (history_suffix);
4891 
4892 	/* get total size */
4893 
4894 	for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4895 
4896 		/* need to clear this because
4897 		 * find_files_matching_filter() is cumulative
4898 		 */
4899 
4900 		files.clear ();
4901 
4902 		find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4903 
4904 		all += files.size();
4905 
4906 		for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4907 			GStatBuf gsb;
4908 			g_stat ((*i).c_str(), &gsb);
4909 			total_bytes += gsb.st_size;
4910 		}
4911 	}
4912 
4913 	/* save old values so we can switch back if we are not switching to the new session */
4914 
4915 	string old_path = _path;
4916 	string old_name = _name;
4917 	string old_snapshot = _current_snapshot_name;
4918 	string old_sd = _session_dir->root_path();
4919 	vector<string> old_search_path[DataType::num_types];
4920 	string old_config_search_path[DataType::num_types];
4921 
4922 	old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4923 	old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4924 	old_config_search_path[DataType::AUDIO]  = config.get_audio_search_path ();
4925 	old_config_search_path[DataType::MIDI]  = config.get_midi_search_path ();
4926 
4927 	/* switch session directory */
4928 
4929 	(*_session_dir) = to_dir;
4930 
4931 	/* create new tree */
4932 
4933 	if (!_session_dir->create()) {
4934 		saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4935 		return -1;
4936 	}
4937 
4938 	try {
4939 		/* copy all relevant files. Find each location in session_dirs,
4940 		 * and copy files from there to target.
4941 		 */
4942 
4943 		for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4944 
4945 			/* need to clear this because
4946 			 * find_files_matching_filter() is cumulative
4947 			 */
4948 
4949 			files.clear ();
4950 
4951 			const size_t prefix_len = (*sd).path.size();
4952 
4953 			/* Work just on the files within this session dir */
4954 
4955 			find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4956 
4957 			/* add dir separator to protect against collisions with
4958 			 * track names (e.g. track named "audiofiles" or
4959 			 * "analysis".
4960 			 */
4961 
4962 			static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4963 			static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4964 			static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4965 
4966 			/* copy all the files. Handling is different for media files
4967 			   than others because of the *silly* subtree we have below the interchange
4968 			   folder. That really was a bad idea, but I'm not fixing it as part of
4969 			   implementing ::save_as().
4970 			*/
4971 
4972 			for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4973 
4974 				std::string from = *i;
4975 
4976 #ifdef __APPLE__
4977 				string filename = Glib::path_get_basename (from);
4978 				std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4979 				if (filename == ".DS_STORE") {
4980 					continue;
4981 				}
4982 #endif
4983 
4984 				if (from.find (audiofile_dir_string) != string::npos) {
4985 
4986 					/* audio file: only copy if asked */
4987 
4988 					if (saveas.include_media && saveas.copy_media) {
4989 
4990 						string to = make_new_media_path (*i, to_dir, new_folder);
4991 
4992 						info << "media file copying from " << from << " to " << to << endmsg;
4993 
4994 						if (!copy_file (from, to)) {
4995 							throw Glib::FileError (Glib::FileError::IO_ERROR,
4996 												   string_compose(_("\ncopying \"%1\" failed !"), from));
4997 						}
4998 					}
4999 
5000 					/* we found media files inside the session folder */
5001 
5002 					internal_file_cnt++;
5003 
5004 				} else if (from.find (midifile_dir_string) != string::npos) {
5005 
5006 					/* midi file: always copy unless
5007 					 * creating an empty new session
5008 					 */
5009 
5010 					if (saveas.include_media) {
5011 
5012 						string to = make_new_media_path (*i, to_dir, new_folder);
5013 
5014 						info << "media file copying from " << from << " to " << to << endmsg;
5015 
5016 						if (!copy_file (from, to)) {
5017 							throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
5018 						}
5019 					}
5020 
5021 					/* we found media files inside the session folder */
5022 
5023 					internal_file_cnt++;
5024 
5025 				} else if (from.find (analysis_dir_string) != string::npos) {
5026 
5027 					/*  make sure analysis dir exists in
5028 					 *  new session folder, but we're not
5029 					 *  copying analysis files here, see
5030 					 *  below
5031 					 */
5032 
5033 					(void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
5034 					continue;
5035 
5036 				} else {
5037 
5038 					/* normal non-media file. Don't copy state, history, etc.
5039 					 */
5040 
5041 					bool do_copy = true;
5042 
5043 					for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
5044 						if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
5045 							/* end of filename matches extension, do not copy file */
5046 							do_copy = false;
5047 							break;
5048 						}
5049 					}
5050 
5051 					if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
5052 						/* don't copy peakfiles if
5053 						 * we're not copying media
5054 						 */
5055 						do_copy = false;
5056 					}
5057 
5058 					if (do_copy) {
5059 						string to = Glib::build_filename (to_dir, from.substr (prefix_len));
5060 
5061 						info << "attempting to make directory/folder " << to << endmsg;
5062 
5063 						if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
5064 							throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
5065 						}
5066 
5067 						info << "attempting to copy " << from << " to " << to << endmsg;
5068 
5069 						if (!copy_file (from, to)) {
5070 							throw Glib::FileError (Glib::FileError::IO_ERROR,
5071 												   string_compose(_("\ncopying \"%1\" failed !"), from));
5072 						}
5073 					}
5074 				}
5075 
5076 				/* measure file size even if we're not going to copy so that our Progress
5077 				   signals are correct, since we included these do-not-copy files
5078 				   in the computation of the total size and file count.
5079 				*/
5080 
5081 				GStatBuf gsb;
5082 				g_stat (from.c_str(), &gsb);
5083 				copied += gsb.st_size;
5084 				cnt++;
5085 
5086 				double fraction = (double) copied / total_bytes;
5087 
5088 				bool keep_going = true;
5089 
5090 				if (saveas.copy_media) {
5091 
5092 					/* no need or expectation of this if
5093 					 * media is not being copied, because
5094 					 * it will be fast(ish).
5095 					 */
5096 
5097 					/* tell someone "X percent, file M of N"; M is one-based */
5098 
5099 					boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
5100 
5101 					if (res) {
5102 						keep_going = *res;
5103 					}
5104 				}
5105 
5106 				if (!keep_going) {
5107 					throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
5108 				}
5109 			}
5110 
5111 		}
5112 
5113 		/* copy optional folders, if any */
5114 
5115 		string old = plugins_dir ();
5116 		if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
5117 			string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
5118 			copy_files (old, newdir);
5119 		}
5120 
5121 		old = externals_dir ();
5122 		if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
5123 			string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
5124 			copy_files (old, newdir);
5125 		}
5126 
5127 		old = automation_dir ();
5128 		if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
5129 			string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
5130 			copy_files (old, newdir);
5131 		}
5132 
5133 		if (saveas.include_media) {
5134 
5135 			if (saveas.copy_media) {
5136 #ifndef PLATFORM_WINDOWS
5137 				/* There are problems with analysis files on
5138 				 * Windows, because they used a colon in their
5139 				 * names as late as 4.0. Colons are not legal
5140 				 * under Windows even if NTFS allows them.
5141 				 *
5142 				 * This is a tricky problem to solve so for
5143 				 * just don't copy these files. They will be
5144 				 * regenerated as-needed anyway, subject to the
5145 				 * existing issue that the filenames will be
5146 				 * rejected by Windows, which is a separate
5147 				 * problem (though related).
5148 				 */
5149 
5150 				/* only needed if we are copying media, since the
5151 				 * analysis data refers to media data
5152 				 */
5153 
5154 				old = analysis_dir ();
5155 				if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
5156 					string newdir = Glib::build_filename (to_dir, "analysis");
5157 					copy_files (old, newdir);
5158 				}
5159 #endif /* PLATFORM_WINDOWS */
5160 			}
5161 		}
5162 
5163 		_path = to_dir;
5164 		set_snapshot_name (saveas.new_name);
5165 		_name = saveas.new_name;
5166 
5167 		if (saveas.include_media && !saveas.copy_media) {
5168 
5169 			/* reset search paths of the new session (which we're pretending to be right now) to
5170 			   include the original session search path, so we can still find all audio.
5171 			*/
5172 
5173 			if (internal_file_cnt) {
5174 				for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
5175 					ensure_search_path_includes (*s, DataType::AUDIO);
5176 					cerr << "be sure to include " << *s << "  for audio" << endl;
5177 				}
5178 
5179 				/* we do not do this for MIDI because we copy
5180 				   all MIDI files if saveas.include_media is
5181 				   true
5182 				*/
5183 			}
5184 		}
5185 
5186 		bool was_dirty = dirty ();
5187 
5188 		save_default_options ();
5189 
5190 		if (saveas.copy_media && saveas.copy_external) {
5191 			if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
5192 				throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
5193 			}
5194 		}
5195 
5196 		saveas.final_session_folder_name = _path;
5197 
5198 		store_recent_sessions (_name, _path);
5199 
5200 		if (!saveas.switch_to) {
5201 
5202 			/* save the new state */
5203 
5204 			save_state ("", false, false, !saveas.include_media);
5205 
5206 			/* switch back to the way things were */
5207 
5208 			_path = old_path;
5209 			_name = old_name;
5210 			set_snapshot_name (old_snapshot);
5211 
5212 			(*_session_dir) = old_sd;
5213 
5214 			if (was_dirty) {
5215 				set_dirty ();
5216 			}
5217 
5218 			if (internal_file_cnt) {
5219 				/* reset these to their original values */
5220 				config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
5221 				config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
5222 			}
5223 
5224 		} else {
5225 
5226 			/* prune session dirs, and update disk space statistics
5227 			 */
5228 
5229 			space_and_path sp;
5230 			sp.path = _path;
5231 			session_dirs.clear ();
5232 			session_dirs.push_back (sp);
5233 			refresh_disk_space ();
5234 
5235 			_writable = exists_and_writable (_path);
5236 
5237 			/* ensure that all existing tracks reset their current capture source paths
5238 			 */
5239 			reset_write_sources (true, true);
5240 
5241 			/* creating new write sources marks the session as
5242 			   dirty. If the new session is empty, then
5243 			   save_state() thinks we're saving a template and will
5244 			   not mark the session as clean. So do that here,
5245 			   before we save state.
5246 			*/
5247 
5248 			if (!saveas.include_media) {
5249 				unset_dirty ();
5250 			}
5251 
5252 			save_state ("", false, false, !saveas.include_media);
5253 
5254 			/* the copying above was based on actually discovering files, not just iterating over the sources list.
5255 			   But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
5256 			*/
5257 
5258 			for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5259 				boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
5260 
5261 				if (!fs) {
5262 					continue;
5263 				}
5264 
5265 				if (fs->within_session()) {
5266 					string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
5267 					fs->set_path (newpath);
5268 				}
5269 			}
5270 		}
5271 
5272 	} catch (Glib::FileError& e) {
5273 
5274 		saveas.failure_message = e.what();
5275 
5276 		/* recursively remove all the directories */
5277 
5278 		remove_directory (to_dir);
5279 
5280 		/* return error */
5281 
5282 		return -1;
5283 
5284 	} catch (...) {
5285 
5286 		saveas.failure_message = _("unknown reason");
5287 
5288 		/* recursively remove all the directories */
5289 
5290 		remove_directory (to_dir);
5291 
5292 		/* return error */
5293 
5294 		return -1;
5295 	}
5296 
5297 	return 0;
5298 }
5299 
set_progress(Progress * p,size_t n,size_t t)5300 static void set_progress (Progress* p, size_t n, size_t t)
5301 {
5302 	p->set_progress (float (n) / float(t));
5303 }
5304 
5305 int
archive_session(const std::string & dest,const std::string & name,ArchiveEncode compress_audio,FileArchive::CompressionLevel compression_level,bool only_used_sources,Progress * progress)5306 Session::archive_session (const std::string& dest,
5307                           const std::string& name,
5308                           ArchiveEncode compress_audio,
5309                           FileArchive::CompressionLevel compression_level,
5310                           bool only_used_sources,
5311                           Progress* progress)
5312 {
5313 	if (dest.empty () || name.empty ()) {
5314 		return -1;
5315 	}
5316 
5317 	/* We are going to temporarily change some source properties,
5318 	 * don't allow any concurrent saves (periodic or otherwise */
5319 	Glib::Threads::Mutex::Lock lm (save_source_lock);
5320 
5321 	disable_record (false);
5322 
5323 	/* save current values */
5324 	string old_path = _path;
5325 	string old_name = _name;
5326 	string old_snapshot = _current_snapshot_name;
5327 	string old_sd = _session_dir->root_path();
5328 	string old_config_search_path[DataType::num_types];
5329 	old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
5330 	old_config_search_path[DataType::MIDI]  = config.get_midi_search_path ();
5331 
5332 	/* ensure that session-path is included in search-path */
5333 	bool ok = false;
5334 	for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
5335 		if ((*sd).path == old_path) {
5336 			ok = true;
5337 		}
5338 	}
5339 	if (!ok) {
5340 		return -1;
5341 	}
5342 
5343 	/* create temporary dir to save session to */
5344 	GError* err = NULL;
5345 	char* td = g_dir_make_tmp ("ardourarchive-XXXXXX", &err);
5346 
5347 	if (!td) {
5348 		error << string_compose(_("Could not make tmpdir: %1"), err->message) << endmsg;
5349 		return -1;
5350 	}
5351 	const string to_dir = PBD::canonical_path (td);
5352 	g_free (td);
5353 	g_clear_error (&err);
5354 
5355 	/* switch session directory temporarily */
5356 	(*_session_dir) = to_dir;
5357 
5358 	if (!_session_dir->create()) {
5359 		(*_session_dir) = old_sd;
5360 		remove_directory (to_dir);
5361 		return -1;
5362 	}
5363 
5364 	/* prepare archive */
5365 	string archive = Glib::build_filename (dest, name + session_archive_suffix);
5366 
5367 	PBD::ScopedConnectionList progress_connection;
5368 	PBD::FileArchive ar (archive);
5369 	if (progress) {
5370 		ar.progress.connect_same_thread (progress_connection, boost::bind (&set_progress, progress, _1, _2));
5371 	}
5372 
5373 	/* collect files to archive */
5374 	std::map<string,string> filemap;
5375 
5376 	vector<string> do_not_copy_extensions;
5377 	do_not_copy_extensions.push_back (statefile_suffix);
5378 	do_not_copy_extensions.push_back (pending_suffix);
5379 	do_not_copy_extensions.push_back (backup_suffix);
5380 	do_not_copy_extensions.push_back (temp_suffix);
5381 	do_not_copy_extensions.push_back (history_suffix);
5382 
5383 	vector<string> blacklist_dirs;
5384 	blacklist_dirs.push_back (string (peak_dir_name) + G_DIR_SEPARATOR);
5385 	blacklist_dirs.push_back (string (analysis_dir_name) + G_DIR_SEPARATOR);
5386 	blacklist_dirs.push_back (string (dead_dir_name) + G_DIR_SEPARATOR);
5387 	blacklist_dirs.push_back (string (export_dir_name) + G_DIR_SEPARATOR);
5388 	blacklist_dirs.push_back (string (externals_dir_name) + G_DIR_SEPARATOR);
5389 	blacklist_dirs.push_back (string (plugins_dir_name) + G_DIR_SEPARATOR);
5390 
5391 	std::map<boost::shared_ptr<AudioFileSource>, std::string> orig_sources;
5392 	std::map<boost::shared_ptr<AudioFileSource>, std::string> orig_origin;
5393 	std::map<boost::shared_ptr<AudioFileSource>, float> orig_gain;
5394 
5395 	set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
5396 	if (only_used_sources) {
5397 		_playlists->sync_all_regions_with_regions ();
5398 		_playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot), false);
5399 	}
5400 
5401 	/* collect audio sources for this session, calc total size for encoding
5402 	 * add option to only include *used* sources (see Session::cleanup_sources)
5403 	 */
5404 	size_t total_size = 0;
5405 	{
5406 		Glib::Threads::Mutex::Lock lm (source_lock);
5407 
5408 		/* build a list of used names */
5409 		std::set<std::string> audio_file_names;
5410 		for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5411 			if (boost::dynamic_pointer_cast<SilentFileSource> (i->second)) {
5412 				continue;
5413 			}
5414 			boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (i->second);
5415 			if (!afs || afs->readable_length () == 0) {
5416 				continue;
5417 			}
5418 			if (only_used_sources) {
5419 				if (!afs->used()) {
5420 					continue;
5421 				}
5422 				if (sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
5423 					continue;
5424 				}
5425 			}
5426 			audio_file_names.insert (Glib::path_get_basename (afs->path()));
5427 		}
5428 
5429 		for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5430 			if (boost::dynamic_pointer_cast<SilentFileSource> (i->second)) {
5431 				continue;
5432 			}
5433 			boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (i->second);
5434 			if (!afs || afs->readable_length () == 0) {
5435 				continue;
5436 			}
5437 
5438 			if (only_used_sources) {
5439 				if (!afs->used()) {
5440 					continue;
5441 				}
5442 				if (sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
5443 					continue;
5444 				}
5445 			}
5446 
5447 			std::string from = afs->path();
5448 
5449 			if (compress_audio != NO_ENCODE) {
5450 				total_size += afs->readable_length ();
5451 			} else {
5452 				/* copy files as-is */
5453 				if (!afs->within_session()) {
5454 					string to = Glib::path_get_basename (from);
5455 
5456 					/* avoid name collitions, see also new_audio_source_path_for_embedded ()
5457 					 * - avoid conflict with files existing in interchange
5458 					 * - avoid conflict with other embedded sources
5459 					 */
5460 					if (audio_file_names.find (to) == audio_file_names.end ()) {
5461 						// we need a new name, add a '-<num>' before the '.<ext>'
5462 						string bn   = to.substr (0, to.find_last_of ('.'));
5463 						string ext  = to.find_last_of ('.') == string::npos ? "" : to.substr (to.find_last_of ('.'));
5464 						to = bn + "-1" + ext;
5465 					}
5466 					while (audio_file_names.find (to) == audio_file_names.end ()) {
5467 						to = bump_name_once (to, '-');
5468 					}
5469 
5470 					audio_file_names.insert (to);
5471 					filemap[from] = make_new_audio_path (to, name, name);
5472 
5473 					remove_dir_from_search_path (Glib::path_get_dirname (from), DataType::AUDIO);
5474 
5475 					orig_origin[afs] = afs->origin ();
5476 					afs->set_origin ("");
5477 
5478 				} else {
5479 					filemap[from] = make_new_media_path (from, name, name);
5480 				}
5481 			}
5482 		}
5483 	}
5484 
5485 	/* encode audio */
5486 	if (compress_audio != NO_ENCODE) {
5487 		if (progress) {
5488 			progress->set_progress (2); // set to "encoding"
5489 			progress->set_progress (0);
5490 		}
5491 
5492 		Glib::Threads::Mutex::Lock lm (source_lock);
5493 		for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
5494 			if (boost::dynamic_pointer_cast<SilentFileSource> (i->second)) {
5495 				continue;
5496 			}
5497 			boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (i->second);
5498 			if (!afs || afs->readable_length () == 0) {
5499 				continue;
5500 			}
5501 
5502 			if (only_used_sources) {
5503 				if (!afs->used()) {
5504 					continue;
5505 				}
5506 				if (sources_used_by_this_snapshot.find (afs) == sources_used_by_this_snapshot.end ()) {
5507 					continue;
5508 				}
5509 			}
5510 
5511 			orig_sources[afs] = afs->path();
5512 			orig_gain[afs]    = afs->gain();
5513 
5514 			std::string new_path = make_new_media_path (afs->path (), to_dir, name);
5515 
5516 			std::string channelsuffix = "";
5517 			if (afs->channel() > 0) {  /* n_channels() is /wrongly/ 1. */
5518 				/* embedded external multi-channel files are converted to multiple-mono */
5519 				channelsuffix = string_compose ("-c%1", afs->channel ());
5520 			}
5521 			new_path = Glib::build_filename (Glib::path_get_dirname (new_path), PBD::basename_nosuffix (new_path) + channelsuffix + ".flac");
5522 			g_mkdir_with_parents (Glib::path_get_dirname (new_path).c_str (), 0755);
5523 
5524 			/* avoid name collisions of external files with same name */
5525 			if (Glib::file_test (new_path, Glib::FILE_TEST_EXISTS)) {
5526 				new_path = Glib::build_filename (Glib::path_get_dirname (new_path), PBD::basename_nosuffix (new_path) + channelsuffix + "-1.flac");
5527 			}
5528 			while (Glib::file_test (new_path, Glib::FILE_TEST_EXISTS)) {
5529 				new_path = bump_name_once (new_path, '-');
5530 			}
5531 
5532 			if (progress) {
5533 				progress->descend ((float)afs->readable_length () / total_size);
5534 			}
5535 
5536 			try {
5537 				SndFileSource* ns = new SndFileSource (*this, *(afs.get()), new_path, compress_audio == FLAC_16BIT, progress);
5538 				afs->replace_file (new_path);
5539 				afs->set_gain (ns->gain(), true);
5540 				delete ns;
5541 			} catch (...) {
5542 				cerr << "failed to encode " << afs->path() << " to " << new_path << "\n";
5543 			}
5544 
5545 			if (progress) {
5546 				progress->ascend ();
5547 			}
5548 		}
5549 	}
5550 
5551 	if (progress) {
5552 		progress->set_progress (-1); // set to "archiving"
5553 		progress->set_progress (0);
5554 	}
5555 
5556 	/* index files relevant for this session */
5557 	for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
5558 		vector<string> files;
5559 
5560 		size_t prefix_len = (*sd).path.size();
5561 		if (prefix_len > 0 && (*sd).path.at (prefix_len - 1) != G_DIR_SEPARATOR) {
5562 			++prefix_len;
5563 		}
5564 
5565 		find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
5566 
5567 		static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
5568 		static const std::string videofile_dir_string = string (video_dir_name) + G_DIR_SEPARATOR;
5569 		static const std::string midifile_dir_string  = string (midi_dir_name)  + G_DIR_SEPARATOR;
5570 
5571 		for (vector<string>::const_iterator i = files.begin (); i != files.end (); ++i) {
5572 			std::string from = *i;
5573 
5574 #ifdef __APPLE__
5575 			string filename = Glib::path_get_basename (from);
5576 			std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
5577 			if (filename == ".DS_STORE") {
5578 				continue;
5579 			}
5580 #endif
5581 
5582 			if (from.find (audiofile_dir_string) != string::npos) {
5583 				; // handled above
5584 			} else if (from.find (midifile_dir_string) != string::npos) {
5585 				filemap[from] = make_new_media_path (from, name, name);
5586 			} else if (from.find (videofile_dir_string) != string::npos) {
5587 				filemap[from] = make_new_media_path (from, name, name);
5588 			} else {
5589 				bool do_copy = true;
5590 				for (vector<string>::iterator v = blacklist_dirs.begin(); v != blacklist_dirs.end(); ++v) {
5591 					if (from.find (*v) != string::npos) {
5592 						do_copy = false;
5593 						break;
5594 					}
5595 				}
5596 				for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
5597 					if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
5598 						do_copy = false;
5599 						break;
5600 					}
5601 				}
5602 
5603 				if (do_copy) {
5604 					filemap[from] = name + G_DIR_SEPARATOR + from.substr (prefix_len);
5605 				}
5606 			}
5607 		}
5608 	}
5609 
5610 	/* write session file */
5611 	_path = to_dir;
5612 	g_mkdir_with_parents (externals_dir ().c_str (), 0755);
5613 
5614 	save_state (name, false, false, false, true, only_used_sources);
5615 
5616 	save_default_options ();
5617 
5618 	size_t prefix_len = _path.size();
5619 	if (prefix_len > 0 && _path.at (prefix_len - 1) != G_DIR_SEPARATOR) {
5620 		++prefix_len;
5621 	}
5622 
5623 	/* collect session-state files */
5624 	vector<string> files;
5625 	do_not_copy_extensions.clear ();
5626 	do_not_copy_extensions.push_back (history_suffix);
5627 
5628 	blacklist_dirs.clear ();
5629 	blacklist_dirs.push_back (string (externals_dir_name) + G_DIR_SEPARATOR);
5630 
5631 	find_files_matching_filter (files, to_dir, accept_all_files, 0, false, true, true);
5632 	for (vector<string>::const_iterator i = files.begin (); i != files.end (); ++i) {
5633 		std::string from = *i;
5634 		bool do_copy = true;
5635 		for (vector<string>::iterator v = blacklist_dirs.begin(); v != blacklist_dirs.end(); ++v) {
5636 			if (from.find (*v) != string::npos) {
5637 				do_copy = false;
5638 				break;
5639 			}
5640 		}
5641 		for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
5642 			if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
5643 				do_copy = false;
5644 				break;
5645 			}
5646 		}
5647 		if (do_copy) {
5648 			filemap[from] = name + G_DIR_SEPARATOR + from.substr (prefix_len);
5649 		}
5650 	}
5651 
5652 	/* restore original values */
5653 	_path = old_path;
5654 	_name = old_name;
5655 	set_snapshot_name (old_snapshot);
5656 	(*_session_dir) = old_sd;
5657 	config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
5658 	config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
5659 
5660 	for (std::map<boost::shared_ptr<AudioFileSource>, std::string>::iterator i = orig_origin.begin (); i != orig_origin.end (); ++i) {
5661 		i->first->set_origin (i->second);
5662 	}
5663 	for (std::map<boost::shared_ptr<AudioFileSource>, std::string>::iterator i = orig_sources.begin (); i != orig_sources.end (); ++i) {
5664 		i->first->replace_file (i->second);
5665 	}
5666 	for (std::map<boost::shared_ptr<AudioFileSource>, float>::iterator i = orig_gain.begin (); i != orig_gain.end (); ++i) {
5667 		i->first->set_gain (i->second, true);
5668 	}
5669 
5670 	int rv = ar.create (filemap, compression_level);
5671 	remove_directory (to_dir);
5672 
5673 	return rv;
5674 }
5675 
5676 void
undo(uint32_t n)5677 Session::undo (uint32_t n)
5678 {
5679 	if (actively_recording()) {
5680 		return;
5681 	}
5682 	StateProtector stp (this);
5683 	_history.undo (n);
5684 }
5685 
5686 void
redo(uint32_t n)5687 Session::redo (uint32_t n)
5688 {
5689 	if (actively_recording()) {
5690 		return;
5691 	}
5692 
5693 	StateProtector stp (this);
5694 	_history.redo (n);
5695 }
5696 
5697 std::string
unnamed_file_name() const5698 Session::unnamed_file_name() const
5699 {
5700 	return Glib::build_filename (_path, X_(".unnamed"));
5701 }
5702 
5703 bool
unnamed() const5704 Session::unnamed() const
5705 {
5706 	return Glib::file_test (unnamed_file_name(), Glib::FILE_TEST_EXISTS);
5707 }
5708 
5709 void
end_unnamed_status() const5710 Session::end_unnamed_status () const
5711 {
5712 	::g_remove (unnamed_file_name().c_str());
5713 }
5714