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