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