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