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