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