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