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