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