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