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