4 * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #include "automation.h"
24 #include "cplayback.h"
26 #include "cwindowgui.h"
29 #include "edlsession.h"
31 #include "localsession.h"
32 #include "maincursor.h"
34 #include "mainsession.h"
37 #include "mwindowgui.h"
39 #include "playbackengine.h"
41 #include "resourcethread.h"
42 #include "samplescroll.h"
44 #include "trackcanvas.h"
46 #include "transportque.h"
50 void MWindow::update_plugins()
52 // Show plugins which are visible and hide plugins which aren't
53 // Update plugin pointers in plugin servers
57 int MWindow::expand_sample()
61 if(edl->local_session->zoom_sample < 0x100000)
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);
71 int MWindow::zoom_in_sample()
75 if(edl->local_session->zoom_sample > 1)
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);
85 int MWindow::zoom_sample(int64_t zoom_sample)
87 CLAMP(zoom_sample, 1, 0x100000);
88 edl->local_session->zoom_sample = zoom_sample;
91 TimelinePane *pane = gui->get_focused_pane();
92 samplemovement(edl->local_session->view_start[pane->number], pane->number);
96 void MWindow::find_cursor()
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)) /
103 edl->session->sample_rate /
104 edl->local_session->zoom_sample -
105 (double)pane->canvas->get_w() /
108 if(edl->local_session->view_start[pane->number] < 0)
109 edl->local_session->view_start[pane->number] = 0;
113 void MWindow::fit_selection()
115 if(EQUIV(edl->local_session->get_selectionstart(1),
116 edl->local_session->get_selectionend(1)))
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)
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)
138 edl->local_session->zoom_sample = MIN(0x100000,
139 edl->local_session->zoom_sample);
140 zoom_sample(edl->local_session->zoom_sample);
144 void MWindow::fit_autos(int doall)
146 float min = 0, max = 0;
150 if(EQUIV(edl->local_session->get_selectionstart(1),
151 edl->local_session->get_selectionend(1)))
154 end = edl->tracks->total_length();
157 // Test autos in highlighting only
159 start = edl->local_session->get_selectionstart(1);
160 end = edl->local_session->get_selectionend(1);
163 int forstart = edl->local_session->zoombar_showautotype;
164 int forend = edl->local_session->zoombar_showautotype + 1;
168 forend = AUTOGROUPTYPE_COUNT;
171 for (int i = forstart; i < forend; i++)
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);
177 float range = max - min;
180 case AUTOGROUPTYPE_AUDIO_FADE:
181 case AUTOGROUPTYPE_VIDEO_FADE:
183 min = MIN(min, edl->local_session->automation_mins[i]);
184 max = MAX(max, edl->local_session->automation_maxs[i]);
187 case AUTOGROUPTYPE_ZOOM:
189 min = floor(min*50)/100;
190 max = floor(max*200)/100;
193 case AUTOGROUPTYPE_SPEED:
195 min = floor(min*5)/100;
196 max = floor(max*300)/100;
199 case AUTOGROUPTYPE_X:
200 case AUTOGROUPTYPE_Y:
202 min = floor((min+max)/2) - 50;
203 max = floor((min+max)/2) + 50;
207 //printf("%f %f\n", min, max);
208 if (!Automation::autogrouptypes_fixedrange[i])
210 edl->local_session->automation_mins[i] = min;
211 edl->local_session->automation_maxs[i] = max;
215 // Show range in zoombar
216 gui->zoombar->update();
219 gui->draw_overlays(1);
223 void MWindow::change_currentautorange(int autogrouptype, int increment, int changemax)
227 val = edl->local_session->automation_maxs[autogrouptype];
229 val = edl->local_session->automation_mins[autogrouptype];
234 switch (autogrouptype) {
235 case AUTOGROUPTYPE_AUDIO_FADE:
238 case AUTOGROUPTYPE_VIDEO_FADE:
241 case AUTOGROUPTYPE_ZOOM:
242 case AUTOGROUPTYPE_SPEED:
248 case AUTOGROUPTYPE_X:
249 case AUTOGROUPTYPE_Y:
250 val = floor(val + 5);
256 switch (autogrouptype) {
257 case AUTOGROUPTYPE_AUDIO_FADE:
260 case AUTOGROUPTYPE_VIDEO_FADE:
263 case AUTOGROUPTYPE_ZOOM:
264 case AUTOGROUPTYPE_SPEED:
265 if (val > 0) val = val/2;
267 case AUTOGROUPTYPE_X:
268 case AUTOGROUPTYPE_Y:
274 AUTOMATIONVIEWCLAMPS(val, autogrouptype);
277 if (val > edl->local_session->automation_mins[autogrouptype])
278 edl->local_session->automation_maxs[autogrouptype] = val;
282 if (val < edl->local_session->automation_maxs[autogrouptype])
283 edl->local_session->automation_mins[autogrouptype] = val;
288 void MWindow::expand_autos(int changeall, int domin, int domax)
291 for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
292 if (domin) change_currentautorange(i, 1, 0);
293 if (domax) change_currentautorange(i, 1, 1);
297 if (domin) change_currentautorange(edl->local_session->zoombar_showautotype, 1, 0);
298 if (domax) change_currentautorange(edl->local_session->zoombar_showautotype, 1, 1);
300 gui->zoombar->update_autozoom();
301 gui->draw_overlays(0);
302 gui->update_patchbay();
303 gui->flash_canvas(1);
306 void MWindow::shrink_autos(int changeall, int domin, int domax)
309 for (int i = 0; i < AUTOGROUPTYPE_COUNT; i++) {
310 if (domin) change_currentautorange(i, 0, 0);
311 if (domax) change_currentautorange(i, 0, 1);
315 if (domin) change_currentautorange(edl->local_session->zoombar_showautotype, 0, 0);
316 if (domax) change_currentautorange(edl->local_session->zoombar_showautotype, 0, 1);
318 gui->zoombar->update_autozoom();
319 gui->draw_overlays(0);
320 gui->update_patchbay();
321 gui->flash_canvas(1);
325 void MWindow::zoom_autos(float min, float max)
327 int i = edl->local_session->zoombar_showautotype;
328 edl->local_session->automation_mins[i] = min;
329 edl->local_session->automation_maxs[i] = max;
330 gui->zoombar->update_autozoom();
331 gui->draw_overlays(1);
335 void MWindow::zoom_amp(int64_t zoom_amp)
337 edl->local_session->zoom_y = zoom_amp;
338 gui->draw_canvas(0, 0);
339 gui->flash_canvas(0);
340 gui->update_patchbay();
344 void MWindow::zoom_track(int64_t zoom_track)
347 edl->local_session->zoom_y = (int64_t)((float)edl->local_session->zoom_y *
349 edl->local_session->zoom_track);
350 CLAMP(edl->local_session->zoom_y, MIN_AMP_ZOOM, MAX_AMP_ZOOM);
353 double scale = (double)zoom_track / edl->local_session->zoom_track;
354 edl->local_session->zoom_track = zoom_track;
356 // shift row position
357 for(int i = 0; i < TOTAL_PANES; i++)
359 edl->local_session->track_start[i] *= scale;
361 edl->tracks->update_y_pixels(theme);
362 gui->draw_trackmovement();
363 //printf("MWindow::zoom_track %d %d\n", edl->local_session->zoom_y, edl->local_session->zoom_track);
366 void MWindow::trackmovement(int offset, int pane_number)
368 edl->local_session->track_start[pane_number] += offset;
369 if(edl->local_session->track_start[pane_number] < 0)
370 edl->local_session->track_start[pane_number] = 0;
372 if(pane_number == TOP_RIGHT_PANE ||
373 pane_number == TOP_LEFT_PANE)
375 edl->local_session->track_start[TOP_LEFT_PANE] =
376 edl->local_session->track_start[TOP_RIGHT_PANE] =
377 edl->local_session->track_start[pane_number];
380 if(pane_number == BOTTOM_RIGHT_PANE ||
381 pane_number == BOTTOM_LEFT_PANE)
383 edl->local_session->track_start[BOTTOM_LEFT_PANE] =
384 edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
385 edl->local_session->track_start[pane_number];
389 edl->tracks->update_y_pixels(theme);
390 gui->draw_trackmovement();
393 void MWindow::move_up(int64_t distance)
395 TimelinePane *pane = gui->get_focused_pane();
396 if(distance == 0) distance = edl->local_session->zoom_track;
398 trackmovement(-distance, pane->number);
401 void MWindow::move_down(int64_t distance)
403 TimelinePane *pane = gui->get_focused_pane();
404 if(distance == 0) distance = edl->local_session->zoom_track;
406 trackmovement(distance, pane->number);
409 int MWindow::goto_end()
411 TimelinePane *pane = gui->get_focused_pane();
412 int64_t old_view_start = edl->local_session->view_start[pane->number];
414 if(edl->tracks->total_length() > (double)pane->canvas->get_w() *
415 edl->local_session->zoom_sample /
416 edl->session->sample_rate)
418 edl->local_session->view_start[pane->number] =
419 Units::round(edl->tracks->total_length() *
420 edl->session->sample_rate /
421 edl->local_session->zoom_sample -
422 pane->canvas->get_w() /
427 edl->local_session->view_start[pane->number] = 0;
430 if(gui->shift_down())
432 edl->local_session->set_selectionend(edl->tracks->total_length());
436 edl->local_session->set_selectionstart(edl->tracks->total_length());
437 edl->local_session->set_selectionend(edl->tracks->total_length());
440 if(edl->local_session->view_start[pane->number] != old_view_start)
442 samplemovement(edl->local_session->view_start[pane->number], pane->number);
443 gui->draw_samplemovement();
446 update_plugin_guis();
448 gui->update_patchbay();
449 gui->update_cursor();
450 gui->activate_timeline();
451 gui->zoombar->update();
452 gui->update_timebar(1);
453 cwindow->update(1, 0, 0, 0, 1);
457 int MWindow::goto_start()
459 TimelinePane *pane = gui->get_focused_pane();
460 int64_t old_view_start = edl->local_session->view_start[pane->number];
462 edl->local_session->view_start[pane->number] = 0;
463 if(gui->shift_down())
465 edl->local_session->set_selectionstart(0);
469 edl->local_session->set_selectionstart(0);
470 edl->local_session->set_selectionend(0);
473 if(edl->local_session->view_start[pane->number] != old_view_start)
475 samplemovement(edl->local_session->view_start[pane->number], pane->number);
476 gui->draw_samplemovement();
479 update_plugin_guis();
480 gui->update_patchbay();
481 gui->update_cursor();
482 gui->activate_timeline();
483 gui->zoombar->update();
484 gui->update_timebar(1);
485 cwindow->update(1, 0, 0, 0, 1);
489 int MWindow::goto_position(double position)
491 TimelinePane *pane = gui->get_focused_pane();
492 int64_t old_view_start = edl->local_session->view_start[pane->number];
493 edl->local_session->set_selectionstart(position);
494 edl->local_session->set_selectionend(position);
496 int64_t new_view_start = edl->local_session->view_start[pane->number];
497 if(new_view_start != old_view_start)
498 samplemovement(new_view_start, pane->number);
499 update_plugin_guis();
500 gui->update_patchbay();
501 gui->update_cursor();
502 gui->activate_timeline();
503 gui->zoombar->update();
504 gui->update_timebar(1);
505 cwindow->update(1, 0, 0, 0, 1);
509 int MWindow::samplemovement(int64_t view_start, int pane_number)
511 if( view_start < 0 ) view_start = 0;
512 edl->local_session->view_start[pane_number] = view_start;
513 if(edl->local_session->view_start[pane_number] < 0)
514 edl->local_session->view_start[pane_number] = 0;
516 if(pane_number == TOP_LEFT_PANE ||
517 pane_number == BOTTOM_LEFT_PANE)
519 edl->local_session->view_start[TOP_LEFT_PANE] =
520 edl->local_session->view_start[BOTTOM_LEFT_PANE] =
521 edl->local_session->view_start[pane_number];
525 edl->local_session->view_start[TOP_RIGHT_PANE] =
526 edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
527 edl->local_session->view_start[pane_number];
530 gui->draw_samplemovement();
535 int MWindow::move_left(int64_t distance)
537 TimelinePane *pane = gui->get_focused_pane();
539 distance = pane->canvas->get_w() /
541 edl->local_session->view_start[pane->number] -= distance;
542 samplemovement(edl->local_session->view_start[pane->number],
547 int MWindow::move_right(int64_t distance)
549 TimelinePane *pane = gui->get_focused_pane();
551 distance = pane->canvas->get_w() /
553 edl->local_session->view_start[pane->number] += distance;
554 samplemovement(edl->local_session->view_start[pane->number],
559 void MWindow::select_all()
561 if( edl->local_session->get_selectionstart(1) == 0 &&
562 edl->local_session->get_selectionend(1) == edl->tracks->total_length() )
563 edl->local_session->set_selectionend(0);
565 edl->local_session->set_selectionstart(0);
566 edl->local_session->set_selectionend(edl->tracks->total_length());
568 gui->update(0, 1, 1, 1, 0, 1, 0);
569 gui->activate_timeline();
570 cwindow->update(1, 0, 0, 0, 1);
571 update_plugin_guis();
574 int MWindow::next_label(int shift_down)
576 double cursor_position = edl->local_session->get_selectionstart(1);
577 Label *current = edl->labels->next_label(cursor_position);
578 double position = !current ? -1 : current->position;
580 // last playback endpoints as fake label positions
581 double playback_start = edl->local_session->playback_start;
582 double playback_end = edl->local_session->playback_end;
583 if( playback_start > cursor_position && ( position < 0 || playback_start < position ) )
584 position = playback_start;
585 else if( playback_end > cursor_position && ( position < 0 || playback_end < position ) )
586 position = playback_end;
588 if( position >= 0 ) {
589 edl->local_session->set_selectionend(position);
591 edl->local_session->set_selectionstart(
592 edl->local_session->get_selectionend(1));
594 update_plugin_guis();
595 TimelinePane *pane = gui->get_focused_pane();
596 if(edl->local_session->get_selectionend(1) >=
597 (double)edl->local_session->view_start[pane->number] *
598 edl->local_session->zoom_sample /
599 edl->session->sample_rate +
600 pane->canvas->time_visible() ||
601 edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
602 edl->local_session->zoom_sample /
603 edl->session->sample_rate)
605 samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
606 edl->session->sample_rate /
607 edl->local_session->zoom_sample -
608 pane->canvas->get_w() /
611 cwindow->update(1, 0, 0, 0, 0);
615 gui->update_patchbay();
616 gui->update_timebar(0);
619 gui->zoombar->update();
620 gui->flash_canvas(1);
621 cwindow->update(1, 0, 0, 0, 1);
631 int MWindow::prev_label(int shift_down)
633 double cursor_position = edl->local_session->get_selectionstart(1);
634 Label *current = edl->labels->prev_label(cursor_position);
635 double position = !current ? -1 : current->position;
637 // last playback endpoints as fake label positions
638 double playback_start = edl->local_session->playback_start;
639 double playback_end = edl->local_session->playback_end;
640 if( playback_end < cursor_position && ( position < 0 || playback_end > position ) )
641 position = playback_end;
642 else if( playback_start < cursor_position && ( position < 0 || playback_start > position ) )
643 position = playback_start;
645 if( position >= 0 ) {
646 edl->local_session->set_selectionstart(position);
648 edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
650 update_plugin_guis();
651 TimelinePane *pane = gui->get_focused_pane();
652 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
653 edl->local_session->zoom_sample /
654 edl->session->sample_rate +
655 pane->canvas->time_visible()
657 edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
658 edl->local_session->zoom_sample /
659 edl->session->sample_rate)
661 samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
662 edl->session->sample_rate /
663 edl->local_session->zoom_sample -
664 pane->canvas->get_w() /
667 cwindow->update(1, 0, 0, 0, 0);
670 // Don't scroll the display
672 gui->update_patchbay();
673 gui->update_timebar(0);
676 gui->zoombar->update();
677 gui->flash_canvas(1);
678 cwindow->update(1, 0, 0, 0, 1);
693 int MWindow::next_edit_handle(int shift_down)
695 double position = edl->local_session->get_selectionend(1);
696 Units::fix_double(&position);
697 double new_position = INFINITY;
698 // Test for edit handles after cursor position
699 for (Track *track = edl->tracks->first; track; track = track->next)
703 for (Edit *edit = track->edits->first; edit; edit = edit->next)
705 double edit_end = track->from_units(edit->startproject + edit->length);
706 Units::fix_double(&edit_end);
707 if (edit_end > position && edit_end < new_position)
708 new_position = edit_end;
713 if(new_position != INFINITY)
716 edl->local_session->set_selectionend(new_position);
717 //printf("MWindow::next_edit_handle %d\n", shift_down);
719 edl->local_session->set_selectionstart(
720 edl->local_session->get_selectionend(1));
722 update_plugin_guis();
723 TimelinePane *pane = gui->get_focused_pane();
724 if(edl->local_session->get_selectionend(1) >=
725 (double)edl->local_session->view_start[pane->number] *
726 edl->local_session->zoom_sample /
727 edl->session->sample_rate +
728 pane->canvas->time_visible() ||
729 edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
730 edl->local_session->zoom_sample /
731 edl->session->sample_rate)
733 samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
734 edl->session->sample_rate /
735 edl->local_session->zoom_sample -
736 pane->canvas->get_w() /
739 cwindow->update(1, 0, 0, 0, 0);
743 gui->update_patchbay();
744 gui->update_timebar(0);
747 gui->zoombar->update();
748 gui->flash_canvas(1);
749 cwindow->update(1, 0, 0, 0, 1);
759 int MWindow::prev_edit_handle(int shift_down)
761 double position = edl->local_session->get_selectionstart(1);
762 double new_position = -1;
763 Units::fix_double(&position);
764 // Test for edit handles before cursor position
765 for (Track *track = edl->tracks->first; track; track = track->next)
769 for (Edit *edit = track->edits->first; edit; edit = edit->next)
771 double edit_end = track->from_units(edit->startproject);
772 Units::fix_double(&edit_end);
773 if (edit_end < position && edit_end > new_position)
774 new_position = edit_end;
779 if(new_position != -1)
782 edl->local_session->set_selectionstart(new_position);
783 //printf("MWindow::next_edit_handle %d\n", shift_down);
785 edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
787 update_plugin_guis();
788 // Scroll the display
789 TimelinePane *pane = gui->get_focused_pane();
790 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
791 edl->local_session->zoom_sample /
792 edl->session->sample_rate +
793 pane->canvas->time_visible()
795 edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
796 edl->local_session->zoom_sample /
797 edl->session->sample_rate)
799 samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
800 edl->session->sample_rate /
801 edl->local_session->zoom_sample -
802 pane->canvas->get_w() /
805 cwindow->update(1, 0, 0, 0, 0);
808 // Don't scroll the display
810 gui->update_patchbay();
811 gui->update_timebar(0);
814 gui->zoombar->update();
815 gui->flash_canvas(1);
816 cwindow->update(1, 0, 0, 0, 1);
833 int MWindow::expand_y()
835 int result = edl->local_session->zoom_y * 2;
836 result = MIN(result, MAX_AMP_ZOOM);
838 gui->zoombar->update();
842 int MWindow::zoom_in_y()
844 int result = edl->local_session->zoom_y / 2;
845 result = MAX(result, MIN_AMP_ZOOM);
847 gui->zoombar->update();
851 int MWindow::expand_t()
853 int result = edl->local_session->zoom_track * 2;
854 result = MIN(result, MAX_TRACK_ZOOM);
856 gui->zoombar->update();
860 int MWindow::zoom_in_t()
862 int result = edl->local_session->zoom_track / 2;
863 result = MAX(result, MIN_TRACK_ZOOM);
865 gui->zoombar->update();
869 void MWindow::split_x()
871 gui->resource_thread->stop_draw(1);
873 if(gui->pane[TOP_RIGHT_PANE])
875 gui->delete_x_pane(theme->mcanvas_w);
876 edl->local_session->x_pane = -1;
880 gui->create_x_pane(theme->mcanvas_w / 2);
881 edl->local_session->x_pane = theme->mcanvas_w / 2;
884 gui->mainmenu->update_toggles(0);
885 gui->update_pane_dividers();
886 gui->update_cursor();
887 // required to get new widgets to appear
890 gui->resource_thread->start_draw();
893 void MWindow::split_y()
895 gui->resource_thread->stop_draw(1);
896 if(gui->pane[BOTTOM_LEFT_PANE])
898 gui->delete_y_pane(theme->mcanvas_h);
899 edl->local_session->y_pane = -1;
903 gui->create_y_pane(theme->mcanvas_h / 2);
904 edl->local_session->y_pane = theme->mcanvas_h / 2;
907 gui->mainmenu->update_toggles(0);
908 gui->update_pane_dividers();
909 gui->update_cursor();
910 // required to get new widgets to appear
912 gui->resource_thread->start_draw();