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 if (ARDOUR_COMMAND_LINE::check_announcements) {
481 check_announcements ();
484 /* we need to create this early because it may need to set the
485 * audio backend end up.
491 amd = dynamic_cast<EngineControl*> (audio_midi_setup.get (true));
493 std::cerr << "audio-midi engine setup failed."<< std::endl;
502 startup_fsm = new StartupFSM (*amd);
503 startup_fsm->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::sfsm_response));
505 /* Note: entire startup process could happen in this one call
509 * 2) session name provided on command line (and valid)
510 * 3) no audio/MIDI setup required
513 startup_fsm->start ();
520 ARDOUR_UI::load_session_from_startup_fsm ()
522 const string session_path = startup_fsm->session_path;
523 const string session_name = startup_fsm->session_name;
524 const string session_template = startup_fsm->session_template;
525 const bool session_is_new = startup_fsm->session_is_new;
526 const BusProfile bus_profile = startup_fsm->bus_profile;
528 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;
530 if (session_is_new) {
532 if (build_session (session_path, session_name, &bus_profile)) {
536 if (!session_template.empty() && session_template.substr (0, 11) == "urn:ardour:") {
537 meta_session_setup (session_template.substr (11));
543 return load_session (session_path, session_name, session_template);
548 ARDOUR_UI::startup_done ()
552 WM::Manager::instance().show_visible ();
554 /* We have to do this here since goto_editor_window() ends up calling show_all() on the
555 * editor window, and we may want stuff to be hidden.
557 _status_bar_visibility.update ();
559 BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
563 ARDOUR_UI::use_config ()
565 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
567 set_transport_controllable_state (*node);
572 ARDOUR_UI::check_memory_locking ()
574 #if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
575 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
579 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
581 if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
583 struct rlimit limits;
585 long pages, page_size;
587 size_t pages_len=sizeof(pages);
588 if ((page_size = getpagesize()) < 0 ||
589 sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
591 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
596 ram = (int64_t) pages * (int64_t) page_size;
599 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
603 if (limits.rlim_cur != RLIM_INFINITY) {
605 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
609 _("WARNING: Your system has a limit for maximum amount of locked memory. "
610 "This might cause %1 to run out of memory before your system "
611 "runs out of memory. \n\n"
612 "You can view the memory limit with 'ulimit -l', "
613 "and it is normally controlled by %2"),
616 X_("/etc/login.conf")
618 X_(" /etc/security/limits.conf")
622 msg.set_default_response (RESPONSE_OK);
624 VBox* vbox = msg.get_vbox();
626 CheckButton cb (_("Do not show this window again"));
627 hbox.pack_start (cb, true, false);
628 vbox->pack_start (hbox);
633 pop_back_splash (msg);
637 if (cb.get_active()) {
638 XMLNode node (X_("no-memory-warning"));
639 Config->add_instant_xml (node);