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