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