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