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