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