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