initial pass at session-renaming functionality
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2007 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 #endif
23
24 #include <stdint.h>
25
26 #include <algorithm>
27 #include <cmath>
28 #include <fcntl.h>
29 #include <signal.h>
30 #include <unistd.h>
31 #include <time.h>
32 #include <cerrno>
33 #include <fstream>
34
35 #include <iostream>
36
37 #include <sys/resource.h>
38
39 #include <gtkmm/messagedialog.h>
40 #include <gtkmm/accelmap.h>
41
42 #include "pbd/error.h"
43 #include "pbd/basename.h"
44 #include "pbd/compose.h"
45 #include "pbd/failed_constructor.h"
46 #include "pbd/enumwriter.h"
47 #include "pbd/memento_command.h"
48 #include "pbd/openuri.h"
49 #include "pbd/file_utils.h"
50
51 #include "gtkmm2ext/application.h"
52 #include "gtkmm2ext/bindings.h"
53 #include "gtkmm2ext/gtk_ui.h"
54 #include "gtkmm2ext/utils.h"
55 #include "gtkmm2ext/click_box.h"
56 #include "gtkmm2ext/fastmeter.h"
57 #include "gtkmm2ext/popup.h"
58 #include "gtkmm2ext/window_title.h"
59
60 #include "midi++/manager.h"
61
62 #include "ardour/ardour.h"
63 #include "ardour/callback.h"
64 #include "ardour/profile.h"
65 #include "ardour/session_directory.h"
66 #include "ardour/session_route.h"
67 #include "ardour/session_state_utils.h"
68 #include "ardour/session_utils.h"
69 #include "ardour/port.h"
70 #include "ardour/audioengine.h"
71 #include "ardour/playlist.h"
72 #include "ardour/utils.h"
73 #include "ardour/audio_diskstream.h"
74 #include "ardour/audiofilesource.h"
75 #include "ardour/recent_sessions.h"
76 #include "ardour/port.h"
77 #include "ardour/audio_track.h"
78 #include "ardour/midi_track.h"
79 #include "ardour/filesystem_paths.h"
80 #include "ardour/filename_extensions.h"
81
82 typedef uint64_t microseconds_t;
83
84 #include "about.h"
85 #include "actions.h"
86 #include "add_route_dialog.h"
87 #include "ambiguous_file_dialog.h"
88 #include "ardour_ui.h"
89 #include "audio_clock.h"
90 #include "bundle_manager.h"
91 #include "engine_dialog.h"
92 #include "gain_meter.h"
93 #include "global_port_matrix.h"
94 #include "gui_object.h"
95 #include "gui_thread.h"
96 #include "keyboard.h"
97 #include "location_ui.h"
98 #include "missing_file_dialog.h"
99 #include "missing_plugin_dialog.h"
100 #include "mixer_ui.h"
101 #include "opts.h"
102 #include "processor_box.h"
103 #include "prompter.h"
104 #include "public_editor.h"
105 #include "route_time_axis.h"
106 #include "session_metadata_dialog.h"
107 #include "shuttle_control.h"
108 #include "speaker_dialog.h"
109 #include "splash.h"
110 #include "startup.h"
111 #include "theme_manager.h"
112 #include "time_axis_view_item.h"
113 #include "utils.h"
114 #include "window_proxy.h"
115
116 #include "i18n.h"
117
118 using namespace ARDOUR;
119 using namespace PBD;
120 using namespace Gtkmm2ext;
121 using namespace Gtk;
122
123 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
124 UIConfiguration *ARDOUR_UI::ui_config = 0;
125
126 sigc::signal<void,bool> ARDOUR_UI::Blink;
127 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
128 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
129 sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
130
131 bool could_be_a_valid_path (const string& path);
132
133 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
134
135         : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp)
136
137         , gui_object_state (new GUIObjectState)
138         , primary_clock (new AudioClock (X_("primary"), false, X_("TransportClockDisplay"), true, true, false, true))
139         , secondary_clock (new AudioClock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, true, false, true))
140         , preroll_clock (new AudioClock (X_("preroll"), false, X_("PreRollClock"), true, false, true))
141         , postroll_clock (new AudioClock (X_("postroll"), false, X_("PostRollClock"), true, false, true))
142
143           /* preroll stuff */
144
145         , preroll_button (_("pre\nroll"))
146         , postroll_button (_("post\nroll"))
147
148           /* big clock */
149
150         , big_clock (new AudioClock (X_("bigclock"), false, "BigClockNonRecording", true, true, false, false))
151
152           /* transport */
153
154         , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
155         , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
156         , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
157         , goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd))
158         , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
159         , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
160         , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
161
162         , roll_button (roll_controllable)
163         , stop_button (stop_controllable)
164         , goto_start_button (goto_start_controllable)
165         , goto_end_button (goto_end_controllable)
166         , auto_loop_button (auto_loop_controllable)
167         , play_selection_button (play_selection_controllable)
168         , rec_button (rec_controllable)
169
170         , auto_return_button (_("Auto Return"))
171         , auto_play_button (_("Auto Play"))
172         , auto_input_button (_("Auto Input"))
173           // , click_button (_("Click"))
174         , time_master_button (_("time\nmaster"))
175
176         , auditioning_alert_button (_("AUDITION"))
177         , solo_alert_button (_("SOLO"))
178
179         , error_log_button (_("Errors"))
180
181 {
182         using namespace Gtk::Menu_Helpers;
183
184         Gtkmm2ext::init();
185
186
187 #ifdef TOP_MENUBAR
188         // _auto_display_errors = false;
189         /*
190          * This was commented out as it wasn't defined
191          * in A3 IIRC.  If this is not needed it should
192          * be completely removed.
193          */
194 #endif
195
196         about = 0;
197         splash = 0;
198         _startup = 0;
199
200         if (theArdourUI == 0) {
201                 theArdourUI = this;
202         }
203
204         ui_config = new UIConfiguration();
205         theme_manager = new ThemeManager();
206
207         key_editor = 0;
208
209         editor = 0;
210         mixer = 0;
211         editor = 0;
212         engine = 0;
213         _session_is_new = false;
214         big_clock_window = 0;
215         big_clock_height = 0;
216         big_clock_resize_in_progress = false;
217         session_selector_window = 0;
218         last_key_press_time = 0;
219         _will_create_new_session_automatically = false;
220         add_route_dialog = 0;
221         route_params = 0;
222         bundle_manager = 0;
223         rc_option_editor = 0;
224         session_option_editor = 0;
225         location_ui = 0;
226         open_session_selector = 0;
227         have_configure_timeout = false;
228         have_disk_speed_dialog_displayed = false;
229         session_loaded = false;
230         ignore_dual_punch = false;
231         original_big_clock_width = -1;
232         original_big_clock_height = -1;
233         original_big_clock_font_size = 0;
234
235         roll_button.unset_flags (Gtk::CAN_FOCUS);
236         stop_button.unset_flags (Gtk::CAN_FOCUS);
237         goto_start_button.unset_flags (Gtk::CAN_FOCUS);
238         goto_end_button.unset_flags (Gtk::CAN_FOCUS);
239         auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
240         play_selection_button.unset_flags (Gtk::CAN_FOCUS);
241         rec_button.unset_flags (Gtk::CAN_FOCUS);
242         join_play_range_button.unset_flags (Gtk::CAN_FOCUS);
243         last_configure_time= 0;
244         last_peak_grab = 0;
245
246         ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
247         ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
248
249         /* handle dialog requests */
250
251         ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
252
253         /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
254
255         ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
256
257         /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
258
259         ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
260
261         /* handle requests to quit (coming from JACK session) */
262
263         ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::finish, this), gui_context ());
264
265         /* handle requests to deal with missing files */
266
267         ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
268
269         /* and ambiguous files */
270
271         ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2, _3));
272
273         /* lets get this party started */
274
275         try {
276                 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
277                         throw failed_constructor ();
278                 }
279
280                 setup_gtk_ardour_enums ();
281                 setup_profile ();
282
283                 GainMeter::setup_slider_pix ();
284                 RouteTimeAxisView::setup_slider_pix ();
285                 SendProcessorEntry::setup_slider_pix ();
286                 SessionEvent::create_per_thread_pool ("GUI", 512);
287
288         } catch (failed_constructor& err) {
289                 error << string_compose (_("could not initialize %1."), PROGRAM_NAME) << endmsg;
290                 // pass it on up
291                 throw;
292         }
293
294         /* we like keyboards */
295
296         keyboard = new ArdourKeyboard(*this);
297
298         XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
299         if (node) {
300                 keyboard->set_state (*node, Stateful::loading_state_version);
301         }
302
303         /* we don't like certain modifiers */
304         Bindings::set_ignored_state (GDK_LOCK_MASK|GDK_MOD2_MASK|GDK_MOD3_MASK);
305
306         reset_dpi();
307
308         TimeAxisViewItem::set_constant_heights ();
309
310         /* The following must happen after ARDOUR::init() so that Config is set up */
311
312         location_ui = new ActionWindowProxy<LocationUIWindow> (X_("locations"), Config->extra_xml (X_("UI")), X_("ToggleLocations"));
313         big_clock_window = new ActionWindowProxy<Gtk::Window> (X_("bigclock"), Config->extra_xml (X_("UI")), X_("ToggleBigClock"));
314         speaker_config_window = new ActionWindowProxy<SpeakerDialog> (X_("speakerconf"), Config->extra_xml (X_("UI")), X_("toggle-speaker-config"));
315
316         for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
317                 _global_port_matrix[*i] = new ActionWindowProxy<GlobalPortMatrixWindow> (
318                         string_compose ("GlobalPortMatrix-%1", (*i).to_string()),
319                         Config->extra_xml (X_("UI")),
320                         string_compose ("toggle-%1-connection-manager", (*i).to_string())
321                         );
322         }
323
324         setup_clock ();
325
326         SpeakerDialog* s = new SpeakerDialog ();
327         s->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/toggle-speaker-config")));
328         speaker_config_window->set (s);
329
330         starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
331         stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
332 }
333
334 /** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
335 bool
336 ARDOUR_UI::run_startup (bool should_be_new, string load_template)
337 {
338         delete _startup;
339         _startup = new ArdourStartup ();
340
341         XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
342
343         if (audio_setup && _startup->engine_control()) {
344                 _startup->engine_control()->set_state (*audio_setup);
345         }
346
347         _startup->set_new_only (should_be_new);
348         if (!load_template.empty()) {
349                 _startup->set_load_template( load_template );
350         }
351         _startup->present ();
352
353         main().run();
354
355         _startup->hide ();
356
357         switch (_startup->response()) {
358         case RESPONSE_OK:
359                 return true;
360         default:
361                 return false;
362         }
363 }
364
365 int
366 ARDOUR_UI::create_engine ()
367 {
368         // this gets called every time by new_session()
369
370         if (engine) {
371                 return 0;
372         }
373
374         loading_message (_("Starting audio engine"));
375
376         try {
377                 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name, ARDOUR_COMMAND_LINE::jack_session_uuid);
378
379         } catch (...) {
380
381                 return -1;
382         }
383
384         engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
385         engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
386         engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
387
388         engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
389
390         ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
391
392         post_engine ();
393
394         return 0;
395 }
396
397 void
398 ARDOUR_UI::post_engine ()
399 {
400         /* Things to be done once we create the AudioEngine
401          */
402
403         ARDOUR::init_post_engine ();
404
405         ActionManager::init ();
406         _tooltips.enable();
407
408         if (setup_windows ()) {
409                 throw failed_constructor ();
410         }
411
412         check_memory_locking();
413
414         /* this is the first point at which all the keybindings are available */
415
416         if (ARDOUR_COMMAND_LINE::show_key_actions) {
417                 vector<string> names;
418                 vector<string> paths;
419                 vector<string> tooltips;
420                 vector<string> keys;
421                 vector<AccelKey> bindings;
422
423                 ActionManager::get_all_actions (names, paths, tooltips, keys, bindings);
424
425                 vector<string>::iterator n;
426                 vector<string>::iterator k;
427                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
428                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
429                 }
430
431                 exit (0);
432         }
433
434         blink_timeout_tag = -1;
435
436         /* this being a GUI and all, we want peakfiles */
437
438         AudioFileSource::set_build_peakfiles (true);
439         AudioFileSource::set_build_missing_peakfiles (true);
440
441         /* set default clock modes */
442
443         if (Profile->get_sae()) {
444                 primary_clock->set_mode (AudioClock::BBT);
445                 secondary_clock->set_mode (AudioClock::MinSec);
446         }  else {
447                 primary_clock->set_mode (AudioClock::Timecode);
448                 secondary_clock->set_mode (AudioClock::BBT);
449         }
450
451         /* start the time-of-day-clock */
452
453 #ifndef GTKOSX
454         /* OS X provides a nearly-always visible wallclock, so don't be stupid */
455         update_wall_clock ();
456         Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
457 #endif
458
459         update_disk_space ();
460         update_cpu_load ();
461         update_sample_rate (engine->frame_rate());
462
463         Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
464         boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
465         Config->map_parameters (pc);
466
467         /* now start and maybe save state */
468
469         if (do_engine_start () == 0) {
470                 if (_session && _session_is_new) {
471                         /* we need to retain initial visual
472                            settings for a new session
473                         */
474                         _session->save_state ("");
475                 }
476         }
477 }
478
479 ARDOUR_UI::~ARDOUR_UI ()
480 {
481         delete keyboard;
482         delete editor;
483         delete mixer;
484         delete add_route_dialog;
485 }
486
487 void
488 ARDOUR_UI::pop_back_splash ()
489 {
490         if (Splash::instance()) {
491                 // Splash::instance()->pop_back();
492                 Splash::instance()->hide ();
493         }
494 }
495
496 gint
497 ARDOUR_UI::configure_timeout ()
498 {
499         if (last_configure_time == 0) {
500                 /* no configure events yet */
501                 return true;
502         }
503
504         /* force a gap of 0.5 seconds since the last configure event
505          */
506
507         if (get_microseconds() - last_configure_time < 500000) {
508                 return true;
509         } else {
510                 have_configure_timeout = false;
511                 cerr << "config event-driven save\n";
512                 save_ardour_state ();
513                 return false;
514         }
515 }
516
517 gboolean
518 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
519 {
520         if (have_configure_timeout) {
521                 last_configure_time = get_microseconds();
522         } else {
523                 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
524                 have_configure_timeout = true;
525         }
526
527         return FALSE;
528 }
529
530 void
531 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
532 {
533         const XMLProperty* prop;
534
535         if ((prop = node.property ("roll")) != 0) {
536                 roll_controllable->set_id (prop->value());
537         }
538         if ((prop = node.property ("stop")) != 0) {
539                 stop_controllable->set_id (prop->value());
540         }
541         if ((prop = node.property ("goto-start")) != 0) {
542                 goto_start_controllable->set_id (prop->value());
543         }
544         if ((prop = node.property ("goto-end")) != 0) {
545                 goto_end_controllable->set_id (prop->value());
546         }
547         if ((prop = node.property ("auto-loop")) != 0) {
548                 auto_loop_controllable->set_id (prop->value());
549         }
550         if ((prop = node.property ("play-selection")) != 0) {
551                 play_selection_controllable->set_id (prop->value());
552         }
553         if ((prop = node.property ("rec")) != 0) {
554                 rec_controllable->set_id (prop->value());
555         }
556         if ((prop = node.property ("shuttle")) != 0) {
557                 shuttle_box->controllable()->set_id (prop->value());
558         }
559
560 }
561
562 XMLNode&
563 ARDOUR_UI::get_transport_controllable_state ()
564 {
565         XMLNode* node = new XMLNode(X_("TransportControllables"));
566         char buf[64];
567
568         roll_controllable->id().print (buf, sizeof (buf));
569         node->add_property (X_("roll"), buf);
570         stop_controllable->id().print (buf, sizeof (buf));
571         node->add_property (X_("stop"), buf);
572         goto_start_controllable->id().print (buf, sizeof (buf));
573         node->add_property (X_("goto_start"), buf);
574         goto_end_controllable->id().print (buf, sizeof (buf));
575         node->add_property (X_("goto_end"), buf);
576         auto_loop_controllable->id().print (buf, sizeof (buf));
577         node->add_property (X_("auto_loop"), buf);
578         play_selection_controllable->id().print (buf, sizeof (buf));
579         node->add_property (X_("play_selection"), buf);
580         rec_controllable->id().print (buf, sizeof (buf));
581         node->add_property (X_("rec"), buf);
582         shuttle_box->controllable()->id().print (buf, sizeof (buf));
583         node->add_property (X_("shuttle"), buf);
584
585         return *node;
586 }
587
588
589 gint
590 ARDOUR_UI::autosave_session ()
591 {
592         if (g_main_depth() > 1) {
593                 /* inside a recursive main loop,
594                    give up because we may not be able to
595                    take a lock.
596                 */
597                 return 1;
598         }
599
600         if (!Config->get_periodic_safety_backups()) {
601                 return 1;
602         }
603
604         if (_session) {
605                 _session->maybe_write_autosave();
606         }
607
608         return 1;
609 }
610
611 void
612 ARDOUR_UI::update_autosave ()
613 {
614         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_autosave)
615
616         if (_session && _session->dirty()) {
617                 if (_autosave_connection.connected()) {
618                         _autosave_connection.disconnect();
619                 }
620
621                 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
622                                 Config->get_periodic_safety_backup_interval() * 1000);
623
624         } else {
625                 if (_autosave_connection.connected()) {
626                         _autosave_connection.disconnect();
627                 }
628         }
629 }
630
631 void
632 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
633 {
634         string title;
635         if (we_set_params) {
636                 title = string_compose (_("%1 could not start JACK"), PROGRAM_NAME);
637         } else {
638                 title = string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME);
639         }
640
641         MessageDialog win (title,
642                            false,
643                            Gtk::MESSAGE_INFO,
644                            Gtk::BUTTONS_NONE);
645
646         if (we_set_params) {
647                 win.set_secondary_text(_("There are several possible reasons:\n\
648 \n\
649 1) You requested audio parameters that are not supported..\n\
650 2) JACK is running as another user.\n\
651 \n\
652 Please consider the possibilities, and perhaps try different parameters."));
653         } else {
654                 win.set_secondary_text(_("There are several possible reasons:\n\
655 \n\
656 1) JACK is not running.\n\
657 2) JACK is running as another user, perhaps root.\n\
658 3) There is already another client called \"ardour\".\n\
659 \n\
660 Please consider the possibilities, and perhaps (re)start JACK."));
661         }
662
663         if (toplevel) {
664                 win.set_transient_for (*toplevel);
665         }
666
667         if (we_set_params) {
668                 win.add_button (Stock::OK, RESPONSE_CLOSE);
669         } else {
670                 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
671         }
672
673         win.set_default_response (RESPONSE_CLOSE);
674
675         win.show_all ();
676         win.set_position (Gtk::WIN_POS_CENTER);
677         pop_back_splash ();
678
679         /* we just don't care about the result, but we want to block */
680
681         win.run ();
682 }
683
684 void
685 ARDOUR_UI::startup ()
686 {
687         Application* app = Application::instance ();
688
689         app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
690         app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load));
691
692 #ifdef PHONE_HOME
693         call_the_mothership (VERSIONSTRING);
694 #endif
695
696         app->ready ();
697
698         if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) {
699                 exit (1);
700         }
701
702         use_config ();
703
704         goto_editor_window ();
705
706         /* Add the window proxies here; their addition may cause windows to be opened, and we want them
707            to be opened on top of the editor window that goto_editor_window() just opened.
708         */
709         add_window_proxy (location_ui);
710         add_window_proxy (big_clock_window);
711         for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
712                 add_window_proxy (_global_port_matrix[*i]);
713         }
714
715         BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
716 }
717
718 void
719 ARDOUR_UI::no_memory_warning ()
720 {
721         XMLNode node (X_("no-memory-warning"));
722         Config->add_instant_xml (node);
723 }
724
725 void
726 ARDOUR_UI::check_memory_locking ()
727 {
728 #ifdef __APPLE__
729         /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
730         return;
731 #else // !__APPLE__
732
733         XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
734
735         if (engine->is_realtime() && memory_warning_node == 0) {
736
737                 struct rlimit limits;
738                 int64_t ram;
739                 long pages, page_size;
740
741                 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
742                         ram = 0;
743                 } else {
744                         ram = (int64_t) pages * (int64_t) page_size;
745                 }
746
747                 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
748                         return;
749                 }
750
751                 if (limits.rlim_cur != RLIM_INFINITY) {
752
753                         if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
754
755                                 MessageDialog msg (
756                                         string_compose (
757                                                 _("WARNING: Your system has a limit for maximum amount of locked memory. "
758                                                   "This might cause %1 to run out of memory before your system "
759                                                   "runs out of memory. \n\n"
760                                                   "You can view the memory limit with 'ulimit -l', "
761                                                   "and it is normally controlled by /etc/security/limits.conf"),
762                                                 PROGRAM_NAME).c_str());
763
764                                 VBox* vbox = msg.get_vbox();
765                                 HBox hbox;
766                                 CheckButton cb (_("Do not show this window again"));
767
768                                 cb.signal_toggled().connect (sigc::mem_fun (*this, &ARDOUR_UI::no_memory_warning));
769
770                                 hbox.pack_start (cb, true, false);
771                                 vbox->pack_start (hbox);
772                                 cb.show();
773                                 vbox->show();
774                                 hbox.show ();
775
776                                 pop_back_splash ();
777
778                                 editor->ensure_float (msg);
779                                 msg.run ();
780                         }
781                 }
782         }
783 #endif // !__APPLE__
784 }
785
786
787 void
788 ARDOUR_UI::queue_finish ()
789 {
790         Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish));
791 }
792
793 bool
794 ARDOUR_UI::idle_finish ()
795 {
796         finish ();
797         return false; /* do not call again */
798 }
799
800 void
801 ARDOUR_UI::finish()
802 {
803         if (_session) {
804                 int tries = 0;
805
806                 if (_session->transport_rolling() && (++tries < 8)) {
807                         _session->request_stop (false, true);
808                         usleep (10000);
809                 }
810
811                 if (_session->dirty()) {
812                         vector<string> actions;
813                         actions.push_back (_("Don't quit"));
814                         actions.push_back (_("Just quit"));
815                         actions.push_back (_("Save and quit"));
816                         switch (ask_about_saving_session(actions)) {
817                         case -1:
818                                 return;
819                                 break;
820                         case 1:
821                                 /* use the default name */
822                                 if (save_state_canfail ("")) {
823                                         /* failed - don't quit */
824                                         MessageDialog msg (*editor,
825                                                            _("\
826 Ardour was unable to save your session.\n\n\
827 If you still wish to quit, please use the\n\n\
828 \"Just quit\" option."));
829                                         pop_back_splash();
830                                         msg.run ();
831                                         return;
832                                 }
833                                 break;
834                         case 0:
835                                 break;
836                         }
837                 }
838
839                 second_connection.disconnect ();
840                 point_one_second_connection.disconnect ();
841                 point_oh_five_second_connection.disconnect ();
842                 point_zero_one_second_connection.disconnect();
843         }
844
845         /* Save state before deleting the session, as that causes some
846            windows to be destroyed before their visible state can be
847            saved.
848         */
849         save_ardour_state ();
850
851         if (_session) {
852                 // _session->set_deletion_in_progress ();
853                 _session->set_clean ();
854                 _session->remove_pending_capture_state ();
855                 delete _session;
856                 _session = 0;
857         }
858
859         ArdourDialog::close_all_dialogs ();
860         engine->stop (true);
861         quit ();
862 }
863
864 int
865 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
866 {
867         ArdourDialog window (_("Unsaved Session"));
868         Gtk::HBox dhbox;  // the hbox for the image and text
869         Gtk::Label  prompt_label;
870         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
871
872         string msg;
873
874         assert (actions.size() >= 3);
875
876         window.add_button (actions[0], RESPONSE_REJECT);
877         window.add_button (actions[1], RESPONSE_APPLY);
878         window.add_button (actions[2], RESPONSE_ACCEPT);
879
880         window.set_default_response (RESPONSE_ACCEPT);
881
882         Gtk::Button noquit_button (msg);
883         noquit_button.set_name ("EditorGTKButton");
884
885         string prompt;
886
887         if (_session->snap_name() == _session->name()) {
888                 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?"),
889                                         _session->snap_name());
890         } else {
891                 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?"),
892                                         _session->snap_name());
893         }
894
895         prompt_label.set_text (prompt);
896         prompt_label.set_name (X_("PrompterLabel"));
897         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
898
899         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
900         dhbox.set_homogeneous (false);
901         dhbox.pack_start (*dimage, false, false, 5);
902         dhbox.pack_start (prompt_label, true, false, 5);
903         window.get_vbox()->pack_start (dhbox);
904
905         window.set_name (_("Prompter"));
906         window.set_position (Gtk::WIN_POS_MOUSE);
907         window.set_modal (true);
908         window.set_resizable (false);
909
910         dhbox.show();
911         prompt_label.show();
912         dimage->show();
913         window.show();
914         window.set_keep_above (true);
915         window.present ();
916
917         ResponseType r = (ResponseType) window.run();
918
919         window.hide ();
920
921         switch (r) {
922         case RESPONSE_ACCEPT: // save and get out of here
923                 return 1;
924         case RESPONSE_APPLY:  // get out of here
925                 return 0;
926         default:
927                 break;
928         }
929
930         return -1;
931 }
932
933 gint
934 ARDOUR_UI::every_second ()
935 {
936         update_cpu_load ();
937         update_buffer_load ();
938         update_disk_space ();
939         return TRUE;
940 }
941
942 gint
943 ARDOUR_UI::every_point_one_seconds ()
944 {
945         shuttle_box->update_speed_display ();
946         RapidScreenUpdate(); /* EMIT_SIGNAL */
947         return TRUE;
948 }
949
950 gint
951 ARDOUR_UI::every_point_zero_one_seconds ()
952 {
953         // august 2007: actual update frequency: 40Hz, not 100Hz
954
955         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
956         return TRUE;
957 }
958
959 void
960 ARDOUR_UI::update_sample_rate (framecnt_t)
961 {
962         char buf[32];
963
964         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
965
966         if (!engine->connected()) {
967
968                 snprintf (buf, sizeof (buf), _("disconnected"));
969
970         } else {
971
972                 framecnt_t rate = engine->frame_rate();
973
974                 if (fmod (rate, 1000.0) != 0.0) {
975                         snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
976                                   (float) rate/1000.0f,
977                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
978                 } else {
979                         snprintf (buf, sizeof (buf), _("%" PRId64 " kHz / %4.1f ms"),
980                                   rate/1000,
981                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
982                 }
983         }
984
985         sample_rate_label.set_text (buf);
986 }
987
988 void
989 ARDOUR_UI::update_format ()
990 {
991         if (!_session) {
992                 format_label.set_text ("");
993                 return;
994         }
995
996         stringstream s;
997
998         switch (_session->config.get_native_file_header_format ()) {
999         case BWF:
1000                 s << "BWF";
1001                 break;
1002         case WAVE:
1003                 s << "WAV";
1004                 break;
1005         case WAVE64:
1006                 s << "WAV64";
1007                 break;
1008         case CAF:
1009                 s << "CAF";
1010                 break;
1011         case AIFF:
1012                 s << "AIFF";
1013                 break;
1014         case iXML:
1015                 s << "iXML";
1016                 break;
1017         case RF64:
1018                 s << "RF64";
1019                 break;
1020         }
1021
1022         s << " ";
1023         
1024         switch (_session->config.get_native_file_data_format ()) {
1025         case FormatFloat:
1026                 s << "32-float";
1027                 break;
1028         case FormatInt24:
1029                 s << "24-int";
1030                 break;
1031         case FormatInt16:
1032                 s << "16-int";
1033                 break;
1034         }
1035
1036         format_label.set_text (s.str ());
1037 }
1038
1039 void
1040 ARDOUR_UI::update_cpu_load ()
1041 {
1042         char buf[32];
1043         snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
1044         cpu_load_label.set_text (buf);
1045 }
1046
1047 void
1048 ARDOUR_UI::update_buffer_load ()
1049 {
1050         char buf[64];
1051
1052         if (_session) {
1053                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
1054                           _session->playback_load(), _session->capture_load());
1055                 buffer_load_label.set_text (buf);
1056         } else {
1057                 buffer_load_label.set_text ("");
1058         }
1059 }
1060
1061 void
1062 ARDOUR_UI::count_recenabled_streams (Route& route)
1063 {
1064         Track* track = dynamic_cast<Track*>(&route);
1065         if (track && track->record_enabled()) {
1066                 rec_enabled_streams += track->n_inputs().n_total();
1067         }
1068 }
1069
1070 void
1071 ARDOUR_UI::update_disk_space()
1072 {
1073         if (_session == 0) {
1074                 return;
1075         }
1076
1077         framecnt_t frames = _session->available_capture_duration();
1078         char buf[64];
1079         framecnt_t fr = _session->frame_rate();
1080
1081         if (frames == max_framecnt) {
1082                 strcpy (buf, _("Disk: 24hrs+"));
1083         } else {
1084                 rec_enabled_streams = 0;
1085                 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
1086
1087                 if (rec_enabled_streams) {
1088                         frames /= rec_enabled_streams;
1089                 }
1090
1091                 int hrs;
1092                 int mins;
1093                 int secs;
1094
1095                 hrs  = frames / (fr * 3600);
1096                 frames -= hrs * fr * 3600;
1097                 mins = frames / (fr * 60);
1098                 frames -= mins * fr * 60;
1099                 secs = frames / fr;
1100
1101                 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
1102         }
1103
1104         disk_space_label.set_text (buf);
1105
1106         // An attempt to make the disk space label flash red when space has run out.
1107
1108         if (frames < fr * 60 * 5) {
1109         /*      disk_space_box.style ("disk_space_label_empty"); */
1110         } else {
1111         /*      disk_space_box.style ("disk_space_label"); */
1112         }
1113
1114 }
1115
1116 gint
1117 ARDOUR_UI::update_wall_clock ()
1118 {
1119         time_t now;
1120         struct tm *tm_now;
1121         char buf[16];
1122
1123         time (&now);
1124         tm_now = localtime (&now);
1125
1126         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1127         wall_clock_label.set_text (buf);
1128
1129         return TRUE;
1130 }
1131
1132 gint
1133 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1134 {
1135         session_popup_menu->popup (0, 0);
1136         return TRUE;
1137 }
1138
1139 void
1140 ARDOUR_UI::redisplay_recent_sessions ()
1141 {
1142         std::vector<sys::path> session_directories;
1143         RecentSessionsSorter cmp;
1144
1145         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1146         recent_session_model->clear ();
1147
1148         ARDOUR::RecentSessions rs;
1149         ARDOUR::read_recent_sessions (rs);
1150
1151         if (rs.empty()) {
1152                 recent_session_display.set_model (recent_session_model);
1153                 return;
1154         }
1155         //
1156         // sort them alphabetically
1157         sort (rs.begin(), rs.end(), cmp);
1158
1159         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1160                 session_directories.push_back ((*i).second);
1161         }
1162
1163         for (vector<sys::path>::const_iterator i = session_directories.begin();
1164                         i != session_directories.end(); ++i)
1165         {
1166                 std::vector<sys::path> state_file_paths;
1167
1168                 // now get available states for this session
1169
1170                 get_state_files_in_directory (*i, state_file_paths);
1171
1172                 vector<string*>* states;
1173                 vector<const gchar*> item;
1174                 string fullpath = (*i).to_string();
1175
1176                 /* remove any trailing / */
1177
1178                 if (fullpath[fullpath.length()-1] == '/') {
1179                         fullpath = fullpath.substr (0, fullpath.length()-1);
1180                 }
1181
1182                 /* check whether session still exists */
1183                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1184                         /* session doesn't exist */
1185                         cerr << "skipping non-existent session " << fullpath << endl;
1186                         continue;
1187                 }
1188
1189                 /* now get available states for this session */
1190
1191                 if ((states = Session::possible_states (fullpath)) == 0) {
1192                         /* no state file? */
1193                         continue;
1194                 }
1195
1196                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1197
1198                 Gtk::TreeModel::Row row = *(recent_session_model->append());
1199
1200                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1201                 row[recent_session_columns.fullpath] = fullpath;
1202
1203                 if (state_file_names.size() > 1) {
1204
1205                         // add the children
1206
1207                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1208                                         i2 != state_file_names.end(); ++i2)
1209                         {
1210
1211                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1212
1213                                 child_row[recent_session_columns.visible_name] = *i2;
1214                                 child_row[recent_session_columns.fullpath] = fullpath;
1215                         }
1216                 }
1217         }
1218
1219         recent_session_display.set_model (recent_session_model);
1220 }
1221
1222 void
1223 ARDOUR_UI::build_session_selector ()
1224 {
1225         session_selector_window = new ArdourDialog (_("Recent Sessions"));
1226
1227         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1228
1229         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1230         session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1231         session_selector_window->set_default_response (RESPONSE_ACCEPT);
1232         recent_session_model = TreeStore::create (recent_session_columns);
1233         recent_session_display.set_model (recent_session_model);
1234         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1235         recent_session_display.set_headers_visible (false);
1236         recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1237         recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1238
1239         scroller->add (recent_session_display);
1240         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1241
1242         session_selector_window->set_name ("SessionSelectorWindow");
1243         session_selector_window->set_size_request (200, 400);
1244         session_selector_window->get_vbox()->pack_start (*scroller);
1245
1246         recent_session_display.show();
1247         scroller->show();
1248         //session_selector_window->get_vbox()->show();
1249 }
1250
1251 void
1252 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1253 {
1254         session_selector_window->response (RESPONSE_ACCEPT);
1255 }
1256
1257 void
1258 ARDOUR_UI::open_recent_session ()
1259 {
1260         bool can_return = (_session != 0);
1261
1262         if (session_selector_window == 0) {
1263                 build_session_selector ();
1264         }
1265
1266         redisplay_recent_sessions ();
1267
1268         while (true) {
1269
1270                 session_selector_window->set_position (WIN_POS_MOUSE);
1271
1272                 ResponseType r = (ResponseType) session_selector_window->run ();
1273
1274                 switch (r) {
1275                 case RESPONSE_ACCEPT:
1276                         break;
1277                 default:
1278                         if (can_return) {
1279                                 session_selector_window->hide();
1280                                 return;
1281                         } else {
1282                                 exit (1);
1283                         }
1284                 }
1285
1286                 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1287                         continue;
1288                 }
1289
1290                 session_selector_window->hide();
1291
1292                 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1293
1294                 if (i == recent_session_model->children().end()) {
1295                         return;
1296                 }
1297
1298                 std::string path = (*i)[recent_session_columns.fullpath];
1299                 std::string state = (*i)[recent_session_columns.visible_name];
1300
1301                 _session_is_new = false;
1302
1303                 if (load_session (path, state) == 0) {
1304                         break;
1305                 }
1306
1307                 can_return = false;
1308         }
1309 }
1310
1311 bool
1312 ARDOUR_UI::check_audioengine ()
1313 {
1314         if (engine) {
1315                 if (!engine->connected()) {
1316                         MessageDialog msg (string_compose (
1317                                                    _("%1 is not connected to JACK\n"
1318                                                      "You cannot open or close sessions in this condition"),
1319                                                    PROGRAM_NAME));
1320                         pop_back_splash ();
1321                         msg.run ();
1322                         return false;
1323                 }
1324                 return true;
1325         } else {
1326                 return false;
1327         }
1328 }
1329
1330 void
1331 ARDOUR_UI::open_session ()
1332 {
1333         if (!check_audioengine()) {
1334                 return;
1335
1336         }
1337
1338         /* popup selector window */
1339
1340         if (open_session_selector == 0) {
1341
1342                 /* ardour sessions are folders */
1343
1344                 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1345                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1346                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1347                 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1348
1349                 FileFilter session_filter;
1350                 session_filter.add_pattern ("*.ardour");
1351                 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1352                 open_session_selector->add_filter (session_filter);
1353                 open_session_selector->set_filter (session_filter);
1354         }
1355
1356         int response = open_session_selector->run();
1357         open_session_selector->hide ();
1358
1359         switch (response) {
1360         case RESPONSE_ACCEPT:
1361                 break;
1362         default:
1363                 open_session_selector->hide();
1364                 return;
1365         }
1366
1367         open_session_selector->hide();
1368         string session_path = open_session_selector->get_filename();
1369         string path, name;
1370         bool isnew;
1371
1372         if (session_path.length() > 0) {
1373                 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1374                         _session_is_new = isnew;
1375                         load_session (path, name);
1376                 }
1377         }
1378 }
1379
1380
1381 void
1382 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, string const & name_template)
1383 {
1384         list<boost::shared_ptr<MidiTrack> > tracks;
1385
1386         if (_session == 0) {
1387                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1388                 return;
1389         }
1390
1391         try {
1392                 if (disk) {
1393
1394                         tracks = _session->new_midi_track (ARDOUR::Normal, route_group, how_many, name_template);
1395
1396                         if (tracks.size() != how_many) {
1397                                 if (how_many == 1) {
1398                                         error << _("could not create a new midi track") << endmsg;
1399                                 } else {
1400                                         error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1401                                 }
1402                         }
1403                 } /*else {
1404                         if ((route = _session->new_midi_route ()) == 0) {
1405                                 error << _("could not create new midi bus") << endmsg;
1406                         }
1407                 }*/
1408         }
1409
1410         catch (...) {
1411                 MessageDialog msg (*editor,
1412                                    string_compose (_("There are insufficient JACK ports available\n\
1413 to create a new track or bus.\n\
1414 You should save %1, exit and\n\
1415 restart JACK with more ports."), PROGRAM_NAME));
1416                 msg.run ();
1417         }
1418 }
1419
1420
1421 void
1422 ARDOUR_UI::session_add_audio_route (
1423         bool track,
1424         int32_t input_channels,
1425         int32_t output_channels,
1426         ARDOUR::TrackMode mode,
1427         RouteGroup* route_group,
1428         uint32_t how_many,
1429         string const & name_template
1430         )
1431 {
1432         list<boost::shared_ptr<AudioTrack> > tracks;
1433         RouteList routes;
1434
1435         if (_session == 0) {
1436                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1437                 return;
1438         }
1439
1440         try {
1441                 if (track) {
1442                         tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
1443
1444                         if (tracks.size() != how_many) {
1445                                 if (how_many == 1) {
1446                                         error << _("could not create a new audio track") << endmsg;
1447                                 } else {
1448                                         error << string_compose (_("could only create %1 of %2 new audio %3"),
1449                                                                  tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1450                                 }
1451                         }
1452
1453                 } else {
1454
1455                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
1456
1457                         if (routes.size() != how_many) {
1458                                 if (how_many == 1) {
1459                                         error << _("could not create a new audio track") << endmsg;
1460                                 } else {
1461                                         error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1462                                 }
1463                         }
1464                 }
1465         }
1466
1467         catch (...) {
1468                 MessageDialog msg (*editor,
1469                                    string_compose (_("There are insufficient JACK ports available\n\
1470 to create a new track or bus.\n\
1471 You should save %1, exit and\n\
1472 restart JACK with more ports."), PROGRAM_NAME));
1473                 pop_back_splash ();
1474                 msg.run ();
1475         }
1476 }
1477
1478 void
1479 ARDOUR_UI::do_transport_locate (framepos_t new_position, bool with_roll)
1480 {
1481         framecnt_t _preroll = 0;
1482
1483         if (_session) {
1484                 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1485                 // _preroll = _session->convert_to_frames_at (new_position, Config->get_preroll());
1486
1487                 if (new_position > _preroll) {
1488                         new_position -= _preroll;
1489                 } else {
1490                         new_position = 0;
1491                 }
1492
1493                 _session->request_locate (new_position, with_roll);
1494         }
1495 }
1496
1497 void
1498 ARDOUR_UI::transport_goto_start ()
1499 {
1500         if (_session) {
1501                 _session->goto_start();
1502
1503                 /* force displayed area in editor to start no matter
1504                    what "follow playhead" setting is.
1505                 */
1506
1507                 if (editor) {
1508                         editor->center_screen (_session->current_start_frame ());
1509                 }
1510         }
1511 }
1512
1513 void
1514 ARDOUR_UI::transport_goto_zero ()
1515 {
1516         if (_session) {
1517                 _session->request_locate (0);
1518
1519                 /* force displayed area in editor to start no matter
1520                    what "follow playhead" setting is.
1521                 */
1522
1523                 if (editor) {
1524                         editor->reset_x_origin (0);
1525                 }
1526         }
1527 }
1528
1529 void
1530 ARDOUR_UI::transport_goto_wallclock ()
1531 {
1532         if (_session && editor) {
1533
1534                 time_t now;
1535                 struct tm tmnow;
1536                 framepos_t frames;
1537
1538                 time (&now);
1539                 localtime_r (&now, &tmnow);
1540
1541                 frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate());
1542                 frames += tmnow.tm_min * (60 * _session->frame_rate());
1543                 frames += tmnow.tm_sec * _session->frame_rate();
1544
1545                 _session->request_locate (frames, _session->transport_rolling ());
1546
1547                 /* force displayed area in editor to start no matter
1548                    what "follow playhead" setting is.
1549                 */
1550
1551                 if (editor) {
1552                         editor->center_screen (frames);
1553                 }
1554         }
1555 }
1556
1557 void
1558 ARDOUR_UI::transport_goto_end ()
1559 {
1560         if (_session) {
1561                 framepos_t const frame = _session->current_end_frame();
1562                 _session->request_locate (frame);
1563
1564                 /* force displayed area in editor to start no matter
1565                    what "follow playhead" setting is.
1566                 */
1567
1568                 if (editor) {
1569                         editor->center_screen (frame);
1570                 }
1571         }
1572 }
1573
1574 void
1575 ARDOUR_UI::transport_stop ()
1576 {
1577         if (!_session) {
1578                 return;
1579         }
1580
1581         if (_session->is_auditioning()) {
1582                 _session->cancel_audition ();
1583                 return;
1584         }
1585
1586         _session->request_stop (false, true);
1587 }
1588
1589 void
1590 ARDOUR_UI::transport_stop_and_forget_capture ()
1591 {
1592         if (_session) {
1593                 _session->request_stop (true, true);
1594         }
1595 }
1596
1597 void
1598 ARDOUR_UI::remove_last_capture()
1599 {
1600         if (editor) {
1601                 editor->remove_last_capture();
1602         }
1603 }
1604
1605 void
1606 ARDOUR_UI::transport_record (bool roll)
1607 {
1608
1609         if (_session) {
1610                 switch (_session->record_status()) {
1611                 case Session::Disabled:
1612                         if (_session->ntracks() == 0) {
1613                                 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1614                                 msg.run ();
1615                                 return;
1616                         }
1617                         _session->maybe_enable_record ();
1618                         if (roll) {
1619                                 transport_roll ();
1620                         }
1621                         break;
1622                 case Session::Recording:
1623                         if (roll) {
1624                                 _session->request_stop();
1625                         } else {
1626                                 _session->disable_record (false, true);
1627                         }
1628                         break;
1629
1630                 case Session::Enabled:
1631                         _session->disable_record (false, true);
1632                 }
1633         }
1634         //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " _session->record_status() = " << _session->record_status() << endl;
1635 }
1636
1637 void
1638 ARDOUR_UI::transport_roll ()
1639 {
1640         if (!_session) {
1641                 return;
1642         }
1643
1644         if (_session->is_auditioning()) {
1645                 return;
1646         }
1647
1648 #if 0
1649         if (_session->config.get_external_sync()) {
1650                 switch (_session->config.get_sync_source()) {
1651                 case JACK:
1652                         break;
1653                 default:
1654                         /* transport controlled by the master */
1655                         return;
1656                 }
1657         }
1658 #endif
1659
1660         bool rolling = _session->transport_rolling();
1661
1662         if (_session->get_play_loop()) {
1663                 /* XXX it is not possible to just leave seamless loop and keep
1664                    playing at present (nov 4th 2009)
1665                 */
1666                 if (!Config->get_seamless_loop()) {
1667                         _session->request_play_loop (false, true);
1668                 }
1669         } else if (_session->get_play_range () && !join_play_range_button.get_active()) {
1670                 /* stop playing a range if we currently are */
1671                 _session->request_play_range (0, true);
1672         }
1673
1674         if (join_play_range_button.get_active()) {
1675                 _session->request_play_range (&editor->get_selection().time, true);
1676         }
1677
1678         if (!rolling) {
1679                 _session->request_transport_speed (1.0f);
1680         }
1681 }
1682
1683 void
1684 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1685 {
1686
1687         if (!_session) {
1688                 return;
1689         }
1690
1691         if (_session->is_auditioning()) {
1692                 _session->cancel_audition ();
1693                 return;
1694         }
1695
1696         if (_session->config.get_external_sync()) {
1697                 switch (_session->config.get_sync_source()) {
1698                 case JACK:
1699                         break;
1700                 default:
1701                         /* transport controlled by the master */
1702                         return;
1703                 }
1704         }
1705
1706         bool rolling = _session->transport_rolling();
1707         bool affect_transport = true;
1708
1709         if (rolling && roll_out_of_bounded_mode) {
1710                 /* drop out of loop/range playback but leave transport rolling */
1711                 if (_session->get_play_loop()) {
1712                         if (Config->get_seamless_loop()) {
1713                                 /* the disk buffers contain copies of the loop - we can't
1714                                    just keep playing, so stop the transport. the user
1715                                    can restart as they wish.
1716                                 */
1717                                 affect_transport = true;
1718                         } else {
1719                                 /* disk buffers are normal, so we can keep playing */
1720                                 affect_transport = false;
1721                         }
1722                         _session->request_play_loop (false, true);
1723                 } else if (_session->get_play_range ()) {
1724                         affect_transport = false;
1725                         _session->request_play_range (0, true);
1726                 }
1727         }
1728
1729         if (affect_transport) {
1730                 if (rolling) {
1731                         _session->request_stop (with_abort, true);
1732                 } else {
1733                         if (join_play_range_button.get_active()) {
1734                                 _session->request_play_range (&editor->get_selection().time, true);
1735                         }
1736
1737                         _session->request_transport_speed (1.0f);
1738                 }
1739         }
1740 }
1741
1742 void
1743 ARDOUR_UI::toggle_session_auto_loop ()
1744 {
1745         if (!_session) {
1746                 return;
1747         }
1748
1749         if (_session->get_play_loop()) {
1750
1751                 if (_session->transport_rolling()) {
1752
1753                         Location * looploc = _session->locations()->auto_loop_location();
1754
1755                         if (looploc) {
1756                                 _session->request_locate (looploc->start(), true);
1757                                 _session->request_play_loop (false);
1758                         }
1759
1760                 } else {
1761                         _session->request_play_loop (false);
1762                 }
1763         } else {
1764
1765           Location * looploc = _session->locations()->auto_loop_location();
1766
1767                 if (looploc) {
1768                         _session->request_play_loop (true);
1769                 }
1770         }
1771 }
1772
1773 void
1774 ARDOUR_UI::transport_play_selection ()
1775 {
1776         if (!_session) {
1777                 return;
1778         }
1779
1780         editor->play_selection ();
1781 }
1782
1783 void
1784 ARDOUR_UI::transport_rewind (int option)
1785 {
1786         float current_transport_speed;
1787
1788         if (_session) {
1789                 current_transport_speed = _session->transport_speed();
1790
1791                 if (current_transport_speed >= 0.0f) {
1792                         switch (option) {
1793                         case 0:
1794                                 _session->request_transport_speed (-1.0f);
1795                                 break;
1796                         case 1:
1797                                 _session->request_transport_speed (-4.0f);
1798                                 break;
1799                         case -1:
1800                                 _session->request_transport_speed (-0.5f);
1801                                 break;
1802                         }
1803                 } else {
1804                         /* speed up */
1805                         _session->request_transport_speed (current_transport_speed * 1.5f);
1806                 }
1807         }
1808 }
1809
1810 void
1811 ARDOUR_UI::transport_forward (int option)
1812 {
1813         float current_transport_speed;
1814
1815         if (_session) {
1816                 current_transport_speed = _session->transport_speed();
1817
1818                 if (current_transport_speed <= 0.0f) {
1819                         switch (option) {
1820                         case 0:
1821                                 _session->request_transport_speed (1.0f);
1822                                 break;
1823                         case 1:
1824                                 _session->request_transport_speed (4.0f);
1825                                 break;
1826                         case -1:
1827                                 _session->request_transport_speed (0.5f);
1828                                 break;
1829                         }
1830                 } else {
1831                         /* speed up */
1832                         _session->request_transport_speed (current_transport_speed * 1.5f);
1833                 }
1834
1835         }
1836 }
1837
1838 void
1839 ARDOUR_UI::toggle_record_enable (uint32_t rid)
1840 {
1841         if (_session == 0) {
1842                 return;
1843         }
1844
1845         boost::shared_ptr<Route> r;
1846
1847         if ((r = _session->route_by_remote_id (rid)) != 0) {
1848
1849                 Track* t;
1850
1851                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1852                         t->set_record_enabled (!t->record_enabled(), this);
1853                 }
1854         }
1855         if (_session == 0) {
1856                 return;
1857         }
1858 }
1859
1860 void
1861 ARDOUR_UI::map_transport_state ()
1862 {
1863         if (!_session) {
1864                 auto_loop_button.set_visual_state (0);
1865                 play_selection_button.set_visual_state (0);
1866                 roll_button.set_visual_state (0);
1867                 stop_button.set_visual_state (1);
1868                 return;
1869         }
1870
1871         shuttle_box->map_transport_state ();
1872
1873         float sp = _session->transport_speed();
1874
1875         if (sp != 0.0f) {
1876
1877                 /* we're rolling */
1878
1879                 if (_session->get_play_range()) {
1880
1881                         play_selection_button.set_visual_state (1);
1882                         roll_button.set_visual_state (0);
1883                         auto_loop_button.set_visual_state (0);
1884
1885                 } else if (_session->get_play_loop ()) {
1886
1887                         auto_loop_button.set_visual_state (1);
1888                         play_selection_button.set_visual_state (0);
1889                         roll_button.set_visual_state (0);
1890
1891                 } else {
1892
1893                         roll_button.set_visual_state (1);
1894                         play_selection_button.set_visual_state (0);
1895                         auto_loop_button.set_visual_state (0);
1896                 }
1897
1898                 if (join_play_range_button.get_active()) {
1899                         /* light up both roll and play-selection if they are joined */
1900                         roll_button.set_visual_state (1);
1901                         play_selection_button.set_visual_state (1);
1902                 }
1903
1904                 stop_button.set_visual_state (0);
1905
1906         } else {
1907
1908                 stop_button.set_visual_state (1);
1909                 roll_button.set_visual_state (0);
1910                 play_selection_button.set_visual_state (0);
1911                 auto_loop_button.set_visual_state (0);
1912                 update_disk_space ();
1913         }
1914 }
1915
1916 void
1917 ARDOUR_UI::engine_stopped ()
1918 {
1919         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
1920         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1921         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1922 }
1923
1924 void
1925 ARDOUR_UI::engine_running ()
1926 {
1927         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
1928         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1929         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1930
1931         Glib::RefPtr<Action> action;
1932         const char* action_name = 0;
1933
1934         switch (engine->frames_per_cycle()) {
1935         case 32:
1936                 action_name = X_("JACKLatency32");
1937                 break;
1938         case 64:
1939                 action_name = X_("JACKLatency64");
1940                 break;
1941         case 128:
1942                 action_name = X_("JACKLatency128");
1943                 break;
1944         case 512:
1945                 action_name = X_("JACKLatency512");
1946                 break;
1947         case 1024:
1948                 action_name = X_("JACKLatency1024");
1949                 break;
1950         case 2048:
1951                 action_name = X_("JACKLatency2048");
1952                 break;
1953         case 4096:
1954                 action_name = X_("JACKLatency4096");
1955                 break;
1956         case 8192:
1957                 action_name = X_("JACKLatency8192");
1958                 break;
1959         default:
1960                 /* XXX can we do anything useful ? */
1961                 break;
1962         }
1963
1964         if (action_name) {
1965
1966                 action = ActionManager::get_action (X_("JACK"), action_name);
1967
1968                 if (action) {
1969                         Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1970                         ract->set_active ();
1971                 }
1972         }
1973 }
1974
1975 void
1976 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
1977 {
1978         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
1979                 /* we can't rely on the original string continuing to exist when we are called
1980                    again in the GUI thread, so make a copy and note that we need to
1981                    free it later.
1982                 */
1983                 char *copy = strdup (reason);
1984                 Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
1985                 return;
1986         }
1987
1988         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1989         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1990
1991         update_sample_rate (0);
1992
1993         string msgstr;
1994
1995         /* if the reason is a non-empty string, it means that the backend was shutdown
1996            rather than just Ardour.
1997         */
1998
1999         if (strlen (reason)) {
2000                 msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason);
2001         } else {
2002                 msgstr = string_compose (_("\
2003 JACK has either been shutdown or it\n\
2004 disconnected %1 because %1\n\
2005 was not fast enough. Try to restart\n\
2006 JACK, reconnect and save the session."), PROGRAM_NAME);
2007         }
2008
2009         MessageDialog msg (*editor, msgstr);
2010         pop_back_splash ();
2011         msg.run ();
2012
2013         if (free_reason) {
2014                 free ((char*) reason);
2015         }
2016 }
2017
2018 int32_t
2019 ARDOUR_UI::do_engine_start ()
2020 {
2021         try {
2022                 engine->start();
2023         }
2024
2025         catch (...) {
2026                 engine->stop ();
2027                 error << _("Unable to start the session running")
2028                       << endmsg;
2029                 unload_session ();
2030                 return -2;
2031         }
2032
2033         return 0;
2034 }
2035
2036 void
2037 ARDOUR_UI::setup_theme ()
2038 {
2039         theme_manager->setup_theme();
2040 }
2041
2042 void
2043 ARDOUR_UI::update_clocks ()
2044 {
2045         if (!editor || !editor->dragging_playhead()) {
2046                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
2047         }
2048 }
2049
2050 void
2051 ARDOUR_UI::start_clocking ()
2052 {
2053         clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2054 }
2055
2056 void
2057 ARDOUR_UI::stop_clocking ()
2058 {
2059         clock_signal_connection.disconnect ();
2060 }
2061
2062 void
2063 ARDOUR_UI::toggle_clocking ()
2064 {
2065 #if 0
2066         if (clock_button.get_active()) {
2067                 start_clocking ();
2068         } else {
2069                 stop_clocking ();
2070         }
2071 #endif
2072 }
2073
2074 gint
2075 ARDOUR_UI::_blink (void *arg)
2076
2077 {
2078         ((ARDOUR_UI *) arg)->blink ();
2079         return TRUE;
2080 }
2081
2082 void
2083 ARDOUR_UI::blink ()
2084 {
2085         Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2086 }
2087
2088 void
2089 ARDOUR_UI::start_blinking ()
2090 {
2091         /* Start the blink signal. Everybody with a blinking widget
2092            uses Blink to drive the widget's state.
2093         */
2094
2095         if (blink_timeout_tag < 0) {
2096                 blink_on = false;
2097                 blink_timeout_tag = g_timeout_add (240, _blink, this);
2098         }
2099 }
2100
2101 void
2102 ARDOUR_UI::stop_blinking ()
2103 {
2104         if (blink_timeout_tag >= 0) {
2105                 g_source_remove (blink_timeout_tag);
2106                 blink_timeout_tag = -1;
2107         }
2108 }
2109
2110
2111 /** Ask the user for the name of a new shapshot and then take it.
2112  */
2113
2114 void
2115 ARDOUR_UI::snapshot_session (bool switch_to_it)
2116 {
2117         ArdourPrompter prompter (true);
2118         string snapname;
2119
2120         prompter.set_name ("Prompter");
2121         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2122         prompter.set_title (_("Take Snapshot"));
2123         prompter.set_prompt (_("Name of new snapshot"));
2124
2125         if (!switch_to_it) {
2126                 char timebuf[128];
2127                 time_t n;
2128                 struct tm local_time;
2129
2130                 time (&n);
2131                 localtime_r (&n, &local_time);
2132                 strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
2133                 prompter.set_initial_text (timebuf);
2134         }
2135
2136   again:
2137         switch (prompter.run()) {
2138         case RESPONSE_ACCEPT:
2139         {
2140                 prompter.get_result (snapname);
2141
2142                 bool do_save = (snapname.length() != 0);
2143
2144                 if (do_save) {
2145                         if (snapname.find ('/') != string::npos) {
2146                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2147                                                      "snapshot names may not contain a '/' character"));
2148                                 msg.run ();
2149                                 goto again;
2150                         }
2151                         if (snapname.find ('\\') != string::npos) {
2152                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2153                                                      "snapshot names may not contain a '\\' character"));
2154                                 msg.run ();
2155                                 goto again;
2156                         }
2157                 }
2158
2159                 vector<sys::path> p;
2160                 get_state_files_in_directory (_session->session_directory().root_path(), p);
2161                 vector<string> n = get_file_names_no_extension (p);
2162                 if (find (n.begin(), n.end(), snapname) != n.end()) {
2163
2164                         ArdourDialog confirm (_("Confirm Snapshot Overwrite"), true);
2165                         Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
2166                         confirm.get_vbox()->pack_start (m, true, true);
2167                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
2168                         confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
2169                         confirm.show_all ();
2170                         switch (confirm.run()) {
2171                         case RESPONSE_CANCEL:
2172                                 do_save = false;
2173                         }
2174                 }
2175
2176                 if (do_save) {
2177                         save_state (snapname, switch_to_it);
2178                 }
2179                 break;
2180         }
2181
2182         default:
2183                 break;
2184         }
2185 }
2186
2187 /** Ask the user for the name of a new shapshot and then take it.
2188  */
2189
2190 void
2191 ARDOUR_UI::rename_session ()
2192 {
2193         if (!_session) {
2194                 return;
2195         }
2196
2197         ArdourPrompter prompter (true);
2198         string name;
2199
2200         prompter.set_name ("Prompter");
2201         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2202         prompter.set_title (_("Rename Session"));
2203         prompter.set_prompt (_("New session name"));
2204
2205   again:
2206         switch (prompter.run()) {
2207         case RESPONSE_ACCEPT:
2208         {
2209                 prompter.get_result (name);
2210
2211                 bool do_rename = (name.length() != 0);
2212
2213                 if (do_rename) {
2214                         if (name.find ('/') != string::npos) {
2215                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2216                                                      "session names may not contain a '/' character"));
2217                                 msg.run ();
2218                                 goto again;
2219                         }
2220                         if (name.find ('\\') != string::npos) {
2221                                 MessageDialog msg (_("To ensure compatibility with various systems\n"
2222                                                      "session names may not contain a '\\' character"));
2223                                 msg.run ();
2224                                 goto again;
2225                         }
2226
2227                         switch (_session->rename (name)) {
2228                         case -1: {
2229                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2230                                 msg.set_position (WIN_POS_MOUSE);
2231                                 msg.run ();
2232                                 goto again;
2233                                 break;
2234                         }
2235                         case 0:
2236                                 break;
2237                         default: {
2238                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2239                                 msg.set_position (WIN_POS_MOUSE);
2240                                 msg.run ();
2241                                 break;
2242                         }
2243                         }
2244                 }
2245                 
2246                 break;
2247         }
2248
2249         default:
2250                 break;
2251         }
2252 }
2253
2254 void
2255 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2256 {
2257         XMLNode* node = new XMLNode (X_("UI"));
2258
2259         for (list<WindowProxyBase*>::iterator i = _window_proxies.begin(); i != _window_proxies.end(); ++i) {
2260                 if (!(*i)->rc_configured()) {
2261                         node->add_child_nocopy (*((*i)->get_state ()));
2262                 }
2263         }
2264
2265         node->add_child_nocopy (gui_object_state->get_state());
2266
2267         _session->add_extra_xml (*node);
2268
2269         save_state_canfail (name, switch_to_it);
2270 }
2271
2272 int
2273 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2274 {
2275         if (_session) {
2276                 int ret;
2277
2278                 if (name.length() == 0) {
2279                         name = _session->snap_name();
2280                 }
2281
2282                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2283                         return ret;
2284                 }
2285         }
2286
2287         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2288         return 0;
2289 }
2290
2291 void
2292 ARDOUR_UI::primary_clock_value_changed ()
2293 {
2294         if (_session) {
2295                 _session->request_locate (primary_clock->current_time ());
2296         }
2297 }
2298
2299 void
2300 ARDOUR_UI::big_clock_value_changed ()
2301 {
2302         if (_session) {
2303                 _session->request_locate (big_clock->current_time ());
2304         }
2305 }
2306
2307 void
2308 ARDOUR_UI::secondary_clock_value_changed ()
2309 {
2310         if (_session) {
2311                 _session->request_locate (secondary_clock->current_time ());
2312         }
2313 }
2314
2315 void
2316 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2317 {
2318         if (_session == 0) {
2319                 return;
2320         }
2321
2322         if (_session->step_editing()) {
2323                 return;
2324         }
2325
2326         Session::RecordState const r = _session->record_status ();
2327         bool const h = _session->have_rec_enabled_track ();
2328
2329         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2330                 if (onoff) {
2331                         rec_button.set_visual_state (2);
2332                 } else {
2333                         rec_button.set_visual_state (0);
2334                 }
2335         } else if (r == Session::Recording && h) {
2336                 rec_button.set_visual_state (1);
2337         } else {
2338                 rec_button.set_visual_state (0);
2339         }
2340 }
2341
2342 void
2343 ARDOUR_UI::save_template ()
2344 {
2345         ArdourPrompter prompter (true);
2346         string name;
2347
2348         if (!check_audioengine()) {
2349                 return;
2350         }
2351
2352         prompter.set_name (X_("Prompter"));
2353         prompter.set_title (_("Save Template"));
2354         prompter.set_prompt (_("Name for template:"));
2355         prompter.set_initial_text(_session->name() + _("-template"));
2356         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2357
2358         switch (prompter.run()) {
2359         case RESPONSE_ACCEPT:
2360                 prompter.get_result (name);
2361
2362                 if (name.length()) {
2363                         _session->save_template (name);
2364                 }
2365                 break;
2366
2367         default:
2368                 break;
2369         }
2370 }
2371
2372 void
2373 ARDOUR_UI::edit_metadata ()
2374 {
2375         SessionMetadataEditor dialog;
2376         dialog.set_session (_session);
2377         editor->ensure_float (dialog);
2378         dialog.run ();
2379 }
2380
2381 void
2382 ARDOUR_UI::import_metadata ()
2383 {
2384         SessionMetadataImporter dialog;
2385         dialog.set_session (_session);
2386         editor->ensure_float (dialog);
2387         dialog.run ();
2388 }
2389
2390 bool
2391 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2392 {
2393         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2394
2395         MessageDialog msg (str,
2396                            false,
2397                            Gtk::MESSAGE_WARNING,
2398                            Gtk::BUTTONS_YES_NO,
2399                            true);
2400
2401
2402         msg.set_name (X_("OpenExistingDialog"));
2403         msg.set_title (_("Open Existing Session"));
2404         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2405         msg.set_position (Gtk::WIN_POS_MOUSE);
2406         pop_back_splash ();
2407
2408         switch (msg.run()) {
2409         case RESPONSE_YES:
2410                 return true;
2411                 break;
2412         }
2413         return false;
2414 }
2415
2416 int
2417 ARDOUR_UI::build_session_from_nsd (const std::string& session_path, const std::string& session_name)
2418 {
2419         BusProfile bus_profile;
2420
2421         if (Profile->get_sae()) {
2422
2423                 bus_profile.master_out_channels = 2;
2424                 bus_profile.input_ac = AutoConnectPhysical;
2425                 bus_profile.output_ac = AutoConnectMaster;
2426                 bus_profile.requested_physical_in = 0; // use all available
2427                 bus_profile.requested_physical_out = 0; // use all available
2428
2429         } else {
2430
2431                 /* get settings from advanced section of NSD */
2432
2433                 if (_startup->create_master_bus()) {
2434                         bus_profile.master_out_channels = (uint32_t) _startup->master_channel_count();
2435                 } else {
2436                         bus_profile.master_out_channels = 0;
2437                 }
2438
2439                 if (_startup->connect_inputs()) {
2440                         bus_profile.input_ac = AutoConnectPhysical;
2441                 } else {
2442                         bus_profile.input_ac = AutoConnectOption (0);
2443                 }
2444
2445                 /// @todo some minor tweaks.
2446
2447                 bus_profile.output_ac = AutoConnectOption (0);
2448
2449                 if (_startup->connect_outputs ()) {
2450                         if (_startup->connect_outs_to_master()) {
2451                                 bus_profile.output_ac = AutoConnectMaster;
2452                         } else if (_startup->connect_outs_to_physical()) {
2453                                 bus_profile.output_ac = AutoConnectPhysical;
2454                         }
2455                 }
2456
2457                 bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count();
2458                 bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count();
2459         }
2460
2461         if (build_session (session_path, session_name, bus_profile)) {
2462                 return -1;
2463         }
2464
2465         return 0;
2466 }
2467
2468 void
2469 ARDOUR_UI::idle_load (const std::string& path)
2470 {
2471         if (_session) {
2472                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2473                         /* /path/to/foo => /path/to/foo, foo */
2474                         load_session (path, basename_nosuffix (path));
2475                 } else {
2476                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2477                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2478                 }
2479         } else {
2480
2481                 ARDOUR_COMMAND_LINE::session_name = path;
2482
2483                 /*
2484                  * new_session_dialog doens't exist in A3
2485                  * Try to remove all references to it to
2486                  * see if it will compile.  NOTE: this will
2487                  * likely cause a runtime issue is my somewhat
2488                  * uneducated guess.
2489                  */
2490
2491                 //if (new_session_dialog) {
2492
2493
2494                         /* make it break out of Dialog::run() and
2495                            start again.
2496                          */
2497
2498                         //new_session_dialog->response (1);
2499                 //}
2500         }
2501 }
2502
2503 void
2504 ARDOUR_UI::end_loading_messages ()
2505 {
2506         // hide_splash ();
2507 }
2508
2509 void
2510 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2511 {
2512         // show_splash ();
2513         // splash->message (msg);
2514         flush_pending ();
2515 }
2516
2517 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2518 int
2519 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2520 {
2521         string session_name;
2522         string session_path;
2523         string template_name;
2524         int ret = -1;
2525         bool likely_new = false;
2526
2527         if (!load_template.empty()) {
2528                 should_be_new = true;
2529                 template_name = load_template;
2530         }
2531
2532         while (ret != 0) {
2533
2534                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2535
2536                         /* if they named a specific statefile, use it, otherwise they are
2537                            just giving a session folder, and we want to use it as is
2538                            to find the session.
2539                         */
2540
2541                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
2542
2543                         if (suffix != string::npos) {
2544                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2545                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
2546                                 session_name = Glib::path_get_basename (session_name);
2547                         } else {
2548                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2549                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2550                         }
2551
2552                 } else {
2553
2554                         bool const apply = run_startup (should_be_new, load_template);
2555
2556                         if (!apply) {
2557                                 if (quit_on_cancel) {
2558                                         exit (1);
2559                                 } else {
2560                                         return ret;
2561                                 }
2562                         }
2563
2564                         /* if we run the startup dialog again, offer more than just "new session" */
2565
2566                         should_be_new = false;
2567
2568                         session_name = _startup->session_name (likely_new);
2569
2570                         /* this shouldn't happen, but we catch it just in case it does */
2571
2572                         if (session_name.empty()) {
2573                                 continue;
2574                         }
2575
2576                         if (_startup->use_session_template()) {
2577                                 template_name = _startup->session_template_name();
2578                                 _session_is_new = true;
2579                         }
2580
2581                         if (session_name[0] == G_DIR_SEPARATOR ||
2582                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
2583                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)) {
2584
2585                                 /* absolute path or cwd-relative path specified for session name: infer session folder
2586                                    from what was given.
2587                                 */
2588
2589                                 session_path = Glib::path_get_dirname (session_name);
2590                                 session_name = Glib::path_get_basename (session_name);
2591
2592                         } else {
2593
2594                                 session_path = _startup->session_folder();
2595
2596                                 if (session_name.find ('/') != string::npos) {
2597                                         MessageDialog msg (*_startup,
2598                                                            _("To ensure compatibility with various systems\n"
2599                                                              "session names may not contain a '/' character"));
2600                                         msg.run ();
2601                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2602                                         continue;
2603                                 }
2604
2605                                 if (session_name.find ('\\') != string::npos) {
2606                                         MessageDialog msg (*_startup,
2607                                                            _("To ensure compatibility with various systems\n"
2608                                                              "session names may not contain a '\\' character"));
2609                                         msg.run ();
2610                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2611                                         continue;
2612                                 }
2613                         }
2614                 }
2615
2616                 if (create_engine ()) {
2617                         break;
2618                 }
2619
2620                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2621
2622                         if (likely_new) {
2623
2624                                 std::string existing = Glib::build_filename (session_path, session_name);
2625
2626                                 if (!ask_about_loading_existing_session (existing)) {
2627                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2628                                         continue;
2629                                 }
2630                         }
2631
2632                         _session_is_new = false;
2633
2634                 } else {
2635
2636                         if (!likely_new) {
2637                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2638                                 msg.run ();
2639                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2640                                 continue;
2641                         }
2642
2643                         if (session_name.find ('/') != std::string::npos) {
2644                                 MessageDialog msg (*_startup,
2645                                                    _("To ensure compatibility with various systems\n"
2646                                                      "session names may not contain a '/' character"));
2647                                 msg.run ();
2648                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2649                                 continue;
2650                         }
2651
2652                         if (session_name.find ('\\') != std::string::npos) {
2653                                 MessageDialog msg (*_startup,
2654                                                    _("To ensure compatibility with various systems\n"
2655                                                      "session names may not contain a '\\' character"));
2656                                 msg.run ();
2657                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2658                                 continue;
2659                         }
2660
2661                         _session_is_new = true;
2662                 }
2663
2664                 if (likely_new && template_name.empty()) {
2665
2666                         ret = build_session_from_nsd (session_path, session_name);
2667
2668                 } else {
2669
2670                         ret = load_session (session_path, session_name, template_name);
2671
2672                         if (ret == -2) {
2673                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
2674                                 exit (1);
2675                         }
2676
2677                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2678                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2679                                 exit (1);
2680                         }
2681                 }
2682         }
2683
2684         return ret;
2685 }
2686
2687 void
2688 ARDOUR_UI::close_session()
2689 {
2690         if (!check_audioengine()) {
2691                 return;
2692         }
2693
2694         if (unload_session (true)) {
2695                 return;
2696         }
2697
2698         ARDOUR_COMMAND_LINE::session_name = "";
2699
2700         if (get_session_parameters (true, false)) {
2701                 exit (1);
2702         }
2703
2704         goto_editor_window ();
2705 }
2706
2707 /** @param snap_name Snapshot name (without .ardour suffix).
2708  *  @return -2 if the load failed because we are not connected to the AudioEngine.
2709  */
2710 int
2711 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
2712 {
2713         Session *new_session;
2714         int unload_status;
2715         int retval = -1;
2716
2717         session_loaded = false;
2718
2719         if (!check_audioengine()) {
2720                 return -2;
2721         }
2722
2723         unload_status = unload_session ();
2724
2725         if (unload_status < 0) {
2726                 goto out;
2727         } else if (unload_status > 0) {
2728                 retval = 0;
2729                 goto out;
2730         }
2731
2732         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
2733
2734         try {
2735                 new_session = new Session (*engine, path, snap_name, 0, mix_template);
2736         }
2737
2738         /* this one is special */
2739
2740         catch (AudioEngine::PortRegistrationFailure& err) {
2741
2742                 MessageDialog msg (err.what(),
2743                                    true,
2744                                    Gtk::MESSAGE_INFO,
2745                                    Gtk::BUTTONS_CLOSE);
2746
2747                 msg.set_title (_("Port Registration Error"));
2748                 msg.set_secondary_text (_("Click the Close button to try again."));
2749                 msg.set_position (Gtk::WIN_POS_CENTER);
2750                 pop_back_splash ();
2751                 msg.present ();
2752
2753                 int response = msg.run ();
2754
2755                 msg.hide ();
2756
2757                 switch (response) {
2758                 case RESPONSE_CANCEL:
2759                         exit (1);
2760                 default:
2761                         break;
2762                 }
2763                 goto out;
2764         }
2765
2766         catch (...) {
2767
2768                 MessageDialog msg (string_compose(
2769                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
2770                                            path, snap_name),
2771                                    true,
2772                                    Gtk::MESSAGE_INFO,
2773                                    BUTTONS_OK);
2774
2775                 msg.set_title (_("Loading Error"));
2776                 msg.set_secondary_text (_("Click the Refresh button to try again."));
2777                 msg.add_button (Stock::REFRESH, 1);
2778                 msg.set_position (Gtk::WIN_POS_CENTER);
2779                 pop_back_splash ();
2780                 msg.present ();
2781
2782                 int response = msg.run ();
2783
2784                 switch (response) {
2785                 case 1:
2786                         break;
2787                 default:
2788                         exit (1);
2789                 }
2790
2791                 msg.hide ();
2792
2793                 goto out;
2794         }
2795
2796         {
2797                 list<string> const u = new_session->unknown_processors ();
2798                 if (!u.empty()) {
2799                         MissingPluginDialog d (_session, u);
2800                         d.run ();
2801                 }
2802         }
2803
2804         /* Now the session been created, add the transport controls */
2805         new_session->add_controllable(roll_controllable);
2806         new_session->add_controllable(stop_controllable);
2807         new_session->add_controllable(goto_start_controllable);
2808         new_session->add_controllable(goto_end_controllable);
2809         new_session->add_controllable(auto_loop_controllable);
2810         new_session->add_controllable(play_selection_controllable);
2811         new_session->add_controllable(rec_controllable);
2812
2813         set_session (new_session);
2814
2815         session_loaded = true;
2816
2817         goto_editor_window ();
2818
2819         if (_session) {
2820                 _session->set_clean ();
2821         }
2822
2823         flush_pending ();
2824         retval = 0;
2825
2826   out:
2827         return retval;
2828 }
2829
2830 int
2831 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
2832 {
2833         Session *new_session;
2834         int x;
2835
2836         if (!check_audioengine()) {
2837                 return -1;
2838         }
2839
2840         session_loaded = false;
2841
2842         x = unload_session ();
2843
2844         if (x < 0) {
2845                 return -1;
2846         } else if (x > 0) {
2847                 return 0;
2848         }
2849
2850         _session_is_new = true;
2851
2852         try {
2853                 new_session = new Session (*engine, path, snap_name, &bus_profile);
2854         }
2855
2856         catch (...) {
2857
2858                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2859                 pop_back_splash ();
2860                 msg.run ();
2861                 return -1;
2862         }
2863
2864         /* Give the new session the default GUI state, if such things exist */
2865
2866         XMLNode* n;
2867         n = Config->instant_xml (X_("Editor"));
2868         if (n) {
2869                 new_session->add_instant_xml (*n, false);
2870         }
2871         n = Config->instant_xml (X_("Mixer"));
2872         if (n) {
2873                 new_session->add_instant_xml (*n, false);
2874         }
2875
2876         /* Put the playhead at 0 and scroll fully left */
2877         n = new_session->instant_xml (X_("Editor"));
2878         if (n) {
2879                 n->add_property (X_("playhead"), X_("0"));
2880                 n->add_property (X_("left-frame"), X_("0"));
2881         }
2882
2883         set_session (new_session);
2884
2885         session_loaded = true;
2886
2887         new_session->save_state(new_session->name());
2888
2889         return 0;
2890 }
2891
2892 void
2893 ARDOUR_UI::launch_chat ()
2894 {
2895 #ifdef __APPLE__
2896         open_uri("http://webchat.freenode.net/?channels=ardour-osx");
2897 #else
2898         open_uri("http://webchat.freenode.net/?channels=ardour");
2899 #endif
2900 }
2901
2902 void
2903 ARDOUR_UI::show_about ()
2904 {
2905         if (about == 0) {
2906                 about = new About;
2907                 about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2908         }
2909
2910         about->set_transient_for(*editor);
2911         about->show_all ();
2912 }
2913
2914 void
2915 ARDOUR_UI::launch_manual ()
2916 {
2917         PBD::open_uri("http://ardour.org/flossmanual");
2918 }
2919
2920 void
2921 ARDOUR_UI::launch_reference ()
2922 {
2923         PBD::open_uri("http://ardour.org/refmanual");
2924 }
2925
2926 void
2927 ARDOUR_UI::hide_about ()
2928 {
2929         if (about) {
2930                 about->get_window()->set_cursor ();
2931                 about->hide ();
2932         }
2933 }
2934
2935 void
2936 ARDOUR_UI::about_signal_response (int /*response*/)
2937 {
2938         hide_about();
2939 }
2940
2941 void
2942 ARDOUR_UI::show_splash ()
2943 {
2944         if (splash == 0) {
2945                 try {
2946                         splash = new Splash;
2947                 } catch (...) {
2948                         return;
2949                 }
2950         }
2951
2952         splash->show ();
2953         splash->present ();
2954         splash->queue_draw ();
2955         splash->get_window()->process_updates (true);
2956         flush_pending ();
2957 }
2958
2959 void
2960 ARDOUR_UI::hide_splash ()
2961 {
2962         if (splash) {
2963                 splash->hide();
2964         }
2965 }
2966
2967 void
2968 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title,
2969                                     const string& plural_msg, const string& singular_msg)
2970 {
2971         size_t removed;
2972
2973         removed = rep.paths.size();
2974
2975         if (removed == 0) {
2976                 MessageDialog msgd (*editor,
2977                                     _("No files were ready for clean-up"),
2978                                     true,
2979                                     Gtk::MESSAGE_INFO,
2980                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2981                 msgd.set_title (_("Clean-up"));
2982                 msgd.set_secondary_text (_("If this seems suprising, \n\
2983 check for any existing snapshots.\n\
2984 These may still include regions that\n\
2985 require some unused files to continue to exist."));
2986
2987                 msgd.run ();
2988                 return;
2989         }
2990
2991         ArdourDialog results (_("Clean-up"), true, false);
2992
2993         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2994             CleanupResultsModelColumns() {
2995                     add (visible_name);
2996                     add (fullpath);
2997             }
2998             Gtk::TreeModelColumn<std::string> visible_name;
2999             Gtk::TreeModelColumn<std::string> fullpath;
3000         };
3001
3002
3003         CleanupResultsModelColumns results_columns;
3004         Glib::RefPtr<Gtk::ListStore> results_model;
3005         Gtk::TreeView results_display;
3006
3007         results_model = ListStore::create (results_columns);
3008         results_display.set_model (results_model);
3009         results_display.append_column (list_title, results_columns.visible_name);
3010
3011         results_display.set_name ("CleanupResultsList");
3012         results_display.set_headers_visible (true);
3013         results_display.set_headers_clickable (false);
3014         results_display.set_reorderable (false);
3015
3016         Gtk::ScrolledWindow list_scroller;
3017         Gtk::Label txt;
3018         Gtk::VBox dvbox;
3019         Gtk::HBox dhbox;  // the hbox for the image and text
3020         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3021         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3022
3023         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3024
3025         const string dead_directory = _session->session_directory().dead_path().to_string();
3026
3027         /* subst:
3028            %1 - number of files removed
3029            %2 - location of "dead"
3030            %3 - size of files affected
3031            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3032         */
3033
3034         const char* bprefix;
3035         double space_adjusted = 0;
3036
3037         if (rep.space < 1000) {
3038                 bprefix = X_("");
3039                 space_adjusted = rep.space;
3040         } else if (rep.space < 1000000) {
3041                 bprefix = X_("kilo");
3042                 space_adjusted = truncf((float)rep.space / 1000.0);
3043         } else if (rep.space < 1000000 * 1000) {
3044                 bprefix = X_("mega");
3045                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000.0));
3046         } else {
3047                 bprefix = X_("giga");
3048                 space_adjusted = truncf((float)rep.space / (1000.0 * 1000 * 1000.0));
3049         }
3050
3051         if (removed > 1) {
3052                 txt.set_text (string_compose (plural_msg, removed, dead_directory, space_adjusted, bprefix));
3053         } else {
3054                 txt.set_text (string_compose (singular_msg, removed, dead_directory, space_adjusted, bprefix));
3055         }
3056
3057         dhbox.pack_start (*dimage, true, false, 5);
3058         dhbox.pack_start (txt, true, false, 5);
3059
3060         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3061                 TreeModel::Row row = *(results_model->append());
3062                 row[results_columns.visible_name] = *i;
3063                 row[results_columns.fullpath] = *i;
3064         }
3065
3066         list_scroller.add (results_display);
3067         list_scroller.set_size_request (-1, 150);
3068         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3069
3070         dvbox.pack_start (dhbox, true, false, 5);
3071         dvbox.pack_start (list_scroller, true, false, 5);
3072         ddhbox.pack_start (dvbox, true, false, 5);
3073
3074         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3075         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3076         results.set_default_response (RESPONSE_CLOSE);
3077         results.set_position (Gtk::WIN_POS_MOUSE);
3078
3079         results_display.show();
3080         list_scroller.show();
3081         txt.show();
3082         dvbox.show();
3083         dhbox.show();
3084         ddhbox.show();
3085         dimage->show();
3086
3087         //results.get_vbox()->show();
3088         results.set_resizable (false);
3089
3090         results.run ();
3091
3092 }
3093
3094 void
3095 ARDOUR_UI::cleanup ()
3096 {
3097         if (_session == 0) {
3098                 /* shouldn't happen: menu item is insensitive */
3099                 return;
3100         }
3101
3102
3103         MessageDialog checker (_("Are you sure you want to clean-up?"),
3104                                 true,
3105                                 Gtk::MESSAGE_QUESTION,
3106                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
3107
3108         checker.set_title (_("Clean-up"));
3109
3110         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3111 ALL undo/redo information will be lost if you clean-up.\n\
3112 Clean-up will move all unused files to a \"dead\" location."));
3113
3114         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3115         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3116         checker.set_default_response (RESPONSE_CANCEL);
3117
3118         checker.set_name (_("CleanupDialog"));
3119         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3120         checker.set_position (Gtk::WIN_POS_MOUSE);
3121
3122         switch (checker.run()) {
3123         case RESPONSE_ACCEPT:
3124                 break;
3125         default:
3126                 return;
3127         }
3128
3129         ARDOUR::CleanupReport rep;
3130
3131         editor->prepare_for_cleanup ();
3132
3133         /* do not allow flush until a session is reloaded */
3134
3135         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3136         if (act) {
3137                 act->set_sensitive (false);
3138         }
3139
3140         if (_session->cleanup_sources (rep)) {
3141                 editor->finish_cleanup ();
3142                 return;
3143         }
3144
3145         editor->finish_cleanup ();
3146
3147         checker.hide();
3148         display_cleanup_results (rep,
3149                                  _("Cleaned Files"),
3150                                  _("\
3151 The following %1 files were not in use and \n\
3152 have been moved to:\n\n\
3153 %2\n\n\
3154 After a restart of Ardour,\n\n\
3155 Session -> Clean-up -> Flush Wastebasket\n\n\
3156 will release an additional\n\
3157 %3 %4bytes of disk space.\n"),
3158                                  _("\
3159 The following file was not in use and \n\
3160 has been moved to:\n                            \
3161 %2\n\n\
3162 After a restart of Ardour,\n\n\
3163 Session -> Clean-up -> Flush Wastebasket\n\n\
3164 will release an additional\n\
3165 %3 %4bytes of disk space.\n"
3166                                          ));
3167
3168 }
3169
3170 void
3171 ARDOUR_UI::flush_trash ()
3172 {
3173         if (_session == 0) {
3174                 /* shouldn't happen: menu item is insensitive */
3175                 return;
3176         }
3177
3178         ARDOUR::CleanupReport rep;
3179
3180         if (_session->cleanup_trash_sources (rep)) {
3181                 return;
3182         }
3183
3184         display_cleanup_results (rep,
3185                                  _("deleted file"),
3186                                  _("The following %1 files were deleted from\n\
3187 %2,\n\
3188 releasing %3 %4bytes of disk space"),
3189                                  _("The following file was deleted from\n\
3190 %2,\n\
3191 releasing %3 %4bytes of disk space"));
3192 }
3193
3194 void
3195 ARDOUR_UI::add_route (Gtk::Window* float_window)
3196 {
3197         int count;
3198
3199         if (!_session) {
3200                 return;
3201         }
3202
3203         if (add_route_dialog == 0) {
3204                 add_route_dialog = new AddRouteDialog (_session);
3205                 if (float_window) {
3206                         add_route_dialog->set_transient_for (*float_window);
3207                 }
3208         }
3209
3210         if (add_route_dialog->is_visible()) {
3211                 /* we're already doing this */
3212                 return;
3213         }
3214
3215         ResponseType r = (ResponseType) add_route_dialog->run ();
3216
3217         add_route_dialog->hide();
3218
3219         switch (r) {
3220                 case RESPONSE_ACCEPT:
3221                         break;
3222                 default:
3223                         return;
3224                         break;
3225         }
3226
3227         if ((count = add_route_dialog->count()) <= 0) {
3228                 return;
3229         }
3230
3231         string template_path = add_route_dialog->track_template();
3232
3233         if (!template_path.empty()) {
3234                 _session->new_route_from_template (count, template_path);
3235                 return;
3236         }
3237
3238         uint32_t input_chan = add_route_dialog->channels ();
3239         uint32_t output_chan;
3240         string name_template = add_route_dialog->name_template ();
3241         bool track = add_route_dialog->track ();
3242         RouteGroup* route_group = add_route_dialog->route_group ();
3243
3244         AutoConnectOption oac = Config->get_output_auto_connect();
3245
3246         if (oac & AutoConnectMaster) {
3247                 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
3248         } else {
3249                 output_chan = input_chan;
3250         }
3251
3252         /* XXX do something with name template */
3253
3254         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
3255                 if (track) {
3256                         session_add_midi_track (route_group, count, name_template);
3257                 } else  {
3258                         MessageDialog msg (*editor,
3259                                         _("Sorry, MIDI Busses are not supported at this time."));
3260                         msg.run ();
3261                         //session_add_midi_bus();
3262                 }
3263         } else {
3264                 if (track) {
3265                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count, name_template);
3266                 } else {
3267                         session_add_audio_bus (input_chan, output_chan, route_group, count, name_template);
3268                 }
3269         }
3270 }
3271
3272 XMLNode*
3273 ARDOUR_UI::mixer_settings () const
3274 {
3275         XMLNode* node = 0;
3276
3277         if (_session) {
3278                 node = _session->instant_xml(X_("Mixer"));
3279         } else {
3280                 node = Config->instant_xml(X_("Mixer"));
3281         }
3282
3283         if (!node) {
3284                 node = new XMLNode (X_("Mixer"));
3285         }
3286
3287         return node;
3288 }
3289
3290 XMLNode*
3291 ARDOUR_UI::editor_settings () const
3292 {
3293         XMLNode* node = 0;
3294
3295         if (_session) {
3296                 node = _session->instant_xml(X_("Editor"));
3297         } else {
3298                 node = Config->instant_xml(X_("Editor"));
3299         }
3300
3301         if (!node) {
3302                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
3303                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
3304                 }
3305         }
3306
3307         if (!node) {
3308                 node = new XMLNode (X_("Editor"));
3309         }
3310
3311         return node;
3312 }
3313
3314 XMLNode*
3315 ARDOUR_UI::keyboard_settings () const
3316 {
3317         XMLNode* node = 0;
3318
3319         node = Config->extra_xml(X_("Keyboard"));
3320
3321         if (!node) {
3322                 node = new XMLNode (X_("Keyboard"));
3323         }
3324
3325         return node;
3326 }
3327
3328 void
3329 ARDOUR_UI::create_xrun_marker (framepos_t where)
3330 {
3331         editor->mouse_add_new_marker (where, false, true);
3332 }
3333
3334 void
3335 ARDOUR_UI::halt_on_xrun_message ()
3336 {
3337         MessageDialog msg (*editor,
3338                            _("Recording was stopped because your system could not keep up."));
3339         msg.run ();
3340 }
3341
3342 void
3343 ARDOUR_UI::xrun_handler (framepos_t where)
3344 {
3345         if (!_session) {
3346                 return;
3347         }
3348
3349         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
3350
3351         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
3352                 create_xrun_marker(where);
3353         }
3354
3355         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
3356                 halt_on_xrun_message ();
3357         }
3358 }
3359
3360 void
3361 ARDOUR_UI::disk_overrun_handler ()
3362 {
3363         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
3364
3365         if (!have_disk_speed_dialog_displayed) {
3366                 have_disk_speed_dialog_displayed = true;
3367                 MessageDialog* msg = new MessageDialog (*editor, string_compose (_("\
3368 The disk system on your computer\n\
3369 was not able to keep up with %1.\n\
3370 \n\
3371 Specifically, it failed to write data to disk\n\
3372 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
3373                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3374                 msg->show ();
3375         }
3376 }
3377
3378 void
3379 ARDOUR_UI::disk_underrun_handler ()
3380 {
3381         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
3382
3383         if (!have_disk_speed_dialog_displayed) {
3384                 have_disk_speed_dialog_displayed = true;
3385                 MessageDialog* msg = new MessageDialog (
3386                         *editor, string_compose (_("The disk system on your computer\n\
3387 was not able to keep up with %1.\n\
3388 \n\
3389 Specifically, it failed to read data from disk\n\
3390 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
3391                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3392                 msg->show ();
3393         }
3394 }
3395
3396 void
3397 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3398 {
3399         have_disk_speed_dialog_displayed = false;
3400         delete msg;
3401 }
3402
3403 void
3404 ARDOUR_UI::session_dialog (std::string msg)
3405 {
3406         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
3407
3408         MessageDialog* d;
3409
3410         if (editor) {
3411                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3412         } else {
3413                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3414         }
3415
3416         d->show_all ();
3417         d->run ();
3418         delete d;
3419 }
3420
3421 int
3422 ARDOUR_UI::pending_state_dialog ()
3423 {
3424         HBox* hbox = new HBox();
3425         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3426         ArdourDialog dialog (_("Crash Recovery"), true);
3427         Label  message (_("\
3428 This session appears to have been in\n\
3429 middle of recording when ardour or\n\
3430 the computer was shutdown.\n\
3431 \n\
3432 Ardour can recover any captured audio for\n\
3433 you, or it can ignore it. Please decide\n\
3434 what you would like to do.\n"));
3435         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3436         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3437         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3438         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3439         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3440         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3441         dialog.set_default_response (RESPONSE_ACCEPT);
3442         dialog.set_position (WIN_POS_CENTER);
3443         message.show();
3444         image->show();
3445         hbox->show();
3446
3447         switch (dialog.run ()) {
3448         case RESPONSE_ACCEPT:
3449                 return 1;
3450         default:
3451                 return 0;
3452         }
3453 }
3454
3455 int
3456 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
3457 {
3458         HBox* hbox = new HBox();
3459         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3460         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3461         Label  message (string_compose (_("\
3462 This session was created with a sample rate of %1 Hz\n\
3463 \n\
3464 The audioengine is currently running at %2 Hz\n"), desired, actual));
3465
3466         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3467         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3468         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3469         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3470         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3471         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3472         dialog.set_default_response (RESPONSE_ACCEPT);
3473         dialog.set_position (WIN_POS_CENTER);
3474         message.show();
3475         image->show();
3476         hbox->show();
3477
3478         switch (dialog.run ()) {
3479         case RESPONSE_ACCEPT:
3480                 return 0;
3481         default:
3482                 return 1;
3483         }
3484 }
3485
3486
3487 void
3488 ARDOUR_UI::disconnect_from_jack ()
3489 {
3490         if (engine) {
3491                 if( engine->disconnect_from_jack ()) {
3492                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3493                         msg.run ();
3494                 }
3495
3496                 update_sample_rate (0);
3497         }
3498 }
3499
3500 void
3501 ARDOUR_UI::reconnect_to_jack ()
3502 {
3503         if (engine) {
3504                 if (engine->reconnect_to_jack ()) {
3505                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3506                         msg.run ();
3507                 }
3508
3509                 update_sample_rate (0);
3510         }
3511 }
3512
3513 void
3514 ARDOUR_UI::use_config ()
3515 {
3516         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3517         if (node) {
3518                 set_transport_controllable_state (*node);
3519         }
3520 }
3521
3522 void
3523 ARDOUR_UI::update_transport_clocks (framepos_t pos)
3524 {
3525         if (Config->get_primary_clock_delta_edit_cursor()) {
3526                 primary_clock->set (pos, false, editor->get_preferred_edit_position(), 1);
3527         } else {
3528                 primary_clock->set (pos, 0, true);
3529         }
3530
3531         if (Config->get_secondary_clock_delta_edit_cursor()) {
3532                 secondary_clock->set (pos, false, editor->get_preferred_edit_position(), 2);
3533         } else {
3534                 secondary_clock->set (pos);
3535         }
3536
3537         if (big_clock_window->get()) {
3538                 big_clock->set (pos);
3539         }
3540 }
3541
3542
3543 void
3544 ARDOUR_UI::step_edit_status_change (bool yn)
3545 {
3546         // XXX should really store pre-step edit status of things
3547         // we make insensitive
3548
3549         if (yn) {
3550                 rec_button.set_visual_state (3);
3551                 rec_button.set_sensitive (false);
3552         } else {
3553                 rec_button.set_visual_state (0);
3554                 rec_button.set_sensitive (true);
3555         }
3556 }
3557
3558 void
3559 ARDOUR_UI::record_state_changed ()
3560 {
3561         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
3562
3563         if (!_session || !big_clock_window->get()) {
3564                 /* why bother - the clock isn't visible */
3565                 return;
3566         }
3567
3568         Session::RecordState const r = _session->record_status ();
3569         bool const h = _session->have_rec_enabled_track ();
3570
3571         if (r == Session::Recording && h)  {
3572                 big_clock->set_widget_name ("BigClockRecording");
3573         } else {
3574                 big_clock->set_widget_name ("BigClockNonRecording");
3575         }
3576 }
3577
3578 bool
3579 ARDOUR_UI::first_idle ()
3580 {
3581         if (_session) {
3582                 _session->allow_auto_play (true);
3583         }
3584
3585         if (editor) {
3586                 editor->first_idle();
3587         }
3588
3589         Keyboard::set_can_save_keybindings (true);
3590         return false;
3591 }
3592
3593 void
3594 ARDOUR_UI::store_clock_modes ()
3595 {
3596         XMLNode* node = new XMLNode(X_("ClockModes"));
3597
3598         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3599                 XMLNode* child = new XMLNode (X_("Clock"));
3600                 
3601                 child->add_property (X_("name"), (*x)->name());
3602                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
3603                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
3604
3605                 node->add_child_nocopy (*child);
3606         }
3607
3608         _session->add_extra_xml (*node);
3609         _session->set_dirty ();
3610 }
3611
3612 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3613         : Controllable (name), ui (u), type(tp)
3614 {
3615
3616 }
3617
3618 void
3619 ARDOUR_UI::TransportControllable::set_value (double val)
3620 {
3621         if (val < 0.5) {
3622                 /* do nothing: these are radio-style actions */
3623                 return;
3624         }
3625
3626         const char *action = 0;
3627
3628         switch (type) {
3629         case Roll:
3630                 action = X_("Roll");
3631                 break;
3632         case Stop:
3633                 action = X_("Stop");
3634                 break;
3635         case GotoStart:
3636                 action = X_("Goto Start");
3637                 break;
3638         case GotoEnd:
3639                 action = X_("Goto End");
3640                 break;
3641         case AutoLoop:
3642                 action = X_("Loop");
3643                 break;
3644         case PlaySelection:
3645                 action = X_("Play Selection");
3646                 break;
3647         case RecordEnable:
3648                 action = X_("Record");
3649                 break;
3650         default:
3651                 break;
3652         }
3653
3654         if (action == 0) {
3655                 return;
3656         }
3657
3658         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3659
3660         if (act) {
3661                 act->activate ();
3662         }
3663 }
3664
3665 double
3666 ARDOUR_UI::TransportControllable::get_value (void) const
3667 {
3668         float val = 0.0;
3669
3670         switch (type) {
3671         case Roll:
3672                 break;
3673         case Stop:
3674                 break;
3675         case GotoStart:
3676                 break;
3677         case GotoEnd:
3678                 break;
3679         case AutoLoop:
3680                 break;
3681         case PlaySelection:
3682                 break;
3683         case RecordEnable:
3684                 break;
3685         default:
3686                 break;
3687         }
3688
3689         return val;
3690 }
3691
3692 void
3693 ARDOUR_UI::TransportControllable::set_id (const string& str)
3694 {
3695         _id = str;
3696 }
3697
3698 void
3699 ARDOUR_UI::setup_profile ()
3700 {
3701         if (gdk_screen_width() < 1200) {
3702                 Profile->set_small_screen ();
3703         }
3704
3705
3706         if (getenv ("ARDOUR_SAE")) {
3707                 Profile->set_sae ();
3708                 Profile->set_single_package ();
3709         }
3710 }
3711
3712 void
3713 ARDOUR_UI::toggle_translations ()
3714 {
3715         using namespace Glib;
3716
3717         RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("EnableTranslation"));
3718         if (act) {
3719                 RefPtr<ToggleAction> ract = RefPtr<ToggleAction>::cast_dynamic (act);
3720                 if (ract) {
3721
3722                         string i18n_killer = ARDOUR::translation_kill_path();
3723
3724                         bool already_enabled = !ARDOUR::translations_are_disabled ();
3725
3726                         if (ract->get_active ()) {
3727 /* we don't care about errors */
3728                                 int fd = ::open (i18n_killer.c_str(), O_RDONLY|O_CREAT, 0644);
3729                                 close (fd);
3730                         } else {
3731 /* we don't care about errors */
3732                                 unlink (i18n_killer.c_str());
3733                         }
3734
3735                         if (already_enabled != ract->get_active()) {
3736                                 MessageDialog win (already_enabled ? _("Translations disabled") : _("Translations enabled"),
3737                                                    false,
3738                                                    Gtk::MESSAGE_WARNING,
3739                                                    Gtk::BUTTONS_OK);
3740                                 win.set_secondary_text (string_compose (_("You must restart %1 for this to take effect."), PROGRAM_NAME));
3741                                 win.set_position (Gtk::WIN_POS_CENTER);
3742                                 win.present ();
3743                                 win.run ();
3744                         }
3745                 }
3746         }
3747 }
3748
3749 /** Add a window proxy to our list, so that its state will be saved.
3750  *  This call also causes the window to be created and opened if its
3751  *  state was saved as `visible'.
3752  */
3753 void
3754 ARDOUR_UI::add_window_proxy (WindowProxyBase* p)
3755 {
3756         _window_proxies.push_back (p);
3757         p->maybe_show ();
3758 }
3759
3760 /** Remove a window proxy from our list.  Must be called if a WindowProxy
3761  *  is deleted, to prevent hanging pointers.
3762  */
3763 void
3764 ARDOUR_UI::remove_window_proxy (WindowProxyBase* p)
3765 {
3766         _window_proxies.remove (p);
3767 }
3768
3769 int
3770 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
3771 {
3772         MissingFileDialog dialog (s, str, type);
3773
3774         dialog.show ();
3775         dialog.present ();
3776
3777         int result = dialog.run ();
3778         dialog.hide ();
3779
3780         switch (result) {
3781         case RESPONSE_OK:
3782                 break;
3783         default:
3784                 return 1; // quit entire session load
3785         }
3786
3787         result = dialog.get_action ();
3788
3789         return result;
3790 }
3791
3792 int
3793 ARDOUR_UI::ambiguous_file (std::string file, std::string path, std::vector<std::string> hits)
3794 {
3795         AmbiguousFileDialog dialog (file, hits);
3796
3797         dialog.show ();
3798         dialog.present ();
3799
3800         dialog.run ();
3801         return dialog.get_which ();
3802 }