fa4517aff4ceb7b87f3986421a448a1e782e2ab3
[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         sfdb = 0;
857         open_session_selector = 0;
858         have_configure_timeout = false;
859         have_disk_overrun_displayed = false;
860         have_disk_underrun_displayed = false;
861         _will_create_new_session_automatically = false;
862         session_loaded = false;
863
864
865         last_configure_time.tv_sec = 0;
866         last_configure_time.tv_usec = 0;
867
868         shuttle_grabbed = false;
869         shuttle_fract = 0.0;
870
871         set_shuttle_units (Percentage);
872         set_shuttle_behaviour (Sprung);
873
874         shuttle_style_menu = 0;
875         shuttle_unit_menu = 0;
876
877         gettimeofday (&last_peak_grab, 0);
878         gettimeofday (&last_shuttle_request, 0);
879
880         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
881         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
882         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
883         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
884
885         /* handle pending state with a dialog */
886
887         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
888
889         channel_combo_strings = internationalize (channel_setup_names);
890         
891         /* have to wait for AudioEngine and Configuration before proceeding */
892 }
893
894 void
895 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
896 {
897         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
898         
899         string msg = string_compose (_("\
900 You cannot record-enable\n\
901 track %1\n\
902 because it has no input connections.\n\
903 You would be wasting space recording silence."),
904                               ds->name());
905
906         ArdourMessage message (editor, X_("cannotrecord"), msg);
907 }
908
909 void
910 ARDOUR_UI::set_engine (AudioEngine& e)
911 {
912         engine = &e;
913
914         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
915         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
916         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
917         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
918
919         _tooltips.enable();
920
921         keyboard = new Keyboard;
922         install_keybindings ();
923
924         FastMeter::set_vertical_xpm (v_meter_strip_xpm);
925         FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
926
927         if (setup_windows ()) {
928                 throw failed_constructor ();
929         }
930
931         if (GTK_ARDOUR::show_key_actions) {
932                 vector<string> names;
933                 vector<string> paths;
934                 vector<string> keys;
935                 vector<AccelKey> bindings;
936
937                 ActionManager::get_all_actions (names, paths, keys, bindings);
938
939                 vector<string>::iterator n;
940                 vector<string>::iterator k;
941                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
942                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
943                 }
944
945                 exit (0);
946         }
947
948         /* start with timecode, metering enabled
949         */
950         
951         blink_timeout_tag = -1;
952
953         /* this being a GUI and all, we want peakfiles */
954
955         FileSource::set_build_peakfiles (true);
956         FileSource::set_build_missing_peakfiles (true);
957
958         if (Source::start_peak_thread ()) {
959                 throw failed_constructor();
960         }
961
962         /* start the time-of-day-clock */
963         
964         update_wall_clock ();
965         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
966
967         update_disk_space ();
968         update_cpu_load ();
969         update_sample_rate (engine->frame_rate());
970
971         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
972         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
973 }
974
975 ARDOUR_UI::~ARDOUR_UI ()
976 {
977         save_ardour_state ();
978
979         if (keyboard) {
980                 delete keyboard;
981         }
982
983         if (editor) {
984                 delete editor;
985         }
986
987         if (mixer) {
988                 delete mixer;
989         }
990
991         if (add_route_dialog) {
992                 delete add_route_dialog;
993         }
994
995         Source::stop_peak_thread ();
996 }
997
998 gint
999 ARDOUR_UI::configure_timeout ()
1000 {
1001         struct timeval now;
1002         struct timeval diff;
1003
1004         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
1005                 /* no configure events yet */
1006                 return TRUE;
1007         }
1008
1009         gettimeofday (&now, 0);
1010         timersub (&now, &last_configure_time, &diff);
1011
1012         /* force a gap of 0.5 seconds since the last configure event
1013          */
1014
1015         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1016                 return TRUE;
1017         } else {
1018                 have_configure_timeout = false;
1019                 save_ardour_state ();
1020                 return FALSE;
1021         }
1022 }
1023
1024 gboolean
1025 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1026 {
1027         if (have_configure_timeout) {
1028                 gettimeofday (&last_configure_time, 0);
1029         } else {
1030                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1031                 have_configure_timeout = true;
1032         }
1033                 
1034         return FALSE;
1035 }
1036
1037 void
1038 ARDOUR_UI::save_ardour_state ()
1039 {
1040         if (!keyboard || !mixer || !editor) {
1041                 return;
1042         }
1043         
1044         /* XXX this is all a bit dubious. add_extra_xml() uses
1045            a different lifetime model from add_instant_xml().
1046         */
1047
1048         XMLNode* node = new XMLNode (keyboard->get_state());
1049         Config->add_extra_xml (*node);
1050         Config->save_state();
1051
1052         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1053         XMLNode& mnode (mixer->get_state());
1054
1055         if (session) {
1056                 session->add_instant_xml(enode, session->path());
1057                 session->add_instant_xml(mnode, session->path());
1058         } else {
1059                 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1060                 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1061         }
1062 }
1063
1064 void
1065 ARDOUR_UI::startup ()
1066 {
1067         /* Once the UI is up and running, start the audio engine. Doing
1068            this before the UI is up and running can cause problems
1069            when not running with SCHED_FIFO, because the amount of
1070            CPU and disk work needed to get the UI started can interfere
1071            with the scheduling of the audio thread.
1072         */
1073
1074         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1075 }
1076
1077 void
1078 ARDOUR_UI::finish()
1079 {
1080         if (session && session->dirty()) {
1081                 switch (ask_about_saving_session(_("quit"))) {
1082                 case -1:
1083                         return;
1084                         break;
1085                 case 1:
1086                         /* use the default name */
1087                         if (save_state_canfail ("")) {
1088                                 /* failed - don't quit */
1089                                 ArdourMessage (editor, X_("badsave dialog"),
1090                                                _("\
1091 Ardour was unable to save your session.\n\n\
1092 If you still wish to quit, please use the\n\n\
1093 \"Just quit\" option."));
1094                                 return;
1095                         }
1096                         break;
1097                 case 0:
1098                         break;
1099                 }
1100         }
1101
1102         quit ();
1103 }
1104
1105 int
1106 ARDOUR_UI::ask_about_saving_session (string what)
1107 {
1108         ArdourDialog window (_("ardour: save session?"));
1109         Gtk::Label  prompt_label;
1110         string msg;
1111
1112         msg = string_compose(_("Save and %1"), what);
1113         window.add_button (msg, RESPONSE_ACCEPT);
1114         msg = string_compose(_("Just %1"), what);
1115         window.add_button (msg, RESPONSE_APPLY);
1116         msg = string_compose(_("Don't %1"), what);
1117         window.add_button (msg, RESPONSE_REJECT);
1118
1119         Gtk::Button noquit_button (msg);
1120         noquit_button.set_name ("EditorGTKButton");
1121
1122         string prompt;
1123         string type;
1124
1125         if (session->snap_name() == session->name()) {
1126                 type = _("session");
1127         } else {
1128                 type = _("snapshot");
1129         }
1130         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?"), 
1131                          type, session->snap_name());
1132         
1133         prompt_label.set_text (prompt);
1134         prompt_label.set_alignment (0.5, 0.5);
1135         prompt_label.set_name (X_("PrompterLabel"));
1136         
1137         window.get_vbox()->pack_start (prompt_label);
1138
1139         window.set_name (_("Prompter"));
1140         window.set_position (Gtk::WIN_POS_MOUSE);
1141         window.set_modal (true);
1142         window.show_all ();
1143
1144         save_the_session = 0;
1145
1146         editor->ensure_float (window);
1147
1148         ResponseType r = (ResponseType) window.run();
1149
1150         window.hide ();
1151
1152         switch (r) {
1153         case RESPONSE_ACCEPT: // save and get out of here
1154                 return 1;
1155         case RESPONSE_APPLY:  // get out of here
1156                 return 0;
1157         default:
1158                 break;
1159         }
1160
1161         return -1;
1162 }
1163         
1164 gint
1165 ARDOUR_UI::every_second ()
1166 {
1167         update_cpu_load ();
1168         update_buffer_load ();
1169         update_disk_space ();
1170         // update_disk_rate ();
1171         return TRUE;
1172 }
1173
1174 gint
1175 ARDOUR_UI::every_point_one_seconds ()
1176 {
1177         struct timeval now;
1178         struct timeval diff;
1179         
1180         /* do not attempt to grab peak power more than once per cycle.
1181          */
1182
1183         gettimeofday (&now, 0);
1184         timersub (&now, &last_peak_grab, &diff);
1185
1186         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1187                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1188                 last_peak_grab = now;
1189         } 
1190
1191         update_speed_display ();
1192         RapidScreenUpdate(); /* EMIT_SIGNAL */
1193         return TRUE;
1194 }
1195
1196 gint
1197 ARDOUR_UI::every_point_zero_one_seconds ()
1198 {
1199         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1200         return TRUE;
1201 }
1202
1203 void
1204 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1205 {
1206         char buf[32];
1207
1208         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1209
1210         if (!engine->connected()) {
1211
1212                 snprintf (buf, sizeof (buf), _("disconnected"));
1213
1214         } else {
1215
1216                 jack_nframes_t rate = engine->frame_rate();
1217                 
1218                 if (fmod (rate, 1000.0) != 0.0) {
1219                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
1220                                   (float) rate/1000.0f,
1221                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1222                 } else {
1223                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
1224                                   rate/1000,
1225                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1226                 }
1227         }
1228
1229         sample_rate_label.set_text (buf);
1230 }
1231
1232 void
1233 ARDOUR_UI::update_cpu_load ()
1234 {
1235         char buf[32];
1236         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1237         cpu_load_label.set_text (buf);
1238 }
1239
1240 void
1241 ARDOUR_UI::update_disk_rate ()
1242 {
1243         char buf[64];
1244
1245         if (session) {
1246                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
1247                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1248                 disk_rate_label.set_text (buf);
1249         } else {
1250                 disk_rate_label.set_text ("");
1251         }
1252 }
1253
1254 void
1255 ARDOUR_UI::update_buffer_load ()
1256 {
1257         char buf[64];
1258
1259         if (session) {
1260                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
1261                           session->playback_load(), session->capture_load());
1262                 buffer_load_label.set_text (buf);
1263         } else {
1264                 buffer_load_label.set_text ("");
1265         }
1266 }
1267
1268 void
1269 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1270 {
1271         if (ds.record_enabled()) {
1272                 rec_enabled_diskstreams++;
1273         }
1274 }
1275
1276 void
1277 ARDOUR_UI::update_disk_space()
1278 {
1279         if (session == 0) {
1280                 return;
1281         }
1282
1283         jack_nframes_t frames = session->available_capture_duration();
1284         char buf[64];
1285
1286         if (frames == max_frames) {
1287                 strcpy (buf, _("space: 24hrs+"));
1288         } else {
1289                 int hrs;
1290                 int mins;
1291                 int secs;
1292                 jack_nframes_t fr = session->frame_rate();
1293                 
1294                 if (session->actively_recording()){
1295                         
1296                         rec_enabled_diskstreams = 0;
1297                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1298                         
1299                         if (rec_enabled_diskstreams) {
1300                                 frames /= rec_enabled_diskstreams;
1301                         }
1302                         
1303                 } else {
1304                         
1305                         /* hmmm. shall we divide by the route count? or the diskstream count?
1306                            or what? for now, do nothing ...
1307                         */
1308                         
1309                 }
1310                 
1311                 hrs  = frames / (fr * 3600);
1312                 frames -= hrs * fr * 3600;
1313                 mins = frames / (fr * 60);
1314                 frames -= mins * fr * 60;
1315                 secs = frames / fr;
1316                 
1317                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1318         }
1319
1320         disk_space_label.set_text (buf);
1321 }                 
1322
1323 gint
1324 ARDOUR_UI::update_wall_clock ()
1325 {
1326         time_t now;
1327         struct tm *tm_now;
1328         char buf[16];
1329
1330         time (&now);
1331         tm_now = localtime (&now);
1332
1333         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1334         wall_clock_label.set_text (buf);
1335
1336         return TRUE;
1337 }
1338
1339 void
1340 ARDOUR_UI::toggle_recording_plugins ()
1341 {
1342         /* XXX use toggle_some_session_state */
1343
1344         if (session == 0) {
1345                 return;
1346         }
1347
1348         session->set_recording_plugins (!session->get_recording_plugins());
1349 }
1350         
1351 void
1352 ARDOUR_UI::toggle_auto_play ()
1353
1354 {
1355         toggle_some_session_state (auto_play_button,
1356                                    &Session::get_auto_play,
1357                                    &Session::set_auto_play);
1358 }
1359
1360 void
1361 ARDOUR_UI::toggle_auto_return ()
1362
1363 {
1364         toggle_some_session_state (auto_return_button,
1365                                    &Session::get_auto_return,
1366                                    &Session::set_auto_return);
1367 }
1368
1369 void
1370 ARDOUR_UI::toggle_click ()
1371 {
1372         toggle_some_session_state (click_button,
1373                                    &Session::get_clicking,
1374                                    &Session::set_clicking);
1375 }
1376
1377 void
1378 ARDOUR_UI::follow_changed ()
1379 {
1380         bool x;
1381
1382         if (!editor) {
1383                 return;
1384         }
1385
1386         if (follow_button.get_active() != (x = editor->follow_playhead())) {
1387                 follow_button.set_active (x);
1388         }
1389 }
1390
1391 void
1392 ARDOUR_UI::toggle_follow ()
1393 {
1394         bool x;
1395
1396         if (!editor) {
1397                 return;
1398         }
1399
1400         if (editor->follow_playhead() != (x = follow_button.get_active())) {
1401                 editor->set_follow_playhead (x);
1402         }
1403 }
1404
1405 void
1406 ARDOUR_UI::toggle_session_auto_loop ()
1407 {
1408         if (session) {
1409                 if (session->get_auto_loop()) {
1410                         if (session->transport_rolling()) {
1411                                 transport_roll();
1412                         }
1413                         else {
1414                                 session->request_auto_loop (false);
1415                         }
1416                 }
1417                 else {
1418                         session->request_auto_loop (true);
1419                 }
1420         }
1421 }
1422
1423 void
1424 ARDOUR_UI::toggle_session_punch_in ()
1425 {
1426         if (session) {
1427                 session->set_punch_in (!session->get_punch_in());
1428         }
1429 }
1430
1431 void
1432 ARDOUR_UI::toggle_punch_out ()
1433 {
1434         toggle_some_session_state (punch_out_button,
1435                                    &Session::get_punch_out,
1436                                    &Session::set_punch_out);
1437 }
1438
1439 void
1440 ARDOUR_UI::toggle_punch_in ()
1441 {
1442         toggle_some_session_state (punch_in_button,
1443                                    &Session::get_punch_in,
1444                                    &Session::set_punch_in);
1445 }
1446
1447 void
1448 ARDOUR_UI::map_button_state ()
1449
1450 {
1451         map_some_session_state (auto_return_button,
1452                                 &Session::get_auto_return);
1453         map_some_session_state (auto_play_button,
1454                                 &Session::get_auto_play);
1455         map_some_session_state (auto_input_button,
1456                                 &Session::get_auto_input);
1457         map_some_session_state (punch_in_button,
1458                                 &Session::get_punch_in);
1459         map_some_session_state (punch_out_button,
1460                                 &Session::get_punch_out);
1461         map_some_session_state (click_button,
1462                                 &Session::get_clicking);
1463 }
1464
1465 void
1466 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1467 {
1468         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1469 }
1470
1471 void
1472 ARDOUR_UI::map_control_change (Session::ControlType t)
1473 {
1474         switch (t) {
1475         case Session::AutoPlay:
1476                 map_some_session_state (auto_play_button, &Session::get_auto_play);
1477                 break;
1478
1479         case Session::AutoLoop:
1480                 break;
1481
1482         case Session::AutoReturn:
1483                 map_some_session_state (auto_return_button, &Session::get_auto_return);
1484                 break;
1485
1486         case Session::AutoInput:
1487                 map_some_session_state (auto_input_button, &Session::get_auto_input);
1488                 break;
1489
1490         case Session::PunchOut:
1491                 map_some_session_state (punch_in_button, &Session::get_punch_out);
1492                 break;
1493
1494         case Session::PunchIn:
1495                 map_some_session_state (punch_in_button, &Session::get_punch_in);
1496                 break;
1497
1498         case Session::Clicking:
1499                 map_some_session_state (click_button, &Session::get_clicking);
1500                 break;
1501
1502         case Session::SlaveType:
1503 //              map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1504                 break;
1505
1506         case Session::SendMTC:
1507 //              map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1508                 break;
1509
1510         case Session::SendMMC:
1511 //              map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1512                 break;
1513
1514         case Session::MMCControl:       
1515 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1516                 break;
1517
1518         case Session::MidiFeedback:       
1519 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1520                 break;
1521         case Session::MidiControl:       
1522 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1523                 break;
1524                 
1525         case Session::Live:
1526                 break;
1527
1528         case Session::RecordingPlugins:
1529                 break;
1530
1531         case Session::CrossFadesActive:
1532                 break;
1533                 
1534         case Session::EditingMode:
1535                 break;
1536
1537         case Session::PlayRange:
1538                 break;
1539
1540         case Session::AlignChoice:
1541                 /* don't care, this is handled by the options editor */
1542                 break;
1543         case Session::SeamlessLoop:
1544                 /* don't care, this is handled by the options editor */
1545                 break;
1546                
1547         }
1548 }
1549
1550 void
1551 ARDOUR_UI::control_methods_adjusted ()
1552
1553 {
1554         int which_method;
1555
1556         which_method = (int) online_control_button->adjustment.get_value();
1557         switch (which_method) {
1558         case 0:
1559                 allow_mmc_and_local ();
1560                 break;
1561         case 1:
1562                 allow_mmc_only ();
1563                 break;
1564         case 2:
1565                 allow_local_only ();
1566                 break;
1567         default:
1568                 fatal << _("programming error: impossible control method") << endmsg;
1569         }
1570 }
1571         
1572
1573 void
1574 ARDOUR_UI::mmc_device_id_adjusted ()
1575
1576 {
1577 #if 0
1578         if (mmc) {
1579                 int dev_id = (int) mmc_id_button->adjustment.get_value();
1580                 mmc->set_device_id (dev_id);
1581         }
1582 #endif
1583 }
1584
1585 void
1586 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1587                                    bool (Session::*get)() const)
1588         
1589 {
1590         bool x;
1591
1592         if (session == 0) {
1593                 return;
1594         }
1595         
1596         if (button.get_active() != (x = (session->*get)())) {
1597                 button.set_active (x);
1598         }
1599 }
1600
1601 void
1602 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1603                                       bool (Session::*get)() const,
1604                                       void (Session::*set)(bool))
1605
1606 {
1607         bool button_state;
1608         bool session_state;
1609
1610         if (session == 0) {
1611                 return;
1612         }
1613
1614         button_state = button.get_active ();
1615         session_state = (session->*get)();
1616
1617         if (button_state != session_state) {
1618                 (session->*set) (button_state);
1619 #if 0
1620         
1621                 /* check that it worked, and reverse
1622                    the button state if it didn't
1623                 */
1624
1625                 if ((session->*get)() != button_state) {
1626                         button->set_active (!button_state);
1627                 }
1628 #endif
1629
1630         }
1631 }       
1632
1633 gint
1634 ARDOUR_UI::session_menu (GdkEventButton *ev)
1635 {
1636         session_popup_menu->popup (0, 0);
1637         return TRUE;
1638 }
1639
1640 void
1641 ARDOUR_UI::redisplay_recent_sessions ()
1642 {
1643         vector<string *> *sessions;
1644         vector<string *>::iterator i;
1645         RecentSessionsSorter cmp;
1646         
1647         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1648         recent_session_model->clear ();
1649
1650         RecentSessions rs;
1651         ARDOUR::read_recent_sessions (rs);
1652
1653         if (rs.empty()) {
1654                 recent_session_display.set_model (recent_session_model);
1655                 return;
1656         }
1657
1658         /* sort them alphabetically */
1659         sort (rs.begin(), rs.end(), cmp);
1660         sessions = new vector<string*>;
1661
1662         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1663                 sessions->push_back (new string ((*i).second));
1664         }
1665
1666         for (i = sessions->begin(); i != sessions->end(); ++i) {
1667
1668                 vector<string*>* states;
1669                 vector<const gchar*> item;
1670                 string fullpath = *(*i);
1671                 
1672                 /* remove any trailing / */
1673
1674                 if (fullpath[fullpath.length()-1] == '/') {
1675                         fullpath = fullpath.substr (0, fullpath.length()-1);
1676                 }
1677
1678                 /* now get available states for this session */
1679
1680                 if ((states = Session::possible_states (fullpath)) == 0) {
1681                         /* no state file? */
1682                         continue;
1683                 }
1684
1685                 TreeModel::Row row = *(recent_session_model->append());
1686
1687                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1688                 row[recent_session_columns.fullpath] = fullpath;
1689
1690                 if (states->size() > 1) {
1691
1692                         /* add the children */
1693                         
1694                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1695                                 
1696                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1697
1698                                 child_row[recent_session_columns.visible_name] = **i2;
1699                                 child_row[recent_session_columns.fullpath] = fullpath;
1700
1701                                 delete *i2;
1702                         }
1703                 }
1704
1705                 delete states;
1706         }
1707
1708         recent_session_display.set_model (recent_session_model);
1709         delete sessions;
1710 }
1711
1712 void
1713 ARDOUR_UI::build_session_selector ()
1714 {
1715         session_selector_window = new ArdourDialog ("session selector");
1716         
1717         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1718         
1719         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1720         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1721
1722         recent_session_model = TreeStore::create (recent_session_columns);
1723         recent_session_display.set_model (recent_session_model);
1724         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1725         recent_session_display.set_headers_visible (false);
1726
1727         scroller->add (recent_session_display);
1728         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1729
1730         session_selector_window->set_name ("SessionSelectorWindow");
1731         session_selector_window->set_size_request (200, 400);
1732         session_selector_window->get_vbox()->pack_start (*scroller);
1733         session_selector_window->show_all_children();
1734 }
1735
1736 void
1737 ARDOUR_UI::open_recent_session ()
1738 {
1739         /* popup selector window */
1740
1741         if (session_selector_window == 0) {
1742                 build_session_selector ();
1743         }
1744
1745         redisplay_recent_sessions ();
1746
1747         ResponseType r = (ResponseType) session_selector_window->run ();
1748
1749         session_selector_window->hide();
1750
1751         switch (r) {
1752         case RESPONSE_ACCEPT:
1753                 break;
1754         default:
1755                 return;
1756         }
1757
1758         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1759
1760         if (i == recent_session_model->children().end()) {
1761                 return;
1762         }
1763         
1764         Glib::ustring path = (*i)[recent_session_columns.fullpath];
1765         Glib::ustring state = (*i)[recent_session_columns.visible_name];
1766
1767         _session_is_new = false;
1768
1769         load_session (path, state);
1770 }
1771
1772 bool
1773 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
1774 {
1775         struct stat statbuf;
1776
1777         if (stat (info.filename.c_str(), &statbuf) != 0) {
1778                 return false;
1779         }
1780
1781         if (!S_ISDIR(statbuf.st_mode)) {
1782                 return false;
1783         }
1784
1785         string session_file = info.filename;
1786         session_file += '/';
1787         session_file += PBD::basename (info.filename);
1788         session_file += ".ardour";
1789         
1790         if (stat (session_file.c_str(), &statbuf) != 0) {
1791                 return false;
1792         }
1793
1794         return S_ISREG (statbuf.st_mode);
1795 }
1796
1797 void
1798 ARDOUR_UI::open_session ()
1799 {
1800         /* popup selector window */
1801
1802         if (open_session_selector == 0) {
1803
1804                 /* ardour sessions are folders */
1805
1806                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1807                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1808                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1809
1810                 FileFilter session_filter;
1811                 session_filter.add_pattern ("*.ardour");
1812                 session_filter.set_name (_("Ardour sessions"));
1813                 open_session_selector->add_filter (session_filter);
1814                 open_session_selector->set_filter (session_filter);
1815         }
1816
1817         int response = open_session_selector->run();
1818         open_session_selector->hide ();
1819
1820         switch (response) {
1821         case RESPONSE_ACCEPT:
1822                 break;
1823         default:
1824                 open_session_selector->hide();
1825                 return;
1826         }
1827
1828         open_session_selector->hide();
1829         string session_path = open_session_selector->get_filename();
1830         string path, name;
1831         bool isnew;
1832
1833         if (session_path.length() > 0) {
1834                 if (Session::find_session (session_path, path, name, isnew) == 0) {
1835                         _session_is_new = isnew;
1836                         load_session (path, name);
1837                 }
1838         }
1839 }
1840
1841
1842 void
1843 ARDOUR_UI::session_add_midi_track ()
1844 {
1845         cerr << _("Patience is a virtue.\n");
1846 }
1847
1848 void
1849 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1850 {
1851         Route* route;
1852
1853         if (session == 0) {
1854                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1855                 return;
1856         }
1857
1858         try { 
1859                 if (disk) {
1860                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1861                                 error << _("could not create new audio track") << endmsg;
1862                         }
1863                 } else {
1864                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1865                                 error << _("could not create new audio bus") << endmsg;
1866                         }
1867                 }
1868                 
1869 #if CONTROLOUTS
1870                 if (need_control_room_outs) {
1871                         pan_t pans[2];
1872                         
1873                         pans[0] = 0.5;
1874                         pans[1] = 0.5;
1875                         
1876                         route->set_stereo_control_outs (control_lr_channels);
1877                         route->control_outs()->set_stereo_pan (pans, this);
1878                 }
1879 #endif /* CONTROLOUTS */
1880         }
1881
1882         catch (...) {
1883                 ArdourMessage msg (editor, X_("noport dialog"),
1884                                    _("There are insufficient JACK ports available\n\
1885 to create a new track or bus.\n\
1886 You should save Ardour, exit and\n\
1887 restart JACK with more ports."));
1888         }
1889 }
1890
1891 void
1892 ARDOUR_UI::diskstream_added (DiskStream* ds)
1893 {
1894 }
1895
1896 void
1897 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1898 {
1899         jack_nframes_t _preroll;
1900
1901         if (session) {
1902                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1903
1904                 if (new_position > _preroll) {
1905                         new_position -= _preroll;
1906                 } else {
1907                         new_position = 0;
1908                 }
1909
1910                 session->request_locate (new_position);
1911         }
1912 }
1913
1914 void
1915 ARDOUR_UI::transport_goto_start ()
1916 {
1917         if (session) {
1918                 session->request_locate (0);
1919
1920                 
1921                 /* force displayed area in editor to start no matter
1922                    what "follow playhead" setting is.
1923                 */
1924                 
1925                 if (editor) {
1926                         editor->reposition_x_origin (0);
1927                 }
1928         }
1929 }
1930
1931 void
1932 ARDOUR_UI::transport_goto_end ()
1933 {
1934         if (session) {
1935                 jack_nframes_t frame = session->current_end_frame();
1936                 session->request_locate (frame);
1937
1938                 /* force displayed area in editor to start no matter
1939                    what "follow playhead" setting is.
1940                 */
1941                 
1942                 if (editor) {
1943                         editor->reposition_x_origin (frame);
1944                 }
1945         }
1946 }
1947
1948 void
1949 ARDOUR_UI::transport_stop ()
1950 {
1951         if (!session) {
1952                 return;
1953         }
1954
1955         if (session->is_auditioning()) {
1956                 session->cancel_audition ();
1957                 return;
1958         }
1959         
1960         if (session->get_auto_loop()) {
1961                 session->request_auto_loop (false);
1962         }
1963         
1964         session->request_stop ();
1965 }
1966
1967 void
1968 ARDOUR_UI::transport_stop_and_forget_capture ()
1969 {
1970         if (session) {
1971                 session->request_stop (true);
1972         }
1973 }
1974
1975 void
1976 ARDOUR_UI::remove_last_capture()
1977 {
1978         if (editor) {
1979                 editor->remove_last_capture();
1980         }
1981 }
1982
1983 void
1984 ARDOUR_UI::transport_record ()
1985 {
1986         if (session) {
1987                 switch (session->record_status()) {
1988                 case Session::Disabled:
1989                         if (session->ntracks() == 0) {
1990                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1991                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1992                                 return;
1993                         }
1994                         session->maybe_enable_record ();
1995                         break;
1996                 case Session::Recording:
1997                 case Session::Enabled:
1998                         session->disable_record ();
1999                 }
2000         }
2001 }
2002
2003 void
2004 ARDOUR_UI::transport_roll ()
2005 {
2006         bool rolling;
2007
2008         if (!session) {
2009                 return;
2010         }
2011
2012         rolling = session->transport_rolling ();
2013
2014         if (session->get_auto_loop()) {
2015                 session->request_auto_loop (false);
2016                 auto_loop_button.set_active (false);
2017                 roll_button.set_active (true);
2018         } else if (session->get_play_range ()) {
2019                 session->request_play_range (false);
2020                 play_selection_button.set_active (false);
2021         } else if (rolling) {
2022                 session->request_locate (session->last_transport_start(), true);
2023         }
2024
2025         session->request_transport_speed (1.0f);
2026 }
2027
2028 void
2029 ARDOUR_UI::transport_loop()
2030 {
2031         if (session) {
2032                 if (session->get_auto_loop()) {
2033                         if (session->transport_rolling()) {
2034                                 Location * looploc = session->locations()->auto_loop_location();
2035                                 if (looploc) {
2036                                         session->request_locate (looploc->start(), true);
2037                                 }
2038                         }
2039                 }
2040                 else {
2041                         session->request_auto_loop (true);
2042                 }
2043         }
2044 }
2045
2046 void
2047 ARDOUR_UI::transport_play_selection ()
2048 {
2049         if (!session) {
2050                 return;
2051         }
2052
2053         if (!session->get_play_range()) {
2054                 session->request_stop ();
2055         }
2056
2057         editor->play_selection ();
2058 }
2059
2060 void
2061 ARDOUR_UI::transport_rewind (int option)
2062 {
2063         float current_transport_speed;
2064  
2065         if (session) {
2066                 current_transport_speed = session->transport_speed();
2067                 
2068                 if (current_transport_speed >= 0.0f) {
2069                         switch (option) {
2070                         case 0:
2071                                 session->request_transport_speed (-1.0f);
2072                                 break;
2073                         case 1:
2074                                 session->request_transport_speed (-4.0f);
2075                                 break;
2076                         case -1:
2077                                 session->request_transport_speed (-0.5f);
2078                                 break;
2079                         }
2080                 } else {
2081                         /* speed up */
2082                         session->request_transport_speed (current_transport_speed * 1.5f);
2083                 }
2084         }
2085 }
2086
2087 void
2088 ARDOUR_UI::transport_forward (int option)
2089 {
2090         float current_transport_speed;
2091         
2092         if (session) {
2093                 current_transport_speed = session->transport_speed();
2094                 
2095                 if (current_transport_speed <= 0.0f) {
2096                         switch (option) {
2097                         case 0:
2098                                 session->request_transport_speed (1.0f);
2099                                 break;
2100                         case 1:
2101                                 session->request_transport_speed (4.0f);
2102                                 break;
2103                         case -1:
2104                                 session->request_transport_speed (0.5f);
2105                                 break;
2106                         }
2107                 } else {
2108                         /* speed up */
2109                         session->request_transport_speed (current_transport_speed * 1.5f);
2110                 }
2111         }
2112 }
2113
2114 void
2115 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2116 {
2117         if (session == 0) {
2118                 return;
2119         }
2120
2121         DiskStream *ds;
2122
2123         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2124                 Port *port = ds->io()->input (0);
2125                 port->request_monitor_input (!port->monitoring_input());
2126         }
2127 }
2128
2129 void
2130 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2131 {
2132         if (session == 0) {
2133                 return;
2134         }
2135
2136         DiskStream *ds;
2137
2138         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2139                 ds->set_record_enabled (!ds->record_enabled(), this);
2140         }
2141 }
2142
2143 void
2144 ARDOUR_UI::queue_transport_change ()
2145 {
2146         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2147 }
2148
2149 void
2150 ARDOUR_UI::map_transport_state ()
2151 {
2152         float sp = session->transport_speed();
2153
2154         if (sp == 1.0f) {
2155                 transport_rolling ();
2156         } else if (sp < 0.0f) {
2157                 transport_rewinding ();
2158         } else if (sp > 0.0f) {
2159                 transport_forwarding ();
2160         } else {
2161                 transport_stopped ();
2162         }
2163 }
2164
2165 void
2166 ARDOUR_UI::send_all_midi_feedback ()
2167 {
2168         if (session) {
2169                 session->send_all_midi_feedback();
2170         }
2171 }
2172
2173 void
2174 ARDOUR_UI::allow_local_only ()
2175 {
2176
2177 }
2178
2179 void
2180 ARDOUR_UI::allow_mmc_only ()
2181 {
2182
2183 }
2184
2185 void
2186 ARDOUR_UI::allow_mmc_and_local ()
2187 {
2188
2189 }
2190
2191 void
2192 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2193 {
2194         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2195                 (int) adj.get_value()].c_str());
2196 }
2197
2198 void
2199 ARDOUR_UI::engine_stopped ()
2200 {
2201         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2202         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2203         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2204 }
2205
2206
2207 void
2208 ARDOUR_UI::engine_running ()
2209 {
2210         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2211         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2212         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2213 }
2214
2215 void
2216 ARDOUR_UI::engine_halted ()
2217 {
2218         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2219
2220         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2221         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2222
2223         update_sample_rate (0);
2224
2225         ArdourMessage msg (editor, X_("halted"),
2226                            _("\
2227 JACK has either been shutdown or it\n\
2228 disconnected Ardour because Ardour\n\
2229 was not fast enough. You can save the\n\
2230 session and/or try to reconnect to JACK ."));
2231 }
2232
2233 int32_t
2234 ARDOUR_UI::do_engine_start ()
2235 {
2236         try { 
2237                 engine->start();
2238         }
2239
2240         catch (AudioEngine::PortRegistrationFailure& err) {
2241                 engine->stop ();
2242                 error << _("Unable to create all required ports")
2243                       << endmsg;
2244                 unload_session ();
2245                 return -1;
2246         }
2247
2248         catch (...) {
2249                 engine->stop ();
2250                 error << _("Unable to start the session running")
2251                       << endmsg;
2252                 unload_session ();
2253                 return -2;
2254         }
2255         
2256         return 0;
2257 }
2258
2259 gint
2260 ARDOUR_UI::start_engine ()
2261 {
2262         if (do_engine_start () == 0) {
2263                 if (session && _session_is_new) {
2264                         /* we need to retain initial visual 
2265                            settings for a new session 
2266                         */
2267                         session->save_state ("");
2268                 }
2269
2270                 /* there is too much going on, in too many threads, for us to 
2271                    end up with a clean session. So wait 1 second after loading,
2272                    and fix it up. its ugly, but until i come across a better
2273                    solution, its what we have.
2274                 */
2275
2276                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2277         }
2278
2279         return FALSE;
2280 }
2281
2282 void
2283 ARDOUR_UI::update_clocks ()
2284 {
2285          Clock (session->audible_frame()); /* EMIT_SIGNAL */
2286 }
2287
2288 void
2289 ARDOUR_UI::start_clocking ()
2290 {
2291         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2292 }
2293
2294 void
2295 ARDOUR_UI::stop_clocking ()
2296 {
2297         clock_signal_connection.disconnect ();
2298 }
2299         
2300 void
2301 ARDOUR_UI::toggle_clocking ()
2302 {
2303 #if 0
2304         if (clock_button.get_active()) {
2305                 start_clocking ();
2306         } else {
2307                 stop_clocking ();
2308         }
2309 #endif
2310 }
2311
2312 gint
2313 ARDOUR_UI::_blink (void *arg)
2314
2315 {
2316         ((ARDOUR_UI *) arg)->blink ();
2317         return TRUE;
2318 }
2319
2320 void
2321 ARDOUR_UI::blink ()
2322 {
2323          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2324 }
2325
2326 void
2327 ARDOUR_UI::start_blinking ()
2328 {
2329         /* Start the blink signal. Everybody with a blinking widget
2330            uses Blink to drive the widget's state.
2331         */
2332
2333         if (blink_timeout_tag < 0) {
2334                 blink_on = false;       
2335                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2336         }
2337 }
2338
2339 void
2340 ARDOUR_UI::stop_blinking ()
2341 {
2342         if (blink_timeout_tag >= 0) {
2343                 gtk_timeout_remove (blink_timeout_tag);
2344                 blink_timeout_tag = -1;
2345         }
2346 }
2347
2348
2349 void
2350 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2351 {
2352         using namespace Gtk;
2353         using namespace Menu_Helpers;
2354
2355         if (dstream.hidden()) {
2356                 return;
2357         }
2358
2359         MenuList& items = diskstream_menu->items();
2360         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2361 }
2362         
2363 void
2364 ARDOUR_UI::diskstream_selected (gint32 id)
2365 {
2366         selected_dstream = id;
2367         Main::quit ();
2368 }
2369
2370 gint32
2371 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2372 {
2373         using namespace Gtk;
2374         using namespace Menu_Helpers;
2375
2376         if (session == 0) {
2377                 return -1;
2378         }
2379
2380         diskstream_menu = new Menu();
2381         diskstream_menu->set_name ("ArdourContextMenu");
2382         using namespace Gtk;
2383         using namespace Menu_Helpers;
2384
2385         MenuList& items = diskstream_menu->items();
2386         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2387
2388         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2389
2390         if (ev) {
2391                 diskstream_menu->popup (ev->button, ev->time);
2392         } else {
2393                 diskstream_menu->popup (0, 0);
2394         }
2395
2396         selected_dstream = -1;
2397
2398         Main::run ();
2399
2400         delete diskstream_menu;
2401
2402         return selected_dstream;
2403 }
2404
2405 void
2406 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
2407                           string& buf,
2408                           IO& io,
2409                           bool in)
2410 {
2411         if (in) {
2412                 if (io.n_inputs() == 0) {
2413                         buf = _("none");
2414                         return;
2415                 }
2416                 
2417                 /* XXX we're not handling multiple ports yet. */
2418
2419                 const char **connections = io.input(0)->get_connections();
2420                 
2421                 if (connections == 0 || connections[0] == '\0') {
2422                         buf = _("off");
2423                 } else {
2424                         buf = connections[0];
2425                 }
2426
2427                 free (connections);
2428
2429         } else {
2430
2431                 if (io.n_outputs() == 0) {
2432                         buf = _("none");
2433                         return;
2434                 }
2435                 
2436                 /* XXX we're not handling multiple ports yet. */
2437
2438                 const char **connections = io.output(0)->get_connections();
2439                 
2440                 if (connections == 0 || connections[0] == '\0') {
2441                         buf = _("off");
2442                 } else {
2443                         buf = connections[0];
2444                 }
2445
2446                 free (connections);
2447         }
2448 }
2449
2450 void
2451 ARDOUR_UI::snapshot_session ()
2452 {
2453         ArdourPrompter prompter (true);
2454         string snapname;
2455         string now;
2456         time_t n;
2457
2458         time (&n);
2459         now = ctime (&n);
2460         now = now.substr (0, now.length() - 1);
2461
2462         prompter.set_name ("Prompter");
2463         prompter.set_prompt (_("Name for snapshot"));
2464         prompter.set_initial_text (now);
2465         
2466         switch (prompter.run()) {
2467         case RESPONSE_ACCEPT:
2468                 prompter.get_result (snapname);
2469                 if (snapname.length()){
2470                         save_state (snapname);
2471                 }
2472                 break;
2473
2474         default:
2475                 break;
2476         }
2477 }
2478
2479 void
2480 ARDOUR_UI::save_state (string name)
2481 {
2482         (void) save_state_canfail (name);
2483 }
2484                 
2485 int
2486 ARDOUR_UI::save_state_canfail (string name)
2487 {
2488         if (session) {
2489                 int ret;
2490
2491                 if (name.length() == 0) {
2492                         name = session->snap_name();
2493                 }
2494
2495                 if ((ret = session->save_state (name)) != 0) {
2496                         return ret;
2497                 }
2498         }
2499         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2500         return 0;
2501 }
2502
2503 void
2504 ARDOUR_UI::restore_state (string name)
2505 {
2506         if (session) {
2507                 if (name.length() == 0) {
2508                         name = session->name();
2509                 }
2510                 session->restore_state (name);
2511         }
2512 }
2513
2514 void
2515 ARDOUR_UI::primary_clock_value_changed ()
2516 {
2517         if (session) {
2518                 session->request_locate (primary_clock.current_time ());
2519         }
2520 }
2521
2522 void
2523 ARDOUR_UI::secondary_clock_value_changed ()
2524 {
2525         if (session) {
2526                 session->request_locate (secondary_clock.current_time ());
2527         }
2528 }
2529
2530 void
2531 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2532 {
2533         if (session && dstream && dstream->record_enabled()) {
2534
2535                 Session::RecordState rs;
2536                 
2537                 rs = session->record_status ();
2538
2539                 switch (rs) {
2540                 case Session::Disabled:
2541                 case Session::Enabled:
2542                         if (w->get_state() != STATE_SELECTED) {
2543                                 w->set_state (STATE_SELECTED);
2544                         }
2545                         break;
2546
2547                 case Session::Recording:
2548                         if (w->get_state() != STATE_ACTIVE) {
2549                                 w->set_state (STATE_ACTIVE);
2550                         }
2551                         break;
2552                 }
2553
2554         } else {
2555                 if (w->get_state() != STATE_NORMAL) {
2556                         w->set_state (STATE_NORMAL);
2557                 }
2558         }
2559 }
2560
2561 void
2562 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
2563 {
2564         if (session == 0) {
2565                 return;
2566         }
2567         
2568         switch (session->record_status()) {
2569         case Session::Enabled:
2570                 if (onoff) {
2571                         rec_button.set_state (STATE_ACTIVE);
2572                 } else {
2573                         rec_button.set_state (STATE_NORMAL);
2574                 }
2575                 break;
2576
2577         case Session::Recording:
2578                 rec_button.set_state (STATE_ACTIVE);
2579                 break;
2580
2581         default:
2582                 rec_button.set_active (false);
2583                 rec_button.set_state (STATE_NORMAL);
2584                 break;
2585         }
2586 }
2587
2588 gint
2589 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2590 {
2591         window->hide();
2592         Gtk::Main::quit ();
2593         return TRUE;
2594 }
2595
2596 void
2597 ARDOUR_UI::start_keyboard_prefix ()
2598 {
2599         keyboard->start_prefix();
2600 }
2601
2602 void
2603 ARDOUR_UI::save_template ()
2604
2605 {
2606         ArdourPrompter prompter (true);
2607         string name;
2608
2609         prompter.set_name (X_("Prompter"));
2610         prompter.set_prompt (_("Name for mix template:"));
2611         prompter.set_initial_text(session->name() + _("-template"));
2612         
2613         switch (prompter.run()) {
2614         case RESPONSE_ACCEPT:
2615                 prompter.get_result (name);
2616                 
2617                 if (name.length()) {
2618                         session->save_template (name);
2619                 }
2620                 break;
2621
2622         default:
2623                 break;
2624         }
2625 }
2626
2627 void
2628 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2629 {
2630         m_new_session_dialog->show_all();
2631         m_new_session_dialog->set_transient_for(*editor);
2632         m_new_session_dialog->set_name(predetermined_path);
2633
2634         int response = Gtk::RESPONSE_CANCEL;
2635
2636         do {
2637                 response = m_new_session_dialog->run ();
2638         
2639                 if(response == Gtk::RESPONSE_OK) {
2640
2641                         _session_is_new = true;
2642                         
2643                         std::string session_name = m_new_session_dialog->session_name();
2644                         std::string session_path = m_new_session_dialog->session_folder();
2645                         
2646                         /*
2647                           XXX This is needed because session constructor wants a 
2648                           non-existant path. hopefully this will be fixed at some point.
2649                         */
2650                         session_path = Glib::build_filename(session_path, session_name);
2651                         
2652                         std::string template_name = m_new_session_dialog->session_template_name();
2653                         
2654                         if (m_new_session_dialog->use_session_template()) {
2655                                 
2656                                 load_session (session_path, session_name, &template_name);
2657                                 
2658                         } else {
2659                                 
2660                                 uint32_t cchns;
2661                                 uint32_t mchns;
2662                                 Session::AutoConnectOption iconnect;
2663                                 Session::AutoConnectOption oconnect;
2664                                 
2665                                 if (m_new_session_dialog->create_control_bus()) {
2666                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2667                                 } else {
2668                                         cchns = 0;
2669                                 }
2670                                 
2671                                 if (m_new_session_dialog->create_master_bus()) {
2672                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2673                                 } else {
2674                                         mchns = 0;
2675                                 }
2676                                 
2677                                 if (m_new_session_dialog->connect_inputs()) {
2678                                         iconnect = Session::AutoConnectPhysical;
2679                                 } else {
2680                                         iconnect = Session::AutoConnectOption (0);
2681                                 }
2682                                 
2683                                 /// @todo some minor tweaks.
2684
2685                                 if (m_new_session_dialog->connect_outs_to_master()) {
2686                                         oconnect = Session::AutoConnectMaster;
2687                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2688                                         oconnect = Session::AutoConnectPhysical;
2689                                 } else {
2690                                         oconnect = Session::AutoConnectOption (0);
2691                                 } 
2692                                 
2693                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2694                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2695                                 
2696                                 build_session (session_path,
2697                                                session_name,
2698                                                cchns,
2699                                                mchns,
2700                                                iconnect,
2701                                                oconnect,
2702                                                nphysin,
2703                                                nphysout, 
2704                                                engine->frame_rate() * 60 * 5);
2705                         }               
2706                 }
2707
2708         } while(response == Gtk::RESPONSE_HELP);
2709         m_new_session_dialog->hide_all();
2710 }
2711
2712 int
2713 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2714 {
2715         Session *new_session;
2716         int x;
2717         session_loaded = false;
2718         x = unload_session ();
2719
2720         if (x < 0) {
2721                 return -1;
2722         } else if (x > 0) {
2723                 return 0;
2724         }
2725
2726         /* if it already exists, we must have write access */
2727
2728         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2729                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2730 You do not have write access to this session.\n\
2731 This prevents the session from being loaded."));
2732                 return -1;
2733         }
2734
2735         try {
2736                 new_session = new Session (*engine, path, snap_name, mix_template);
2737         }
2738
2739         catch (...) {
2740
2741                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2742                 return -1;
2743         }
2744
2745         connect_to_session (new_session);
2746
2747         //if (engine->running()) {
2748         //mixer->show_window();
2749         //}
2750         session_loaded = true;
2751         return 0;
2752 }
2753
2754 int
2755 ARDOUR_UI::make_session_clean ()
2756 {
2757         if (session) {
2758                 session->set_clean ();
2759         }
2760
2761         return FALSE;
2762 }
2763
2764 int
2765 ARDOUR_UI::build_session (string path, string snap_name, 
2766                           uint32_t control_channels,
2767                           uint32_t master_channels, 
2768                           Session::AutoConnectOption input_connect,
2769                           Session::AutoConnectOption output_connect,
2770                           uint32_t nphysin,
2771                           uint32_t nphysout,
2772                           jack_nframes_t initial_length)
2773 {
2774         Session *new_session;
2775         int x;
2776
2777         session_loaded = false;
2778         x = unload_session ();
2779         if (x < 0) {
2780                 return -1;
2781         } else if (x > 0) {
2782                 return 0;
2783         }
2784         
2785         _session_is_new = true;
2786
2787         try {
2788                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2789                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2790         }
2791
2792         catch (...) {
2793
2794                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2795                 return -1;
2796         }
2797
2798         connect_to_session (new_session);
2799
2800         //if (engine->running()) {
2801         //mixer->show_window();
2802         //}
2803         session_loaded = true;
2804         return 0;
2805 }
2806
2807 void
2808 ARDOUR_UI::show ()
2809 {
2810         if (editor) {
2811                 editor->show_window ();
2812                 shown_flag = true;
2813         }
2814
2815         if (session && mixer) {
2816                 // mixer->show_window ();
2817         }
2818         
2819         if (about) {
2820                 about->present ();
2821         }
2822 }
2823
2824 void
2825 ARDOUR_UI::show_splash ()
2826 {
2827         if (about == 0) {
2828                 about = new About();
2829         }
2830         about->present();
2831 }
2832
2833 void
2834 ARDOUR_UI::hide_splash ()
2835 {
2836         if (about) {
2837                 // about->hide();
2838         }
2839 }
2840
2841 void
2842 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2843 {
2844         size_t removed;
2845
2846         removed = rep.paths.size();
2847
2848         if (removed == 0) {
2849                 ArdourMessage msg (editor, X_("cleanupresults"),
2850                                    _("\
2851 No audio files were ready for cleanup\n\n\
2852 If this seems suprising, check for any existing\n\
2853 snapshots. These may still include regions that\n\
2854 require some unused files to continue to exist."));
2855                 return;
2856         } 
2857
2858         ArdourDialog results (_("ardour: cleanup"), true);
2859         
2860         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2861             CleanupResultsModelColumns() { 
2862                     add (visible_name);
2863                     add (fullpath);
2864             }
2865             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2866             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2867         };
2868
2869         
2870         Glib::RefPtr<Gtk::ListStore> results_model;
2871         CleanupResultsModelColumns results_columns;
2872         Gtk::TreeView results_display;
2873         
2874         results_model = ListStore::create (results_columns);
2875         results_display.set_model (results_model);
2876         results_display.append_column (list_title, results_columns.visible_name);
2877         results_display.set_headers_visible (true);
2878
2879         Gtk::ScrolledWindow list_scroller;
2880         Gtk::Label txt;
2881
2882         if (rep.space < 1048576.0f) {
2883                 if (removed > 1) {
2884                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2885                 } else {
2886                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2887                 }
2888         } else {
2889                 if (removed > 1) {
2890                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2891                 } else {
2892                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2893                 }
2894         }
2895
2896         results.get_vbox()->pack_start (txt, false, false);
2897         
2898         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2899                 TreeModel::Row row = *(results_model->append());
2900                 row[results_columns.visible_name] = *i;
2901                 row[results_columns.fullpath] = *i;
2902         }
2903         
2904         list_scroller.add (results_display);
2905         list_scroller.set_size_request (-1, 250);
2906         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2907         
2908         results.get_vbox()->pack_start (list_scroller, true, true);
2909         results.add_button (Stock::OK, RESPONSE_ACCEPT);
2910         results.set_position (Gtk::WIN_POS_MOUSE);
2911
2912         results.run ();
2913 }
2914
2915 void
2916 ARDOUR_UI::cleanup ()
2917 {
2918         if (session == 0) {
2919                 /* shouldn't happen: menu item is insensitive */
2920                 return;
2921         }
2922
2923         ArdourDialog checker (_("ardour cleanup"));
2924         Gtk::Label label (_("\
2925 Cleanup is a destructive operation.\n\
2926 ALL undo/redo information will be lost if you cleanup.\n\
2927 Unused audio files will be moved to a \"dead sounds\" location."));
2928         
2929         checker.get_vbox()->pack_start (label, false, false);
2930         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2931         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2932
2933         checker.set_name (_("CleanupDialog"));
2934         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2935         checker.set_position (Gtk::WIN_POS_MOUSE);
2936
2937         switch (checker.run()) {
2938         case RESPONSE_ACCEPT:
2939                 break;
2940         default:
2941                 return;
2942         }
2943
2944         Session::cleanup_report rep;
2945
2946         editor->prepare_for_cleanup ();
2947
2948         if (session->cleanup_sources (rep)) {
2949                 return;
2950         }
2951
2952         display_cleanup_results (rep, 
2953                                  _("cleaned files"),
2954                                  _("\
2955 The following %1 %2 were not in use.\n\
2956 The next time you flush the wastebasket\n\
2957 it will release an additional %3 %4bytes\n\
2958 of disk space"
2959                                          ));
2960 }
2961
2962 void
2963 ARDOUR_UI::flush_trash ()
2964 {
2965         if (session == 0) {
2966                 /* shouldn't happen: menu item is insensitive */
2967                 return;
2968         }
2969
2970         Session::cleanup_report rep;
2971
2972         if (session->cleanup_trash_sources (rep)) {
2973                 return;
2974         }
2975
2976         display_cleanup_results (rep, 
2977                                  _("deleted file"),
2978                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2979 }
2980
2981 void
2982 ARDOUR_UI::add_route ()
2983 {
2984         int count;
2985
2986         if (!session) {
2987                 return;
2988         }
2989
2990         if (add_route_dialog == 0) {
2991                 add_route_dialog = new AddRouteDialog;
2992                 editor->ensure_float (*add_route_dialog);
2993         }
2994
2995         if (add_route_dialog->is_visible()) {
2996                 /* we're already doing this */
2997                 return;
2998         }
2999
3000         ResponseType r = (ResponseType) add_route_dialog->run ();
3001         
3002         add_route_dialog->hide();
3003
3004         switch (r) {
3005         case RESPONSE_ACCEPT:
3006                 break;
3007         default:
3008                 return;
3009                 break;
3010         }
3011
3012         if ((count = add_route_dialog->count()) <= 0) {
3013                 return;
3014         }
3015
3016         uint32_t input_chan = add_route_dialog->channels ();
3017         uint32_t output_chan;
3018         string name_template = add_route_dialog->name_template ();
3019         bool track = add_route_dialog->track ();
3020
3021         Session::AutoConnectOption oac = session->get_output_auto_connect();
3022
3023         if (oac & Session::AutoConnectMaster) {
3024                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3025         } else {
3026                 output_chan = input_chan;
3027         }
3028
3029         /* XXX do something with name template */
3030
3031         while (count) {
3032                 if (track) {
3033                         session_add_audio_track (input_chan, output_chan);
3034                 } else {
3035                         session_add_audio_bus (input_chan, output_chan);
3036                 }
3037                 --count;
3038                 
3039                 while (Main::events_pending()) {
3040                         Main::iteration ();
3041                 }
3042         }
3043 }
3044
3045 XMLNode*
3046 ARDOUR_UI::mixer_settings () const
3047 {
3048         XMLNode* node = 0;
3049
3050         if (session) {
3051                 node = session->instant_xml(X_("Mixer"), session->path());
3052         } else {
3053                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3054         }
3055
3056         if (!node) {
3057                 node = new XMLNode (X_("Mixer"));
3058         }
3059
3060         return node;
3061 }
3062
3063 XMLNode*
3064 ARDOUR_UI::editor_settings () const
3065 {
3066         XMLNode* node = 0;
3067
3068         if (session) {
3069                 node = session->instant_xml(X_("Editor"), session->path());
3070         } else {
3071                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3072         }
3073
3074         if (!node) {
3075                 node = new XMLNode (X_("Editor"));
3076         }
3077         return node;
3078 }
3079
3080 XMLNode*
3081 ARDOUR_UI::keyboard_settings () const
3082 {
3083         XMLNode* node = 0;
3084
3085         node = Config->extra_xml(X_("Keyboard"));
3086         
3087         if (!node) {
3088                 node = new XMLNode (X_("Keyboard"));
3089         }
3090         return node;
3091 }
3092
3093 void
3094 ARDOUR_UI::halt_on_xrun_message ()
3095 {
3096         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3097
3098         ArdourMessage msg (editor, X_("haltonxrun"),
3099                            _("Recording was stopped because your system could not keep up."));
3100 }
3101
3102 void 
3103 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3104 {
3105         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3106
3107         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3108                 delete *i;
3109         }
3110
3111         delete deletion_list;
3112 }
3113
3114 void
3115 ARDOUR_UI::disk_overrun_handler ()
3116 {
3117         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3118
3119         if (!have_disk_overrun_displayed) {
3120                 have_disk_overrun_displayed = true;
3121                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3122 The disk system on your computer\n\
3123 was not able to keep up with Ardour.\n\
3124 \n\
3125 Specifically, it failed to write data to disk\n\
3126 quickly enough to keep up with recording.\n"));
3127                 have_disk_overrun_displayed = false;
3128         }
3129 }
3130
3131 void
3132 ARDOUR_UI::disk_underrun_handler ()
3133 {
3134         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3135
3136         if (!have_disk_underrun_displayed) {
3137                 have_disk_underrun_displayed = true;
3138                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3139                         (_("The disk system on your computer\n\
3140 was not able to keep up with Ardour.\n\
3141 \n\
3142 Specifically, it failed to read data from disk\n\
3143 quickly enough to keep up with playback.\n")));
3144                 have_disk_underrun_displayed = false;
3145         } 
3146 }
3147
3148 void
3149 ARDOUR_UI::disk_underrun_message_gone ()
3150 {
3151         have_disk_underrun_displayed = false;
3152 }
3153
3154 void
3155 ARDOUR_UI::disk_overrun_message_gone ()
3156 {
3157         have_disk_underrun_displayed = false;
3158 }
3159
3160 int
3161 ARDOUR_UI::pending_state_dialog ()
3162 {
3163         ArdourDialog dialog ("pending state dialog");
3164         Label  message (_("\
3165 This session appears to have been in\n\
3166 middle of recording when ardour or\n\
3167 the computer was shutdown.\n\
3168 \n\
3169 Ardour can recover any captured audio for\n\
3170 you, or it can ignore it. Please decide\n\
3171 what you would like to do.\n"));
3172
3173         dialog.get_vbox()->pack_start (message);
3174         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3175         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3176
3177         dialog.set_position (WIN_POS_CENTER);
3178         dialog.show_all ();
3179         
3180         switch (dialog.run ()) {
3181         case RESPONSE_ACCEPT:
3182                 break;
3183         default:
3184                 return 1;
3185         }
3186
3187         return 0;
3188 }
3189         
3190         
3191 void
3192 ARDOUR_UI::disconnect_from_jack ()
3193 {
3194         if (engine) {
3195                 if( engine->disconnect_from_jack ()) {
3196                         ArdourMessage msg (editor, X_("nojack dialog"),
3197                                            _("Could not disconnect from JACK"));
3198                 }
3199
3200                 update_sample_rate (0);
3201         }
3202 }
3203
3204 void
3205 ARDOUR_UI::reconnect_to_jack ()
3206 {
3207         if (engine) {
3208                 if (engine->reconnect_to_jack ()) {
3209                         ArdourMessage msg (editor, X_("nojack dialog"),
3210                                            _("Could not reconnect to JACK"));
3211                 }
3212
3213                 update_sample_rate (0);
3214         }
3215 }
3216
3217 void
3218 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3219 {
3220         engine->request_buffer_size (nframes);
3221         update_sample_rate (0);
3222 }
3223
3224 int
3225 ARDOUR_UI::cmdline_new_session (string path)
3226 {
3227         if (path[0] != '/') {
3228                 char buf[PATH_MAX+1];
3229                 string str;
3230
3231                 getcwd (buf, sizeof (buf));
3232                 str = buf;
3233                 str += '/';
3234                 str += path;
3235                 path = str;
3236         }
3237
3238         new_session (false, path);
3239
3240         _will_create_new_session_automatically = false; /* done it */
3241         return FALSE; /* don't call it again */
3242 }