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_message.h"
65 #include "ardour_ui.h"
67 #include "engine_dialog.h"
69 #include "missing_file_dialog.h"
73 #include "public_editor.h"
78 using namespace ARDOUR;
81 using namespace Gtkmm2ext;
86 _hide_splash (gpointer arg)
88 ((ARDOUR_UI*)arg)->hide_splash();
93 ARDOUR_UI::first_idle ()
96 _session->allow_auto_play (true);
100 editor->first_idle();
103 /* in 1 second, hide the splash screen
105 * Consider hiding it *now*. If a user opens opens a dialog
106 * during that one second while the splash is still visible,
107 * the dialog will push-back the splash.
108 * Closing the dialog later will pop it back.
110 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
112 Keyboard::set_can_save_keybindings (true);
117 ARDOUR_UI::setup_profile ()
119 if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
120 Profile->set_small_screen ();
123 if (g_getenv ("MIXBUS")) {
124 Profile->set_mixbus ();
129 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
131 MissingFileDialog dialog (s, str, type);
136 int result = dialog.run ();
143 return 1; // quit entire session load
146 result = dialog.get_action ();
152 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
154 AmbiguousFileDialog dialog (file, hits);
161 return dialog.get_which ();
165 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
167 const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
168 const char* end_big = "</span>";
169 const char* start_mono = "<tt>";
170 const char* end_mono = "</tt>";
172 ArdourMessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
173 "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
174 "From now on, use the backup copy with older versions of %3"),
175 xml_path, backup_path, PROGRAM_NAME,
177 start_mono, end_mono), true);
184 ARDOUR_UI::sr_mismatch_dialog (samplecnt_t desired, samplecnt_t actual)
186 HBox* hbox = new HBox();
187 Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
188 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
189 Label message (string_compose (_("\
190 This session was created with a sample rate of %1 Hz, but\n\
191 %2 is currently running at %3 Hz. If you load this session,\n\
192 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
194 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
195 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
196 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
197 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
198 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
199 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
200 dialog.set_default_response (RESPONSE_ACCEPT);
201 dialog.set_position (WIN_POS_CENTER);
206 switch (dialog.run()) {
207 case RESPONSE_ACCEPT:
217 ARDOUR_UI::sr_mismatch_message (samplecnt_t desired, samplecnt_t actual)
219 ArdourMessageDialog msg (string_compose (_("\
220 This session was created with a sample rate of %1 Hz, but\n\
221 %2 is currently running at %3 Hz.\n\
222 Audio will be recorded and played at the wrong sample rate.\n\
223 Re-Configure the Audio Engine in\n\
224 Menu > Window > Audio/Midi Setup"),
225 desired, PROGRAM_NAME, actual),
227 Gtk::MESSAGE_WARNING);
233 ARDOUR_UI::preferences_settings () const
238 node = _session->instant_xml(X_("Preferences"));
240 node = Config->instant_xml(X_("Preferences"));
244 node = new XMLNode (X_("Preferences"));
251 ARDOUR_UI::mixer_settings () const
256 node = _session->instant_xml(X_("Mixer"));
258 node = Config->instant_xml(X_("Mixer"));
262 node = new XMLNode (X_("Mixer"));
269 ARDOUR_UI::main_window_settings () const
274 node = _session->instant_xml(X_("Main"));
276 node = Config->instant_xml(X_("Main"));
280 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
281 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
286 node = new XMLNode (X_("Main"));
293 ARDOUR_UI::editor_settings () const
298 node = _session->instant_xml(X_("Editor"));
300 node = Config->instant_xml(X_("Editor"));
304 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
305 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
310 node = new XMLNode (X_("Editor"));
317 ARDOUR_UI::keyboard_settings () const
321 node = Config->extra_xml(X_("Keyboard"));
324 node = new XMLNode (X_("Keyboard"));
331 ARDOUR_UI::hide_splash ()
337 ARDOUR_UI::check_announcements ()
340 string _annc_filename;
343 _annc_filename = PROGRAM_NAME "_announcements_osx_";
344 #elif defined PLATFORM_WINDOWS
345 _annc_filename = PROGRAM_NAME "_announcements_windows_";
347 _annc_filename = PROGRAM_NAME "_announcements_linux_";
349 _annc_filename.append (VERSIONSTRING);
351 _announce_string = "";
353 std::string path = Glib::build_filename (user_config_directory(), _annc_filename);
354 FILE* fin = g_fopen (path.c_str(), "rb");
356 while (!feof (fin)) {
359 if ((len = fread (tmp, sizeof(char), 1024, fin)) == 0 || ferror (fin)) {
362 _announce_string.append (tmp, len);
367 pingback (VERSIONSTRING, path);
372 ARDOUR_UI::nsm_init ()
376 if ((nsm_url = g_getenv ("NSM_URL")) == 0) {
380 nsm = new NSM_Client;
382 if (nsm->init (nsm_url)) {
385 error << _("NSM: initialization failed") << endmsg;
389 /* the ardour executable may have different names:
391 * waf's obj.target for distro versions: eg ardour4, ardourvst4
392 * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
393 * argv[0] does not apply since we need the wrapper-script (not the binary itself)
395 * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
397 const char *process_name = g_getenv ("ARDOUR_SELF");
398 nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour6");
401 // wait for announce reply from nsm server
402 for ( i = 0; i < 5000; ++i) {
406 if (nsm->is_active()) {
411 error << _("NSM server did not announce itself") << endmsg;
414 // wait for open command from nsm server
415 for ( i = 0; i < 5000; ++i) {
418 if (nsm->client_id ()) {
424 error << _("NSM: no client ID provided") << endmsg;
428 if (_session && nsm) {
429 _session->set_nsm_state( nsm->is_active() );
431 error << _("NSM: no session created") << endmsg;
435 // nsm requires these actions disabled
436 vector<string> action_names;
437 action_names.push_back("SaveAs");
438 action_names.push_back("Rename");
439 action_names.push_back("New");
440 action_names.push_back("Open");
441 action_names.push_back("Recent");
442 action_names.push_back("Close");
444 for (vector<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
445 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), (*n).c_str());
447 act->set_sensitive (false);
455 ARDOUR_UI::sfsm_response (StartupFSM::Result r)
457 DEBUG_TRACE (DEBUG::GuiStartup, string_compose (X_("startup FSM response %1\n"), r));
460 case StartupFSM::ExitProgram:
464 case StartupFSM::LoadSession:
466 if (load_session_from_startup_fsm () == 0) {
471 startup_fsm->reset ();
479 ARDOUR_UI::starting ()
481 Application* app = Application::instance();
483 if (ARDOUR_COMMAND_LINE::check_announcements) {
484 check_announcements ();
489 /* we need to create this early because it may need to set the
490 * audio backend end up.
496 amd = dynamic_cast<EngineControl*> (audio_midi_setup.get (true));
498 std::cerr << "audio-midi engine setup failed."<< std::endl;
507 startup_fsm = new StartupFSM (*amd);
508 startup_fsm->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::sfsm_response));
510 /* Note: entire startup process could happen in this one call
514 * 2) session name provided on command line (and valid)
515 * 3) no audio/MIDI setup required
518 startup_fsm->start ();
525 ARDOUR_UI::load_session_from_startup_fsm ()
527 const string session_path = startup_fsm->session_path;
528 const string session_name = startup_fsm->session_name;
529 const string session_template = startup_fsm->session_template;
530 const bool session_is_new = startup_fsm->session_is_new;
531 const BusProfile bus_profile = startup_fsm->bus_profile;
533 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;
535 if (session_is_new) {
537 if (build_session (session_path, session_name, &bus_profile)) {
541 if (!session_template.empty() && session_template.substr (0, 11) == "urn:ardour:") {
542 meta_session_setup (session_template.substr (11));
548 return load_session (session_path, session_name, session_template);
553 ARDOUR_UI::startup_done ()
555 /* ShouldQuit is a desktop environment mechanism that tells the
556 application it should exit for reasons external to the application
559 During startup, startupFSM handles ShouldQuit. But it is done now,
560 and we have to take over responsibility.
562 Application::instance()->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
566 WM::Manager::instance().show_visible ();
568 /* We have to do this here since goto_editor_window() ends up calling show_all() on the
569 * editor window, and we may want stuff to be hidden.
571 _status_bar_visibility.update ();
573 BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
577 ARDOUR_UI::use_config ()
579 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
581 set_transport_controllable_state (*node);
586 ARDOUR_UI::check_memory_locking ()
588 #if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
589 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
593 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
595 if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
597 struct rlimit limits;
599 long pages, page_size;
601 size_t pages_len=sizeof(pages);
602 if ((page_size = getpagesize()) < 0 ||
603 sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
605 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
610 ram = (int64_t) pages * (int64_t) page_size;
613 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
617 if (limits.rlim_cur != RLIM_INFINITY) {
619 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
621 ArdourMessageDialog msg (
623 _("WARNING: Your system has a limit for maximum amount of locked memory. "
624 "This might cause %1 to run out of memory before your system "
625 "runs out of memory. \n\n"
626 "You can view the memory limit with 'ulimit -l', "
627 "and it is normally controlled by %2"),
630 X_("/etc/login.conf")
632 X_(" /etc/security/limits.conf")
636 msg.set_default_response (RESPONSE_OK);
638 VBox* vbox = msg.get_vbox();
640 CheckButton cb (_("Do not show this window again"));
641 hbox.pack_start (cb, true, false);
642 vbox->pack_start (hbox);
649 if (cb.get_active()) {
650 XMLNode node (X_("no-memory-warning"));
651 Config->add_instant_xml (node);