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