rename transport masters dialog -> window
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2013 Paul Davis
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
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #include "gtk2ardour-version.h"
23 #endif
24
25 #include <algorithm>
26 #include <cmath>
27 #include <iostream>
28 #include <cerrno>
29
30 #include <stdarg.h>
31
32 #ifndef PLATFORM_WINDOWS
33 #include <sys/resource.h>
34 #endif
35
36 #ifdef __FreeBSD__
37 #include <sys/types.h>
38 #include <sys/sysctl.h>
39 #endif
40
41 #include <stdint.h>
42 #include <fcntl.h>
43 #include <signal.h>
44 #include <unistd.h>
45 #include <time.h>
46
47 #include <glib.h>
48 #include "pbd/gstdio_compat.h"
49
50 #include <gtkmm/accelmap.h>
51 #include <gtkmm/messagedialog.h>
52 #include <gtkmm/stock.h>
53 #include <gtkmm/uimanager.h>
54
55 #include "pbd/error.h"
56 #include "pbd/basename.h"
57 #include "pbd/compose.h"
58 #include "pbd/convert.h"
59 #include "pbd/failed_constructor.h"
60 #include "pbd/file_archive.h"
61 #include "pbd/enumwriter.h"
62 #include "pbd/memento_command.h"
63 #include "pbd/openuri.h"
64 #include "pbd/stl_delete.h"
65 #include "pbd/types_convert.h"
66 #include "pbd/unwind.h"
67 #include "pbd/file_utils.h"
68 #include "pbd/localtime_r.h"
69 #include "pbd/pthread_utils.h"
70 #include "pbd/replace_all.h"
71 #include "pbd/scoped_file_descriptor.h"
72 #include "pbd/xml++.h"
73
74 #include "gtkmm2ext/application.h"
75 #include "gtkmm2ext/bindings.h"
76 #include "gtkmm2ext/gtk_ui.h"
77 #include "gtkmm2ext/utils.h"
78 #include "gtkmm2ext/window_title.h"
79
80 #include "widgets/fastmeter.h"
81 #include "widgets/prompter.h"
82 #include "widgets/tooltips.h"
83
84 #include "ardour/ardour.h"
85 #include "ardour/audio_backend.h"
86 #include "ardour/audio_track.h"
87 #include "ardour/audioengine.h"
88 #include "ardour/audiofilesource.h"
89 #include "ardour/automation_watch.h"
90 #include "ardour/disk_reader.h"
91 #include "ardour/disk_writer.h"
92 #include "ardour/filename_extensions.h"
93 #include "ardour/filesystem_paths.h"
94 #include "ardour/ltc_file_reader.h"
95 #include "ardour/midi_track.h"
96 #include "ardour/port.h"
97 #include "ardour/plugin_manager.h"
98 #include "ardour/process_thread.h"
99 #include "ardour/profile.h"
100 #include "ardour/recent_sessions.h"
101 #include "ardour/record_enable_control.h"
102 #include "ardour/revision.h"
103 #include "ardour/session_directory.h"
104 #include "ardour/session_route.h"
105 #include "ardour/session_state_utils.h"
106 #include "ardour/session_utils.h"
107 #include "ardour/source_factory.h"
108 #include "ardour/transport_master.h"
109 #include "ardour/transport_master_manager.h"
110 #include "ardour/system_exec.h"
111 #include "ardour/track.h"
112 #include "ardour/vca_manager.h"
113 #include "ardour/utils.h"
114
115 #include "LuaBridge/LuaBridge.h"
116
117 #ifdef WINDOWS_VST_SUPPORT
118 #include <fst.h>
119 #endif
120 #ifdef AUDIOUNIT_SUPPORT
121 #include "ardour/audio_unit.h"
122 #endif
123
124 // fix for OSX (nsm.h has a check function, AU/Apple defines check)
125 #ifdef check
126 #undef check
127 #endif
128
129 #include "temporal/time.h"
130
131 typedef uint64_t microseconds_t;
132
133 #include "about.h"
134 #include "editing.h"
135 #include "enums_convert.h"
136 #include "actions.h"
137 #include "add_route_dialog.h"
138 #include "ambiguous_file_dialog.h"
139 #include "ardour_ui.h"
140 #include "audio_clock.h"
141 #include "audio_region_view.h"
142 #include "big_clock_window.h"
143 #include "big_transport_window.h"
144 #include "bundle_manager.h"
145 #include "duplicate_routes_dialog.h"
146 #include "debug.h"
147 #include "engine_dialog.h"
148 #include "export_video_dialog.h"
149 #include "export_video_infobox.h"
150 #include "gain_meter.h"
151 #include "global_port_matrix.h"
152 #include "gui_object.h"
153 #include "gui_thread.h"
154 #include "idleometer.h"
155 #include "keyboard.h"
156 #include "keyeditor.h"
157 #include "location_ui.h"
158 #include "lua_script_manager.h"
159 #include "luawindow.h"
160 #include "main_clock.h"
161 #include "missing_file_dialog.h"
162 #include "missing_plugin_dialog.h"
163 #include "mixer_ui.h"
164 #include "meterbridge.h"
165 #include "meter_patterns.h"
166 #include "mouse_cursors.h"
167 #include "nsm.h"
168 #include "opts.h"
169 #include "pingback.h"
170 #include "processor_box.h"
171 #include "public_editor.h"
172 #include "rc_option_editor.h"
173 #include "route_time_axis.h"
174 #include "route_params_ui.h"
175 #include "save_as_dialog.h"
176 #include "save_template_dialog.h"
177 #include "script_selector.h"
178 #include "session_archive_dialog.h"
179 #include "session_dialog.h"
180 #include "session_metadata_dialog.h"
181 #include "session_option_editor.h"
182 #include "speaker_dialog.h"
183 #include "splash.h"
184 #include "startup.h"
185 #include "template_dialog.h"
186 #include "time_axis_view_item.h"
187 #include "time_info_box.h"
188 #include "timers.h"
189 #include "transport_masters_dialog.h"
190 #include "utils.h"
191 #include "utils_videotl.h"
192 #include "video_server_dialog.h"
193 #include "add_video_dialog.h"
194 #include "transcode_video_dialog.h"
195
196 #include "pbd/i18n.h"
197
198 using namespace ARDOUR;
199 using namespace ARDOUR_UI_UTILS;
200 using namespace PBD;
201 using namespace Gtkmm2ext;
202 using namespace ArdourWidgets;
203 using namespace Gtk;
204 using namespace std;
205 using namespace Editing;
206
207 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
208
209 sigc::signal<void, samplepos_t> ARDOUR_UI::Clock;
210 sigc::signal<void> ARDOUR_UI::CloseAllDialogs;
211
212 static bool
213 ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
214 {
215         MessageDialog msg (string_compose (_("%1 %2.x has discovered configuration files from %1 %3.x.\n\n"
216                                              "Would you like these files to be copied and used for %1 %2.x?\n\n"
217                                              "(This will require you to restart %1.)"),
218                                            PROGRAM_NAME, PROGRAM_VERSION, version),
219                            false, /* no markup */
220                            Gtk::MESSAGE_INFO,
221                            Gtk::BUTTONS_YES_NO,
222                            true /* modal, though it hardly matters since it is the only window */
223         );
224
225         msg.set_default_response (Gtk::RESPONSE_YES);
226         msg.show_all ();
227
228         return (msg.run() == Gtk::RESPONSE_YES);
229 }
230
231 static void
232 libxml_generic_error_func (void* /* parsing_context*/,
233                            const char* msg,
234                            ...)
235 {
236         va_list ap;
237         char buf[2048];
238
239         va_start (ap, msg);
240         vsnprintf (buf, sizeof (buf), msg, ap);
241         error << buf << endmsg;
242         va_end (ap);
243 }
244
245 static void
246 libxml_structured_error_func (void* /* parsing_context*/,
247                               xmlErrorPtr err)
248 {
249         string msg;
250
251         if (err->message)
252                 msg = err->message;
253
254         replace_all (msg, "\n", "");
255
256         if (!msg.empty()) {
257                 if (err->file && err->line) {
258                         error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line;
259
260                         if (err->int2) {
261                                 error << ':' << err->int2;
262                         }
263
264                         error << endmsg;
265                 } else {
266                         error << X_("XML error: ") << msg << endmsg;
267                 }
268         }
269 }
270
271
272 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
273         : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
274         , session_loaded (false)
275         , session_load_in_progress (false)
276         , gui_object_state (new GUIObjectState)
277         , primary_clock   (new MainClock (X_("primary"),   X_("transport"), true ))
278         , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
279         , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
280         , video_timeline(0)
281         , global_actions (X_("global"))
282         , ignore_dual_punch (false)
283         , main_window_visibility (0)
284         , editor (0)
285         , mixer (0)
286         , nsm (0)
287         , _was_dirty (false)
288         , _mixer_on_top (false)
289         , _initial_verbose_plugin_scan (false)
290         , first_time_engine_run (true)
291         , secondary_clock_spacer (0)
292         , auto_input_button (ArdourButton::led_default_elements)
293         , time_info_box (0)
294         , auto_return_button (ArdourButton::led_default_elements)
295         , follow_edits_button (ArdourButton::led_default_elements)
296         , auditioning_alert_button (_("Audition"))
297         , solo_alert_button (_("Solo"))
298         , feedback_alert_button (_("Feedback"))
299         , error_alert_button ( ArdourButton::just_led_default_elements )
300         , editor_meter_peak_display()
301         , editor_meter(0)
302         , _suspend_editor_meter_callbacks (false)
303         , _numpad_locate_happening (false)
304         , _session_is_new (false)
305         , last_key_press_time (0)
306         , save_as_dialog (0)
307         , meterbridge (0)
308         , luawindow (0)
309         , rc_option_editor (0)
310         , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
311         , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
312         , about (X_("about"), _("About"))
313         , location_ui (X_("locations"), S_("Ranges|Locations"))
314         , route_params (X_("inspector"), _("Tracks and Busses"))
315         , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
316         , export_video_dialog (X_("video-export"), _("Video Export Dialog"))
317         , lua_script_window (X_("script-manager"), _("Script Manager"))
318         , idleometer (X_("idle-o-meter"), _("Idle'o'Meter"))
319         , transport_masters_window (X_("transport-masters"), _("Transport Masters"))
320         , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
321         , add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
322         , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
323         , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
324         , big_transport_window (X_("big-transport"), _("Transport Controls"), boost::bind (&ARDOUR_UI::create_big_transport_window, this))
325         , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
326         , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
327         , key_editor (X_("key-editor"), _("Keyboard Shortcuts"), boost::bind (&ARDOUR_UI::create_key_editor, this))
328         , video_server_process (0)
329         , splash (0)
330         , have_configure_timeout (false)
331         , last_configure_time (0)
332         , last_peak_grab (0)
333         , have_disk_speed_dialog_displayed (false)
334         , _status_bar_visibility (X_("status-bar"))
335         , _feedback_exists (false)
336         , _log_not_acknowledged (LogLevelNone)
337         , duplicate_routes_dialog (0)
338         , editor_visibility_button (S_("Window|Editor"))
339         , mixer_visibility_button (S_("Window|Mixer"))
340         , prefs_visibility_button (S_("Window|Preferences"))
341 {
342         Gtkmm2ext::init (localedir);
343
344         UIConfiguration::instance().post_gui_init ();
345
346         if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) {
347                 {
348                         /* "touch" the been-here-before path now that config has been migrated */
349                         PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
350                 }
351                 MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
352                 msg.run ();
353                 /* configuration was modified, exit immediately */
354                 _exit (0);
355         }
356
357
358         if (string (VERSIONSTRING).find (".pre") != string::npos) {
359                 /* check this is not being run from ./ardev etc. */
360                 if (!running_from_source_tree ()) {
361                         pre_release_dialog ();
362                 }
363         }
364
365         if (theArdourUI == 0) {
366                 theArdourUI = this;
367         }
368
369         /* track main window visibility */
370
371         main_window_visibility = new VisibilityTracker (_main_window);
372
373         /* stop libxml from spewing to stdout/stderr */
374
375         xmlSetGenericErrorFunc (this, libxml_generic_error_func);
376         xmlSetStructuredErrorFunc (this, libxml_structured_error_func);
377
378         UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
379         boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
380         UIConfiguration::instance().map_parameters (pc);
381
382         transport_ctrl.setup (this);
383
384         ARDOUR::DiskWriter::Overrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
385         ARDOUR::DiskReader::Underrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
386
387         ARDOUR::Session::VersionMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_format_mismatch, this, _1, _2), gui_context());
388
389         /* handle dialog requests */
390
391         ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
392
393         /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
394
395         ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
396
397         /* handle Audio/MIDI setup when session requires it */
398
399         ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1));
400
401         /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
402
403         ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
404
405         /* handle sr mismatch with a dialog - cross-thread from engine */
406         ARDOUR::Session::NotifyAboutSampleRateMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::sr_mismatch_message, this, _1, _2), gui_context ());
407
408         /* handle requests to quit (coming from JACK session) */
409
410         ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::finish, this), gui_context ());
411
412         /* tell the user about feedback */
413
414         ARDOUR::Session::FeedbackDetected.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::feedback_detected, this), gui_context ());
415         ARDOUR::Session::SuccessfulGraphSort.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::successful_graph_sort, this), gui_context ());
416
417         /* handle requests to deal with missing files */
418
419         ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
420
421         /* and ambiguous files */
422
423         ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2));
424
425         /* also plugin scan messages */
426         ARDOUR::PluginScanMessage.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_dialog, this, _1, _2, _3), gui_context());
427         ARDOUR::PluginScanTimeout.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_timeout, this, _1), gui_context());
428
429         ARDOUR::GUIIdle.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::gui_idle_handler, this), gui_context());
430
431         Config->ParameterChanged.connect ( forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::set_flat_buttons, this), gui_context() );
432         set_flat_buttons();
433
434         /* lets get this party started */
435
436         setup_gtk_ardour_enums ();
437         setup_profile ();
438
439         SessionEvent::create_per_thread_pool ("GUI", 4096);
440
441         /* we like keyboards */
442
443         keyboard = new ArdourKeyboard(*this);
444
445         XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
446         if (node) {
447                 keyboard->set_state (*node, Stateful::loading_state_version);
448         }
449
450         UIConfiguration::instance().reset_dpi ();
451
452         TimeAxisViewItem::set_constant_heights ();
453
454         /* Set this up so that our window proxies can register actions */
455
456         ActionManager::init ();
457
458         /* The following must happen after ARDOUR::init() so that Config is set up */
459
460         const XMLNode* ui_xml = Config->extra_xml (X_("UI"));
461
462         if (ui_xml) {
463                 std::cerr << "\n\n\nHAVE UI XML, set dialogs\n\n\n";
464                 key_editor.set_state (*ui_xml, 0);
465                 session_option_editor.set_state (*ui_xml, 0);
466                 speaker_config_window.set_state (*ui_xml, 0);
467                 about.set_state (*ui_xml, 0);
468                 add_route_dialog.set_state (*ui_xml, 0);
469                 add_video_dialog.set_state (*ui_xml, 0);
470                 route_params.set_state (*ui_xml, 0);
471                 bundle_manager.set_state (*ui_xml, 0);
472                 location_ui.set_state (*ui_xml, 0);
473                 big_clock_window.set_state (*ui_xml, 0);
474                 big_transport_window.set_state (*ui_xml, 0);
475                 audio_port_matrix.set_state (*ui_xml, 0);
476                 midi_port_matrix.set_state (*ui_xml, 0);
477                 export_video_dialog.set_state (*ui_xml, 0);
478                 lua_script_window.set_state (*ui_xml, 0);
479                 idleometer.set_state (*ui_xml, 0);
480                 transport_masters_window.set_state (*ui_xml, 0);
481         }
482
483         /* Separate windows */
484
485         WM::Manager::instance().register_window (&key_editor);
486         WM::Manager::instance().register_window (&session_option_editor);
487         WM::Manager::instance().register_window (&speaker_config_window);
488         WM::Manager::instance().register_window (&about);
489         WM::Manager::instance().register_window (&add_route_dialog);
490         WM::Manager::instance().register_window (&add_video_dialog);
491         WM::Manager::instance().register_window (&route_params);
492         WM::Manager::instance().register_window (&audio_midi_setup);
493         WM::Manager::instance().register_window (&export_video_dialog);
494         WM::Manager::instance().register_window (&lua_script_window);
495         WM::Manager::instance().register_window (&bundle_manager);
496         WM::Manager::instance().register_window (&location_ui);
497         WM::Manager::instance().register_window (&big_clock_window);
498         WM::Manager::instance().register_window (&big_transport_window);
499         WM::Manager::instance().register_window (&audio_port_matrix);
500         WM::Manager::instance().register_window (&midi_port_matrix);
501         WM::Manager::instance().register_window (&idleometer);
502         WM::Manager::instance().register_window (&transport_masters_window);
503
504         /* do not retain position for add route dialog */
505         add_route_dialog.set_state_mask (WindowProxy::Size);
506
507         /* Trigger setting up the color scheme and loading the GTK RC file */
508
509         UIConfiguration::instance().load_rc_file (false);
510
511         _process_thread = new ProcessThread ();
512         _process_thread->init ();
513
514         UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets));
515
516         attach_to_engine ();
517 }
518
519 void
520 ARDOUR_UI::pre_release_dialog ()
521 {
522         ArdourDialog d (_("Pre-Release Warning"), true, false);
523         d.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
524
525         Label* label = manage (new Label);
526         label->set_markup (string_compose (_("<b>Welcome to this pre-release build of %1 %2</b>\n\n\
527 There are still several issues and bugs to be worked on,\n\
528 as well as general workflow improvements, before this can be considered\n\
529 release software. So, a few guidelines:\n\
530 \n\
531 1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
532    though it may be so, depending on your workflow.\n\
533 2) Please wait for a helpful writeup of new features.\n\
534 3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
535 4) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
536    making sure to note the product version number as 6.0-pre.\n\
537 5) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
538 6) Please <b>DO</b> join us on IRC for real time discussions about %1 %2. You\n\
539    can get there directly from within the program via the Help->Chat menu option.\n\
540 \n\
541 Full information on all the above can be found on the support page at\n\
542 \n\
543                 http://ardour.org/support\n\
544 "), PROGRAM_NAME, VERSIONSTRING));
545
546         d.get_vbox()->set_border_width (12);
547         d.get_vbox()->pack_start (*label, false, false, 12);
548         d.get_vbox()->show_all ();
549
550         d.run ();
551 }
552
553 GlobalPortMatrixWindow*
554 ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type)
555 {
556         if (!_session) {
557                 return 0;
558         }
559         return new GlobalPortMatrixWindow (_session, type);
560 }
561
562 void
563 ARDOUR_UI::attach_to_engine ()
564 {
565         AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
566         ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
567 }
568
569 void
570 ARDOUR_UI::engine_stopped ()
571 {
572         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
573         ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
574         ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
575         update_sample_rate (0);
576         update_cpu_load ();
577 }
578
579 void
580 ARDOUR_UI::engine_running ()
581 {
582         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
583         if (first_time_engine_run) {
584                 post_engine();
585                 first_time_engine_run = false;
586         }
587
588         if (_session) {
589                 _session->reset_xrun_count ();
590         }
591         update_disk_space ();
592         update_cpu_load ();
593         update_sample_rate (AudioEngine::instance()->sample_rate());
594         update_timecode_format ();
595         update_peak_thread_work ();
596         ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, true);
597         ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, false);
598 }
599
600 void
601 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
602 {
603         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
604                 /* we can't rely on the original string continuing to exist when we are called
605                    again in the GUI thread, so make a copy and note that we need to
606                    free it later.
607                 */
608                 char *copy = strdup (reason);
609                 Gtkmm2ext::UI::instance()->call_slot (MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
610                 return;
611         }
612
613         ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
614         ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
615
616         update_sample_rate (0);
617
618         string msgstr;
619
620         /* if the reason is a non-empty string, it means that the backend was shutdown
621            rather than just Ardour.
622         */
623
624         if (strlen (reason)) {
625                 msgstr = string_compose (_("The audio backend was shutdown because:\n\n%1"), reason);
626         } else {
627                 msgstr = string_compose (_("\
628 The audio backend has either been shutdown or it\n\
629 disconnected %1 because %1\n\
630 was not fast enough. Try to restart\n\
631 the audio backend and save the session."), PROGRAM_NAME);
632         }
633
634         MessageDialog msg (_main_window, msgstr);
635         pop_back_splash (msg);
636         msg.run ();
637
638         if (free_reason) {
639                 free (const_cast<char*> (reason));
640         }
641 }
642
643 void
644 ARDOUR_UI::post_engine ()
645 {
646         /* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine
647          */
648 #ifdef AUDIOUNIT_SUPPORT
649         std::string au_msg;
650         if (AUPluginInfo::au_get_crashlog(au_msg)) {
651                 popup_error(_("Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. Please see the log window for further details."));
652                 error << _("Audio Unit Plugin Scan Failed:") << endmsg;
653                 info << au_msg << endmsg;
654         }
655 #endif
656
657         ARDOUR::init_post_engine ();
658
659         /* connect to important signals */
660
661         AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
662         AudioEngine::instance()->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
663         AudioEngine::instance()->BufferSizeChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
664         AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
665         AudioEngine::instance()->BecameSilent.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::audioengine_became_silent, this), gui_context());
666
667         if (setup_windows ()) {
668                 throw failed_constructor ();
669         }
670
671         transport_ctrl.map_actions ();
672
673         /* Do this after setup_windows (), as that's when the _status_bar_visibility is created */
674         XMLNode* n = Config->extra_xml (X_("UI"));
675         if (n) {
676                 _status_bar_visibility.set_state (*n);
677         }
678
679         check_memory_locking();
680
681         /* this is the first point at which all the possible actions are
682          * available, because some of the available actions are dependent on
683          * aspects of the engine/backend.
684          */
685
686         if (ARDOUR_COMMAND_LINE::show_key_actions) {
687                 stringstream sstr;
688                 Bindings::save_all_bindings_as_html (sstr);
689
690                 if (sstr.str().empty()) {
691                         return;
692                 }
693                 gchar* file_name;
694                 GError *err = NULL;
695                 gint fd;
696
697                 if ((fd = g_file_open_tmp ("akprintXXXXXX.html", &file_name, &err)) < 0) {
698                         if (err) {
699                                 error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg;
700                                 g_error_free (err);
701                         }
702                         return;
703                 }
704
705 #ifdef PLATFORM_WINDOWS
706                 ::close (fd);
707 #endif
708
709                 err = NULL;
710
711                 if (!g_file_set_contents (file_name, sstr.str().c_str(), sstr.str().size(), &err)) {
712 #ifndef PLATFORM_WINDOWS
713                         ::close (fd);
714 #endif
715                         g_unlink (file_name);
716                         if (err) {
717                                 error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg;
718                                 g_error_free (err);
719                         }
720                         return;
721                 }
722
723 #ifndef PLATFORM_WINDOWS
724                 ::close (fd);
725 #endif
726
727                 PBD::open_uri (string_compose ("file:///%1", file_name));
728
729                 halt_connection.disconnect ();
730                 AudioEngine::instance()->stop ();
731                 exit (0);
732
733         }
734
735         if (ARDOUR_COMMAND_LINE::show_actions) {
736
737
738                 vector<string> paths;
739                 vector<string> labels;
740                 vector<string> tooltips;
741                 vector<string> keys;
742                 vector<Glib::RefPtr<Gtk::Action> > actions;
743                 string ver_in = revision;
744                 string ver = ver_in.substr(0, ver_in.find("-"));
745
746                 stringstream output;
747                 output << "\n<h2>Menu actions</h2>" << endl;
748                 output << "<p>\n  Every single menu item in " << PROGRAM_NAME << "'s GUI is accessible by control" << endl;
749                 output << "  surfaces or scripts.\n</p>\n" << endl;
750                 output << "<p>\n  The list below shows all available values of <em>action-name</em> as of" << endl;
751                 output << "  " << PROGRAM_NAME << " " << ver << ". You can get the current list at any" << endl;
752                 output << "  time by running " << PROGRAM_NAME << " with the -A flag.\n</p>\n" << endl;
753                 output << "<table class=\"dl\">\n  <thead>" << endl;
754                 output << "      <tr><th>Action Name</th><th>Menu Name</th></tr>" << endl;
755                 output << "  </thead>\n  <tbody>" << endl;
756
757                 Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions);
758
759                 vector<string>::iterator p;
760                 vector<string>::iterator l;
761
762                 for (p = paths.begin(), l = labels.begin(); p != paths.end(); ++p, ++l) {
763                         output << "     <tr><th><kbd class=\"osc\">" << (*p).substr (10, string::npos);
764                         output << "</kbd></th><td>" << *l << "</td></tr>" << endl;
765                 }
766                 output << "  </tbody>\n  </table>" << endl;
767
768                 // output this mess to a browser for easiest X-platform use
769                 // it is not pretty HTML, but it works and it's main purpose
770                 // is to create raw html to fit in Ardour's manual with no editing
771                 gchar* file_name;
772                 GError *err = NULL;
773                 gint fd;
774
775                 if ((fd = g_file_open_tmp ("list-of-menu-actionsXXXXXX.html", &file_name, &err)) < 0) {
776                         if (err) {
777                                 error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg;
778                                 g_error_free (err);
779                         }
780                         return;
781                 }
782
783 #ifdef PLATFORM_WINDOWS
784                 ::close (fd);
785 #endif
786
787                 err = NULL;
788
789                 if (!g_file_set_contents (file_name, output.str().c_str(), output.str().size(), &err)) {
790 #ifndef PLATFORM_WINDOWS
791                         ::close (fd);
792 #endif
793                         g_unlink (file_name);
794                         if (err) {
795                                 error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg;
796                                 g_error_free (err);
797                         }
798                         return;
799                 }
800
801 #ifndef PLATFORM_WINDOWS
802                 ::close (fd);
803 #endif
804
805                 PBD::open_uri (string_compose ("file:///%1", file_name));
806
807                 halt_connection.disconnect ();
808                 AudioEngine::instance()->stop ();
809                 exit (0);
810         }
811
812         /* this being a GUI and all, we want peakfiles */
813
814         AudioFileSource::set_build_peakfiles (true);
815         AudioFileSource::set_build_missing_peakfiles (true);
816
817         /* set default clock modes */
818
819         primary_clock->set_mode (AudioClock::Timecode);
820         secondary_clock->set_mode (AudioClock::BBT);
821
822         /* start the time-of-day-clock */
823
824 #ifndef __APPLE__
825         /* OS X provides a nearly-always visible wallclock, so don't be stupid */
826         update_wall_clock ();
827         Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1);
828 #endif
829
830         {
831                 DisplaySuspender ds;
832                 Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
833                 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
834                 Config->map_parameters (pc);
835
836                 UIConfiguration::instance().map_parameters (pc);
837         }
838 }
839
840 ARDOUR_UI::~ARDOUR_UI ()
841 {
842         UIConfiguration::instance().save_state();
843
844         stop_video_server();
845
846         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
847                 // don't bother at 'real' exit. the OS cleans up for us.
848                 delete big_clock; big_clock = 0;
849                 delete primary_clock; primary_clock = 0;
850                 delete secondary_clock; secondary_clock = 0;
851                 delete _process_thread; _process_thread = 0;
852                 delete time_info_box; time_info_box = 0;
853                 delete meterbridge; meterbridge = 0;
854                 delete luawindow; luawindow = 0;
855                 delete editor; editor = 0;
856                 delete mixer; mixer = 0;
857                 delete rc_option_editor; rc_option_editor = 0; // failed to wrap object warning
858                 delete nsm; nsm = 0;
859                 delete gui_object_state; gui_object_state = 0;
860                 delete main_window_visibility;
861                 FastMeter::flush_pattern_cache ();
862                 ArdourFader::flush_pattern_cache ();
863         }
864
865 #ifndef NDEBUG
866         /* Small trick to flush main-thread event pool.
867          * Other thread-pools are destroyed at pthread_exit(),
868          * but tmain thread termination is too late to trigger Pool::~Pool()
869          */
870         SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Clear, SessionEvent::Immediate, 0, 0); // get the pool reference, values don't matter since the event is never queued.
871         delete ev->event_pool();
872 #endif
873 }
874
875 void
876 ARDOUR_UI::pop_back_splash (Gtk::Window& win)
877 {
878         if (Splash::instance()) {
879                 Splash::instance()->pop_back_for (win);
880         }
881 }
882
883 gint
884 ARDOUR_UI::configure_timeout ()
885 {
886         if (last_configure_time == 0) {
887                 /* no configure events yet */
888                 return true;
889         }
890
891         /* force a gap of 0.5 seconds since the last configure event
892          */
893
894         if (get_microseconds() - last_configure_time < 500000) {
895                 return true;
896         } else {
897                 have_configure_timeout = false;
898                 save_ardour_state ();
899                 return false;
900         }
901 }
902
903 gboolean
904 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
905 {
906         if (have_configure_timeout) {
907                 last_configure_time = get_microseconds();
908         } else {
909                 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
910                 have_configure_timeout = true;
911         }
912
913         return FALSE;
914 }
915
916 void
917 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
918 {
919         std::string str;
920
921         if (node.get_property ("roll", str)){
922                 roll_controllable->set_id (str);
923         }
924         if (node.get_property ("stop", str)) {
925                 stop_controllable->set_id (str);
926         }
927         if (node.get_property ("goto-start", str)) {
928                 goto_start_controllable->set_id (str);
929         }
930         if (node.get_property ("goto-end", str)) {
931                 goto_end_controllable->set_id (str);
932         }
933         if (node.get_property ("auto-loop", str)) {
934                 auto_loop_controllable->set_id (str);
935         }
936         if (node.get_property ("play-selection", str)) {
937                 play_selection_controllable->set_id (str);
938         }
939         if (node.get_property ("rec", str)) {
940                 rec_controllable->set_id (str);
941         }
942         if (node.get_property ("shuttle", str)) {
943                 shuttle_box.controllable()->set_id (str);
944         }
945 }
946
947 XMLNode&
948 ARDOUR_UI::get_transport_controllable_state ()
949 {
950         XMLNode* node = new XMLNode(X_("TransportControllables"));
951
952         node->set_property (X_("roll"), roll_controllable->id());
953         node->set_property (X_("stop"), stop_controllable->id());
954         node->set_property (X_("goto-start"), goto_start_controllable->id());
955         node->set_property (X_("goto-end"), goto_end_controllable->id());
956         node->set_property (X_("auto-loop"), auto_loop_controllable->id());
957         node->set_property (X_("play-selection"), play_selection_controllable->id());
958         node->set_property (X_("rec"), rec_controllable->id());
959         node->set_property (X_("shuttle"), shuttle_box.controllable()->id());
960
961         return *node;
962 }
963
964 void
965 ARDOUR_UI::save_session_at_its_request (std::string snapshot_name)
966 {
967         if (_session) {
968                 _session->save_state (snapshot_name);
969         }
970 }
971
972 gint
973 ARDOUR_UI::autosave_session ()
974 {
975         if (g_main_depth() > 1) {
976                 /* inside a recursive main loop,
977                    give up because we may not be able to
978                    take a lock.
979                 */
980                 return 1;
981         }
982
983         if (!Config->get_periodic_safety_backups()) {
984                 return 1;
985         }
986
987         if (_session) {
988                 _session->maybe_write_autosave();
989         }
990
991         return 1;
992 }
993
994 void
995 ARDOUR_UI::session_dirty_changed ()
996 {
997         update_autosave ();
998         update_title ();
999 }
1000
1001 void
1002 ARDOUR_UI::update_autosave ()
1003 {
1004         if (_session && _session->dirty()) {
1005                 if (_autosave_connection.connected()) {
1006                         _autosave_connection.disconnect();
1007                 }
1008
1009                 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
1010                                 Config->get_periodic_safety_backup_interval() * 1000);
1011
1012         } else {
1013                 if (_autosave_connection.connected()) {
1014                         _autosave_connection.disconnect();
1015                 }
1016         }
1017 }
1018
1019 void
1020 ARDOUR_UI::check_announcements ()
1021 {
1022 #ifdef PHONE_HOME
1023         string _annc_filename;
1024
1025 #ifdef __APPLE__
1026         _annc_filename = PROGRAM_NAME "_announcements_osx_";
1027 #elif defined PLATFORM_WINDOWS
1028         _annc_filename = PROGRAM_NAME "_announcements_windows_";
1029 #else
1030         _annc_filename = PROGRAM_NAME "_announcements_linux_";
1031 #endif
1032         _annc_filename.append (VERSIONSTRING);
1033
1034         _announce_string = "";
1035
1036         std::string path = Glib::build_filename (user_config_directory(), _annc_filename);
1037         FILE* fin = g_fopen (path.c_str(), "rb");
1038         if (fin) {
1039                 while (!feof (fin)) {
1040                         char tmp[1024];
1041                         size_t len;
1042                         if ((len = fread (tmp, sizeof(char), 1024, fin)) == 0 || ferror (fin)) {
1043                                 break;
1044                         }
1045                         _announce_string.append (tmp, len);
1046                 }
1047                 fclose (fin);
1048         }
1049
1050         pingback (VERSIONSTRING, path);
1051 #endif
1052 }
1053
1054 static bool
1055 _hide_splash (gpointer arg)
1056 {
1057         ((ARDOUR_UI*)arg)->hide_splash();
1058         return false;
1059 }
1060
1061 int
1062 ARDOUR_UI::starting ()
1063 {
1064         Application* app = Application::instance ();
1065         const char *nsm_url;
1066         bool brand_new_user = ArdourStartup::required ();
1067
1068         app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
1069         app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::load_from_application_api));
1070
1071         if (ARDOUR_COMMAND_LINE::check_announcements) {
1072                 check_announcements ();
1073         }
1074
1075         app->ready ();
1076
1077         /* we need to create this early because it may need to set the
1078          *  audio backend end up.
1079          */
1080
1081         try {
1082                 audio_midi_setup.get (true);
1083         } catch (...) {
1084                 std::cerr << "audio-midi engine setup failed."<< std::endl;
1085                 return -1;
1086         }
1087
1088         if ((nsm_url = g_getenv ("NSM_URL")) != 0) {
1089                 nsm = new NSM_Client;
1090                 if (!nsm->init (nsm_url)) {
1091                         /* the ardour executable may have different names:
1092                          *
1093                          * waf's obj.target for distro versions: eg ardour4, ardourvst4
1094                          * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
1095                          * argv[0] does not apply since we need the wrapper-script (not the binary itself)
1096                          *
1097                          * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
1098                          */
1099                         const char *process_name = g_getenv ("ARDOUR_SELF");
1100                         nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour6");
1101
1102                         unsigned int i = 0;
1103                         // wait for announce reply from nsm server
1104                         for ( i = 0; i < 5000; ++i) {
1105                                 nsm->check ();
1106
1107                                 Glib::usleep (i);
1108                                 if (nsm->is_active()) {
1109                                         break;
1110                                 }
1111                         }
1112                         if (i == 5000) {
1113                                 error << _("NSM server did not announce itself") << endmsg;
1114                                 return -1;
1115                         }
1116                         // wait for open command from nsm server
1117                         for ( i = 0; i < 5000; ++i) {
1118                                 nsm->check ();
1119                                 Glib::usleep (1000);
1120                                 if (nsm->client_id ()) {
1121                                         break;
1122                                 }
1123                         }
1124
1125                         if (i == 5000) {
1126                                 error << _("NSM: no client ID provided") << endmsg;
1127                                 return -1;
1128                         }
1129
1130                         if (_session && nsm) {
1131                                 _session->set_nsm_state( nsm->is_active() );
1132                         } else {
1133                                 error << _("NSM: no session created") << endmsg;
1134                                 return -1;
1135                         }
1136
1137                         // nsm requires these actions disabled
1138                         vector<string> action_names;
1139                         action_names.push_back("SaveAs");
1140                         action_names.push_back("Rename");
1141                         action_names.push_back("New");
1142                         action_names.push_back("Open");
1143                         action_names.push_back("Recent");
1144                         action_names.push_back("Close");
1145
1146                         for (vector<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
1147                                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), (*n).c_str());
1148                                 if (act) {
1149                                         act->set_sensitive (false);
1150                                 }
1151                         }
1152
1153                 } else {
1154                         delete nsm;
1155                         nsm = 0;
1156                         error << _("NSM: initialization failed") << endmsg;
1157                         return -1;
1158                 }
1159
1160         } else  {
1161
1162                 if (brand_new_user) {
1163                         _initial_verbose_plugin_scan = true;
1164                         ArdourStartup s;
1165                         s.present ();
1166                         main().run();
1167                         s.hide ();
1168                         _initial_verbose_plugin_scan = false;
1169                         switch (s.response ()) {
1170                         case Gtk::RESPONSE_OK:
1171                                 break;
1172                         default:
1173                                 return -1;
1174                         }
1175                 }
1176
1177                 // TODO: maybe IFF brand_new_user
1178                 if (ARDOUR::Profile->get_mixbus () && Config->get_copy_demo_sessions ()) {
1179                         std::string dspd (Config->get_default_session_parent_dir());
1180                         Searchpath ds (ARDOUR::ardour_data_search_path());
1181                         ds.add_subdirectory_to_paths ("sessions");
1182                         vector<string> demos;
1183                         find_files_matching_pattern (demos, ds, ARDOUR::session_archive_suffix);
1184
1185                         ARDOUR::RecentSessions rs;
1186                         ARDOUR::read_recent_sessions (rs);
1187
1188                         for (vector<string>::iterator i = demos.begin(); i != demos.end (); ++i) {
1189                                 /* "demo-session" must be inside "demo-session.<session_archive_suffix>" */
1190                                 std::string name = basename_nosuffix (basename_nosuffix (*i));
1191                                 std::string path = Glib::build_filename (dspd, name);
1192                                 /* skip if session-dir already exists */
1193                                 if (Glib::file_test(path.c_str(), Glib::FILE_TEST_IS_DIR)) {
1194                                         continue;
1195                                 }
1196                                 /* skip sessions that are already in 'recent'.
1197                                  * eg. a new user changed <session-default-dir> shorly after installation
1198                                  */
1199                                 for (ARDOUR::RecentSessions::iterator r = rs.begin(); r != rs.end(); ++r) {
1200                                         if ((*r).first == name) {
1201                                                 continue;
1202                                         }
1203                                 }
1204                                 try {
1205                                         PBD::FileArchive ar (*i);
1206                                         if (0 == ar.inflate (dspd)) {
1207                                                 store_recent_sessions (name, path);
1208                                                 info << string_compose (_("Copied Demo Session %1."), name) << endmsg;
1209                                         }
1210                                 } catch (...) {}
1211                         }
1212                 }
1213
1214 #ifdef NO_PLUGIN_STATE
1215
1216                 ARDOUR::RecentSessions rs;
1217                 ARDOUR::read_recent_sessions (rs);
1218
1219                 string path = Glib::build_filename (user_config_directory(), ".iknowaboutfreeversion");
1220
1221                 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS) && !rs.empty()) {
1222
1223                         /* already used Ardour, have sessions ... warn about plugin state */
1224
1225                         ArdourDialog d (_("Free/Demo Version Warning"), true);
1226                         Label l;
1227                         Button b (string_compose (_("Subscribe and support development of %1"), PROGRAM_NAME));
1228                         CheckButton c (_("Don't warn me about this again"));
1229
1230                         l.set_markup (string_compose (_("<span weight=\"bold\" size=\"large\">%1</span>\n\n<b>%2</b>\n\n<i>%3</i>\n\n%4"),
1231                                                       string_compose (_("This is a free/demo version of %1"), PROGRAM_NAME),
1232                                                       _("It will not restore OR save any plugin settings"),
1233                                                       _("If you load an existing session with plugin settings\n"
1234                                                         "they will not be used and will be lost."),
1235                                                       _("To get full access to updates without this limitation\n"
1236                                                         "consider becoming a subscriber for a low cost every month.")));
1237                         l.set_justify (JUSTIFY_CENTER);
1238
1239                         b.signal_clicked().connect (mem_fun(*this, &ARDOUR_UI::launch_subscribe));
1240
1241                         d.get_vbox()->pack_start (l, true, true);
1242                         d.get_vbox()->pack_start (b, false, false, 12);
1243                         d.get_vbox()->pack_start (c, false, false, 12);
1244
1245                         d.add_button (_("Quit now"), RESPONSE_CANCEL);
1246                         d.add_button (string_compose (_("Continue using %1"), PROGRAM_NAME), RESPONSE_OK);
1247
1248                         d.show_all ();
1249
1250                         c.signal_toggled().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (toggle_file_existence), path)));
1251
1252                         if (d.run () != RESPONSE_OK) {
1253                                 _exit (0);
1254                         }
1255                 }
1256 #endif
1257
1258                 /* go get a session */
1259
1260                 const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user);
1261
1262                 if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) {
1263                         std::cerr << "Cannot get session parameters."<< std::endl;
1264                         return -1;
1265                 }
1266         }
1267
1268         use_config ();
1269
1270         WM::Manager::instance().show_visible ();
1271
1272         /* We have to do this here since goto_editor_window() ends up calling show_all() on the
1273          * editor window, and we may want stuff to be hidden.
1274          */
1275         _status_bar_visibility.update ();
1276
1277         BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
1278
1279         /* all other dialogs are created conditionally */
1280
1281         return 0;
1282 }
1283
1284 void
1285 ARDOUR_UI::check_memory_locking ()
1286 {
1287 #if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
1288         /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
1289         return;
1290 #else // !__APPLE__
1291
1292         XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
1293
1294         if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
1295
1296                 struct rlimit limits;
1297                 int64_t ram;
1298                 long pages, page_size;
1299 #ifdef __FreeBSD__
1300                 size_t pages_len=sizeof(pages);
1301                 if ((page_size = getpagesize()) < 0 ||
1302                                 sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
1303 #else
1304                 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
1305 #endif
1306                 {
1307                         ram = 0;
1308                 } else {
1309                         ram = (int64_t) pages * (int64_t) page_size;
1310                 }
1311
1312                 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
1313                         return;
1314                 }
1315
1316                 if (limits.rlim_cur != RLIM_INFINITY) {
1317
1318                         if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
1319
1320                                 MessageDialog msg (
1321                                         string_compose (
1322                                                 _("WARNING: Your system has a limit for maximum amount of locked memory. "
1323                                                   "This might cause %1 to run out of memory before your system "
1324                                                   "runs out of memory. \n\n"
1325                                                   "You can view the memory limit with 'ulimit -l', "
1326                                                   "and it is normally controlled by %2"),
1327                                                 PROGRAM_NAME,
1328 #ifdef __FreeBSD__
1329                                                 X_("/etc/login.conf")
1330 #else
1331                                                 X_(" /etc/security/limits.conf")
1332 #endif
1333                                         ).c_str());
1334
1335                                 msg.set_default_response (RESPONSE_OK);
1336
1337                                 VBox* vbox = msg.get_vbox();
1338                                 HBox hbox;
1339                                 CheckButton cb (_("Do not show this window again"));
1340                                 hbox.pack_start (cb, true, false);
1341                                 vbox->pack_start (hbox);
1342                                 cb.show();
1343                                 vbox->show();
1344                                 hbox.show ();
1345
1346                                 pop_back_splash (msg);
1347
1348                                 msg.run ();
1349
1350                                 if (cb.get_active()) {
1351                                         XMLNode node (X_("no-memory-warning"));
1352                                         Config->add_instant_xml (node);
1353                                 }
1354                         }
1355                 }
1356         }
1357 #endif // !__APPLE__
1358 }
1359
1360
1361 void
1362 ARDOUR_UI::queue_finish ()
1363 {
1364         Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish));
1365 }
1366
1367 bool
1368 ARDOUR_UI::idle_finish ()
1369 {
1370         finish ();
1371         return false; /* do not call again */
1372 }
1373
1374 void
1375 ARDOUR_UI::finish()
1376 {
1377         if (_session) {
1378                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
1379
1380                 if (_session->dirty()) {
1381                         vector<string> actions;
1382                         actions.push_back (_("Don't quit"));
1383                         actions.push_back (_("Just quit"));
1384                         actions.push_back (_("Save and quit"));
1385                         switch (ask_about_saving_session(actions)) {
1386                         case -1:
1387                                 return;
1388                                 break;
1389                         case 1:
1390                                 /* use the default name */
1391                                 if (save_state_canfail ("")) {
1392                                         /* failed - don't quit */
1393                                         MessageDialog msg (_main_window,
1394                                                            string_compose (_("\
1395 %1 was unable to save your session.\n\n\
1396 If you still wish to quit, please use the\n\n\
1397 \"Just quit\" option."), PROGRAM_NAME));
1398                                         pop_back_splash(msg);
1399                                         msg.run ();
1400                                         return;
1401                                 }
1402                                 break;
1403                         case 0:
1404                                 break;
1405                         }
1406                 }
1407
1408                 second_connection.disconnect ();
1409                 point_one_second_connection.disconnect ();
1410                 point_zero_something_second_connection.disconnect();
1411                 fps_connection.disconnect();
1412         }
1413
1414         delete ARDOUR_UI::instance()->video_timeline;
1415         ARDOUR_UI::instance()->video_timeline = NULL;
1416         stop_video_server();
1417
1418         /* Save state before deleting the session, as that causes some
1419            windows to be destroyed before their visible state can be
1420            saved.
1421         */
1422         save_ardour_state ();
1423
1424         if (key_editor.get (false)) {
1425                 key_editor->disconnect ();
1426         }
1427
1428         close_all_dialogs ();
1429
1430         if (_session) {
1431                 _session->set_clean ();
1432                 _session->remove_pending_capture_state ();
1433                 delete _session;
1434                 _session = 0;
1435         }
1436
1437         halt_connection.disconnect ();
1438         AudioEngine::instance()->stop ();
1439 #ifdef WINDOWS_VST_SUPPORT
1440         fst_stop_threading();
1441 #endif
1442         quit ();
1443 }
1444
1445 int
1446 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
1447 {
1448         ArdourDialog window (_("Unsaved Session"));
1449         Gtk::HBox dhbox;  // the hbox for the image and text
1450         Gtk::Label  prompt_label;
1451         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
1452
1453         string msg;
1454
1455         assert (actions.size() >= 3);
1456
1457         window.add_button (actions[0], RESPONSE_REJECT);
1458         window.add_button (actions[1], RESPONSE_APPLY);
1459         window.add_button (actions[2], RESPONSE_ACCEPT);
1460
1461         window.set_default_response (RESPONSE_ACCEPT);
1462
1463         Gtk::Button noquit_button (msg);
1464         noquit_button.set_name ("EditorGTKButton");
1465
1466         string prompt;
1467
1468         if (_session->snap_name() == _session->name()) {
1469                 prompt = string_compose(_("The session \"%1\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
1470                                         _session->snap_name());
1471         } else {
1472                 prompt = string_compose(_("The snapshot \"%1\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
1473                                         _session->snap_name());
1474         }
1475
1476         prompt_label.set_text (prompt);
1477         prompt_label.set_name (X_("PrompterLabel"));
1478         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
1479
1480         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
1481         dhbox.set_homogeneous (false);
1482         dhbox.pack_start (*dimage, false, false, 5);
1483         dhbox.pack_start (prompt_label, true, false, 5);
1484         window.get_vbox()->pack_start (dhbox);
1485
1486         window.set_name (_("Prompter"));
1487         window.set_modal (true);
1488         window.set_resizable (false);
1489
1490         dhbox.show();
1491         prompt_label.show();
1492         dimage->show();
1493         window.show();
1494         window.present ();
1495
1496         ResponseType r = (ResponseType) window.run();
1497
1498         window.hide ();
1499
1500         switch (r) {
1501         case RESPONSE_ACCEPT: // save and get out of here
1502                 return 1;
1503         case RESPONSE_APPLY:  // get out of here
1504                 return 0;
1505         default:
1506                 break;
1507         }
1508
1509         return -1;
1510 }
1511
1512
1513 void
1514 ARDOUR_UI::every_second ()
1515 {
1516         update_cpu_load ();
1517         update_disk_space ();
1518         update_timecode_format ();
1519         update_peak_thread_work ();
1520
1521         if (nsm && nsm->is_active ()) {
1522                 nsm->check ();
1523
1524                 if (!_was_dirty && _session->dirty ()) {
1525                         nsm->is_dirty ();
1526                         _was_dirty = true;
1527                 }
1528                 else if (_was_dirty && !_session->dirty ()){
1529                         nsm->is_clean ();
1530                         _was_dirty = false;
1531                 }
1532         }
1533 }
1534
1535 void
1536 ARDOUR_UI::every_point_one_seconds ()
1537 {
1538         if (editor) editor->build_region_boundary_cache();
1539 }
1540
1541 void
1542 ARDOUR_UI::every_point_zero_something_seconds ()
1543 {
1544         // august 2007: actual update frequency: 25Hz (40ms), not 100Hz
1545
1546         if (editor_meter && UIConfiguration::instance().get_show_editor_meter() && editor_meter_peak_display.is_mapped ()) {
1547                 float mpeak = editor_meter->update_meters();
1548                 if (mpeak > editor_meter_max_peak) {
1549                         if (mpeak >= UIConfiguration::instance().get_meter_peak()) {
1550                                 editor_meter_peak_display.set_active_state ( Gtkmm2ext::ExplicitActive );
1551                         }
1552                 }
1553         }
1554 }
1555
1556 void
1557 ARDOUR_UI::set_fps_timeout_connection ()
1558 {
1559         unsigned int interval = 40;
1560         if (!_session) return;
1561         if (_session->timecode_frames_per_second() != 0) {
1562                 /* ideally we'll use a select() to sleep and not accumulate
1563                  * idle time to provide a regular periodic signal.
1564                  * See linux_vst_gui_support.cc 'elapsed_time_ms'.
1565                  * However, that'll require a dedicated thread and cross-thread
1566                  * signals to the GUI Thread..
1567                  */
1568                 interval = floor(500. /* update twice per FPS, since Glib::signal_timeout is very irregular */
1569                                 * _session->sample_rate() / _session->nominal_sample_rate()
1570                                 / _session->timecode_frames_per_second()
1571                                 );
1572 #ifdef PLATFORM_WINDOWS
1573                 // the smallest windows scheduler time-slice is ~15ms.
1574                 // periodic GUI timeouts shorter than that will cause
1575                 // WaitForSingleObject to spinlock (100% of one CPU Core)
1576                 // and gtk never enters idle mode.
1577                 // also changing timeBeginPeriod(1) does not affect that in
1578                 // any beneficial way, so we just limit the max rate for now.
1579                 interval = std::max(30u, interval); // at most ~33Hz.
1580 #else
1581                 interval = std::max(8u, interval); // at most 120Hz.
1582 #endif
1583         }
1584         fps_connection.disconnect();
1585         Timers::set_fps_interval (interval);
1586 }
1587
1588 void
1589 ARDOUR_UI::update_sample_rate (samplecnt_t)
1590 {
1591         char buf[64];
1592
1593         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
1594
1595         if (!AudioEngine::instance()->connected()) {
1596
1597                 snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1598
1599         } else {
1600
1601                 samplecnt_t rate = AudioEngine::instance()->sample_rate();
1602
1603                 if (rate == 0) {
1604                         /* no sample rate available */
1605                         snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1606                 } else {
1607
1608                         if (fmod (rate, 1000.0) != 0.0) {
1609                                 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
1610                                           (float) rate / 1000.0f,
1611                                           (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1612                         } else {
1613                                 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
1614                                           rate/1000,
1615                                           (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1616                         }
1617                 }
1618         }
1619         sample_rate_label.set_markup (buf);
1620 }
1621
1622 void
1623 ARDOUR_UI::update_format ()
1624 {
1625         if (!_session) {
1626                 format_label.set_text ("");
1627                 return;
1628         }
1629
1630         stringstream s;
1631         s << _("File:") << X_(" <span foreground=\"green\">");
1632
1633         switch (_session->config.get_native_file_header_format ()) {
1634         case BWF:
1635                 s << _("BWF");
1636                 break;
1637         case WAVE:
1638                 s << _("WAV");
1639                 break;
1640         case WAVE64:
1641                 s << _("WAV64");
1642                 break;
1643         case CAF:
1644                 s << _("CAF");
1645                 break;
1646         case AIFF:
1647                 s << _("AIFF");
1648                 break;
1649         case iXML:
1650                 s << _("iXML");
1651                 break;
1652         case RF64:
1653                 s << _("RF64");
1654                 break;
1655         case RF64_WAV:
1656                 s << _("RF64/WAV");
1657                 break;
1658         case MBWF:
1659                 s << _("MBWF");
1660                 break;
1661         }
1662
1663         s << " ";
1664
1665         switch (_session->config.get_native_file_data_format ()) {
1666         case FormatFloat:
1667                 s << _("32-float");
1668                 break;
1669         case FormatInt24:
1670                 s << _("24-int");
1671                 break;
1672         case FormatInt16:
1673                 s << _("16-int");
1674                 break;
1675         }
1676
1677         s << X_("</span>");
1678
1679         format_label.set_markup (s.str ());
1680 }
1681
1682 void
1683 ARDOUR_UI::update_cpu_load ()
1684 {
1685         const unsigned int x = _session ? _session->get_xrun_count () : 0;
1686         double const c = AudioEngine::instance()->get_dsp_load ();
1687
1688         const char* const bg = c > 90 ? " background=\"red\"" : "";
1689
1690         char buf[64];
1691         if (x > 9999) {
1692                 snprintf (buf, sizeof (buf), "DSP: <span%s>%.0f%%</span> (>10k)", bg, c);
1693         } else if (x > 0) {
1694                 snprintf (buf, sizeof (buf), "DSP: <span%s>%.0f%%</span> (%d)", bg, c, x);
1695         } else {
1696                 snprintf (buf, sizeof (buf), "DSP: <span%s>%.0f%%</span>", bg, c);
1697         }
1698
1699         dsp_load_label.set_markup (buf);
1700
1701         if (x > 9999) {
1702                 snprintf (buf, sizeof (buf), _("DSP: %.1f%% X: >10k\n%s"), c, _("Shift+Click to clear xruns."));
1703         } else if (x > 0) {
1704                 snprintf (buf, sizeof (buf), _("DSP: %.1f%% X: %u\n%s"), c, x, _("Shift+Click to clear xruns."));
1705         } else {
1706                 snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), c);
1707         }
1708
1709         ArdourWidgets::set_tooltip (dsp_load_label, buf);
1710 }
1711
1712 void
1713 ARDOUR_UI::update_peak_thread_work ()
1714 {
1715         char buf[64];
1716         const int c = SourceFactory::peak_work_queue_length ();
1717         if (c > 0) {
1718                 snprintf (buf, sizeof (buf), _("PkBld: <span foreground=\"%s\">%d</span>"), c >= 2 ? X_("red") : X_("green"), c);
1719                 peak_thread_work_label.set_markup (buf);
1720         } else {
1721                 peak_thread_work_label.set_markup (X_(""));
1722         }
1723 }
1724
1725 void
1726 ARDOUR_UI::count_recenabled_streams (Route& route)
1727 {
1728         Track* track = dynamic_cast<Track*>(&route);
1729         if (track && track->rec_enable_control()->get_value()) {
1730                 rec_enabled_streams += track->n_inputs().n_total();
1731         }
1732 }
1733
1734 void
1735 ARDOUR_UI::format_disk_space_label (float remain_sec)
1736 {
1737         if (remain_sec < 0) {
1738                 disk_space_label.set_text (_("N/A"));
1739                 ArdourWidgets::set_tooltip (disk_space_label, _("Unknown"));
1740                 return;
1741         }
1742
1743         char buf[64];
1744
1745         int sec = floor (remain_sec);
1746         int hrs  = sec / 3600;
1747         int mins = (sec / 60) % 60;
1748         int secs = sec % 60;
1749         snprintf (buf, sizeof(buf), _("%02dh:%02dm:%02ds"), hrs, mins, secs);
1750         ArdourWidgets::set_tooltip (disk_space_label, buf);
1751
1752         if (remain_sec > 86400) {
1753                 disk_space_label.set_text (_("Rec: >24h"));
1754                 return;
1755         } else if (remain_sec > 32400 /* 9 hours */) {
1756                 snprintf (buf, sizeof (buf), "Rec: %.0fh", remain_sec / 3600.f);
1757         } else if (remain_sec > 5940 /* 99 mins */) {
1758                 snprintf (buf, sizeof (buf), "Rec: %.1fh", remain_sec / 3600.f);
1759         } else {
1760                 snprintf (buf, sizeof (buf), "Rec: %.0fm", remain_sec / 60.f);
1761         }
1762         disk_space_label.set_text (buf);
1763
1764 }
1765
1766 void
1767 ARDOUR_UI::update_disk_space()
1768 {
1769         if (_session == 0) {
1770                 format_disk_space_label (-1);
1771                 return;
1772         }
1773
1774         boost::optional<samplecnt_t> opt_samples = _session->available_capture_duration();
1775         samplecnt_t fr = _session->sample_rate();
1776
1777         if (fr == 0) {
1778                 /* skip update - no SR available */
1779                 format_disk_space_label (-1);
1780                 return;
1781         }
1782
1783         if (!opt_samples) {
1784                 /* Available space is unknown */
1785                 format_disk_space_label (-1);
1786         } else if (opt_samples.get_value_or (0) == max_samplecnt) {
1787                 format_disk_space_label (max_samplecnt);
1788         } else {
1789                 rec_enabled_streams = 0;
1790                 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams, false);
1791
1792                 samplecnt_t samples = opt_samples.get_value_or (0);
1793
1794                 if (rec_enabled_streams) {
1795                         samples /= rec_enabled_streams;
1796                 }
1797
1798                 format_disk_space_label (samples / (float)fr);
1799         }
1800
1801 }
1802
1803 void
1804 ARDOUR_UI::update_timecode_format ()
1805 {
1806         char buf[64];
1807
1808         if (_session) {
1809                 bool matching;
1810                 boost::shared_ptr<TimecodeTransportMaster> tcmaster;
1811                 boost::shared_ptr<TransportMaster> tm = TransportMasterManager::instance().current();
1812
1813                 if ((tm->type() == LTC || tm->type() == MTC) && (tcmaster = boost::dynamic_pointer_cast<TimecodeTransportMaster>(tm)) != 0) {
1814                         matching = (tcmaster->apparent_timecode_format() == _session->config.get_timecode_format());
1815                 } else {
1816                         matching = true;
1817                 }
1818
1819                 snprintf (buf, sizeof (buf), S_("Timecode|TC: <span foreground=\"%s\">%s</span>"),
1820                           matching ? X_("green") : X_("red"),
1821                           Timecode::timecode_format_name (_session->config.get_timecode_format()).c_str());
1822         } else {
1823                 snprintf (buf, sizeof (buf), "TC: n/a");
1824         }
1825
1826         timecode_format_label.set_markup (buf);
1827 }
1828
1829 gint
1830 ARDOUR_UI::update_wall_clock ()
1831 {
1832         time_t now;
1833         struct tm *tm_now;
1834         static int last_min = -1;
1835
1836         time (&now);
1837         tm_now = localtime (&now);
1838         if (last_min != tm_now->tm_min) {
1839                 char buf[16];
1840                 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1841                 wall_clock_label.set_text (buf);
1842                 last_min = tm_now->tm_min;
1843         }
1844
1845         return TRUE;
1846 }
1847
1848 void
1849 ARDOUR_UI::open_recent_session ()
1850 {
1851         bool can_return = (_session != 0);
1852
1853         SessionDialog recent_session_dialog;
1854
1855         while (true) {
1856
1857                 ResponseType r = (ResponseType) recent_session_dialog.run ();
1858
1859                 switch (r) {
1860                 case RESPONSE_ACCEPT:
1861                         break;
1862                 default:
1863                         if (can_return) {
1864                                 recent_session_dialog.hide();
1865                                 return;
1866                         } else {
1867                                 exit (1);
1868                         }
1869                 }
1870
1871                 recent_session_dialog.hide();
1872
1873                 bool should_be_new;
1874
1875                 std::string path = recent_session_dialog.session_folder();
1876                 std::string state = recent_session_dialog.session_name (should_be_new);
1877
1878                 if (should_be_new == true) {
1879                         continue;
1880                 }
1881
1882                 _session_is_new = false;
1883
1884                 if (load_session (path, state) == 0) {
1885                         break;
1886                 }
1887
1888                 can_return = false;
1889         }
1890 }
1891
1892 bool
1893 ARDOUR_UI::check_audioengine (Gtk::Window& parent)
1894 {
1895         if (!AudioEngine::instance()->connected()) {
1896                 MessageDialog msg (parent, string_compose (
1897                                            _("%1 is not connected to any audio backend.\n"
1898                                            "You cannot open or close sessions in this condition"),
1899                                            PROGRAM_NAME));
1900                 pop_back_splash (msg);
1901                 msg.run ();
1902                 return false;
1903         }
1904         return true;
1905 }
1906
1907 void
1908 ARDOUR_UI::open_session ()
1909 {
1910         if (!check_audioengine (_main_window)) {
1911                 return;
1912         }
1913
1914         /* ardour sessions are folders */
1915         Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1916         open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1917         open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1918         open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
1919
1920         if (_session) {
1921                 string session_parent_dir = Glib::path_get_dirname(_session->path());
1922                 open_session_selector.set_current_folder(session_parent_dir);
1923         } else {
1924                 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
1925         }
1926
1927         Gtkmm2ext::add_volume_shortcuts (open_session_selector);
1928         try {
1929                 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
1930                 string default_session_folder = Config->get_default_session_parent_dir();
1931                 open_session_selector.add_shortcut_folder (default_session_folder);
1932         }
1933         catch (Glib::Error const& e) {
1934                 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
1935         }
1936
1937         FileFilter session_filter;
1938         session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
1939         session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1940         open_session_selector.add_filter (session_filter);
1941
1942         FileFilter archive_filter;
1943         archive_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::session_archive_suffix));
1944         archive_filter.set_name (_("Session Archives"));
1945
1946         open_session_selector.add_filter (archive_filter);
1947
1948         open_session_selector.set_filter (session_filter);
1949
1950         int response = open_session_selector.run();
1951         open_session_selector.hide ();
1952
1953         if (response == Gtk::RESPONSE_CANCEL) {
1954                 return;
1955         }
1956
1957         string session_path = open_session_selector.get_filename();
1958         string path, name;
1959         bool isnew;
1960
1961         if (session_path.length() > 0) {
1962                 int rv = ARDOUR::inflate_session (session_path,
1963                                 Config->get_default_session_parent_dir(), path, name);
1964                 if (rv == 0) {
1965                         _session_is_new = false;
1966                         load_session (path, name);
1967                 }
1968                 else if (rv < 0) {
1969                         MessageDialog msg (_main_window,
1970                                         string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
1971                         msg.run ();
1972                 }
1973                 else if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1974                         _session_is_new = isnew;
1975                         load_session (path, name);
1976                 }
1977         }
1978 }
1979
1980 void
1981 ARDOUR_UI::session_add_mixed_track (
1982                 const ChanCount& input,
1983                 const ChanCount& output,
1984                 RouteGroup* route_group,
1985                 uint32_t how_many,
1986                 const string& name_template,
1987                 bool strict_io,
1988                 PluginInfoPtr instrument,
1989                 Plugin::PresetRecord* pset,
1990                 ARDOUR::PresentationInfo::order_t order)
1991 {
1992         assert (_session);
1993
1994         if (Profile->get_mixbus ()) {
1995                 strict_io = true;
1996         }
1997
1998         try {
1999                 list<boost::shared_ptr<MidiTrack> > tracks;
2000                 tracks = _session->new_midi_track (input, output, strict_io, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
2001
2002                 if (tracks.size() != how_many) {
2003                         error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
2004                 }
2005         }
2006
2007         catch (...) {
2008                 display_insufficient_ports_message ();
2009                 return;
2010         }
2011 }
2012
2013 void
2014 ARDOUR_UI::session_add_midi_bus (
2015                 RouteGroup* route_group,
2016                 uint32_t how_many,
2017                 const string& name_template,
2018                 bool strict_io,
2019                 PluginInfoPtr instrument,
2020                 Plugin::PresetRecord* pset,
2021                 ARDOUR::PresentationInfo::order_t order)
2022 {
2023         if (_session == 0) {
2024                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
2025                 return;
2026         }
2027
2028         if (Profile->get_mixbus ()) {
2029                 strict_io = true;
2030         }
2031
2032         try {
2033                 RouteList routes;
2034                 routes = _session->new_midi_route (route_group, how_many, name_template, strict_io, instrument, pset, PresentationInfo::MidiBus, order);
2035                 if (routes.size() != how_many) {
2036                         error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
2037                 }
2038
2039         }
2040         catch (...) {
2041                 display_insufficient_ports_message ();
2042                 return;
2043         }
2044 }
2045
2046 void
2047 ARDOUR_UI::session_add_midi_route (
2048                 bool disk,
2049                 RouteGroup* route_group,
2050                 uint32_t how_many,
2051                 const string& name_template,
2052                 bool strict_io,
2053                 PluginInfoPtr instrument,
2054                 Plugin::PresetRecord* pset,
2055                 ARDOUR::PresentationInfo::order_t order)
2056 {
2057         ChanCount one_midi_channel;
2058         one_midi_channel.set (DataType::MIDI, 1);
2059
2060         if (disk) {
2061                 session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, instrument, pset, order);
2062         } else {
2063                 session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument, pset, order);
2064         }
2065 }
2066
2067 void
2068 ARDOUR_UI::session_add_audio_route (
2069         bool track,
2070         int32_t input_channels,
2071         int32_t output_channels,
2072         ARDOUR::TrackMode mode,
2073         RouteGroup* route_group,
2074         uint32_t how_many,
2075         string const & name_template,
2076         bool strict_io,
2077         ARDOUR::PresentationInfo::order_t order)
2078 {
2079         list<boost::shared_ptr<AudioTrack> > tracks;
2080         RouteList routes;
2081
2082         assert (_session);
2083
2084         try {
2085                 if (track) {
2086                         tracks = _session->new_audio_track (input_channels, output_channels, route_group, how_many, name_template, order, mode);
2087
2088                         if (tracks.size() != how_many) {
2089                                 error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
2090                                       << endmsg;
2091                         }
2092
2093                 } else {
2094
2095                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template, PresentationInfo::AudioBus, order);
2096
2097                         if (routes.size() != how_many) {
2098                                 error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
2099                                       << endmsg;
2100                         }
2101                 }
2102         }
2103
2104         catch (...) {
2105                 display_insufficient_ports_message ();
2106                 return;
2107         }
2108
2109         if (strict_io) {
2110                 for (list<boost::shared_ptr<AudioTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
2111                         (*i)->set_strict_io (true);
2112                 }
2113                 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2114                         (*i)->set_strict_io (true);
2115                 }
2116         }
2117 }
2118
2119 void
2120 ARDOUR_UI::display_insufficient_ports_message ()
2121 {
2122         MessageDialog msg (_main_window,
2123                         string_compose (_("There are insufficient ports available\n\
2124 to create a new track or bus.\n\
2125 You should save %1, exit and\n\
2126 restart with more ports."), PROGRAM_NAME));
2127         pop_back_splash (msg);
2128         msg.run ();
2129 }
2130
2131 void
2132 ARDOUR_UI::transport_goto_start ()
2133 {
2134         if (_session) {
2135                 _session->goto_start();
2136
2137                 /* force displayed area in editor to start no matter
2138                    what "follow playhead" setting is.
2139                 */
2140
2141                 if (editor) {
2142                         editor->center_screen (_session->current_start_sample ());
2143                 }
2144         }
2145 }
2146
2147 void
2148 ARDOUR_UI::transport_goto_zero ()
2149 {
2150         if (_session) {
2151                 _session->request_locate (0);
2152
2153                 /* force displayed area in editor to start no matter
2154                    what "follow playhead" setting is.
2155                 */
2156
2157                 if (editor) {
2158                         editor->reset_x_origin (0);
2159                 }
2160         }
2161 }
2162
2163 void
2164 ARDOUR_UI::transport_goto_wallclock ()
2165 {
2166         if (_session && editor) {
2167
2168                 time_t now;
2169                 struct tm tmnow;
2170                 samplepos_t samples;
2171
2172                 time (&now);
2173                 localtime_r (&now, &tmnow);
2174
2175                 samplecnt_t sample_rate = _session->sample_rate();
2176
2177                 if (sample_rate == 0) {
2178                         /* no frame rate available */
2179                         return;
2180                 }
2181
2182                 samples = tmnow.tm_hour * (60 * 60 * sample_rate);
2183                 samples += tmnow.tm_min * (60 * sample_rate);
2184                 samples += tmnow.tm_sec * sample_rate;
2185
2186                 _session->request_locate (samples, _session->transport_rolling ());
2187
2188                 /* force displayed area in editor to start no matter
2189                    what "follow playhead" setting is.
2190                 */
2191
2192                 if (editor) {
2193                         editor->center_screen (samples);
2194                 }
2195         }
2196 }
2197
2198 void
2199 ARDOUR_UI::transport_goto_end ()
2200 {
2201         if (_session) {
2202                 samplepos_t const sample = _session->current_end_sample();
2203                 _session->request_locate (sample);
2204
2205                 /* force displayed area in editor to start no matter
2206                    what "follow playhead" setting is.
2207                 */
2208
2209                 if (editor) {
2210                         editor->center_screen (sample);
2211                 }
2212         }
2213 }
2214
2215 void
2216 ARDOUR_UI::transport_stop ()
2217 {
2218         if (!_session) {
2219                 return;
2220         }
2221
2222         if (_session->is_auditioning()) {
2223                 _session->cancel_audition ();
2224                 return;
2225         }
2226
2227         _session->request_stop (false, true);
2228 }
2229
2230 /** Check if any tracks are record enabled. If none are, record enable all of them.
2231  * @return true if track record-enabled status was changed, false otherwise.
2232  */
2233 bool
2234 ARDOUR_UI::trx_record_enable_all_tracks ()
2235 {
2236         if (!_session) {
2237                 return false;
2238         }
2239
2240         boost::shared_ptr<RouteList> rl = _session->get_tracks ();
2241         bool none_record_enabled = true;
2242
2243         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
2244                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
2245                 assert (t);
2246
2247                 if (t->rec_enable_control()->get_value()) {
2248                         none_record_enabled = false;
2249                         break;
2250                 }
2251         }
2252
2253         if (none_record_enabled) {
2254                 _session->set_controls (route_list_to_control_list (rl, &Stripable::rec_enable_control), 1.0, Controllable::NoGroup);
2255         }
2256
2257         return none_record_enabled;
2258 }
2259
2260 void
2261 ARDOUR_UI::transport_record (bool roll)
2262 {
2263         if (_session) {
2264                 switch (_session->record_status()) {
2265                 case Session::Disabled:
2266                         if (_session->ntracks() == 0) {
2267                                 MessageDialog msg (_main_window, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu."));
2268                                 msg.run ();
2269                                 return;
2270                         }
2271                         if (Profile->get_trx()) {
2272                                 roll = trx_record_enable_all_tracks ();
2273                         }
2274                         _session->maybe_enable_record ();
2275                         if (roll) {
2276                                 transport_roll ();
2277                         }
2278                         break;
2279                 case Session::Recording:
2280                         if (roll) {
2281                                 _session->request_stop();
2282                         } else {
2283                                 _session->disable_record (false, true);
2284                         }
2285                         break;
2286
2287                 case Session::Enabled:
2288                         _session->disable_record (false, true);
2289                 }
2290         }
2291 }
2292
2293 void
2294 ARDOUR_UI::transport_roll ()
2295 {
2296         if (!_session) {
2297                 return;
2298         }
2299
2300         if (_session->is_auditioning()) {
2301                 return;
2302         }
2303
2304 #if 0
2305         if (_session->config.get_external_sync()) {
2306                 switch (Config->get_sync_source()) {
2307                 case Engine:
2308                         break;
2309                 default:
2310                         /* transport controlled by the master */
2311                         return;
2312                 }
2313         }
2314 #endif
2315
2316         bool rolling = _session->transport_rolling();
2317
2318         if (_session->get_play_loop()) {
2319
2320                 /* If loop playback is not a mode, then we should cancel
2321                    it when this action is requested. If it is a mode
2322                    we just leave it in place.
2323                 */
2324
2325                 if (!Config->get_loop_is_mode()) {
2326                         /* XXX it is not possible to just leave seamless loop and keep
2327                            playing at present (nov 4th 2009)
2328                         */
2329                         if (!Config->get_seamless_loop()) {
2330                                 /* stop loop playback and stop rolling */
2331                                 _session->request_play_loop (false, true);
2332                         } else if (rolling) {
2333                                 /* stop loop playback but keep rolling */
2334                                 _session->request_play_loop (false, false);
2335                         }
2336                 }
2337
2338         } else if (_session->get_play_range () ) {
2339                 /* stop playing a range if we currently are */
2340                 _session->request_play_range (0, true);
2341         }
2342
2343         if (!rolling) {
2344                 _session->request_transport_speed (1.0f);
2345         }
2346 }
2347
2348 bool
2349 ARDOUR_UI::get_smart_mode() const
2350 {
2351         return ( editor->get_smart_mode() );
2352 }
2353
2354
2355 void
2356 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
2357 {
2358         if (!_session) {
2359                 return;
2360         }
2361
2362         if (_session->is_auditioning()) {
2363                 _session->cancel_audition ();
2364                 return;
2365         }
2366
2367         if (_session->config.get_external_sync()) {
2368                 switch (Config->get_sync_source()) {
2369                 case Engine:
2370                         break;
2371                 default:
2372                         /* transport controlled by the master */
2373                         return;
2374                 }
2375         }
2376
2377         bool rolling = _session->transport_rolling();
2378         bool affect_transport = true;
2379
2380         if (rolling && roll_out_of_bounded_mode) {
2381                 /* drop out of loop/range playback but leave transport rolling */
2382                 if (_session->get_play_loop()) {
2383                         if (_session->actively_recording()) {
2384
2385                                 /* just stop using the loop, then actually stop
2386                                  * below
2387                                  */
2388                                 _session->request_play_loop (false, affect_transport);
2389
2390                         } else {
2391                                 if (Config->get_seamless_loop()) {
2392                                         /* the disk buffers contain copies of the loop - we can't
2393                                            just keep playing, so stop the transport. the user
2394                                            can restart as they wish.
2395                                         */
2396                                         affect_transport = true;
2397                                 } else {
2398                                         /* disk buffers are normal, so we can keep playing */
2399                                         affect_transport = false;
2400                                 }
2401                                 _session->request_play_loop (false, affect_transport);
2402                         }
2403                 } else if (_session->get_play_range ()) {
2404                         affect_transport = false;
2405                         _session->request_play_range (0, true);
2406                 }
2407         }
2408
2409         if (affect_transport) {
2410                 if (rolling) {
2411                         _session->request_stop (with_abort, true);
2412
2413                 } else if (!with_abort) { /* with_abort == true means the
2414                                            * command was intended to stop
2415                                            * transport, not start.
2416                                            */
2417
2418                         /* the only external sync condition we can be in here
2419                          * would be Engine (JACK) sync, in which case we still
2420                          * want to do this.
2421                          */
2422
2423                         if (UIConfiguration::instance().get_follow_edits() && ( editor->get_selection().time.front().start == _session->transport_sample() ) ) {  //if playhead is exactly at the start of a range, we can assume it was placed there by follow_edits
2424                                 _session->request_play_range (&editor->get_selection().time, true);
2425                                 _session->set_requested_return_sample( editor->get_selection().time.front().start );  //force an auto-return here
2426                         }
2427                         _session->request_transport_speed (1.0f);
2428                 }
2429         }
2430 }
2431
2432 void
2433 ARDOUR_UI::toggle_session_auto_loop ()
2434 {
2435         if (!_session) {
2436                 return;
2437         }
2438
2439         Location * looploc = _session->locations()->auto_loop_location();
2440
2441         if (!looploc) {
2442                 return;
2443         }
2444
2445         if (_session->get_play_loop()) {
2446
2447                 /* looping enabled, our job is to disable it */
2448
2449                 _session->request_play_loop (false);
2450
2451         } else {
2452
2453                 /* looping not enabled, our job is to enable it.
2454
2455                    loop-is-NOT-mode: this action always starts the transport rolling.
2456                    loop-IS-mode:     this action simply sets the loop play mechanism, but
2457                                         does not start transport.
2458                 */
2459                 if (Config->get_loop_is_mode()) {
2460                         _session->request_play_loop (true, false);
2461                 } else {
2462                         _session->request_play_loop (true, true);
2463                 }
2464         }
2465
2466         //show the loop markers
2467         looploc->set_hidden (false, this);
2468 }
2469
2470 void
2471 ARDOUR_UI::transport_play_selection ()
2472 {
2473         if (!_session) {
2474                 return;
2475         }
2476
2477         editor->play_selection ();
2478 }
2479
2480 void
2481 ARDOUR_UI::transport_play_preroll ()
2482 {
2483         if (!_session) {
2484                 return;
2485         }
2486         editor->play_with_preroll ();
2487 }
2488
2489 void
2490 ARDOUR_UI::transport_rec_preroll ()
2491 {
2492         if (!_session) {
2493                 return;
2494         }
2495         editor->rec_with_preroll ();
2496 }
2497
2498 void
2499 ARDOUR_UI::transport_rec_count_in ()
2500 {
2501         if (!_session) {
2502                 return;
2503         }
2504         editor->rec_with_count_in ();
2505 }
2506
2507 void
2508 ARDOUR_UI::transport_rewind (int option)
2509 {
2510         float current_transport_speed;
2511
2512         if (_session) {
2513                 current_transport_speed = _session->transport_speed();
2514
2515                 if (current_transport_speed >= 0.0f) {
2516                         switch (option) {
2517                         case 0:
2518                                 _session->request_transport_speed (-1.0f);
2519                                 break;
2520                         case 1:
2521                                 _session->request_transport_speed (-4.0f);
2522                                 break;
2523                         case -1:
2524                                 _session->request_transport_speed (-0.5f);
2525                                 break;
2526                         }
2527                 } else {
2528                         /* speed up */
2529                         _session->request_transport_speed (current_transport_speed * 1.5f);
2530                 }
2531         }
2532 }
2533
2534 void
2535 ARDOUR_UI::transport_forward (int option)
2536 {
2537         if (!_session) {
2538                 return;
2539         }
2540
2541         float current_transport_speed = _session->transport_speed();
2542
2543         if (current_transport_speed <= 0.0f) {
2544                 switch (option) {
2545                 case 0:
2546                         _session->request_transport_speed (1.0f);
2547                         break;
2548                 case 1:
2549                         _session->request_transport_speed (4.0f);
2550                         break;
2551                 case -1:
2552                         _session->request_transport_speed (0.5f);
2553                         break;
2554                 }
2555         } else {
2556                 /* speed up */
2557                 _session->request_transport_speed (current_transport_speed * 1.5f);
2558         }
2559 }
2560
2561 void
2562 ARDOUR_UI::toggle_record_enable (uint16_t rid)
2563 {
2564         if (!_session) {
2565                 return;
2566         }
2567
2568         boost::shared_ptr<Route> r;
2569
2570         if ((r = _session->get_remote_nth_route (rid)) != 0) {
2571
2572                 boost::shared_ptr<Track> t;
2573
2574                 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2575                         t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), Controllable::UseGroup);
2576                 }
2577         }
2578 }
2579
2580 void
2581 ARDOUR_UI::map_transport_state ()
2582 {
2583         if (!_session) {
2584                 layered_button.set_sensitive (false);
2585                 return;
2586         }
2587
2588         shuttle_box.map_transport_state ();
2589
2590         float sp = _session->transport_speed();
2591
2592         if (sp != 0.0f) {
2593                 layered_button.set_sensitive (!_session->actively_recording ());
2594         } else {
2595                 layered_button.set_sensitive (true);
2596                 update_disk_space ();
2597         }
2598 }
2599
2600 void
2601 ARDOUR_UI::blink_handler (bool blink_on)
2602 {
2603         sync_blink (blink_on);
2604
2605         if (!UIConfiguration::instance().get_blink_alert_indicators()) {
2606                 blink_on = true;
2607         }
2608         error_blink (blink_on);
2609         solo_blink (blink_on);
2610         audition_blink (blink_on);
2611         feedback_blink (blink_on);
2612 }
2613
2614 void
2615 ARDOUR_UI::update_clocks ()
2616 {
2617         if (!_session) return;
2618
2619         if (editor && !editor->dragging_playhead()) {
2620                 Clock (_session->audible_sample()); /* EMIT_SIGNAL */
2621         }
2622 }
2623
2624 void
2625 ARDOUR_UI::start_clocking ()
2626 {
2627         if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2628                 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2629         } else {
2630                 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2631         }
2632 }
2633
2634 void
2635 ARDOUR_UI::stop_clocking ()
2636 {
2637         clock_signal_connection.disconnect ();
2638 }
2639
2640 bool
2641 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2642 {
2643         char buf[256];
2644
2645         snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2646
2647         label->set_text (buf);
2648         bar->set_fraction (fraction);
2649
2650         /* process events, redraws, etc. */
2651
2652         while (gtk_events_pending()) {
2653                 gtk_main_iteration ();
2654         }
2655
2656         return true; /* continue with save-as */
2657 }
2658
2659 void
2660 ARDOUR_UI::save_session_as ()
2661 {
2662         if (!_session) {
2663                 return;
2664         }
2665
2666         if (_session->dirty()) {
2667                 vector<string> actions;
2668                 actions.push_back (_("Abort save-as"));
2669                 actions.push_back (_("Don't save now, just save-as"));
2670                 actions.push_back (_("Save it first"));
2671                 switch (ask_about_saving_session(actions)) {
2672                         case -1:
2673                                 return;
2674                                 break;
2675                         case 1:
2676                                 if (save_state_canfail ("")) {
2677                                         MessageDialog msg (_main_window,
2678                                                         string_compose (_("\
2679 %1 was unable to save your session.\n\n\
2680 If you still wish to proceed, please use the\n\n\
2681 \"Don't save now\" option."), PROGRAM_NAME));
2682                                         pop_back_splash(msg);
2683                                         msg.run ();
2684                                         return;
2685                                 }
2686                                 // no break
2687                         case 0:
2688                                 _session->remove_pending_capture_state ();
2689                                 break;
2690                 }
2691         }
2692
2693         if (!save_as_dialog) {
2694                 save_as_dialog = new SaveAsDialog;
2695         }
2696
2697         save_as_dialog->set_name (_session->name());
2698
2699         int response = save_as_dialog->run ();
2700
2701         save_as_dialog->hide ();
2702
2703         switch (response) {
2704         case Gtk::RESPONSE_OK:
2705                 break;
2706         default:
2707                 return;
2708         }
2709
2710
2711         Session::SaveAs sa;
2712
2713         sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2714         sa.new_name = save_as_dialog->new_name ();
2715         sa.switch_to = save_as_dialog->switch_to();
2716         sa.copy_media = save_as_dialog->copy_media();
2717         sa.copy_external = save_as_dialog->copy_external();
2718         sa.include_media = save_as_dialog->include_media ();
2719
2720         /* Only bother with a progress dialog if we're going to copy
2721            media into the save-as target. Without that choice, this
2722            will be very fast because we're only talking about a few kB's to
2723            perhaps a couple of MB's of data.
2724         */
2725
2726         ArdourDialog progress_dialog (_("Save As"), true);
2727         ScopedConnection c;
2728
2729         if (sa.include_media && sa.copy_media) {
2730
2731                 Gtk::Label* label = manage (new Gtk::Label());
2732                 Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ());
2733
2734                 progress_dialog.get_vbox()->pack_start (*label);
2735                 progress_dialog.get_vbox()->pack_start (*progress_bar);
2736                 label->show ();
2737                 progress_bar->show ();
2738
2739                 /* this signal will be emitted from within this, the calling thread,
2740                  * after every file is copied. It provides information on percentage
2741                  * complete (in terms of total data to copy), the number of files
2742                  * copied so far, and the total number to copy.
2743                  */
2744
2745                 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, label, progress_bar));
2746
2747                 progress_dialog.show_all ();
2748                 progress_dialog.present ();
2749         }
2750
2751         if (_session->save_as (sa)) {
2752                 /* ERROR MESSAGE */
2753                 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2754                 msg.run ();
2755         }
2756
2757         /* the logic here may seem odd: why isn't the condition sa.switch_to ?
2758          * the trick is this: if the new session was copy with media included,
2759          * then Session::save_as() will have already done a neat trick to avoid
2760          * us having to unload and load the new state. But if the media was not
2761          * included, then this is required (it avoids us having to otherwise
2762          * drop all references to media (sources).
2763          */
2764
2765         if (!sa.include_media && sa.switch_to) {
2766                 unload_session (false);
2767                 load_session (sa.final_session_folder_name, sa.new_name);
2768         }
2769 }
2770
2771 void
2772 ARDOUR_UI::archive_session ()
2773 {
2774         if (!_session) {
2775                 return;
2776         }
2777
2778         time_t n;
2779         time (&n);
2780         Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
2781
2782         SessionArchiveDialog sad;
2783         sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
2784         int response = sad.run ();
2785
2786         if (response != Gtk::RESPONSE_OK) {
2787                 sad.hide ();
2788                 return;
2789         }
2790
2791         if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.compression_level (), sad.only_used_sources (), &sad)) {
2792                 MessageDialog msg (_("Session Archiving failed."));
2793                 msg.run ();
2794         }
2795 }
2796
2797 void
2798 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2799 {
2800                 char timebuf[128];
2801                 time_t n;
2802                 struct tm local_time;
2803
2804                 time (&n);
2805                 localtime_r (&n, &local_time);
2806                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2807                 if (switch_to_it && _session->dirty ()) {
2808                         save_state_canfail ("");
2809                 }
2810
2811                 save_state (timebuf, switch_to_it);
2812 }
2813
2814
2815 bool
2816 ARDOUR_UI::process_snapshot_session_prompter (Prompter& prompter, bool switch_to_it)
2817 {
2818         string snapname;
2819
2820         prompter.get_result (snapname);
2821
2822         bool do_save = (snapname.length() != 0);
2823
2824         if (do_save) {
2825                 char illegal = Session::session_name_is_legal(snapname);
2826                 if (illegal) {
2827                         MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2828                                                              "snapshot names may not contain a '%1' character"), illegal));
2829                         msg.run ();
2830                         return false;
2831                 }
2832         }
2833
2834         vector<std::string> p;
2835         get_state_files_in_directory (_session->session_directory().root_path(), p);
2836         vector<string> n = get_file_names_no_extension (p);
2837
2838         if (find (n.begin(), n.end(), snapname) != n.end()) {
2839
2840                 do_save = overwrite_file_dialog (prompter,
2841                                                  _("Confirm Snapshot Overwrite"),
2842                                                  _("A snapshot already exists with that name. Do you want to overwrite it?"));
2843         }
2844
2845         if (do_save) {
2846                 save_state (snapname, switch_to_it);
2847         }
2848         else {
2849                 return false;
2850         }
2851
2852         return true;
2853 }
2854
2855
2856 /** Ask the user for the name of a new snapshot and then take it.
2857  */
2858
2859 void
2860 ARDOUR_UI::snapshot_session (bool switch_to_it)
2861 {
2862         if (switch_to_it && _session->dirty()) {
2863                 vector<string> actions;
2864                 actions.push_back (_("Abort saving snapshot"));
2865                 actions.push_back (_("Don't save now, just snapshot"));
2866                 actions.push_back (_("Save it first"));
2867                 switch (ask_about_saving_session(actions)) {
2868                         case -1:
2869                                 return;
2870                                 break;
2871                         case 1:
2872                                 if (save_state_canfail ("")) {
2873                                         MessageDialog msg (_main_window,
2874                                                         string_compose (_("\
2875 %1 was unable to save your session.\n\n\
2876 If you still wish to proceed, please use the\n\n\
2877 \"Don't save now\" option."), PROGRAM_NAME));
2878                                         pop_back_splash(msg);
2879                                         msg.run ();
2880                                         return;
2881                                 }
2882                                 // no break
2883                         case 0:
2884                                 _session->remove_pending_capture_state ();
2885                                 break;
2886                 }
2887         }
2888
2889         Prompter prompter (true);
2890         prompter.set_name ("Prompter");
2891         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2892         if (switch_to_it) {
2893                 prompter.set_title (_("Snapshot and switch"));
2894                 prompter.set_prompt (_("New session name"));
2895         } else {
2896                 prompter.set_title (_("Take Snapshot"));
2897                 prompter.set_prompt (_("Name of new snapshot"));
2898         }
2899
2900         if (switch_to_it) {
2901                 prompter.set_initial_text (_session->snap_name());
2902         } else {
2903                 Glib::DateTime tm (g_date_time_new_now_local ());
2904                 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
2905         }
2906
2907         bool finished = false;
2908         while (!finished) {
2909                 switch (prompter.run()) {
2910                 case RESPONSE_ACCEPT:
2911                 {
2912                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
2913                         break;
2914                 }
2915
2916                 default:
2917                         finished = true;
2918                         break;
2919                 }
2920         }
2921 }
2922
2923 /** Ask the user for a new session name and then rename the session to it.
2924  */
2925
2926 void
2927 ARDOUR_UI::rename_session ()
2928 {
2929         if (!_session) {
2930                 return;
2931         }
2932
2933         Prompter prompter (true);
2934         string name;
2935
2936         prompter.set_name ("Prompter");
2937         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2938         prompter.set_title (_("Rename Session"));
2939         prompter.set_prompt (_("New session name"));
2940
2941   again:
2942         switch (prompter.run()) {
2943         case RESPONSE_ACCEPT:
2944         {
2945                 prompter.get_result (name);
2946
2947                 bool do_rename = (name.length() != 0);
2948
2949                 if (do_rename) {
2950                         char illegal = Session::session_name_is_legal (name);
2951
2952                         if (illegal) {
2953                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2954                                                                      "session names may not contain a '%1' character"), illegal));
2955                                 msg.run ();
2956                                 goto again;
2957                         }
2958
2959                         switch (_session->rename (name)) {
2960                         case -1: {
2961                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2962                                 msg.set_position (WIN_POS_MOUSE);
2963                                 msg.run ();
2964                                 goto again;
2965                                 break;
2966                         }
2967                         case 0:
2968                                 break;
2969                         default: {
2970                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2971                                 msg.set_position (WIN_POS_MOUSE);
2972                                 msg.run ();
2973                                 break;
2974                         }
2975                         }
2976                 }
2977
2978                 break;
2979         }
2980
2981         default:
2982                 break;
2983         }
2984 }
2985
2986 void
2987 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2988 {
2989         if (!_session || _session->deletion_in_progress()) {
2990                 return;
2991         }
2992
2993         XMLNode* node = new XMLNode (X_("UI"));
2994
2995         WM::Manager::instance().add_state (*node);
2996
2997         node->add_child_nocopy (gui_object_state->get_state());
2998
2999         _session->add_extra_xml (*node);
3000
3001         if (export_video_dialog) {
3002                 _session->add_extra_xml (export_video_dialog->get_state());
3003         }
3004
3005         save_state_canfail (name, switch_to_it);
3006 }
3007
3008 int
3009 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
3010 {
3011         if (_session) {
3012                 int ret;
3013
3014                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
3015                         return ret;
3016                 }
3017         }
3018
3019         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
3020         return 0;
3021 }
3022
3023 void
3024 ARDOUR_UI::primary_clock_value_changed ()
3025 {
3026         if (_session) {
3027                 _session->request_locate (primary_clock->current_time ());
3028         }
3029 }
3030
3031 void
3032 ARDOUR_UI::big_clock_value_changed ()
3033 {
3034         if (_session) {
3035                 _session->request_locate (big_clock->current_time ());
3036         }
3037 }
3038
3039 void
3040 ARDOUR_UI::secondary_clock_value_changed ()
3041 {
3042         if (_session) {
3043                 _session->request_locate (secondary_clock->current_time ());
3044         }
3045 }
3046 void
3047 ARDOUR_UI::save_template_dialog_response (int response, SaveTemplateDialog* d)
3048 {
3049         if (response == RESPONSE_ACCEPT) {
3050                 const string name = d->get_template_name ();
3051                 const string desc = d->get_description ();
3052
3053                 int failed = _session->save_template (name, desc);
3054
3055                 if (failed == -2) { /* file already exists. */
3056                         bool overwrite = overwrite_file_dialog (*d,
3057                                                                 _("Confirm Template Overwrite"),
3058                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
3059
3060                         if (overwrite) {
3061                                 _session->save_template (name, desc, true);
3062                         }
3063                         else {
3064                                 d->show ();
3065                                 return;
3066                         }
3067                 }
3068         }
3069         delete d;
3070 }
3071
3072 void
3073 ARDOUR_UI::save_template ()
3074 {
3075         if (!check_audioengine (_main_window)) {
3076                 return;
3077         }
3078
3079         const std::string desc = SessionMetadata::Metadata()->description ();
3080         SaveTemplateDialog* d = new SaveTemplateDialog (_session->name (), desc);
3081         d->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::save_template_dialog_response), d));
3082         d->show ();
3083 }
3084
3085 void ARDOUR_UI::manage_templates ()
3086 {
3087         TemplateDialog td;
3088         td.run();
3089 }
3090
3091 void
3092 ARDOUR_UI::edit_metadata ()
3093 {
3094         SessionMetadataEditor dialog;
3095         dialog.set_session (_session);
3096         dialog.grab_focus ();
3097         dialog.run ();
3098 }
3099
3100 void
3101 ARDOUR_UI::import_metadata ()
3102 {
3103         SessionMetadataImporter dialog;
3104         dialog.set_session (_session);
3105         dialog.run ();
3106 }
3107
3108 bool
3109 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
3110 {
3111         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
3112
3113         MessageDialog msg (str,
3114                            false,
3115                            Gtk::MESSAGE_WARNING,
3116                            Gtk::BUTTONS_YES_NO,
3117                            true);
3118
3119
3120         msg.set_name (X_("OpenExistingDialog"));
3121         msg.set_title (_("Open Existing Session"));
3122         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
3123         msg.set_position (Gtk::WIN_POS_CENTER);
3124         pop_back_splash (msg);
3125
3126         switch (msg.run()) {
3127         case RESPONSE_YES:
3128                 return true;
3129                 break;
3130         }
3131         return false;
3132 }
3133
3134 int
3135 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
3136 {
3137         BusProfile bus_profile;
3138
3139         if (nsm) {
3140                 bus_profile.master_out_channels = 2;
3141         } else {
3142                 /* get settings from advanced section of NSD */
3143                 bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
3144         }
3145
3146         // NULL profile: no master, no monitor
3147         if (build_session (session_path, session_name, bus_profile.master_out_channels > 0 ? &bus_profile : NULL)) {
3148                 return -1;
3149         }
3150
3151         return 0;
3152 }
3153
3154 void
3155 ARDOUR_UI::load_from_application_api (const std::string& path)
3156 {
3157         /* OS X El Capitan (and probably later) now somehow passes the command
3158            line arguments to an app via the openFile delegate protocol. Ardour
3159            already does its own command line processing, and having both
3160            pathways active causes crashes. So, if the command line was already
3161            set, do nothing here.
3162         */
3163
3164         if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3165                 return;
3166         }
3167
3168         ARDOUR_COMMAND_LINE::session_name = path;
3169
3170         /* Cancel SessionDialog if it's visible to make OSX delegates work.
3171          *
3172          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
3173          * race-condition:
3174          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
3175          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
3176          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
3177          *    -> SessionDialog is not displayed
3178          */
3179
3180         if (_session_dialog) {
3181                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3182                 std::string session_path = path;
3183                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
3184                         session_path = Glib::path_get_dirname (session_path);
3185                 }
3186                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
3187                 _session_dialog->set_provided_session (session_name, session_path);
3188                 _session_dialog->response (RESPONSE_NONE);
3189                 _session_dialog->hide();
3190                 return;
3191         }
3192
3193         int rv;
3194         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
3195                 /* /path/to/foo => /path/to/foo, foo */
3196                 rv = load_session (path, basename_nosuffix (path));
3197         } else {
3198                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
3199                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
3200         }
3201
3202         // if load_session fails -> pop up SessionDialog.
3203         if (rv) {
3204                 ARDOUR_COMMAND_LINE::session_name = "";
3205
3206                 if (get_session_parameters (true, false)) {
3207                         exit (1);
3208                 }
3209         }
3210 }
3211
3212 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
3213 int
3214 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
3215 {
3216         string session_name;
3217         string session_path;
3218         string template_name;
3219         int ret = -1;
3220         bool likely_new = false;
3221         bool cancel_not_quit;
3222
3223         /* deal with any existing DIRTY session now, rather than later. don't
3224          * treat a non-dirty session this way, so that it stays visible
3225          * as we bring up the new session dialog.
3226          */
3227
3228         if (_session && ARDOUR_UI::instance()->video_timeline) {
3229                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
3230         }
3231
3232         /* if there is already a session, relabel the button
3233            on the SessionDialog so that we don't Quit directly
3234         */
3235         cancel_not_quit = (_session != 0) && !quit_on_cancel;
3236
3237         if (_session && _session->dirty()) {
3238                 if (unload_session (false)) {
3239                         /* unload cancelled by user */
3240                         return 0;
3241                 }
3242                 ARDOUR_COMMAND_LINE::session_name = "";
3243         }
3244
3245         if (!load_template.empty()) {
3246                 should_be_new = true;
3247                 template_name = load_template;
3248         }
3249
3250         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3251         session_path = ARDOUR_COMMAND_LINE::session_name;
3252
3253         if (!session_path.empty()) {
3254                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3255                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3256                                 /* session/snapshot file, change path to be dir */
3257                                 session_path = Glib::path_get_dirname (session_path);
3258                         }
3259                 }
3260         }
3261
3262         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3263
3264         _session_dialog = &session_dialog;
3265         while (ret != 0) {
3266
3267                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3268
3269                         /* if they named a specific statefile, use it, otherwise they are
3270                            just giving a session folder, and we want to use it as is
3271                            to find the session.
3272                         */
3273
3274                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3275
3276                         if (suffix != string::npos) {
3277                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3278                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3279                                 session_name = Glib::path_get_basename (session_name);
3280                         } else {
3281                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3282                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3283                         }
3284                 } else {
3285                         session_path = "";
3286                         session_name = "";
3287                         session_dialog.clear_given ();
3288                 }
3289
3290                 if (should_be_new || session_name.empty()) {
3291                         /* need the dialog to get info from user */
3292
3293                         cerr << "run dialog\n";
3294
3295                         switch (session_dialog.run()) {
3296                         case RESPONSE_ACCEPT:
3297                                 break;
3298                         case RESPONSE_NONE:
3299                                 /* this is used for async * app->ShouldLoad(). */
3300                                 continue; // while loop
3301                                 break;
3302                         default:
3303                                 if (quit_on_cancel) {
3304                                         ARDOUR_UI::finish ();
3305                                         Gtkmm2ext::Application::instance()->cleanup();
3306                                         ARDOUR::cleanup ();
3307                                         pthread_cancel_all ();
3308                                         return -1; // caller is responsible to call exit()
3309                                 } else {
3310                                         return ret;
3311                                 }
3312                         }
3313
3314                         session_dialog.hide ();
3315                 }
3316
3317                 /* if we run the startup dialog again, offer more than just "new session" */
3318
3319                 should_be_new = false;
3320
3321                 session_name = session_dialog.session_name (likely_new);
3322                 session_path = session_dialog.session_folder ();
3323
3324                 if (nsm) {
3325                         likely_new = true;
3326                 }
3327
3328                 if (!likely_new) {
3329                         int rv = ARDOUR::inflate_session (session_name,
3330                                         Config->get_default_session_parent_dir(), session_path, session_name);
3331                         if (rv < 0) {
3332                                 MessageDialog msg (session_dialog,
3333                                         string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
3334                                 msg.run ();
3335                                 continue;
3336                         }
3337                         else if (rv == 0) {
3338                                 session_dialog.set_provided_session (session_name, session_path);
3339                         }
3340                 }
3341
3342                 // XXX check archive, inflate
3343                 string::size_type suffix = session_name.find (statefile_suffix);
3344
3345                 if (suffix != string::npos) {
3346                         session_name = session_name.substr (0, suffix);
3347                 }
3348
3349                 /* this shouldn't happen, but we catch it just in case it does */
3350
3351                 if (session_name.empty()) {
3352                         continue;
3353                 }
3354
3355                 if (session_dialog.use_session_template()) {
3356                         template_name = session_dialog.session_template_name();
3357                         _session_is_new = true;
3358                 }
3359
3360                 if (session_name[0] == G_DIR_SEPARATOR ||
3361 #ifdef PLATFORM_WINDOWS
3362                    (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3363 #else
3364                    (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3365                    (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3366 #endif
3367                 )
3368                 {
3369
3370                         /* absolute path or cwd-relative path specified for session name: infer session folder
3371                            from what was given.
3372                         */
3373
3374                         session_path = Glib::path_get_dirname (session_name);
3375                         session_name = Glib::path_get_basename (session_name);
3376
3377                 } else {
3378
3379                         session_path = session_dialog.session_folder();
3380
3381                         char illegal = Session::session_name_is_legal (session_name);
3382
3383                         if (illegal) {
3384                                 MessageDialog msg (session_dialog,
3385                                                    string_compose (_("To ensure compatibility with various systems\n"
3386                                                                      "session names may not contain a '%1' character"),
3387                                                                    illegal));
3388                                 msg.run ();
3389                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3390                                 continue;
3391                         }
3392                 }
3393
3394                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3395
3396
3397                         if (likely_new && !nsm) {
3398
3399                                 std::string existing = Glib::build_filename (session_path, session_name);
3400
3401                                 if (!ask_about_loading_existing_session (existing)) {
3402                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3403                                         continue;
3404                                 }
3405                         }
3406
3407                         _session_is_new = false;
3408
3409                 } else {
3410
3411                         if (!likely_new) {
3412                                 pop_back_splash (session_dialog);
3413                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3414                                 msg.run ();
3415                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3416                                 continue;
3417                         }
3418
3419                         char illegal = Session::session_name_is_legal(session_name);
3420
3421                         if (illegal) {
3422                                 pop_back_splash (session_dialog);
3423                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3424                                                                                     "session names may not contain a '%1' character"), illegal));
3425                                 msg.run ();
3426                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3427                                 continue;
3428                         }
3429
3430                         _session_is_new = true;
3431                 }
3432
3433                 if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
3434
3435                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3436                         meta_session_setup (template_name.substr (11));
3437
3438                 } else if (likely_new && template_name.empty()) {
3439
3440                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3441
3442                 } else {
3443
3444                         ret = load_session (session_path, session_name, template_name);
3445
3446                         if (ret == -2) {
3447                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3448                                 exit (1);
3449                         }
3450
3451                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3452                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3453                                 exit (1);
3454                         }
3455
3456                         /* clear this to avoid endless attempts to load the
3457                            same session.
3458                         */
3459
3460                         ARDOUR_COMMAND_LINE::session_name = "";
3461                 }
3462         }
3463
3464         _session_dialog = NULL;
3465
3466         return ret;
3467 }
3468
3469 void
3470 ARDOUR_UI::close_session()
3471 {
3472         if (!check_audioengine (_main_window)) {
3473                 return;
3474         }
3475
3476         if (unload_session (true)) {
3477                 return;
3478         }
3479
3480         ARDOUR_COMMAND_LINE::session_name = "";
3481
3482         if (get_session_parameters (true, false)) {
3483                 exit (1);
3484         }
3485 }
3486
3487 /** @param snap_name Snapshot name (without .ardour suffix).
3488  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3489  */
3490 int
3491 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3492 {
3493         /* load_session calls flush_pending() which allows
3494          * GUI interaction and potentially loading another session
3495          * (that was easy via snapshot sidebar).
3496          * Recursing into load_session() from load_session() and recusive
3497          * event loops causes all kind of crashes.
3498          */
3499         assert (!session_load_in_progress);
3500         if (session_load_in_progress) {
3501                 return -1;
3502         }
3503         PBD::Unwinder<bool> lsu (session_load_in_progress, true);
3504
3505         Session *new_session;
3506         int unload_status;
3507         int retval = -1;
3508
3509         if (_session) {
3510                 unload_status = unload_session ();
3511
3512                 if (unload_status < 0) {
3513                         goto out;
3514                 } else if (unload_status > 0) {
3515                         retval = 0;
3516                         goto out;
3517                 }
3518         }
3519
3520         session_loaded = false;
3521
3522         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3523
3524         try {
3525                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3526         }
3527
3528         /* this one is special */
3529
3530         catch (AudioEngine::PortRegistrationFailure const& err) {
3531
3532                 MessageDialog msg (err.what(),
3533                                    true,
3534                                    Gtk::MESSAGE_INFO,
3535                                    Gtk::BUTTONS_CLOSE);
3536
3537                 msg.set_title (_("Port Registration Error"));
3538                 msg.set_secondary_text (_("Click the Close button to try again."));
3539                 msg.set_position (Gtk::WIN_POS_CENTER);
3540                 pop_back_splash (msg);
3541                 msg.present ();
3542
3543                 int response = msg.run ();
3544
3545                 msg.hide ();
3546
3547                 switch (response) {
3548                 case RESPONSE_CANCEL:
3549                         exit (1);
3550                 default:
3551                         break;
3552                 }
3553                 goto out;
3554         }
3555         catch (SessionException const& e) {
3556                 MessageDialog msg (string_compose(
3557                                            _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
3558                                            path, snap_name, e.what()),
3559                                    true,
3560                                    Gtk::MESSAGE_INFO,
3561                                    BUTTONS_OK);
3562
3563                 msg.set_title (_("Loading Error"));
3564                 msg.set_position (Gtk::WIN_POS_CENTER);
3565                 pop_back_splash (msg);
3566                 msg.present ();
3567
3568                 dump_errors (cerr);
3569
3570                 (void) msg.run ();
3571                 msg.hide ();
3572
3573                 goto out;
3574         }
3575         catch (...) {
3576
3577                 MessageDialog msg (string_compose(
3578                                            _("Session \"%1 (snapshot %2)\" did not load successfully."),
3579                                            path, snap_name),
3580                                    true,
3581                                    Gtk::MESSAGE_INFO,
3582                                    BUTTONS_OK);
3583
3584                 msg.set_title (_("Loading Error"));
3585                 msg.set_position (Gtk::WIN_POS_CENTER);
3586                 pop_back_splash (msg);
3587                 msg.present ();
3588
3589                 dump_errors (cerr);
3590
3591                 (void) msg.run ();
3592                 msg.hide ();
3593
3594                 goto out;
3595         }
3596
3597         {
3598                 list<string> const u = new_session->unknown_processors ();
3599                 if (!u.empty()) {
3600                         MissingPluginDialog d (_session, u);
3601                         d.run ();
3602                 }
3603         }
3604
3605         if (!new_session->writable()) {
3606                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3607                                    true,
3608                                    Gtk::MESSAGE_INFO,
3609                                    BUTTONS_OK);
3610
3611                 msg.set_title (_("Read-only Session"));
3612                 msg.set_position (Gtk::WIN_POS_CENTER);
3613                 pop_back_splash (msg);
3614                 msg.present ();
3615                 (void) msg.run ();
3616                 msg.hide ();
3617         }
3618
3619
3620         /* Now the session been created, add the transport controls */
3621         new_session->add_controllable(roll_controllable);
3622         new_session->add_controllable(stop_controllable);
3623         new_session->add_controllable(goto_start_controllable);
3624         new_session->add_controllable(goto_end_controllable);
3625         new_session->add_controllable(auto_loop_controllable);
3626         new_session->add_controllable(play_selection_controllable);
3627         new_session->add_controllable(rec_controllable);
3628
3629         set_session (new_session);
3630
3631         session_loaded = true;
3632
3633         if (_session) {
3634                 _session->set_clean ();
3635         }
3636
3637 #ifdef WINDOWS_VST_SUPPORT
3638         fst_stop_threading();
3639 #endif
3640
3641         {
3642                 Timers::TimerSuspender t;
3643                 flush_pending (10);
3644         }
3645
3646 #ifdef WINDOWS_VST_SUPPORT
3647         fst_start_threading();
3648 #endif
3649         retval = 0;
3650
3651         if (!mix_template.empty ()) {
3652                 /* if mix_template is given, assume this is a new session */
3653                 string metascript = Glib::build_filename (mix_template, "template.lua");
3654                 meta_session_setup (metascript);
3655         }
3656
3657
3658   out:
3659         /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
3660          * which is queued by set_session().
3661          * If session-loading fails we hide it explicitly.
3662          * This covers both cases in a central place.
3663          */
3664         if (retval) {
3665                 hide_splash ();
3666         }
3667         return retval;
3668 }
3669
3670 int
3671 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile* bus_profile)
3672 {
3673         Session *new_session;
3674         int x;
3675
3676         session_loaded = false;
3677         x = unload_session ();
3678
3679         if (x < 0) {
3680                 return -1;
3681         } else if (x > 0) {
3682                 return 0;
3683         }
3684
3685         _session_is_new = true;
3686
3687         try {
3688                 new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile);
3689         }
3690
3691         catch (SessionException const& e) {
3692                 cerr << "Here are the errors associated with this failed session:\n";
3693                 dump_errors (cerr);
3694                 cerr << "---------\n";
3695                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3696                 msg.set_title (_("Loading Error"));
3697                 msg.set_position (Gtk::WIN_POS_CENTER);
3698                 pop_back_splash (msg);
3699                 msg.run ();
3700                 return -1;
3701         }
3702         catch (...) {
3703                 cerr << "Here are the errors associated with this failed session:\n";
3704                 dump_errors (cerr);
3705                 cerr << "---------\n";
3706                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3707                 msg.set_title (_("Loading Error"));
3708                 msg.set_position (Gtk::WIN_POS_CENTER);
3709                 pop_back_splash (msg);
3710                 msg.run ();
3711                 return -1;
3712         }
3713
3714         /* Give the new session the default GUI state, if such things exist */
3715
3716         XMLNode* n;
3717         n = Config->instant_xml (X_("Editor"));
3718         if (n) {
3719                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3720                 new_session->add_instant_xml (*n, false);
3721         }
3722         n = Config->instant_xml (X_("Mixer"));
3723         if (n) {
3724                 new_session->add_instant_xml (*n, false);
3725         }
3726
3727         n = Config->instant_xml (X_("Preferences"));
3728         if (n) {
3729                 new_session->add_instant_xml (*n, false);
3730         }
3731
3732         /* Put the playhead at 0 and scroll fully left */
3733         n = new_session->instant_xml (X_("Editor"));
3734         if (n) {
3735                 n->set_property (X_("playhead"), X_("0"));
3736                 n->set_property (X_("left-frame"), X_("0"));
3737         }
3738
3739         set_session (new_session);
3740
3741         session_loaded = true;
3742
3743         new_session->save_state(new_session->name());
3744
3745         return 0;
3746 }
3747
3748
3749 static void _lua_print (std::string s) {
3750 #ifndef NDEBUG
3751         std::cout << "LuaInstance: " << s << "\n";
3752 #endif
3753         PBD::info << "LuaInstance: " << s << endmsg;
3754 }
3755
3756 std::map<std::string, std::string>
3757 ARDOUR_UI::route_setup_info (const std::string& script_path)
3758 {
3759         std::map<std::string, std::string> rv;
3760
3761         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3762                 return rv;
3763         }
3764
3765         LuaState lua;
3766         lua.Print.connect (&_lua_print);
3767         lua.sandbox (true);
3768
3769         lua_State* L = lua.getState();
3770         LuaInstance::register_classes (L);
3771         LuaBindings::set_session (L, _session);
3772         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3773         lua_setglobal (L, "Editor");
3774
3775         lua.do_command ("function ardour () end");
3776         lua.do_file (script_path);
3777
3778         try {
3779                 luabridge::LuaRef fn = luabridge::getGlobal (L, "route_setup");
3780                 if (!fn.isFunction ()) {
3781                         return rv;
3782                 }
3783                 luabridge::LuaRef rs = fn ();
3784                 if (!rs.isTable ()) {
3785                         return rv;
3786                 }
3787                 for (luabridge::Iterator i(rs); !i.isNil (); ++i) {
3788                         if (!i.key().isString()) {
3789                                 continue;
3790                         }
3791                         std::string key = i.key().tostring();
3792                         if (i.value().isString() || i.value().isNumber() || i.value().isBoolean()) {
3793                                 rv[key] = i.value().tostring();
3794                         }
3795                 }
3796         } catch (luabridge::LuaException const& e) {
3797                 cerr << "LuaException:" << e.what () << endl;
3798         } catch (...) { }
3799         return rv;
3800 }
3801
3802 void
3803 ARDOUR_UI::meta_route_setup (const std::string& script_path)
3804 {
3805         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3806                 return;
3807         }
3808         assert (add_route_dialog);
3809
3810         int count;
3811         if ((count = add_route_dialog->count()) <= 0) {
3812                 return;
3813         }
3814
3815         LuaState lua;
3816         lua.Print.connect (&_lua_print);
3817         lua.sandbox (true);
3818
3819         lua_State* L = lua.getState();
3820         LuaInstance::register_classes (L);
3821         LuaBindings::set_session (L, _session);
3822         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3823         lua_setglobal (L, "Editor");
3824
3825         lua.do_command ("function ardour () end");
3826         lua.do_file (script_path);
3827
3828         luabridge::LuaRef args (luabridge::newTable (L));
3829
3830         args["name"]       = add_route_dialog->name_template ();
3831         args["insert_at"]  = translate_order (add_route_dialog->insert_at());
3832         args["group"]      = add_route_dialog->route_group ();
3833         args["strict_io"]  = add_route_dialog->use_strict_io ();
3834         args["instrument"] = add_route_dialog->requested_instrument ();
3835         args["track_mode"] = add_route_dialog->mode ();
3836         args["channels"]   = add_route_dialog->channel_count ();
3837         args["how_many"]   = count;
3838
3839         try {
3840                 luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
3841                 if (fn.isFunction()) {
3842                         fn (args)();
3843                 }
3844         } catch (luabridge::LuaException const& e) {
3845                 cerr << "LuaException:" << e.what () << endl;
3846         } catch (...) {
3847                 display_insufficient_ports_message ();
3848         }
3849 }
3850
3851 void
3852 ARDOUR_UI::meta_session_setup (const std::string& script_path)
3853 {
3854         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3855                 return;
3856         }
3857
3858         LuaState lua;
3859         lua.Print.connect (&_lua_print);
3860         lua.sandbox (true);
3861
3862         lua_State* L = lua.getState();
3863         LuaInstance::register_classes (L);
3864         LuaBindings::set_session (L, _session);
3865         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3866         lua_setglobal (L, "Editor");
3867
3868         lua.do_command ("function ardour () end");
3869         lua.do_file (script_path);
3870
3871         try {
3872                 luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
3873                 if (fn.isFunction()) {
3874                         fn ()();
3875                 }
3876         } catch (luabridge::LuaException const& e) {
3877                 cerr << "LuaException:" << e.what () << endl;
3878         } catch (...) {
3879                 display_insufficient_ports_message ();
3880         }
3881 }
3882
3883 void
3884 ARDOUR_UI::launch_chat ()
3885 {
3886         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3887
3888         dialog.set_title (_("About the Chat"));
3889         dialog.set_secondary_text (_("When you're inside the chat just ask your question and wait for an answer. The chat is occupied by real people with real lives so many of them are passively online and might not read your question before minutes or hours later.\nSo please be patient and wait for an answer.\n\nYou should just leave the chat window open and check back regularly until someone has answered your question."));
3890
3891         switch (dialog.run()) {
3892         case RESPONSE_OK:
3893                 open_uri("http://webchat.freenode.net/?channels=ardour");
3894                 break;
3895         default:
3896                 break;
3897         }
3898 }
3899
3900 void
3901 ARDOUR_UI::launch_manual ()
3902 {
3903         PBD::open_uri (Config->get_tutorial_manual_url());
3904 }
3905
3906 void
3907 ARDOUR_UI::launch_reference ()
3908 {
3909         PBD::open_uri (Config->get_reference_manual_url());
3910 }
3911
3912 void
3913 ARDOUR_UI::launch_tracker ()
3914 {
3915         PBD::open_uri ("http://tracker.ardour.org");
3916 }
3917
3918 void
3919 ARDOUR_UI::launch_subscribe ()
3920 {
3921         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3922 }
3923
3924 void
3925 ARDOUR_UI::launch_cheat_sheet ()
3926 {
3927 #ifdef __APPLE__
3928         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3929 #else
3930         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3931 #endif
3932 }
3933
3934 void
3935 ARDOUR_UI::launch_website ()
3936 {
3937         PBD::open_uri ("http://ardour.org");
3938 }
3939
3940 void
3941 ARDOUR_UI::launch_website_dev ()
3942 {
3943         PBD::open_uri ("http://ardour.org/development.html");
3944 }
3945
3946 void
3947 ARDOUR_UI::launch_forums ()
3948 {
3949         PBD::open_uri ("https://community.ardour.org/forums");
3950 }
3951
3952 void
3953 ARDOUR_UI::launch_howto_report ()
3954 {
3955         PBD::open_uri ("http://ardour.org/reporting_bugs");
3956 }
3957
3958 void
3959 ARDOUR_UI::loading_message (const std::string& msg)
3960 {
3961         if (ARDOUR_COMMAND_LINE::no_splash) {
3962                 return;
3963         }
3964
3965         if (!splash) {
3966                 show_splash ();
3967         }
3968
3969         splash->message (msg);
3970 }
3971
3972 void
3973 ARDOUR_UI::show_splash ()
3974 {
3975         if (splash == 0) {
3976                 try {
3977                         splash = new Splash;
3978                 } catch (...) {
3979                         return;
3980                 }
3981         }
3982
3983         splash->display ();
3984 }
3985
3986 void
3987 ARDOUR_UI::hide_splash ()
3988 {
3989         delete splash;
3990         splash = 0;
3991 }
3992
3993 void
3994 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3995 {
3996         size_t removed;
3997
3998         removed = rep.paths.size();
3999
4000         if (removed == 0) {
4001                 MessageDialog msgd (_main_window,
4002                                     _("No files were ready for clean-up"),
4003                                     true,
4004                                     Gtk::MESSAGE_INFO,
4005                                     Gtk::BUTTONS_OK);
4006                 msgd.set_title (_("Clean-up"));
4007                 msgd.set_secondary_text (_("If this seems surprising, \n\
4008 check for any existing snapshots.\n\
4009 These may still include regions that\n\
4010 require some unused files to continue to exist."));
4011
4012                 msgd.run ();
4013                 return;
4014         }
4015
4016         ArdourDialog results (_("Clean-up"), true, false);
4017
4018         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
4019                 CleanupResultsModelColumns() {
4020                         add (visible_name);
4021                         add (fullpath);
4022                 }
4023                 Gtk::TreeModelColumn<std::string> visible_name;
4024                 Gtk::TreeModelColumn<std::string> fullpath;
4025         };
4026
4027
4028         CleanupResultsModelColumns results_columns;
4029         Glib::RefPtr<Gtk::ListStore> results_model;
4030         Gtk::TreeView results_display;
4031
4032         results_model = ListStore::create (results_columns);
4033         results_display.set_model (results_model);
4034         results_display.append_column (list_title, results_columns.visible_name);
4035
4036         results_display.set_name ("CleanupResultsList");
4037         results_display.set_headers_visible (true);
4038         results_display.set_headers_clickable (false);
4039         results_display.set_reorderable (false);
4040
4041         Gtk::ScrolledWindow list_scroller;
4042         Gtk::Label txt;
4043         Gtk::VBox dvbox;
4044         Gtk::HBox dhbox;  // the hbox for the image and text
4045         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
4046         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
4047
4048         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
4049
4050         const string dead_directory = _session->session_directory().dead_path();
4051
4052         /* subst:
4053            %1 - number of files removed
4054            %2 - location of "dead"
4055            %3 - size of files affected
4056            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
4057         */
4058
4059         const char* bprefix;
4060         double space_adjusted = 0;
4061
4062         if (rep.space < 1000) {
4063                 bprefix = X_("");
4064                 space_adjusted = rep.space;
4065         } else if (rep.space < 1000000) {
4066                 bprefix = _("kilo");
4067                 space_adjusted = floorf((float)rep.space / 1000.0);
4068         } else if (rep.space < 1000000 * 1000) {
4069                 bprefix = _("mega");
4070                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
4071         } else {
4072                 bprefix = _("giga");
4073                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
4074         }
4075
4076         if (msg_delete) {
4077                 txt.set_markup (string_compose (P_("\
4078 The following file was deleted from %2,\n\
4079 releasing %3 %4bytes of disk space", "\
4080 The following %1 files were deleted from %2,\n\
4081 releasing %3 %4bytes of disk space", removed),
4082                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4083         } else {
4084                 txt.set_markup (string_compose (P_("\
4085 The following file was not in use and \n\
4086 has been moved to: %2\n\n\
4087 After a restart of %5\n\n\
4088 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4089 will release an additional %3 %4bytes of disk space.\n", "\
4090 The following %1 files were not in use and \n\
4091 have been moved to: %2\n\n\
4092 After a restart of %5\n\n\
4093 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4094 will release an additional %3 %4bytes of disk space.\n", removed),
4095                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4096         }
4097
4098         dhbox.pack_start (*dimage, true, false, 5);
4099         dhbox.pack_start (txt, true, false, 5);
4100
4101         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
4102                 TreeModel::Row row = *(results_model->append());
4103                 row[results_columns.visible_name] = *i;
4104                 row[results_columns.fullpath] = *i;
4105         }
4106
4107         list_scroller.add (results_display);
4108         list_scroller.set_size_request (-1, 150);
4109         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
4110
4111         dvbox.pack_start (dhbox, true, false, 5);
4112         dvbox.pack_start (list_scroller, true, false, 5);
4113         ddhbox.pack_start (dvbox, true, false, 5);
4114
4115         results.get_vbox()->pack_start (ddhbox, true, false, 5);
4116         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
4117         results.set_default_response (RESPONSE_CLOSE);
4118         results.set_position (Gtk::WIN_POS_MOUSE);
4119
4120         results_display.show();
4121         list_scroller.show();
4122         txt.show();
4123         dvbox.show();
4124         dhbox.show();
4125         ddhbox.show();
4126         dimage->show();
4127
4128         //results.get_vbox()->show();
4129         results.set_resizable (false);
4130
4131         results.run ();
4132
4133 }
4134
4135 void
4136 ARDOUR_UI::cleanup ()
4137 {
4138         if (_session == 0) {
4139                 /* shouldn't happen: menu item is insensitive */
4140                 return;
4141         }
4142
4143
4144         MessageDialog checker (_("Are you sure you want to clean-up?"),
4145                                 true,
4146                                 Gtk::MESSAGE_QUESTION,
4147                                 Gtk::BUTTONS_NONE);
4148
4149         checker.set_title (_("Clean-up"));
4150
4151         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
4152 ALL undo/redo information will be lost if you clean-up.\n\
4153 Clean-up will move all unused files to a \"dead\" location."));
4154
4155         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
4156         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
4157         checker.set_default_response (RESPONSE_CANCEL);
4158
4159         checker.set_name (_("CleanupDialog"));
4160         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
4161         checker.set_position (Gtk::WIN_POS_MOUSE);
4162
4163         switch (checker.run()) {
4164         case RESPONSE_ACCEPT:
4165                 break;
4166         default:
4167                 return;
4168         }
4169
4170         ARDOUR::CleanupReport rep;
4171
4172         editor->prepare_for_cleanup ();
4173
4174         /* do not allow flush until a session is reloaded */
4175
4176         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
4177         if (act) {
4178                 act->set_sensitive (false);
4179         }
4180
4181         if (_session->cleanup_sources (rep)) {
4182                 editor->finish_cleanup ();
4183                 return;
4184         }
4185
4186         editor->finish_cleanup ();
4187
4188         checker.hide();
4189         display_cleanup_results (rep, _("Cleaned Files"), false);
4190 }
4191
4192 void
4193 ARDOUR_UI::flush_trash ()
4194 {
4195         if (_session == 0) {
4196                 /* shouldn't happen: menu item is insensitive */
4197                 return;
4198         }
4199
4200         ARDOUR::CleanupReport rep;
4201
4202         if (_session->cleanup_trash_sources (rep)) {
4203                 return;
4204         }
4205
4206         display_cleanup_results (rep, _("deleted file"), true);
4207 }
4208
4209 void
4210 ARDOUR_UI::cleanup_peakfiles ()
4211 {
4212         if (_session == 0) {
4213                 /* shouldn't happen: menu item is insensitive */
4214                 return;
4215         }
4216
4217         if (! _session->can_cleanup_peakfiles ()) {
4218                 return;
4219         }
4220
4221         // get all region-views in this session
4222         RegionSelection rs;
4223         TrackViewList empty;
4224         empty.clear();
4225         editor->get_regions_after(rs, (samplepos_t) 0, empty);
4226         std::list<RegionView*> views = rs.by_layer();
4227
4228         // remove displayed audio-region-views waveforms
4229         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4230                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4231                 if (!arv) { continue ; }
4232                 arv->delete_waves();
4233         }
4234
4235         // cleanup peak files:
4236         // - stop pending peakfile threads
4237         // - close peakfiles if any
4238         // - remove peak dir in session
4239         // - setup peakfiles (background thread)
4240         _session->cleanup_peakfiles ();
4241
4242         // re-add waves to ARV
4243         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4244                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4245                 if (!arv) { continue ; }
4246                 arv->create_waves();
4247         }
4248 }
4249
4250 PresentationInfo::order_t
4251 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
4252 {
4253         if (editor->get_selection().tracks.empty()) {
4254                 return place == RouteDialogs::First ? 0 : PresentationInfo::max_order;
4255         }
4256
4257         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
4258
4259         /*
4260           we want the new routes to have their order keys set starting from
4261           the highest order key in the selection + 1 (if available).
4262         */
4263
4264         if (place == RouteDialogs::AfterSelection) {
4265                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
4266                 if (rtav) {
4267                         order_hint = rtav->route()->presentation_info().order();
4268                         order_hint++;
4269                 }
4270         } else if (place == RouteDialogs::BeforeSelection) {
4271                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
4272                 if (rtav) {
4273                         order_hint = rtav->route()->presentation_info().order();
4274                 }
4275         } else if (place == RouteDialogs::First) {
4276                 order_hint = 0;
4277         } else {
4278                 /* leave order_hint at max_order */
4279         }
4280
4281         return order_hint;
4282 }
4283
4284 void
4285 ARDOUR_UI::start_duplicate_routes ()
4286 {
4287         if (!duplicate_routes_dialog) {
4288                 duplicate_routes_dialog = new DuplicateRouteDialog;
4289         }
4290
4291         if (duplicate_routes_dialog->restart (_session)) {
4292                 return;
4293         }
4294
4295         duplicate_routes_dialog->present ();
4296 }
4297
4298 void
4299 ARDOUR_UI::add_route ()
4300 {
4301         if (!add_route_dialog.get (false)) {
4302                 add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
4303         }
4304
4305         if (!_session) {
4306                 return;
4307         }
4308
4309         if (add_route_dialog->is_visible()) {
4310                 /* we're already doing this */
4311                 return;
4312         }
4313
4314         add_route_dialog->set_position (WIN_POS_MOUSE);
4315         add_route_dialog->present();
4316 }
4317
4318 void
4319 ARDOUR_UI::add_route_dialog_response (int r)
4320 {
4321         if (!_session) {
4322                 warning << _("You cannot add tracks or busses without a session already loaded.") << endmsg;
4323                 return;
4324         }
4325
4326         int count;
4327
4328         switch (r) {
4329         case AddRouteDialog::Add:
4330                 add_route_dialog->reset_name_edited ();
4331                 break;
4332         case AddRouteDialog::AddAndClose:
4333                 add_route_dialog->ArdourDialog::on_response (r);
4334                 break;
4335         default:
4336                 add_route_dialog->ArdourDialog::on_response (r);
4337                 return;
4338         }
4339
4340         std::string template_path = add_route_dialog->get_template_path();
4341         if (!template_path.empty() && template_path.substr (0, 11) == "urn:ardour:") {
4342                 meta_route_setup (template_path.substr (11));
4343                 return;
4344         }
4345
4346         if ((count = add_route_dialog->count()) <= 0) {
4347                 return;
4348         }
4349
4350         PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
4351         const string name_template = add_route_dialog->name_template ();
4352         DisplaySuspender ds;
4353
4354         if (!template_path.empty ()) {
4355                 if (add_route_dialog->name_template_is_default ()) {
4356                         _session->new_route_from_template (count, order, template_path, string ());
4357                 } else {
4358                         _session->new_route_from_template (count, order, template_path, name_template);
4359                 }
4360                 return;
4361         }
4362
4363         ChanCount input_chan= add_route_dialog->channels ();
4364         ChanCount output_chan;
4365         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
4366         RouteGroup* route_group = add_route_dialog->route_group ();
4367         AutoConnectOption oac = Config->get_output_auto_connect();
4368         bool strict_io = add_route_dialog->use_strict_io ();
4369
4370         if (oac & AutoConnectMaster) {
4371                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
4372                 output_chan.set (DataType::MIDI, 0);
4373         } else {
4374                 output_chan = input_chan;
4375         }
4376
4377         /* XXX do something with name template */
4378
4379         Session::ProcessorChangeBlocker pcb (_session);
4380
4381         switch (add_route_dialog->type_wanted()) {
4382         case AddRouteDialog::AudioTrack:
4383                 session_add_audio_route (true, input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order);
4384                 break;
4385         case AddRouteDialog::MidiTrack:
4386                 session_add_midi_route (true, route_group, count, name_template, strict_io, instrument, 0, order);
4387                 break;
4388         case AddRouteDialog::MixedTrack:
4389                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
4390                 break;
4391         case AddRouteDialog::AudioBus:
4392                 session_add_audio_route (false, input_chan.n_audio(), output_chan.n_audio(), ARDOUR::Normal, route_group, count, name_template, strict_io, order);
4393                 break;
4394         case AddRouteDialog::MidiBus:
4395                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
4396                 break;
4397         case AddRouteDialog::VCAMaster:
4398                 _session->vca_manager().create_vca (count, name_template);
4399                 break;
4400         }
4401 }
4402
4403 void
4404 ARDOUR_UI::stop_video_server (bool ask_confirm)
4405 {
4406         if (!video_server_process && ask_confirm) {
4407                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4408         }
4409         if (video_server_process) {
4410                 if(ask_confirm) {
4411                         ArdourDialog confirm (_("Stop Video-Server"), true);
4412                         Label m (_("Do you really want to stop the Video Server?"));
4413                         confirm.get_vbox()->pack_start (m, true, true);
4414                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4415                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4416                         confirm.show_all ();
4417                         if (confirm.run() == RESPONSE_CANCEL) {
4418                                 return;
4419                         }
4420                 }
4421                 delete video_server_process;
4422                 video_server_process =0;
4423         }
4424 }
4425
4426 void
4427 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4428 {
4429   ARDOUR_UI::start_video_server( float_window, true);
4430 }
4431
4432 bool
4433 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4434 {
4435         if (!_session) {
4436                 return false;
4437         }
4438         if (popup_msg) {
4439                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4440                         if (video_server_process) {
4441                                 popup_error(_("The Video Server is already started."));
4442                         } else {
4443                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4444                         }
4445                 }
4446         }
4447
4448         int firsttime = 0;
4449         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4450                 if (firsttime++) {
4451                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4452                 }
4453                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4454                 if (float_window) {
4455                         video_server_dialog->set_transient_for (*float_window);
4456                 }
4457
4458                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4459                         video_server_dialog->hide();
4460                 } else {
4461                         ResponseType r = (ResponseType) video_server_dialog->run ();
4462                         video_server_dialog->hide();
4463                         if (r != RESPONSE_ACCEPT) { return false; }
4464                         if (video_server_dialog->show_again()) {
4465                                 Config->set_show_video_server_dialog(false);
4466                         }
4467                 }
4468
4469                 std::string icsd_exec = video_server_dialog->get_exec_path();
4470                 std::string icsd_docroot = video_server_dialog->get_docroot();
4471 #ifndef PLATFORM_WINDOWS
4472                 if (icsd_docroot.empty()) {
4473                         icsd_docroot = VideoUtils::video_get_docroot (Config);
4474                 }
4475 #endif
4476
4477                 GStatBuf sb;
4478 #ifdef PLATFORM_WINDOWS
4479                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4480                         /* OK, allow all drive letters */
4481                 } else
4482 #endif
4483                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4484                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4485                         continue;
4486                 }
4487 #ifndef PLATFORM_WINDOWS
4488                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4489                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4490                         warning << _("Given Video Server is not an executable file.") << endmsg;
4491                         continue;
4492                 }
4493 #else
4494                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4495                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4496                         warning << _("Given Video Server is not an executable file.") << endmsg;
4497                         continue;
4498                 }
4499 #endif
4500
4501                 char **argp;
4502                 argp=(char**) calloc(9,sizeof(char*));
4503                 argp[0] = strdup(icsd_exec.c_str());
4504                 argp[1] = strdup("-P");
4505                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4506                 argp[3] = strdup("-p");
4507                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4508                 argp[5] = strdup("-C");
4509                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4510                 argp[7] = strdup(icsd_docroot.c_str());
4511                 argp[8] = 0;
4512                 stop_video_server();
4513
4514 #ifdef PLATFORM_WINDOWS
4515                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4516                         /* OK, allow all drive letters */
4517                 } else
4518 #endif
4519                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4520                         Config->set_video_advanced_setup(false);
4521                 } else {
4522                         std::string url_str = "http://127.0.0.1:" + to_string(video_server_dialog->get_listenport()) + "/";
4523                         Config->set_video_server_url(url_str);
4524                         Config->set_video_server_docroot(icsd_docroot);
4525                         Config->set_video_advanced_setup(true);
4526                 }
4527
4528                 if (video_server_process) {
4529                         delete video_server_process;
4530                 }
4531
4532                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4533                 if (video_server_process->start()) {
4534                         warning << _("Cannot launch the video-server") << endmsg;
4535                         continue;
4536                 }
4537                 int timeout = 120; // 6 sec
4538                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4539                         Glib::usleep (50000);
4540                         gui_idle_handler();
4541                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4542                 }
4543                 if (timeout <= 0) {
4544                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4545                 } else {
4546                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4547                                 delete video_server_process;
4548                                 video_server_process = 0;
4549                         }
4550                 }
4551         }
4552         return true;
4553 }
4554
4555 void
4556 ARDOUR_UI::add_video (Gtk::Window* float_window)
4557 {
4558         if (!_session) {
4559                 return;
4560         }
4561
4562         if (!start_video_server(float_window, false)) {
4563                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4564                 return;
4565         }
4566
4567         if (float_window) {
4568                 add_video_dialog->set_transient_for (*float_window);
4569         }
4570
4571         if (add_video_dialog->is_visible()) {
4572                 /* we're already doing this */
4573                 return;
4574         }
4575
4576         ResponseType r = (ResponseType) add_video_dialog->run ();
4577         add_video_dialog->hide();
4578         if (r != RESPONSE_ACCEPT) { return; }
4579
4580         bool local_file, orig_local_file;
4581         std::string path = add_video_dialog->file_name(local_file);
4582
4583         std::string orig_path = path;
4584         orig_local_file = local_file;
4585
4586         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4587
4588         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4589                 warning << string_compose(_("could not open %1"), path) << endmsg;
4590                 return;
4591         }
4592         if (!local_file && path.length() == 0) {
4593                 warning << _("no video-file selected") << endmsg;
4594                 return;
4595         }
4596
4597         std::string audio_from_video;
4598         bool detect_ltc = false;
4599
4600         switch (add_video_dialog->import_option()) {
4601                 case VTL_IMPORT_TRANSCODE:
4602                         {
4603                                 TranscodeVideoDialog *transcode_video_dialog;
4604                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4605                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4606                                 transcode_video_dialog->hide();
4607                                 if (r != RESPONSE_ACCEPT) {
4608                                         delete transcode_video_dialog;
4609                                         return;
4610                                 }
4611
4612                                 audio_from_video = transcode_video_dialog->get_audiofile();
4613
4614                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4615                                         detect_ltc = true;
4616                                 }
4617                                 else if (!audio_from_video.empty()) {
4618                                         editor->embed_audio_from_video(
4619                                                         audio_from_video,
4620                                                         video_timeline->get_offset(),
4621                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4622                                                         );
4623                                 }
4624                                 switch (transcode_video_dialog->import_option()) {
4625                                         case VTL_IMPORT_TRANSCODED:
4626                                                 path = transcode_video_dialog->get_filename();
4627                                                 local_file = true;
4628                                                 break;
4629                                         case VTL_IMPORT_REFERENCE:
4630                                                 break;
4631                                         default:
4632                                                 delete transcode_video_dialog;
4633                                                 return;
4634                                 }
4635                                 delete transcode_video_dialog;
4636                         }
4637                         break;
4638                 default:
4639                 case VTL_IMPORT_NONE:
4640                         break;
4641         }
4642
4643         /* strip _session->session_directory().video_path() from video file if possible */
4644         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4645                  path=path.substr(_session->session_directory().video_path().size());
4646                  if (path.at(0) == G_DIR_SEPARATOR) {
4647                          path=path.substr(1);
4648                  }
4649         }
4650
4651         video_timeline->set_update_session_fps(auto_set_session_fps);
4652
4653         if (video_timeline->video_file_info(path, local_file)) {
4654                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4655                 node->set_property (X_("Filename"), path);
4656                 node->set_property (X_("AutoFPS"), auto_set_session_fps);
4657                 node->set_property (X_("LocalFile"), local_file);
4658                 if (orig_local_file) {
4659                         node->set_property (X_("OriginalVideoFile"), orig_path);
4660                 } else {
4661                         node->remove_property (X_("OriginalVideoFile"));
4662                 }
4663                 _session->add_extra_xml (*node);
4664                 _session->set_dirty ();
4665
4666                 if (!audio_from_video.empty() && detect_ltc) {
4667                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4668
4669                         try {
4670                                 /* TODO ask user about TV standard (LTC alignment if any) */
4671                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4672                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4673
4674                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC samples to decode*/ 15);
4675
4676                                 /* TODO seek near end of file, and read LTC until end.
4677                                  * if it fails to find any LTC samples, scan complete file
4678                                  *
4679                                  * calculate drift of LTC compared to video-duration,
4680                                  * ask user for reference (timecode from start/mid/end)
4681                                  */
4682                         } catch (...) {
4683                                 // LTCFileReader will have written error messages
4684                         }
4685
4686                         ::g_unlink(audio_from_video.c_str());
4687
4688                         if (ltc_seq.size() == 0) {
4689                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4690                         } else {
4691                                 /* the very first TC in the file is somteimes not aligned properly */
4692                                 int i = ltc_seq.size() -1;
4693                                 ARDOUR::sampleoffset_t video_start_offset =
4694                                         _session->nominal_sample_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4695                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4696                                 video_timeline->set_offset(video_start_offset);
4697                         }
4698                 }
4699
4700                 _session->maybe_update_session_range(
4701                         std::max(video_timeline->get_offset(), (ARDOUR::sampleoffset_t) 0),
4702                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::sampleoffset_t) 0));
4703
4704
4705                 if (add_video_dialog->launch_xjadeo() && local_file) {
4706                         editor->set_xjadeo_sensitive(true);
4707                         editor->toggle_xjadeo_proc(1);
4708                 } else {
4709                         editor->toggle_xjadeo_proc(0);
4710                 }
4711                 editor->toggle_ruler_video(true);
4712         }
4713 }
4714
4715 void
4716 ARDOUR_UI::remove_video ()
4717 {
4718         video_timeline->close_session();
4719         editor->toggle_ruler_video(false);
4720
4721         /* reset state */
4722         video_timeline->set_offset_locked(false);
4723         video_timeline->set_offset(0);
4724
4725         /* delete session state */
4726         XMLNode* node = new XMLNode(X_("Videotimeline"));
4727         _session->add_extra_xml(*node);
4728         node = new XMLNode(X_("Videomonitor"));
4729         _session->add_extra_xml(*node);
4730         node = new XMLNode(X_("Videoexport"));
4731         _session->add_extra_xml(*node);
4732         stop_video_server();
4733 }
4734
4735 void
4736 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4737 {
4738         if (localcacheonly) {
4739                 video_timeline->vmon_update();
4740         } else {
4741                 video_timeline->flush_cache();
4742         }
4743         editor->queue_visual_videotimeline_update();
4744 }
4745
4746 void
4747 ARDOUR_UI::export_video (bool range)
4748 {
4749         if (ARDOUR::Config->get_show_video_export_info()) {
4750                 ExportVideoInfobox infobox (_session);
4751                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4752                 if (infobox.show_again()) {
4753                         ARDOUR::Config->set_show_video_export_info(false);
4754                 }
4755                 switch (rv) {
4756                         case GTK_RESPONSE_YES:
4757                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4758                                 break;
4759                         default:
4760                                 break;
4761                 }
4762         }
4763         export_video_dialog->set_session (_session);
4764         export_video_dialog->apply_state(editor->get_selection().time, range);
4765         export_video_dialog->run ();
4766         export_video_dialog->hide ();
4767 }
4768
4769 XMLNode*
4770 ARDOUR_UI::preferences_settings () const
4771 {
4772         XMLNode* node = 0;
4773
4774         if (_session) {
4775                 node = _session->instant_xml(X_("Preferences"));
4776         } else {
4777                 node = Config->instant_xml(X_("Preferences"));
4778         }
4779
4780         if (!node) {
4781                 node = new XMLNode (X_("Preferences"));
4782         }
4783
4784         return node;
4785 }
4786
4787 XMLNode*
4788 ARDOUR_UI::mixer_settings () const
4789 {
4790         XMLNode* node = 0;
4791
4792         if (_session) {
4793                 node = _session->instant_xml(X_("Mixer"));
4794         } else {
4795                 node = Config->instant_xml(X_("Mixer"));
4796         }
4797
4798         if (!node) {
4799                 node = new XMLNode (X_("Mixer"));
4800         }
4801
4802         return node;
4803 }
4804
4805 XMLNode*
4806 ARDOUR_UI::main_window_settings () const
4807 {
4808         XMLNode* node = 0;
4809
4810         if (_session) {
4811                 node = _session->instant_xml(X_("Main"));
4812         } else {
4813                 node = Config->instant_xml(X_("Main"));
4814         }
4815
4816         if (!node) {
4817                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4818                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4819                 }
4820         }
4821
4822         if (!node) {
4823                 node = new XMLNode (X_("Main"));
4824         }
4825
4826         return node;
4827 }
4828
4829 XMLNode*
4830 ARDOUR_UI::editor_settings () const
4831 {
4832         XMLNode* node = 0;
4833
4834         if (_session) {
4835                 node = _session->instant_xml(X_("Editor"));
4836         } else {
4837                 node = Config->instant_xml(X_("Editor"));
4838         }
4839
4840         if (!node) {
4841                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4842                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4843                 }
4844         }
4845
4846         if (!node) {
4847                 node = new XMLNode (X_("Editor"));
4848         }
4849
4850         return node;
4851 }
4852
4853 XMLNode*
4854 ARDOUR_UI::keyboard_settings () const
4855 {
4856         XMLNode* node = 0;
4857
4858         node = Config->extra_xml(X_("Keyboard"));
4859
4860         if (!node) {
4861                 node = new XMLNode (X_("Keyboard"));
4862         }
4863
4864         return node;
4865 }
4866
4867 void
4868 ARDOUR_UI::create_xrun_marker (samplepos_t where)
4869 {
4870         if (_session) {
4871                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark, 0);
4872                 _session->locations()->add (location);
4873         }
4874 }
4875
4876 void
4877 ARDOUR_UI::halt_on_xrun_message ()
4878 {
4879         cerr << "HALT on xrun\n";
4880         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4881         msg.run ();
4882 }
4883
4884 void
4885 ARDOUR_UI::xrun_handler (samplepos_t where)
4886 {
4887         if (!_session) {
4888                 return;
4889         }
4890
4891         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4892
4893         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4894                 create_xrun_marker(where);
4895         }
4896
4897         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4898                 halt_on_xrun_message ();
4899         }
4900 }
4901
4902 void
4903 ARDOUR_UI::disk_overrun_handler ()
4904 {
4905         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4906
4907         if (!have_disk_speed_dialog_displayed) {
4908                 have_disk_speed_dialog_displayed = true;
4909                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4910 The disk system on your computer\n\
4911 was not able to keep up with %1.\n\
4912 \n\
4913 Specifically, it failed to write data to disk\n\
4914 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4915                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4916                 msg->show ();
4917         }
4918 }
4919
4920
4921 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4922 static MessageDialog *scan_dlg = NULL;
4923 static ProgressBar   *scan_pbar = NULL;
4924 static HBox          *scan_tbox = NULL;
4925 static Gtk::Button   *scan_timeout_button;
4926
4927 void
4928 ARDOUR_UI::cancel_plugin_scan ()
4929 {
4930         PluginManager::instance().cancel_plugin_scan();
4931 }
4932
4933 void
4934 ARDOUR_UI::cancel_plugin_timeout ()
4935 {
4936         PluginManager::instance().cancel_plugin_timeout();
4937         scan_timeout_button->set_sensitive (false);
4938 }
4939
4940 void
4941 ARDOUR_UI::plugin_scan_timeout (int timeout)
4942 {
4943         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4944                 return;
4945         }
4946         if (timeout > 0) {
4947                 scan_pbar->set_sensitive (false);
4948                 scan_timeout_button->set_sensitive (true);
4949                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4950                 scan_tbox->show();
4951         } else {
4952                 scan_pbar->set_sensitive (false);
4953                 scan_timeout_button->set_sensitive (false);
4954         }
4955         gui_idle_handler();
4956 }
4957
4958 void
4959 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4960 {
4961         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4962                 return;
4963         }
4964
4965         const bool cancelled = PluginManager::instance().cancelled();
4966         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4967                 if (cancelled && scan_dlg->is_mapped()) {
4968                         scan_dlg->hide();
4969                         gui_idle_handler();
4970                         return;
4971                 }
4972                 if (cancelled || !can_cancel) {
4973                         return;
4974                 }
4975         }
4976
4977         static Gtk::Button *cancel_button;
4978         if (!scan_dlg) {
4979                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4980                 VBox* vbox = scan_dlg->get_vbox();
4981                 vbox->set_size_request(400,-1);
4982                 scan_dlg->set_title (_("Scanning for plugins"));
4983
4984                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4985                 cancel_button->set_name ("EditorGTKButton");
4986                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4987                 cancel_button->show();
4988
4989                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4990
4991                 scan_tbox = manage( new HBox() );
4992
4993                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4994                 scan_timeout_button->set_name ("EditorGTKButton");
4995                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4996                 scan_timeout_button->show();
4997
4998                 scan_pbar = manage(new ProgressBar());
4999                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
5000                 scan_pbar->set_text(_("Scan Timeout"));
5001                 scan_pbar->show();
5002
5003                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
5004                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
5005
5006                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
5007         }
5008
5009         assert(scan_dlg && scan_tbox && cancel_button);
5010
5011         if (type == X_("closeme")) {
5012                 scan_tbox->hide();
5013                 scan_dlg->hide();
5014         } else {
5015                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
5016                 scan_dlg->show();
5017         }
5018         if (!can_cancel || !cancelled) {
5019                 scan_timeout_button->set_sensitive(false);
5020         }
5021         cancel_button->set_sensitive(can_cancel && !cancelled);
5022
5023         gui_idle_handler();
5024 }
5025
5026 void
5027 ARDOUR_UI::gui_idle_handler ()
5028 {
5029         int timeout = 30;
5030         /* due to idle calls, gtk_events_pending() may always return true */
5031         while (gtk_events_pending() && --timeout) {
5032                 gtk_main_iteration ();
5033         }
5034 }
5035
5036 void
5037 ARDOUR_UI::disk_underrun_handler ()
5038 {
5039         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
5040
5041         if (!have_disk_speed_dialog_displayed) {
5042                 have_disk_speed_dialog_displayed = true;
5043                 MessageDialog* msg = new MessageDialog (
5044                         _main_window, string_compose (_("The disk system on your computer\n\
5045 was not able to keep up with %1.\n\
5046 \n\
5047 Specifically, it failed to read data from disk\n\
5048 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
5049                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
5050                 msg->show ();
5051         }
5052 }
5053
5054 void
5055 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
5056 {
5057         have_disk_speed_dialog_displayed = false;
5058         delete msg;
5059 }
5060
5061 void
5062 ARDOUR_UI::session_dialog (std::string msg)
5063 {
5064         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
5065
5066         MessageDialog* d;
5067
5068         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
5069         d->show_all ();
5070         d->run ();
5071         delete d;
5072 }
5073
5074 int
5075 ARDOUR_UI::pending_state_dialog ()
5076 {
5077         HBox* hbox = manage (new HBox());
5078         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
5079         ArdourDialog dialog (_("Crash Recovery"), true);
5080         Label  message (string_compose (_("\
5081 This session appears to have been in the\n\
5082 middle of recording when %1 or\n\
5083 the computer was shutdown.\n\
5084 \n\
5085 %1 can recover any captured audio for\n\
5086 you, or it can ignore it. Please decide\n\
5087 what you would like to do.\n"), PROGRAM_NAME));
5088         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5089         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5090         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5091         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5092         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
5093         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
5094         dialog.set_default_response (RESPONSE_ACCEPT);
5095         dialog.set_position (WIN_POS_CENTER);
5096         message.show();
5097         image->show();
5098         hbox->show();
5099
5100         switch (dialog.run ()) {
5101         case RESPONSE_ACCEPT:
5102                 return 1;
5103         default:
5104                 return 0;
5105         }
5106 }
5107
5108 int
5109 ARDOUR_UI::sr_mismatch_dialog (samplecnt_t desired, samplecnt_t actual)
5110 {
5111         HBox* hbox = new HBox();
5112         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
5113         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
5114         Label  message (string_compose (_("\
5115 This session was created with a sample rate of %1 Hz, but\n\
5116 %2 is currently running at %3 Hz.  If you load this session,\n\
5117 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
5118
5119         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5120         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5121         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5122         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5123         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
5124         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
5125         dialog.set_default_response (RESPONSE_ACCEPT);
5126         dialog.set_position (WIN_POS_CENTER);
5127         message.show();
5128         image->show();
5129         hbox->show();
5130
5131         switch (dialog.run()) {
5132         case RESPONSE_ACCEPT:
5133                 return 0;
5134         default:
5135                 break;
5136         }
5137
5138         return 1;
5139 }
5140
5141 void
5142 ARDOUR_UI::sr_mismatch_message (samplecnt_t desired, samplecnt_t actual)
5143 {
5144         MessageDialog msg (string_compose (_("\
5145 This session was created with a sample rate of %1 Hz, but\n\
5146 %2 is currently running at %3 Hz.\n\
5147 Audio will be recorded and played at the wrong sample rate.\n\
5148 Re-Configure the Audio Engine in\n\
5149 Menu > Window > Audio/Midi Setup"),
5150                                 desired, PROGRAM_NAME, actual),
5151                         true,
5152                         Gtk::MESSAGE_WARNING);
5153         msg.run ();
5154 }
5155
5156 void
5157 ARDOUR_UI::use_config ()
5158 {
5159         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
5160         if (node) {
5161                 set_transport_controllable_state (*node);
5162         }
5163 }
5164
5165 void
5166 ARDOUR_UI::update_transport_clocks (samplepos_t pos)
5167 {
5168         switch (UIConfiguration::instance().get_primary_clock_delta_mode()) {
5169                 case NoDelta:
5170                         primary_clock->set (pos);
5171                         break;
5172                 case DeltaEditPoint:
5173                         primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5174                         break;
5175                 case DeltaOriginMarker:
5176                         {
5177                                 Location* loc = _session->locations()->clock_origin_location ();
5178                                 primary_clock->set (pos, false, loc ? loc->start() : 0);
5179                         }
5180                         break;
5181         }
5182
5183         switch (UIConfiguration::instance().get_secondary_clock_delta_mode()) {
5184                 case NoDelta:
5185                         secondary_clock->set (pos);
5186                         break;
5187                 case DeltaEditPoint:
5188                         secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5189                         break;
5190                 case DeltaOriginMarker:
5191                         {
5192                                 Location* loc = _session->locations()->clock_origin_location ();
5193                                 secondary_clock->set (pos, false, loc ? loc->start() : 0);
5194                         }
5195                         break;
5196         }
5197
5198         if (big_clock_window) {
5199                 big_clock->set (pos);
5200         }
5201         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
5202 }
5203
5204
5205 void
5206 ARDOUR_UI::record_state_changed ()
5207 {
5208         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
5209
5210         if (!_session) {
5211                 /* why bother - the clock isn't visible */
5212                 return;
5213         }
5214
5215         ActionManager::set_sensitive (ActionManager::rec_sensitive_actions, !_session->actively_recording());
5216
5217         if (big_clock_window) {
5218                 if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
5219                         big_clock->set_active (true);
5220                 } else {
5221                         big_clock->set_active (false);
5222                 }
5223         }
5224
5225 }
5226
5227 bool
5228 ARDOUR_UI::first_idle ()
5229 {
5230         if (_session) {
5231                 _session->allow_auto_play (true);
5232         }
5233
5234         if (editor) {
5235                 editor->first_idle();
5236         }
5237
5238         /* in 1 second, hide the splash screen
5239          *
5240          * Consider hiding it *now*. If a user opens opens a dialog
5241          * during that one second while the splash is still visible,
5242          * the dialog will push-back the splash.
5243          * Closing the dialog later will pop it back.
5244          */
5245         Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
5246
5247         Keyboard::set_can_save_keybindings (true);
5248         return false;
5249 }
5250
5251 void
5252 ARDOUR_UI::store_clock_modes ()
5253 {
5254         XMLNode* node = new XMLNode(X_("ClockModes"));
5255
5256         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
5257                 XMLNode* child = new XMLNode (X_("Clock"));
5258
5259                 child->set_property (X_("name"), (*x)->name());
5260                 child->set_property (X_("mode"), (*x)->mode());
5261                 child->set_property (X_("on"), (*x)->on());
5262
5263                 node->add_child_nocopy (*child);
5264         }
5265
5266         _session->add_extra_xml (*node);
5267         _session->set_dirty ();
5268 }
5269
5270 void
5271 ARDOUR_UI::setup_profile ()
5272 {
5273         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5274                 Profile->set_small_screen ();
5275         }
5276
5277         if (g_getenv ("TRX")) {
5278                 Profile->set_trx ();
5279         }
5280
5281         if (g_getenv ("MIXBUS")) {
5282                 Profile->set_mixbus ();
5283         }
5284 }
5285
5286 int
5287 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5288 {
5289         MissingFileDialog dialog (s, str, type);
5290
5291         dialog.show ();
5292         dialog.present ();
5293
5294         int result = dialog.run ();
5295         dialog.hide ();
5296
5297         switch (result) {
5298         case RESPONSE_OK:
5299                 break;
5300         default:
5301                 return 1; // quit entire session load
5302         }
5303
5304         result = dialog.get_action ();
5305
5306         return result;
5307 }
5308
5309 int
5310 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5311 {
5312         AmbiguousFileDialog dialog (file, hits);
5313
5314         dialog.show ();
5315         dialog.present ();
5316
5317         dialog.run ();
5318
5319         return dialog.get_which ();
5320 }
5321
5322 /** Allocate our thread-local buffers */
5323 void
5324 ARDOUR_UI::get_process_buffers ()
5325 {
5326         _process_thread->get_buffers ();
5327 }
5328
5329 /** Drop our thread-local buffers */
5330 void
5331 ARDOUR_UI::drop_process_buffers ()
5332 {
5333         _process_thread->drop_buffers ();
5334 }
5335
5336 void
5337 ARDOUR_UI::feedback_detected ()
5338 {
5339         _feedback_exists = true;
5340 }
5341
5342 void
5343 ARDOUR_UI::successful_graph_sort ()
5344 {
5345         _feedback_exists = false;
5346 }
5347
5348 void
5349 ARDOUR_UI::midi_panic ()
5350 {
5351         if (_session) {
5352                 _session->midi_panic();
5353         }
5354 }
5355
5356 void
5357 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5358 {
5359         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5360         const char* end_big = "</span>";
5361         const char* start_mono = "<tt>";
5362         const char* end_mono = "</tt>";
5363
5364         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5365                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5366                                              "From now on, use the backup copy with older versions of %3"),
5367                                            xml_path, backup_path, PROGRAM_NAME,
5368                                            start_big, end_big,
5369                                            start_mono, end_mono), true);
5370
5371         msg.run ();
5372 }
5373
5374 void
5375 ARDOUR_UI::add_editor_meter_type_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type)
5376 {
5377         using namespace Menu_Helpers;
5378
5379         items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (editor_meter, &LevelMeterHBox::set_meter_type), type)));
5380         RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
5381         i->set_active (editor_meter->meter_type () == type);
5382 }
5383
5384 void
5385 ARDOUR_UI::popup_editor_meter_menu (GdkEventButton* ev)
5386 {
5387         using namespace Gtk::Menu_Helpers;
5388
5389         Gtk::Menu* m = manage (new Menu);
5390         MenuList& items = m->items ();
5391
5392         RadioMenuItem::Group group;
5393
5394         _suspend_editor_meter_callbacks = true;
5395         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
5396         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak0dB), MeterPeak0dB);
5397         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterKrms),  MeterKrms);
5398         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN);
5399         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR);
5400         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC);
5401         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
5402         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20);
5403         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14);
5404         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK12), MeterK12);
5405         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU),  MeterVU);
5406
5407         m->popup (ev->button, ev->time);
5408         _suspend_editor_meter_callbacks = false;
5409 }
5410
5411 bool
5412 ARDOUR_UI::editor_meter_button_press (GdkEventButton* ev)
5413 {
5414         if (ev->button == 3 && editor_meter) {
5415                 popup_editor_meter_menu (ev);
5416                 return true;
5417         }
5418         return false;
5419 }
5420
5421 void
5422 ARDOUR_UI::reset_peak_display ()
5423 {
5424         if (!_session || !_session->master_out() || !editor_meter) return;
5425         editor_meter->clear_meters();
5426         editor_meter_max_peak = -INFINITY;
5427         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5428 }
5429
5430 void
5431 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5432 {
5433         if (!_session || !_session->master_out()) return;
5434         if (group == _session->master_out()->route_group()) {
5435                 reset_peak_display ();
5436         }
5437 }
5438
5439 void
5440 ARDOUR_UI::reset_route_peak_display (Route* route)
5441 {
5442         if (!_session || !_session->master_out()) return;
5443         if (_session->master_out().get() == route) {
5444                 reset_peak_display ();
5445         }
5446 }
5447
5448 int
5449 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5450 {
5451         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5452         audio_midi_setup->set_position (WIN_POS_CENTER);
5453
5454         if (desired_sample_rate != 0) {
5455                 if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
5456                         audio_midi_setup->try_autostart ();
5457                         if (ARDOUR::AudioEngine::instance()->running()) {
5458                                 return 0;
5459                         }
5460                 }
5461         }
5462
5463         while (true) {
5464                 int response = audio_midi_setup->run();
5465                 switch (response) {
5466                 case Gtk::RESPONSE_DELETE_EVENT:
5467                         // after latency callibration engine may run,
5468                         // Running() signal was emitted, but dialog will not
5469                         // have emitted a response. The user needs to close
5470                         // the dialog -> Gtk::RESPONSE_DELETE_EVENT
5471                         if (!AudioEngine::instance()->running()) {
5472                                 return -1;
5473                         }
5474                         // fall through
5475                 default:
5476                         if (!AudioEngine::instance()->running()) {
5477                                 continue;
5478                         }
5479                         audio_midi_setup->hide ();
5480                         return 0;
5481                 }
5482         }
5483 }
5484
5485
5486 gint
5487 ARDOUR_UI::transport_numpad_timeout ()
5488 {
5489         _numpad_locate_happening = false;
5490         if (_numpad_timeout_connection.connected() )
5491                 _numpad_timeout_connection.disconnect();
5492         return 1;
5493 }
5494
5495 void
5496 ARDOUR_UI::transport_numpad_decimal ()
5497 {
5498         _numpad_timeout_connection.disconnect();
5499
5500         if (_numpad_locate_happening) {
5501                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5502                 _numpad_locate_happening = false;
5503         } else {
5504                 _pending_locate_num = 0;
5505                 _numpad_locate_happening = true;
5506                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5507         }
5508 }
5509
5510 void
5511 ARDOUR_UI::transport_numpad_event (int num)
5512 {
5513         if ( _numpad_locate_happening ) {
5514                 _pending_locate_num = _pending_locate_num*10 + num;
5515         } else {
5516                 switch (num) {
5517                         case 0:  toggle_roll(false, false);             break;
5518                         case 1:  transport_rewind(1);                           break;
5519                         case 2:  transport_forward(1);                          break;
5520                         case 3:  transport_record(true);                        break;
5521                         case 4:  toggle_session_auto_loop();            break;
5522                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5523                         case 6:  toggle_punch();                                        break;
5524                         case 7:  toggle_click();                                break;
5525                         case 8:  toggle_auto_return();                  break;
5526                         case 9:  toggle_follow_edits();         break;
5527                 }
5528         }
5529 }
5530
5531 void
5532 ARDOUR_UI::set_flat_buttons ()
5533 {
5534         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5535 }
5536
5537 void
5538 ARDOUR_UI::audioengine_became_silent ()
5539 {
5540         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5541                            true,
5542                            Gtk::MESSAGE_WARNING,
5543                            Gtk::BUTTONS_NONE,
5544                            true);
5545
5546         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5547
5548         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5549         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5550         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5551         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5552         Gtk::HBox pay_button_box;
5553         Gtk::HBox subscribe_button_box;
5554
5555         pay_button_box.pack_start (pay_button, true, false);
5556         subscribe_button_box.pack_start (subscribe_button, true, false);
5557
5558         bool (*openuri)(const char*) = PBD::open_uri; /* this forces selection of the const char* variant of PBD::open_uri(), which we need to avoid ambiguity below */
5559
5560         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5561         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5562
5563         msg.get_vbox()->pack_start (pay_label);
5564         msg.get_vbox()->pack_start (pay_button_box);
5565         msg.get_vbox()->pack_start (subscribe_label);
5566         msg.get_vbox()->pack_start (subscribe_button_box);
5567
5568         msg.get_vbox()->show_all ();
5569
5570         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5571         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5572         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5573
5574         int r = msg.run ();
5575
5576         switch (r) {
5577         case Gtk::RESPONSE_YES:
5578                 AudioEngine::instance()->reset_silence_countdown ();
5579                 break;
5580
5581         case Gtk::RESPONSE_NO:
5582                 /* save and quit */
5583                 save_state_canfail ("");
5584                 exit (0);
5585                 break;
5586
5587         case Gtk::RESPONSE_CANCEL:
5588         default:
5589                 /* don't reset, save session and exit */
5590                 break;
5591         }
5592 }
5593
5594 void
5595 ARDOUR_UI::hide_application ()
5596 {
5597         Application::instance ()-> hide ();
5598 }
5599
5600 void
5601 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5602 {
5603         /* icons, titles, WM stuff */
5604
5605         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5606
5607         if (window_icons.empty()) {
5608                 Glib::RefPtr<Gdk::Pixbuf> icon;
5609                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
5610                         window_icons.push_back (icon);
5611                 }
5612                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
5613                         window_icons.push_back (icon);
5614                 }
5615                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
5616                         window_icons.push_back (icon);
5617                 }
5618                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
5619                         window_icons.push_back (icon);
5620                 }
5621         }
5622
5623         if (!window_icons.empty()) {
5624                 window.set_default_icon_list (window_icons);
5625         }
5626
5627         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5628
5629         if (!name.empty()) {
5630                 title += name;
5631         }
5632
5633         window.set_title (title.get_string());
5634         window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME);
5635
5636         window.set_flags (CAN_FOCUS);
5637         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5638
5639         /* This is a hack to ensure that GTK-accelerators continue to
5640          * work. Once we switch over to entirely native bindings, this will be
5641          * unnecessary and should be removed
5642          */
5643         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5644
5645         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5646         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5647         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5648         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5649 }
5650
5651 bool
5652 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5653 {
5654         Gtkmm2ext::Bindings* bindings = 0;
5655         Gtk::Window* window = 0;
5656
5657         /* until we get ardour bindings working, we are not handling key
5658          * releases yet.
5659          */
5660
5661         if (ev->type != GDK_KEY_PRESS) {
5662                 return false;
5663         }
5664
5665         if (event_window == &_main_window) {
5666
5667                 window = event_window;
5668
5669                 /* find current tab contents */
5670
5671                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5672
5673                 /* see if it uses the ardour binding system */
5674
5675                 if (w) {
5676                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5677                 }
5678
5679                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5680
5681         } else {
5682
5683                 window = event_window;
5684
5685                 /* see if window uses ardour binding system */
5686
5687                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5688         }
5689
5690         /* An empty binding set is treated as if it doesn't exist */
5691
5692         if (bindings && bindings->empty()) {
5693                 bindings = 0;
5694         }
5695
5696         return key_press_focus_accelerator_handler (*window, ev, bindings);
5697 }
5698
5699 static Gtkmm2ext::Bindings*
5700 get_bindings_from_widget_heirarchy (GtkWidget** w)
5701 {
5702         void* p = NULL;
5703
5704         while (*w) {
5705                 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
5706                         break;
5707                 }
5708                 *w = gtk_widget_get_parent (*w);
5709         }
5710
5711         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5712 }
5713
5714 bool
5715 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5716 {
5717         GtkWindow* win = window.gobj();
5718         GtkWidget* focus = gtk_window_get_focus (win);
5719         GtkWidget* binding_widget = focus;
5720         bool special_handling_of_unmodified_accelerators = false;
5721         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5722
5723         if (focus) {
5724
5725                 /* some widget has keyboard focus */
5726
5727                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5728
5729                         /* A particular kind of focusable widget currently has keyboard
5730                          * focus. All unmodified key events should go to that widget
5731                          * first and not be used as an accelerator by default
5732                          */
5733
5734                         special_handling_of_unmodified_accelerators = true;
5735
5736                 } else {
5737
5738                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5739                         if (focus_bindings) {
5740                                 bindings = focus_bindings;
5741                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5742                         }
5743                 }
5744         }
5745
5746         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 [title = %9] focus = %7 (%8) Key event: code = %2  state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n",
5747                                                           win,
5748                                                           ev->keyval,
5749                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
5750                                                           special_handling_of_unmodified_accelerators,
5751                                                           Keyboard::some_magic_widget_has_focus(),
5752                                                           focus,
5753                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5754                                                           ((ev->state & mask) ? "yes" : "no"),
5755                                                           window.get_title()));
5756
5757         /* This exists to allow us to override the way GTK handles
5758            key events. The normal sequence is:
5759
5760            a) event is delivered to a GtkWindow
5761            b) accelerators/mnemonics are activated
5762            c) if (b) didn't handle the event, propagate to
5763                the focus widget and/or focus chain
5764
5765            The problem with this is that if the accelerators include
5766            keys without modifiers, such as the space bar or the
5767            letter "e", then pressing the key while typing into
5768            a text entry widget results in the accelerator being
5769            activated, instead of the desired letter appearing
5770            in the text entry.
5771
5772            There is no good way of fixing this, but this
5773            represents a compromise. The idea is that
5774            key events involving modifiers (not Shift)
5775            get routed into the activation pathway first, then
5776            get propagated to the focus widget if necessary.
5777
5778            If the key event doesn't involve modifiers,
5779            we deliver to the focus widget first, thus allowing
5780            it to get "normal text" without interference
5781            from acceleration.
5782
5783            Of course, this can also be problematic: if there
5784            is a widget with focus, then it will swallow
5785            all "normal text" accelerators.
5786         */
5787
5788
5789         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5790
5791                 /* no special handling or there are modifiers in effect: accelerate first */
5792
5793                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5794                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5795                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5796
5797                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5798                 KeyboardKey k (ev->state, ev->keyval);
5799
5800                 while (bindings) {
5801
5802                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5803
5804                         if (bindings->activate (k, Bindings::Press)) {
5805                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5806                                 return true;
5807                         }
5808
5809                         if (binding_widget) {
5810                                 binding_widget = gtk_widget_get_parent (binding_widget);
5811                                 if (binding_widget) {
5812                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5813                                 } else {
5814                                         bindings = 0;
5815                                 }
5816                         } else {
5817                                 bindings = 0;
5818                         }
5819                 }
5820
5821                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5822
5823                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5824                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5825                         return true;
5826                 }
5827
5828                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5829
5830                 if (gtk_window_propagate_key_event (win, ev)) {
5831                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5832                         return true;
5833                 }
5834
5835         } else {
5836
5837                 /* no modifiers, propagate first */
5838
5839                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5840
5841                 if (gtk_window_propagate_key_event (win, ev)) {
5842                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5843                         return true;
5844                 }
5845
5846                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5847                 KeyboardKey k (ev->state, ev->keyval);
5848
5849                 while (bindings) {
5850
5851                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5852
5853
5854                         if (bindings->activate (k, Bindings::Press)) {
5855                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5856                                 return true;
5857                         }
5858
5859                         if (binding_widget) {
5860                                 binding_widget = gtk_widget_get_parent (binding_widget);
5861                                 if (binding_widget) {
5862                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5863                                 } else {
5864                                         bindings = 0;
5865                                 }
5866                         } else {
5867                                 bindings = 0;
5868                         }
5869                 }
5870
5871                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5872
5873                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5874                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5875                         return true;
5876                 }
5877         }
5878
5879         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5880         return true;
5881 }
5882
5883 void
5884 ARDOUR_UI::load_bindings ()
5885 {
5886         if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
5887                 error << _("Global keybindings are missing") << endmsg;
5888         }
5889 }
5890
5891 void
5892 ARDOUR_UI::cancel_solo ()
5893 {
5894         if (_session) {
5895                 _session->cancel_all_solo ();
5896         }
5897 }
5898
5899 void
5900 ARDOUR_UI::reset_focus (Gtk::Widget* w)
5901 {
5902         /* this resets focus to the first focusable parent of the given widget,
5903          * or, if there is no focusable parent, cancels focus in the toplevel
5904          * window that the given widget is packed into (if there is one).
5905          */
5906
5907         if (!w) {
5908                 return;
5909         }
5910
5911         Gtk::Widget* top = w->get_toplevel();
5912
5913         if (!top || !top->is_toplevel()) {
5914                 return;
5915         }
5916
5917         w = w->get_parent ();
5918
5919         while (w) {
5920
5921                 if (w->is_toplevel()) {
5922                         /* Setting the focus widget to a Gtk::Window causes all
5923                          * subsequent calls to ::has_focus() on the nominal
5924                          * focus widget in that window to return
5925                          * false. Workaround: never set focus to the toplevel
5926                          * itself.
5927                          */
5928                         break;
5929                 }
5930
5931                 if (w->get_can_focus ()) {
5932                         Gtk::Window* win = dynamic_cast<Gtk::Window*> (top);
5933                         win->set_focus (*w);
5934                         return;
5935                 }
5936                 w = w->get_parent ();
5937         }
5938
5939         if (top == &_main_window) {
5940
5941         }
5942
5943         /* no focusable parent found, cancel focus in top level window.
5944            C++ API cannot be used for this. Thanks, references.
5945         */
5946
5947         gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0);
5948
5949 }