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