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