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