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