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