changes to niceify the audio setup dialog on OS X, plus that fix for brand new GTK+
[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->present ();
1958         new_session_dialog->set_current_page (0);
1959
1960         do {
1961
1962                 new_session_dialog->set_have_engine (have_engine);
1963
1964                 response = new_session_dialog->run ();
1965
1966                 _session_is_new = false;
1967
1968                 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1969
1970                         if (!session) {
1971                                 quit();
1972                         }
1973                         new_session_dialog->hide ();
1974                         return false;
1975
1976                 } else if (response == Gtk::RESPONSE_NONE) {
1977
1978                         /* Clear was pressed */
1979                         new_session_dialog->reset();
1980                         continue;
1981                 }
1982
1983                 /* first things first ... we need an audio engine running */
1984
1985                 if (!have_engine) {
1986                         if (start_backend_audio ()) {
1987                                 new_session_dialog->hide ();
1988                                 return false;
1989                         }
1990                         have_engine = true;
1991                 }
1992
1993                 create_engine ();
1994
1995                 /* now handle possible affirmative responses */
1996
1997                 if (response == Gtk::RESPONSE_YES) {
1998
1999                         /* YES == OPEN from the open session tab */
2000
2001                         session_name = new_session_dialog->session_name();
2002                         
2003                         if (session_name.empty()) {
2004                                 response = Gtk::RESPONSE_NONE;
2005                                 continue;
2006                         } 
2007
2008                         if (session_name[0] == '/' || 
2009                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2010                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2011                                 load_session (Glib::path_get_dirname (session_name), session_name);
2012                         } else {
2013                                 session_path = new_session_dialog->session_folder();
2014                                 load_session (session_path, session_name);
2015                         }
2016                         
2017                 } else if (response == Gtk::RESPONSE_OK) {
2018
2019                         /* OK == OPEN from new session tab */
2020
2021                         session_name = new_session_dialog->session_name();
2022                         
2023                         if (new_session_dialog->get_current_page() == 1) {
2024                                 
2025                                 if (session_name.empty()) {
2026                                         response = Gtk::RESPONSE_NONE;
2027                                         continue;
2028                                 } 
2029                                 
2030                                 if (session_name[0] == '/' || 
2031                                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2032                                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2033                                         load_session (Glib::path_get_dirname (session_name), session_name);
2034                                 } else {
2035                                         session_path = new_session_dialog->session_folder();
2036                                         load_session (session_path, session_name);
2037                                 }
2038                         
2039                         } else {
2040
2041                                 if (session_name.empty()) {
2042                                         response = Gtk::RESPONSE_NONE;
2043                                         continue;
2044                                 } 
2045
2046                                 /* handle what appear to be paths rather than just a name */
2047
2048                                 if (session_name[0] == '/' || 
2049                                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2050                                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2051
2052                                         session_path = Glib::path_get_dirname (session_name);
2053                                         session_name = Glib::path_get_basename (session_name);
2054
2055                                 } else {
2056
2057                                         session_path = new_session_dialog->session_folder();
2058
2059                                 }
2060                                 
2061                                 //XXX This is needed because session constructor wants a 
2062                                 //non-existant path. hopefully this will be fixed at some point.
2063                                 
2064                                 session_path = Glib::build_filename (session_path, session_name);
2065                                                 
2066                                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2067
2068                                         Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2069
2070                                         MessageDialog msg (str,
2071                                                            false,
2072                                                            Gtk::MESSAGE_WARNING,
2073                                                            Gtk::BUTTONS_YES_NO,
2074                                                            true);
2075
2076
2077                                         msg.set_name (X_("CleanupDialog"));
2078                                         msg.set_wmclass (X_("existing_session"), "Ardour");
2079                                         msg.set_position (Gtk::WIN_POS_MOUSE);
2080                                         
2081                                         switch (msg.run()) {
2082                                         case RESPONSE_YES:
2083                                                 load_session (session_path, session_name);
2084                                                 goto done;
2085                                                 break;
2086                                         default:
2087                                                 response = RESPONSE_NONE;
2088                                                 new_session_dialog->reset ();
2089                                                 continue;
2090                                         }
2091                                 }
2092
2093                                 _session_is_new = true;
2094
2095                                 std::string template_name = new_session_dialog->session_template_name();
2096                                                 
2097                                 if (new_session_dialog->use_session_template()) {
2098                                                         
2099                                         load_session (session_path, session_name, &template_name);
2100                           
2101                                 } else {
2102
2103                                         uint32_t cchns;
2104                                         uint32_t mchns;
2105                                         AutoConnectOption iconnect;
2106                                         AutoConnectOption oconnect;
2107                                         uint32_t nphysin;
2108                                         uint32_t nphysout;
2109                                         
2110                                         if (Profile->get_sae()) {
2111
2112                                                 cchns = 0;
2113                                                 mchns = 2;
2114                                                 iconnect = AutoConnectPhysical;
2115                                                 oconnect = AutoConnectMaster;
2116                                                 nphysin = 0; // use all available
2117                                                 nphysout = 0; // use all available
2118
2119                                         } else {
2120
2121                                                 /* get settings from advanced section of NSD */
2122                                                 
2123                                                 if (new_session_dialog->create_control_bus()) {
2124                                                         cchns = (uint32_t) new_session_dialog->control_channel_count();
2125                                                 } else {
2126                                                         cchns = 0;
2127                                                 }
2128                                                 
2129                                                 if (new_session_dialog->create_master_bus()) {
2130                                                         mchns = (uint32_t) new_session_dialog->master_channel_count();
2131                                                 } else {
2132                                                         mchns = 0;
2133                                                 }
2134                                                 
2135                                                 if (new_session_dialog->connect_inputs()) {
2136                                                         iconnect = AutoConnectPhysical;
2137                                                 } else {
2138                                                         iconnect = AutoConnectOption (0);
2139                                                 }
2140                                                 
2141                                                 /// @todo some minor tweaks.
2142                                                 
2143                                                 if (new_session_dialog->connect_outs_to_master()) {
2144                                                         oconnect = AutoConnectMaster;
2145                                                 } else if (new_session_dialog->connect_outs_to_physical()) {
2146                                                         oconnect = AutoConnectPhysical;
2147                                                 } else {
2148                                                         oconnect = AutoConnectOption (0);
2149                                                 } 
2150                                                 
2151                                                 nphysin = (uint32_t) new_session_dialog->input_limit_count();
2152                                                 nphysout = (uint32_t) new_session_dialog->output_limit_count();
2153                                         }
2154
2155                                         if (build_session (session_path,
2156                                                            session_name,
2157                                                            cchns,
2158                                                            mchns,
2159                                                            iconnect,
2160                                                            oconnect,
2161                                                            nphysin,
2162                                                            nphysout, 
2163                                                            engine->frame_rate() * 60 * 5)) {
2164                                                 
2165                                                 response = Gtk::RESPONSE_NONE;
2166                                                 new_session_dialog->reset ();
2167                                                 continue;
2168                                         }
2169                                 }
2170                         }
2171                 }
2172                 
2173         } while (response == Gtk::RESPONSE_NONE);
2174
2175   done:
2176         show();
2177         new_session_dialog->get_window()->set_cursor();
2178         new_session_dialog->hide();
2179         return true;
2180 }
2181
2182 void
2183 ARDOUR_UI::close_session()
2184 {
2185         if (!check_audioengine()) {
2186                 return;
2187         }
2188
2189         unload_session();
2190         new_session ("", true);
2191 }
2192
2193 int
2194 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2195 {
2196         Session *new_session;
2197         int x;
2198         session_loaded = false;
2199         
2200         if (!check_audioengine()) {
2201                 return -1;
2202         }
2203
2204         x = unload_session ();
2205
2206         if (x < 0) {
2207                 return -1;
2208         } else if (x > 0) {
2209                 return 0;
2210         }
2211
2212         /* if it already exists, we must have write access */
2213
2214         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2215                 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2216                                               "This prevents the session from being loaded."));
2217                 msg.run ();
2218                 return -1;
2219         }
2220
2221         try {
2222                 new_session = new Session (*engine, path, snap_name, mix_template);
2223         }
2224
2225         catch (...) {
2226
2227                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2228                 return -1;
2229         }
2230
2231         connect_to_session (new_session);
2232
2233         Config->set_current_owner (ConfigVariableBase::Interface);
2234
2235         session_loaded = true;
2236         
2237         goto_editor_window ();
2238
2239         if (session) {
2240                 session->set_clean ();
2241         }
2242
2243         editor->edit_cursor_position (true);
2244         return 0;
2245 }
2246
2247 int
2248 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
2249                           uint32_t control_channels,
2250                           uint32_t master_channels, 
2251                           AutoConnectOption input_connect,
2252                           AutoConnectOption output_connect,
2253                           uint32_t nphysin,
2254                           uint32_t nphysout,
2255                           nframes_t initial_length)
2256 {
2257         Session *new_session;
2258         int x;
2259
2260         if (!check_audioengine()) {
2261                 return -1;
2262         }
2263
2264         session_loaded = false;
2265
2266         x = unload_session ();
2267
2268         if (x < 0) {
2269                 return -1;
2270         } else if (x > 0) {
2271                 return 0;
2272         }
2273         
2274         _session_is_new = true;
2275
2276         try {
2277                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2278                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2279         }
2280
2281         catch (...) {
2282
2283                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2284                 msg.run ();
2285                 return -1;
2286         }
2287
2288         connect_to_session (new_session);
2289
2290         session_loaded = true;
2291         return 0;
2292 }
2293
2294 void
2295 ARDOUR_UI::show ()
2296 {
2297         if (editor) {
2298                 editor->show_window ();
2299                 
2300                 if (!shown_flag) {
2301                         editor->present ();
2302                 }
2303
2304                 shown_flag = true;
2305         }
2306 }
2307
2308 void
2309 ARDOUR_UI::show_splash ()
2310 {
2311         if (about == 0) {
2312                 about = new About();
2313                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2314         }
2315         about->present();
2316         flush_pending ();
2317 }
2318
2319 void
2320 ARDOUR_UI::about_signal_response(int response)
2321 {
2322         hide_splash();
2323 }
2324
2325 void
2326 ARDOUR_UI::hide_splash ()
2327 {
2328         if (about) {
2329                 about->get_window()->set_cursor ();
2330                 about->hide();
2331         }
2332 }
2333
2334 void
2335 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2336 {
2337         size_t removed;
2338
2339         removed = rep.paths.size();
2340
2341         if (removed == 0) {
2342                 MessageDialog msgd (*editor,
2343                                     _("No audio files were ready for cleanup"), 
2344                                     true,
2345                                     Gtk::MESSAGE_INFO,
2346                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2347                 msgd.set_secondary_text (_("If this seems suprising, \n\
2348 check for any existing snapshots.\n\
2349 These may still include regions that\n\
2350 require some unused files to continue to exist."));
2351         
2352                 msgd.run ();
2353                 return;
2354         } 
2355
2356         ArdourDialog results (_("ardour: cleanup"), true, false);
2357         
2358         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2359             CleanupResultsModelColumns() { 
2360                     add (visible_name);
2361                     add (fullpath);
2362             }
2363             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2364             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2365         };
2366
2367         
2368         CleanupResultsModelColumns results_columns;
2369         Glib::RefPtr<Gtk::ListStore> results_model;
2370         Gtk::TreeView results_display;
2371         
2372         results_model = ListStore::create (results_columns);
2373         results_display.set_model (results_model);
2374         results_display.append_column (list_title, results_columns.visible_name);
2375
2376         results_display.set_name ("CleanupResultsList");
2377         results_display.set_headers_visible (true);
2378         results_display.set_headers_clickable (false);
2379         results_display.set_reorderable (false);
2380
2381         Gtk::ScrolledWindow list_scroller;
2382         Gtk::Label txt;
2383         Gtk::VBox dvbox;
2384         Gtk::HBox dhbox;  // the hbox for the image and text
2385         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2386         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2387
2388         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2389
2390         if (rep.space < 1048576.0f) {
2391                 if (removed > 1) {
2392                   txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2393                 } else {
2394                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2395                 }
2396         } else {
2397                 if (removed > 1) {
2398                         txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2399                 } else {
2400                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2401                 }
2402         }
2403
2404         dhbox.pack_start (*dimage, true, false, 5);
2405         dhbox.pack_start (txt, true, false, 5);
2406
2407         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2408                 TreeModel::Row row = *(results_model->append());
2409                 row[results_columns.visible_name] = *i;
2410                 row[results_columns.fullpath] = *i;
2411         }
2412         
2413         list_scroller.add (results_display);
2414         list_scroller.set_size_request (-1, 150);
2415         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2416
2417         dvbox.pack_start (dhbox, true, false, 5);
2418         dvbox.pack_start (list_scroller, true, false, 5);
2419         ddhbox.pack_start (dvbox, true, false, 5);
2420
2421         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2422         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2423         results.set_default_response (RESPONSE_CLOSE);
2424         results.set_position (Gtk::WIN_POS_MOUSE);
2425         results.show_all_children ();
2426         results.set_resizable (false);
2427
2428         results.run ();
2429
2430 }
2431
2432 void
2433 ARDOUR_UI::cleanup ()
2434 {
2435         if (session == 0) {
2436                 /* shouldn't happen: menu item is insensitive */
2437                 return;
2438         }
2439
2440
2441         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2442                                 true,
2443                                 Gtk::MESSAGE_QUESTION,
2444                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2445
2446         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2447 ALL undo/redo information will be lost if you cleanup.\n\
2448 After cleanup, unused audio files will be moved to a \
2449 \"dead sounds\" location."));
2450         
2451         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2452         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2453         checker.set_default_response (RESPONSE_CANCEL);
2454
2455         checker.set_name (_("CleanupDialog"));
2456         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2457         checker.set_position (Gtk::WIN_POS_MOUSE);
2458
2459         switch (checker.run()) {
2460         case RESPONSE_ACCEPT:
2461                 break;
2462         default:
2463                 return;
2464         }
2465
2466         Session::cleanup_report rep;
2467
2468         editor->prepare_for_cleanup ();
2469
2470         /* do not allow flush until a session is reloaded */
2471
2472         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2473         if (act) {
2474                 act->set_sensitive (false);
2475         }
2476
2477         if (session->cleanup_sources (rep)) {
2478                 return;
2479         }
2480
2481         checker.hide();
2482         display_cleanup_results (rep, 
2483                                  _("cleaned files"),
2484                                  _("\
2485 The following %1 %2 not in use and \n\
2486 have been moved to:\n\
2487 %3. \n\n\
2488 Flushing the wastebasket will \n\
2489 release an additional\n\
2490 %4 %5bytes of disk space.\n"
2491                                          ));
2492
2493
2494
2495 }
2496
2497 void
2498 ARDOUR_UI::flush_trash ()
2499 {
2500         if (session == 0) {
2501                 /* shouldn't happen: menu item is insensitive */
2502                 return;
2503         }
2504
2505         Session::cleanup_report rep;
2506
2507         if (session->cleanup_trash_sources (rep)) {
2508                 return;
2509         }
2510
2511         display_cleanup_results (rep, 
2512                                  _("deleted file"),
2513                                  _("The following %1 %2 deleted from\n\
2514 %3,\n\
2515 releasing %4 %5bytes of disk space"));
2516 }
2517
2518 void
2519 ARDOUR_UI::add_route (Gtk::Window* float_window)
2520 {
2521         int count;
2522
2523         if (!session) {
2524                 return;
2525         }
2526
2527         if (add_route_dialog == 0) {
2528                 add_route_dialog = new AddRouteDialog;
2529                 if (float_window) {
2530                         add_route_dialog->set_transient_for (*float_window);
2531                 }
2532         }
2533
2534         if (add_route_dialog->is_visible()) {
2535                 /* we're already doing this */
2536                 return;
2537         }
2538
2539         ResponseType r = (ResponseType) add_route_dialog->run ();
2540         
2541         add_route_dialog->hide();
2542
2543         switch (r) {
2544         case RESPONSE_ACCEPT:
2545                 break;
2546         default:
2547                 return;
2548                 break;
2549         }
2550
2551         if ((count = add_route_dialog->count()) <= 0) {
2552                 return;
2553         }
2554
2555         uint32_t input_chan = add_route_dialog->channels ();
2556         uint32_t output_chan;
2557         string name_template = add_route_dialog->name_template ();
2558         bool track = add_route_dialog->track ();
2559
2560         AutoConnectOption oac = Config->get_output_auto_connect();
2561
2562         if (oac & AutoConnectMaster) {
2563                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2564         } else {
2565                 output_chan = input_chan;
2566         }
2567
2568         /* XXX do something with name template */
2569
2570         if (track) {
2571                 session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2572         } else {
2573                 session_add_audio_bus (input_chan, output_chan, count);
2574         }
2575 }
2576
2577 XMLNode*
2578 ARDOUR_UI::mixer_settings () const
2579 {
2580         XMLNode* node = 0;
2581
2582         if (session) {
2583                 node = session->instant_xml(X_("Mixer"), session->path());
2584         } else {
2585                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2586         }
2587
2588         if (!node) {
2589                 node = new XMLNode (X_("Mixer"));
2590         }
2591
2592         return node;
2593 }
2594
2595 XMLNode*
2596 ARDOUR_UI::editor_settings () const
2597 {
2598         XMLNode* node = 0;
2599
2600         if (session) {
2601                 node = session->instant_xml(X_("Editor"), session->path());
2602         } else {
2603                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2604         }
2605
2606         if (!node) {
2607                 node = new XMLNode (X_("Editor"));
2608         }
2609         return node;
2610 }
2611
2612 XMLNode*
2613 ARDOUR_UI::keyboard_settings () const
2614 {
2615         XMLNode* node = 0;
2616
2617         node = Config->extra_xml(X_("Keyboard"));
2618         
2619         if (!node) {
2620                 node = new XMLNode (X_("Keyboard"));
2621         }
2622         return node;
2623 }
2624
2625 void
2626 ARDOUR_UI::halt_on_xrun_message ()
2627 {
2628         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2629
2630         MessageDialog msg (*editor,
2631                            _("Recording was stopped because your system could not keep up."));
2632         msg.run ();
2633 }
2634
2635 void
2636 ARDOUR_UI::disk_overrun_handler ()
2637 {
2638         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2639
2640         if (!have_disk_speed_dialog_displayed) {
2641                 have_disk_speed_dialog_displayed = true;
2642                 MessageDialog* msg = new MessageDialog (*editor, _("\
2643 The disk system on your computer\n\
2644 was not able to keep up with Ardour.\n\
2645 \n\
2646 Specifically, it failed to write data to disk\n\
2647 quickly enough to keep up with recording.\n"));
2648                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2649                 msg->show_all ();
2650         }
2651 }
2652
2653 void
2654 ARDOUR_UI::disk_underrun_handler ()
2655 {
2656         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2657
2658         if (!have_disk_speed_dialog_displayed) {
2659                 have_disk_speed_dialog_displayed = true;
2660                 MessageDialog* msg = new MessageDialog (*editor,
2661                                    _("The disk system on your computer\n\
2662 was not able to keep up with Ardour.\n\
2663 \n\
2664 Specifically, it failed to read data from disk\n\
2665 quickly enough to keep up with playback.\n"));
2666                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2667                 msg->show_all ();
2668         } 
2669 }
2670
2671 void
2672 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2673 {
2674         have_disk_speed_dialog_displayed = false;
2675         delete msg;
2676 }
2677
2678 int
2679 ARDOUR_UI::pending_state_dialog ()
2680 {
2681         ArdourDialog dialog ("pending state dialog");
2682         Label  message (_("\
2683 This session appears to have been in\n\
2684 middle of recording when ardour or\n\
2685 the computer was shutdown.\n\
2686 \n\
2687 Ardour can recover any captured audio for\n\
2688 you, or it can ignore it. Please decide\n\
2689 what you would like to do.\n"));
2690
2691         dialog.get_vbox()->pack_start (message);
2692         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2693         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2694
2695         dialog.set_position (WIN_POS_CENTER);
2696         dialog.show_all ();
2697         
2698         switch (dialog.run ()) {
2699         case RESPONSE_ACCEPT:
2700                 return 1;
2701         default:
2702                 return 0;
2703         }
2704 }
2705         
2706 void
2707 ARDOUR_UI::disconnect_from_jack ()
2708 {
2709         if (engine) {
2710                 if( engine->disconnect_from_jack ()) {
2711                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2712                         msg.run ();
2713                 }
2714
2715                 update_sample_rate (0);
2716         }
2717 }
2718
2719 void
2720 ARDOUR_UI::reconnect_to_jack ()
2721 {
2722         if (engine) {
2723                 if (engine->reconnect_to_jack ()) {
2724                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
2725                         msg.run ();
2726                 }
2727
2728                 update_sample_rate (0);
2729         }
2730 }
2731
2732 int
2733 ARDOUR_UI::cmdline_new_session (string path)
2734 {
2735         if (path[0] != '/') {
2736                 char buf[PATH_MAX+1];
2737                 string str;
2738
2739                 getcwd (buf, sizeof (buf));
2740                 str = buf;
2741                 str += '/';
2742                 str += path;
2743                 path = str;
2744         }
2745
2746         new_session (path);
2747
2748         _will_create_new_session_automatically = false; /* done it */
2749         return FALSE; /* don't call it again */
2750 }
2751
2752 void
2753 ARDOUR_UI::use_config ()
2754 {
2755         Glib::RefPtr<Action> act;
2756
2757         switch (Config->get_native_file_data_format ()) {
2758         case FormatFloat:
2759                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2760                 break;
2761         case FormatInt24:
2762                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2763                 break;
2764         case FormatInt16:
2765                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
2766                 break;
2767         }
2768
2769         if (act) {
2770                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2771                 ract->set_active ();
2772         }       
2773
2774         switch (Config->get_native_file_header_format ()) {
2775         case BWF:
2776                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2777                 break;
2778         case WAVE:
2779                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2780                 break;
2781         case WAVE64:
2782                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2783                 break;
2784         case iXML:
2785                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2786                 break;
2787         case RF64:
2788                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2789                 break;
2790         case CAF:
2791                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2792                 break;
2793         case AIFF:
2794                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2795                 break;
2796         }
2797
2798         if (act) {
2799                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2800                 ract->set_active ();
2801         }       
2802
2803         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2804         if (node) {
2805                 set_transport_controllable_state (*node);
2806         }
2807 }
2808
2809 void
2810 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2811 {
2812         if (Config->get_primary_clock_delta_edit_cursor()) {
2813                 primary_clock.set (pos, false, editor->edit_cursor_position(false), 1);
2814         } else {
2815                 primary_clock.set (pos, 0, true);
2816         }
2817
2818         if (Config->get_secondary_clock_delta_edit_cursor()) {
2819                 secondary_clock.set (pos, false, editor->edit_cursor_position(false), 2);
2820         } else {
2821                 secondary_clock.set (pos);
2822         }
2823
2824         if (big_clock_window) {
2825                 big_clock.set (pos);
2826         }
2827 }
2828
2829 void
2830 ARDOUR_UI::record_state_changed ()
2831 {
2832         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2833
2834         if (!session || !big_clock_window) {
2835                 /* why bother - the clock isn't visible */
2836                 return;
2837         }
2838
2839         switch (session->record_status()) {
2840         case Session::Recording:
2841                 big_clock.set_widget_name ("BigClockRecording");
2842                 break;
2843         default:
2844                 big_clock.set_widget_name ("BigClockNonRecording");
2845                 break;
2846         }
2847 }
2848
2849 void
2850 ARDOUR_UI::set_keybindings_path (string path)
2851 {
2852         keybindings_path = path;
2853 }
2854
2855 void
2856 ARDOUR_UI::save_keybindings ()
2857 {
2858         if (can_save_keybindings) {
2859                 AccelMap::save (user_keybindings_path);
2860         } 
2861 }
2862
2863 bool
2864 ARDOUR_UI::first_idle ()
2865 {
2866         if (session) {
2867                 session->allow_auto_play (true);
2868         }
2869         can_save_keybindings = true;
2870         return false;
2871 }
2872
2873 void
2874 ARDOUR_UI::store_clock_modes ()
2875 {
2876         XMLNode* node = new XMLNode(X_("ClockModes"));
2877
2878         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2879                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2880         }
2881
2882         session->add_extra_xml (*node);
2883         session->set_dirty ();
2884 }
2885
2886
2887                 
2888 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2889         : Controllable (name), ui (u), type(tp)
2890 {
2891         
2892 }
2893
2894 void
2895 ARDOUR_UI::TransportControllable::set_value (float val)
2896 {
2897         if (type == ShuttleControl) {
2898                 double fract;
2899
2900                 if (val == 0.5f) {
2901                         fract = 0.0;
2902                 } else {
2903                         if (val < 0.5f) {
2904                                 fract = -((0.5f - val)/0.5f);
2905                         } else {
2906                                 fract = ((val - 0.5f)/0.5f);
2907                         }
2908                 }
2909                 
2910                 ui.set_shuttle_fract (fract);
2911                 return;
2912         }
2913
2914         if (val < 0.5f) {
2915                 /* do nothing: these are radio-style actions */
2916                 return;
2917         }
2918
2919         char *action = 0;
2920
2921         switch (type) {
2922         case Roll:
2923                 action = X_("Roll");
2924                 break;
2925         case Stop:
2926                 action = X_("Stop");
2927                 break;
2928         case GotoStart:
2929                 action = X_("Goto Start");
2930                 break;
2931         case GotoEnd:
2932                 action = X_("Goto End");
2933                 break;
2934         case AutoLoop:
2935                 action = X_("Loop");
2936                 break;
2937         case PlaySelection:
2938                 action = X_("Play Selection");
2939                 break;
2940         case RecordEnable:
2941                 action = X_("Record");
2942                 break;
2943         default:
2944                 break;
2945         }
2946
2947         if (action == 0) {
2948                 return;
2949         }
2950
2951         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2952
2953         if (act) {
2954                 act->activate ();
2955         }
2956 }
2957
2958 float
2959 ARDOUR_UI::TransportControllable::get_value (void) const
2960 {
2961         float val = 0.0f;
2962         
2963         switch (type) {
2964         case Roll:
2965                 break;
2966         case Stop:
2967                 break;
2968         case GotoStart:
2969                 break;
2970         case GotoEnd:
2971                 break;
2972         case AutoLoop:
2973                 break;
2974         case PlaySelection:
2975                 break;
2976         case RecordEnable:
2977                 break;
2978         case ShuttleControl:
2979                 break;
2980         default:
2981                 break;
2982         }
2983
2984         return val;
2985 }
2986
2987 void
2988 ARDOUR_UI::TransportControllable::set_id (const string& str)
2989 {
2990         _id = str;
2991 }
2992
2993 void
2994 ARDOUR_UI::setup_profile ()
2995 {
2996         if (gdk_screen_width() < 1200) {
2997                 Profile->set_small_screen ();
2998         }
2999
3000         if (getenv ("ARDOUR_SAE")) {
3001                 Profile->set_sae ();
3002                 Profile->set_single_package ();
3003         }
3004 }
3005
3006 void
3007 ARDOUR_UI::audioengine_setup ()
3008 {
3009 }