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