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