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