more fixes
[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 <pbd/error.h>
32 #include <pbd/compose.h>
33 #include <pbd/basename.h>
34 #include <pbd/pathscanner.h>
35 #include <pbd/failed_constructor.h>
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/pix.h>
38 #include <gtkmm2ext/utils.h>
39 #include <gtkmm2ext/click_box.h>
40 #include <gtkmm2ext/fastmeter.h>
41 #include <gtkmm2ext/stop_signal.h>
42 #include <gtkmm2ext/popup.h>
43
44 #include <midi++/port.h>
45 #include <midi++/mmc.h>
46
47 #include <ardour/ardour.h>
48 #include <ardour/port.h>
49 #include <ardour/audioengine.h>
50 #include <ardour/playlist.h>
51 #include <ardour/utils.h>
52 #include <ardour/diskstream.h>
53 #include <ardour/filesource.h>
54 #include <ardour/recent_sessions.h>
55 #include <ardour/session_diskstream.h>
56 #include <ardour/port.h>
57 #include <ardour/audio_track.h>
58
59 #include "actions.h"
60 #include "ardour_ui.h"
61 #include "ardour_message.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
75 #include "i18n.h"
76
77 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
79 using namespace Gtk;
80 using namespace sigc;
81
82 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
83
84 sigc::signal<void,bool> ARDOUR_UI::Blink;
85 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
86 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
87 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
88
89 /* XPM */
90 static const gchar *h_meter_strip_xpm[] = {
91 "186 5 187 2",
92 "       c None",
93 ".      c #2BFE00",
94 "+      c #2DFE00",
95 "@      c #2FFE01",
96 "#      c #32FE01",
97 "$      c #34FE02",
98 "%      c #36FE02",
99 "&      c #38FE03",
100 "*      c #3BFE03",
101 "=      c #3DFD04",
102 "-      c #3FFD04",
103 ";      c #41FD05",
104 ">      c #44FD05",
105 ",      c #46FD06",
106 "'      c #48FD06",
107 ")      c #4AFD07",
108 "!      c #4DFD07",
109 "~      c #4FFD08",
110 "{      c #51FC08",
111 "]      c #53FC09",
112 "^      c #56FC09",
113 "/      c #58FC09",
114 "(      c #5AFC0A",
115 "_      c #5CFC0A",
116 ":      c #5FFC0B",
117 "<      c #61FC0B",
118 "[      c #63FB0C",
119 "}      c #65FB0C",
120 "|      c #68FB0D",
121 "1      c #6AFB0D",
122 "2      c #6CFB0E",
123 "3      c #6EFB0E",
124 "4      c #71FB0F",
125 "5      c #73FB0F",
126 "6      c #75FB10",
127 "7      c #77FA10",
128 "8      c #7AFA11",
129 "9      c #7CFA11",
130 "0      c #7EFA12",
131 "a      c #80FA12",
132 "b      c #83FA12",
133 "c      c #85FA13",
134 "d      c #87FA13",
135 "e      c #89FA14",
136 "f      c #8CF914",
137 "g      c #8EF915",
138 "h      c #90F915",
139 "i      c #92F916",
140 "j      c #95F916",
141 "k      c #97F917",
142 "l      c #99F917",
143 "m      c #9BF918",
144 "n      c #9EF818",
145 "o      c #A0F819",
146 "p      c #A2F819",
147 "q      c #A4F81A",
148 "r      c #A7F81A",
149 "s      c #A9F81A",
150 "t      c #ABF81B",
151 "u      c #ADF81B",
152 "v      c #B0F81C",
153 "w      c #B2F71C",
154 "x      c #B4F71D",
155 "y      c #B6F71D",
156 "z      c #B9F71E",
157 "A      c #BBF71E",
158 "B      c #BDF71F",
159 "C      c #BFF71F",
160 "D      c #C2F720",
161 "E      c #C4F720",
162 "F      c #C6F621",
163 "G      c #C8F621",
164 "H      c #CBF622",
165 "I      c #CDF622",
166 "J      c #CFF623",
167 "K      c #D1F623",
168 "L      c #D4F624",
169 "M      c #D6F624",
170 "N      c #D8F524",
171 "O      c #DAF525",
172 "P      c #DDF525",
173 "Q      c #DFF526",
174 "R      c #E1F526",
175 "S      c #E3F527",
176 "T      c #E6F527",
177 "U      c #E8F528",
178 "V      c #EAF528",
179 "W      c #ECF429",
180 "X      c #EFF429",
181 "Y      c #F1F42A",
182 "Z      c #F3F42A",
183 "`      c #F5F42B",
184 " .     c #F8F42B",
185 "..     c #FAF42C",
186 "+.     c #FCF42C",
187 "@.     c #FFF42D",
188 "#.     c #FFF22C",
189 "$.     c #FFF12B",
190 "%.     c #FFF02A",
191 "&.     c #FFEF2A",
192 "*.     c #FFEE29",
193 "=.     c #FFED28",
194 "-.     c #FFEC28",
195 ";.     c #FFEB27",
196 ">.     c #FFE926",
197 ",.     c #FFE826",
198 "'.     c #FFE725",
199 ").     c #FFE624",
200 "!.     c #FFE524",
201 "~.     c #FFE423",
202 "{.     c #FFE322",
203 "].     c #FFE222",
204 "^.     c #FFE021",
205 "/.     c #FFDF20",
206 "(.     c #FFDE20",
207 "_.     c #FFDD1F",
208 ":.     c #FFDC1E",
209 "<.     c #FFDB1E",
210 "[.     c #FFDA1D",
211 "}.     c #FFD91C",
212 "|.     c #FFD71B",
213 "1.     c #FFD61B",
214 "2.     c #FFD51A",
215 "3.     c #FFD419",
216 "4.     c #FFD319",
217 "5.     c #FFD218",
218 "6.     c #FFD117",
219 "7.     c #FFD017",
220 "8.     c #FFCF16",
221 "9.     c #FFCD15",
222 "0.     c #FFCC15",
223 "a.     c #FFCB14",
224 "b.     c #FFCA13",
225 "c.     c #FFC913",
226 "d.     c #FFC812",
227 "e.     c #FFC711",
228 "f.     c #FFC611",
229 "g.     c #FFC410",
230 "h.     c #FFC30F",
231 "i.     c #FFC20F",
232 "j.     c #FFC10E",
233 "k.     c #FFC00D",
234 "l.     c #FFBF0C",
235 "m.     c #FFBE0C",
236 "n.     c #FFBD0B",
237 "o.     c #FFBB0A",
238 "p.     c #FFBA0A",
239 "q.     c #FFB909",
240 "r.     c #FFB808",
241 "s.     c #FFB708",
242 "t.     c #FFB607",
243 "u.     c #FFB506",
244 "v.     c #FFB406",
245 "w.     c #FFB205",
246 "x.     c #FFB104",
247 "y.     c #FFB004",
248 "z.     c #FFAF03",
249 "A.     c #FFAE02",
250 "B.     c #FFAD02",
251 "C.     c #FFAC01",
252 "D.     c #FFAB00",
253 "E.     c #FFA900",
254 "F.     c #F11F00",
255 "G.     c #F21E00",
256 "H.     c #F21C00",
257 "I.     c #F31B00",
258 "J.     c #F31A00",
259 "K.     c #F41800",
260 "L.     c #F41700",
261 "M.     c #F51600",
262 "N.     c #F61400",
263 "O.     c #F61300",
264 "P.     c #F71100",
265 "Q.     c #F71000",
266 "R.     c #F80F00",
267 "S.     c #F90D00",
268 "T.     c #F90C00",
269 "U.     c #FA0B00",
270 "V.     c #FA0900",
271 "W.     c #FB0800",
272 "X.     c #FC0600",
273 "Y.     c #FC0500",
274 "Z.     c #FD0400",
275 "`.     c #FD0200",
276 " +     c #FE0100",
277 ".+     c #FE0000",
278 "++     c #FF0000",
279 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
280 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
281 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
282 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
283 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++"};
284
285 /* XPM */
286 static const gchar * v_meter_strip_xpm[] = {
287 "5 250 230 2",
288 "       c None",
289 ".      c #FE0000",
290 "+      c #FF0000",
291 "@      c #FE0100",
292 "#      c #FD0200",
293 "$      c #FD0300",
294 "%      c #FD0400",
295 "&      c #FC0500",
296 "*      c #FC0600",
297 "=      c #FC0700",
298 "-      c #FB0800",
299 ";      c #FA0900",
300 ">      c #FA0A00",
301 ",      c #FA0B00",
302 "'      c #F90C00",
303 ")      c #F90D00",
304 "!      c #F80E00",
305 "~      c #F80F00",
306 "{      c #F71000",
307 "]      c #F71100",
308 "^      c #F61200",
309 "/      c #F61300",
310 "(      c #F61400",
311 "_      c #F51600",
312 ":      c #F41700",
313 "<      c #F41800",
314 "[      c #F31A00",
315 "}      c #F31B00",
316 "|      c #F21C00",
317 "1      c #F21E00",
318 "2      c #F11F00",
319 "3      c #F54A00",
320 "4      c #FFA900",
321 "5      c #FFAB00",
322 "6      c #FFAC01",
323 "7      c #FFAD02",
324 "8      c #FFAE02",
325 "9      c #FFAF03",
326 "0      c #FFB004",
327 "a      c #FFB104",
328 "b      c #FFB205",
329 "c      c #FFB406",
330 "d      c #FFB506",
331 "e      c #FFB607",
332 "f      c #FFB708",
333 "g      c #FFB808",
334 "h      c #FFB909",
335 "i      c #FFBA0A",
336 "j      c #FFBB0A",
337 "k      c #FFBC0A",
338 "l      c #FFBD0B",
339 "m      c #FFBE0C",
340 "n      c #FFBF0C",
341 "o      c #FFC00D",
342 "p      c #FFC10E",
343 "q      c #FFC20F",
344 "r      c #FFC30F",
345 "s      c #FFC410",
346 "t      c #FFC511",
347 "u      c #FFC611",
348 "v      c #FFC711",
349 "w      c #FFC812",
350 "x      c #FFC913",
351 "y      c #FFCA13",
352 "z      c #FFCB14",
353 "A      c #FFCC15",
354 "B      c #FFCD15",
355 "C      c #FFCF16",
356 "D      c #FFD017",
357 "E      c #FFD117",
358 "F      c #FFD218",
359 "G      c #FFD319",
360 "H      c #FFD419",
361 "I      c #FFD51A",
362 "J      c #FFD61B",
363 "K      c #FFD71B",
364 "L      c #FFD81C",
365 "M      c #FFD91C",
366 "N      c #FFDA1D",
367 "O      c #FFDB1E",
368 "P      c #FFDC1E",
369 "Q      c #FFDD1F",
370 "R      c #FFDE20",
371 "S      c #FFDF20",
372 "T      c #FFE021",
373 "U      c #FFE222",
374 "V      c #FFE322",
375 "W      c #FFE423",
376 "X      c #FFE524",
377 "Y      c #FFE624",
378 "Z      c #FFE725",
379 "`      c #FFE826",
380 " .     c #FFE926",
381 "..     c #FFEA26",
382 "+.     c #FFEB27",
383 "@.     c #FFEC28",
384 "#.     c #FFED28",
385 "$.     c #FFEE29",
386 "%.     c #FFEF2A",
387 "&.     c #FFF02A",
388 "*.     c #FFF12B",
389 "=.     c #FFF22C",
390 "-.     c #FFF32D",
391 ";.     c #FFF42D",
392 ">.     c #FDF42C",
393 ",.     c #FBF42C",
394 "'.     c #FAF42C",
395 ").     c #F8F42B",
396 "!.     c #F6F42B",
397 "~.     c #F4F42B",
398 "{.     c #F3F42A",
399 "].     c #F1F42A",
400 "^.     c #F0F429",
401 "/.     c #EEF429",
402 "(.     c #ECF429",
403 "_.     c #EAF528",
404 ":.     c #E9F528",
405 "<.     c #E7F528",
406 "[.     c #E5F527",
407 "}.     c #E3F527",
408 "|.     c #E2F526",
409 "1.     c #E0F526",
410 "2.     c #DFF526",
411 "3.     c #DDF525",
412 "4.     c #DBF525",
413 "5.     c #D9F525",
414 "6.     c #D8F524",
415 "7.     c #D6F624",
416 "8.     c #D5F624",
417 "9.     c #D3F624",
418 "0.     c #D1F623",
419 "a.     c #CFF623",
420 "b.     c #CEF622",
421 "c.     c #CCF622",
422 "d.     c #CBF622",
423 "e.     c #C9F621",
424 "f.     c #C7F621",
425 "g.     c #C5F621",
426 "h.     c #C4F720",
427 "i.     c #C2F720",
428 "j.     c #C0F71F",
429 "k.     c #BEF71F",
430 "l.     c #BDF71F",
431 "m.     c #BBF71E",
432 "n.     c #BAF71E",
433 "o.     c #B8F71E",
434 "p.     c #B6F71D",
435 "q.     c #B5F71D",
436 "r.     c #B3F71D",
437 "s.     c #B2F71C",
438 "t.     c #B0F81C",
439 "u.     c #AEF81B",
440 "v.     c #ACF81B",
441 "w.     c #ABF81B",
442 "x.     c #A9F81A",
443 "y.     c #A8F81A",
444 "z.     c #A6F81A",
445 "A.     c #A4F81A",
446 "B.     c #A2F819",
447 "C.     c #A1F819",
448 "D.     c #9FF819",
449 "E.     c #9EF818",
450 "F.     c #9BF918",
451 "G.     c #9AF917",
452 "H.     c #98F917",
453 "I.     c #97F917",
454 "J.     c #95F916",
455 "K.     c #93F916",
456 "L.     c #91F916",
457 "M.     c #90F915",
458 "N.     c #8EF915",
459 "O.     c #8DF914",
460 "P.     c #8BF914",
461 "Q.     c #89FA14",
462 "R.     c #87FA13",
463 "S.     c #86FA13",
464 "T.     c #84FA13",
465 "U.     c #83FA12",
466 "V.     c #81FA12",
467 "W.     c #7FFA12",
468 "X.     c #7DFA12",
469 "Y.     c #7CFA11",
470 "Z.     c #7AFA11",
471 "`.     c #78FA10",
472 " +     c #76FA10",
473 ".+     c #75FB10",
474 "++     c #73FB0F",
475 "@+     c #72FB0F",
476 "#+     c #70FB0F",
477 "$+     c #6EFB0E",
478 "%+     c #6DFB0E",
479 "&+     c #6BFB0E",
480 "*+     c #6AFB0D",
481 "=+     c #68FB0D",
482 "-+     c #66FB0C",
483 ";+     c #64FB0C",
484 ">+     c #63FB0C",
485 ",+     c #61FC0B",
486 "'+     c #60FC0B",
487 ")+     c #5EFC0B",
488 "!+     c #5CFC0A",
489 "~+     c #5AFC0A",
490 "{+     c #59FC09",
491 "]+     c #57FC09",
492 "^+     c #56FC09",
493 "/+     c #53FC09",
494 "(+     c #52FC08",
495 "_+     c #50FC08",
496 ":+     c #4FFD08",
497 "<+     c #4DFD07",
498 "[+     c #4BFD07",
499 "}+     c #49FD07",
500 "|+     c #48FD06",
501 "1+     c #46FD06",
502 "2+     c #45FD05",
503 "3+     c #43FD05",
504 "4+     c #41FD05",
505 "5+     c #3FFD04",
506 "6+     c #3EFD04",
507 "7+     c #3CFD04",
508 "8+     c #3BFE03",
509 "9+     c #39FE03",
510 "0+     c #37FE02",
511 "a+     c #35FE02",
512 "b+     c #34FE02",
513 "c+     c #32FE01",
514 "d+     c #30FE01",
515 "e+     c #2EFE01",
516 "f+     c #2DFE00",
517 "g+     c #2BFE00",
518 ". . + + + ",
519 ". . + + + ",
520 "@ @ @ @ @ ",
521 "# # # # # ",
522 "$ $ $ $ $ ",
523 "% % % % % ",
524 "& & & & & ",
525 "* * * * * ",
526 "= = = = = ",
527 "- - - - - ",
528 "; ; ; ; ; ",
529 "> > > > > ",
530 ", , , , , ",
531 "' ' ' ' ' ",
532 ") ) ) ) ) ",
533 "! ! ! ! ! ",
534 "~ ~ ~ ~ ~ ",
535 "{ { { { { ",
536 "] ] ] ] ] ",
537 "^ ^ ^ ^ ^ ",
538 "/ / / / / ",
539 "( ( ( ( ( ",
540 "_ _ _ _ _ ",
541 ": : : : : ",
542 ": : : : : ",
543 "< < < < < ",
544 "[ [ [ [ [ ",
545 "} } } } } ",
546 "} } } } } ",
547 "| | | | | ",
548 "1 1 1 1 1 ",
549 "2 2 2 2 2 ",
550 "3 3 3 3 3 ",
551 "4 4 4 4 4 ",
552 "5 5 5 5 5 ",
553 "6 6 6 6 6 ",
554 "6 6 6 6 6 ",
555 "7 7 7 7 7 ",
556 "8 8 8 8 8 ",
557 "9 9 9 9 9 ",
558 "9 9 9 9 9 ",
559 "0 0 0 0 0 ",
560 "a a a a a ",
561 "a a a a a ",
562 "b b b b b ",
563 "c c c c c ",
564 "d d d d d ",
565 "d d d d d ",
566 "e e e e e ",
567 "f f f f f ",
568 "g g g g g ",
569 "g g g g g ",
570 "h h h h h ",
571 "i i i i i ",
572 "j j j j j ",
573 "k k k k k ",
574 "l l l l l ",
575 "m m m m m ",
576 "n n n n n ",
577 "n n n n n ",
578 "o o o o o ",
579 "p p p p p ",
580 "q q q q q ",
581 "q q q q q ",
582 "r r r r r ",
583 "s s s s s ",
584 "t t t t t ",
585 "u u u u u ",
586 "v v v v v ",
587 "w w w w w ",
588 "x x x x x ",
589 "x x x x x ",
590 "y y y y y ",
591 "z z z z z ",
592 "A A A A A ",
593 "A A A A A ",
594 "B B B B B ",
595 "C C C C C ",
596 "D D D D D ",
597 "D D D D D ",
598 "E E E E E ",
599 "F F F F F ",
600 "G G G G G ",
601 "G G G G G ",
602 "H H H H H ",
603 "I I I I I ",
604 "I I I I I ",
605 "J J J J J ",
606 "K K K K K ",
607 "L L L L L ",
608 "M M M M M ",
609 "N N N N N ",
610 "O O O O O ",
611 "P P P P P ",
612 "P P P P P ",
613 "Q Q Q Q Q ",
614 "R R R R R ",
615 "S S S S S ",
616 "S S S S S ",
617 "T T T T T ",
618 "U U U U U ",
619 "V V V V V ",
620 "V V V V V ",
621 "W W W W W ",
622 "X X X X X ",
623 "Y Y Y Y Y ",
624 "Y Y Y Y Y ",
625 "Z Z Z Z Z ",
626 "` ` ` ` ` ",
627 " . . . . .",
628 "..........",
629 "+.+.+.+.+.",
630 "@.@.@.@.@.",
631 "#.#.#.#.#.",
632 "#.#.#.#.#.",
633 "$.$.$.$.$.",
634 "%.%.%.%.%.",
635 "&.&.&.&.&.",
636 "&.&.&.&.&.",
637 "*.*.*.*.*.",
638 "=.=.=.=.=.",
639 "-.-.-.-.-.",
640 ";.;.;.;.;.",
641 ";.;.;.;.;.",
642 ">.>.>.>.>.",
643 ",.,.,.,.,.",
644 "'.'.'.'.'.",
645 ").).).).).",
646 "!.!.!.!.!.",
647 "~.~.~.~.~.",
648 "{.{.{.{.{.",
649 "].].].].].",
650 "^.^.^.^.^.",
651 "/././././.",
652 "(.(.(.(.(.",
653 "_._._._._.",
654 ":.:.:.:.:.",
655 "<.<.<.<.<.",
656 "[.[.[.[.[.",
657 "}.}.}.}.}.",
658 "|.|.|.|.|.",
659 "1.1.1.1.1.",
660 "2.2.2.2.2.",
661 "3.3.3.3.3.",
662 "4.4.4.4.4.",
663 "5.5.5.5.5.",
664 "6.6.6.6.6.",
665 "7.7.7.7.7.",
666 "8.8.8.8.8.",
667 "9.9.9.9.9.",
668 "0.0.0.0.0.",
669 "a.a.a.a.a.",
670 "b.b.b.b.b.",
671 "c.c.c.c.c.",
672 "d.d.d.d.d.",
673 "e.e.e.e.e.",
674 "f.f.f.f.f.",
675 "g.g.g.g.g.",
676 "h.h.h.h.h.",
677 "i.i.i.i.i.",
678 "j.j.j.j.j.",
679 "k.k.k.k.k.",
680 "l.l.l.l.l.",
681 "m.m.m.m.m.",
682 "n.n.n.n.n.",
683 "o.o.o.o.o.",
684 "p.p.p.p.p.",
685 "q.q.q.q.q.",
686 "r.r.r.r.r.",
687 "s.s.s.s.s.",
688 "t.t.t.t.t.",
689 "u.u.u.u.u.",
690 "v.v.v.v.v.",
691 "w.w.w.w.w.",
692 "x.x.x.x.x.",
693 "y.y.y.y.y.",
694 "z.z.z.z.z.",
695 "A.A.A.A.A.",
696 "B.B.B.B.B.",
697 "C.C.C.C.C.",
698 "D.D.D.D.D.",
699 "E.E.E.E.E.",
700 "F.F.F.F.F.",
701 "G.G.G.G.G.",
702 "H.H.H.H.H.",
703 "I.I.I.I.I.",
704 "J.J.J.J.J.",
705 "K.K.K.K.K.",
706 "L.L.L.L.L.",
707 "M.M.M.M.M.",
708 "N.N.N.N.N.",
709 "O.O.O.O.O.",
710 "P.P.P.P.P.",
711 "Q.Q.Q.Q.Q.",
712 "R.R.R.R.R.",
713 "S.S.S.S.S.",
714 "T.T.T.T.T.",
715 "U.U.U.U.U.",
716 "V.V.V.V.V.",
717 "W.W.W.W.W.",
718 "X.X.X.X.X.",
719 "Y.Y.Y.Y.Y.",
720 "Z.Z.Z.Z.Z.",
721 "`.`.`.`.`.",
722 " + + + + +",
723 ".+.+.+.+.+",
724 "++++++++++",
725 "@+@+@+@+@+",
726 "#+#+#+#+#+",
727 "$+$+$+$+$+",
728 "%+%+%+%+%+",
729 "&+&+&+&+&+",
730 "*+*+*+*+*+",
731 "=+=+=+=+=+",
732 "-+-+-+-+-+",
733 ";+;+;+;+;+",
734 ">+>+>+>+>+",
735 ",+,+,+,+,+",
736 "'+'+'+'+'+",
737 ")+)+)+)+)+",
738 "!+!+!+!+!+",
739 "~+~+~+~+~+",
740 "{+{+{+{+{+",
741 "]+]+]+]+]+",
742 "^+^+^+^+^+",
743 "/+/+/+/+/+",
744 "(+(+(+(+(+",
745 "_+_+_+_+_+",
746 ":+:+:+:+:+",
747 "<+<+<+<+<+",
748 "[+[+[+[+[+",
749 "}+}+}+}+}+",
750 "|+|+|+|+|+",
751 "1+1+1+1+1+",
752 "2+2+2+2+2+",
753 "3+3+3+3+3+",
754 "4+4+4+4+4+",
755 "5+5+5+5+5+",
756 "6+6+6+6+6+",
757 "7+7+7+7+7+",
758 "8+8+8+8+8+",
759 "9+9+9+9+9+",
760 "0+0+0+0+0+",
761 "a+a+a+a+a+",
762 "b+b+b+b+b+",
763 "c+c+c+c+c+",
764 "d+d+d+d+d+",
765 "e+e+e+e+e+",
766 "f+f+f+f+f+",
767 "g+g+g+g+g+"};
768
769 static const char* channel_setup_names[] = {
770         "mono",
771         "stereo",
772         "3 channels",
773         "4 channels",
774         "5 channels",
775         "8 channels",
776         "manual setup",
777         0
778 };
779
780 vector<string> channel_combo_strings;
781
782 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
783
784         : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
785           
786           primary_clock (X_("TransportClockDisplay"), true, false, true),
787           secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
788           preroll_clock (X_("PreRollClock"), true, true),
789           postroll_clock (X_("PostRollClock"), true, true),
790
791           /* adjuster table */
792
793           adjuster_table (3, 3),
794
795           /* preroll stuff */
796
797           preroll_button (_("pre\nroll")),
798           postroll_button (_("post\nroll")),
799
800           /* big clock */
801
802           big_clock ("BigClockDisplay", true),
803
804           /* transport */
805
806           shuttle_units_button (_("% ")),
807           shuttle_style_button (_("spring")),
808
809           punch_in_button (_("punch\nin")),
810           punch_out_button (_("punch\nout")),
811           auto_return_button (_("auto\nreturn")),
812           auto_play_button (_("auto\nplay")),
813           auto_input_button (_("auto\ninput")),
814           click_button (_("click")),
815           follow_button (_("follow\nPH")),
816           auditioning_alert_button (_("AUDITIONING")),
817           solo_alert_button (_("SOLO")),
818           shown_flag (false)
819
820 {
821         using namespace Gtk::Menu_Helpers;
822
823         Gtkmm2ext::init();
824
825         /* actually, its already loaded, but ... */
826
827         cerr << "Loading UI configuration file " << rcfile << endl;
828
829         about = 0;
830
831         if (theArdourUI == 0) {
832                 theArdourUI = this;
833         }
834
835         // allow run-time rebinding of accels
836
837         Settings::get_default()->property_gtk_can_change_accels() = true;
838
839         ActionManager::init ();
840         
841         m_new_session_dialog = 0;
842         m_new_session_dialog_ref = NewSessionDialogFactory::create();
843         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
844         editor = 0;
845         mixer = 0;
846         session = 0;
847         _session_is_new = false;
848         big_clock_window = 0;
849         session_selector_window = 0;
850         last_key_press_time = 0;
851         connection_editor = 0;
852         add_route_dialog = 0;
853         route_params = 0;
854         option_editor = 0;
855         location_ui = 0;
856         open_session_selector = 0;
857         have_configure_timeout = false;
858         have_disk_overrun_displayed = false;
859         have_disk_underrun_displayed = false;
860         _will_create_new_session_automatically = false;
861         session_loaded = false;
862
863
864         last_configure_time.tv_sec = 0;
865         last_configure_time.tv_usec = 0;
866
867         shuttle_grabbed = false;
868         shuttle_fract = 0.0;
869
870         set_shuttle_units (Percentage);
871         set_shuttle_behaviour (Sprung);
872
873         shuttle_style_menu = 0;
874         shuttle_unit_menu = 0;
875
876         gettimeofday (&last_peak_grab, 0);
877         gettimeofday (&last_shuttle_request, 0);
878
879         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
880         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
881         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
882         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
883
884         /* handle pending state with a dialog */
885
886         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
887
888         channel_combo_strings = internationalize (channel_setup_names);
889         
890         /* have to wait for AudioEngine and Configuration before proceeding */
891 }
892
893 void
894 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
895 {
896         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
897         
898         string msg = string_compose (_("\
899 You cannot record-enable\n\
900 track %1\n\
901 because it has no input connections.\n\
902 You would be wasting space recording silence."),
903                               ds->name());
904
905         ArdourMessage message (editor, X_("cannotrecord"), msg);
906 }
907
908 void
909 ARDOUR_UI::set_engine (AudioEngine& e)
910 {
911         engine = &e;
912
913         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
914         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
915         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
916         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
917
918         _tooltips.enable();
919
920         keyboard = new Keyboard;
921         install_keybindings ();
922
923         FastMeter::set_vertical_xpm (v_meter_strip_xpm);
924         FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
925
926         if (setup_windows ()) {
927                 throw failed_constructor ();
928         }
929
930         if (GTK_ARDOUR::show_key_actions) {
931                 vector<string> names;
932                 vector<string> paths;
933                 vector<string> keys;
934                 vector<AccelKey> bindings;
935
936                 ActionManager::get_all_actions (names, paths, keys, bindings);
937
938                 vector<string>::iterator n;
939                 vector<string>::iterator k;
940                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
941                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
942                 }
943
944                 exit (0);
945         }
946
947         /* start with timecode, metering enabled
948         */
949         
950         blink_timeout_tag = -1;
951
952         /* this being a GUI and all, we want peakfiles */
953
954         FileSource::set_build_peakfiles (true);
955         FileSource::set_build_missing_peakfiles (true);
956
957         if (Source::start_peak_thread ()) {
958                 throw failed_constructor();
959         }
960
961         /* start the time-of-day-clock */
962         
963         update_wall_clock ();
964         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
965
966         update_disk_space ();
967         update_cpu_load ();
968         update_sample_rate (engine->frame_rate());
969
970         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
971         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
972 }
973
974 ARDOUR_UI::~ARDOUR_UI ()
975 {
976         save_ardour_state ();
977
978         if (keyboard) {
979                 delete keyboard;
980         }
981
982         if (editor) {
983                 delete editor;
984         }
985
986         if (mixer) {
987                 delete mixer;
988         }
989
990         if (add_route_dialog) {
991                 delete add_route_dialog;
992         }
993
994         Source::stop_peak_thread ();
995 }
996
997 gint
998 ARDOUR_UI::configure_timeout ()
999 {
1000         struct timeval now;
1001         struct timeval diff;
1002
1003         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
1004                 /* no configure events yet */
1005                 return TRUE;
1006         }
1007
1008         gettimeofday (&now, 0);
1009         timersub (&now, &last_configure_time, &diff);
1010
1011         /* force a gap of 0.5 seconds since the last configure event
1012          */
1013
1014         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1015                 return TRUE;
1016         } else {
1017                 have_configure_timeout = false;
1018                 save_ardour_state ();
1019                 return FALSE;
1020         }
1021 }
1022
1023 gboolean
1024 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1025 {
1026         if (have_configure_timeout) {
1027                 gettimeofday (&last_configure_time, 0);
1028         } else {
1029                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1030                 have_configure_timeout = true;
1031         }
1032                 
1033         return FALSE;
1034 }
1035
1036 void
1037 ARDOUR_UI::save_ardour_state ()
1038 {
1039         if (!keyboard || !mixer || !editor) {
1040                 return;
1041         }
1042         
1043         /* XXX this is all a bit dubious. add_extra_xml() uses
1044            a different lifetime model from add_instant_xml().
1045         */
1046
1047         XMLNode* node = new XMLNode (keyboard->get_state());
1048         Config->add_extra_xml (*node);
1049         Config->save_state();
1050
1051         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1052         XMLNode& mnode (mixer->get_state());
1053
1054         if (session) {
1055                 session->add_instant_xml(enode, session->path());
1056                 session->add_instant_xml(mnode, session->path());
1057         } else {
1058                 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1059                 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1060         }
1061 }
1062
1063 void
1064 ARDOUR_UI::startup ()
1065 {
1066         /* Once the UI is up and running, start the audio engine. Doing
1067            this before the UI is up and running can cause problems
1068            when not running with SCHED_FIFO, because the amount of
1069            CPU and disk work needed to get the UI started can interfere
1070            with the scheduling of the audio thread.
1071         */
1072
1073         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1074 }
1075
1076 void
1077 ARDOUR_UI::finish()
1078 {
1079         if (session && session->dirty()) {
1080                 switch (ask_about_saving_session(_("quit"))) {
1081                 case -1:
1082                         return;
1083                         break;
1084                 case 1:
1085                         /* use the default name */
1086                         if (save_state_canfail ("")) {
1087                                 /* failed - don't quit */
1088                                 ArdourMessage (editor, X_("badsave dialog"),
1089                                                _("\
1090 Ardour was unable to save your session.\n\n\
1091 If you still wish to quit, please use the\n\n\
1092 \"Just quit\" option."));
1093                                 return;
1094                         }
1095                         break;
1096                 case 0:
1097                         break;
1098                 }
1099         }
1100
1101         quit ();
1102 }
1103
1104 int
1105 ARDOUR_UI::ask_about_saving_session (string what)
1106 {
1107         ArdourDialog window (_("ardour: save session?"));
1108         Gtk::Label  prompt_label;
1109         string msg;
1110
1111         msg = string_compose(_("Save and %1"), what);
1112         window.add_button (msg, RESPONSE_ACCEPT);
1113         msg = string_compose(_("Just %1"), what);
1114         window.add_button (msg, RESPONSE_APPLY);
1115         msg = string_compose(_("Don't %1"), what);
1116         window.add_button (msg, RESPONSE_REJECT);
1117
1118         Gtk::Button noquit_button (msg);
1119         noquit_button.set_name ("EditorGTKButton");
1120
1121         string prompt;
1122         string type;
1123
1124         if (session->snap_name() == session->name()) {
1125                 type = _("session");
1126         } else {
1127                 type = _("snapshot");
1128         }
1129         prompt = string_compose(_("The %1\n\"%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?"), 
1130                          type, session->snap_name());
1131         
1132         prompt_label.set_text (prompt);
1133         prompt_label.set_alignment (0.5, 0.5);
1134         prompt_label.set_name (X_("PrompterLabel"));
1135         
1136         window.get_vbox()->pack_start (prompt_label);
1137
1138         window.set_name (_("Prompter"));
1139         window.set_position (Gtk::WIN_POS_MOUSE);
1140         window.set_modal (true);
1141         window.show_all ();
1142
1143         save_the_session = 0;
1144
1145         editor->ensure_float (window);
1146
1147         ResponseType r = (ResponseType) window.run();
1148
1149         window.hide ();
1150
1151         switch (r) {
1152         case RESPONSE_ACCEPT: // save and get out of here
1153                 return 1;
1154         case RESPONSE_APPLY:  // get out of here
1155                 return 0;
1156         default:
1157                 break;
1158         }
1159
1160         return -1;
1161 }
1162         
1163 gint
1164 ARDOUR_UI::every_second ()
1165 {
1166         update_cpu_load ();
1167         update_buffer_load ();
1168         update_disk_space ();
1169         // update_disk_rate ();
1170         return TRUE;
1171 }
1172
1173 gint
1174 ARDOUR_UI::every_point_one_seconds ()
1175 {
1176         struct timeval now;
1177         struct timeval diff;
1178         
1179         /* do not attempt to grab peak power more than once per cycle.
1180          */
1181
1182         gettimeofday (&now, 0);
1183         timersub (&now, &last_peak_grab, &diff);
1184
1185         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1186                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1187                 last_peak_grab = now;
1188         } 
1189
1190         update_speed_display ();
1191         RapidScreenUpdate(); /* EMIT_SIGNAL */
1192         return TRUE;
1193 }
1194
1195 gint
1196 ARDOUR_UI::every_point_zero_one_seconds ()
1197 {
1198         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1199         return TRUE;
1200 }
1201
1202 void
1203 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1204 {
1205         char buf[32];
1206
1207         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1208
1209         if (!engine->connected()) {
1210
1211                 snprintf (buf, sizeof (buf), _("disconnected"));
1212
1213         } else {
1214
1215                 jack_nframes_t rate = engine->frame_rate();
1216                 
1217                 if (fmod (rate, 1000.0) != 0.0) {
1218                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
1219                                   (float) rate/1000.0f,
1220                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1221                 } else {
1222                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
1223                                   rate/1000,
1224                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1225                 }
1226         }
1227
1228         sample_rate_label.set_text (buf);
1229 }
1230
1231 void
1232 ARDOUR_UI::update_cpu_load ()
1233 {
1234         char buf[32];
1235         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1236         cpu_load_label.set_text (buf);
1237 }
1238
1239 void
1240 ARDOUR_UI::update_disk_rate ()
1241 {
1242         char buf[64];
1243
1244         if (session) {
1245                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
1246                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1247                 disk_rate_label.set_text (buf);
1248         } else {
1249                 disk_rate_label.set_text ("");
1250         }
1251 }
1252
1253 void
1254 ARDOUR_UI::update_buffer_load ()
1255 {
1256         char buf[64];
1257
1258         if (session) {
1259                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
1260                           session->playback_load(), session->capture_load());
1261                 buffer_load_label.set_text (buf);
1262         } else {
1263                 buffer_load_label.set_text ("");
1264         }
1265 }
1266
1267 void
1268 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1269 {
1270         if (ds.record_enabled()) {
1271                 rec_enabled_diskstreams++;
1272         }
1273 }
1274
1275 void
1276 ARDOUR_UI::update_disk_space()
1277 {
1278         if (session == 0) {
1279                 return;
1280         }
1281
1282         jack_nframes_t frames = session->available_capture_duration();
1283         char buf[64];
1284
1285         if (frames == max_frames) {
1286                 strcpy (buf, _("space: 24hrs+"));
1287         } else {
1288                 int hrs;
1289                 int mins;
1290                 int secs;
1291                 jack_nframes_t fr = session->frame_rate();
1292                 
1293                 if (session->actively_recording()){
1294                         
1295                         rec_enabled_diskstreams = 0;
1296                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1297                         
1298                         if (rec_enabled_diskstreams) {
1299                                 frames /= rec_enabled_diskstreams;
1300                         }
1301                         
1302                 } else {
1303                         
1304                         /* hmmm. shall we divide by the route count? or the diskstream count?
1305                            or what? for now, do nothing ...
1306                         */
1307                         
1308                 }
1309                 
1310                 hrs  = frames / (fr * 3600);
1311                 frames -= hrs * fr * 3600;
1312                 mins = frames / (fr * 60);
1313                 frames -= mins * fr * 60;
1314                 secs = frames / fr;
1315                 
1316                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1317         }
1318
1319         disk_space_label.set_text (buf);
1320 }                 
1321
1322 gint
1323 ARDOUR_UI::update_wall_clock ()
1324 {
1325         time_t now;
1326         struct tm *tm_now;
1327         char buf[16];
1328
1329         time (&now);
1330         tm_now = localtime (&now);
1331
1332         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1333         wall_clock_label.set_text (buf);
1334
1335         return TRUE;
1336 }
1337
1338 void
1339 ARDOUR_UI::toggle_recording_plugins ()
1340 {
1341         /* XXX use toggle_some_session_state */
1342
1343         if (session == 0) {
1344                 return;
1345         }
1346
1347         session->set_recording_plugins (!session->get_recording_plugins());
1348 }
1349         
1350 void
1351 ARDOUR_UI::toggle_auto_play ()
1352
1353 {
1354         toggle_some_session_state (auto_play_button,
1355                                    &Session::get_auto_play,
1356                                    &Session::set_auto_play);
1357 }
1358
1359 void
1360 ARDOUR_UI::toggle_auto_return ()
1361
1362 {
1363         toggle_some_session_state (auto_return_button,
1364                                    &Session::get_auto_return,
1365                                    &Session::set_auto_return);
1366 }
1367
1368 void
1369 ARDOUR_UI::toggle_click ()
1370 {
1371         toggle_some_session_state (click_button,
1372                                    &Session::get_clicking,
1373                                    &Session::set_clicking);
1374 }
1375
1376 void
1377 ARDOUR_UI::follow_changed ()
1378 {
1379         bool x;
1380
1381         if (!editor) {
1382                 return;
1383         }
1384
1385         if (follow_button.get_active() != (x = editor->follow_playhead())) {
1386                 follow_button.set_active (x);
1387         }
1388 }
1389
1390 void
1391 ARDOUR_UI::toggle_follow ()
1392 {
1393         bool x;
1394
1395         if (!editor) {
1396                 return;
1397         }
1398
1399         if (editor->follow_playhead() != (x = follow_button.get_active())) {
1400                 editor->set_follow_playhead (x);
1401         }
1402 }
1403
1404 void
1405 ARDOUR_UI::toggle_session_auto_loop ()
1406 {
1407         if (session) {
1408                 if (session->get_auto_loop()) {
1409                         if (session->transport_rolling()) {
1410                                 transport_roll();
1411                         }
1412                         else {
1413                                 session->request_auto_loop (false);
1414                         }
1415                 }
1416                 else {
1417                         session->request_auto_loop (true);
1418                 }
1419         }
1420 }
1421
1422 void
1423 ARDOUR_UI::toggle_session_punch_in ()
1424 {
1425         if (session) {
1426                 session->set_punch_in (!session->get_punch_in());
1427         }
1428 }
1429
1430 void
1431 ARDOUR_UI::toggle_punch_out ()
1432 {
1433         toggle_some_session_state (punch_out_button,
1434                                    &Session::get_punch_out,
1435                                    &Session::set_punch_out);
1436 }
1437
1438 void
1439 ARDOUR_UI::toggle_punch_in ()
1440 {
1441         toggle_some_session_state (punch_in_button,
1442                                    &Session::get_punch_in,
1443                                    &Session::set_punch_in);
1444 }
1445
1446 void
1447 ARDOUR_UI::map_button_state ()
1448
1449 {
1450         map_some_session_state (auto_return_button,
1451                                 &Session::get_auto_return);
1452         map_some_session_state (auto_play_button,
1453                                 &Session::get_auto_play);
1454         map_some_session_state (auto_input_button,
1455                                 &Session::get_auto_input);
1456         map_some_session_state (punch_in_button,
1457                                 &Session::get_punch_in);
1458         map_some_session_state (punch_out_button,
1459                                 &Session::get_punch_out);
1460         map_some_session_state (click_button,
1461                                 &Session::get_clicking);
1462 }
1463
1464 void
1465 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1466 {
1467         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1468 }
1469
1470 void
1471 ARDOUR_UI::map_control_change (Session::ControlType t)
1472 {
1473         switch (t) {
1474         case Session::AutoPlay:
1475                 map_some_session_state (auto_play_button, &Session::get_auto_play);
1476                 break;
1477
1478         case Session::AutoLoop:
1479                 break;
1480
1481         case Session::AutoReturn:
1482                 map_some_session_state (auto_return_button, &Session::get_auto_return);
1483                 break;
1484
1485         case Session::AutoInput:
1486                 map_some_session_state (auto_input_button, &Session::get_auto_input);
1487                 break;
1488
1489         case Session::PunchOut:
1490                 map_some_session_state (punch_in_button, &Session::get_punch_out);
1491                 break;
1492
1493         case Session::PunchIn:
1494                 map_some_session_state (punch_in_button, &Session::get_punch_in);
1495                 break;
1496
1497         case Session::Clicking:
1498                 map_some_session_state (click_button, &Session::get_clicking);
1499                 break;
1500
1501         case Session::SlaveType:
1502 //              map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1503                 break;
1504
1505         case Session::SendMTC:
1506 //              map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1507                 break;
1508
1509         case Session::SendMMC:
1510 //              map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1511                 break;
1512
1513         case Session::MMCControl:       
1514 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1515                 break;
1516
1517         case Session::MidiFeedback:       
1518 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1519                 break;
1520         case Session::MidiControl:       
1521 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1522                 break;
1523                 
1524         case Session::Live:
1525                 break;
1526
1527         case Session::RecordingPlugins:
1528                 break;
1529
1530         case Session::CrossFadesActive:
1531                 break;
1532                 
1533         case Session::EditingMode:
1534                 break;
1535
1536         case Session::PlayRange:
1537                 break;
1538
1539         case Session::AlignChoice:
1540                 /* don't care, this is handled by the options editor */
1541                 break;
1542         case Session::SeamlessLoop:
1543                 /* don't care, this is handled by the options editor */
1544                 break;
1545                
1546         }
1547 }
1548
1549 void
1550 ARDOUR_UI::control_methods_adjusted ()
1551
1552 {
1553         int which_method;
1554
1555         which_method = (int) online_control_button->adjustment.get_value();
1556         switch (which_method) {
1557         case 0:
1558                 allow_mmc_and_local ();
1559                 break;
1560         case 1:
1561                 allow_mmc_only ();
1562                 break;
1563         case 2:
1564                 allow_local_only ();
1565                 break;
1566         default:
1567                 fatal << _("programming error: impossible control method") << endmsg;
1568         }
1569 }
1570         
1571
1572 void
1573 ARDOUR_UI::mmc_device_id_adjusted ()
1574
1575 {
1576 #if 0
1577         if (mmc) {
1578                 int dev_id = (int) mmc_id_button->adjustment.get_value();
1579                 mmc->set_device_id (dev_id);
1580         }
1581 #endif
1582 }
1583
1584 void
1585 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1586                                    bool (Session::*get)() const)
1587         
1588 {
1589         bool x;
1590
1591         if (session == 0) {
1592                 return;
1593         }
1594         
1595         if (button.get_active() != (x = (session->*get)())) {
1596                 button.set_active (x);
1597         }
1598 }
1599
1600 void
1601 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1602                                       bool (Session::*get)() const,
1603                                       void (Session::*set)(bool))
1604
1605 {
1606         bool button_state;
1607         bool session_state;
1608
1609         if (session == 0) {
1610                 return;
1611         }
1612
1613         button_state = button.get_active ();
1614         session_state = (session->*get)();
1615
1616         if (button_state != session_state) {
1617                 (session->*set) (button_state);
1618 #if 0
1619         
1620                 /* check that it worked, and reverse
1621                    the button state if it didn't
1622                 */
1623
1624                 if ((session->*get)() != button_state) {
1625                         button->set_active (!button_state);
1626                 }
1627 #endif
1628
1629         }
1630 }       
1631
1632 gint
1633 ARDOUR_UI::session_menu (GdkEventButton *ev)
1634 {
1635         session_popup_menu->popup (0, 0);
1636         return TRUE;
1637 }
1638
1639 void
1640 ARDOUR_UI::redisplay_recent_sessions ()
1641 {
1642         vector<string *> *sessions;
1643         vector<string *>::iterator i;
1644         RecentSessionsSorter cmp;
1645         
1646         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1647         recent_session_model->clear ();
1648
1649         RecentSessions rs;
1650         ARDOUR::read_recent_sessions (rs);
1651
1652         if (rs.empty()) {
1653                 recent_session_display.set_model (recent_session_model);
1654                 return;
1655         }
1656
1657         /* sort them alphabetically */
1658         sort (rs.begin(), rs.end(), cmp);
1659         sessions = new vector<string*>;
1660
1661         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1662                 sessions->push_back (new string ((*i).second));
1663         }
1664
1665         for (i = sessions->begin(); i != sessions->end(); ++i) {
1666
1667                 vector<string*>* states;
1668                 vector<const gchar*> item;
1669                 string fullpath = *(*i);
1670                 
1671                 /* remove any trailing / */
1672
1673                 if (fullpath[fullpath.length()-1] == '/') {
1674                         fullpath = fullpath.substr (0, fullpath.length()-1);
1675                 }
1676
1677                 /* now get available states for this session */
1678
1679                 if ((states = Session::possible_states (fullpath)) == 0) {
1680                         /* no state file? */
1681                         continue;
1682                 }
1683
1684                 TreeModel::Row row = *(recent_session_model->append());
1685
1686                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1687                 row[recent_session_columns.fullpath] = fullpath;
1688
1689                 if (states->size() > 1) {
1690
1691                         /* add the children */
1692                         
1693                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1694                                 
1695                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1696
1697                                 child_row[recent_session_columns.visible_name] = **i2;
1698                                 child_row[recent_session_columns.fullpath] = fullpath;
1699
1700                                 delete *i2;
1701                         }
1702                 }
1703
1704                 delete states;
1705         }
1706
1707         recent_session_display.set_model (recent_session_model);
1708         delete sessions;
1709 }
1710
1711 void
1712 ARDOUR_UI::build_session_selector ()
1713 {
1714         session_selector_window = new ArdourDialog ("session selector");
1715         
1716         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1717         
1718         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1719         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1720
1721         recent_session_model = TreeStore::create (recent_session_columns);
1722         recent_session_display.set_model (recent_session_model);
1723         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1724         recent_session_display.set_headers_visible (false);
1725
1726         scroller->add (recent_session_display);
1727         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1728
1729         session_selector_window->set_name ("SessionSelectorWindow");
1730         session_selector_window->set_size_request (200, 400);
1731         session_selector_window->get_vbox()->pack_start (*scroller);
1732         session_selector_window->show_all_children();
1733 }
1734
1735 void
1736 ARDOUR_UI::open_recent_session ()
1737 {
1738         /* popup selector window */
1739
1740         if (session_selector_window == 0) {
1741                 build_session_selector ();
1742         }
1743
1744         redisplay_recent_sessions ();
1745
1746         ResponseType r = (ResponseType) session_selector_window->run ();
1747
1748         session_selector_window->hide();
1749
1750         switch (r) {
1751         case RESPONSE_ACCEPT:
1752                 break;
1753         default:
1754                 return;
1755         }
1756
1757         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1758
1759         if (i == recent_session_model->children().end()) {
1760                 return;
1761         }
1762         
1763         Glib::ustring path = (*i)[recent_session_columns.fullpath];
1764         Glib::ustring state = (*i)[recent_session_columns.visible_name];
1765
1766         _session_is_new = false;
1767
1768         load_session (path, state);
1769 }
1770
1771 bool
1772 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
1773 {
1774         struct stat statbuf;
1775
1776         if (stat (info.filename.c_str(), &statbuf) != 0) {
1777                 return false;
1778         }
1779
1780         if (!S_ISDIR(statbuf.st_mode)) {
1781                 return false;
1782         }
1783
1784         string session_file = info.filename;
1785         session_file += '/';
1786         session_file += PBD::basename (info.filename);
1787         session_file += ".ardour";
1788         
1789         if (stat (session_file.c_str(), &statbuf) != 0) {
1790                 return false;
1791         }
1792
1793         return S_ISREG (statbuf.st_mode);
1794 }
1795
1796 void
1797 ARDOUR_UI::open_session ()
1798 {
1799         /* popup selector window */
1800
1801         if (open_session_selector == 0) {
1802
1803                 /* ardour sessions are folders */
1804
1805                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1806                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1807                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1808
1809                 FileFilter session_filter;
1810                 session_filter.add_pattern ("*.ardour");
1811                 session_filter.set_name (_("Ardour sessions"));
1812                 open_session_selector->add_filter (session_filter);
1813                 open_session_selector->set_filter (session_filter);
1814         }
1815
1816         int response = open_session_selector->run();
1817         open_session_selector->hide ();
1818
1819         switch (response) {
1820         case RESPONSE_ACCEPT:
1821                 break;
1822         default:
1823                 open_session_selector->hide();
1824                 return;
1825         }
1826
1827         open_session_selector->hide();
1828         string session_path = open_session_selector->get_filename();
1829         string path, name;
1830         bool isnew;
1831
1832         if (session_path.length() > 0) {
1833                 if (Session::find_session (session_path, path, name, isnew) == 0) {
1834                         _session_is_new = isnew;
1835                         load_session (path, name);
1836                 }
1837         }
1838 }
1839
1840
1841 void
1842 ARDOUR_UI::session_add_midi_track ()
1843 {
1844         cerr << _("Patience is a virtue.\n");
1845 }
1846
1847 void
1848 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1849 {
1850         Route* route;
1851
1852         if (session == 0) {
1853                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1854                 return;
1855         }
1856
1857         try { 
1858                 if (disk) {
1859                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1860                                 error << _("could not create new audio track") << endmsg;
1861                         }
1862                 } else {
1863                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1864                                 error << _("could not create new audio bus") << endmsg;
1865                         }
1866                 }
1867                 
1868 #if CONTROLOUTS
1869                 if (need_control_room_outs) {
1870                         pan_t pans[2];
1871                         
1872                         pans[0] = 0.5;
1873                         pans[1] = 0.5;
1874                         
1875                         route->set_stereo_control_outs (control_lr_channels);
1876                         route->control_outs()->set_stereo_pan (pans, this);
1877                 }
1878 #endif /* CONTROLOUTS */
1879         }
1880
1881         catch (...) {
1882                 ArdourMessage msg (editor, X_("noport dialog"),
1883                                    _("There are insufficient JACK ports available\n\
1884 to create a new track or bus.\n\
1885 You should save Ardour, exit and\n\
1886 restart JACK with more ports."));
1887         }
1888 }
1889
1890 void
1891 ARDOUR_UI::diskstream_added (DiskStream* ds)
1892 {
1893 }
1894
1895 void
1896 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1897 {
1898         jack_nframes_t _preroll;
1899
1900         if (session) {
1901                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1902
1903                 if (new_position > _preroll) {
1904                         new_position -= _preroll;
1905                 } else {
1906                         new_position = 0;
1907                 }
1908
1909                 session->request_locate (new_position);
1910         }
1911 }
1912
1913 void
1914 ARDOUR_UI::transport_goto_start ()
1915 {
1916         if (session) {
1917                 session->request_locate (0);
1918
1919                 
1920                 /* force displayed area in editor to start no matter
1921                    what "follow playhead" setting is.
1922                 */
1923                 
1924                 if (editor) {
1925                         editor->reposition_x_origin (0);
1926                 }
1927         }
1928 }
1929
1930 void
1931 ARDOUR_UI::transport_goto_end ()
1932 {
1933         if (session) {
1934                 jack_nframes_t frame = session->current_end_frame();
1935                 session->request_locate (frame);
1936
1937                 /* force displayed area in editor to start no matter
1938                    what "follow playhead" setting is.
1939                 */
1940                 
1941                 if (editor) {
1942                         editor->reposition_x_origin (frame);
1943                 }
1944         }
1945 }
1946
1947 void
1948 ARDOUR_UI::transport_stop ()
1949 {
1950         if (!session) {
1951                 return;
1952         }
1953
1954         if (session->is_auditioning()) {
1955                 session->cancel_audition ();
1956                 return;
1957         }
1958         
1959         if (session->get_auto_loop()) {
1960                 session->request_auto_loop (false);
1961         }
1962         
1963         session->request_stop ();
1964 }
1965
1966 void
1967 ARDOUR_UI::transport_stop_and_forget_capture ()
1968 {
1969         if (session) {
1970                 session->request_stop (true);
1971         }
1972 }
1973
1974 void
1975 ARDOUR_UI::remove_last_capture()
1976 {
1977         if (editor) {
1978                 editor->remove_last_capture();
1979         }
1980 }
1981
1982 void
1983 ARDOUR_UI::transport_record ()
1984 {
1985         if (session) {
1986                 switch (session->record_status()) {
1987                 case Session::Disabled:
1988                         if (session->ntracks() == 0) {
1989                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1990                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1991                                 return;
1992                         }
1993                         session->maybe_enable_record ();
1994                         break;
1995                 case Session::Recording:
1996                 case Session::Enabled:
1997                         session->disable_record ();
1998                 }
1999         }
2000 }
2001
2002 void
2003 ARDOUR_UI::transport_roll ()
2004 {
2005         bool rolling;
2006
2007         if (!session) {
2008                 return;
2009         }
2010
2011         rolling = session->transport_rolling ();
2012
2013         if (session->get_auto_loop()) {
2014                 session->request_auto_loop (false);
2015                 auto_loop_button.set_active (false);
2016                 roll_button.set_active (true);
2017         } else if (session->get_play_range ()) {
2018                 session->request_play_range (false);
2019                 play_selection_button.set_active (false);
2020         } else if (rolling) {
2021                 session->request_locate (session->last_transport_start(), true);
2022         }
2023
2024         session->request_transport_speed (1.0f);
2025 }
2026
2027 void
2028 ARDOUR_UI::transport_loop()
2029 {
2030         if (session) {
2031                 if (session->get_auto_loop()) {
2032                         if (session->transport_rolling()) {
2033                                 Location * looploc = session->locations()->auto_loop_location();
2034                                 if (looploc) {
2035                                         session->request_locate (looploc->start(), true);
2036                                 }
2037                         }
2038                 }
2039                 else {
2040                         session->request_auto_loop (true);
2041                 }
2042         }
2043 }
2044
2045 void
2046 ARDOUR_UI::transport_play_selection ()
2047 {
2048         if (!session) {
2049                 return;
2050         }
2051
2052         if (!session->get_play_range()) {
2053                 session->request_stop ();
2054         }
2055
2056         editor->play_selection ();
2057 }
2058
2059 void
2060 ARDOUR_UI::transport_rewind (int option)
2061 {
2062         float current_transport_speed;
2063  
2064         if (session) {
2065                 current_transport_speed = session->transport_speed();
2066                 
2067                 if (current_transport_speed >= 0.0f) {
2068                         switch (option) {
2069                         case 0:
2070                                 session->request_transport_speed (-1.0f);
2071                                 break;
2072                         case 1:
2073                                 session->request_transport_speed (-4.0f);
2074                                 break;
2075                         case -1:
2076                                 session->request_transport_speed (-0.5f);
2077                                 break;
2078                         }
2079                 } else {
2080                         /* speed up */
2081                         session->request_transport_speed (current_transport_speed * 1.5f);
2082                 }
2083         }
2084 }
2085
2086 void
2087 ARDOUR_UI::transport_forward (int option)
2088 {
2089         float current_transport_speed;
2090         
2091         if (session) {
2092                 current_transport_speed = session->transport_speed();
2093                 
2094                 if (current_transport_speed <= 0.0f) {
2095                         switch (option) {
2096                         case 0:
2097                                 session->request_transport_speed (1.0f);
2098                                 break;
2099                         case 1:
2100                                 session->request_transport_speed (4.0f);
2101                                 break;
2102                         case -1:
2103                                 session->request_transport_speed (0.5f);
2104                                 break;
2105                         }
2106                 } else {
2107                         /* speed up */
2108                         session->request_transport_speed (current_transport_speed * 1.5f);
2109                 }
2110         }
2111 }
2112
2113 void
2114 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2115 {
2116         if (session == 0) {
2117                 return;
2118         }
2119
2120         DiskStream *ds;
2121
2122         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2123                 Port *port = ds->io()->input (0);
2124                 port->request_monitor_input (!port->monitoring_input());
2125         }
2126 }
2127
2128 void
2129 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2130 {
2131         if (session == 0) {
2132                 return;
2133         }
2134
2135         DiskStream *ds;
2136
2137         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2138                 ds->set_record_enabled (!ds->record_enabled(), this);
2139         }
2140 }
2141
2142 void
2143 ARDOUR_UI::queue_transport_change ()
2144 {
2145         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2146 }
2147
2148 void
2149 ARDOUR_UI::map_transport_state ()
2150 {
2151         float sp = session->transport_speed();
2152
2153         if (sp == 1.0f) {
2154                 transport_rolling ();
2155         } else if (sp < 0.0f) {
2156                 transport_rewinding ();
2157         } else if (sp > 0.0f) {
2158                 transport_forwarding ();
2159         } else {
2160                 transport_stopped ();
2161         }
2162 }
2163
2164 void
2165 ARDOUR_UI::send_all_midi_feedback ()
2166 {
2167         if (session) {
2168                 session->send_all_midi_feedback();
2169         }
2170 }
2171
2172 void
2173 ARDOUR_UI::allow_local_only ()
2174 {
2175
2176 }
2177
2178 void
2179 ARDOUR_UI::allow_mmc_only ()
2180 {
2181
2182 }
2183
2184 void
2185 ARDOUR_UI::allow_mmc_and_local ()
2186 {
2187
2188 }
2189
2190 void
2191 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2192 {
2193         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2194                 (int) adj.get_value()].c_str());
2195 }
2196
2197 void
2198 ARDOUR_UI::engine_stopped ()
2199 {
2200         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2201         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2202         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2203 }
2204
2205
2206 void
2207 ARDOUR_UI::engine_running ()
2208 {
2209         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2210         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2211         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2212 }
2213
2214 void
2215 ARDOUR_UI::engine_halted ()
2216 {
2217         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2218
2219         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2220         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2221
2222         update_sample_rate (0);
2223
2224         ArdourMessage msg (editor, X_("halted"),
2225                            _("\
2226 JACK has either been shutdown or it\n\
2227 disconnected Ardour because Ardour\n\
2228 was not fast enough. You can save the\n\
2229 session and/or try to reconnect to JACK ."));
2230 }
2231
2232 int32_t
2233 ARDOUR_UI::do_engine_start ()
2234 {
2235         try { 
2236                 engine->start();
2237         }
2238
2239         catch (AudioEngine::PortRegistrationFailure& err) {
2240                 engine->stop ();
2241                 error << _("Unable to create all required ports")
2242                       << endmsg;
2243                 unload_session ();
2244                 return -1;
2245         }
2246
2247         catch (...) {
2248                 engine->stop ();
2249                 error << _("Unable to start the session running")
2250                       << endmsg;
2251                 unload_session ();
2252                 return -2;
2253         }
2254         
2255         return 0;
2256 }
2257
2258 gint
2259 ARDOUR_UI::start_engine ()
2260 {
2261         if (do_engine_start () == 0) {
2262                 if (session && _session_is_new) {
2263                         /* we need to retain initial visual 
2264                            settings for a new session 
2265                         */
2266                         session->save_state ("");
2267                 }
2268
2269                 /* there is too much going on, in too many threads, for us to 
2270                    end up with a clean session. So wait 1 second after loading,
2271                    and fix it up. its ugly, but until i come across a better
2272                    solution, its what we have.
2273                 */
2274
2275                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2276         }
2277
2278         return FALSE;
2279 }
2280
2281 void
2282 ARDOUR_UI::update_clocks ()
2283 {
2284          Clock (session->audible_frame()); /* EMIT_SIGNAL */
2285 }
2286
2287 void
2288 ARDOUR_UI::start_clocking ()
2289 {
2290         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2291 }
2292
2293 void
2294 ARDOUR_UI::stop_clocking ()
2295 {
2296         clock_signal_connection.disconnect ();
2297 }
2298         
2299 void
2300 ARDOUR_UI::toggle_clocking ()
2301 {
2302 #if 0
2303         if (clock_button.get_active()) {
2304                 start_clocking ();
2305         } else {
2306                 stop_clocking ();
2307         }
2308 #endif
2309 }
2310
2311 gint
2312 ARDOUR_UI::_blink (void *arg)
2313
2314 {
2315         ((ARDOUR_UI *) arg)->blink ();
2316         return TRUE;
2317 }
2318
2319 void
2320 ARDOUR_UI::blink ()
2321 {
2322          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2323 }
2324
2325 void
2326 ARDOUR_UI::start_blinking ()
2327 {
2328         /* Start the blink signal. Everybody with a blinking widget
2329            uses Blink to drive the widget's state.
2330         */
2331
2332         if (blink_timeout_tag < 0) {
2333                 blink_on = false;       
2334                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2335         }
2336 }
2337
2338 void
2339 ARDOUR_UI::stop_blinking ()
2340 {
2341         if (blink_timeout_tag >= 0) {
2342                 gtk_timeout_remove (blink_timeout_tag);
2343                 blink_timeout_tag = -1;
2344         }
2345 }
2346
2347
2348 void
2349 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2350 {
2351         using namespace Gtk;
2352         using namespace Menu_Helpers;
2353
2354         if (dstream.hidden()) {
2355                 return;
2356         }
2357
2358         MenuList& items = diskstream_menu->items();
2359         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2360 }
2361         
2362 void
2363 ARDOUR_UI::diskstream_selected (gint32 id)
2364 {
2365         selected_dstream = id;
2366         Main::quit ();
2367 }
2368
2369 gint32
2370 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2371 {
2372         using namespace Gtk;
2373         using namespace Menu_Helpers;
2374
2375         if (session == 0) {
2376                 return -1;
2377         }
2378
2379         diskstream_menu = new Menu();
2380         diskstream_menu->set_name ("ArdourContextMenu");
2381         using namespace Gtk;
2382         using namespace Menu_Helpers;
2383
2384         MenuList& items = diskstream_menu->items();
2385         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2386
2387         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2388
2389         if (ev) {
2390                 diskstream_menu->popup (ev->button, ev->time);
2391         } else {
2392                 diskstream_menu->popup (0, 0);
2393         }
2394
2395         selected_dstream = -1;
2396
2397         Main::run ();
2398
2399         delete diskstream_menu;
2400
2401         return selected_dstream;
2402 }
2403
2404 void
2405 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
2406                           string& buf,
2407                           IO& io,
2408                           bool in)
2409 {
2410         if (in) {
2411                 if (io.n_inputs() == 0) {
2412                         buf = _("none");
2413                         return;
2414                 }
2415                 
2416                 /* XXX we're not handling multiple ports yet. */
2417
2418                 const char **connections = io.input(0)->get_connections();
2419                 
2420                 if (connections == 0 || connections[0] == '\0') {
2421                         buf = _("off");
2422                 } else {
2423                         buf = connections[0];
2424                 }
2425
2426                 free (connections);
2427
2428         } else {
2429
2430                 if (io.n_outputs() == 0) {
2431                         buf = _("none");
2432                         return;
2433                 }
2434                 
2435                 /* XXX we're not handling multiple ports yet. */
2436
2437                 const char **connections = io.output(0)->get_connections();
2438                 
2439                 if (connections == 0 || connections[0] == '\0') {
2440                         buf = _("off");
2441                 } else {
2442                         buf = connections[0];
2443                 }
2444
2445                 free (connections);
2446         }
2447 }
2448
2449 void
2450 ARDOUR_UI::snapshot_session ()
2451 {
2452         ArdourPrompter prompter (true);
2453         string snapname;
2454         string now;
2455         time_t n;
2456
2457         time (&n);
2458         now = ctime (&n);
2459         now = now.substr (0, now.length() - 1);
2460
2461         prompter.set_name ("Prompter");
2462         prompter.set_prompt (_("Name for snapshot"));
2463         prompter.set_initial_text (now);
2464         
2465         switch (prompter.run()) {
2466         case RESPONSE_ACCEPT:
2467                 prompter.get_result (snapname);
2468                 if (snapname.length()){
2469                         save_state (snapname);
2470                 }
2471                 break;
2472
2473         default:
2474                 break;
2475         }
2476 }
2477
2478 void
2479 ARDOUR_UI::save_state (string name)
2480 {
2481         (void) save_state_canfail (name);
2482 }
2483                 
2484 int
2485 ARDOUR_UI::save_state_canfail (string name)
2486 {
2487         if (session) {
2488                 int ret;
2489
2490                 if (name.length() == 0) {
2491                         name = session->snap_name();
2492                 }
2493
2494                 if ((ret = session->save_state (name)) != 0) {
2495                         return ret;
2496                 }
2497         }
2498         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2499         return 0;
2500 }
2501
2502 void
2503 ARDOUR_UI::restore_state (string name)
2504 {
2505         if (session) {
2506                 if (name.length() == 0) {
2507                         name = session->name();
2508                 }
2509                 session->restore_state (name);
2510         }
2511 }
2512
2513 void
2514 ARDOUR_UI::primary_clock_value_changed ()
2515 {
2516         if (session) {
2517                 session->request_locate (primary_clock.current_time ());
2518         }
2519 }
2520
2521 void
2522 ARDOUR_UI::secondary_clock_value_changed ()
2523 {
2524         if (session) {
2525                 session->request_locate (secondary_clock.current_time ());
2526         }
2527 }
2528
2529 void
2530 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2531 {
2532         if (session && dstream && dstream->record_enabled()) {
2533
2534                 Session::RecordState rs;
2535                 
2536                 rs = session->record_status ();
2537
2538                 switch (rs) {
2539                 case Session::Disabled:
2540                 case Session::Enabled:
2541                         if (w->get_state() != STATE_SELECTED) {
2542                                 w->set_state (STATE_SELECTED);
2543                         }
2544                         break;
2545
2546                 case Session::Recording:
2547                         if (w->get_state() != STATE_ACTIVE) {
2548                                 w->set_state (STATE_ACTIVE);
2549                         }
2550                         break;
2551                 }
2552
2553         } else {
2554                 if (w->get_state() != STATE_NORMAL) {
2555                         w->set_state (STATE_NORMAL);
2556                 }
2557         }
2558 }
2559
2560 void
2561 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
2562 {
2563         if (session == 0) {
2564                 return;
2565         }
2566         
2567         switch (session->record_status()) {
2568         case Session::Enabled:
2569                 if (onoff) {
2570                         rec_button.set_state (STATE_ACTIVE);
2571                 } else {
2572                         rec_button.set_state (STATE_NORMAL);
2573                 }
2574                 break;
2575
2576         case Session::Recording:
2577                 rec_button.set_state (STATE_ACTIVE);
2578                 break;
2579
2580         default:
2581                 rec_button.set_active (false);
2582                 rec_button.set_state (STATE_NORMAL);
2583                 break;
2584         }
2585 }
2586
2587 gint
2588 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2589 {
2590         window->hide();
2591         Gtk::Main::quit ();
2592         return TRUE;
2593 }
2594
2595 void
2596 ARDOUR_UI::start_keyboard_prefix ()
2597 {
2598         keyboard->start_prefix();
2599 }
2600
2601 void
2602 ARDOUR_UI::save_template ()
2603
2604 {
2605         ArdourPrompter prompter (true);
2606         string name;
2607
2608         prompter.set_name (X_("Prompter"));
2609         prompter.set_prompt (_("Name for mix template:"));
2610         prompter.set_initial_text(session->name() + _("-template"));
2611         
2612         switch (prompter.run()) {
2613         case RESPONSE_ACCEPT:
2614                 prompter.get_result (name);
2615                 
2616                 if (name.length()) {
2617                         session->save_template (name);
2618                 }
2619                 break;
2620
2621         default:
2622                 break;
2623         }
2624 }
2625
2626 void
2627 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2628 {
2629         m_new_session_dialog->show_all();
2630         m_new_session_dialog->set_transient_for(*editor);
2631         m_new_session_dialog->set_name(predetermined_path);
2632
2633         int response = Gtk::RESPONSE_CANCEL;
2634
2635         do {
2636                 response = m_new_session_dialog->run ();
2637         
2638                 if(response == Gtk::RESPONSE_OK) {
2639
2640                         _session_is_new = true;
2641                         
2642                         std::string session_name = m_new_session_dialog->session_name();
2643                         std::string session_path = m_new_session_dialog->session_folder();
2644                         
2645                         /*
2646                           XXX This is needed because session constructor wants a 
2647                           non-existant path. hopefully this will be fixed at some point.
2648                         */
2649                         session_path = Glib::build_filename(session_path, session_name);
2650                         
2651                         std::string template_name = m_new_session_dialog->session_template_name();
2652                         
2653                         if (m_new_session_dialog->use_session_template()) {
2654                                 
2655                                 load_session (session_path, session_name, &template_name);
2656                                 
2657                         } else {
2658                                 
2659                                 uint32_t cchns;
2660                                 uint32_t mchns;
2661                                 Session::AutoConnectOption iconnect;
2662                                 Session::AutoConnectOption oconnect;
2663                                 
2664                                 if (m_new_session_dialog->create_control_bus()) {
2665                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2666                                 } else {
2667                                         cchns = 0;
2668                                 }
2669                                 
2670                                 if (m_new_session_dialog->create_master_bus()) {
2671                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2672                                 } else {
2673                                         mchns = 0;
2674                                 }
2675                                 
2676                                 if (m_new_session_dialog->connect_inputs()) {
2677                                         iconnect = Session::AutoConnectPhysical;
2678                                 } else {
2679                                         iconnect = Session::AutoConnectOption (0);
2680                                 }
2681                                 
2682                                 /// @todo some minor tweaks.
2683
2684                                 if (m_new_session_dialog->connect_outs_to_master()) {
2685                                         oconnect = Session::AutoConnectMaster;
2686                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2687                                         oconnect = Session::AutoConnectPhysical;
2688                                 } else {
2689                                         oconnect = Session::AutoConnectOption (0);
2690                                 } 
2691                                 
2692                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2693                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2694                                 
2695                                 build_session (session_path,
2696                                                session_name,
2697                                                cchns,
2698                                                mchns,
2699                                                iconnect,
2700                                                oconnect,
2701                                                nphysin,
2702                                                nphysout, 
2703                                                engine->frame_rate() * 60 * 5);
2704                         }               
2705                 }
2706
2707         } while(response == Gtk::RESPONSE_HELP);
2708         m_new_session_dialog->hide_all();
2709 }
2710
2711 int
2712 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2713 {
2714         Session *new_session;
2715         int x;
2716         session_loaded = false;
2717         x = unload_session ();
2718
2719         if (x < 0) {
2720                 return -1;
2721         } else if (x > 0) {
2722                 return 0;
2723         }
2724
2725         /* if it already exists, we must have write access */
2726
2727         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2728                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2729 You do not have write access to this session.\n\
2730 This prevents the session from being loaded."));
2731                 return -1;
2732         }
2733
2734         try {
2735                 new_session = new Session (*engine, path, snap_name, mix_template);
2736         }
2737
2738         catch (...) {
2739
2740                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2741                 return -1;
2742         }
2743
2744         connect_to_session (new_session);
2745
2746         //if (engine->running()) {
2747         //mixer->show_window();
2748         //}
2749         session_loaded = true;
2750         return 0;
2751 }
2752
2753 int
2754 ARDOUR_UI::make_session_clean ()
2755 {
2756         if (session) {
2757                 session->set_clean ();
2758         }
2759
2760         return FALSE;
2761 }
2762
2763 int
2764 ARDOUR_UI::build_session (string path, string snap_name, 
2765                           uint32_t control_channels,
2766                           uint32_t master_channels, 
2767                           Session::AutoConnectOption input_connect,
2768                           Session::AutoConnectOption output_connect,
2769                           uint32_t nphysin,
2770                           uint32_t nphysout,
2771                           jack_nframes_t initial_length)
2772 {
2773         Session *new_session;
2774         int x;
2775
2776         session_loaded = false;
2777         x = unload_session ();
2778         if (x < 0) {
2779                 return -1;
2780         } else if (x > 0) {
2781                 return 0;
2782         }
2783         
2784         _session_is_new = true;
2785
2786         try {
2787                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2788                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2789         }
2790
2791         catch (...) {
2792
2793                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2794                 return -1;
2795         }
2796
2797         connect_to_session (new_session);
2798
2799         //if (engine->running()) {
2800         //mixer->show_window();
2801         //}
2802         session_loaded = true;
2803         return 0;
2804 }
2805
2806 void
2807 ARDOUR_UI::show ()
2808 {
2809         if (editor) {
2810                 editor->show_window ();
2811                 shown_flag = true;
2812         }
2813
2814         if (session && mixer) {
2815                 // mixer->show_window ();
2816         }
2817         
2818         if (about) {
2819                 about->present ();
2820         }
2821 }
2822
2823 void
2824 ARDOUR_UI::show_splash ()
2825 {
2826         if (about == 0) {
2827                 about = new About();
2828         }
2829         about->present();
2830 }
2831
2832 void
2833 ARDOUR_UI::hide_splash ()
2834 {
2835         if (about) {
2836                 // about->hide();
2837         }
2838 }
2839
2840 void
2841 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2842 {
2843         size_t removed;
2844
2845         removed = rep.paths.size();
2846
2847         if (removed == 0) {
2848                 ArdourMessage msg (editor, X_("cleanupresults"),
2849                                    _("\
2850 No audio files were ready for cleanup\n\n\
2851 If this seems suprising, check for any existing\n\
2852 snapshots. These may still include regions that\n\
2853 require some unused files to continue to exist."));
2854                 return;
2855         } 
2856
2857         ArdourDialog results (_("ardour: cleanup"), true);
2858         
2859         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2860             CleanupResultsModelColumns() { 
2861                     add (visible_name);
2862                     add (fullpath);
2863             }
2864             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2865             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2866         };
2867
2868         
2869         Glib::RefPtr<Gtk::ListStore> results_model;
2870         CleanupResultsModelColumns results_columns;
2871         Gtk::TreeView results_display;
2872         
2873         results_model = ListStore::create (results_columns);
2874         results_display.set_model (results_model);
2875         results_display.append_column (list_title, results_columns.visible_name);
2876         results_display.set_headers_visible (true);
2877
2878         Gtk::ScrolledWindow list_scroller;
2879         Gtk::Label txt;
2880
2881         if (rep.space < 1048576.0f) {
2882                 if (removed > 1) {
2883                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2884                 } else {
2885                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2886                 }
2887         } else {
2888                 if (removed > 1) {
2889                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2890                 } else {
2891                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2892                 }
2893         }
2894
2895         results.get_vbox()->pack_start (txt, false, false);
2896         
2897         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2898                 TreeModel::Row row = *(results_model->append());
2899                 row[results_columns.visible_name] = *i;
2900                 row[results_columns.fullpath] = *i;
2901         }
2902         
2903         list_scroller.add (results_display);
2904         list_scroller.set_size_request (-1, 250);
2905         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2906         
2907         results.get_vbox()->pack_start (list_scroller, true, true);
2908         results.add_button (Stock::OK, RESPONSE_ACCEPT);
2909         results.set_position (Gtk::WIN_POS_MOUSE);
2910
2911         results.run ();
2912 }
2913
2914 void
2915 ARDOUR_UI::cleanup ()
2916 {
2917         if (session == 0) {
2918                 /* shouldn't happen: menu item is insensitive */
2919                 return;
2920         }
2921
2922         ArdourDialog checker (_("ardour cleanup"));
2923         Gtk::Label label (_("\
2924 Cleanup is a destructive operation.\n\
2925 ALL undo/redo information will be lost if you cleanup.\n\
2926 Unused audio files will be moved to a \"dead sounds\" location."));
2927         
2928         checker.get_vbox()->pack_start (label, false, false);
2929         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2930         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2931
2932         checker.set_name (_("CleanupDialog"));
2933         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2934         checker.set_position (Gtk::WIN_POS_MOUSE);
2935
2936         switch (checker.run()) {
2937         case RESPONSE_ACCEPT:
2938                 break;
2939         default:
2940                 return;
2941         }
2942
2943         Session::cleanup_report rep;
2944
2945         editor->prepare_for_cleanup ();
2946
2947         if (session->cleanup_sources (rep)) {
2948                 return;
2949         }
2950
2951         display_cleanup_results (rep, 
2952                                  _("cleaned files"),
2953                                  _("\
2954 The following %1 %2 were not in use.\n\
2955 The next time you flush the wastebasket\n\
2956 it will release an additional %3 %4bytes\n\
2957 of disk space"
2958                                          ));
2959 }
2960
2961 void
2962 ARDOUR_UI::flush_trash ()
2963 {
2964         if (session == 0) {
2965                 /* shouldn't happen: menu item is insensitive */
2966                 return;
2967         }
2968
2969         Session::cleanup_report rep;
2970
2971         if (session->cleanup_trash_sources (rep)) {
2972                 return;
2973         }
2974
2975         display_cleanup_results (rep, 
2976                                  _("deleted file"),
2977                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2978 }
2979
2980 void
2981 ARDOUR_UI::add_route ()
2982 {
2983         int count;
2984
2985         if (!session) {
2986                 return;
2987         }
2988
2989         if (add_route_dialog == 0) {
2990                 add_route_dialog = new AddRouteDialog;
2991                 editor->ensure_float (*add_route_dialog);
2992         }
2993
2994         if (add_route_dialog->is_visible()) {
2995                 /* we're already doing this */
2996                 return;
2997         }
2998
2999         ResponseType r = (ResponseType) add_route_dialog->run ();
3000         
3001         add_route_dialog->hide();
3002
3003         switch (r) {
3004         case RESPONSE_ACCEPT:
3005                 break;
3006         default:
3007                 return;
3008                 break;
3009         }
3010
3011         if ((count = add_route_dialog->count()) <= 0) {
3012                 return;
3013         }
3014
3015         uint32_t input_chan = add_route_dialog->channels ();
3016         uint32_t output_chan;
3017         string name_template = add_route_dialog->name_template ();
3018         bool track = add_route_dialog->track ();
3019
3020         Session::AutoConnectOption oac = session->get_output_auto_connect();
3021
3022         if (oac & Session::AutoConnectMaster) {
3023                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3024         } else {
3025                 output_chan = input_chan;
3026         }
3027
3028         /* XXX do something with name template */
3029
3030         while (count) {
3031                 if (track) {
3032                         session_add_audio_track (input_chan, output_chan);
3033                 } else {
3034                         session_add_audio_bus (input_chan, output_chan);
3035                 }
3036                 --count;
3037                 
3038                 while (Main::events_pending()) {
3039                         Main::iteration ();
3040                 }
3041         }
3042 }
3043
3044 XMLNode*
3045 ARDOUR_UI::mixer_settings () const
3046 {
3047         XMLNode* node = 0;
3048
3049         if (session) {
3050                 node = session->instant_xml(X_("Mixer"), session->path());
3051         } else {
3052                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3053         }
3054
3055         if (!node) {
3056                 node = new XMLNode (X_("Mixer"));
3057         }
3058
3059         return node;
3060 }
3061
3062 XMLNode*
3063 ARDOUR_UI::editor_settings () const
3064 {
3065         XMLNode* node = 0;
3066
3067         if (session) {
3068                 node = session->instant_xml(X_("Editor"), session->path());
3069         } else {
3070                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3071         }
3072
3073         if (!node) {
3074                 node = new XMLNode (X_("Editor"));
3075         }
3076         return node;
3077 }
3078
3079 XMLNode*
3080 ARDOUR_UI::keyboard_settings () const
3081 {
3082         XMLNode* node = 0;
3083
3084         node = Config->extra_xml(X_("Keyboard"));
3085         
3086         if (!node) {
3087                 node = new XMLNode (X_("Keyboard"));
3088         }
3089         return node;
3090 }
3091
3092 void
3093 ARDOUR_UI::halt_on_xrun_message ()
3094 {
3095         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3096
3097         ArdourMessage msg (editor, X_("haltonxrun"),
3098                            _("Recording was stopped because your system could not keep up."));
3099 }
3100
3101 void 
3102 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3103 {
3104         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3105
3106         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3107                 delete *i;
3108         }
3109
3110         delete deletion_list;
3111 }
3112
3113 void
3114 ARDOUR_UI::disk_overrun_handler ()
3115 {
3116         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3117
3118         if (!have_disk_overrun_displayed) {
3119                 have_disk_overrun_displayed = true;
3120                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3121 The disk system on your computer\n\
3122 was not able to keep up with Ardour.\n\
3123 \n\
3124 Specifically, it failed to write data to disk\n\
3125 quickly enough to keep up with recording.\n"));
3126                 have_disk_overrun_displayed = false;
3127         }
3128 }
3129
3130 void
3131 ARDOUR_UI::disk_underrun_handler ()
3132 {
3133         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3134
3135         if (!have_disk_underrun_displayed) {
3136                 have_disk_underrun_displayed = true;
3137                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3138                         (_("The disk system on your computer\n\
3139 was not able to keep up with Ardour.\n\
3140 \n\
3141 Specifically, it failed to read data from disk\n\
3142 quickly enough to keep up with playback.\n")));
3143                 have_disk_underrun_displayed = false;
3144         } 
3145 }
3146
3147 void
3148 ARDOUR_UI::disk_underrun_message_gone ()
3149 {
3150         have_disk_underrun_displayed = false;
3151 }
3152
3153 void
3154 ARDOUR_UI::disk_overrun_message_gone ()
3155 {
3156         have_disk_underrun_displayed = false;
3157 }
3158
3159 int
3160 ARDOUR_UI::pending_state_dialog ()
3161 {
3162         ArdourDialog dialog ("pending state dialog");
3163         Label  message (_("\
3164 This session appears to have been in\n\
3165 middle of recording when ardour or\n\
3166 the computer was shutdown.\n\
3167 \n\
3168 Ardour can recover any captured audio for\n\
3169 you, or it can ignore it. Please decide\n\
3170 what you would like to do.\n"));
3171
3172         dialog.get_vbox()->pack_start (message);
3173         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3174         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3175
3176         dialog.set_position (WIN_POS_CENTER);
3177         dialog.show_all ();
3178         
3179         switch (dialog.run ()) {
3180         case RESPONSE_ACCEPT:
3181                 break;
3182         default:
3183                 return 1;
3184         }
3185
3186         return 0;
3187 }
3188         
3189         
3190 void
3191 ARDOUR_UI::disconnect_from_jack ()
3192 {
3193         if (engine) {
3194                 if( engine->disconnect_from_jack ()) {
3195                         ArdourMessage msg (editor, X_("nojack dialog"),
3196                                            _("Could not disconnect from JACK"));
3197                 }
3198
3199                 update_sample_rate (0);
3200         }
3201 }
3202
3203 void
3204 ARDOUR_UI::reconnect_to_jack ()
3205 {
3206         if (engine) {
3207                 if (engine->reconnect_to_jack ()) {
3208                         ArdourMessage msg (editor, X_("nojack dialog"),
3209                                            _("Could not reconnect to JACK"));
3210                 }
3211
3212                 update_sample_rate (0);
3213         }
3214 }
3215
3216 void
3217 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3218 {
3219         engine->request_buffer_size (nframes);
3220         update_sample_rate (0);
3221 }
3222
3223 int
3224 ARDOUR_UI::cmdline_new_session (string path)
3225 {
3226         if (path[0] != '/') {
3227                 char buf[PATH_MAX+1];
3228                 string str;
3229
3230                 getcwd (buf, sizeof (buf));
3231                 str = buf;
3232                 str += '/';
3233                 str += path;
3234                 path = str;
3235         }
3236
3237         new_session (false, path);
3238
3239         _will_create_new_session_automatically = false; /* done it */
3240         return FALSE; /* don't call it again */
3241 }