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