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