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