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