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