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