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>
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.
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.
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.
35 #include "gtk2ardour-config.h"
36 #include "gtk2ardour-version.h"
39 #ifndef PLATFORM_WINDOWS
40 #include <sys/resource.h>
44 #include <sys/types.h>
45 #include <sys/sysctl.h>
49 #include "pbd/gstdio_compat.h"
51 #include <gtkmm/stock.h>
53 #include "pbd/basename.h"
54 #include "pbd/file_utils.h"
56 #include "ardour/audioengine.h"
57 #include "ardour/filename_extensions.h"
58 #include "ardour/filesystem_paths.h"
59 #include "ardour/profile.h"
61 #include "gtkmm2ext/application.h"
63 #include "ambiguous_file_dialog.h"
64 #include "ardour_ui.h"
66 #include "engine_dialog.h"
68 #include "missing_file_dialog.h"
72 #include "public_editor.h"
77 using namespace ARDOUR;
80 using namespace Gtkmm2ext;
85 _hide_splash (gpointer arg)
87 ((ARDOUR_UI*)arg)->hide_splash();
92 ARDOUR_UI::first_idle ()
95 _session->allow_auto_play (true);
102 /* in 1 second, hide the splash screen
104 * Consider hiding it *now*. If a user opens opens a dialog
105 * during that one second while the splash is still visible,
106 * the dialog will push-back the splash.
107 * Closing the dialog later will pop it back.
109 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
111 Keyboard::set_can_save_keybindings (true);
116 ARDOUR_UI::setup_profile ()
118 if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
119 Profile->set_small_screen ();
122 if (g_getenv ("MIXBUS")) {
123 Profile->set_mixbus ();
128 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
130 MissingFileDialog dialog (s, str, type);
135 int result = dialog.run ();
142 return 1; // quit entire session load
145 result = dialog.get_action ();
151 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
153 AmbiguousFileDialog dialog (file, hits);
160 return dialog.get_which ();
164 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
166 const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
167 const char* end_big = "</span>";
168 const char* start_mono = "<tt>";
169 const char* end_mono = "</tt>";
171 MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
172 "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
173 "From now on, use the backup copy with older versions of %3"),
174 xml_path, backup_path, PROGRAM_NAME,
176 start_mono, end_mono), true);
183 ARDOUR_UI::sr_mismatch_dialog (samplecnt_t desired, samplecnt_t actual)
185 HBox* hbox = new HBox();
186 Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
187 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
188 Label message (string_compose (_("\
189 This session was created with a sample rate of %1 Hz, but\n\
190 %2 is currently running at %3 Hz. If you load this session,\n\
191 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
193 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
194 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
195 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
196 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
197 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
198 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
199 dialog.set_default_response (RESPONSE_ACCEPT);
200 dialog.set_position (WIN_POS_CENTER);
205 switch (dialog.run()) {
206 case RESPONSE_ACCEPT:
216 ARDOUR_UI::sr_mismatch_message (samplecnt_t desired, samplecnt_t actual)
218 MessageDialog msg (string_compose (_("\
219 This session was created with a sample rate of %1 Hz, but\n\
220 %2 is currently running at %3 Hz.\n\
221 Audio will be recorded and played at the wrong sample rate.\n\
222 Re-Configure the Audio Engine in\n\
223 Menu > Window > Audio/Midi Setup"),
224 desired, PROGRAM_NAME, actual),
226 Gtk::MESSAGE_WARNING);
232 ARDOUR_UI::preferences_settings () const
237 node = _session->instant_xml(X_("Preferences"));
239 node = Config->instant_xml(X_("Preferences"));
243 node = new XMLNode (X_("Preferences"));
250 ARDOUR_UI::mixer_settings () const
255 node = _session->instant_xml(X_("Mixer"));
257 node = Config->instant_xml(X_("Mixer"));
261 node = new XMLNode (X_("Mixer"));
268 ARDOUR_UI::main_window_settings () const
273 node = _session->instant_xml(X_("Main"));
275 node = Config->instant_xml(X_("Main"));
279 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
280 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
285 node = new XMLNode (X_("Main"));
292 ARDOUR_UI::editor_settings () const
297 node = _session->instant_xml(X_("Editor"));
299 node = Config->instant_xml(X_("Editor"));
303 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
304 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
309 node = new XMLNode (X_("Editor"));
316 ARDOUR_UI::keyboard_settings () const
320 node = Config->extra_xml(X_("Keyboard"));
323 node = new XMLNode (X_("Keyboard"));
330 ARDOUR_UI::hide_splash ()
336 ARDOUR_UI::check_announcements ()
339 string _annc_filename;
342 _annc_filename = PROGRAM_NAME "_announcements_osx_";
343 #elif defined PLATFORM_WINDOWS
344 _annc_filename = PROGRAM_NAME "_announcements_windows_";
346 _annc_filename = PROGRAM_NAME "_announcements_linux_";
348 _annc_filename.append (VERSIONSTRING);
350 _announce_string = "";
352 std::string path = Glib::build_filename (user_config_directory(), _annc_filename);
353 FILE* fin = g_fopen (path.c_str(), "rb");
355 while (!feof (fin)) {
358 if ((len = fread (tmp, sizeof(char), 1024, fin)) == 0 || ferror (fin)) {
361 _announce_string.append (tmp, len);
366 pingback (VERSIONSTRING, path);
371 ARDOUR_UI::nsm_init ()
375 if ((nsm_url = g_getenv ("NSM_URL")) == 0) {
379 nsm = new NSM_Client;
381 if (nsm->init (nsm_url)) {
384 error << _("NSM: initialization failed") << endmsg;
388 /* the ardour executable may have different names:
390 * waf's obj.target for distro versions: eg ardour4, ardourvst4
391 * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
392 * argv[0] does not apply since we need the wrapper-script (not the binary itself)
394 * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
396 const char *process_name = g_getenv ("ARDOUR_SELF");
397 nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour6");
400 // wait for announce reply from nsm server
401 for ( i = 0; i < 5000; ++i) {
405 if (nsm->is_active()) {
410 error << _("NSM server did not announce itself") << endmsg;
413 // wait for open command from nsm server
414 for ( i = 0; i < 5000; ++i) {
417 if (nsm->client_id ()) {
423 error << _("NSM: no client ID provided") << endmsg;
427 if (_session && nsm) {
428 _session->set_nsm_state( nsm->is_active() );
430 error << _("NSM: no session created") << endmsg;
434 // nsm requires these actions disabled
435 vector<string> action_names;
436 action_names.push_back("SaveAs");
437 action_names.push_back("Rename");
438 action_names.push_back("New");
439 action_names.push_back("Open");
440 action_names.push_back("Recent");
441 action_names.push_back("Close");
443 for (vector<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
444 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), (*n).c_str());
446 act->set_sensitive (false);
454 ARDOUR_UI::sfsm_response (StartupFSM::Result r)
456 DEBUG_TRACE (DEBUG::GuiStartup, string_compose (X_("startup FSM response %1\n"), r));
459 case StartupFSM::ExitProgram:
463 case StartupFSM::LoadSession:
465 if (load_session_from_startup_fsm () == 0) {
470 startup_fsm->reset ();
478 ARDOUR_UI::starting ()
480 Application* app = Application::instance();
482 if (ARDOUR_COMMAND_LINE::check_announcements) {
483 check_announcements ();
488 /* we need to create this early because it may need to set the
489 * audio backend end up.
495 amd = dynamic_cast<EngineControl*> (audio_midi_setup.get (true));
497 std::cerr << "audio-midi engine setup failed."<< std::endl;
506 startup_fsm = new StartupFSM (*amd);
507 startup_fsm->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::sfsm_response));
509 /* Note: entire startup process could happen in this one call
513 * 2) session name provided on command line (and valid)
514 * 3) no audio/MIDI setup required
517 startup_fsm->start ();
524 ARDOUR_UI::load_session_from_startup_fsm ()
526 const string session_path = startup_fsm->session_path;
527 const string session_name = startup_fsm->session_name;
528 const string session_template = startup_fsm->session_template;
529 const bool session_is_new = startup_fsm->session_is_new;
530 const BusProfile bus_profile = startup_fsm->bus_profile;
532 std::cerr << " loading from " << session_path << " as " << session_name << " templ " << session_template << " is_new " << session_is_new << " bp " << bus_profile.master_out_channels << std::endl;
534 if (session_is_new) {
536 if (build_session (session_path, session_name, &bus_profile)) {
540 if (!session_template.empty() && session_template.substr (0, 11) == "urn:ardour:") {
541 meta_session_setup (session_template.substr (11));
547 return load_session (session_path, session_name, session_template);
552 ARDOUR_UI::startup_done ()
554 /* ShouldQuit is a desktop environment mechanism that tells the
555 application it should exit for reasons external to the application
558 During startup, startupFSM handles ShouldQuit. But it is done now,
559 and we have to take over responsibility.
561 Application::instance()->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
565 WM::Manager::instance().show_visible ();
567 /* We have to do this here since goto_editor_window() ends up calling show_all() on the
568 * editor window, and we may want stuff to be hidden.
570 _status_bar_visibility.update ();
572 BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
576 ARDOUR_UI::use_config ()
578 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
580 set_transport_controllable_state (*node);
585 ARDOUR_UI::check_memory_locking ()
587 #if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
588 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
592 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
594 if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
596 struct rlimit limits;
598 long pages, page_size;
600 size_t pages_len=sizeof(pages);
601 if ((page_size = getpagesize()) < 0 ||
602 sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
604 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
609 ram = (int64_t) pages * (int64_t) page_size;
612 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
616 if (limits.rlim_cur != RLIM_INFINITY) {
618 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
622 _("WARNING: Your system has a limit for maximum amount of locked memory. "
623 "This might cause %1 to run out of memory before your system "
624 "runs out of memory. \n\n"
625 "You can view the memory limit with 'ulimit -l', "
626 "and it is normally controlled by %2"),
629 X_("/etc/login.conf")
631 X_(" /etc/security/limits.conf")
635 msg.set_default_response (RESPONSE_OK);
637 VBox* vbox = msg.get_vbox();
639 CheckButton cb (_("Do not show this window again"));
640 hbox.pack_start (cb, true, false);
641 vbox->pack_start (hbox);
646 pop_back_splash (msg);
650 if (cb.get_active()) {
651 XMLNode node (X_("no-memory-warning"));
652 Config->add_instant_xml (node);