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