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