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