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