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