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