fix deletion/pointer error
[ardour.git] / gtk2_ardour / startup_fsm.cc
1 /*
2  * Copyright (C) 2019 Paul Davis <paul@linuxaudiosystems.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #include <vector>
20
21 #include <gtkmm/dialog.h>
22 #include <gtkmm/liststore.h>
23 #include <gtkmm/messagedialog.h>
24 #include <gtkmm/stock.h>
25
26 #include "pbd/basename.h"
27 #include "pbd/file_archive.h"
28 #include "pbd/file_utils.h"
29 #include "pbd/i18n.h"
30
31 #include "ardour/audioengine.h"
32 #include "ardour/filename_extensions.h"
33 #include "ardour/filesystem_paths.h"
34 #include "ardour/profile.h"
35 #include "ardour/recent_sessions.h"
36 #include "ardour/rc_configuration.h"
37 #include "ardour/search_paths.h"
38 #include "ardour/session.h"
39 #include "ardour/session_utils.h"
40 #include "ardour/template_utils.h"
41
42 #include "gtkmm2ext/application.h"
43 #include <gtkmm2ext/doi.h>
44
45 #include "ardour_ui.h"
46 #include "debug.h"
47 #include "engine_dialog.h"
48 #include "new_user_wizard.h"
49 #include "opts.h"
50 #include "plugin_scan_dialog.h"
51 #include "session_dialog.h"
52 #include "splash.h"
53 #include "startup_fsm.h"
54
55 #ifdef WAF_BUILD
56 #include "gtk2ardour-version.h"
57 #endif
58
59 using namespace ARDOUR;
60 using namespace Gtk;
61 using namespace Gtkmm2ext;
62 using namespace PBD;
63
64 using std::string;
65 using std::vector;
66
67 StartupFSM::StartupFSM (EngineControl& amd)
68         : session_existing_sample_rate (0)
69         , session_is_new (false)
70         , new_user (NewUserWizard::required())
71         , new_session_required (ARDOUR_COMMAND_LINE::new_session || (!ARDOUR::Profile->get_mixbus() && new_user))
72         , _state (new_user ? WaitingForNewUser : WaitingForSessionPath)
73         , audiomidi_dialog (amd)
74         , new_user_dialog (0)
75         , session_dialog (0)
76         , pre_release_dialog (0)
77         , plugin_scan_dialog (0)
78 {
79         /* note that our initial state can be any of:
80          *
81          * WaitingForPreRelease:  if this is a pre-release build of Ardour and the user has not testified to their fidelity to our creed
82          * WaitingForNewUser:     if this is the first time any version appears to have been run on this machine by this user
83          * WaitingForSessionPath: if the previous two conditions are not true
84          */
85
86         if (string (VERSIONSTRING).find (".pre") != string::npos) {
87                 string fn = Glib::build_filename (user_config_directory(), ".i_swear_that_i_will_heed_the_guidelines_stated_in_the_pre_release_dialog");
88                 if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
89                         set_state (WaitingForPreRelease);
90                 }
91         }
92
93         Application* app = Application::instance ();
94
95         app->ShouldQuit.connect (sigc::mem_fun (*this, &StartupFSM::queue_finish));
96         app->ShouldLoad.connect (sigc::mem_fun (*this, &StartupFSM::load_from_application_api));
97 }
98
99 StartupFSM::~StartupFSM ()
100 {
101         delete session_dialog;
102         delete pre_release_dialog;
103         delete plugin_scan_dialog;
104         delete new_user_dialog;
105 }
106
107 void
108 StartupFSM::queue_finish ()
109 {
110         _signal_response (ExitProgram);
111 }
112
113 void
114 StartupFSM::start ()
115 {
116         /* get the splash screen visible, if it isn't yet */
117         Splash::instance()->pop_front();
118         /* make it all happen on-screen */
119         ARDOUR_UI::instance()->flush_pending ();
120
121         DEBUG_TRACE (DEBUG::GuiStartup, string_compose (X_("State at startup: %1\n"), enum_2_string (_state)));
122
123         switch (_state) {
124         case WaitingForPreRelease:
125                 show_pre_release_dialog ();
126                 break;
127         case WaitingForNewUser:
128                 show_new_user_dialog ();
129                 break;
130         case WaitingForSessionPath:
131                 if (ARDOUR_COMMAND_LINE::session_name.empty()) {
132
133                         /* nothing given on the command line ... show new session dialog */
134
135                         show_session_dialog (new_session_required);
136
137                 } else {
138
139                         if (get_session_parameters_from_command_line (new_session_required)) {
140
141                                 /* command line arguments all OK. Get engine parameters */
142
143                                 if (!new_session_required && session_existing_sample_rate > 0) {
144                                         audiomidi_dialog.set_desired_sample_rate (session_existing_sample_rate);
145                                 }
146
147                                 start_audio_midi_setup ();
148
149                         } else {
150
151                                 /* command line arguments not good. Use
152                                  * dialog, but prime the dialog with
153                                  * the information we set up in
154                                  * get_session_parameters_from_command_line()
155                                  */
156
157                                 show_session_dialog (new_session_required);
158                         }
159                 }
160                 break;
161         default:
162                 fatal << string_compose (_("Programming error: %1"), string_compose (X_("impossible starting state in StartupFSM (%1)"), enum_2_string (_state))) << endmsg;
163                 std::cerr << string_compose (_("Programming error: %1"), string_compose (X_("impossible starting state in StartupFSM (%1)"), enum_2_string (_state))) << std::endl;
164                 /* NOTREACHED */
165                 abort ();
166         }
167
168         DEBUG_TRACE (DEBUG::GuiStartup, string_compose (X_("State after startup: %1\n"), enum_2_string (_state)));
169
170         /* this may cause the delivery of ShouldLoad etc if we were invoked in
171          * particular ways. It will happen when the event loop runs again.
172          */
173
174         Application::instance()->ready ();
175 }
176
177 void
178 StartupFSM::reset()
179 {
180         show_session_dialog (new_session_required);
181 }
182
183 void
184 StartupFSM::set_state (MainState ms)
185 {
186         DEBUG_TRACE (DEBUG::GuiStartup, string_compose (X_("new state: %1\n"), enum_2_string (ms)));
187         _state = ms;
188 }
189
190 template<typename T> void
191 StartupFSM::end_dialog (T** d)
192 {
193         assert (d);
194         assert (*d);
195
196         end_dialog (**d);
197         delete_when_idle (*d);
198         *d = 0;
199 }
200
201 template<typename T> void
202 StartupFSM::end_dialog (T& d)
203 {
204         d.hide ();
205         current_dialog_connection.disconnect ();
206 }
207
208 void
209 StartupFSM::dialog_response_handler (int response, StartupFSM::DialogID dialog_id)
210 {
211         DEBUG_TRACE (DEBUG::GuiStartup, string_compose ("Response %1 from %2 (nsr: %3 / nu: %4)\n", enum_2_string (Gtk::ResponseType (response)), enum_2_string (dialog_id), new_session_required, new_user));
212
213         /* Notes:
214          *
215          * 1) yes, a brand new user might have specified a command line
216          * argument naming a new session. We ignore it. You're new to Ardour?
217          * We want to guide you through the startup.
218          */
219
220         switch (_state) {
221         case WaitingForPreRelease:
222                 switch (dialog_id) {
223                 case PreReleaseDialog:
224                 default:
225                         /* any response value from the pre-release dialog means
226                            "move along now"
227                         */
228                         end_dialog (&pre_release_dialog);
229
230                         if (NewUserWizard::required()) {
231                                 show_new_user_dialog ();
232                         } else {
233                                 show_session_dialog (new_session_required);
234                         }
235                         break;
236                 }
237                 break;
238
239         case WaitingForNewUser:
240                 switch (dialog_id) {
241                 case NewUserDialog:
242                         switch (response) {
243                         case RESPONSE_OK:
244                                 end_dialog (&new_user_dialog);
245                                 show_session_dialog (new_session_required);
246                                 break;
247                         default:
248                                 _signal_response (ExitProgram);
249                         }
250                 default:
251                         /* ERROR */
252                         break;
253                 }
254                 break;
255
256         case WaitingForSessionPath:
257                 switch (dialog_id) {
258                 case NewSessionDialog:
259                         switch (response) {
260                         case RESPONSE_OK:
261                         case RESPONSE_ACCEPT:
262                                 switch (check_session_parameters (new_session_required)) {
263                                 case -1:
264                                         /* Unrecoverable error */
265                                         _signal_response (ExitProgram);
266                                         break;
267                                 case 0:
268                                         end_dialog (&session_dialog);
269                                         start_audio_midi_setup ();
270                                         break;
271                                 case 1:
272                                         /* do nothing - keep dialog up for a
273                                          * retry. Errors were addressed by
274                                          * ::check_session_parameters()
275                                          */
276                                         break;
277                                 }
278                                 break;
279
280                         default:
281                                 _signal_response (ExitProgram);
282                                 break;
283                         }
284                         break;
285
286                 default:
287                         /* ERROR */
288                         break;
289                 }
290                 break;
291
292         case WaitingForEngineParams:
293                 switch (dialog_id) {
294                 case AudioMIDISetup:
295                         switch (response) {
296                         case RESPONSE_OK:
297                         case RESPONSE_ACCEPT:
298                                 if (AudioEngine::instance()->running()) {
299                                         end_dialog (audiomidi_dialog);
300                                         engine_running ();
301                                 } else {
302                                         /* just keep going */
303                                 }
304                                 break;
305                         default:
306                                 _signal_response (ExitProgram);
307                         }
308                         break;
309                 default:
310                         /* ERROR */
311                         break;
312                 }
313                 break;
314
315         case WaitingForPlugins:
316                 switch (dialog_id) {
317                 case PluginDialog:
318                         end_dialog (&plugin_scan_dialog);
319                         switch (response) {
320                         case RESPONSE_OK:
321                                 _signal_response (LoadSession);
322                                 break;
323                         default:
324                                 _signal_response (ExitProgram);
325                                 break;
326                         }
327                 default:
328                         /* ERROR */
329                         break;
330                 }
331         }
332 }
333
334 void
335 StartupFSM::show_plugin_scan_dialog ()
336 {
337         set_state (WaitingForPlugins);
338
339         /* if the user does not ask to discover VSTs at startup, or if this is Mixbus, then the plugin scan
340            that we run here, during startup, should only use the existing plugin cache (if any).
341         */
342
343         plugin_scan_dialog = new PluginScanDialog ((!Config->get_discover_vst_on_start() || Profile->get_mixbus()), new_user);
344         current_dialog_connection = plugin_scan_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), PluginDialog));
345         plugin_scan_dialog->set_position (WIN_POS_CENTER);
346
347         /* We don't show the plugin scan dialog by default. It will appear using it's own code if/when plugins are discovered, if required.
348          *
349          * See also comments in PluginScanDialog::start() to understand the absurd complexities behind this call.
350          */
351
352         DEBUG_TRACE (DEBUG::GuiStartup, string_compose ("starting plugin dialog, cache only ? %1\n", !Config->get_discover_vst_on_start()));
353         plugin_scan_dialog->start();
354         DEBUG_TRACE (DEBUG::GuiStartup, "plugin dialog done\n");
355 }
356
357
358 void
359 StartupFSM::show_new_user_dialog ()
360 {
361         set_state (WaitingForNewUser);
362         new_user_dialog = new NewUserWizard;
363         current_dialog_connection = new_user_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), NewUserDialog));
364         new_user_dialog->set_position (WIN_POS_CENTER);
365         new_user_dialog->present ();
366 }
367
368 void
369 StartupFSM::show_session_dialog (bool new_session_required)
370 {
371         set_state (WaitingForSessionPath);
372         session_dialog = new SessionDialog (new_session_required, session_name, session_path, session_template, false);
373         current_dialog_connection = session_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), NewSessionDialog));
374         session_dialog->set_position (WIN_POS_CENTER);
375         session_dialog->present ();
376 }
377
378 void
379 StartupFSM::show_audiomidi_dialog ()
380 {
381         set_state (WaitingForEngineParams);
382         current_dialog_connection = audiomidi_dialog.signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), AudioMIDISetup));
383         audiomidi_dialog.set_position (WIN_POS_CENTER);
384         audiomidi_dialog.present ();
385 }
386
387 void
388 StartupFSM::start_audio_midi_setup ()
389 {
390         bool setup_required = false;
391
392         if (AudioEngine::instance()->current_backend() == 0) {
393                 /* backend is unknown ... */
394                 setup_required = true;
395
396         } else if (session_is_new && AudioEngine::instance()->running() && AudioEngine::instance()->sample_rate () == session_existing_sample_rate) {
397                 /* keep engine */
398
399                 warning << "A running engine should not be possible at this point" << endmsg;
400
401         } else if (AudioEngine::instance()->setup_required()) {
402                 /* backend is known, but setup is needed */
403                 setup_required = true;
404
405         } else if (!AudioEngine::instance()->running()) {
406                 /* should always be true during startup */
407                 if (AudioEngine::instance()->start()) {
408                         setup_required = true;
409                 }
410         }
411
412         if (setup_required) {
413                 if (!session_is_new && session_existing_sample_rate > 0) {
414                         audiomidi_dialog.set_desired_sample_rate (session_existing_sample_rate);
415                 }
416                 show_audiomidi_dialog ();
417                 DEBUG_TRACE (DEBUG::GuiStartup, "audiomidi shown and waiting\n");
418         } else {
419
420                 DEBUG_TRACE (DEBUG::GuiStartup, "engine already running, audio/MIDI setup dialog not required\n");
421                 engine_running ();
422         }
423 }
424
425 void
426 StartupFSM::engine_running ()
427 {
428         DEBUG_TRACE (DEBUG::GuiStartup, "engine running, start plugin scan then attach UI to engine\n");
429
430         /* This may be very slow. See comments in PluginScanDialog::start() */
431         show_plugin_scan_dialog ();
432
433         DEBUG_TRACE (DEBUG::GuiStartup, "attach UI to engine\n");
434
435         /* This may be very slow: it will run the GUI's post-engine
436            initialization which is essentially unbounded in time/scope of what
437            it can do.
438         */
439
440         ARDOUR_UI::instance()->attach_to_engine ();
441
442         /* now that we've done the plugin scan AND attached the UI to the engine, we can
443            proceed with the next (final) steps of startup. This uses the same response
444            signal mechanism we use for the other dialogs.
445         */
446
447         plugin_scan_dialog->response (RESPONSE_OK);
448 }
449
450 bool
451 StartupFSM::get_session_parameters_from_command_line (bool new_session_required)
452 {
453         return get_session_parameters_from_path (ARDOUR_COMMAND_LINE::session_name, ARDOUR_COMMAND_LINE::load_template, new_session_required);
454 }
455
456 bool
457 StartupFSM::get_session_parameters_from_path (string const & path, string const & template_name, bool new_session_required)
458 {
459         if (path.empty()) {
460                 /* use GUI to ask the user */
461                 return false;
462         }
463
464         if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS)) {
465
466                 session_is_new = false;
467
468                 if (new_session_required) {
469                         /* wait! it already exists */
470
471                         if (!ask_about_loading_existing_session (path)) {
472                                 return false;
473                         } else {
474                                 /* load it anyway */
475                         }
476                 }
477
478                 session_name = basename_nosuffix (path);
479
480                 if (Glib::file_test (path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
481                         /* session/snapshot file, change path to be dir */
482                         session_path = Glib::path_get_dirname (path);
483                 } else {
484                         session_path = path;
485                 }
486
487                 float sr;
488                 SampleFormat fmt;
489                 string program_version;
490
491                 const string statefile_path = Glib::build_filename (session_path, session_name + ARDOUR::statefile_suffix);
492                 if (Session::get_info_from_path (statefile_path, sr, fmt, program_version)) {
493                         /* exists but we can't read it correctly */
494                         error << string_compose (_("Cannot get existing session information from %1"), statefile_path) << endmsg;
495                         return false;
496                 }
497
498                 session_existing_sample_rate = sr;
499                 return true;
500
501         }
502
503         /*  Everything after this involves a new session
504          *
505          *  ... did the  user give us a path or just a name?
506          */
507
508         if (path.find (G_DIR_SEPARATOR) == string::npos) {
509                 /* user gave session name with no path info, use
510                    default session folder.
511                 */
512                 session_name = ARDOUR_COMMAND_LINE::session_name;
513                 session_path = Glib::build_filename (Config->get_default_session_parent_dir (), session_name);
514         } else {
515                 session_name = basename_nosuffix (path);
516                 session_path = path;
517         }
518
519
520         if (!template_name.empty()) {
521
522                 /* Allow the user to specify a template via path or name on the
523                  * command line
524                  */
525
526                 bool have_resolved_template_name = false;
527
528                 /* compare by name (path may or may not be UTF-8) */
529
530                 vector<TemplateInfo> templates;
531                 find_session_templates (templates, false);
532                 for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
533                         if ((*x).name == template_name) {
534                                 session_template = (*x).path;
535                                 have_resolved_template_name = true;
536                                 break;
537                         }
538                 }
539
540                 /* look up script by name */
541                 LuaScriptList scripts (LuaScripting::instance ().scripts (LuaScriptInfo::SessionInit));
542                 LuaScriptList& as (LuaScripting::instance ().scripts (LuaScriptInfo::EditorAction));
543                 for (LuaScriptList::const_iterator s = as.begin(); s != as.end(); ++s) {
544                         if ((*s)->subtype & LuaScriptInfo::SessionSetup) {
545                                 scripts.push_back (*s);
546                         }
547                 }
548                 std::sort (scripts.begin(), scripts.end(), LuaScripting::Sorter());
549                 for (LuaScriptList::const_iterator s = scripts.begin(); s != scripts.end(); ++s) {
550                         if ((*s)->name == template_name) {
551                                 session_template = "urn:ardour:" + (*s)->path;
552                                 have_resolved_template_name = true;
553                                 break;
554                         }
555                 }
556
557                 if (!have_resolved_template_name) {
558                         /* this will produce a more or less meaninful error later:
559                          * "ERROR: Could not open session template [abs-path to user-config dir]"
560                          */
561                         session_template = Glib::build_filename (ARDOUR::user_template_directory (), template_name);
562                 }
563         }
564
565         /* We don't know what this is, because the session is new and the
566          * command line doesn't let us specify it. The user will get to decide
567          * in the audio/MIDI dialog.
568          */
569
570         session_existing_sample_rate = 0;
571         session_is_new = true;
572
573         /* this is an arbitrary default value but since the user insists on
574          * starting a new session from the command line, it will do as well as
575          * any other possible value. I mean, seriously, what else could it be
576          * by default?
577          */
578
579         bus_profile.master_out_channels = 2;
580
581         return true;
582 }
583
584 /** return values:
585  * -1: failure
586  *  1: failure but user can retry
587  *  0: success, seesion parameters ready for use
588  */
589 int
590 StartupFSM::check_session_parameters (bool must_be_new)
591 {
592         bool requested_new = false;
593
594         session_name = session_dialog->session_name (requested_new);
595         session_path = session_dialog->session_folder ();
596
597         if (must_be_new) {
598                 assert (requested_new);
599         }
600
601         if (!must_be_new) {
602
603                 /* See if the specified session is a session archive */
604
605                 int rv = ARDOUR::inflate_session (session_name, Config->get_default_session_parent_dir(), session_path, session_name);
606                 if (rv < 0) {
607                         MessageDialog msg (*session_dialog, string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
608                         msg.run ();
609
610                         return 1;
611                 } else if (rv == 0) {
612                         /* names are good (and session is unarchived/inflated */
613                         return 0;
614                 }
615         }
616
617         /* check for ".ardour" in statefile name, because we don't want
618          * it
619          *
620          * XXX Note this wierd conflation of a
621          * file-name-without-a-suffix and the session name. It's not
622          * really a session name at all, but rather the suffix-free
623          * name of a statefile (snapshot).
624          */
625
626         const string::size_type suffix_at = session_name.find (statefile_suffix);
627
628         if (suffix_at != string::npos) {
629                 session_name = session_name.substr (0, suffix_at);
630         }
631
632         /* this shouldn't happen, but we catch it just in case it does */
633
634         if (session_name.empty()) {
635                 return 1; /* keep running dialog */
636         }
637
638         if (session_dialog->use_session_template()) {
639                 session_template = session_dialog->session_template_name();
640         }
641
642         if (session_name[0] == G_DIR_SEPARATOR ||
643 #ifdef PLATFORM_WINDOWS
644             // Windows file system .. detect absolute path
645             // C:/*
646             (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
647 #else
648             // Sensible file systems
649             // /* or ./* or ../*
650             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
651             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
652 #endif
653                 )
654         {
655
656                 /* user typed absolute path or cwd-relative path
657                    specified into session name field. So ... infer
658                    session path and name from what was given.
659                 */
660
661                 session_path = Glib::path_get_dirname (session_name);
662                 session_name = Glib::path_get_basename (session_name);
663
664         } else {
665
666                 /* session name is just a name */
667         }
668
669         /* check if name is legal */
670
671         const char illegal = Session::session_name_is_legal (session_name);
672
673         if (illegal) {
674                 MessageDialog msg (*session_dialog,
675                                    string_compose (_("To ensure compatibility with various systems\n"
676                                                      "session names may not contain a '%1' character"),
677                                                    illegal));
678                 msg.run ();
679                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
680                 return 1; /* keep running dialog */
681         }
682
683
684         /* check if the currently-exists status matches whether or not
685          * it should be new
686          */
687
688         if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
689
690                 if (requested_new /*&& !nsm*/) {
691
692                         std::string existing = Glib::build_filename (session_path, session_name);
693
694                         if (!ask_about_loading_existing_session (existing)) {
695                                 session_dialog->clear_name ();
696                                 return 1; /* try again */
697                         }
698                 }
699
700                 session_is_new = false;
701
702         } else {
703
704                 /* does not exist at present */
705
706                 if (!requested_new) {
707                         ARDOUR_UI::pop_back_splash (*session_dialog);
708                         MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
709                         msg.run ();
710                         session_dialog->clear_name();
711                         return 1;
712                 }
713
714                 session_is_new = true;
715         }
716
717         float sr;
718         SampleFormat fmt;
719         string program_version;
720         const string statefile_path = Glib::build_filename (session_path, session_name + ARDOUR::statefile_suffix);
721
722         if (!session_is_new) {
723
724                 if (Session::get_info_from_path (statefile_path, sr, fmt, program_version)) {
725                         /* exists but we can't read it */
726                         return -1;
727                 }
728
729                 session_existing_sample_rate = sr;
730
731         } else {
732
733                 bus_profile.master_out_channels = session_dialog->master_channel_count ();
734         }
735
736         return 0;
737 }
738
739 void
740 StartupFSM::copy_demo_sessions ()
741 {
742         // TODO: maybe IFF brand_new_user
743         if (ARDOUR::Profile->get_mixbus () && Config->get_copy_demo_sessions ()) {
744                 std::string dspd (Config->get_default_session_parent_dir());
745                 Searchpath ds (ARDOUR::ardour_data_search_path());
746                 ds.add_subdirectory_to_paths ("sessions");
747                 vector<string> demos;
748                 find_files_matching_pattern (demos, ds, ARDOUR::session_archive_suffix);
749
750                 ARDOUR::RecentSessions rs;
751                 ARDOUR::read_recent_sessions (rs);
752
753                 for (vector<string>::iterator i = demos.begin(); i != demos.end (); ++i) {
754                         /* "demo-session" must be inside "demo-session.<session_archive_suffix>" */
755                         std::string name = basename_nosuffix (basename_nosuffix (*i));
756                         std::string path = Glib::build_filename (dspd, name);
757                         /* skip if session-dir already exists */
758                         if (Glib::file_test(path.c_str(), Glib::FILE_TEST_IS_DIR)) {
759                                 continue;
760                         }
761                         /* skip sessions that are already in 'recent'.
762                          * eg. a new user changed <session-default-dir> shorly after installation
763                          */
764                         for (ARDOUR::RecentSessions::iterator r = rs.begin(); r != rs.end(); ++r) {
765                                 if ((*r).first == name) {
766                                         continue;
767                                 }
768                         }
769                         try {
770                                 PBD::FileArchive ar (*i);
771                                 if (0 == ar.inflate (dspd)) {
772                                         store_recent_sessions (name, path);
773                                         info << string_compose (_("Copied Demo Session %1."), name) << endmsg;
774                                 }
775                         } catch (...) {
776                                 /* relax ? */
777                         }
778                 }
779         }
780 }
781
782 void
783 StartupFSM::load_from_application_api (const std::string& path)
784 {
785         /* macOS El Capitan (and probably later) now somehow passes the command
786            line arguments to an app via the openFile delegate protocol. Ardour
787            already does its own command line processing, and having both
788            pathways active causes crashes. So, if the command line was already
789            set, do nothing here.
790         */
791
792         if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
793                 return;
794         }
795
796         /* Cancel SessionDialog if it's visible to make macOS delegates work.
797          *
798          * there's a race condition here: we connect to app->ShouldLoad
799          * and then at some point (might) show a session dialog. The race is
800          * caused by the non-deterministic interaction between the macOS event
801          * loop(s) and the GDK one(s).
802          *
803          *  - ShouldLoad does not arrive before we show the session dialog
804          *          -> here we should hide the session dialog, then use the
805          *             supplied path as if it was provided on the command line
806          *  - ShouldLoad signal arrives before we show a session dialog
807          *          -> don't bother showing the session dialog, just use the
808          *             supplied path as if it was provided on the command line
809          *
810          */
811
812         if (session_dialog) {
813                 session_dialog->hide ();
814                 delete_when_idle (session_dialog);
815                 session_dialog = 0;
816         }
817
818         /* no command line argument given ... must just be via
819          * desktop/finder/window manager API (e.g. double click on "foo.ardour"
820          * icon)
821          */
822
823         if (get_session_parameters_from_path (path, string(), false)) {
824                 _signal_response (LoadSession);
825                 return;
826         }
827
828         /* given parameters failed for some reason. This is probably true
829          * anyway, but force it to be true and then carry on with whatever the
830          * main event loop is doing.
831          */
832
833         set_state (WaitingForSessionPath);
834 }
835
836 bool
837 StartupFSM::ask_about_loading_existing_session (const std::string& session_path)
838 {
839         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
840
841         MessageDialog msg (str,
842                            false,
843                            Gtk::MESSAGE_WARNING,
844                            Gtk::BUTTONS_YES_NO,
845                            true);
846
847
848         msg.set_name (X_("OpenExistingDialog"));
849         msg.set_title (_("Open Existing Session"));
850         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
851         msg.set_position (Gtk::WIN_POS_CENTER);
852         ARDOUR_UI::pop_back_splash (msg);
853
854         switch (msg.run()) {
855         case RESPONSE_YES:
856                 return true;
857                 break;
858         }
859         return false;
860 }
861
862 void
863 StartupFSM::show_pre_release_dialog ()
864 {
865         pre_release_dialog = new ArdourDialog  (_("Pre-Release Warning"), true, false);
866         pre_release_dialog->add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
867
868         Label* label = manage (new Label);
869         label->set_markup (string_compose (_("<span size=\"x-large\" weight=\"bold\">Welcome to this pre-release build of %1 %2</span>\n\n\
870 <span size=\"large\">There are still several issues and bugs to be worked on,\n\
871 as well as general workflow improvements, before this can be considered\n\
872 release software. So, a few guidelines:\n\
873 \n\
874 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
875    though it may be so, depending on your workflow.\n\
876 2) Please wait for a helpful writeup of new features.\n\
877 3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
878 4) <b>Please do NOT file bugs for this alpha-development versions at this point in time</b>.\n\
879    There is no bug triaging before the initial development concludes and\n\
880    reporting issue for incomplete, ongoing work-in-progress is mostly useless.\n\
881 5) Please <b>DO</b> join us on IRC for real time discussions about %1 %2. You\n\
882    can get there directly from within the program via the Help->Chat menu option.\n\
883 6) Please <b>DO</b> submit patches for issues after discussing them on IRC.\n\
884 \n\
885 Full information on all the above can be found on the support page at\n\
886 \n\
887                 http://ardour.org/support</span>\n\
888 "), PROGRAM_NAME, VERSIONSTRING));
889
890
891         current_dialog_connection = pre_release_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (this, &StartupFSM::dialog_response_handler), PreReleaseDialog));
892
893         pre_release_dialog->get_vbox()->set_border_width (12);
894         pre_release_dialog->get_vbox()->pack_start (*label, false, false, 12);
895         pre_release_dialog->get_vbox()->show_all ();
896         pre_release_dialog->set_position (WIN_POS_CENTER);
897         pre_release_dialog->present ();
898 }