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