1 /*
2  * Copyright (C) 2005-2007 Doug McLain <doug@nostar.net>
3  * Copyright (C) 2005-2017 Tim Mayberry <mojofunk@gmail.com>
4  * Copyright (C) 2005-2019 Paul Davis <paul@linuxaudiosystems.com>
5  * Copyright (C) 2005 Karsten Wiese <fzuuzf@googlemail.com>
6  * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
7  * Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
8  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
9  * Copyright (C) 2008-2010 Sakari Bergen <sakari.bergen@beatwaves.net>
10  * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
11  * Copyright (C) 2013-2015 Colin Fletcher <colin.m.fletcher@googlemail.com>
12  * Copyright (C) 2013-2016 John Emmas <john@creativepost.co.uk>
13  * Copyright (C) 2013-2016 Nick Mainsbridge <mainsbridge@gmail.com>
14  * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
15  * Copyright (C) 2015 André Nusser <andre.nusser@googlemail.com>
16  * Copyright (C) 2016-2018 Len Ovens <len@ovenwerks.net>
17  * Copyright (C) 2017 Johannes Mueller <github@johannes-mueller.org>
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 2 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License along
30  * with this program; if not, write to the Free Software Foundation, Inc.,
31  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32  */
33 
34 #ifdef WAF_BUILD
35 #include "gtk2ardour-config.h"
36 #include "gtk2ardour-version.h"
37 #endif
38 
39 #ifndef PLATFORM_WINDOWS
40 #include <sys/resource.h>
41 #endif
42 
43 #ifdef __FreeBSD__
44 #include <sys/types.h>
45 #include <sys/sysctl.h>
46 #endif
47 
48 #include <glib.h>
49 #include "pbd/gstdio_compat.h"
50 
51 #include <gtkmm/stock.h>
52 
53 #include "pbd/basename.h"
54 #include "pbd/file_utils.h"
55 
56 #include "ardour/audioengine.h"
57 #include "ardour/filename_extensions.h"
58 #include "ardour/filesystem_paths.h"
59 #include "ardour/profile.h"
60 
61 #include "gtkmm2ext/application.h"
62 
63 #include "ambiguous_file_dialog.h"
64 #include "ardour_message.h"
65 #include "ardour_ui.h"
66 #include "debug.h"
67 #include "engine_dialog.h"
68 #include "keyboard.h"
69 #include "missing_file_dialog.h"
70 #include "nsm.h"
71 #include "opts.h"
72 #include "pingback.h"
73 #include "plugin_scan_dialog.h"
74 #include "public_editor.h"
75 #include "splash.h"
76 
77 #include "pbd/i18n.h"
78 
79 using namespace ARDOUR;
80 using namespace PBD;
81 using namespace Gtk;
82 using namespace Gtkmm2ext;
83 using namespace std;
84 
85 
86 static bool
_hide_splash(gpointer arg)87 _hide_splash (gpointer arg)
88 {
89 	((ARDOUR_UI*)arg)->hide_splash();
90 	return false;
91 }
92 
93 bool
first_idle()94 ARDOUR_UI::first_idle ()
95 {
96 	if (_session) {
97 		_session->reset_xrun_count ();
98 		_session->allow_auto_play (true);
99 	}
100 
101 	if (editor) {
102 		editor->first_idle();
103 	}
104 
105 	/* in 1 second, hide the splash screen */
106 	Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
107 
108 	Keyboard::set_can_save_keybindings (true);
109 	return false;
110 }
111 
112 void
setup_profile()113 ARDOUR_UI::setup_profile ()
114 {
115 	if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
116 		Profile->set_small_screen ();
117 	}
118 
119 	if (g_getenv ("MIXBUS")) {
120 		Profile->set_mixbus ();
121 	}
122 }
123 
124 int
missing_file(Session * s,std::string str,DataType type)125 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
126 {
127 	MissingFileDialog dialog (s, str, type);
128 
129 	dialog.show ();
130 	dialog.present ();
131 
132 	int result = dialog.run ();
133 	dialog.hide ();
134 
135 	switch (result) {
136 	case RESPONSE_OK:
137 		break;
138 	default:
139 		return 1; // quit entire session load
140 	}
141 
142 	result = dialog.get_action ();
143 
144 	return result;
145 }
146 
147 int
ambiguous_file(std::string file,std::vector<std::string> hits)148 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
149 {
150 	AmbiguousFileDialog dialog (file, hits);
151 
152 	dialog.show ();
153 	dialog.present ();
154 
155 	dialog.run ();
156 
157 	return dialog.get_which ();
158 }
159 
160 void
session_format_mismatch(std::string xml_path,std::string backup_path)161 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
162 {
163 	const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
164 	const char* end_big = "</span>";
165 	const char* start_mono = "<tt>";
166 	const char* end_mono = "</tt>";
167 
168 	ArdourMessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
169 	                                           "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
170 	                                           "From now on, use the backup copy with older versions of %3"),
171 	                                         xml_path, backup_path, PROGRAM_NAME,
172 	                                         start_big, end_big,
173 	                                         start_mono, end_mono), true);
174 
175 	msg.run ();
176 }
177 
178 
179 int
sr_mismatch_dialog(samplecnt_t desired,samplecnt_t actual)180 ARDOUR_UI::sr_mismatch_dialog (samplecnt_t desired, samplecnt_t actual)
181 {
182 	HBox* hbox = new HBox();
183 	Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
184 	ArdourDialog dialog (_("Sample Rate Mismatch"), true);
185 	Label  message (string_compose (_("\
186 This session was created with a sample rate of %1 Hz, but\n\
187 %2 is currently running at %3 Hz.  If you load this session,\n\
188 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
189 
190 	image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
191 	hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
192 	hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
193 	dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
194 	dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
195 	dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
196 	dialog.set_default_response (RESPONSE_ACCEPT);
197 	dialog.set_position (WIN_POS_CENTER);
198 	message.show();
199 	image->show();
200 	hbox->show();
201 
202 	switch (dialog.run()) {
203 	case RESPONSE_ACCEPT:
204 		return 0;
205 	default:
206 		break;
207 	}
208 
209 	return 1;
210 }
211 
212 void
sr_mismatch_message(samplecnt_t desired,samplecnt_t actual)213 ARDOUR_UI::sr_mismatch_message (samplecnt_t desired, samplecnt_t actual)
214 {
215 	ArdourMessageDialog msg (string_compose (_("\
216 This session was created with a sample rate of %1 Hz, but\n\
217 %2 is currently running at %3 Hz.\n\
218 Audio will be recorded and played at the wrong sample rate.\n\
219 Re-Configure the Audio Engine in\n\
220 Menu > Window > Audio/Midi Setup"),
221 				desired, PROGRAM_NAME, actual),
222 			true,
223 			Gtk::MESSAGE_WARNING);
224 	msg.run ();
225 }
226 
227 
228 XMLNode*
preferences_settings() const229 ARDOUR_UI::preferences_settings () const
230 {
231 	XMLNode* node = 0;
232 
233 	if (_session) {
234 		node = _session->instant_xml(X_("Preferences"));
235 	} else {
236 		node = Config->instant_xml(X_("Preferences"));
237 	}
238 
239 	if (!node) {
240 		node = new XMLNode (X_("Preferences"));
241 	}
242 
243 	return node;
244 }
245 
246 XMLNode*
mixer_settings() const247 ARDOUR_UI::mixer_settings () const
248 {
249 	XMLNode* node = 0;
250 
251 	if (_session) {
252 		node = _session->instant_xml(X_("Mixer"));
253 	} else {
254 		node = Config->instant_xml(X_("Mixer"));
255 	}
256 
257 	if (!node) {
258 		node = new XMLNode (X_("Mixer"));
259 	}
260 
261 	return node;
262 }
263 
264 XMLNode*
main_window_settings() const265 ARDOUR_UI::main_window_settings () const
266 {
267 	XMLNode* node = 0;
268 
269 	if (_session) {
270 		node = _session->instant_xml(X_("Main"));
271 	} else {
272 		node = Config->instant_xml(X_("Main"));
273 	}
274 
275 	if (!node) {
276 		if (getenv("ARDOUR_INSTANT_XML_PATH")) {
277 			node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
278 		}
279 	}
280 
281 	if (!node) {
282 		node = new XMLNode (X_("Main"));
283 	}
284 
285 	return node;
286 }
287 
288 XMLNode*
editor_settings() const289 ARDOUR_UI::editor_settings () const
290 {
291 	XMLNode* node = 0;
292 
293 	if (_session) {
294 		node = _session->instant_xml(X_("Editor"));
295 	} else {
296 		node = Config->instant_xml(X_("Editor"));
297 	}
298 
299 	if (!node) {
300 		if (getenv("ARDOUR_INSTANT_XML_PATH")) {
301 			node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
302 		}
303 	}
304 
305 	if (!node) {
306 		node = new XMLNode (X_("Editor"));
307 	}
308 
309 	return node;
310 }
311 
312 XMLNode*
recorder_settings() const313 ARDOUR_UI::recorder_settings () const
314 {
315 	XMLNode* node = 0;
316 
317 	if (_session) {
318 		node = _session->instant_xml(X_("Recorder"));
319 	} else {
320 		node = Config->instant_xml(X_("Recorder"));
321 	}
322 
323 	if (!node) {
324 		node = new XMLNode (X_("Recorder"));
325 	}
326 
327 	return node;
328 }
329 
330 XMLNode*
keyboard_settings() const331 ARDOUR_UI::keyboard_settings () const
332 {
333 	XMLNode* node = 0;
334 
335 	node = Config->extra_xml(X_("Keyboard"));
336 
337 	if (!node) {
338 		node = new XMLNode (X_("Keyboard"));
339 	}
340 
341 	return node;
342 }
343 
344 void
hide_splash()345 ARDOUR_UI::hide_splash ()
346 {
347 	Splash::drop ();
348 }
349 
350 void
check_announcements()351 ARDOUR_UI::check_announcements ()
352 {
353 #ifdef PHONE_HOME
354 	string _annc_filename;
355 
356 #ifdef __APPLE__
357 	_annc_filename = PROGRAM_NAME "_announcements_osx_";
358 #elif defined PLATFORM_WINDOWS
359 	_annc_filename = PROGRAM_NAME "_announcements_windows_";
360 #else
361 	_annc_filename = PROGRAM_NAME "_announcements_linux_";
362 #endif
363 	_annc_filename.append (VERSIONSTRING);
364 
365 	_announce_string = "";
366 
367 	std::string path = Glib::build_filename (user_config_directory(), _annc_filename);
368 	FILE* fin = g_fopen (path.c_str(), "rb");
369 	if (fin) {
370 		while (!feof (fin)) {
371 			char tmp[1024];
372 			size_t len;
373 			if ((len = fread (tmp, sizeof(char), 1024, fin)) == 0 || ferror (fin)) {
374 				break;
375 			}
376 			_announce_string.append (tmp, len);
377 		}
378 		fclose (fin);
379 	}
380 
381 	pingback (VERSIONSTRING, path);
382 #endif
383 }
384 
385 int
nsm_init()386 ARDOUR_UI::nsm_init ()
387 {
388 	const char *nsm_url;
389 
390 	if ((nsm_url = g_getenv ("NSM_URL")) == 0) {
391 		return 0;
392 	}
393 
394 	nsm = new NSM_Client;
395 
396 	if (nsm->init (nsm_url)) {
397 		delete nsm;
398 		nsm = 0;
399 		error << _("NSM: initialization failed") << endmsg;
400 		return -1;
401 	}
402 
403 	/* the ardour executable may have different names:
404 	 *
405 	 * waf's obj.target for distro versions: eg ardour4, ardourvst4
406 	 * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
407 	 * argv[0] does not apply since we need the wrapper-script (not the binary itself)
408 	 *
409 	 * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
410 	 */
411 	const char *process_name = g_getenv ("ARDOUR_SELF");
412 	nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour6");
413 
414 	unsigned int i = 0;
415 	// wait for announce reply from nsm server
416 	for ( i = 0; i < 5000; ++i) {
417 		nsm->check ();
418 
419 		Glib::usleep (i);
420 		if (nsm->is_active()) {
421 			break;
422 		}
423 	}
424 	if (i == 5000) {
425 		error << _("NSM server did not announce itself. Continuing without NSM.") << endmsg;
426 		delete nsm;
427 		nsm = 0;
428 		return 0;
429 	}
430 
431 	/* wait for open command from nsm server */
432 	for (i = 0; i < 5000; ++i) {
433 		nsm->check ();
434 		Glib::usleep (1000);
435 		if (nsm->client_id ()) {
436 			break;
437 		}
438 	}
439 
440 	if (i == 5000) {
441 		error << _("NSM: no client ID provided") << endmsg;
442 		delete nsm;
443 		nsm = 0;
444 		return -1;
445 	}
446 
447 	if (_session && nsm) {
448 		_session->set_nsm_state( nsm->is_active() );
449 	} else {
450 		error << _("NSM: no session created") << endmsg;
451 		delete nsm;
452 		nsm = 0;
453 		return -1;
454 	}
455 
456 	// nsm requires these actions disabled
457 	vector<string> action_names;
458 	action_names.push_back("SaveAs");
459 	action_names.push_back("Rename");
460 	action_names.push_back("New");
461 	action_names.push_back("Open");
462 	action_names.push_back("Recent");
463 	action_names.push_back("Close");
464 
465 	for (vector<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
466 		Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), (*n).c_str());
467 		if (act) {
468 			act->set_sensitive (false);
469 		}
470 	}
471 
472 	return 0;
473 }
474 
475 void
sfsm_response(StartupFSM::Result r)476 ARDOUR_UI::sfsm_response (StartupFSM::Result r)
477 {
478 	DEBUG_TRACE (DEBUG::GuiStartup, string_compose (X_("startup FSM response %1\n"), r));
479 
480 	switch (r) {
481 	case StartupFSM::ExitProgram:
482 		queue_finish ();
483 		break;
484 
485 	case StartupFSM::LoadSession:
486 
487 		if (load_session_from_startup_fsm () == 0) {
488 			startup_done ();
489 			delete startup_fsm;
490 			startup_fsm = 0;
491 		} else {
492 			DEBUG_TRACE (DEBUG::GuiStartup, "FSM reset\n");
493 			startup_fsm->reset ();
494 		}
495 
496 		break;
497 	}
498 }
499 
500 int
starting()501 ARDOUR_UI::starting ()
502 {
503 	Application* app = Application::instance();
504 
505 	app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::load_from_application_api));
506 
507 	if (ARDOUR_COMMAND_LINE::check_announcements) {
508 		check_announcements ();
509 	}
510 
511 	app->ready ();
512 
513 	/* we need to create this early because it may need to set the
514 	 *  audio backend end up.
515 	 */
516 
517 	EngineControl* amd;
518 
519 	try {
520 		amd = dynamic_cast<EngineControl*> (audio_midi_setup.get (true));
521 	} catch (...) {
522 		std::cerr << "audio-midi engine setup failed."<< std::endl;
523 		return -1;
524 	}
525 
526 	if (nsm_init ()) {
527 		return -1;
528 	} else  {
529 
530 		if (nsm) {
531 			return 0;
532 		}
533 
534 		startup_fsm = new StartupFSM (*amd);
535 		startup_fsm->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::sfsm_response));
536 
537 
538 		/* allow signals to be handled, ShouldLoad() from flush-pending */
539 		Splash::instance()->exists(); // create splash
540 		flush_pending ();
541 
542 		if (!startup_fsm) {
543 			DEBUG_TRACE (DEBUG::GuiStartup, "Starting: SFSM was driven by flush-pending\n");
544 			return 0;
545 		}
546 
547 		/* Note: entire startup process could happen in this one call
548 		 * if:
549 		 *
550 		 * 1) not a new user
551 		 * 2) session name provided on command line (and valid)
552 		 * 3) no audio/MIDI setup required
553 		 */
554 
555 		startup_fsm->start ();
556 	}
557 
558 	return 0;
559 }
560 
561 int
load_session_from_startup_fsm()562 ARDOUR_UI::load_session_from_startup_fsm ()
563 {
564 	const string session_path = startup_fsm->session_path;
565 	const string session_name = startup_fsm->session_name;
566 	const string session_template = startup_fsm->session_template;
567 	const bool   session_is_new = startup_fsm->session_is_new;
568 	const BusProfile bus_profile = startup_fsm->bus_profile;
569 	const bool   session_was_not_named = (!startup_fsm->session_name_edited && ARDOUR_COMMAND_LINE::session_name.empty());
570 
571 	if (session_is_new) {
572 
573 		if (build_session (session_path, session_name, session_template, bus_profile, true, session_was_not_named)) {
574 			return -1;
575 		}
576 		return 0;
577 	}
578 
579 	return load_session (session_path, session_name, session_template);
580 
581 }
582 
583 void
startup_done()584 ARDOUR_UI::startup_done ()
585 {
586 	/* ShouldQuit is a desktop environment mechanism that tells the
587 	   application it should exit for reasons external to the application
588 	   itself.
589 
590 	   During startup, startupFSM handles ShouldQuit. But it is done now,
591 	   and we have to take over responsibility.
592 	*/
593 	Application::instance()->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
594 	/* Same story applies for ShouldLoad ... startupFSM will handle it
595 	   normally, but if it doesn't we (ARDOUR_UI) need to take responsibility
596 	   for it.
597 	*/
598 	Application::instance()->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::load_from_application_api));
599 
600 	use_config ();
601 
602 	WM::Manager::instance().show_visible ();
603 
604 	/* We have to do this here since goto_editor_window() ends up calling show_all() on the
605 	 * editor window, and we may want stuff to be hidden.
606 	 */
607 	_status_bar_visibility.update ();
608 
609 	BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
610 }
611 
612 void
use_config()613 ARDOUR_UI::use_config ()
614 {
615 	XMLNode* node = Config->extra_xml (X_("TransportControllables"));
616 	if (node) {
617 		set_transport_controllable_state (*node);
618 	}
619 }
620 
621 void
check_memory_locking()622 ARDOUR_UI::check_memory_locking ()
623 {
624 #if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
625 	/* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
626 	return;
627 #else // !__APPLE__
628 
629 	XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
630 
631 	if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
632 
633 		struct rlimit limits;
634 		int64_t ram;
635 		long pages, page_size;
636 #ifdef __FreeBSD__
637 		size_t pages_len=sizeof(pages);
638 		if ((page_size = getpagesize()) < 0 ||
639 				sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
640 #else
641 		if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
642 #endif
643 		{
644 			ram = 0;
645 		} else {
646 			ram = (int64_t) pages * (int64_t) page_size;
647 		}
648 
649 		if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
650 			return;
651 		}
652 
653 		if (limits.rlim_cur != RLIM_INFINITY) {
654 
655 			if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
656 
657 				ArdourMessageDialog msg (
658 					string_compose (
659 						_("WARNING: Your system has a limit for maximum amount of locked memory. "
660 						  "This might cause %1 to run out of memory before your system "
661 						  "runs out of memory. \n\n"
662 						  "You can view the memory limit with 'ulimit -l', "
663 						  "and it is normally controlled by %2"),
664 						PROGRAM_NAME,
665 #if defined(__FreeBSD__) || defined(__NetBSD__)
666 						X_("/etc/login.conf")
667 #else
668 						X_(" /etc/security/limits.conf")
669 #endif
670 					).c_str());
671 
672 				msg.set_default_response (RESPONSE_OK);
673 
674 				VBox* vbox = msg.get_vbox();
675 				HBox hbox;
676 				CheckButton cb (_("Do not show this window again"));
677 				hbox.pack_start (cb, true, false);
678 				vbox->pack_start (hbox);
679 				cb.show();
680 				vbox->show();
681 				hbox.show ();
682 
683 				msg.run ();
684 
685 				if (cb.get_active()) {
686 					XMLNode node (X_("no-memory-warning"));
687 					Config->add_instant_xml (node);
688 				}
689 			}
690 		}
691 	}
692 #endif // !__APPLE__
693 }
694 
695 void
load_from_application_api(const std::string & path)696 ARDOUR_UI::load_from_application_api (const std::string& path)
697 {
698 	/* OS X El Capitan (and probably later) now somehow passes the command
699 	   line arguments to an app via the openFile delegate protocol. Ardour
700 	   already does its own command line processing, and having both
701 	   pathways active causes crashes. So, if the command line was already
702 	   set, do nothing here. NSM also uses this code path.
703 	*/
704 
705 	if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
706 		return;
707 	}
708 
709 
710 	/* Cancel SessionDialog if it's visible to make OSX delegates work.
711 	 *
712 	 * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
713 	 * race-condition:
714 	 *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
715 	 *    -> startupFSM starts a SessionDialog.
716 	 *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
717 	 *    -> SessionDialog is not displayed
718 	 */
719 
720 	if (startup_fsm) {
721 		/* this will result in the StartupFSM signalling us to load a
722 		 * session, which if successful will then destroy the
723 		 * startupFSM and we'll move right along.
724 		 */
725 
726 		startup_fsm->handle_path (path);
727 		return;
728 	}
729 
730 	if (nsm) {
731 		if (!AudioEngine::instance()->set_backend("JACK", "", "")) {
732 			error << _("NSM: The JACK backend is mandatory and can not be loaded.") << endmsg;
733 			return;
734 		}
735 
736 		if (!AudioEngine::instance()->running()) {
737 			/* this auto-starts jackd with recent settings
738 			 * TODO: if Glib::file_test (path, Glib::FILE_TEST_IS_DIR)
739 			 *  query sample-rate of the session and use it.
740 			 */
741 			if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
742 				float sr;
743 				SampleFormat sf;
744 				string pv;
745 				if (0 == Session::get_info_from_path (Glib::build_filename (path, basename_nosuffix (path) + statefile_suffix), sr, sf, pv)) {
746 					ARDOUR::AudioEngine::instance ()->set_sample_rate (sr);
747 				}
748 			}
749 			if (AudioEngine::instance()->start()) {
750 				error << string_compose (_("NSM: %1 cannot connect to the JACK server. Please start jackd first."), PROGRAM_NAME) << endmsg;
751 				return;
752 			}
753 		}
754 
755 		PluginScanDialog psd (true, false);
756 		psd.start ();
757 
758 		post_engine ();
759 	}
760 
761 	/* the mechanisms that can result is this being called are only
762 	 * possible for existing sessions.
763 	 */
764 
765 	if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
766 		if (nsm) {
767 			BusProfile bus_profile;
768 			bus_profile.master_out_channels = 2;
769 			build_session (path, basename_nosuffix (path), "", bus_profile, true, false);
770 		}
771 		return;
772 	}
773 
774 	ARDOUR_COMMAND_LINE::session_name = path;
775 
776 	int rv;
777 
778 	if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
779 		/* /path/to/foo => /path/to/foo, foo */
780 		rv = load_session (path, basename_nosuffix (path));
781 	} else {
782 		/* /path/to/foo/foo.ardour => /path/to/foo, foo */
783 		rv = load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
784 	}
785 
786 	// there was no startupFSM, load_session fails, and there is no existing session ....
787 
788 	if (rv && !_session) {
789 
790 		ARDOUR_COMMAND_LINE::session_name = string();
791 
792 		/* do this again */
793 
794 		EngineControl* amd;
795 
796 		try {
797 			amd = dynamic_cast<EngineControl*> (audio_midi_setup.get (true));
798 		} catch (...) {
799 			std::cerr << "audio-midi engine setup failed."<< std::endl;
800 			return;
801 		}
802 
803 		startup_fsm = new StartupFSM (*amd);
804 		startup_fsm->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::sfsm_response));
805 
806 		/* Note: entire startup process could happen in this one call
807 		 * if:
808 		 *
809 		 * 1) not a new user
810 		 * 2) session name provided on command line (and valid)
811 		 * 3) no audio/MIDI setup required
812 		 */
813 
814 		Splash::instance()->exists(); // create splash
815 		startup_fsm->start ();
816 	}
817 }
818