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