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