rework audio import_samples + resample + playback speed sampling, fix clear_boarder...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / mwindowgui.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "androidcontrol.h"
23 #include "awindowgui.h"
24 #include "awindow.h"
25 #include "bcdisplayinfo.h"
26 #include "bchash.h"
27 #include "bcsignals.h"
28 #include "clip.h"
29 #include "cwindowgui.h"
30 #include "cwindow.h"
31 #include "channelinfo.h"
32 #include "dbwindow.h"
33 #include "edit.h"
34 #include "editpopup.h"
35 #include "edits.h"
36 #include "edl.h"
37 #include "edlsession.h"
38 #include "filesystem.h"
39 #include "filexml.h"
40 #include "keyframepopup.h"
41 #include "keys.h"
42 #include "language.h"
43 #include "localsession.h"
44 #include "mainclock.h"
45 #include "maincursor.h"
46 #include "mainmenu.h"
47 #include "mainsession.h"
48 #include "mainundo.h"
49 #include "mbuttons.h"
50 #include "mtimebar.h"
51 #include "mwindowgui.h"
52 #include "mwindow.h"
53 #include "panedividers.h"
54 #include "patchbay.h"
55 #include "plugin.h"
56 #include "pluginpopup.h"
57 #include "pluginset.h"
58 #include "preferences.h"
59 #include "record.h"
60 #include "recordgui.h"
61 #include "renderengine.h"
62 #include "resourcethread.h"
63 #include "samplescroll.h"
64 #include "shbtnprefs.h"
65 #include "statusbar.h"
66 #include "swindow.h"
67 #include "theme.h"
68 #include "trackcanvas.h"
69 #include "trackpopup.h"
70 #include "trackscroll.h"
71 #include "tracks.h"
72 #include "transitionpopup.h"
73 #include "vwindowgui.h"
74 #include "vwindow.h"
75 #include "zoombar.h"
76
77 #define PANE_DRAG_MARGIN MAX(mwindow->theme->pane_w, mwindow->theme->pane_h)
78
79
80 // the main window uses its own private colormap for video
81 MWindowGUI::MWindowGUI(MWindow *mwindow)
82  : BC_Window(_(PROGRAM_NAME ": Program"),
83                 mwindow->session->mwindow_x, mwindow->session->mwindow_y,
84                 mwindow->session->mwindow_w, mwindow->session->mwindow_h,
85                 xS(100), yS(100), 1, 1, 1)
86 {
87         this->mwindow = mwindow;
88 //      samplescroll = 0;
89 //      trackscroll = 0;
90 //      cursor = 0;
91 //      patchbay = 0;
92 //      timebar = 0;
93 //      canvas = 0;
94         focused_pane = TOP_LEFT_PANE;
95         x_divider = 0;
96         y_divider = 0;
97         x_pane_drag = 0;
98         y_pane_drag = 0;
99         dragging_pane = 0;
100         drag_popup = 0;
101
102         render_engine = 0;
103         for(int i = 0; i < TOTAL_PANES; i++)
104                 pane[i] = 0;
105
106         record = 0;
107         channel_info = 0;
108         swindow = 0;
109         db_window = 0;
110 // subwindows
111         mbuttons = 0;
112         statusbar = 0;
113         zoombar = 0;
114         mainclock = 0;
115         track_menu = 0;
116         edit_menu = 0;
117         plugin_menu = 0;
118         keyframe_menu = 0;
119         keyframe_hide = 0;
120         keyvalue_popup = 0;
121         transition_menu = 0;
122         remote_control = 0;
123         cwindow_remote_handler = 0;
124         record_remote_handler = 0;
125         android_control = 0;
126 }
127
128
129 MWindowGUI::~MWindowGUI()
130 {
131         delete android_control;
132         delete cwindow_remote_handler;
133         delete record_remote_handler;
134         delete remote_control;
135         delete keyvalue_popup;
136 //      delete samplescroll;
137 //      delete trackscroll;
138         for(int i = 0; i < TOTAL_PANES; i++)
139                 if(pane[i]) delete pane[i];
140 //      delete cursor;
141         delete render_engine;
142         delete resource_thread;
143         resource_pixmaps.remove_all_objects();
144         delete swindow;
145 #ifdef HAVE_DVB
146         delete channel_info;
147 #endif
148         delete db_window;
149         delete x_divider;
150         delete y_divider;
151 }
152
153 void MWindowGUI::create_objects()
154 {
155         lock_window("MWindowGUI::create_objects");
156         const int debug = 0;
157
158         resource_thread = new ResourceThread(mwindow, this);
159         resource_thread->create_objects();
160
161
162         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
163         set_icon(mwindow->theme->get_image("mwindow_icon"));
164         remote_control = new RemoteControl(this);
165         cwindow_remote_handler = new CWindowRemoteHandler(remote_control);
166         record_remote_handler = new RecordRemoteHandler(remote_control);
167         mwindow->reset_android_remote();
168
169         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
170
171         int x = get_w() - MainShBtns::calculate_w(-1, 0, -1);
172         add_subwindow(mainmenu = new MainMenu(mwindow, this, x));
173         mainmenu->create_objects();
174         add_subwindow(mainshbtns = new MainShBtns(mwindow, x, -1));
175         mainshbtns->load(mwindow->preferences);
176         mwindow->theme->get_mwindow_sizes(this, get_w(), get_h());
177         mwindow->theme->draw_mwindow_bg(this);
178         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
179
180         add_subwindow(mbuttons = new MButtons(mwindow, this));
181         mbuttons->create_objects();
182         int x1 = mbuttons->get_x() + mbuttons->get_w(), y1 = mbuttons->get_y()+yS(2);
183         add_subwindow(proxy_toggle = new ProxyToggle(mwindow, mbuttons, x1, y1));
184         x1 += proxy_toggle->get_w() + xS(3);
185         add_subwindow(ffmpeg_toggle = new FFMpegToggle(mwindow, mbuttons, x1, y1));
186
187         pane[TOP_LEFT_PANE] = new TimelinePane(mwindow,
188                 TOP_LEFT_PANE,
189                 mwindow->theme->mcanvas_x,
190                 mwindow->theme->mcanvas_y,
191                 mwindow->theme->mcanvas_w,
192                 mwindow->theme->mcanvas_h);
193         pane[TOP_LEFT_PANE]->create_objects();
194
195         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
196         add_subwindow(zoombar = new ZoomBar(mwindow, this));
197         zoombar->create_objects();
198
199
200         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
201         add_subwindow(statusbar = new StatusBar(mwindow, this));
202         statusbar->create_objects();
203
204
205
206         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
207         add_subwindow(mainclock = new MainClock(mwindow,
208                 mwindow->theme->mclock_x, mwindow->theme->mclock_y,
209                 mwindow->theme->mclock_w));
210         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
211         mainclock->update(0);
212
213
214
215 //      if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
216 //      cursor = new MainCursor(mwindow, this);
217 //      cursor->create_objects();
218
219
220         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
221         add_subwindow(track_menu = new TrackPopup(mwindow, this));
222         track_menu->create_objects();
223         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
224         add_subwindow(edit_menu = new EditPopup(mwindow, this));
225         edit_menu->create_objects();
226
227
228         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
229         add_subwindow(plugin_menu = new PluginPopup(mwindow, this));
230         plugin_menu->create_objects();
231
232
233         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
234         add_subwindow(keyframe_menu = new KeyframePopup(mwindow, this));
235         keyframe_menu->create_objects();
236         add_subwindow(keyframe_hide = new KeyframeHidePopup(mwindow, this));
237         keyframe_hide->create_objects();
238
239
240         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
241         add_subwindow(transition_menu = new TransitionPopup(mwindow, this));
242         transition_menu->create_objects();
243
244 #ifdef HAVE_DVB
245         channel_info = new ChannelInfo(mwindow);
246 #endif
247 #ifdef HAVE_COMMERCIAL
248         db_window = new DbWindow(mwindow);
249 #endif
250         swindow = new SWindow(mwindow);
251
252         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
253
254         add_subwindow(pane_button = new PaneButton(mwindow,
255                 get_w() - mwindow->theme->get_image_set("pane")[0]->get_w(),
256                 mwindow->theme->mzoom_y + 1 - mwindow->theme->get_image_set("pane")[0]->get_h()));
257
258         pane[TOP_LEFT_PANE]->canvas->activate();
259
260         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
261         unlock_window();
262 }
263
264 void MWindowGUI::redraw_time_dependancies()
265 {
266         zoombar->redraw_time_dependancies();
267         for(int i = 0; i < TOTAL_PANES; i++)
268                 if(pane[i] && pane[i]->timebar) pane[i]->timebar->update(0);
269         mainclock->update(mwindow->edl->local_session->get_selectionstart(1));
270 }
271
272 int MWindowGUI::focus_in_event()
273 {
274         for(int i = 0; i < TOTAL_PANES; i++)
275                 if(pane[i]) pane[i]->cursor->focus_in_event();
276         return 1;
277 }
278
279 int MWindowGUI::focus_out_event()
280 {
281         for(int i = 0; i < TOTAL_PANES; i++)
282                 if(pane[i]) pane[i]->cursor->focus_out_event();
283         return 1;
284 }
285
286
287 int MWindowGUI::resize_event(int w, int h)
288 {
289 //printf("MWindowGUI::resize_event %d\n", __LINE__);
290         mwindow->session->mwindow_w = w;
291         mwindow->session->mwindow_h = h;
292         int x = w - MainShBtns::calculate_w(-1, 0, -1);
293         mainmenu->resize_event(x, mainmenu->get_h());
294         mainshbtns->reposition_window(x, -1);
295         mwindow->theme->get_mwindow_sizes(this, w, h);
296         mwindow->theme->draw_mwindow_bg(this);
297         mbuttons->resize_event();
298         int x1 = mbuttons->get_x() + mbuttons->get_w(), y1 = mbuttons->get_y()+yS(2);
299         proxy_toggle->reposition_window(x1, y1);
300         x1 += proxy_toggle->get_w() + xS(3);
301         ffmpeg_toggle->reposition_window(x1, y1);
302         statusbar->resize_event();
303         zoombar->resize_event();
304
305         resource_thread->stop_draw(1);
306
307         if(total_panes() > 1)
308         {
309                 if(horizontal_panes())
310                 {
311 //                      printf("MWindowGUI::resize_event %d %d %d\n",
312 //                              __LINE__,
313 //                              pane[TOP_RIGHT_PANE]->x,
314 //                              mwindow->theme->mcanvas_w -
315 //                                      BC_ScrollBar::get_span(SCROLL_VERT) -
316 //                                      PANE_DRAG_MARGIN);
317                         if(pane[TOP_RIGHT_PANE]->x >= mwindow->theme->mcanvas_w -
318                                 BC_ScrollBar::get_span(SCROLL_VERT) -
319                                 PANE_DRAG_MARGIN)
320                         {
321                                 delete_x_pane(pane[TOP_RIGHT_PANE]->x);
322                                 mwindow->edl->local_session->x_pane = -1;
323                         }
324                 }
325                 else
326                 if(vertical_panes())
327                 {
328                         if(pane[BOTTOM_LEFT_PANE]->y >= mwindow->theme->mzoom_y -
329                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
330                                 PANE_DRAG_MARGIN)
331                         {
332                                 delete_y_pane(pane[BOTTOM_LEFT_PANE]->y);
333                                 mwindow->edl->local_session->y_pane = -1;
334                         }
335                 }
336                 else
337                 {
338                         if(pane[TOP_RIGHT_PANE]->x >= mwindow->theme->mcanvas_w -
339                                         BC_ScrollBar::get_span(SCROLL_VERT) -
340                                         PANE_DRAG_MARGIN)
341                         {
342                                 delete_x_pane(pane[TOP_RIGHT_PANE]->x);
343                                 mwindow->edl->local_session->x_pane = -1;
344                         }
345
346                         if(pane[BOTTOM_LEFT_PANE]->y >= mwindow->theme->mzoom_y -
347                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
348                                 PANE_DRAG_MARGIN)
349                         {
350                                 delete_y_pane(pane[BOTTOM_LEFT_PANE]->y);
351                                 mwindow->edl->local_session->y_pane = -1;
352                         }
353                 }
354         }
355
356         if(total_panes() == 1)
357         {
358                 pane[TOP_LEFT_PANE]->resize_event(
359                         mwindow->theme->mcanvas_x,
360                         mwindow->theme->mcanvas_y,
361                         mwindow->theme->mcanvas_w,
362                         mwindow->theme->mcanvas_h);
363         }
364         else
365         if(horizontal_panes())
366         {
367                 pane[TOP_LEFT_PANE]->resize_event(
368                         pane[TOP_LEFT_PANE]->x,
369                         pane[TOP_LEFT_PANE]->y,
370                         pane[TOP_LEFT_PANE]->w,
371                         mwindow->theme->mcanvas_h);
372                 pane[TOP_RIGHT_PANE]->resize_event(
373                         pane[TOP_RIGHT_PANE]->x,
374                         pane[TOP_RIGHT_PANE]->y,
375                         mwindow->theme->mcanvas_w - pane[TOP_RIGHT_PANE]->x,
376                         mwindow->theme->mcanvas_h);
377         }
378         else
379         if(vertical_panes())
380         {
381                 pane[TOP_LEFT_PANE]->resize_event(
382                         pane[TOP_LEFT_PANE]->x,
383                         pane[TOP_LEFT_PANE]->y,
384                         mwindow->theme->mcanvas_w,
385                         pane[TOP_LEFT_PANE]->h);
386                 pane[BOTTOM_LEFT_PANE]->resize_event(
387                         pane[BOTTOM_LEFT_PANE]->x,
388                         pane[BOTTOM_LEFT_PANE]->y,
389                         mwindow->theme->mcanvas_w,
390                         mwindow->theme->mcanvas_y +
391                                 mwindow->theme->mcanvas_h -
392                                 pane[BOTTOM_LEFT_PANE]->y);
393         }
394         else
395         {
396                 pane[TOP_LEFT_PANE]->resize_event(
397                         pane[TOP_LEFT_PANE]->x,
398                         pane[TOP_LEFT_PANE]->y,
399                         pane[TOP_LEFT_PANE]->w,
400                         pane[TOP_LEFT_PANE]->h);
401                 pane[TOP_RIGHT_PANE]->resize_event(
402                         pane[TOP_RIGHT_PANE]->x,
403                         pane[TOP_RIGHT_PANE]->y,
404                         mwindow->theme->mcanvas_w - pane[TOP_RIGHT_PANE]->x,
405                         pane[TOP_RIGHT_PANE]->h);
406                 pane[BOTTOM_LEFT_PANE]->resize_event(
407                         pane[BOTTOM_LEFT_PANE]->x,
408                         pane[BOTTOM_LEFT_PANE]->y,
409                         pane[BOTTOM_LEFT_PANE]->w,
410                         mwindow->theme->mcanvas_y +
411                                 mwindow->theme->mcanvas_h -
412                                 pane[BOTTOM_LEFT_PANE]->y);
413                 pane[BOTTOM_RIGHT_PANE]->resize_event(
414                         pane[BOTTOM_RIGHT_PANE]->x,
415                         pane[BOTTOM_RIGHT_PANE]->y,
416                         mwindow->theme->mcanvas_w -
417                                 pane[BOTTOM_RIGHT_PANE]->x,
418                         mwindow->theme->mcanvas_y +
419                                 mwindow->theme->mcanvas_h -
420                                 pane[BOTTOM_RIGHT_PANE]->y);
421         }
422
423         update_pane_dividers();
424         pane_button->reposition_window(w - mwindow->theme->get_image_set("pane")[0]->get_w(),
425                 mwindow->theme->mzoom_y + 1 - mwindow->theme->get_image_set("pane")[0]->get_h());
426         resource_thread->start_draw();
427
428         flash(1);
429         return 0;
430 }
431
432 int MWindowGUI::total_panes()
433 {
434         int total = 0;
435         for(int i = 0; i < TOTAL_PANES; i++)
436                 if(pane[i]) total++;
437         return total;
438 }
439
440 int MWindowGUI::vertical_panes()
441 {
442         return total_panes() == 2 &&
443                 pane[TOP_LEFT_PANE] &&
444                 pane[BOTTOM_LEFT_PANE];
445 }
446
447 int MWindowGUI::horizontal_panes()
448 {
449         return total_panes() == 2 &&
450                 pane[TOP_LEFT_PANE] &&
451                 pane[TOP_RIGHT_PANE];
452 }
453
454 TimelinePane* MWindowGUI::get_focused_pane()
455 {
456         if(pane[focused_pane]) return pane[focused_pane];
457         for(int i = 0; i < TOTAL_PANES; i++)
458         {
459                 if(pane[i]) return pane[i];
460         }
461         return 0;
462 }
463
464 void MWindowGUI::activate_timeline()
465 {
466         if(pane[focused_pane])
467         {
468                 pane[focused_pane]->activate();
469         }
470         else
471         {
472                 for(int i = 0; i < TOTAL_PANES; i++)
473                 {
474                         if(pane[i])
475                         {
476                                 pane[i]->activate();
477                                 return;
478                         }
479                 }
480         }
481 }
482
483 void MWindowGUI::deactivate_timeline()
484 {
485         for(int i = 0; i < TOTAL_PANES; i++)
486         {
487                 if(pane[i])
488                 {
489                         pane[i]->canvas->deactivate();
490                 }
491         }
492 }
493
494 void MWindowGUI::update_title(char *path)
495 {
496         FileSystem fs;
497         char filename[BCTEXTLEN], string[BCTEXTLEN];
498         fs.extract_name(filename, path);
499         sprintf(string, _(PROGRAM_NAME ": %s"), filename);
500         set_title(string);
501 //printf("MWindowGUI::update_title %s\n", string);
502         flush();
503 }
504
505 void MWindowGUI::draw_overlays(int flash_it)
506 {
507         for(int i = 0; i < TOTAL_PANES; i++)
508         {
509                 if(pane[i])
510                 {
511                         pane[i]->canvas->draw_overlays();
512                         if(flash_it) pane[i]->canvas->flash();
513                 }
514         }
515 }
516
517 void MWindowGUI::update_timebar(int flush_it)
518 {
519         for(int i = 0; i < TOTAL_PANES; i++)
520         {
521                 if(pane[i] && pane[i]->timebar)
522                 {
523                         pane[i]->timebar->update(flush_it);
524                 }
525         }
526 }
527
528 void MWindowGUI::update_timebar_highlights()
529 {
530         for(int i = 0; i < TOTAL_PANES; i++)
531         {
532                 if(pane[i] && pane[i]->timebar)
533                 {
534                         pane[i]->timebar->update_highlights();
535                 }
536         }
537 }
538
539
540 void MWindowGUI::update_patchbay()
541 {
542         for(int i = 0; i < TOTAL_PANES; i++)
543         {
544                 if(pane[i] && pane[i]->patchbay)
545                 {
546                         pane[i]->patchbay->update();
547                 }
548         }
549 }
550
551 void MWindowGUI::update_proxy_toggle()
552 {
553         int value = mwindow->edl->session->proxy_scale == 1 ? 1 : 0;
554         proxy_toggle->set_value(value);
555         if( mwindow->edl->session->proxy_scale == 1 &&
556             mwindow->edl->session->proxy_disabled_scale == 1 )
557                 proxy_toggle->hide();
558         else
559                 proxy_toggle->show();
560 }
561
562 void MWindowGUI::update_plugintoggles()
563 {
564         for(int i = 0; i < TOTAL_PANES; i++)
565         {
566                 if(pane[i])
567                 {
568                         pane[i]->canvas->refresh_plugintoggles();
569                 }
570         }
571
572 }
573
574 void MWindowGUI::draw_indexes(Indexable *indexable)
575 {
576         for(int i = 0; i < TOTAL_PANES; i++)
577         {
578                 if(pane[i])
579                 {
580                         pane[i]->canvas->draw_indexes(indexable);
581                 }
582         }
583 }
584
585 void MWindowGUI::draw_canvas(int redraw, int hide_cursor)
586 {
587         resource_thread->stop_draw(0);
588
589         int mode = redraw ? FORCE_REDRAW : NORMAL_DRAW;
590         for(int i = 0; i < TOTAL_PANES; i++) {
591                 if( pane[i] )
592                         pane[i]->canvas->draw(mode, hide_cursor);
593         }
594
595         resource_thread->start_draw();
596 }
597
598 void MWindowGUI::flash_canvas(int flush)
599 {
600         for(int i = 0; i < TOTAL_PANES; i++)
601         {
602                 if(pane[i])
603                 {
604                         pane[i]->canvas->flash(flush);
605                 }
606         }
607 }
608
609 int MWindowGUI::show_window(int flush)
610 {
611         int ret = BC_WindowBase::show_window(flush);
612         update_proxy_toggle();
613         return ret;
614 }
615
616 void MWindowGUI::draw_cursor(int do_plugintoggles)
617 {
618         for(int i = 0; i < TOTAL_PANES; i++)
619         {
620                 if(pane[i])
621                 {
622                         pane[i]->cursor->draw(do_plugintoggles);
623                 }
624         }
625 }
626
627 void MWindowGUI::show_cursor(int do_plugintoggles)
628 {
629         for(int i = 0; i < TOTAL_PANES; i++)
630         {
631                 if(pane[i])
632                 {
633                         pane[i]->cursor->show(do_plugintoggles);
634                 }
635         }
636 }
637
638 void MWindowGUI::hide_cursor(int do_plugintoggles)
639 {
640         for(int i = 0; i < TOTAL_PANES; i++)
641         {
642                 if(pane[i])
643                 {
644                         pane[i]->cursor->hide(do_plugintoggles);
645                 }
646         }
647 }
648
649 void MWindowGUI::update_cursor()
650 {
651         for(int i = 0; i < TOTAL_PANES; i++)
652         {
653                 if(pane[i])
654                 {
655                         pane[i]->cursor->update();
656                 }
657         }
658 }
659
660 void MWindowGUI::set_playing_back(int value)
661 {
662         for(int i = 0; i < TOTAL_PANES; i++)
663         {
664                 if(pane[i])
665                 {
666                         pane[i]->cursor->playing_back = value;
667                 }
668         }
669 }
670
671 void MWindowGUI::update_scrollbars(int flush)
672 {
673         for(int i = 0; i < TOTAL_PANES; i++)
674         {
675                 if(pane[i])
676                 {
677                         pane[i]->update(1, NO_DRAW, 0, 0);
678                 }
679         }
680         if(flush) this->flush();
681 }
682
683 void MWindowGUI::reset_meters()
684 {
685         for(int i = 0; i < TOTAL_PANES; i++)
686         {
687                 if(pane[i] && pane[i]->patchbay)
688                 {
689                         pane[i]->patchbay->reset_meters();
690                 }
691         }
692 }
693
694 void MWindowGUI::stop_meters()
695 {
696         for(int i = 0; i < TOTAL_PANES; i++)
697         {
698                 if(pane[i] && pane[i]->patchbay)
699                 {
700                         pane[i]->patchbay->stop_meters();
701                 }
702         }
703 }
704
705 void MWindowGUI::update_meters(ArrayList<double> *module_levels)
706 {
707         for(int i = 0; i < TOTAL_PANES; i++)
708         {
709                 if(pane[i] && pane[i]->patchbay)
710                 {
711                         pane[i]->patchbay->update_meters(module_levels);
712                 }
713         }
714 }
715
716 void MWindowGUI::set_editing_mode(int flush)
717 {
718         for(int i = 0; i < TOTAL_PANES; i++)
719         {
720                 if(pane[i])
721                 {
722                         pane[i]->canvas->update_cursor(flush);
723                 }
724         }
725 }
726
727 void MWindowGUI::set_meter_format(int mode, int min, int max)
728 {
729         for(int i = 0; i < TOTAL_PANES; i++)
730         {
731                 if(pane[i] && pane[i]->patchbay)
732                 {
733                         pane[i]->patchbay->set_meter_format(mode, min, max);
734                 }
735         }
736 }
737
738 void MWindowGUI::update(int scrollbars,
739         int do_canvas,
740         int timebar,
741         int zoombar,
742         int patchbay,
743         int clock,
744         int buttonbar)
745 {
746         const int debug = 0;
747         if(debug) PRINT_TRACE
748
749
750
751         mwindow->edl->tracks->update_y_pixels(mwindow->theme);
752
753         if( do_canvas != NO_DRAW && do_canvas != IGNORE_THREAD )
754                 resource_thread->stop_draw(1);
755
756         for(int i = 0; i < TOTAL_PANES; i++)
757         {
758                 if(pane[i]) pane[i]->update(scrollbars,
759                         do_canvas,
760                         timebar,
761                         patchbay);
762         }
763
764         if( do_canvas != NO_DRAW && do_canvas != IGNORE_THREAD )
765                 resource_thread->start_draw();
766
767 //      if(scrollbars) this->get_scrollbars(0);
768 //      if(timebar) this->timebar->update(0);
769         if(zoombar) this->zoombar->update();
770 //      if(patchbay) this->patchbay->update();
771         if(clock) this->mainclock->update(
772                 mwindow->edl->local_session->get_selectionstart(1));
773         if(debug) PRINT_TRACE
774
775
776
777 //      if(do_canvas)
778 //      {
779 //              this->canvas->draw(do_canvas);
780 //              this->cursor->show();
781 //              this->canvas->flash(0);
782 // Activate causes the menubar to deactivate.  Don't want this for
783 // picon thread.
784 //              if(canvas != IGNORE_THREAD) this->canvas->activate();
785 //      }
786         if(debug) PRINT_TRACE
787
788
789
790         if(buttonbar) mbuttons->update();
791         if(debug) PRINT_TRACE
792
793 // Can't age if the cache called this to draw missing picons
794 // or the GUI is updating the status of the draw toggle.
795         if( do_canvas != FORCE_REDRAW && do_canvas != IGNORE_THREAD ) {
796                 unlock_window();
797                 mwindow->age_caches();
798                 lock_window("MWindowGUI::update");
799         }
800
801         flush();
802         if(debug) PRINT_TRACE
803 }
804
805 int MWindowGUI::visible(int64_t x1, int64_t x2, int64_t view_x1, int64_t view_x2)
806 {
807         return (x1 >= view_x1 && x1 < view_x2) ||
808                 (x2 > view_x1 && x2 <= view_x2) ||
809                 (x1 <= view_x1 && x2 >= view_x2);
810 }
811
812
813 void MWindowGUI::show_message(const char *message, int msg_color, int bar_color)
814 {
815         statusbar->show_message(message, msg_color, bar_color);
816 }
817
818 void MWindowGUI::update_default_message()
819 {
820         statusbar->update_default_message();
821 }
822
823 void MWindowGUI::reset_default_message()
824 {
825         statusbar->reset_default_message();
826 }
827
828 void MWindowGUI::default_message()
829 {
830         statusbar->default_message();
831 }
832
833 // Drag motion called from other window
834 int MWindowGUI::drag_motion()
835 {
836         if(get_hidden()) return 0;
837
838         Track *over_track = 0;
839         Edit *over_edit = 0;
840         PluginSet *over_pluginset = 0;
841         Plugin *over_plugin = 0;
842         int redraw = 0;
843
844         if(drag_popup)
845         {
846                 drag_popup->cursor_motion_event();
847         }
848
849
850 // there's no point in drawing highlights has until drag operation has been set
851         if (!mwindow->session->current_operation)
852                 return 0;
853
854         for(int i = 0; i < TOTAL_PANES; i++)
855         {
856                 if(pane[i]) pane[i]->canvas->drag_motion(
857                         &over_track,
858                         &over_edit,
859                         &over_pluginset,
860                         &over_plugin);
861         }
862
863         if(mwindow->session->track_highlighted != over_track)
864         {
865                 mwindow->session->track_highlighted = over_track;
866                 redraw = 1;
867         }
868
869         if(mwindow->session->edit_highlighted != over_edit)
870         {
871                 mwindow->session->edit_highlighted = over_edit;
872                 redraw = 1;
873         }
874
875         if(mwindow->session->pluginset_highlighted != over_pluginset)
876         {
877                 mwindow->session->pluginset_highlighted = over_pluginset;
878                 redraw = 1;
879         }
880
881         if(mwindow->session->plugin_highlighted != over_plugin)
882         {
883                 mwindow->session->plugin_highlighted = over_plugin;
884                 redraw = 1;
885         }
886
887         if( mwindow->session->current_operation == DRAG_ASSET ||
888             mwindow->session->current_operation == DRAG_EDIT ||
889             mwindow->session->current_operation == DRAG_GROUP ||
890             mwindow->session->current_operation == DRAG_AEFFECT_COPY ||
891             mwindow->session->current_operation == DRAG_VEFFECT_COPY ) {
892                 redraw = 1;
893         }
894
895
896 // printf("drag_motion %d %d over_track=%p over_edit=%p\n",
897 // __LINE__,
898 // redraw,
899 // over_track,
900 // over_edit);
901         if(redraw)
902         {
903                 lock_window("MWindowGUI::drag_motion");
904                 draw_overlays(1);
905                 unlock_window();
906         }
907         return 0;
908 }
909
910 int MWindowGUI::drag_stop()
911 {
912         if(get_hidden()) return 0;
913         int result = 0, redraw = 0;
914
915         for(int i = 0; i < TOTAL_PANES; i++)
916         {
917                 if(pane[i]) result |= pane[i]->canvas->drag_stop(
918                         &redraw);
919         }
920         mwindow->edl->optimize();
921
922 // since we don't have subwindows we have to terminate any drag operation
923         if(result)
924         {
925                 if (mwindow->session->track_highlighted
926                         || mwindow->session->edit_highlighted
927                         || mwindow->session->plugin_highlighted
928                         || mwindow->session->pluginset_highlighted)
929                         redraw = 1;
930                 mwindow->session->track_highlighted = 0;
931                 mwindow->session->edit_highlighted = 0;
932                 mwindow->session->plugin_highlighted = 0;
933                 mwindow->session->pluginset_highlighted = 0;
934                 mwindow->session->current_operation = NO_OPERATION;
935         }
936
937
938 //printf("MWindowGUI::drag_stop %d %d\n", redraw, mwindow->session->current_operation);
939         if(redraw)
940         {
941                 mwindow->edl->tracks->update_y_pixels(mwindow->theme);
942                 update_scrollbars(0);
943                 update_patchbay();
944                 draw_canvas(1, 1);
945                 update_cursor();
946                 flash_canvas(1);
947         }
948
949         if(drag_popup)
950         {
951                 delete drag_popup;
952                 drag_popup = 0;
953         }
954         return result;
955 }
956
957 void MWindowGUI::default_positions()
958 {
959 //printf("MWindowGUI::default_positions 1\n");
960         VWindow *vwindow = mwindow->vwindows.size() > DEFAULT_VWINDOW ?
961                 mwindow->vwindows.get(DEFAULT_VWINDOW) : 0;
962         if( vwindow && !vwindow->is_running() ) vwindow = 0;
963         if( vwindow ) vwindow->gui->lock_window("MWindowGUI::default_positions");
964         mwindow->cwindow->gui->lock_window("MWindowGUI::default_positions");
965         mwindow->awindow->gui->lock_window("MWindowGUI::default_positions");
966
967 // printf("MWindowGUI::default_positions 1 %d %d %d %d\n", mwindow->session->vwindow_x,
968 // mwindow->session->vwindow_y,
969 // mwindow->session->vwindow_w,
970 // mwindow->session->vwindow_h);
971         reposition_window(mwindow->session->mwindow_x,
972                 mwindow->session->mwindow_y,
973                 mwindow->session->mwindow_w,
974                 mwindow->session->mwindow_h);
975         if( vwindow ) vwindow->gui->reposition_window(mwindow->session->vwindow_x,
976                 mwindow->session->vwindow_y,
977                 mwindow->session->vwindow_w,
978                 mwindow->session->vwindow_h);
979         mwindow->cwindow->gui->reposition_window(mwindow->session->cwindow_x,
980                 mwindow->session->cwindow_y,
981                 mwindow->session->cwindow_w,
982                 mwindow->session->cwindow_h);
983         mwindow->awindow->gui->reposition_window(mwindow->session->awindow_x,
984                 mwindow->session->awindow_y,
985                 mwindow->session->awindow_w,
986                 mwindow->session->awindow_h);
987 //printf("MWindowGUI::default_positions 1\n");
988
989         resize_event(mwindow->session->mwindow_w,
990                 mwindow->session->mwindow_h);
991 //printf("MWindowGUI::default_positions 1\n");
992         if( vwindow ) vwindow->gui->resize_event(mwindow->session->vwindow_w,
993                 mwindow->session->vwindow_h);
994 //printf("MWindowGUI::default_positions 1\n");
995         mwindow->cwindow->gui->resize_event(mwindow->session->cwindow_w,
996                 mwindow->session->cwindow_h);
997 //printf("MWindowGUI::default_positions 1\n");
998         mwindow->awindow->gui->resize_event(mwindow->session->awindow_w,
999                 mwindow->session->awindow_h);
1000
1001 //printf("MWindowGUI::default_positions 1\n");
1002
1003         flush();
1004         if( vwindow ) vwindow->gui->flush();
1005         mwindow->cwindow->gui->flush();
1006         mwindow->awindow->gui->flush();
1007
1008         if( vwindow ) vwindow->gui->unlock_window();
1009         mwindow->cwindow->gui->unlock_window();
1010         mwindow->awindow->gui->unlock_window();
1011 //printf("MWindowGUI::default_positions 2\n");
1012 }
1013
1014
1015 int MWindowGUI::repeat_event(int64_t duration)
1016 {
1017 // if(duration == 100)
1018 // mwindow->sync_parameters(CHANGE_ALL);
1019         int result = 0;
1020         for(int i = 0; i < TOTAL_PANES; i++)
1021         {
1022                 if(pane[i]) result = pane[i]->cursor->repeat_event(duration);
1023         }
1024         return result;
1025 }
1026
1027
1028 int MWindowGUI::translation_event()
1029 {
1030 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
1031         mwindow->session->mwindow_x = get_x();
1032         mwindow->session->mwindow_y = get_y();
1033         return 0;
1034 }
1035
1036
1037 int MWindowGUI::save_defaults(BC_Hash *defaults)
1038 {
1039         defaults->update("MWINDOWWIDTH", get_w());
1040         defaults->update("MWINDOWHEIGHT", get_h());
1041         mainmenu->save_defaults(defaults);
1042         BC_WindowBase::save_defaults(defaults);
1043         return 0;
1044 }
1045
1046 int MWindowGUI::keypress_event()
1047 {
1048 //printf("MWindowGUI::keypress_event 1 %d\n", get_keypress());
1049         int result = mbuttons->keypress_event();
1050         if( result ) return result;
1051
1052         Track *this_track = 0, *first_track = 0;
1053         int collapse = 0, packed = 0, overwrite = 0, plugins = 0;
1054         double position = 0;
1055
1056         switch( get_keypress() ) {
1057         case 'A':
1058                 if( !ctrl_down() || !shift_down() || alt_down() ) break;
1059                 mwindow->edl->tracks->clear_selected_edits();
1060                 draw_overlays(1);
1061                 result = 1;
1062                 break;
1063         case 'e':
1064                 mwindow->toggle_editing_mode();
1065                 result = 1;
1066                 break;
1067
1068         case 'k': case 'K':
1069                 if( alt_down() ) break;
1070                 stop_transport("MWindowGUI::keypress_event 1");
1071                 mwindow->nearest_plugin_keyframe(shift_down(),
1072                         !ctrl_down() ? PLAY_FORWARD : PLAY_REVERSE);
1073                 result = 1;
1074                 break;
1075
1076         case 'C':
1077                 packed = 1;
1078         case 'c':
1079                 if( !ctrl_down() || alt_down() ) break;
1080                 mwindow->selected_edits_to_clipboard(packed);
1081                 result = 1;
1082                 break;
1083         case 'P':
1084                 plugins = 1;
1085         case 'b':
1086                 overwrite = -1; // fall thru
1087         case 'v':
1088                 if( !ctrl_down() || alt_down() ) break;
1089                 if( mwindow->session->current_operation == DROP_TARGETING ) {
1090                         mwindow->session->current_operation = NO_OPERATION;
1091                         mwindow->gui->set_editing_mode(1);
1092                         int pane_no = 0;
1093                         for( ; pane_no<TOTAL_PANES; ++pane_no  ) {
1094                                 if( !pane[pane_no] ) continue;
1095                                 first_track = pane[pane_no]->over_track();
1096                                 if( first_track ) break;
1097                         }
1098                         if( first_track ) {
1099                                 int cursor_x = pane[pane_no]->canvas->get_relative_cursor_x();
1100                                 position = mwindow->edl->get_cursor_position(cursor_x, pane_no);
1101                         }
1102                 }
1103                 else
1104                         position = mwindow->edl->local_session->get_selectionstart();
1105                 if( !plugins )
1106                         mwindow->paste(position, first_track, 0, overwrite);
1107                 else
1108                         mwindow->paste_clipboard(first_track, position, 1, 0, 1, 1, 1);
1109                 mwindow->edl->tracks->clear_selected_edits();
1110                 draw_overlays(1);
1111                 result = 1;
1112                 break;
1113         case 'M':
1114                 collapse = 1;
1115         case BACKSPACE:
1116         case 'm':
1117                 mwindow->cut_selected_edits(0, collapse);
1118                 result = 1;
1119                 break;
1120         case 'z':
1121                 collapse = 1;
1122         case 'x':
1123                 if( !ctrl_down() || alt_down() ) break;
1124                 mwindow->cut_selected_edits(1, collapse);
1125                 result = 1;
1126                 break;
1127
1128         case '1' ... '8':
1129                 if( !alt_down() || shift_down() ) break;
1130                 if( !mwindow->select_asset(get_keypress()-'1',1) )
1131                         result = 1;
1132                 break;
1133
1134         case LEFT:
1135                 if( !ctrl_down() ) {
1136                         if( alt_down() ) {
1137                                 stop_transport("MWindowGUI::keypress_event 1");
1138                                 mwindow->prev_edit_handle(shift_down());
1139                         }
1140                         else
1141                                 mwindow->move_left();
1142                         result = 1;
1143                 }
1144                 break;
1145
1146         case ',':
1147                 if( !ctrl_down() && !alt_down() ) {
1148                         mwindow->move_left();
1149                         result = 1;
1150                 }
1151                 break;
1152
1153         case RIGHT:
1154                 if( !ctrl_down() ) {
1155                         if( alt_down() ) {
1156                                 stop_transport("MWindowGUI::keypress_event 2");
1157                                 mwindow->next_edit_handle(shift_down());
1158                         }
1159                         else
1160                                 mwindow->move_right();
1161                         result = 1;
1162                 }
1163                 break;
1164
1165         case '.':
1166                 if( !ctrl_down() && !alt_down() ) {
1167                         mwindow->move_right();
1168                         result = 1;
1169                 }
1170                 break;
1171
1172         case UP:
1173                 if( ctrl_down() && !alt_down() )
1174                         mwindow->expand_y();
1175                 else if( !ctrl_down() && alt_down() )
1176                         mwindow->expand_autos(0,1,1);
1177                 else if( ctrl_down() && alt_down() )
1178                         mwindow->expand_autos(1,1,1);
1179                 else
1180                         mwindow->expand_sample();
1181                 result = 1;
1182                 break;
1183
1184         case DOWN:
1185                 if( ctrl_down() && !alt_down() )
1186                         mwindow->zoom_in_y();
1187                 else if( !ctrl_down() && alt_down() )
1188                         mwindow->shrink_autos(0,1,1);
1189                 else if( ctrl_down() && alt_down() )
1190                         mwindow->shrink_autos(1,1,1);
1191                 else
1192                         mwindow->zoom_in_sample();
1193                 result = 1;
1194                 break;
1195
1196         case PGUP:
1197                 if( !ctrl_down() )
1198                         mwindow->move_up();
1199                 else
1200                         mwindow->expand_t();
1201                 result = 1;
1202                 break;
1203
1204         case PGDN:
1205                 if( !ctrl_down() )
1206                         mwindow->move_down();
1207                 else
1208                         mwindow->zoom_in_t();
1209                 result = 1;
1210                 break;
1211
1212         case TAB:
1213         case LEFTTAB:
1214                 for( int i=0; i<TOTAL_PANES; ++i ) {
1215                         if( !pane[i] ) continue;
1216                         if( (this_track = pane[i]->over_track()) != 0 ) break;
1217                         if( (this_track = pane[i]->over_patchbay()) != 0 ) break;
1218                 }
1219
1220                 if( get_keypress() == TAB ) { // Switch the record button
1221                         if( this_track )
1222                                 this_track->record = !this_track->record ? 1 : 0;
1223                 }
1224                 else {
1225                         int total_selected = mwindow->edl->tracks->total_of(Tracks::RECORD);
1226                         // all selected if nothing previously selected or
1227                         // if this patch was previously the only one selected and armed
1228                         int selected = !total_selected || (total_selected == 1 &&
1229                                 this_track && this_track->record ) ? 1 : 0;
1230                         mwindow->edl->tracks->select_all(Tracks::RECORD, selected);
1231                         if( !selected && this_track ) this_track->record = 1;
1232                 }
1233
1234                 update(0, NORMAL_DRAW, 0, 0, 1, 0, 1);
1235                 unlock_window();
1236                 mwindow->cwindow->update(0, 1, 1);
1237                 lock_window("MWindowGUI::keypress_event 3");
1238
1239                 result = 1;
1240                 break;
1241
1242         case KEY_F1 ... KEY_F12:
1243                 resend_event(mwindow->cwindow->gui);
1244                 return 1;
1245         }
1246
1247 // since things under cursor have changed...
1248         if(result)
1249                 cursor_motion_event();
1250
1251         return result;
1252 }
1253
1254 int MWindowGUI::keyboard_listener(BC_WindowBase *wp)
1255 {
1256         return key_listener(wp->get_keypress());
1257 }
1258
1259 int MWindowGUI::key_listener(int key)
1260 {
1261         int result = 1;
1262         switch( key ) {
1263         case KPTV:
1264                 if( !record->running() )
1265                         record->start();
1266                 else
1267                         record->record_gui->interrupt_thread->start(0);
1268                 break;
1269         case KPHAND:
1270                 mwindow->quit();
1271                 break;
1272 #ifdef HAVE_DVB
1273         case KPBOOK:
1274                 channel_info->toggle_scan();
1275                 break;
1276 #endif
1277         case KPMENU:
1278                 if( !remote_control->deactivate() )
1279                         remote_control->activate();
1280                 break;
1281         default:
1282                 result = 0;
1283                 break;
1284         }
1285         return result;
1286 }
1287
1288
1289 void MWindowGUI::use_android_remote(int on)
1290 {
1291         if( !on ) {
1292                 delete android_control;
1293                 android_control = 0;
1294                 return;
1295         }
1296         if( android_control ) return;
1297         android_control = new AndroidControl(this);
1298 }
1299
1300 int MWindowGUI::close_event()
1301 {
1302         mainmenu->quit();
1303         return 0;
1304 }
1305
1306 void MWindowGUI::stop_drawing()
1307 {
1308         resource_thread->stop_draw(1);
1309 }
1310
1311 int MWindowGUI::menu_w()
1312 {
1313         return mainmenu->get_w();
1314 }
1315
1316 int MWindowGUI::menu_h()
1317 {
1318         return mainmenu->get_h();
1319 }
1320
1321 void MWindowGUI::start_x_pane_drag()
1322 {
1323         if(!x_pane_drag)
1324         {
1325                 x_pane_drag = new BC_Popup(this,
1326                         get_abs_cursor_x(0) - mwindow->theme->pane_w,
1327                         BC_DisplayInfo::get_top_border() +
1328                                 get_y() +
1329                                 mwindow->theme->mcanvas_y,
1330                         mwindow->theme->pane_w,
1331                         mwindow->theme->mcanvas_h,
1332                         mwindow->theme->drag_pane_color);
1333                 x_pane_drag->draw_3segmentv(0,
1334                         0,
1335                         x_pane_drag->get_h(),
1336                         mwindow->theme->get_image_set("xpane")[BUTTON_DOWNHI]);
1337                 x_pane_drag->flash(1);
1338         }
1339         dragging_pane = 1;
1340 }
1341
1342 void MWindowGUI::start_y_pane_drag()
1343 {
1344         if(!y_pane_drag)
1345         {
1346 //printf("MWindowGUI::start_y_pane_drag %d %d %d\n", __LINE__, get_x(), get_y());
1347                 y_pane_drag = new BC_Popup(this,
1348                         BC_DisplayInfo::get_left_border() +
1349                                 get_x() +
1350                                 mwindow->theme->mcanvas_x,
1351                         get_abs_cursor_y(0) - mwindow->theme->pane_h,
1352                         mwindow->theme->mcanvas_w,
1353                         mwindow->theme->pane_h,
1354                         mwindow->theme->drag_pane_color);
1355                 y_pane_drag->draw_3segmenth(0,
1356                         0,
1357                         y_pane_drag->get_w(),
1358                         mwindow->theme->get_image_set("ypane")[BUTTON_DOWNHI]);
1359                 y_pane_drag->flash(1);
1360         }
1361         dragging_pane = 1;
1362 }
1363
1364 void MWindowGUI::handle_pane_drag()
1365 {
1366         if(dragging_pane)
1367         {
1368                 if(x_pane_drag)
1369                 {
1370                         x_pane_drag->reposition_window(
1371                                 get_abs_cursor_x(0) - mwindow->theme->pane_w,
1372                                 x_pane_drag->get_y());
1373                 }
1374
1375                 if(y_pane_drag)
1376                 {
1377                         y_pane_drag->reposition_window(
1378                                 y_pane_drag->get_x(),
1379                                 get_abs_cursor_y(0) - mwindow->theme->pane_h);
1380                 }
1381         }
1382 }
1383
1384
1385 void MWindowGUI::create_x_pane(int cursor_x)
1386 {
1387         if(total_panes() == 1)
1388         {
1389 // create a horizontal pane
1390 // do this 1st so the resize_event knows there are 2 panes
1391                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] =
1392                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] +
1393                         cursor_x -
1394                         mwindow->theme->patchbay_w;
1395                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1396                         TOP_RIGHT_PANE,
1397                         mwindow->theme->mcanvas_x +
1398                                 cursor_x,
1399                         mwindow->theme->mcanvas_y,
1400                         mwindow->theme->mcanvas_x +
1401                                 mwindow->theme->mcanvas_w -
1402                                 cursor_x,
1403                         mwindow->theme->mcanvas_h);
1404                 pane[TOP_LEFT_PANE]->resize_event(
1405                         mwindow->theme->mcanvas_x,
1406                         mwindow->theme->mcanvas_y,
1407                         cursor_x - mwindow->theme->pane_w,
1408                         mwindow->theme->mcanvas_h);
1409                 pane[TOP_RIGHT_PANE]->create_objects();
1410         }
1411         else
1412         if(vertical_panes())
1413         {
1414 // create 2 horizontal panes
1415                 mwindow->edl->local_session->track_start[TOP_RIGHT_PANE] =
1416                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE];
1417                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1418                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE];
1419                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] =
1420                         mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1421                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] +
1422                         cursor_x -
1423                         mwindow->theme->patchbay_w;
1424                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1425                         TOP_RIGHT_PANE,
1426                         mwindow->theme->mcanvas_x +
1427                                 cursor_x,
1428                         pane[TOP_LEFT_PANE]->y,
1429                         mwindow->theme->mcanvas_x +
1430                                 mwindow->theme->mcanvas_w -
1431                                 cursor_x,
1432                         pane[TOP_LEFT_PANE]->h);
1433                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1434                         BOTTOM_RIGHT_PANE,
1435                         mwindow->theme->mcanvas_x +
1436                                 cursor_x,
1437                         pane[BOTTOM_LEFT_PANE]->y,
1438                         mwindow->theme->mcanvas_x +
1439                                 mwindow->theme->mcanvas_w -
1440                                 cursor_x,
1441                         pane[BOTTOM_LEFT_PANE]->h);
1442                 pane[TOP_LEFT_PANE]->resize_event(
1443                         pane[TOP_LEFT_PANE]->x,
1444                         pane[TOP_LEFT_PANE]->y,
1445                         cursor_x - mwindow->theme->pane_w,
1446                         pane[TOP_LEFT_PANE]->h);
1447                 pane[BOTTOM_LEFT_PANE]->resize_event(
1448                         pane[BOTTOM_LEFT_PANE]->x,
1449                         pane[BOTTOM_LEFT_PANE]->y,
1450                         cursor_x - mwindow->theme->pane_w,
1451                         pane[BOTTOM_LEFT_PANE]->h);
1452                 pane[TOP_RIGHT_PANE]->create_objects();
1453                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1454         }
1455         else
1456         if(horizontal_panes())
1457         {
1458 // resize a horizontal pane
1459                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] +=
1460                         cursor_x -
1461                         pane[TOP_RIGHT_PANE]->x;
1462                 if(mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] < 0)
1463                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] = 0;
1464                 pane[TOP_LEFT_PANE]->resize_event(
1465                         mwindow->theme->mcanvas_x,
1466                         mwindow->theme->mcanvas_y,
1467                         cursor_x - mwindow->theme->pane_w,
1468                         mwindow->theme->mcanvas_h);
1469                 pane[TOP_RIGHT_PANE]->resize_event(
1470                         mwindow->theme->mcanvas_x +
1471                                 cursor_x,
1472                         pane[TOP_RIGHT_PANE]->y,
1473                         mwindow->theme->mcanvas_x +
1474                                 mwindow->theme->mcanvas_w -
1475                                 cursor_x,
1476                         mwindow->theme->mcanvas_h);
1477         }
1478         else
1479         {
1480 // resize 2 horizontal panes
1481                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] +=
1482                         cursor_x -
1483                         pane[TOP_RIGHT_PANE]->x;
1484                 if(mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] < 0)
1485                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] = 0;
1486                 mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1487                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE];
1488
1489                 pane[TOP_LEFT_PANE]->resize_event(
1490                         mwindow->theme->mcanvas_x,
1491                         pane[TOP_LEFT_PANE]->y,
1492                         cursor_x - mwindow->theme->pane_w,
1493                         pane[TOP_LEFT_PANE]->h);
1494                 pane[TOP_RIGHT_PANE]->resize_event(
1495                         mwindow->theme->mcanvas_x +
1496                                 cursor_x,
1497                         pane[TOP_RIGHT_PANE]->y,
1498                         mwindow->theme->mcanvas_x +
1499                                 mwindow->theme->mcanvas_w -
1500                                 cursor_x,
1501                         pane[TOP_RIGHT_PANE]->h);
1502                 pane[BOTTOM_LEFT_PANE]->resize_event(
1503                         mwindow->theme->mcanvas_x,
1504                         pane[BOTTOM_LEFT_PANE]->y,
1505                         cursor_x - mwindow->theme->pane_w,
1506                         pane[BOTTOM_LEFT_PANE]->h);
1507                 pane[BOTTOM_RIGHT_PANE]->resize_event(
1508                         mwindow->theme->mcanvas_x +
1509                                 cursor_x,
1510                         pane[BOTTOM_RIGHT_PANE]->y,
1511                         mwindow->theme->mcanvas_x +
1512                                 mwindow->theme->mcanvas_w -
1513                                 cursor_x,
1514                         pane[BOTTOM_RIGHT_PANE]->h);
1515
1516         }
1517 }
1518
1519
1520 void MWindowGUI::delete_x_pane(int cursor_x)
1521 {
1522 // give left panes coordinates of right pane
1523         if(cursor_x < mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1524                 pane[TOP_RIGHT_PANE])
1525         {
1526                 mwindow->edl->local_session->view_start[TOP_LEFT_PANE] =
1527                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] -
1528                         pane[TOP_RIGHT_PANE]->x + mwindow->theme->patchbay_w;
1529                 if(mwindow->edl->local_session->view_start[TOP_LEFT_PANE] < 0)
1530                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] = 0;
1531                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1532                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1533         }
1534
1535         switch(total_panes())
1536         {
1537                 case 2:
1538                         if(pane[TOP_LEFT_PANE] && pane[TOP_RIGHT_PANE])
1539                         {
1540 // delete right pane
1541                                 delete pane[TOP_RIGHT_PANE];
1542                                 pane[TOP_RIGHT_PANE] = 0;
1543                                 pane[TOP_LEFT_PANE]->resize_event(
1544                                         mwindow->theme->mcanvas_x,
1545                                         mwindow->theme->mcanvas_y,
1546                                         mwindow->theme->mcanvas_w,
1547                                         mwindow->theme->mcanvas_h);
1548
1549                         }
1550                         break;
1551
1552                 case 4:
1553 // delete right panes
1554                         delete pane[TOP_RIGHT_PANE];
1555                         pane[TOP_RIGHT_PANE] = 0;
1556                         delete pane[BOTTOM_RIGHT_PANE];
1557                         pane[BOTTOM_RIGHT_PANE] = 0;
1558                         pane[TOP_LEFT_PANE]->resize_event(
1559                                 mwindow->theme->mcanvas_x,
1560                                 pane[TOP_LEFT_PANE]->y,
1561                                 mwindow->theme->mcanvas_w,
1562                                 pane[TOP_LEFT_PANE]->h);
1563                         pane[BOTTOM_LEFT_PANE]->resize_event(
1564                                 mwindow->theme->mcanvas_x,
1565                                 pane[BOTTOM_LEFT_PANE]->y,
1566                                 mwindow->theme->mcanvas_w,
1567                                 pane[BOTTOM_LEFT_PANE]->h);
1568                         break;
1569         }
1570 }
1571
1572 void MWindowGUI::create_y_pane(int cursor_y)
1573 {
1574         if(total_panes() == 1)
1575         {
1576                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1577                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1578                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] =
1579                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] +
1580                         cursor_y -
1581                         mwindow->theme->mtimebar_h;
1582 // do this 1st so the resize_event knows there are 2 panes
1583                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1584                         BOTTOM_LEFT_PANE,
1585                         mwindow->theme->mcanvas_x,
1586                         mwindow->theme->mcanvas_y +
1587                                 cursor_y,
1588                         mwindow->theme->mcanvas_w,
1589                         mwindow->theme->mcanvas_h -
1590                                 cursor_y);
1591                 pane[TOP_LEFT_PANE]->resize_event(
1592                         mwindow->theme->mcanvas_x,
1593                         mwindow->theme->mcanvas_y,
1594                         mwindow->theme->mcanvas_w,
1595                         pane[BOTTOM_LEFT_PANE]->y -
1596                                 mwindow->theme->mcanvas_y -
1597                                 mwindow->theme->pane_h);
1598                 pane[BOTTOM_LEFT_PANE]->create_objects();
1599         }
1600         else
1601         if(horizontal_panes())
1602         {
1603 // create 2 panes
1604                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1605                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1606                 mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1607                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE];
1608                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] =
1609                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1610                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] +
1611                         cursor_y -
1612                         mwindow->theme->mtimebar_h;
1613
1614                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1615                         BOTTOM_LEFT_PANE,
1616                         pane[TOP_LEFT_PANE]->x,
1617                         mwindow->theme->mcanvas_y +
1618                                 cursor_y,
1619                         pane[TOP_LEFT_PANE]->w,
1620                         mwindow->theme->mcanvas_h -
1621                                 cursor_y);
1622                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1623                         BOTTOM_RIGHT_PANE,
1624                         pane[TOP_RIGHT_PANE]->x,
1625                         mwindow->theme->mcanvas_y +
1626                                 cursor_y,
1627                         pane[TOP_RIGHT_PANE]->w,
1628                         mwindow->theme->mcanvas_h -
1629                                 cursor_y);
1630
1631                 pane[TOP_LEFT_PANE]->resize_event(
1632                         pane[TOP_LEFT_PANE]->x,
1633                         pane[TOP_LEFT_PANE]->y,
1634                         pane[TOP_LEFT_PANE]->w,
1635                         pane[BOTTOM_LEFT_PANE]->y -
1636                                 mwindow->theme->mcanvas_y -
1637                                 mwindow->theme->pane_h);
1638                 pane[TOP_RIGHT_PANE]->resize_event(
1639                         pane[TOP_RIGHT_PANE]->x,
1640                         pane[TOP_RIGHT_PANE]->y,
1641                         pane[TOP_RIGHT_PANE]->w,
1642                         pane[BOTTOM_RIGHT_PANE]->y -
1643                                 mwindow->theme->mcanvas_y -
1644                                 mwindow->theme->pane_h);
1645
1646                 pane[BOTTOM_LEFT_PANE]->create_objects();
1647                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1648         }
1649         else
1650         if(vertical_panes())
1651         {
1652 // resize a pane
1653                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] +=
1654                         cursor_y -
1655                         (pane[BOTTOM_LEFT_PANE]->y - mwindow->theme->mcanvas_y);
1656                 if(mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] < 0)
1657                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] = 0;
1658                 pane[TOP_LEFT_PANE]->resize_event(
1659                         mwindow->theme->mcanvas_x,
1660                         mwindow->theme->mcanvas_y,
1661                         mwindow->theme->mcanvas_w,
1662                         cursor_y - mwindow->theme->pane_h);
1663                 pane[BOTTOM_LEFT_PANE]->resize_event(
1664                         pane[BOTTOM_LEFT_PANE]->x,
1665                         cursor_y +
1666                                 mwindow->theme->mcanvas_y,
1667                         mwindow->theme->mcanvas_w,
1668                         mwindow->theme->mcanvas_h -
1669                                 cursor_y);
1670         }
1671         else
1672         {
1673 // resize 2 panes
1674                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] +=
1675                         cursor_y -
1676                         (pane[BOTTOM_LEFT_PANE]->y - mwindow->theme->mcanvas_y);
1677                 if(mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] < 0)
1678                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] = 0;
1679                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1680                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE];
1681                 pane[TOP_LEFT_PANE]->resize_event(
1682                         pane[TOP_LEFT_PANE]->x,
1683                         pane[TOP_LEFT_PANE]->y,
1684                         pane[TOP_LEFT_PANE]->w,
1685                         cursor_y - mwindow->theme->pane_h);
1686                 pane[BOTTOM_LEFT_PANE]->resize_event(
1687                         pane[BOTTOM_LEFT_PANE]->x,
1688                         cursor_y +
1689                                 mwindow->theme->mcanvas_y,
1690                         pane[BOTTOM_LEFT_PANE]->w,
1691                         mwindow->theme->mcanvas_h -
1692                                         cursor_y);
1693                 pane[TOP_RIGHT_PANE]->resize_event(
1694                         pane[TOP_RIGHT_PANE]->x,
1695                         pane[TOP_RIGHT_PANE]->y,
1696                         pane[TOP_RIGHT_PANE]->w,
1697                         cursor_y - mwindow->theme->pane_h);
1698                 pane[BOTTOM_RIGHT_PANE]->resize_event(
1699                         pane[BOTTOM_RIGHT_PANE]->x,
1700                         cursor_y +
1701                                 mwindow->theme->mcanvas_y,
1702                         pane[BOTTOM_RIGHT_PANE]->w,
1703                         mwindow->theme->mcanvas_h -
1704                                         cursor_y);
1705         }
1706 }
1707
1708 void MWindowGUI::delete_y_pane(int cursor_y)
1709 {
1710         if(cursor_y < mwindow->theme->mtimebar_h +
1711                 PANE_DRAG_MARGIN &&
1712                 pane[BOTTOM_LEFT_PANE])
1713         {
1714 // give top pane coordinates of bottom pane
1715                 mwindow->edl->local_session->track_start[TOP_LEFT_PANE] =
1716                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] -
1717                         pane[BOTTOM_LEFT_PANE]->y;
1718                 if(mwindow->edl->local_session->track_start[TOP_LEFT_PANE] < 0)
1719                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] = 0;
1720                 mwindow->edl->local_session->track_start[TOP_RIGHT_PANE] =
1721                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE];
1722         }
1723
1724 // delete a pane
1725         switch(total_panes())
1726         {
1727                 case 2:
1728                         delete pane[BOTTOM_LEFT_PANE];
1729                         pane[BOTTOM_LEFT_PANE] = 0;
1730                         pane[TOP_LEFT_PANE]->resize_event(
1731                                 mwindow->theme->mcanvas_x,
1732                                 mwindow->theme->mcanvas_y,
1733                                 mwindow->theme->mcanvas_w,
1734                                 mwindow->theme->mcanvas_h);
1735                         break;
1736
1737                 case 4:
1738 // delete bottom 2 panes
1739
1740                         delete pane[BOTTOM_LEFT_PANE];
1741                         pane[BOTTOM_LEFT_PANE] = 0;
1742                         delete pane[BOTTOM_RIGHT_PANE];
1743                         pane[BOTTOM_RIGHT_PANE] = 0;
1744                         pane[TOP_LEFT_PANE]->resize_event(
1745                                 pane[TOP_LEFT_PANE]->x,
1746                                 mwindow->theme->mcanvas_y,
1747                                 pane[TOP_LEFT_PANE]->w,
1748                                 mwindow->theme->mcanvas_h);
1749                         pane[TOP_RIGHT_PANE]->resize_event(
1750                                 pane[TOP_RIGHT_PANE]->x,
1751                                 mwindow->theme->mcanvas_y,
1752                                 pane[TOP_RIGHT_PANE]->w,
1753                                 mwindow->theme->mcanvas_h);
1754                         break;
1755         }
1756 }
1757
1758 void MWindowGUI::stop_pane_drag()
1759 {
1760         dragging_pane = 0;
1761         resource_thread->stop_draw(0);
1762
1763         if(x_pane_drag)
1764         {
1765 // cursor position relative to canvas
1766                 int cursor_x = x_pane_drag->get_x() -
1767                         get_x() -
1768                         BC_DisplayInfo::get_left_border() -
1769                         mwindow->theme->mcanvas_x +
1770                         mwindow->theme->pane_w;
1771                 delete x_pane_drag;
1772                 x_pane_drag = 0;
1773
1774
1775                 if(cursor_x >= mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1776                         cursor_x < mwindow->theme->mcanvas_w -
1777                                 BC_ScrollBar::get_span(SCROLL_VERT) -
1778                                 PANE_DRAG_MARGIN)
1779                 {
1780                         create_x_pane(cursor_x);
1781                         mwindow->edl->local_session->x_pane = cursor_x;
1782                 }
1783                 else
1784 // deleted a pane
1785                 {
1786                         delete_x_pane(cursor_x);
1787                         mwindow->edl->local_session->x_pane = -1;
1788                 }
1789
1790
1791         }
1792
1793         if(y_pane_drag)
1794         {
1795 // cursor position relative to canvas
1796                 int cursor_y = y_pane_drag->get_y() -
1797                         get_y() -
1798                         BC_DisplayInfo::get_top_border() -
1799                         mwindow->theme->mcanvas_y +
1800                         mwindow->theme->pane_h;
1801                 delete y_pane_drag;
1802                 y_pane_drag = 0;
1803
1804
1805
1806                 if(cursor_y >= mwindow->theme->mtimebar_h +
1807                                 PANE_DRAG_MARGIN &&
1808                         cursor_y < mwindow->theme->mcanvas_h -
1809                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
1810                                 PANE_DRAG_MARGIN)
1811                 {
1812                         create_y_pane(cursor_y);
1813                         mwindow->edl->local_session->y_pane = cursor_y;
1814                 }
1815                 else
1816                 {
1817                         delete_y_pane(cursor_y);
1818                         mwindow->edl->local_session->y_pane = -1;
1819                 }
1820         }
1821
1822         update_pane_dividers();
1823         update_cursor();
1824 // required to get new widgets to appear
1825         show_window();
1826         resource_thread->start_draw();
1827 }
1828
1829 // create panes from EDL
1830 void MWindowGUI::load_panes()
1831 {
1832         int need_x_panes = 0;
1833         int need_y_panes = 0;
1834 // use names from create functions
1835         int cursor_x = mwindow->edl->local_session->x_pane;
1836         int cursor_y = mwindow->edl->local_session->y_pane;
1837
1838         resource_thread->stop_draw(1);
1839         if(cursor_x >=
1840                 mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1841                 cursor_x <
1842                 mwindow->theme->mcanvas_w -
1843                                 BC_ScrollBar::get_span(SCROLL_VERT) -
1844                                 PANE_DRAG_MARGIN)
1845         {
1846                 need_x_panes = 1;
1847         }
1848
1849         if(cursor_y >=
1850                 mwindow->theme->mtimebar_h + PANE_DRAG_MARGIN &&
1851                 cursor_y <
1852                 mwindow->theme->mcanvas_h -
1853                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
1854                                 PANE_DRAG_MARGIN)
1855         {
1856                 need_y_panes = 1;
1857         }
1858
1859 //printf("MWindowGUI::load_panes %d %d %d\n", __LINE__, need_x_panes, need_y_panes);
1860
1861
1862         if(need_x_panes)
1863         {
1864                 if(need_y_panes)
1865                 {
1866 // 4 panes
1867                         if(total_panes() == 1)
1868                         {
1869 // create 4 panes
1870 //printf("MWindowGUI::load_panes %d\n", __LINE__);
1871                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1872                                         TOP_RIGHT_PANE,
1873                                         mwindow->theme->mcanvas_x +
1874                                                 cursor_x,
1875                                         mwindow->theme->mcanvas_y,
1876                                         mwindow->theme->mcanvas_x +
1877                                                 mwindow->theme->mcanvas_w -
1878                                                 cursor_x,
1879                                         cursor_y - mwindow->theme->pane_h);
1880                                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1881                                         BOTTOM_LEFT_PANE,
1882                                         mwindow->theme->mcanvas_x,
1883                                         mwindow->theme->mcanvas_y +
1884                                                 cursor_y,
1885                                         cursor_x - mwindow->theme->pane_w,
1886                                         mwindow->theme->mcanvas_h -
1887                                                 cursor_y);
1888                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1889                                         BOTTOM_RIGHT_PANE,
1890                                         pane[TOP_RIGHT_PANE]->x,
1891                                         mwindow->theme->mcanvas_y +
1892                                                 cursor_y,
1893                                         pane[TOP_RIGHT_PANE]->w,
1894                                         mwindow->theme->mcanvas_h -
1895                                                 cursor_y);
1896                                 pane[TOP_LEFT_PANE]->resize_event(
1897                                         pane[TOP_LEFT_PANE]->x,
1898                                         pane[TOP_LEFT_PANE]->y,
1899                                         cursor_x - mwindow->theme->pane_w,
1900                                         cursor_y - mwindow->theme->pane_h);
1901                                 pane[TOP_RIGHT_PANE]->create_objects();
1902                                 pane[BOTTOM_LEFT_PANE]->create_objects();
1903                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1904                         }
1905                         else
1906                         if(horizontal_panes())
1907                         {
1908 // create vertical panes
1909 //printf("MWindowGUI::load_panes %d\n", __LINE__);
1910                                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1911                                         BOTTOM_LEFT_PANE,
1912                                         mwindow->theme->mcanvas_x,
1913                                         mwindow->theme->mcanvas_y +
1914                                                 cursor_y,
1915                                         cursor_x - mwindow->theme->pane_w,
1916                                         mwindow->theme->mcanvas_h -
1917                                                 cursor_y);
1918                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1919                                         BOTTOM_RIGHT_PANE,
1920                                         pane[TOP_RIGHT_PANE]->x,
1921                                         mwindow->theme->mcanvas_y +
1922                                                 cursor_y,
1923                                         pane[TOP_RIGHT_PANE]->w,
1924                                         mwindow->theme->mcanvas_h -
1925                                                 cursor_y);
1926                                 pane[TOP_LEFT_PANE]->resize_event(
1927                                         pane[TOP_LEFT_PANE]->x,
1928                                         pane[TOP_LEFT_PANE]->y,
1929                                         cursor_x - mwindow->theme->pane_w,
1930                                         cursor_y - mwindow->theme->pane_h);
1931                                 pane[TOP_RIGHT_PANE]->resize_event(
1932                                         mwindow->theme->mcanvas_x +
1933                                                 cursor_x,
1934                                         mwindow->theme->mcanvas_y,
1935                                         mwindow->theme->mcanvas_x +
1936                                                 mwindow->theme->mcanvas_w -
1937                                                 cursor_x,
1938                                         cursor_y - mwindow->theme->pane_h);
1939                                 pane[BOTTOM_LEFT_PANE]->create_objects();
1940                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1941                         }
1942                         else
1943                         if(vertical_panes())
1944                         {
1945 // create horizontal panes
1946 //printf("MWindowGUI::load_panes %d\n", __LINE__);
1947                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1948                                         TOP_RIGHT_PANE,
1949                                         mwindow->theme->mcanvas_x +
1950                                                 cursor_x,
1951                                         mwindow->theme->mcanvas_y,
1952                                         mwindow->theme->mcanvas_x +
1953                                                 mwindow->theme->mcanvas_w -
1954                                                 cursor_x,
1955                                         cursor_y - mwindow->theme->pane_h);
1956                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1957                                         BOTTOM_RIGHT_PANE,
1958                                         pane[TOP_RIGHT_PANE]->x,
1959                                         mwindow->theme->mcanvas_y +
1960                                                 cursor_y,
1961                                         pane[TOP_RIGHT_PANE]->w,
1962                                         mwindow->theme->mcanvas_h -
1963                                                 cursor_y);
1964                                 pane[TOP_LEFT_PANE]->resize_event(
1965                                         pane[TOP_LEFT_PANE]->x,
1966                                         pane[TOP_LEFT_PANE]->y,
1967                                         cursor_x - mwindow->theme->pane_w,
1968                                         cursor_y - mwindow->theme->pane_h);
1969                                 pane[BOTTOM_LEFT_PANE]->resize_event(
1970                                         pane[TOP_LEFT_PANE]->x,
1971                                         mwindow->theme->mcanvas_y +
1972                                                 cursor_y,
1973                                         mwindow->theme->mcanvas_x +
1974                                                 mwindow->theme->mcanvas_w -
1975                                                 cursor_x -  mwindow->theme->pane_w,
1976                                         mwindow->theme->mcanvas_h -
1977                                                 cursor_y);
1978                                 pane[TOP_RIGHT_PANE]->create_objects();
1979                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1980
1981
1982                         }
1983                         else
1984                         {
1985 // resize all panes
1986 //printf("MWindowGUI::load_panes %d\n", __LINE__);
1987                                 pane[TOP_LEFT_PANE]->resize_event(
1988                                         pane[TOP_LEFT_PANE]->x,
1989                                         pane[TOP_LEFT_PANE]->y,
1990                                         cursor_x - mwindow->theme->pane_w,
1991                                         cursor_y - mwindow->theme->pane_h);
1992                                 pane[TOP_RIGHT_PANE]->resize_event(
1993                                         mwindow->theme->mcanvas_x +
1994                                                 cursor_x,
1995                                         mwindow->theme->mcanvas_y,
1996                                         mwindow->theme->mcanvas_x +
1997                                                 mwindow->theme->mcanvas_w -
1998                                                 cursor_x,
1999                                         cursor_y - mwindow->theme->pane_h);
2000                                 pane[BOTTOM_LEFT_PANE]->resize_event(
2001                                         pane[TOP_LEFT_PANE]->x,
2002                                         mwindow->theme->mcanvas_y +
2003                                                 cursor_y,
2004                                         mwindow->theme->mcanvas_x +
2005                                                 mwindow->theme->mcanvas_w -
2006                                                 cursor_x - mwindow->theme->pane_w,
2007                                         mwindow->theme->mcanvas_h -
2008                                                 cursor_y);
2009                                 pane[BOTTOM_RIGHT_PANE]->resize_event(
2010                                         pane[TOP_RIGHT_PANE]->x,
2011                                         mwindow->theme->mcanvas_y +
2012                                                 cursor_y,
2013                                         pane[TOP_RIGHT_PANE]->w,
2014                                         mwindow->theme->mcanvas_h -
2015                                                 cursor_y);
2016
2017
2018                         }
2019                 }
2020                 else
2021                 {
2022 // 2 X panes
2023                         if(pane[BOTTOM_LEFT_PANE]) delete pane[BOTTOM_LEFT_PANE];
2024                         if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2025                         pane[BOTTOM_LEFT_PANE] = 0;
2026                         pane[BOTTOM_RIGHT_PANE] = 0;
2027
2028                         if(!pane[TOP_RIGHT_PANE])
2029                         {
2030                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
2031                                         TOP_RIGHT_PANE,
2032                                         mwindow->theme->mcanvas_x +
2033                                                 cursor_x,
2034                                         mwindow->theme->mcanvas_y,
2035                                         mwindow->theme->mcanvas_x +
2036                                                 mwindow->theme->mcanvas_w -
2037                                                 cursor_x,
2038                                         mwindow->theme->mcanvas_h);
2039                                 pane[TOP_LEFT_PANE]->resize_event(
2040                                         mwindow->theme->mcanvas_x,
2041                                         mwindow->theme->mcanvas_y,
2042                                         cursor_x - mwindow->theme->pane_w,
2043                                         mwindow->theme->mcanvas_h);
2044                                 pane[TOP_RIGHT_PANE]->create_objects();
2045                         }
2046                         else
2047                         {
2048                                 pane[TOP_LEFT_PANE]->resize_event(
2049                                         mwindow->theme->mcanvas_x,
2050                                         mwindow->theme->mcanvas_y,
2051                                         cursor_x - mwindow->theme->pane_w,
2052                                         mwindow->theme->mcanvas_h);
2053                                 pane[TOP_RIGHT_PANE]->resize_event(
2054                                         mwindow->theme->mcanvas_x +
2055                                                 cursor_x,
2056                                         pane[TOP_RIGHT_PANE]->y,
2057                                         mwindow->theme->mcanvas_x +
2058                                                 mwindow->theme->mcanvas_w -
2059                                                 cursor_x,
2060                                         mwindow->theme->mcanvas_h);
2061                         }
2062                 }
2063         }
2064         else
2065         if(need_y_panes)
2066         {
2067 // 2 Y panes
2068                 if(pane[TOP_RIGHT_PANE]) delete pane[TOP_RIGHT_PANE];
2069                 if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2070                 pane[TOP_RIGHT_PANE] = 0;
2071                 pane[BOTTOM_RIGHT_PANE] = 0;
2072
2073                 if(!pane[BOTTOM_LEFT_PANE])
2074                 {
2075 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2076                         pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
2077                                 BOTTOM_LEFT_PANE,
2078                                 mwindow->theme->mcanvas_x,
2079                                 mwindow->theme->mcanvas_y +
2080                                         cursor_y,
2081                                 mwindow->theme->mcanvas_w,
2082                                 mwindow->theme->mcanvas_h -
2083                                         cursor_y);
2084                         pane[TOP_LEFT_PANE]->resize_event(
2085                                 mwindow->theme->mcanvas_x,
2086                                 mwindow->theme->mcanvas_y,
2087                                 mwindow->theme->mcanvas_w,
2088                                 pane[BOTTOM_LEFT_PANE]->y -
2089                                         mwindow->theme->mcanvas_y -
2090                                         mwindow->theme->pane_h);
2091                         pane[BOTTOM_LEFT_PANE]->create_objects();
2092                 }
2093                 else
2094                 {
2095                         pane[TOP_LEFT_PANE]->resize_event(
2096                                 mwindow->theme->mcanvas_x,
2097                                 mwindow->theme->mcanvas_y,
2098                                 mwindow->theme->mcanvas_w,
2099                                 cursor_y - mwindow->theme->pane_h);
2100                         pane[BOTTOM_LEFT_PANE]->resize_event(
2101                                 pane[BOTTOM_LEFT_PANE]->x,
2102                                 cursor_y +
2103                                         mwindow->theme->mcanvas_y,
2104                                 mwindow->theme->mcanvas_w,
2105                                 mwindow->theme->mcanvas_h -
2106                                         cursor_y);
2107                 }
2108         }
2109         else
2110         {
2111 // 1 pane
2112                 if(pane[TOP_RIGHT_PANE]) delete pane[TOP_RIGHT_PANE];
2113                 if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2114                 if(pane[BOTTOM_LEFT_PANE]) delete pane[BOTTOM_LEFT_PANE];
2115                 pane[TOP_RIGHT_PANE] = 0;
2116                 pane[BOTTOM_RIGHT_PANE] = 0;
2117                 pane[BOTTOM_LEFT_PANE] = 0;
2118                 pane[TOP_LEFT_PANE]->resize_event(
2119                         mwindow->theme->mcanvas_x,
2120                         mwindow->theme->mcanvas_y,
2121                         mwindow->theme->mcanvas_w,
2122                         mwindow->theme->mcanvas_h);
2123         }
2124
2125         update_pane_dividers();
2126         show_window();
2127
2128         resource_thread->start_draw();
2129 }
2130
2131 void MWindowGUI::update_pane_dividers()
2132 {
2133
2134         if(horizontal_panes() || total_panes() == 4)
2135         {
2136                 int x = pane[TOP_RIGHT_PANE]->x - mwindow->theme->pane_w;
2137                 int y = mwindow->theme->mcanvas_y;
2138                 int h = mwindow->theme->mcanvas_h;
2139
2140                 if(!x_divider)
2141                 {
2142                         add_subwindow(x_divider = new PaneDivider(
2143                                 mwindow, x, y, h, 1));
2144                         x_divider->create_objects();
2145                 }
2146                 else
2147                 {
2148                         x_divider->reposition_window(x, y, h);
2149                         x_divider->draw(0);
2150                 }
2151         }
2152         else
2153         {
2154                 if(x_divider)
2155                 {
2156                         delete x_divider;
2157                         x_divider = 0;
2158                 }
2159         }
2160
2161         if(vertical_panes() || total_panes() == 4)
2162         {
2163                 int x = mwindow->theme->mcanvas_x;
2164                 int y = pane[BOTTOM_LEFT_PANE]->y -
2165                         mwindow->theme->pane_h;
2166                 int w = mwindow->theme->mcanvas_w;
2167                 if(!y_divider)
2168                 {
2169                         add_subwindow(y_divider = new PaneDivider(
2170                                 mwindow, x, y, w, 0));
2171                         y_divider->create_objects();
2172                 }
2173                 else
2174                 {
2175                         y_divider->reposition_window(x, y, w);
2176                         y_divider->draw(0);
2177                 }
2178         }
2179         else
2180         {
2181                 if(y_divider)
2182                 {
2183                         delete y_divider;
2184                         y_divider = 0;
2185                 }
2186         }
2187 }
2188
2189 void MWindowGUI::draw_samplemovement()
2190 {
2191         draw_canvas(0, 1);
2192         show_cursor(1);
2193         flash_canvas(0);
2194         update_timebar(0);
2195         zoombar->update();
2196         update_scrollbars(1);
2197 }
2198
2199 void MWindowGUI::draw_trackmovement()
2200 {
2201         update_scrollbars(0);
2202         draw_canvas(0, 0);
2203         update_patchbay();
2204         flash_canvas(1);
2205 }
2206
2207
2208 void MWindowGUI::update_mixers(Track *track, int v)
2209 {
2210         for( int i=0; i<TOTAL_PANES;  ++i ) {
2211                 if( !pane[i] ) continue;
2212                 PatchBay *patchbay = pane[i]->patchbay;
2213                 if( !patchbay ) continue;
2214                 for( int j=0; j<patchbay->patches.total; ++j ) {
2215                         PatchGUI *patchgui = patchbay->patches.values[j];
2216                         if( !patchgui->mix ) continue;
2217                         if( !track || patchgui->track == track ) {
2218                                 patchgui->mix->update(v>=0 ? v :
2219                                         mwindow->mixer_track_active(patchgui->track));
2220                         }
2221                 }
2222         }
2223 }
2224
2225 void MWindowGUI::stop_transport(const char *lock_msg)
2226 {
2227         if( !mbuttons->transport->is_stopped() ) {
2228                 if( lock_msg ) unlock_window();
2229                 mbuttons->transport->handle_transport(STOP, 1);
2230                 if( lock_msg ) lock_window(lock_msg);
2231         }
2232 }
2233
2234 PaneButton::PaneButton(MWindow *mwindow, int x, int y)
2235  : BC_Button(x, y, mwindow->theme->get_image_set("pane"))
2236 {
2237         this->mwindow = mwindow;
2238 }
2239
2240 int PaneButton::cursor_motion_event()
2241 {
2242         if(get_top_level()->get_button_down() &&
2243                 is_event_win() &&
2244                 get_status() == BUTTON_DOWNHI &&
2245                 !cursor_inside())
2246         {
2247 //              printf("PaneButton::cursor_motion_event %d\n", __LINE__);
2248 // create drag bar
2249                 if(get_cursor_x() < 0 && !mwindow->gui->dragging_pane)
2250                 {
2251                         mwindow->gui->start_x_pane_drag();
2252                 }
2253                 else
2254                 if(get_cursor_y() < 0 && !mwindow->gui->dragging_pane)
2255                 {
2256                         mwindow->gui->start_y_pane_drag();
2257                 }
2258         }
2259
2260         mwindow->gui->handle_pane_drag();
2261
2262         int result = BC_Button::cursor_motion_event();
2263         return result;
2264 }
2265
2266 int PaneButton::button_release_event()
2267 {
2268         if( get_buttonpress() != WHEEL_DOWN && get_buttonpress() != WHEEL_UP )
2269                 mwindow->gui->stop_pane_drag();
2270         int result = BC_Button::button_release_event();
2271         return result;
2272 }
2273
2274
2275 FFMpegToggle::FFMpegToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y)
2276  : BC_Toggle(x, y, mwindow->theme->ffmpeg_toggle,
2277          mwindow->preferences->get_file_probe_armed("FFMPEG_Early") > 0 ? 1 : 0)
2278 {
2279         this->mwindow = mwindow;
2280         this->mbuttons = mbuttons;
2281         set_tooltip(get_value() ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
2282 }
2283
2284 FFMpegToggle::~FFMpegToggle()
2285 {
2286 }
2287
2288 int FFMpegToggle::handle_event()
2289 {
2290         int ffmpeg_early_probe = get_value();
2291         set_tooltip(ffmpeg_early_probe ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
2292         mwindow->preferences->set_file_probe_armed("FFMPEG_Early", ffmpeg_early_probe);
2293         mwindow->preferences->set_file_probe_armed("FFMPEG_Late", !ffmpeg_early_probe);
2294         mwindow->update_preferences(mwindow->preferences);
2295         mwindow->show_warning(&mwindow->preferences->warn_indexes,
2296                 _("Changing the base codecs may require rebuilding indexes."));
2297         return 1;
2298 }
2299
2300
2301 ProxyToggle::ProxyToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y)
2302  : BC_Toggle(x, y, ( !mwindow->edl->session->proxy_use_scaler ?
2303                         mwindow->theme->proxy_p_toggle :
2304                         mwindow->theme->proxy_s_toggle ),
2305                 mwindow->edl->session->proxy_disabled_scale != 1)
2306 {
2307         this->mwindow = mwindow;
2308         this->mbuttons = mbuttons;
2309         scaler_images = mwindow->edl->session->proxy_use_scaler;
2310         set_tooltip(mwindow->edl->session->proxy_disabled_scale==1 ?
2311                 _("Disable proxy") : _("Enable proxy"));
2312 }
2313
2314 void ProxyToggle::show()
2315 {
2316         int use_scaler = mwindow->edl->session->proxy_use_scaler;
2317         if( scaler_images != use_scaler )
2318                 set_images(!(scaler_images=use_scaler) ?
2319                         mwindow->theme->proxy_p_toggle :
2320                         mwindow->theme->proxy_s_toggle );
2321         draw_face(1, 0);
2322         if( is_hidden() )
2323                 show_window();
2324 }
2325
2326 void ProxyToggle::hide()
2327 {
2328         if( !is_hidden() )
2329                 hide_window();
2330 }
2331
2332 ProxyToggle::~ProxyToggle()
2333 {
2334 }
2335
2336 int ProxyToggle::handle_event()
2337 {
2338         int disabled = get_value();
2339         mwindow->gui->unlock_window();
2340         if( disabled )
2341                 mwindow->disable_proxy();
2342         else
2343                 mwindow->enable_proxy();
2344         mwindow->gui->lock_window("ProxyToggle::handle_event");
2345         set_tooltip(!disabled ? _("Disable proxy") : _("Enable proxy"));
2346         return 1;
2347 }
2348
2349 int ProxyToggle::keypress_event()
2350 {
2351         if( ctrl_down() && !shift_down() && !alt_down() ) {
2352                 int key = get_keypress();
2353                 if( key == 'r' ) {
2354                         int value = get_value() ? 0 : 1;
2355                         set_value(value);
2356                         return handle_event();
2357                 }
2358         }
2359         return 0;
2360 }
2361