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