Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / cinelerra / mwindowmove.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 "automation.h"
23 #include "clip.h"
24 #include "cplayback.h"
25 #include "cwindow.h"
26 #include "cwindowgui.h"
27 #include "edits.h"
28 #include "edl.h"
29 #include "edlsession.h"
30 #include "labels.h"
31 #include "localsession.h"
32 #include "maincursor.h"
33 #include "mainmenu.h"
34 #include "mainsession.h"
35 #include "mtimebar.h"
36 #include "mwindow.h"
37 #include "mwindowgui.h"
38 #include "patchbay.h"
39 #include "playbackengine.h"
40 #include "plugin.h"
41 #include "resourcethread.h"
42 #include "samplescroll.h"
43 #include "theme.h"
44 #include "trackcanvas.h"
45 #include "tracks.h"
46 #include "transportque.h"
47 #include "zoombar.h"
48
49
50 void MWindow::update_plugins()
51 {
52 // Show plugins which are visible and hide plugins which aren't
53 // Update plugin pointers in plugin servers
54 }
55
56
57 int MWindow::expand_sample()
58 {
59         if(gui)
60         {
61                 if(edl->local_session->zoom_sample < 0x100000)
62                 {
63                         edl->local_session->zoom_sample *= 2;
64                         gui->zoombar->sample_zoom->update(edl->local_session->zoom_sample);
65                         zoom_sample(edl->local_session->zoom_sample);
66                 }
67         }
68         return 0;
69 }
70
71 int MWindow::zoom_in_sample()
72 {
73         if(gui)
74         {
75                 if(edl->local_session->zoom_sample > 1)
76                 {
77                         edl->local_session->zoom_sample /= 2;
78                         gui->zoombar->sample_zoom->update(edl->local_session->zoom_sample);
79                         zoom_sample(edl->local_session->zoom_sample);
80                 }
81         }
82         return 0;
83 }
84
85 int MWindow::zoom_sample(int64_t zoom_sample)
86 {
87         CLAMP(zoom_sample, 1, 0x100000);
88         edl->local_session->zoom_sample = zoom_sample;
89                 find_cursor();
90
91         TimelinePane *pane = gui->get_focused_pane();
92         samplemovement(edl->local_session->view_start[pane->number], pane->number);
93         return 0;
94 }
95
96 void MWindow::find_cursor()
97 {
98         TimelinePane *pane = gui->get_focused_pane();
99         edl->local_session->view_start[pane->number] =
100                 Units::round((edl->local_session->get_selectionend(1) +
101                 edl->local_session->get_selectionstart(1)) /
102                 2 *
103                 edl->session->sample_rate /
104                 edl->local_session->zoom_sample -
105                 (double)pane->canvas->get_w() /
106                 2);
107
108         if(edl->local_session->view_start[pane->number] < 0)
109                 edl->local_session->view_start[pane->number] = 0;
110 }
111
112
113 void MWindow::fit_selection()
114 {
115         if(EQUIV(edl->local_session->get_selectionstart(1),
116                 edl->local_session->get_selectionend(1)))
117         {
118                 double total_samples = edl->tracks->total_length() *
119                         edl->session->sample_rate;
120                 TimelinePane *pane = gui->get_focused_pane();
121                 for(edl->local_session->zoom_sample = 1;
122                         pane->canvas->get_w() * edl->local_session->zoom_sample < total_samples;
123                         edl->local_session->zoom_sample *= 2)
124                         ;
125         }
126         else
127         {
128                 double total_samples = (edl->local_session->get_selectionend(1) -
129                         edl->local_session->get_selectionstart(1)) *
130                         edl->session->sample_rate;
131                 TimelinePane *pane = gui->get_focused_pane();
132                 for(edl->local_session->zoom_sample = 1;
133                         pane->canvas->get_w() * edl->local_session->zoom_sample < total_samples;
134                         edl->local_session->zoom_sample *= 2)
135                         ;
136         }
137
138         edl->local_session->zoom_sample = MIN(0x100000,
139                 edl->local_session->zoom_sample);
140         zoom_sample(edl->local_session->zoom_sample);
141 }
142
143
144 void MWindow::fit_autos(int doall)
145 {
146         float min = 0, max = 0;
147         double start, end;
148
149 // Test all autos
150         if(EQUIV(edl->local_session->get_selectionstart(1),
151                 edl->local_session->get_selectionend(1)))
152         {
153                 start = 0;
154                 end = edl->tracks->total_length();
155         }
156         else
157 // Test autos in highlighting only
158         {
159                 start = edl->local_session->get_selectionstart(1);
160                 end = edl->local_session->get_selectionend(1);
161         }
162
163         int forstart = edl->local_session->zoombar_showautotype;
164         int forend   = edl->local_session->zoombar_showautotype + 1;
165
166         if (doall) {
167                 forstart = 0;
168                 forend   = AUTOGROUPTYPE_COUNT;
169         }
170
171         for (int i = forstart; i < forend; i++)
172         {
173 // Adjust min and max
174                 edl->tracks->get_automation_extents(&min, &max, start, end, i);
175 //printf("MWindow::fit_autos %d %f %f results in ", i, min, max);
176
177                 float range = max - min;
178                 switch (i)
179                 {
180                 case AUTOGROUPTYPE_AUDIO_FADE:
181                 case AUTOGROUPTYPE_VIDEO_FADE:
182                         if (range < 0.1) {
183                                 min = MIN(min, edl->local_session->automation_mins[i]);
184                                 max = MAX(max, edl->local_session->automation_maxs[i]);
185                         }
186                         break;
187                 case AUTOGROUPTYPE_ZOOM:
188                         if (range < 0.001) {
189                                 min = floor(min*50)/100;
190                                 max = floor(max*200)/100;
191                         }
192                         break;
193                 case AUTOGROUPTYPE_X:
194                 case AUTOGROUPTYPE_Y:
195                         if (range < 5) {
196                                 min = floor((min+max)/2) - 50;
197                                 max = floor((min+max)/2) + 50;
198                         }
199                         break;
200                 }
201 //printf("%f %f\n", min, max);
202                 if (!Automation::autogrouptypes_fixedrange[i])
203                 {
204                         edl->local_session->automation_mins[i] = min;
205                         edl->local_session->automation_maxs[i] = max;
206                 }
207         }
208
209 // Show range in zoombar
210         gui->zoombar->update();
211
212 // Draw
213         gui->draw_overlays(1);
214 }
215
216
217 void MWindow::change_currentautorange(int autogrouptype, int increment, int changemax)
218 {
219         float val;
220         if (changemax) {
221                 val = edl->local_session->automation_maxs[autogrouptype];
222         } else {
223                 val = edl->local_session->automation_mins[autogrouptype];
224         }
225
226         if (increment)
227         {
228                 switch (autogrouptype) {
229                 case AUTOGROUPTYPE_AUDIO_FADE:
230                         val += 2;
231                         break;
232                 case AUTOGROUPTYPE_VIDEO_FADE:
233                         val += 1;
234                         break;
235                 case AUTOGROUPTYPE_ZOOM:
236                         if (val == 0)
237                                 val = 0.001;
238                         else
239                                 val = val*2;
240                         break;
241                 case AUTOGROUPTYPE_X:
242                 case AUTOGROUPTYPE_Y:
243                         val = floor(val + 5);
244                         break;
245                 }
246         }
247         else
248         { // decrement
249                 switch (autogrouptype) {
250                 case AUTOGROUPTYPE_AUDIO_FADE:
251                         val -= 2;
252                         break;
253                 case AUTOGROUPTYPE_VIDEO_FADE:
254                         val -= 1;
255                         break;
256                 case AUTOGROUPTYPE_ZOOM:
257                         if (val > 0) val = val/2;
258                         break;
259                 case AUTOGROUPTYPE_X:
260                 case AUTOGROUPTYPE_Y:
261                         val = floor(val-5);
262                         break;
263                 }
264         }
265
266         AUTOMATIONVIEWCLAMPS(val, autogrouptype);
267
268         if (changemax) {
269                 if (val > edl->local_session->automation_mins[autogrouptype])
270                         edl->local_session->automation_maxs[autogrouptype] = val;
271         }
272         else
273         {
274                 if (val < edl->local_session->automation_maxs[autogrouptype])
275                         edl->local_session->automation_mins[autogrouptype] = val;
276         }
277 }
278
279
280 void MWindow::expand_autos(int changeall, int domin, int domax)
281 {
282         if (changeall)
283                 for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
284                         if (domin) change_currentautorange(i, 1, 0);
285                         if (domax) change_currentautorange(i, 1, 1);
286                 }
287         else
288         {
289                 if (domin) change_currentautorange(edl->local_session->zoombar_showautotype, 1, 0);
290                 if (domax) change_currentautorange(edl->local_session->zoombar_showautotype, 1, 1);
291         }
292         gui->zoombar->update_autozoom();
293         gui->draw_overlays(0);
294         gui->update_patchbay();
295         gui->flash_canvas(1);
296 }
297
298 void MWindow::shrink_autos(int changeall, int domin, int domax)
299 {
300         if (changeall)
301                 for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
302                         if (domin) change_currentautorange(i, 0, 0);
303                         if (domax) change_currentautorange(i, 0, 1);
304                 }
305         else
306         {
307                 if (domin) change_currentautorange(edl->local_session->zoombar_showautotype, 0, 0);
308                 if (domax) change_currentautorange(edl->local_session->zoombar_showautotype, 0, 1);
309         }
310         gui->zoombar->update_autozoom();
311         gui->draw_overlays(0);
312         gui->update_patchbay();
313         gui->flash_canvas(1);
314 }
315
316
317 void MWindow::zoom_autos(float min, float max)
318 {
319         int i = edl->local_session->zoombar_showautotype;
320         edl->local_session->automation_mins[i] = min;
321         edl->local_session->automation_maxs[i] = max;
322         gui->zoombar->update_autozoom();
323         gui->draw_overlays(1);
324 }
325
326
327 void MWindow::zoom_amp(int64_t zoom_amp)
328 {
329         edl->local_session->zoom_y = zoom_amp;
330         gui->draw_canvas(0, 0);
331         gui->flash_canvas(0);
332         gui->update_patchbay();
333         gui->flush();
334 }
335
336 void MWindow::zoom_track(int64_t zoom_track)
337 {
338 // scale waveforms
339         edl->local_session->zoom_y = (int64_t)((float)edl->local_session->zoom_y *
340                 zoom_track /
341                 edl->local_session->zoom_track);
342         CLAMP(edl->local_session->zoom_y, MIN_AMP_ZOOM, MAX_AMP_ZOOM);
343
344 // scale tracks
345         double scale = (double)zoom_track / edl->local_session->zoom_track;
346         edl->local_session->zoom_track = zoom_track;
347
348 // shift row position
349         for(int i = 0; i < TOTAL_PANES; i++)
350         {
351                 edl->local_session->track_start[i] *= scale;
352         }
353         edl->tracks->update_y_pixels(theme);
354         gui->draw_trackmovement();
355 //printf("MWindow::zoom_track %d %d\n", edl->local_session->zoom_y, edl->local_session->zoom_track);
356 }
357
358 void MWindow::trackmovement(int offset, int pane_number)
359 {
360         edl->local_session->track_start[pane_number] += offset;
361         if(edl->local_session->track_start[pane_number] < 0)
362                 edl->local_session->track_start[pane_number] = 0;
363
364         if(pane_number == TOP_RIGHT_PANE ||
365                 pane_number == TOP_LEFT_PANE)
366         {
367                 edl->local_session->track_start[TOP_LEFT_PANE] =
368                         edl->local_session->track_start[TOP_RIGHT_PANE] =
369                         edl->local_session->track_start[pane_number];
370         }
371         else
372         if(pane_number == BOTTOM_RIGHT_PANE ||
373                 pane_number == BOTTOM_LEFT_PANE)
374         {
375                 edl->local_session->track_start[BOTTOM_LEFT_PANE] =
376                         edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
377                         edl->local_session->track_start[pane_number];
378         }
379
380
381         edl->tracks->update_y_pixels(theme);
382         gui->draw_trackmovement();
383 }
384
385 void MWindow::move_up(int64_t distance)
386 {
387         TimelinePane *pane = gui->get_focused_pane();
388         if(distance == 0) distance = edl->local_session->zoom_track;
389
390         trackmovement(-distance, pane->number);
391 }
392
393 void MWindow::move_down(int64_t distance)
394 {
395         TimelinePane *pane = gui->get_focused_pane();
396         if(distance == 0) distance = edl->local_session->zoom_track;
397
398         trackmovement(distance, pane->number);
399 }
400
401 int MWindow::goto_end()
402 {
403         TimelinePane *pane = gui->get_focused_pane();
404         int64_t old_view_start = edl->local_session->view_start[pane->number];
405
406         if(edl->tracks->total_length() > (double)pane->canvas->get_w() *
407                 edl->local_session->zoom_sample /
408                 edl->session->sample_rate)
409         {
410                 edl->local_session->view_start[pane->number] =
411                         Units::round(edl->tracks->total_length() *
412                                 edl->session->sample_rate /
413                                 edl->local_session->zoom_sample -
414                                 pane->canvas->get_w() /
415                                 2);
416         }
417         else
418         {
419                 edl->local_session->view_start[pane->number] = 0;
420         }
421
422         if(gui->shift_down())
423         {
424                 edl->local_session->set_selectionend(edl->tracks->total_length());
425         }
426         else
427         {
428                 edl->local_session->set_selectionstart(edl->tracks->total_length());
429                 edl->local_session->set_selectionend(edl->tracks->total_length());
430         }
431
432         if(edl->local_session->view_start[pane->number] != old_view_start)
433         {
434                 samplemovement(edl->local_session->view_start[pane->number], pane->number);
435                 gui->draw_samplemovement();
436         }
437
438         update_plugin_guis();
439
440         gui->update_patchbay();
441         gui->update_cursor();
442         gui->activate_timeline();
443         gui->zoombar->update();
444         gui->update_timebar(1);
445         cwindow->update(1, 0, 0, 0, 1);
446         return 0;
447 }
448
449 int MWindow::goto_start()
450 {
451         TimelinePane *pane = gui->get_focused_pane();
452         int64_t old_view_start = edl->local_session->view_start[pane->number];
453
454         edl->local_session->view_start[pane->number] = 0;
455         if(gui->shift_down())
456         {
457                 edl->local_session->set_selectionstart(0);
458         }
459         else
460         {
461                 edl->local_session->set_selectionstart(0);
462                 edl->local_session->set_selectionend(0);
463         }
464
465         if(edl->local_session->view_start[pane->number] != old_view_start)
466         {
467                 samplemovement(edl->local_session->view_start[pane->number], pane->number);
468                 gui->draw_samplemovement();
469         }
470
471         update_plugin_guis();
472         gui->update_patchbay();
473         gui->update_cursor();
474         gui->activate_timeline();
475         gui->zoombar->update();
476         gui->update_timebar(1);
477         cwindow->update(1, 0, 0, 0, 1);
478         return 0;
479 }
480
481 int MWindow::goto_position(double position)
482 {
483         TimelinePane *pane = gui->get_focused_pane();
484         int64_t old_view_start = edl->local_session->view_start[pane->number];
485         edl->local_session->set_selectionstart(position);
486         edl->local_session->set_selectionend(position);
487         find_cursor();
488         int64_t new_view_start = edl->local_session->view_start[pane->number];
489         if(new_view_start != old_view_start)
490                 samplemovement(new_view_start, pane->number);
491         update_plugin_guis();
492         gui->update_patchbay();
493         gui->update_cursor();
494         gui->activate_timeline();
495         gui->zoombar->update();
496         gui->update_timebar(1);
497         cwindow->update(1, 0, 0, 0, 1);
498         return 0;
499 }
500
501 int MWindow::samplemovement(int64_t view_start, int pane_number)
502 {
503         if( view_start < 0 ) view_start = 0;
504         edl->local_session->view_start[pane_number] = view_start;
505         if(edl->local_session->view_start[pane_number] < 0)
506                 edl->local_session->view_start[pane_number] = 0;
507
508         if(pane_number == TOP_LEFT_PANE ||
509                 pane_number == BOTTOM_LEFT_PANE)
510         {
511                 edl->local_session->view_start[TOP_LEFT_PANE] =
512                         edl->local_session->view_start[BOTTOM_LEFT_PANE] =
513                         edl->local_session->view_start[pane_number];
514         }
515         else
516         {
517                 edl->local_session->view_start[TOP_RIGHT_PANE] =
518                         edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
519                         edl->local_session->view_start[pane_number];
520         }
521
522         gui->draw_samplemovement();
523
524         return 0;
525 }
526
527 int MWindow::move_left(int64_t distance)
528 {
529         TimelinePane *pane = gui->get_focused_pane();
530         if(!distance)
531                 distance = pane->canvas->get_w() /
532                         10;
533         edl->local_session->view_start[pane->number] -= distance;
534         samplemovement(edl->local_session->view_start[pane->number],
535                 pane->number);
536         return 0;
537 }
538
539 int MWindow::move_right(int64_t distance)
540 {
541         TimelinePane *pane = gui->get_focused_pane();
542         if(!distance)
543                 distance = pane->canvas->get_w() /
544                         10;
545         edl->local_session->view_start[pane->number] += distance;
546         samplemovement(edl->local_session->view_start[pane->number],
547                 pane->number);
548         return 0;
549 }
550
551 void MWindow::select_all()
552 {
553         if( edl->local_session->get_selectionstart(1) == 0 &&
554             edl->local_session->get_selectionend(1) == edl->tracks->total_length() )
555                 edl->local_session->set_selectionend(0);
556         else {
557                 edl->local_session->set_selectionstart(0);
558                 edl->local_session->set_selectionend(edl->tracks->total_length());
559         }
560         gui->update(0, 1, 1, 1, 0, 1, 0);
561         gui->activate_timeline();
562         cwindow->update(1, 0, 0, 0, 1);
563         update_plugin_guis();
564 }
565
566 int MWindow::next_label(int shift_down)
567 {
568         double cursor_position = edl->local_session->get_selectionstart(1);
569         Label *current = edl->labels->next_label(cursor_position);
570         double position = !current ? -1 : current->position;
571
572 // last playback endpoints as fake label positions
573         double playback_start = edl->local_session->playback_start;
574         double playback_end = edl->local_session->playback_end;
575         if( playback_start > cursor_position && ( position < 0 || playback_start < position ) )
576                 position = playback_start;
577         else if( playback_end > cursor_position && ( position < 0 || playback_end < position ) )
578                 position = playback_end;
579
580         if( position >= 0 ) {
581                 edl->local_session->set_selectionend(position);
582                 if(!shift_down)
583                         edl->local_session->set_selectionstart(
584                                 edl->local_session->get_selectionend(1));
585
586                 update_plugin_guis();
587                 TimelinePane *pane = gui->get_focused_pane();
588                 if(edl->local_session->get_selectionend(1) >=
589                         (double)edl->local_session->view_start[pane->number] *
590                                 edl->local_session->zoom_sample /
591                                 edl->session->sample_rate +
592                                 pane->canvas->time_visible() ||
593                         edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
594                                 edl->local_session->zoom_sample /
595                                 edl->session->sample_rate)
596                 {
597                         samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
598                                 edl->session->sample_rate /
599                                 edl->local_session->zoom_sample -
600                                 pane->canvas->get_w() /
601                                 2),
602                                 pane->number);
603                         cwindow->update(1, 0, 0, 0, 0);
604                 }
605                 else
606                 {
607                         gui->update_patchbay();
608                         gui->update_timebar(0);
609                         gui->hide_cursor(0);
610                         gui->draw_cursor(0);
611                         gui->zoombar->update();
612                         gui->flash_canvas(1);
613                         cwindow->update(1, 0, 0, 0, 1);
614                 }
615         }
616         else
617         {
618                 goto_end();
619         }
620         return 0;
621 }
622
623 int MWindow::prev_label(int shift_down)
624 {
625         double cursor_position = edl->local_session->get_selectionstart(1);
626         Label *current = edl->labels->prev_label(cursor_position);
627         double position = !current ? -1 : current->position;
628
629 // last playback endpoints as fake label positions
630         double playback_start = edl->local_session->playback_start;
631         double playback_end = edl->local_session->playback_end;
632         if( playback_end < cursor_position && ( position < 0 || playback_end > position ) )
633                 position = playback_end;
634         else if( playback_start < cursor_position && ( position < 0 || playback_start > position ) )
635                 position = playback_start;
636
637         if( position >= 0 ) {
638                 edl->local_session->set_selectionstart(position);
639                 if(!shift_down)
640                         edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
641
642                 update_plugin_guis();
643                 TimelinePane *pane = gui->get_focused_pane();
644                 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
645                         edl->local_session->zoom_sample /
646                         edl->session->sample_rate +
647                         pane->canvas->time_visible()
648                 ||
649                         edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
650                         edl->local_session->zoom_sample /
651                         edl->session->sample_rate)
652                 {
653                         samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
654                                 edl->session->sample_rate /
655                                 edl->local_session->zoom_sample -
656                                 pane->canvas->get_w() /
657                                 2),
658                                 pane->number);
659                         cwindow->update(1, 0, 0, 0, 0);
660                 }
661                 else
662 // Don't scroll the display
663                 {
664                         gui->update_patchbay();
665                         gui->update_timebar(0);
666                         gui->hide_cursor(0);
667                         gui->draw_cursor(0);
668                         gui->zoombar->update();
669                         gui->flash_canvas(1);
670                         cwindow->update(1, 0, 0, 0, 1);
671                 }
672         }
673         else
674         {
675                 goto_start();
676         }
677         return 0;
678 }
679
680
681
682
683
684
685 int MWindow::next_edit_handle(int shift_down)
686 {
687         double position = edl->local_session->get_selectionend(1);
688         Units::fix_double(&position);
689         double new_position = INFINITY;
690 // Test for edit handles after cursor position
691         for (Track *track = edl->tracks->first; track; track = track->next)
692         {
693                 if (track->record)
694                 {
695                         for (Edit *edit = track->edits->first; edit; edit = edit->next)
696                         {
697                                 double edit_end = track->from_units(edit->startproject + edit->length);
698                                 Units::fix_double(&edit_end);
699                                 if (edit_end > position && edit_end < new_position)
700                                         new_position = edit_end;
701                         }
702                 }
703         }
704
705         if(new_position != INFINITY)
706         {
707
708                 edl->local_session->set_selectionend(new_position);
709 //printf("MWindow::next_edit_handle %d\n", shift_down);
710                 if(!shift_down)
711                         edl->local_session->set_selectionstart(
712                                 edl->local_session->get_selectionend(1));
713
714                 update_plugin_guis();
715                 TimelinePane *pane = gui->get_focused_pane();
716                 if(edl->local_session->get_selectionend(1) >=
717                         (double)edl->local_session->view_start[pane->number] *
718                         edl->local_session->zoom_sample /
719                         edl->session->sample_rate +
720                         pane->canvas->time_visible() ||
721                         edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
722                         edl->local_session->zoom_sample /
723                         edl->session->sample_rate)
724                 {
725                         samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
726                                 edl->session->sample_rate /
727                                 edl->local_session->zoom_sample -
728                                 pane->canvas->get_w() /
729                                 2),
730                                 pane->number);
731                         cwindow->update(1, 0, 0, 0, 0);
732                 }
733                 else
734                 {
735                         gui->update_patchbay();
736                         gui->update_timebar(0);
737                         gui->hide_cursor(0);
738                         gui->draw_cursor(0);
739                         gui->zoombar->update();
740                         gui->flash_canvas(1);
741                         cwindow->update(1, 0, 0, 0, 1);
742                 }
743         }
744         else
745         {
746                 goto_end();
747         }
748         return 0;
749 }
750
751 int MWindow::prev_edit_handle(int shift_down)
752 {
753         double position = edl->local_session->get_selectionstart(1);
754         double new_position = -1;
755         Units::fix_double(&position);
756 // Test for edit handles before cursor position
757         for (Track *track = edl->tracks->first; track; track = track->next)
758         {
759                 if (track->record)
760                 {
761                         for (Edit *edit = track->edits->first; edit; edit = edit->next)
762                         {
763                                 double edit_end = track->from_units(edit->startproject);
764                                 Units::fix_double(&edit_end);
765                                 if (edit_end < position && edit_end > new_position)
766                                         new_position = edit_end;
767                         }
768                 }
769         }
770
771         if(new_position != -1)
772         {
773
774                 edl->local_session->set_selectionstart(new_position);
775 //printf("MWindow::next_edit_handle %d\n", shift_down);
776                 if(!shift_down)
777                         edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
778
779                 update_plugin_guis();
780 // Scroll the display
781                 TimelinePane *pane = gui->get_focused_pane();
782                 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
783                         edl->local_session->zoom_sample /
784                         edl->session->sample_rate +
785                         pane->canvas->time_visible()
786                 ||
787                         edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
788                         edl->local_session->zoom_sample /
789                         edl->session->sample_rate)
790                 {
791                         samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
792                                 edl->session->sample_rate /
793                                 edl->local_session->zoom_sample -
794                                 pane->canvas->get_w() /
795                                 2),
796                                 pane->number);
797                         cwindow->update(1, 0, 0, 0, 0);
798                 }
799                 else
800 // Don't scroll the display
801                 {
802                         gui->update_patchbay();
803                         gui->update_timebar(0);
804                         gui->hide_cursor(0);
805                         gui->draw_cursor(0);
806                         gui->zoombar->update();
807                         gui->flash_canvas(1);
808                         cwindow->update(1, 0, 0, 0, 1);
809                 }
810         }
811         else
812         {
813                 goto_start();
814         }
815         return 0;
816 }
817
818
819
820
821
822
823
824
825 int MWindow::expand_y()
826 {
827         int result = edl->local_session->zoom_y * 2;
828         result = MIN(result, MAX_AMP_ZOOM);
829         zoom_amp(result);
830         gui->zoombar->update();
831         return 0;
832 }
833
834 int MWindow::zoom_in_y()
835 {
836         int result = edl->local_session->zoom_y / 2;
837         result = MAX(result, MIN_AMP_ZOOM);
838         zoom_amp(result);
839         gui->zoombar->update();
840         return 0;
841 }
842
843 int MWindow::expand_t()
844 {
845         int result = edl->local_session->zoom_track * 2;
846         result = MIN(result, MAX_TRACK_ZOOM);
847         zoom_track(result);
848         gui->zoombar->update();
849         return 0;
850 }
851
852 int MWindow::zoom_in_t()
853 {
854         int result = edl->local_session->zoom_track / 2;
855         result = MAX(result, MIN_TRACK_ZOOM);
856         zoom_track(result);
857         gui->zoombar->update();
858         return 0;
859 }
860
861 void MWindow::split_x()
862 {
863         gui->resource_thread->stop_draw(1);
864
865         if(gui->pane[TOP_RIGHT_PANE])
866         {
867                 gui->delete_x_pane(theme->mcanvas_w);
868                 edl->local_session->x_pane = -1;
869         }
870         else
871         {
872                 gui->create_x_pane(theme->mcanvas_w / 2);
873                 edl->local_session->x_pane = theme->mcanvas_w / 2;
874         }
875
876         gui->mainmenu->update_toggles(0);
877         gui->update_pane_dividers();
878         gui->update_cursor();
879 // required to get new widgets to appear
880         gui->show_window();
881
882         gui->resource_thread->start_draw();
883 }
884
885 void MWindow::split_y()
886 {
887         gui->resource_thread->stop_draw(1);
888         if(gui->pane[BOTTOM_LEFT_PANE])
889         {
890                 gui->delete_y_pane(theme->mcanvas_h);
891                 edl->local_session->y_pane = -1;
892         }
893         else
894         {
895                 gui->create_y_pane(theme->mcanvas_h / 2);
896                 edl->local_session->y_pane = theme->mcanvas_h / 2;
897         }
898
899         gui->mainmenu->update_toggles(0);
900         gui->update_pane_dividers();
901         gui->update_cursor();
902 // required to get new widgets to appear
903         gui->show_window();
904         gui->resource_thread->start_draw();
905 }
906
907