improve sysex data display.
[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_rewind (int option)
2402 {
2403         float current_transport_speed;
2404
2405         if (_session) {
2406                 current_transport_speed = _session->transport_speed();
2407
2408                 if (current_transport_speed >= 0.0f) {
2409                         switch (option) {
2410                         case 0:
2411                                 _session->request_transport_speed (-1.0f);
2412                                 break;
2413                         case 1:
2414                                 _session->request_transport_speed (-4.0f);
2415                                 break;
2416                         case -1:
2417                                 _session->request_transport_speed (-0.5f);
2418                                 break;
2419                         }
2420                 } else {
2421                         /* speed up */
2422                         _session->request_transport_speed (current_transport_speed * 1.5f);
2423                 }
2424         }
2425 }
2426
2427 void
2428 ARDOUR_UI::transport_forward (int option)
2429 {
2430         if (!_session) {
2431                 return;
2432         }
2433
2434         float current_transport_speed = _session->transport_speed();
2435
2436         if (current_transport_speed <= 0.0f) {
2437                 switch (option) {
2438                 case 0:
2439                         _session->request_transport_speed (1.0f);
2440                         break;
2441                 case 1:
2442                         _session->request_transport_speed (4.0f);
2443                         break;
2444                 case -1:
2445                         _session->request_transport_speed (0.5f);
2446                         break;
2447                 }
2448         } else {
2449                 /* speed up */
2450                 _session->request_transport_speed (current_transport_speed * 1.5f);
2451         }
2452 }
2453
2454 void
2455 ARDOUR_UI::toggle_record_enable (uint16_t rid)
2456 {
2457         if (!_session) {
2458                 return;
2459         }
2460
2461         boost::shared_ptr<Route> r;
2462
2463         if ((r = _session->get_remote_nth_route (rid)) != 0) {
2464
2465                 boost::shared_ptr<Track> t;
2466
2467                 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2468                         t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), Controllable::UseGroup);
2469                 }
2470         }
2471 }
2472
2473 void
2474 ARDOUR_UI::map_transport_state ()
2475 {
2476         if (!_session) {
2477                 auto_loop_button.unset_active_state ();
2478                 play_selection_button.unset_active_state ();
2479                 roll_button.unset_active_state ();
2480                 stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
2481                 layered_button.set_sensitive (false);
2482                 return;
2483         }
2484
2485         shuttle_box.map_transport_state ();
2486
2487         float sp = _session->transport_speed();
2488
2489         if (sp != 0.0f) {
2490
2491                 /* we're rolling */
2492
2493                 if (_session->get_play_range()) {
2494
2495                         play_selection_button.set_active_state (Gtkmm2ext::ExplicitActive);
2496                         roll_button.unset_active_state ();
2497                         auto_loop_button.unset_active_state ();
2498
2499                 } else if (_session->get_play_loop ()) {
2500
2501                         auto_loop_button.set_active (true);
2502                         play_selection_button.set_active (false);
2503                         if (Config->get_loop_is_mode()) {
2504                                 roll_button.set_active (true);
2505                         } else {
2506                                 roll_button.set_active (false);
2507                         }
2508
2509                 } else {
2510
2511                         roll_button.set_active (true);
2512                         play_selection_button.set_active (false);
2513                         auto_loop_button.set_active (false);
2514                 }
2515
2516                 if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
2517                         /* light up both roll and play-selection if they are joined */
2518                         roll_button.set_active (true);
2519                         play_selection_button.set_active (true);
2520                 }
2521                 layered_button.set_sensitive (!_session->actively_recording ());
2522
2523                 stop_button.set_active (false);
2524
2525         } else {
2526
2527                 layered_button.set_sensitive (true);
2528                 stop_button.set_active (true);
2529                 roll_button.set_active (false);
2530                 play_selection_button.set_active (false);
2531                 if (Config->get_loop_is_mode ()) {
2532                         auto_loop_button.set_active (_session->get_play_loop());
2533                 } else {
2534                         auto_loop_button.set_active (false);
2535                 }
2536                 update_disk_space ();
2537         }
2538 }
2539
2540 void
2541 ARDOUR_UI::blink_handler (bool blink_on)
2542 {
2543         transport_rec_enable_blink (blink_on);
2544         solo_blink (blink_on);
2545         sync_blink (blink_on);
2546         audition_blink (blink_on);
2547         feedback_blink (blink_on);
2548         error_blink (blink_on);
2549 }
2550
2551 void
2552 ARDOUR_UI::update_clocks ()
2553 {
2554         if (!_session) return;
2555
2556         if (editor && !editor->dragging_playhead()) {
2557                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
2558         }
2559 }
2560
2561 void
2562 ARDOUR_UI::start_clocking ()
2563 {
2564         if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2565                 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2566         } else {
2567                 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2568         }
2569 }
2570
2571 void
2572 ARDOUR_UI::stop_clocking ()
2573 {
2574         clock_signal_connection.disconnect ();
2575 }
2576
2577 bool
2578 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2579 {
2580         char buf[256];
2581
2582         snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2583
2584         label->set_text (buf);
2585         bar->set_fraction (fraction);
2586
2587         /* process events, redraws, etc. */
2588
2589         while (gtk_events_pending()) {
2590                 gtk_main_iteration ();
2591         }
2592
2593         return true; /* continue with save-as */
2594 }
2595
2596 void
2597 ARDOUR_UI::save_session_as ()
2598 {
2599         if (!_session) {
2600                 return;
2601         }
2602
2603         if (!save_as_dialog) {
2604                 save_as_dialog = new SaveAsDialog;
2605         }
2606
2607         save_as_dialog->set_name (_session->name());
2608
2609         int response = save_as_dialog->run ();
2610
2611         save_as_dialog->hide ();
2612
2613         switch (response) {
2614         case Gtk::RESPONSE_OK:
2615                 break;
2616         default:
2617                 return;
2618         }
2619
2620
2621         Session::SaveAs sa;
2622
2623         sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2624         sa.new_name = save_as_dialog->new_name ();
2625         sa.switch_to = save_as_dialog->switch_to();
2626         sa.copy_media = save_as_dialog->copy_media();
2627         sa.copy_external = save_as_dialog->copy_external();
2628         sa.include_media = save_as_dialog->include_media ();
2629
2630         /* Only bother with a progress dialog if we're going to copy
2631            media into the save-as target. Without that choice, this
2632            will be very fast because we're only talking about a few kB's to
2633            perhaps a couple of MB's of data.
2634         */
2635
2636         ArdourDialog progress_dialog (_("Save As"), true);
2637
2638         if (sa.include_media && sa.copy_media) {
2639
2640                 Gtk::Label label;
2641                 Gtk::ProgressBar progress_bar;
2642
2643                 progress_dialog.get_vbox()->pack_start (label);
2644                 progress_dialog.get_vbox()->pack_start (progress_bar);
2645                 label.show ();
2646                 progress_bar.show ();
2647
2648                 /* this signal will be emitted from within this, the calling thread,
2649                  * after every file is copied. It provides information on percentage
2650                  * complete (in terms of total data to copy), the number of files
2651                  * copied so far, and the total number to copy.
2652                  */
2653
2654                 ScopedConnection c;
2655
2656                 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
2657
2658                 progress_dialog.show_all ();
2659                 progress_dialog.present ();
2660         }
2661
2662         if (_session->save_as (sa)) {
2663                 /* ERROR MESSAGE */
2664                 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2665                 msg.run ();
2666         }
2667
2668         if (!sa.include_media) {
2669                 unload_session (false);
2670                 load_session (sa.final_session_folder_name, sa.new_name);
2671         }
2672 }
2673
2674 void
2675 ARDOUR_UI::archive_session ()
2676 {
2677         if (!_session) {
2678                 return;
2679         }
2680
2681         time_t n;
2682         time (&n);
2683         Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
2684
2685         SessionArchiveDialog sad;
2686         sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
2687         int response = sad.run ();
2688
2689         if (response != Gtk::RESPONSE_OK) {
2690                 sad.hide ();
2691                 return;
2692         }
2693
2694         if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.only_used_sources (), &sad)) {
2695                 MessageDialog msg (_("Session Archiving failed."));
2696                 msg.run ();
2697         }
2698 }
2699
2700 void
2701 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2702 {
2703                 char timebuf[128];
2704                 time_t n;
2705                 struct tm local_time;
2706
2707                 time (&n);
2708                 localtime_r (&n, &local_time);
2709                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2710
2711                 save_state (timebuf, switch_to_it);
2712 }
2713
2714
2715 bool
2716 ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
2717 {
2718         string snapname;
2719
2720         prompter.get_result (snapname);
2721
2722         bool do_save = (snapname.length() != 0);
2723
2724         if (do_save) {
2725                 char illegal = Session::session_name_is_legal(snapname);
2726                 if (illegal) {
2727                         MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2728                                              "snapshot names may not contain a '%1' character"), illegal));
2729                         msg.run ();
2730                         return false;
2731                 }
2732         }
2733
2734         vector<std::string> p;
2735         get_state_files_in_directory (_session->session_directory().root_path(), p);
2736         vector<string> n = get_file_names_no_extension (p);
2737
2738         if (find (n.begin(), n.end(), snapname) != n.end()) {
2739
2740                 do_save = overwrite_file_dialog (prompter,
2741                                                  _("Confirm Snapshot Overwrite"),
2742                                                  _("A snapshot already exists with that name. Do you want to overwrite it?"));
2743         }
2744
2745         if (do_save) {
2746                 save_state (snapname, switch_to_it);
2747         }
2748         else {
2749                 return false;
2750         }
2751
2752         return true;
2753 }
2754
2755
2756 /** Ask the user for the name of a new snapshot and then take it.
2757  */
2758
2759 void
2760 ARDOUR_UI::snapshot_session (bool switch_to_it)
2761 {
2762         ArdourPrompter prompter (true);
2763
2764         prompter.set_name ("Prompter");
2765         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2766         if (switch_to_it) {
2767                 prompter.set_title (_("Snapshot and switch"));
2768                 prompter.set_prompt (_("New session name"));
2769         } else {
2770                 prompter.set_title (_("Take Snapshot"));
2771                 prompter.set_prompt (_("Name of new snapshot"));
2772         }
2773
2774         if (switch_to_it) {
2775                 prompter.set_initial_text (_session->snap_name());
2776         } else {
2777                 Glib::DateTime tm (g_date_time_new_now_local ());
2778                 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
2779         }
2780
2781         bool finished = false;
2782         while (!finished) {
2783                 switch (prompter.run()) {
2784                 case RESPONSE_ACCEPT:
2785                 {
2786                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
2787                         break;
2788                 }
2789
2790                 default:
2791                         finished = true;
2792                         break;
2793                 }
2794         }
2795 }
2796
2797 /** Ask the user for a new session name and then rename the session to it.
2798  */
2799
2800 void
2801 ARDOUR_UI::rename_session ()
2802 {
2803         if (!_session) {
2804                 return;
2805         }
2806
2807         ArdourPrompter prompter (true);
2808         string name;
2809
2810         prompter.set_name ("Prompter");
2811         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2812         prompter.set_title (_("Rename Session"));
2813         prompter.set_prompt (_("New session name"));
2814
2815   again:
2816         switch (prompter.run()) {
2817         case RESPONSE_ACCEPT:
2818         {
2819                 prompter.get_result (name);
2820
2821                 bool do_rename = (name.length() != 0);
2822
2823                 if (do_rename) {
2824                         char illegal = Session::session_name_is_legal (name);
2825
2826                         if (illegal) {
2827                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2828                                                                      "session names may not contain a '%1' character"), illegal));
2829                                 msg.run ();
2830                                 goto again;
2831                         }
2832
2833                         switch (_session->rename (name)) {
2834                         case -1: {
2835                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2836                                 msg.set_position (WIN_POS_MOUSE);
2837                                 msg.run ();
2838                                 goto again;
2839                                 break;
2840                         }
2841                         case 0:
2842                                 break;
2843                         default: {
2844                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2845                                 msg.set_position (WIN_POS_MOUSE);
2846                                 msg.run ();
2847                                 break;
2848                         }
2849                         }
2850                 }
2851
2852                 break;
2853         }
2854
2855         default:
2856                 break;
2857         }
2858 }
2859
2860 void
2861 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2862 {
2863         if (!_session || _session->deletion_in_progress()) {
2864                 return;
2865         }
2866
2867         XMLNode* node = new XMLNode (X_("UI"));
2868
2869         WM::Manager::instance().add_state (*node);
2870
2871         node->add_child_nocopy (gui_object_state->get_state());
2872
2873         _session->add_extra_xml (*node);
2874
2875         if (export_video_dialog) {
2876                 _session->add_extra_xml (export_video_dialog->get_state());
2877         }
2878
2879         save_state_canfail (name, switch_to_it);
2880 }
2881
2882 int
2883 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2884 {
2885         if (_session) {
2886                 int ret;
2887
2888                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2889                         return ret;
2890                 }
2891         }
2892
2893         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2894         return 0;
2895 }
2896
2897 void
2898 ARDOUR_UI::primary_clock_value_changed ()
2899 {
2900         if (_session) {
2901                 _session->request_locate (primary_clock->current_time ());
2902         }
2903 }
2904
2905 void
2906 ARDOUR_UI::big_clock_value_changed ()
2907 {
2908         if (_session) {
2909                 _session->request_locate (big_clock->current_time ());
2910         }
2911 }
2912
2913 void
2914 ARDOUR_UI::secondary_clock_value_changed ()
2915 {
2916         if (_session) {
2917                 _session->request_locate (secondary_clock->current_time ());
2918         }
2919 }
2920
2921 void
2922 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2923 {
2924         if (_session == 0) {
2925                 return;
2926         }
2927
2928         if (_session->step_editing()) {
2929                 return;
2930         }
2931
2932         Session::RecordState const r = _session->record_status ();
2933         bool const h = _session->have_rec_enabled_track ();
2934
2935         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2936                 if (onoff) {
2937                         rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2938                 } else {
2939                         rec_button.set_active_state (Gtkmm2ext::Off);
2940                 }
2941         } else if (r == Session::Recording && h) {
2942                 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2943         } else {
2944                 rec_button.unset_active_state ();
2945         }
2946 }
2947
2948 bool
2949 ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
2950 {
2951         string name;
2952
2953         prompter.get_result (name);
2954
2955         if (name.length()) {
2956                 int failed = _session->save_template (name);
2957
2958                 if (failed == -2) { /* file already exists. */
2959                         bool overwrite = overwrite_file_dialog (prompter,
2960                                                                 _("Confirm Template Overwrite"),
2961                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
2962
2963                         if (overwrite) {
2964                                 _session->save_template (name, true);
2965                         }
2966                         else {
2967                                 return false;
2968                         }
2969                 }
2970         }
2971
2972         return true;
2973 }
2974
2975 void
2976 ARDOUR_UI::save_template ()
2977 {
2978         ArdourPrompter prompter (true);
2979
2980         if (!check_audioengine (_main_window)) {
2981                 return;
2982         }
2983
2984         prompter.set_name (X_("Prompter"));
2985         prompter.set_title (_("Save Template"));
2986         prompter.set_prompt (_("Name for template:"));
2987         prompter.set_initial_text(_session->name() + _("-template"));
2988         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2989
2990         bool finished = false;
2991         while (!finished) {
2992                 switch (prompter.run()) {
2993                 case RESPONSE_ACCEPT:
2994                         finished = process_save_template_prompter (prompter);
2995                         break;
2996
2997                 default:
2998                         finished = true;
2999                         break;
3000                 }
3001         }
3002 }
3003
3004 void
3005 ARDOUR_UI::edit_metadata ()
3006 {
3007         SessionMetadataEditor dialog;
3008         dialog.set_session (_session);
3009         dialog.grab_focus ();
3010         dialog.run ();
3011 }
3012
3013 void
3014 ARDOUR_UI::import_metadata ()
3015 {
3016         SessionMetadataImporter dialog;
3017         dialog.set_session (_session);
3018         dialog.run ();
3019 }
3020
3021 bool
3022 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
3023 {
3024         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
3025
3026         MessageDialog msg (str,
3027                            false,
3028                            Gtk::MESSAGE_WARNING,
3029                            Gtk::BUTTONS_YES_NO,
3030                            true);
3031
3032
3033         msg.set_name (X_("OpenExistingDialog"));
3034         msg.set_title (_("Open Existing Session"));
3035         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
3036         msg.set_position (Gtk::WIN_POS_CENTER);
3037         pop_back_splash (msg);
3038
3039         switch (msg.run()) {
3040         case RESPONSE_YES:
3041                 return true;
3042                 break;
3043         }
3044         return false;
3045 }
3046
3047 int
3048 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
3049 {
3050         BusProfile bus_profile;
3051
3052         if (nsm) {
3053
3054                 bus_profile.master_out_channels = 2;
3055                 bus_profile.input_ac = AutoConnectPhysical;
3056                 bus_profile.output_ac = AutoConnectMaster;
3057                 bus_profile.requested_physical_in = 0; // use all available
3058                 bus_profile.requested_physical_out = 0; // use all available
3059
3060         } else {
3061
3062                 /* get settings from advanced section of NSD */
3063
3064                 if (sd.create_master_bus()) {
3065                         bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
3066                 } else {
3067                         bus_profile.master_out_channels = 0;
3068                 }
3069
3070                 if (sd.connect_inputs()) {
3071                         bus_profile.input_ac = AutoConnectPhysical;
3072                 } else {
3073                         bus_profile.input_ac = AutoConnectOption (0);
3074                 }
3075
3076                 bus_profile.output_ac = AutoConnectOption (0);
3077
3078                 if (sd.connect_outputs ()) {
3079                         if (sd.connect_outs_to_master()) {
3080                                 bus_profile.output_ac = AutoConnectMaster;
3081                         } else if (sd.connect_outs_to_physical()) {
3082                                 bus_profile.output_ac = AutoConnectPhysical;
3083                         }
3084                 }
3085
3086                 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
3087                 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
3088         }
3089
3090         if (build_session (session_path, session_name, bus_profile)) {
3091                 return -1;
3092         }
3093
3094         return 0;
3095 }
3096
3097 void
3098 ARDOUR_UI::load_from_application_api (const std::string& path)
3099 {
3100         /* OS X El Capitan (and probably later) now somehow passes the command
3101            line arguments to an app via the openFile delegate protocol. Ardour 
3102            already does its own command line processing, and having both
3103            pathways active causes crashes. So, if the command line was already
3104            set, do nothing here.
3105         */
3106
3107         if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3108                 return;
3109         }
3110
3111         ARDOUR_COMMAND_LINE::session_name = path;
3112
3113         /* Cancel SessionDialog if it's visible to make OSX delegates work.
3114          *
3115          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
3116          * race-condition:
3117          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
3118          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
3119          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
3120          *    -> SessionDialog is not displayed
3121          */
3122
3123         if (_session_dialog) {
3124                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3125                 std::string session_path = path;
3126                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
3127                         session_path = Glib::path_get_dirname (session_path);
3128                 }
3129                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
3130                 _session_dialog->set_provided_session (session_name, session_path);
3131                 _session_dialog->response (RESPONSE_NONE);
3132                 _session_dialog->hide();
3133                 return;
3134         }
3135
3136         int rv;
3137         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
3138                 /* /path/to/foo => /path/to/foo, foo */
3139                 rv = load_session (path, basename_nosuffix (path));
3140         } else {
3141                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
3142                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
3143         }
3144
3145         // if load_session fails -> pop up SessionDialog.
3146         if (rv) {
3147                 ARDOUR_COMMAND_LINE::session_name = "";
3148
3149                 if (get_session_parameters (true, false)) {
3150                         exit (1);
3151                 }
3152         }
3153 }
3154
3155 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
3156 int
3157 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
3158 {
3159         string session_name;
3160         string session_path;
3161         string template_name;
3162         int ret = -1;
3163         bool likely_new = false;
3164         bool cancel_not_quit;
3165
3166         /* deal with any existing DIRTY session now, rather than later. don't
3167          * treat a non-dirty session this way, so that it stays visible
3168          * as we bring up the new session dialog.
3169          */
3170
3171         if (_session && ARDOUR_UI::instance()->video_timeline) {
3172                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
3173         }
3174
3175         /* if there is already a session, relabel the button
3176            on the SessionDialog so that we don't Quit directly
3177         */
3178         cancel_not_quit = (_session != 0);
3179
3180         if (_session && _session->dirty()) {
3181                 if (unload_session (false)) {
3182                         /* unload cancelled by user */
3183                         return 0;
3184                 }
3185                 ARDOUR_COMMAND_LINE::session_name = "";
3186         }
3187
3188         if (!load_template.empty()) {
3189                 should_be_new = true;
3190                 template_name = load_template;
3191         }
3192
3193         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3194         session_path = ARDOUR_COMMAND_LINE::session_name;
3195
3196         if (!session_path.empty()) {
3197                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3198                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3199                                 /* session/snapshot file, change path to be dir */
3200                                 session_path = Glib::path_get_dirname (session_path);
3201                         }
3202                 }
3203         }
3204
3205         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3206
3207         _session_dialog = &session_dialog;
3208         while (ret != 0) {
3209
3210                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3211
3212                         /* if they named a specific statefile, use it, otherwise they are
3213                            just giving a session folder, and we want to use it as is
3214                            to find the session.
3215                         */
3216
3217                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3218
3219                         if (suffix != string::npos) {
3220                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3221                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3222                                 session_name = Glib::path_get_basename (session_name);
3223                         } else {
3224                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3225                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3226                         }
3227                 } else {
3228                         session_path = "";
3229                         session_name = "";
3230                         session_dialog.clear_given ();
3231                 }
3232
3233                 if (should_be_new || session_name.empty()) {
3234                         /* need the dialog to get info from user */
3235
3236                         cerr << "run dialog\n";
3237
3238                         switch (session_dialog.run()) {
3239                         case RESPONSE_ACCEPT:
3240                                 break;
3241                         case RESPONSE_NONE:
3242                                 /* this is used for async * app->ShouldLoad(). */
3243                                 continue; // while loop
3244                                 break;
3245                         default:
3246                                 if (quit_on_cancel) {
3247                                         // JE - Currently (July 2014) this section can only get reached if the
3248                                         // user quits from the main 'Session Setup' dialog (i.e. reaching this
3249                                         // point does NOT indicate an abnormal termination). Therefore, let's
3250                                         // behave gracefully (i.e. let's do some cleanup) before we call exit()
3251                                         ARDOUR::cleanup ();
3252                                         pthread_cancel_all ();
3253
3254                                         exit (1);
3255                                 } else {
3256                                         return ret;
3257                                 }
3258                         }
3259
3260                         session_dialog.hide ();
3261                 }
3262
3263                 /* if we run the startup dialog again, offer more than just "new session" */
3264
3265                 should_be_new = false;
3266
3267                 session_name = session_dialog.session_name (likely_new);
3268                 session_path = session_dialog.session_folder ();
3269
3270                 if (nsm) {
3271                         likely_new = true;
3272                 }
3273
3274                 if (!likely_new) {
3275                         int rv = ARDOUR::inflate_session (session_name,
3276                                         Config->get_default_session_parent_dir(), session_path, session_name);
3277                         if (rv < 0) {
3278                                 MessageDialog msg (session_dialog,
3279                                         string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
3280                                 msg.run ();
3281                                 continue;
3282                         }
3283                         else if (rv == 0) {
3284                                 session_dialog.set_provided_session (session_name, session_path);
3285                         }
3286                 }
3287
3288                 // XXX check archive, inflate
3289                 string::size_type suffix = session_name.find (statefile_suffix);
3290
3291                 if (suffix != string::npos) {
3292                         session_name = session_name.substr (0, suffix);
3293                 }
3294
3295                 /* this shouldn't happen, but we catch it just in case it does */
3296
3297                 if (session_name.empty()) {
3298                         continue;
3299                 }
3300
3301                 if (session_dialog.use_session_template()) {
3302                         template_name = session_dialog.session_template_name();
3303                         _session_is_new = true;
3304                 }
3305
3306                 if (session_name[0] == G_DIR_SEPARATOR ||
3307 #ifdef PLATFORM_WINDOWS
3308                     (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3309 #else
3310                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3311                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3312 #endif
3313                          )
3314                 {
3315
3316                         /* absolute path or cwd-relative path specified for session name: infer session folder
3317                            from what was given.
3318                         */
3319
3320                         session_path = Glib::path_get_dirname (session_name);
3321                         session_name = Glib::path_get_basename (session_name);
3322
3323                 } else {
3324
3325                         session_path = session_dialog.session_folder();
3326
3327                         char illegal = Session::session_name_is_legal (session_name);
3328
3329                         if (illegal) {
3330                                 MessageDialog msg (session_dialog,
3331                                                    string_compose (_("To ensure compatibility with various systems\n"
3332                                                                      "session names may not contain a '%1' character"),
3333                                                                    illegal));
3334                                 msg.run ();
3335                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3336                                 continue;
3337                         }
3338                 }
3339
3340                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3341
3342
3343                         if (likely_new && !nsm) {
3344
3345                                 std::string existing = Glib::build_filename (session_path, session_name);
3346
3347                                 if (!ask_about_loading_existing_session (existing)) {
3348                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3349                                         continue;
3350                                 }
3351                         }
3352
3353                         _session_is_new = false;
3354
3355                 } else {
3356
3357                         if (!likely_new) {
3358                                 pop_back_splash (session_dialog);
3359                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3360                                 msg.run ();
3361                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3362                                 continue;
3363                         }
3364
3365                         char illegal = Session::session_name_is_legal(session_name);
3366
3367                         if (illegal) {
3368                                 pop_back_splash (session_dialog);
3369                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3370                                                                                     "session names may not contain a '%1' character"), illegal));
3371                                 msg.run ();
3372                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3373                                 continue;
3374                         }
3375
3376                         _session_is_new = true;
3377                 }
3378
3379                 if (likely_new && template_name.empty()) {
3380
3381                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3382
3383                 } else {
3384
3385                         ret = load_session (session_path, session_name, template_name);
3386
3387                         if (ret == -2) {
3388                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3389                                 exit (1);
3390                         }
3391
3392                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3393                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3394                                 exit (1);
3395                         }
3396
3397                         /* clear this to avoid endless attempts to load the
3398                            same session.
3399                         */
3400
3401                         ARDOUR_COMMAND_LINE::session_name = "";
3402                 }
3403         }
3404
3405         _session_dialog = NULL;
3406
3407         return ret;
3408 }
3409
3410 void
3411 ARDOUR_UI::close_session()
3412 {
3413         if (!check_audioengine (_main_window)) {
3414                 return;
3415         }
3416
3417         if (unload_session (true)) {
3418                 return;
3419         }
3420
3421         ARDOUR_COMMAND_LINE::session_name = "";
3422
3423         if (get_session_parameters (true, false)) {
3424                 exit (1);
3425         }
3426         if (splash && splash->is_visible()) {
3427                 // in 1 second, hide the splash screen
3428                 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
3429         }
3430 }
3431
3432 /** @param snap_name Snapshot name (without .ardour suffix).
3433  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3434  */
3435 int
3436 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3437 {
3438         Session *new_session;
3439         int unload_status;
3440         int retval = -1;
3441
3442         if (_session) {
3443                 unload_status = unload_session ();
3444
3445                 if (unload_status < 0) {
3446                         goto out;
3447                 } else if (unload_status > 0) {
3448                         retval = 0;
3449                         goto out;
3450                 }
3451         }
3452
3453         session_loaded = false;
3454
3455         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3456
3457         try {
3458                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3459         }
3460
3461         /* this one is special */
3462
3463         catch (AudioEngine::PortRegistrationFailure& err) {
3464
3465                 MessageDialog msg (err.what(),
3466                                    true,
3467                                    Gtk::MESSAGE_INFO,
3468                                    Gtk::BUTTONS_CLOSE);
3469
3470                 msg.set_title (_("Port Registration Error"));
3471                 msg.set_secondary_text (_("Click the Close button to try again."));
3472                 msg.set_position (Gtk::WIN_POS_CENTER);
3473                 pop_back_splash (msg);
3474                 msg.present ();
3475
3476                 int response = msg.run ();
3477
3478                 msg.hide ();
3479
3480                 switch (response) {
3481                 case RESPONSE_CANCEL:
3482                         exit (1);
3483                 default:
3484                         break;
3485                 }
3486                 goto out;
3487         }
3488         catch (SessionException e) {
3489                 MessageDialog msg (string_compose(
3490                                            _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3491                                            path, snap_name, e.what()),
3492                                    true,
3493                                    Gtk::MESSAGE_INFO,
3494                                    BUTTONS_OK);
3495
3496                 msg.set_title (_("Loading Error"));
3497                 msg.set_position (Gtk::WIN_POS_CENTER);
3498                 pop_back_splash (msg);
3499                 msg.present ();
3500
3501                 dump_errors (cerr);
3502
3503                 (void) msg.run ();
3504                 msg.hide ();
3505
3506                 goto out;
3507         }
3508         catch (...) {
3509
3510                 MessageDialog msg (string_compose(
3511                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
3512                                            path, snap_name),
3513                                    true,
3514                                    Gtk::MESSAGE_INFO,
3515                                    BUTTONS_OK);
3516
3517                 msg.set_title (_("Loading Error"));
3518                 msg.set_position (Gtk::WIN_POS_CENTER);
3519                 pop_back_splash (msg);
3520                 msg.present ();
3521
3522                 dump_errors (cerr);
3523
3524                 (void) msg.run ();
3525                 msg.hide ();
3526
3527                 goto out;
3528         }
3529
3530         {
3531                 list<string> const u = new_session->unknown_processors ();
3532                 if (!u.empty()) {
3533                         MissingPluginDialog d (_session, u);
3534                         d.run ();
3535                 }
3536         }
3537
3538         if (!new_session->writable()) {
3539                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3540                                    true,
3541                                    Gtk::MESSAGE_INFO,
3542                                    BUTTONS_OK);
3543
3544                 msg.set_title (_("Read-only Session"));
3545                 msg.set_position (Gtk::WIN_POS_CENTER);
3546                 pop_back_splash (msg);
3547                 msg.present ();
3548                 (void) msg.run ();
3549                 msg.hide ();
3550         }
3551
3552         set_session (new_session);
3553
3554         session_loaded = true;
3555
3556         if (_session) {
3557                 _session->set_clean ();
3558         }
3559
3560 #ifdef WINDOWS_VST_SUPPORT
3561         fst_stop_threading();
3562 #endif
3563
3564         {
3565                 Timers::TimerSuspender t;
3566                 flush_pending (10);
3567         }
3568
3569 #ifdef WINDOWS_VST_SUPPORT
3570         fst_start_threading();
3571 #endif
3572         retval = 0;
3573
3574   out:
3575         return retval;
3576 }
3577
3578 int
3579 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3580 {
3581         Session *new_session;
3582         int x;
3583
3584         session_loaded = false;
3585         x = unload_session ();
3586
3587         if (x < 0) {
3588                 return -1;
3589         } else if (x > 0) {
3590                 return 0;
3591         }
3592
3593         _session_is_new = true;
3594
3595         try {
3596                 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3597         }
3598
3599         catch (SessionException e) {
3600                 cerr << "Here are the errors associated with this failed session:\n";
3601                 dump_errors (cerr);
3602                 cerr << "---------\n";
3603                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3604                 msg.set_title (_("Loading Error"));
3605                 msg.set_position (Gtk::WIN_POS_CENTER);
3606                 pop_back_splash (msg);
3607                 msg.run ();
3608                 return -1;
3609         }
3610         catch (...) {
3611                 cerr << "Here are the errors associated with this failed session:\n";
3612                 dump_errors (cerr);
3613                 cerr << "---------\n";
3614                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3615                 msg.set_title (_("Loading Error"));
3616                 msg.set_position (Gtk::WIN_POS_CENTER);
3617                 pop_back_splash (msg);
3618                 msg.run ();
3619                 return -1;
3620         }
3621
3622         /* Give the new session the default GUI state, if such things exist */
3623
3624         XMLNode* n;
3625         n = Config->instant_xml (X_("Editor"));
3626         if (n) {
3627                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3628                 new_session->add_instant_xml (*n, false);
3629         }
3630         n = Config->instant_xml (X_("Mixer"));
3631         if (n) {
3632                 new_session->add_instant_xml (*n, false);
3633         }
3634
3635         n = Config->instant_xml (X_("Preferences"));
3636         if (n) {
3637                 new_session->add_instant_xml (*n, false);
3638         }
3639
3640         /* Put the playhead at 0 and scroll fully left */
3641         n = new_session->instant_xml (X_("Editor"));
3642         if (n) {
3643                 n->add_property (X_("playhead"), X_("0"));
3644                 n->add_property (X_("left-frame"), X_("0"));
3645         }
3646
3647         set_session (new_session);
3648
3649         session_loaded = true;
3650
3651         new_session->save_state(new_session->name());
3652
3653         return 0;
3654 }
3655
3656 void
3657 ARDOUR_UI::launch_chat ()
3658 {
3659         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3660
3661         dialog.set_title (_("About the Chat"));
3662         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."));
3663
3664         switch (dialog.run()) {
3665         case RESPONSE_OK:
3666 #ifdef __APPLE__
3667                 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3668 #elif defined PLATFORM_WINDOWS
3669                 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3670 #else
3671                 open_uri("http://webchat.freenode.net/?channels=ardour");
3672 #endif
3673                 break;
3674         default:
3675                 break;
3676         }
3677 }
3678
3679 void
3680 ARDOUR_UI::launch_manual ()
3681 {
3682         PBD::open_uri (Config->get_tutorial_manual_url());
3683 }
3684
3685 void
3686 ARDOUR_UI::launch_reference ()
3687 {
3688         PBD::open_uri (Config->get_reference_manual_url());
3689 }
3690
3691 void
3692 ARDOUR_UI::launch_tracker ()
3693 {
3694         PBD::open_uri ("http://tracker.ardour.org");
3695 }
3696
3697 void
3698 ARDOUR_UI::launch_subscribe ()
3699 {
3700         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3701 }
3702
3703 void
3704 ARDOUR_UI::launch_cheat_sheet ()
3705 {
3706 #ifdef __APPLE__
3707         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3708 #else
3709         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3710 #endif
3711 }
3712
3713 void
3714 ARDOUR_UI::launch_website ()
3715 {
3716         PBD::open_uri ("http://ardour.org");
3717 }
3718
3719 void
3720 ARDOUR_UI::launch_website_dev ()
3721 {
3722         PBD::open_uri ("http://ardour.org/development.html");
3723 }
3724
3725 void
3726 ARDOUR_UI::launch_forums ()
3727 {
3728         PBD::open_uri ("https://community.ardour.org/forums");
3729 }
3730
3731 void
3732 ARDOUR_UI::launch_howto_report ()
3733 {
3734         PBD::open_uri ("http://ardour.org/reporting_bugs");
3735 }
3736
3737 void
3738 ARDOUR_UI::loading_message (const std::string& msg)
3739 {
3740         if (ARDOUR_COMMAND_LINE::no_splash) {
3741                 return;
3742         }
3743
3744         if (!splash) {
3745                 show_splash ();
3746         }
3747
3748         splash->message (msg);
3749 }
3750
3751 void
3752 ARDOUR_UI::show_splash ()
3753 {
3754         if (splash == 0) {
3755                 try {
3756                         splash = new Splash;
3757                 } catch (...) {
3758                         return;
3759                 }
3760         }
3761
3762         splash->display ();
3763 }
3764
3765 void
3766 ARDOUR_UI::hide_splash ()
3767 {
3768         delete splash;
3769         splash = 0;
3770 }
3771
3772 void
3773 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3774 {
3775         size_t removed;
3776
3777         removed = rep.paths.size();
3778
3779         if (removed == 0) {
3780                 MessageDialog msgd (_main_window,
3781                                     _("No files were ready for clean-up"),
3782                                     true,
3783                                     Gtk::MESSAGE_INFO,
3784                                     Gtk::BUTTONS_OK);
3785                 msgd.set_title (_("Clean-up"));
3786                 msgd.set_secondary_text (_("If this seems suprising, \n\
3787 check for any existing snapshots.\n\
3788 These may still include regions that\n\
3789 require some unused files to continue to exist."));
3790
3791                 msgd.run ();
3792                 return;
3793         }
3794
3795         ArdourDialog results (_("Clean-up"), true, false);
3796
3797         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3798             CleanupResultsModelColumns() {
3799                     add (visible_name);
3800                     add (fullpath);
3801             }
3802             Gtk::TreeModelColumn<std::string> visible_name;
3803             Gtk::TreeModelColumn<std::string> fullpath;
3804         };
3805
3806
3807         CleanupResultsModelColumns results_columns;
3808         Glib::RefPtr<Gtk::ListStore> results_model;
3809         Gtk::TreeView results_display;
3810
3811         results_model = ListStore::create (results_columns);
3812         results_display.set_model (results_model);
3813         results_display.append_column (list_title, results_columns.visible_name);
3814
3815         results_display.set_name ("CleanupResultsList");
3816         results_display.set_headers_visible (true);
3817         results_display.set_headers_clickable (false);
3818         results_display.set_reorderable (false);
3819
3820         Gtk::ScrolledWindow list_scroller;
3821         Gtk::Label txt;
3822         Gtk::VBox dvbox;
3823         Gtk::HBox dhbox;  // the hbox for the image and text
3824         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3825         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3826
3827         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3828
3829         const string dead_directory = _session->session_directory().dead_path();
3830
3831         /* subst:
3832            %1 - number of files removed
3833            %2 - location of "dead"
3834            %3 - size of files affected
3835            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3836         */
3837
3838         const char* bprefix;
3839         double space_adjusted = 0;
3840
3841         if (rep.space < 1000) {
3842                 bprefix = X_("");
3843                 space_adjusted = rep.space;
3844         } else if (rep.space < 1000000) {
3845                 bprefix = _("kilo");
3846                 space_adjusted = floorf((float)rep.space / 1000.0);
3847         } else if (rep.space < 1000000 * 1000) {
3848                 bprefix = _("mega");
3849                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
3850         } else {
3851                 bprefix = _("giga");
3852                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
3853         }
3854
3855         if (msg_delete) {
3856                 txt.set_markup (string_compose (P_("\
3857 The following file was deleted from %2,\n\
3858 releasing %3 %4bytes of disk space", "\
3859 The following %1 files were deleted from %2,\n\
3860 releasing %3 %4bytes of disk space", removed),
3861                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3862         } else {
3863                 txt.set_markup (string_compose (P_("\
3864 The following file was not in use and \n\
3865 has been moved to: %2\n\n\
3866 After a restart of %5\n\n\
3867 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3868 will release an additional %3 %4bytes of disk space.\n", "\
3869 The following %1 files were not in use and \n\
3870 have been moved to: %2\n\n\
3871 After a restart of %5\n\n\
3872 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3873 will release an additional %3 %4bytes of disk space.\n", removed),
3874                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3875         }
3876
3877         dhbox.pack_start (*dimage, true, false, 5);
3878         dhbox.pack_start (txt, true, false, 5);
3879
3880         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3881                 TreeModel::Row row = *(results_model->append());
3882                 row[results_columns.visible_name] = *i;
3883                 row[results_columns.fullpath] = *i;
3884         }
3885
3886         list_scroller.add (results_display);
3887         list_scroller.set_size_request (-1, 150);
3888         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3889
3890         dvbox.pack_start (dhbox, true, false, 5);
3891         dvbox.pack_start (list_scroller, true, false, 5);
3892         ddhbox.pack_start (dvbox, true, false, 5);
3893
3894         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3895         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3896         results.set_default_response (RESPONSE_CLOSE);
3897         results.set_position (Gtk::WIN_POS_MOUSE);
3898
3899         results_display.show();
3900         list_scroller.show();
3901         txt.show();
3902         dvbox.show();
3903         dhbox.show();
3904         ddhbox.show();
3905         dimage->show();
3906
3907         //results.get_vbox()->show();
3908         results.set_resizable (false);
3909
3910         results.run ();
3911
3912 }
3913
3914 void
3915 ARDOUR_UI::cleanup ()
3916 {
3917         if (_session == 0) {
3918                 /* shouldn't happen: menu item is insensitive */
3919                 return;
3920         }
3921
3922
3923         MessageDialog checker (_("Are you sure you want to clean-up?"),
3924                                 true,
3925                                 Gtk::MESSAGE_QUESTION,
3926                                 Gtk::BUTTONS_NONE);
3927
3928         checker.set_title (_("Clean-up"));
3929
3930         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3931 ALL undo/redo information will be lost if you clean-up.\n\
3932 Clean-up will move all unused files to a \"dead\" location."));
3933
3934         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3935         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3936         checker.set_default_response (RESPONSE_CANCEL);
3937
3938         checker.set_name (_("CleanupDialog"));
3939         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3940         checker.set_position (Gtk::WIN_POS_MOUSE);
3941
3942         switch (checker.run()) {
3943         case RESPONSE_ACCEPT:
3944                 break;
3945         default:
3946                 return;
3947         }
3948
3949         ARDOUR::CleanupReport rep;
3950
3951         editor->prepare_for_cleanup ();
3952
3953         /* do not allow flush until a session is reloaded */
3954
3955         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3956         if (act) {
3957                 act->set_sensitive (false);
3958         }
3959
3960         if (_session->cleanup_sources (rep)) {
3961                 editor->finish_cleanup ();
3962                 return;
3963         }
3964
3965         editor->finish_cleanup ();
3966
3967         checker.hide();
3968         display_cleanup_results (rep, _("Cleaned Files"), false);
3969 }
3970
3971 void
3972 ARDOUR_UI::flush_trash ()
3973 {
3974         if (_session == 0) {
3975                 /* shouldn't happen: menu item is insensitive */
3976                 return;
3977         }
3978
3979         ARDOUR::CleanupReport rep;
3980
3981         if (_session->cleanup_trash_sources (rep)) {
3982                 return;
3983         }
3984
3985         display_cleanup_results (rep, _("deleted file"), true);
3986 }
3987
3988 void
3989 ARDOUR_UI::cleanup_peakfiles ()
3990 {
3991         if (_session == 0) {
3992                 /* shouldn't happen: menu item is insensitive */
3993                 return;
3994         }
3995
3996         if (! _session->can_cleanup_peakfiles ()) {
3997                 return;
3998         }
3999
4000         // get all region-views in this session
4001         RegionSelection rs;
4002         TrackViewList empty;
4003         empty.clear();
4004         editor->get_regions_after(rs, (framepos_t) 0, empty);
4005         std::list<RegionView*> views = rs.by_layer();
4006
4007         // remove displayed audio-region-views waveforms
4008         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4009                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4010                 if (!arv) { continue ; }
4011                 arv->delete_waves();
4012         }
4013
4014         // cleanup peak files:
4015         // - stop pending peakfile threads
4016         // - close peakfiles if any
4017         // - remove peak dir in session
4018         // - setup peakfiles (background thread)
4019         _session->cleanup_peakfiles ();
4020
4021         // re-add waves to ARV
4022         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4023                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4024                 if (!arv) { continue ; }
4025                 arv->create_waves();
4026         }
4027 }
4028
4029 PresentationInfo::order_t
4030 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
4031 {
4032         if (editor->get_selection().tracks.empty()) {
4033                 return PresentationInfo::max_order;
4034         }
4035
4036         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
4037
4038         /*
4039           we want the new routes to have their order keys set starting from
4040           the highest order key in the selection + 1 (if available).
4041         */
4042
4043         if (place == RouteDialogs::AfterSelection) {
4044                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
4045                 if (rtav) {
4046                         order_hint = rtav->route()->presentation_info().order();
4047                         order_hint++;
4048                 }
4049         } else if (place == RouteDialogs::BeforeSelection) {
4050                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
4051                 if (rtav) {
4052                         order_hint = rtav->route()->presentation_info().order();
4053                 }
4054         } else if (place == RouteDialogs::First) {
4055                 order_hint = 0;
4056         } else {
4057                 /* leave order_hint at max_order */
4058         }
4059
4060         return order_hint;
4061 }
4062
4063 void
4064 ARDOUR_UI::start_duplicate_routes ()
4065 {
4066         if (!duplicate_routes_dialog) {
4067                 duplicate_routes_dialog = new DuplicateRouteDialog;
4068         }
4069
4070         if (duplicate_routes_dialog->restart (_session)) {
4071                 return;
4072         }
4073
4074         duplicate_routes_dialog->present ();
4075 }
4076
4077 void
4078 ARDOUR_UI::add_route ()
4079 {
4080         if (!add_route_dialog.get (false)) {
4081                 add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_finished));
4082         }
4083
4084         if (!_session) {
4085                 return;
4086         }
4087
4088         if (add_route_dialog->is_visible()) {
4089                 /* we're already doing this */
4090                 return;
4091         }
4092
4093         add_route_dialog->set_position (WIN_POS_MOUSE);
4094         add_route_dialog->present();
4095 }
4096
4097 void
4098 ARDOUR_UI::add_route_dialog_finished (int r)
4099 {
4100         int count;
4101
4102         add_route_dialog->hide();
4103
4104         switch (r) {
4105                 case RESPONSE_ACCEPT:
4106                         break;
4107                 default:
4108                         return;
4109                         break;
4110         }
4111
4112         if ((count = add_route_dialog->count()) <= 0) {
4113                 return;
4114         }
4115
4116         PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
4117         string template_path = add_route_dialog->track_template();
4118         DisplaySuspender ds;
4119
4120         if (!template_path.empty()) {
4121                 if (add_route_dialog->name_template_is_default())  {
4122                         _session->new_route_from_template (count, order, template_path, string());
4123                 } else {
4124                         _session->new_route_from_template (count, order, template_path, add_route_dialog->name_template());
4125                 }
4126                 return;
4127         }
4128
4129         ChanCount input_chan= add_route_dialog->channels ();
4130         ChanCount output_chan;
4131         string name_template = add_route_dialog->name_template ();
4132         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
4133         RouteGroup* route_group = add_route_dialog->route_group ();
4134         AutoConnectOption oac = Config->get_output_auto_connect();
4135         bool strict_io = add_route_dialog->use_strict_io ();
4136
4137         if (oac & AutoConnectMaster) {
4138                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
4139                 output_chan.set (DataType::MIDI, 0);
4140         } else {
4141                 output_chan = input_chan;
4142         }
4143
4144         /* XXX do something with name template */
4145
4146         Session::ProcessorChangeBlocker pcb (_session);
4147
4148         switch (add_route_dialog->type_wanted()) {
4149         case AddRouteDialog::AudioTrack:
4150                 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order);
4151                 break;
4152         case AddRouteDialog::MidiTrack:
4153                 session_add_midi_track (route_group, count, name_template, strict_io, instrument, 0, order);
4154                 break;
4155         case AddRouteDialog::MixedTrack:
4156                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
4157                 break;
4158         case AddRouteDialog::AudioBus:
4159                 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io, order);
4160                 break;
4161         case AddRouteDialog::MidiBus:
4162                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
4163                 break;
4164         case AddRouteDialog::VCAMaster:
4165                 session_add_vca (name_template, count);
4166                 break;
4167         }
4168 }
4169
4170 void
4171 ARDOUR_UI::add_lua_script ()
4172 {
4173         if (!_session) {
4174                 return;
4175         }
4176
4177         LuaScriptInfoPtr spi;
4178         ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session);
4179         switch (ss.run ()) {
4180                 case Gtk::RESPONSE_ACCEPT:
4181                         spi = ss.script();
4182                         break;
4183                 default:
4184                         return;
4185         }
4186         ss.hide();
4187
4188         std::string script = "";
4189
4190         try {
4191                 script = Glib::file_get_contents (spi->path);
4192         } catch (Glib::FileError e) {
4193                 string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what());
4194                 MessageDialog am (msg);
4195                 am.run ();
4196                 return;
4197         }
4198
4199         LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params");
4200         std::vector<std::string> reg = _session->registered_lua_functions ();
4201
4202         ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp);
4203         switch (spd.run ()) {
4204                 case Gtk::RESPONSE_ACCEPT:
4205                         break;
4206                 default:
4207                         return;
4208         }
4209
4210         try {
4211                 _session->register_lua_function (spd.name(), script, lsp);
4212         } catch (luabridge::LuaException const& e) {
4213                 string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ());
4214                 MessageDialog am (msg);
4215                 am.run ();
4216         } catch (SessionException e) {
4217                 string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ());
4218                 MessageDialog am (msg);
4219                 am.run ();
4220         }
4221 }
4222
4223 void
4224 ARDOUR_UI::remove_lua_script ()
4225 {
4226         if (!_session) {
4227                 return;
4228         }
4229         if (_session->registered_lua_function_count () ==  0) {
4230                 string msg = _("There are no active Lua session scripts present in this session.");
4231                 MessageDialog am (msg);
4232                 am.run ();
4233                 return;
4234         }
4235
4236         std::vector<std::string> reg = _session->registered_lua_functions ();
4237         SessionScriptManager sm ("Remove Lua Session Script", reg);
4238         switch (sm.run ()) {
4239                 case Gtk::RESPONSE_ACCEPT:
4240                         break;
4241                 default:
4242                         return;
4243         }
4244         try {
4245                 _session->unregister_lua_function (sm.name());
4246         } catch (luabridge::LuaException const& e) {
4247                 string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ());
4248                 MessageDialog am (msg);
4249                 am.run ();
4250         }
4251 }
4252
4253 void
4254 ARDOUR_UI::stop_video_server (bool ask_confirm)
4255 {
4256         if (!video_server_process && ask_confirm) {
4257                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4258         }
4259         if (video_server_process) {
4260                 if(ask_confirm) {
4261                         ArdourDialog confirm (_("Stop Video-Server"), true);
4262                         Label m (_("Do you really want to stop the Video Server?"));
4263                         confirm.get_vbox()->pack_start (m, true, true);
4264                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4265                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4266                         confirm.show_all ();
4267                         if (confirm.run() == RESPONSE_CANCEL) {
4268                                 return;
4269                         }
4270                 }
4271                 delete video_server_process;
4272                 video_server_process =0;
4273         }
4274 }
4275
4276 void
4277 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4278 {
4279   ARDOUR_UI::start_video_server( float_window, true);
4280 }
4281
4282 bool
4283 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4284 {
4285         if (!_session) {
4286                 return false;
4287         }
4288         if (popup_msg) {
4289                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4290                         if (video_server_process) {
4291                                 popup_error(_("The Video Server is already started."));
4292                         } else {
4293                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4294                         }
4295                 }
4296         }
4297
4298         int firsttime = 0;
4299         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4300                 if (firsttime++) {
4301                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4302                 }
4303                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4304                 if (float_window) {
4305                         video_server_dialog->set_transient_for (*float_window);
4306                 }
4307
4308                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4309                         video_server_dialog->hide();
4310                 } else {
4311                         ResponseType r = (ResponseType) video_server_dialog->run ();
4312                         video_server_dialog->hide();
4313                         if (r != RESPONSE_ACCEPT) { return false; }
4314                         if (video_server_dialog->show_again()) {
4315                                 Config->set_show_video_server_dialog(false);
4316                         }
4317                 }
4318
4319                 std::string icsd_exec = video_server_dialog->get_exec_path();
4320                 std::string icsd_docroot = video_server_dialog->get_docroot();
4321 #ifndef PLATFORM_WINDOWS
4322                 if (icsd_docroot.empty()) {
4323                         icsd_docroot = VideoUtils::video_get_docroot (Config);
4324                 }
4325 #endif
4326
4327                 GStatBuf sb;
4328 #ifdef PLATFORM_WINDOWS
4329                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4330                         /* OK, allow all drive letters */
4331                 } else
4332 #endif
4333                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4334                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4335                         continue;
4336                 }
4337 #ifndef PLATFORM_WINDOWS
4338                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4339                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4340                         warning << _("Given Video Server is not an executable file.") << endmsg;
4341                         continue;
4342                 }
4343 #else
4344                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4345                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4346                         warning << _("Given Video Server is not an executable file.") << endmsg;
4347                         continue;
4348                 }
4349 #endif
4350
4351                 char **argp;
4352                 argp=(char**) calloc(9,sizeof(char*));
4353                 argp[0] = strdup(icsd_exec.c_str());
4354                 argp[1] = strdup("-P");
4355                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4356                 argp[3] = strdup("-p");
4357                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4358                 argp[5] = strdup("-C");
4359                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4360                 argp[7] = strdup(icsd_docroot.c_str());
4361                 argp[8] = 0;
4362                 stop_video_server();
4363
4364 #ifdef PLATFORM_WINDOWS
4365                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4366                         /* OK, allow all drive letters */
4367                 } else
4368 #endif
4369                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4370                         Config->set_video_advanced_setup(false);
4371                 } else {
4372                         std::ostringstream osstream;
4373                         osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
4374                         Config->set_video_server_url(osstream.str());
4375                         Config->set_video_server_docroot(icsd_docroot);
4376                         Config->set_video_advanced_setup(true);
4377                 }
4378
4379                 if (video_server_process) {
4380                         delete video_server_process;
4381                 }
4382
4383                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4384                 if (video_server_process->start()) {
4385                         warning << _("Cannot launch the video-server") << endmsg;
4386                         continue;
4387                 }
4388                 int timeout = 120; // 6 sec
4389                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4390                         Glib::usleep (50000);
4391                         gui_idle_handler();
4392                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4393                 }
4394                 if (timeout <= 0) {
4395                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4396                 } else {
4397                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4398                                 delete video_server_process;
4399                                 video_server_process = 0;
4400                         }
4401                 }
4402         }
4403         return true;
4404 }
4405
4406 void
4407 ARDOUR_UI::add_video (Gtk::Window* float_window)
4408 {
4409         if (!_session) {
4410                 return;
4411         }
4412
4413         if (!start_video_server(float_window, false)) {
4414                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4415                 return;
4416         }
4417
4418         if (float_window) {
4419                 add_video_dialog->set_transient_for (*float_window);
4420         }
4421
4422         if (add_video_dialog->is_visible()) {
4423                 /* we're already doing this */
4424                 return;
4425         }
4426
4427         ResponseType r = (ResponseType) add_video_dialog->run ();
4428         add_video_dialog->hide();
4429         if (r != RESPONSE_ACCEPT) { return; }
4430
4431         bool local_file, orig_local_file;
4432         std::string path = add_video_dialog->file_name(local_file);
4433
4434         std::string orig_path = path;
4435         orig_local_file = local_file;
4436
4437         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4438
4439         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4440                 warning << string_compose(_("could not open %1"), path) << endmsg;
4441                 return;
4442         }
4443         if (!local_file && path.length() == 0) {
4444                 warning << _("no video-file selected") << endmsg;
4445                 return;
4446         }
4447
4448         std::string audio_from_video;
4449         bool detect_ltc = false;
4450
4451         switch (add_video_dialog->import_option()) {
4452                 case VTL_IMPORT_TRANSCODE:
4453                         {
4454                                 TranscodeVideoDialog *transcode_video_dialog;
4455                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4456                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4457                                 transcode_video_dialog->hide();
4458                                 if (r != RESPONSE_ACCEPT) {
4459                                         delete transcode_video_dialog;
4460                                         return;
4461                                 }
4462
4463                                 audio_from_video = transcode_video_dialog->get_audiofile();
4464
4465                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4466                                         detect_ltc = true;
4467                                 }
4468                                 else if (!audio_from_video.empty()) {
4469                                         editor->embed_audio_from_video(
4470                                                         audio_from_video,
4471                                                         video_timeline->get_offset(),
4472                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4473                                                         );
4474                                 }
4475                                 switch (transcode_video_dialog->import_option()) {
4476                                         case VTL_IMPORT_TRANSCODED:
4477                                                 path = transcode_video_dialog->get_filename();
4478                                                 local_file = true;
4479                                                 break;
4480                                         case VTL_IMPORT_REFERENCE:
4481                                                 break;
4482                                         default:
4483                                                 delete transcode_video_dialog;
4484                                                 return;
4485                                 }
4486                                 delete transcode_video_dialog;
4487                         }
4488                         break;
4489                 default:
4490                 case VTL_IMPORT_NONE:
4491                         break;
4492         }
4493
4494         /* strip _session->session_directory().video_path() from video file if possible */
4495         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4496                  path=path.substr(_session->session_directory().video_path().size());
4497                  if (path.at(0) == G_DIR_SEPARATOR) {
4498                          path=path.substr(1);
4499                  }
4500         }
4501
4502         video_timeline->set_update_session_fps(auto_set_session_fps);
4503
4504         if (video_timeline->video_file_info(path, local_file)) {
4505                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4506                 node->add_property (X_("Filename"), path);
4507                 node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
4508                 node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
4509                 if (orig_local_file) {
4510                         node->add_property (X_("OriginalVideoFile"), orig_path);
4511                 } else {
4512                         node->remove_property (X_("OriginalVideoFile"));
4513                 }
4514                 _session->add_extra_xml (*node);
4515                 _session->set_dirty ();
4516
4517                 if (!audio_from_video.empty() && detect_ltc) {
4518                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4519
4520                         try {
4521                                 /* TODO ask user about TV standard (LTC alignment if any) */
4522                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4523                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4524
4525                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4526
4527                                 /* TODO seek near end of file, and read LTC until end.
4528                                  * if it fails to find any LTC frames, scan complete file
4529                                  *
4530                                  * calculate drift of LTC compared to video-duration,
4531                                  * ask user for reference (timecode from start/mid/end)
4532                                  */
4533                         } catch (...) {
4534                                 // LTCFileReader will have written error messages
4535                         }
4536
4537                         ::g_unlink(audio_from_video.c_str());
4538
4539                         if (ltc_seq.size() == 0) {
4540                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4541                         } else {
4542                                 /* the very first TC in the file is somteimes not aligned properly */
4543                                 int i = ltc_seq.size() -1;
4544                                 ARDOUR::frameoffset_t video_start_offset =
4545                                         _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4546                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4547                                 video_timeline->set_offset(video_start_offset);
4548                         }
4549                 }
4550
4551                 _session->maybe_update_session_range(
4552                         std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4553                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4554
4555
4556                 if (add_video_dialog->launch_xjadeo() && local_file) {
4557                         editor->set_xjadeo_sensitive(true);
4558                         editor->toggle_xjadeo_proc(1);
4559                 } else {
4560                         editor->toggle_xjadeo_proc(0);
4561                 }
4562                 editor->toggle_ruler_video(true);
4563         }
4564 }
4565
4566 void
4567 ARDOUR_UI::remove_video ()
4568 {
4569         video_timeline->close_session();
4570         editor->toggle_ruler_video(false);
4571
4572         /* reset state */
4573         video_timeline->set_offset_locked(false);
4574         video_timeline->set_offset(0);
4575
4576         /* delete session state */
4577         XMLNode* node = new XMLNode(X_("Videotimeline"));
4578         _session->add_extra_xml(*node);
4579         node = new XMLNode(X_("Videomonitor"));
4580         _session->add_extra_xml(*node);
4581         node = new XMLNode(X_("Videoexport"));
4582         _session->add_extra_xml(*node);
4583         stop_video_server();
4584 }
4585
4586 void
4587 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4588 {
4589         if (localcacheonly) {
4590                 video_timeline->vmon_update();
4591         } else {
4592                 video_timeline->flush_cache();
4593         }
4594         editor->queue_visual_videotimeline_update();
4595 }
4596
4597 void
4598 ARDOUR_UI::export_video (bool range)
4599 {
4600         if (ARDOUR::Config->get_show_video_export_info()) {
4601                 ExportVideoInfobox infobox (_session);
4602                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4603                 if (infobox.show_again()) {
4604                         ARDOUR::Config->set_show_video_export_info(false);
4605                 }
4606                 switch (rv) {
4607                         case GTK_RESPONSE_YES:
4608                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4609                                 break;
4610                         default:
4611                                 break;
4612                 }
4613         }
4614         export_video_dialog->set_session (_session);
4615         export_video_dialog->apply_state(editor->get_selection().time, range);
4616         export_video_dialog->run ();
4617         export_video_dialog->hide ();
4618 }
4619
4620 XMLNode*
4621 ARDOUR_UI::preferences_settings () const
4622 {
4623         XMLNode* node = 0;
4624
4625         if (_session) {
4626                 node = _session->instant_xml(X_("Preferences"));
4627         } else {
4628                 node = Config->instant_xml(X_("Preferences"));
4629         }
4630
4631         if (!node) {
4632                 node = new XMLNode (X_("Preferences"));
4633         }
4634
4635         return node;
4636 }
4637
4638 XMLNode*
4639 ARDOUR_UI::mixer_settings () const
4640 {
4641         XMLNode* node = 0;
4642
4643         if (_session) {
4644                 node = _session->instant_xml(X_("Mixer"));
4645         } else {
4646                 node = Config->instant_xml(X_("Mixer"));
4647         }
4648
4649         if (!node) {
4650                 node = new XMLNode (X_("Mixer"));
4651         }
4652
4653         return node;
4654 }
4655
4656 XMLNode*
4657 ARDOUR_UI::main_window_settings () const
4658 {
4659         XMLNode* node = 0;
4660
4661         if (_session) {
4662                 node = _session->instant_xml(X_("Main"));
4663         } else {
4664                 node = Config->instant_xml(X_("Main"));
4665         }
4666
4667         if (!node) {
4668                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4669                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4670                 }
4671         }
4672
4673         if (!node) {
4674                 node = new XMLNode (X_("Main"));
4675         }
4676
4677         return node;
4678 }
4679
4680 XMLNode*
4681 ARDOUR_UI::editor_settings () const
4682 {
4683         XMLNode* node = 0;
4684
4685         if (_session) {
4686                 node = _session->instant_xml(X_("Editor"));
4687         } else {
4688                 node = Config->instant_xml(X_("Editor"));
4689         }
4690
4691         if (!node) {
4692                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4693                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4694                 }
4695         }
4696
4697         if (!node) {
4698                 node = new XMLNode (X_("Editor"));
4699         }
4700
4701         return node;
4702 }
4703
4704 XMLNode*
4705 ARDOUR_UI::keyboard_settings () const
4706 {
4707         XMLNode* node = 0;
4708
4709         node = Config->extra_xml(X_("Keyboard"));
4710
4711         if (!node) {
4712                 node = new XMLNode (X_("Keyboard"));
4713         }
4714
4715         return node;
4716 }
4717
4718 void
4719 ARDOUR_UI::create_xrun_marker (framepos_t where)
4720 {
4721         if (_session) {
4722                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark, 0);
4723                 _session->locations()->add (location);
4724         }
4725 }
4726
4727 void
4728 ARDOUR_UI::halt_on_xrun_message ()
4729 {
4730         cerr << "HALT on xrun\n";
4731         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4732         msg.run ();
4733 }
4734
4735 void
4736 ARDOUR_UI::xrun_handler (framepos_t where)
4737 {
4738         if (!_session) {
4739                 return;
4740         }
4741
4742         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4743
4744         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4745                 create_xrun_marker(where);
4746         }
4747
4748         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4749                 halt_on_xrun_message ();
4750         }
4751 }
4752
4753 void
4754 ARDOUR_UI::disk_overrun_handler ()
4755 {
4756         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4757
4758         if (!have_disk_speed_dialog_displayed) {
4759                 have_disk_speed_dialog_displayed = true;
4760                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4761 The disk system on your computer\n\
4762 was not able to keep up with %1.\n\
4763 \n\
4764 Specifically, it failed to write data to disk\n\
4765 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4766                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4767                 msg->show ();
4768         }
4769 }
4770
4771
4772 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4773 static MessageDialog *scan_dlg = NULL;
4774 static ProgressBar   *scan_pbar = NULL;
4775 static HBox          *scan_tbox = NULL;
4776 static Gtk::Button   *scan_timeout_button;
4777
4778 void
4779 ARDOUR_UI::cancel_plugin_scan ()
4780 {
4781         PluginManager::instance().cancel_plugin_scan();
4782 }
4783
4784 void
4785 ARDOUR_UI::cancel_plugin_timeout ()
4786 {
4787         PluginManager::instance().cancel_plugin_timeout();
4788         scan_timeout_button->set_sensitive (false);
4789 }
4790
4791 void
4792 ARDOUR_UI::plugin_scan_timeout (int timeout)
4793 {
4794         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4795                 return;
4796         }
4797         if (timeout > 0) {
4798                 scan_pbar->set_sensitive (false);
4799                 scan_timeout_button->set_sensitive (true);
4800                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4801                 scan_tbox->show();
4802         } else {
4803                 scan_pbar->set_sensitive (false);
4804                 scan_timeout_button->set_sensitive (false);
4805         }
4806         gui_idle_handler();
4807 }
4808
4809 void
4810 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4811 {
4812         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4813                 return;
4814         }
4815
4816         const bool cancelled = PluginManager::instance().cancelled();
4817         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4818                 if (cancelled && scan_dlg->is_mapped()) {
4819                         scan_dlg->hide();
4820                         gui_idle_handler();
4821                         return;
4822                 }
4823                 if (cancelled || !can_cancel) {
4824                         return;
4825                 }
4826         }
4827
4828         static Gtk::Button *cancel_button;
4829         if (!scan_dlg) {
4830                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4831                 VBox* vbox = scan_dlg->get_vbox();
4832                 vbox->set_size_request(400,-1);
4833                 scan_dlg->set_title (_("Scanning for plugins"));
4834
4835                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4836                 cancel_button->set_name ("EditorGTKButton");
4837                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4838                 cancel_button->show();
4839
4840                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4841
4842                 scan_tbox = manage( new HBox() );
4843
4844                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4845                 scan_timeout_button->set_name ("EditorGTKButton");
4846                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4847                 scan_timeout_button->show();
4848
4849                 scan_pbar = manage(new ProgressBar());
4850                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
4851                 scan_pbar->set_text(_("Scan Timeout"));
4852                 scan_pbar->show();
4853
4854                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
4855                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
4856
4857                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
4858         }
4859
4860         assert(scan_dlg && scan_tbox && cancel_button);
4861
4862         if (type == X_("closeme")) {
4863                 scan_tbox->hide();
4864                 scan_dlg->hide();
4865         } else {
4866                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
4867                 scan_dlg->show();
4868         }
4869         if (!can_cancel || !cancelled) {
4870                 scan_timeout_button->set_sensitive(false);
4871         }
4872         cancel_button->set_sensitive(can_cancel && !cancelled);
4873
4874         gui_idle_handler();
4875 }
4876
4877 void
4878 ARDOUR_UI::gui_idle_handler ()
4879 {
4880         int timeout = 30;
4881         /* due to idle calls, gtk_events_pending() may always return true */
4882         while (gtk_events_pending() && --timeout) {
4883                 gtk_main_iteration ();
4884         }
4885 }
4886
4887 void
4888 ARDOUR_UI::disk_underrun_handler ()
4889 {
4890         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
4891
4892         if (!have_disk_speed_dialog_displayed) {
4893                 have_disk_speed_dialog_displayed = true;
4894                 MessageDialog* msg = new MessageDialog (
4895                         _main_window, string_compose (_("The disk system on your computer\n\
4896 was not able to keep up with %1.\n\
4897 \n\
4898 Specifically, it failed to read data from disk\n\
4899 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
4900                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4901                 msg->show ();
4902         }
4903 }
4904
4905 void
4906 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
4907 {
4908         have_disk_speed_dialog_displayed = false;
4909         delete msg;
4910 }
4911
4912 void
4913 ARDOUR_UI::session_dialog (std::string msg)
4914 {
4915         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
4916
4917         MessageDialog* d;
4918
4919         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4920         d->show_all ();
4921         d->run ();
4922         delete d;
4923 }
4924
4925 int
4926 ARDOUR_UI::pending_state_dialog ()
4927 {
4928         HBox* hbox = manage (new HBox());
4929         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
4930         ArdourDialog dialog (_("Crash Recovery"), true);
4931         Label  message (string_compose (_("\
4932 This session appears to have been in the\n\
4933 middle of recording when %1 or\n\
4934 the computer was shutdown.\n\
4935 \n\
4936 %1 can recover any captured audio for\n\
4937 you, or it can ignore it. Please decide\n\
4938 what you would like to do.\n"), PROGRAM_NAME));
4939         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4940         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4941         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4942         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4943         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
4944         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
4945         dialog.set_default_response (RESPONSE_ACCEPT);
4946         dialog.set_position (WIN_POS_CENTER);
4947         message.show();
4948         image->show();
4949         hbox->show();
4950
4951         switch (dialog.run ()) {
4952         case RESPONSE_ACCEPT:
4953                 return 1;
4954         default:
4955                 return 0;
4956         }
4957 }
4958
4959 int
4960 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
4961 {
4962         HBox* hbox = new HBox();
4963         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
4964         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
4965         Label  message (string_compose (_("\
4966 This session was created with a sample rate of %1 Hz, but\n\
4967 %2 is currently running at %3 Hz.  If you load this session,\n\
4968 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
4969
4970         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4971         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4972         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4973         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4974         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
4975         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
4976         dialog.set_default_response (RESPONSE_ACCEPT);
4977         dialog.set_position (WIN_POS_CENTER);
4978         message.show();
4979         image->show();
4980         hbox->show();
4981
4982         switch (dialog.run()) {
4983         case RESPONSE_ACCEPT:
4984                 return 0;
4985         default:
4986                 break;
4987         }
4988
4989         return 1;
4990 }
4991
4992 void
4993 ARDOUR_UI::sr_mismatch_message (framecnt_t desired, framecnt_t actual)
4994 {
4995         MessageDialog msg (string_compose (_("\
4996 This session was created with a sample rate of %1 Hz, but\n\
4997 %2 is currently running at %3 Hz.\n\
4998 Audio will be recorded and played at the wrong sample rate.\n\
4999 Re-Configure the Audio Engine in\n\
5000 Menu > Window > Audio/Midi Setup"),
5001                                 desired, PROGRAM_NAME, actual),
5002                         true,
5003                         Gtk::MESSAGE_WARNING);
5004         msg.run ();
5005 }
5006
5007 void
5008 ARDOUR_UI::use_config ()
5009 {
5010 }
5011
5012 void
5013 ARDOUR_UI::update_transport_clocks (framepos_t pos)
5014 {
5015         if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
5016                 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5017         } else {
5018                 primary_clock->set (pos);
5019         }
5020
5021         if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
5022                 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5023         } else {
5024                 secondary_clock->set (pos);
5025         }
5026
5027         if (big_clock_window) {
5028                 big_clock->set (pos);
5029         }
5030         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
5031 }
5032
5033 void
5034 ARDOUR_UI::step_edit_status_change (bool yn)
5035 {
5036         // XXX should really store pre-step edit status of things
5037         // we make insensitive
5038
5039         if (yn) {
5040                 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
5041                 rec_button.set_sensitive (false);
5042         } else {
5043                 rec_button.unset_active_state ();;
5044                 rec_button.set_sensitive (true);
5045         }
5046 }
5047
5048 void
5049 ARDOUR_UI::record_state_changed ()
5050 {
5051         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
5052
5053         if (!_session) {
5054                 /* why bother - the clock isn't visible */
5055                 return;
5056         }
5057
5058         ActionManager::set_sensitive (ActionManager::rec_sensitive_actions, !_session->actively_recording());
5059
5060         if (big_clock_window) {
5061                 if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
5062                         big_clock->set_active (true);
5063                 } else {
5064                         big_clock->set_active (false);
5065                 }
5066         }
5067
5068 }
5069
5070 bool
5071 ARDOUR_UI::first_idle ()
5072 {
5073         if (_session) {
5074                 _session->allow_auto_play (true);
5075         }
5076
5077         if (editor) {
5078                 editor->first_idle();
5079         }
5080
5081         Keyboard::set_can_save_keybindings (true);
5082         return false;
5083 }
5084
5085 void
5086 ARDOUR_UI::store_clock_modes ()
5087 {
5088         XMLNode* node = new XMLNode(X_("ClockModes"));
5089
5090         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
5091                 XMLNode* child = new XMLNode (X_("Clock"));
5092
5093                 child->add_property (X_("name"), (*x)->name());
5094                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
5095                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
5096
5097                 node->add_child_nocopy (*child);
5098         }
5099
5100         _session->add_extra_xml (*node);
5101         _session->set_dirty ();
5102 }
5103
5104 void
5105 ARDOUR_UI::setup_profile ()
5106 {
5107         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5108                 Profile->set_small_screen ();
5109         }
5110
5111         if (g_getenv ("TRX")) {
5112                 Profile->set_trx ();
5113         }
5114
5115         if (g_getenv ("MIXBUS")) {
5116                 Profile->set_mixbus ();
5117         }
5118 }
5119
5120 int
5121 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5122 {
5123         MissingFileDialog dialog (s, str, type);
5124
5125         dialog.show ();
5126         dialog.present ();
5127
5128         int result = dialog.run ();
5129         dialog.hide ();
5130
5131         switch (result) {
5132         case RESPONSE_OK:
5133                 break;
5134         default:
5135                 return 1; // quit entire session load
5136         }
5137
5138         result = dialog.get_action ();
5139
5140         return result;
5141 }
5142
5143 int
5144 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5145 {
5146         AmbiguousFileDialog dialog (file, hits);
5147
5148         dialog.show ();
5149         dialog.present ();
5150
5151         dialog.run ();
5152
5153         return dialog.get_which ();
5154 }
5155
5156 /** Allocate our thread-local buffers */
5157 void
5158 ARDOUR_UI::get_process_buffers ()
5159 {
5160         _process_thread->get_buffers ();
5161 }
5162
5163 /** Drop our thread-local buffers */
5164 void
5165 ARDOUR_UI::drop_process_buffers ()
5166 {
5167         _process_thread->drop_buffers ();
5168 }
5169
5170 void
5171 ARDOUR_UI::feedback_detected ()
5172 {
5173         _feedback_exists = true;
5174 }
5175
5176 void
5177 ARDOUR_UI::successful_graph_sort ()
5178 {
5179         _feedback_exists = false;
5180 }
5181
5182 void
5183 ARDOUR_UI::midi_panic ()
5184 {
5185         if (_session) {
5186                 _session->midi_panic();
5187         }
5188 }
5189
5190 void
5191 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5192 {
5193         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5194         const char* end_big = "</span>";
5195         const char* start_mono = "<tt>";
5196         const char* end_mono = "</tt>";
5197
5198         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5199                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5200                                              "From now on, use the backup copy with older versions of %3"),
5201                                            xml_path, backup_path, PROGRAM_NAME,
5202                                            start_big, end_big,
5203                                            start_mono, end_mono), true);
5204
5205         msg.run ();
5206 }
5207
5208
5209 void
5210 ARDOUR_UI::reset_peak_display ()
5211 {
5212         if (!_session || !_session->master_out() || !editor_meter) return;
5213         editor_meter->clear_meters();
5214         editor_meter_max_peak = -INFINITY;
5215         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5216 }
5217
5218 void
5219 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5220 {
5221         if (!_session || !_session->master_out()) return;
5222         if (group == _session->master_out()->route_group()) {
5223                 reset_peak_display ();
5224         }
5225 }
5226
5227 void
5228 ARDOUR_UI::reset_route_peak_display (Route* route)
5229 {
5230         if (!_session || !_session->master_out()) return;
5231         if (_session->master_out().get() == route) {
5232                 reset_peak_display ();
5233         }
5234 }
5235
5236 int
5237 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5238 {
5239         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5240         audio_midi_setup->set_position (WIN_POS_CENTER);
5241
5242         if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
5243                 audio_midi_setup->try_autostart ();
5244                 if (ARDOUR::AudioEngine::instance()->running()) {
5245                         return 0;
5246                 }
5247         }
5248
5249         while (true) {
5250                 int response = audio_midi_setup->run();
5251                 printf("RESPONSE %d\n", response);
5252                 switch (response) {
5253                 case Gtk::RESPONSE_DELETE_EVENT:
5254                         return -1;
5255                 default:
5256                         if (!AudioEngine::instance()->running()) {
5257                                 continue;
5258                         }
5259                         audio_midi_setup->hide ();
5260                         return 0;
5261                 }
5262         }
5263 }
5264
5265
5266 gint
5267 ARDOUR_UI::transport_numpad_timeout ()
5268 {
5269         _numpad_locate_happening = false;
5270         if (_numpad_timeout_connection.connected() )
5271                 _numpad_timeout_connection.disconnect();
5272         return 1;
5273 }
5274
5275 void
5276 ARDOUR_UI::transport_numpad_decimal ()
5277 {
5278         _numpad_timeout_connection.disconnect();
5279
5280         if (_numpad_locate_happening) {
5281                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5282                 _numpad_locate_happening = false;
5283         } else {
5284                 _pending_locate_num = 0;
5285                 _numpad_locate_happening = true;
5286                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5287         }
5288 }
5289
5290 void
5291 ARDOUR_UI::transport_numpad_event (int num)
5292 {
5293         if ( _numpad_locate_happening ) {
5294                 _pending_locate_num = _pending_locate_num*10 + num;
5295         } else {
5296                 switch (num) {
5297                         case 0:  toggle_roll(false, false);             break;
5298                         case 1:  transport_rewind(1);                           break;
5299                         case 2:  transport_forward(1);                          break;
5300                         case 3:  transport_record(true);                        break;
5301                         case 4:  toggle_session_auto_loop();            break;
5302                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5303                         case 6:  toggle_punch();                                        break;
5304                         case 7:  toggle_click();                                break;
5305                         case 8:  toggle_auto_return();                  break;
5306                         case 9:  toggle_follow_edits();         break;
5307                 }
5308         }
5309 }
5310
5311 void
5312 ARDOUR_UI::set_flat_buttons ()
5313 {
5314         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5315 }
5316
5317 void
5318 ARDOUR_UI::audioengine_became_silent ()
5319 {
5320         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5321                            true,
5322                            Gtk::MESSAGE_WARNING,
5323                            Gtk::BUTTONS_NONE,
5324                            true);
5325
5326         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5327
5328         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5329         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5330         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5331         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5332         Gtk::HBox pay_button_box;
5333         Gtk::HBox subscribe_button_box;
5334
5335         pay_button_box.pack_start (pay_button, true, false);
5336         subscribe_button_box.pack_start (subscribe_button, true, false);
5337
5338         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 */
5339
5340         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5341         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5342
5343         msg.get_vbox()->pack_start (pay_label);
5344         msg.get_vbox()->pack_start (pay_button_box);
5345         msg.get_vbox()->pack_start (subscribe_label);
5346         msg.get_vbox()->pack_start (subscribe_button_box);
5347
5348         msg.get_vbox()->show_all ();
5349
5350         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5351         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5352         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5353
5354         int r = msg.run ();
5355
5356         switch (r) {
5357         case Gtk::RESPONSE_YES:
5358                 AudioEngine::instance()->reset_silence_countdown ();
5359                 break;
5360
5361         case Gtk::RESPONSE_NO:
5362                 /* save and quit */
5363                 save_state_canfail ("");
5364                 exit (0);
5365                 break;
5366
5367         case Gtk::RESPONSE_CANCEL:
5368         default:
5369                 /* don't reset, save session and exit */
5370                 break;
5371         }
5372 }
5373
5374 void
5375 ARDOUR_UI::hide_application ()
5376 {
5377     Application::instance ()-> hide ();
5378 }
5379
5380 void
5381 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5382 {
5383         /* icons, titles, WM stuff */
5384
5385         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5386
5387         if (window_icons.empty()) {
5388                 Glib::RefPtr<Gdk::Pixbuf> icon;
5389                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
5390                         window_icons.push_back (icon);
5391                 }
5392                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
5393                         window_icons.push_back (icon);
5394                 }
5395                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
5396                         window_icons.push_back (icon);
5397                 }
5398                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
5399                         window_icons.push_back (icon);
5400                 }
5401         }
5402
5403         if (!window_icons.empty()) {
5404                 window.set_default_icon_list (window_icons);
5405         }
5406
5407         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5408
5409         if (!name.empty()) {
5410                 title += name;
5411         }
5412
5413         window.set_title (title.get_string());
5414         window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME);
5415
5416         window.set_flags (CAN_FOCUS);
5417         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5418
5419         /* This is a hack to ensure that GTK-accelerators continue to
5420          * work. Once we switch over to entirely native bindings, this will be
5421          * unnecessary and should be removed
5422          */
5423         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5424
5425         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5426         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5427         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5428         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5429 }
5430
5431 bool
5432 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5433 {
5434         Gtkmm2ext::Bindings* bindings = 0;
5435         Gtk::Window* window = 0;
5436
5437         /* until we get ardour bindings working, we are not handling key
5438          * releases yet.
5439          */
5440
5441         if (ev->type != GDK_KEY_PRESS) {
5442                 return false;
5443         }
5444
5445         if (event_window == &_main_window) {
5446
5447                 window = event_window;
5448
5449                 /* find current tab contents */
5450
5451                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5452
5453                 /* see if it uses the ardour binding system */
5454
5455                 if (w) {
5456                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5457                 }
5458
5459                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5460
5461         } else {
5462
5463                 window = event_window;
5464
5465                 /* see if window uses ardour binding system */
5466
5467                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5468         }
5469
5470         /* An empty binding set is treated as if it doesn't exist */
5471
5472         if (bindings && bindings->empty()) {
5473                 bindings = 0;
5474         }
5475
5476         return key_press_focus_accelerator_handler (*window, ev, bindings);
5477 }
5478
5479 static Gtkmm2ext::Bindings*
5480 get_bindings_from_widget_heirarchy (GtkWidget** w)
5481 {
5482         void* p = NULL;
5483
5484         while (*w) {
5485                 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
5486                         break;
5487                 }
5488                 *w = gtk_widget_get_parent (*w);
5489         }
5490
5491         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5492 }
5493
5494 bool
5495 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5496 {
5497         GtkWindow* win = window.gobj();
5498         GtkWidget* focus = gtk_window_get_focus (win);
5499         GtkWidget* binding_widget = focus;
5500         bool special_handling_of_unmodified_accelerators = false;
5501         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5502
5503         if (focus) {
5504
5505                 /* some widget has keyboard focus */
5506
5507                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5508
5509                         /* A particular kind of focusable widget currently has keyboard
5510                          * focus. All unmodified key events should go to that widget
5511                          * first and not be used as an accelerator by default
5512                          */
5513
5514                         special_handling_of_unmodified_accelerators = true;
5515
5516                 } else {
5517
5518                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5519                         if (focus_bindings) {
5520                                 bindings = focus_bindings;
5521                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5522                         }
5523                 }
5524         }
5525
5526         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",
5527                                                           win,
5528                                                           ev->keyval,
5529                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
5530                                                           special_handling_of_unmodified_accelerators,
5531                                                           Keyboard::some_magic_widget_has_focus(),
5532                                                           focus,
5533                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5534                                                           ((ev->state & mask) ? "yes" : "no"),
5535                                                           window.get_title()));
5536
5537         /* This exists to allow us to override the way GTK handles
5538            key events. The normal sequence is:
5539
5540            a) event is delivered to a GtkWindow
5541            b) accelerators/mnemonics are activated
5542            c) if (b) didn't handle the event, propagate to
5543                the focus widget and/or focus chain
5544
5545            The problem with this is that if the accelerators include
5546            keys without modifiers, such as the space bar or the
5547            letter "e", then pressing the key while typing into
5548            a text entry widget results in the accelerator being
5549            activated, instead of the desired letter appearing
5550            in the text entry.
5551
5552            There is no good way of fixing this, but this
5553            represents a compromise. The idea is that
5554            key events involving modifiers (not Shift)
5555            get routed into the activation pathway first, then
5556            get propagated to the focus widget if necessary.
5557
5558            If the key event doesn't involve modifiers,
5559            we deliver to the focus widget first, thus allowing
5560            it to get "normal text" without interference
5561            from acceleration.
5562
5563            Of course, this can also be problematic: if there
5564            is a widget with focus, then it will swallow
5565            all "normal text" accelerators.
5566         */
5567
5568
5569         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5570
5571                 /* no special handling or there are modifiers in effect: accelerate first */
5572
5573                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5574                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5575                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5576
5577                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5578                 KeyboardKey k (ev->state, ev->keyval);
5579
5580                 while (bindings) {
5581
5582                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5583
5584                         if (bindings->activate (k, Bindings::Press)) {
5585                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5586                                 return true;
5587                         }
5588
5589                         if (binding_widget) {
5590                                 binding_widget = gtk_widget_get_parent (binding_widget);
5591                                 if (binding_widget) {
5592                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5593                                 } else {
5594                                         bindings = 0;
5595                                 }
5596                         } else {
5597                                 bindings = 0;
5598                         }
5599                 }
5600
5601                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5602
5603                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5604                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5605                         return true;
5606                 }
5607
5608                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5609
5610                 if (gtk_window_propagate_key_event (win, ev)) {
5611                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5612                         return true;
5613                 }
5614
5615         } else {
5616
5617                 /* no modifiers, propagate first */
5618
5619                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5620
5621                 if (gtk_window_propagate_key_event (win, ev)) {
5622                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5623                         return true;
5624                 }
5625
5626                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5627                 KeyboardKey k (ev->state, ev->keyval);
5628
5629                 while (bindings) {
5630
5631                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5632
5633
5634                         if (bindings->activate (k, Bindings::Press)) {
5635                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5636                                 return true;
5637                         }
5638
5639                         if (binding_widget) {
5640                                 binding_widget = gtk_widget_get_parent (binding_widget);
5641                                 if (binding_widget) {
5642                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5643                                 } else {
5644                                         bindings = 0;
5645                                 }
5646                         } else {
5647                                 bindings = 0;
5648                         }
5649                 }
5650
5651                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5652
5653                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5654                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5655                         return true;
5656                 }
5657         }
5658
5659         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5660         return true;
5661 }
5662
5663 void
5664 ARDOUR_UI::load_bindings ()
5665 {
5666         if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
5667                 error << _("Global keybindings are missing") << endmsg;
5668         }
5669 }
5670
5671 void
5672 ARDOUR_UI::cancel_solo ()
5673 {
5674         if (_session) {
5675                 _session->cancel_all_solo ();
5676         }
5677 }
5678
5679 void
5680 ARDOUR_UI::reset_focus (Gtk::Widget* w)
5681 {
5682         /* this resets focus to the first focusable parent of the given widget,
5683          * or, if there is no focusable parent, cancels focus in the toplevel
5684          * window that the given widget is packed into (if there is one).
5685          */
5686
5687         if (!w) {
5688                 return;
5689         }
5690
5691         Gtk::Widget* top = w->get_toplevel();
5692
5693         if (!top || !top->is_toplevel()) {
5694                 return;
5695         }
5696
5697         w = w->get_parent ();
5698
5699         while (w) {
5700
5701                 if (w->is_toplevel()) {
5702                         /* Setting the focus widget to a Gtk::Window causes all
5703                          * subsequent calls to ::has_focus() on the nominal
5704                          * focus widget in that window to return
5705                          * false. Workaround: never set focus to the toplevel
5706                          * itself.
5707                          */
5708                         break;
5709                 }
5710
5711                 if (w->get_can_focus ()) {
5712                         Gtk::Window* win = dynamic_cast<Gtk::Window*> (top);
5713                         win->set_focus (*w);
5714                         return;
5715                 }
5716                 w = w->get_parent ();
5717         }
5718
5719         if (top == &_main_window) {
5720
5721         }
5722
5723         /* no focusable parent found, cancel focus in top level window.
5724            C++ API cannot be used for this. Thanks, references.
5725         */
5726
5727         gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0);
5728
5729 }