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
23 #include "cplayback.h"
25 #include "cwindowgui.h"
28 #include "edlsession.h"
30 #include "localsession.h"
31 #include "maincursor.h"
33 #include "mainsession.h"
36 #include "mwindowgui.h"
38 #include "playbackengine.h"
40 #include "resourcethread.h"
41 #include "samplescroll.h"
43 #include "trackcanvas.h"
45 #include "transportque.h"
49 void MWindow::update_plugins()
51 // Show plugins which are visible and hide plugins which aren't
52 // Update plugin pointers in plugin servers
56 int MWindow::expand_sample()
60 if(edl->local_session->zoom_sample < 0x100000)
62 edl->local_session->zoom_sample *= 2;
63 gui->zoombar->sample_zoom->update(edl->local_session->zoom_sample);
64 zoom_sample(edl->local_session->zoom_sample);
70 int MWindow::zoom_in_sample()
74 if(edl->local_session->zoom_sample > 1)
76 edl->local_session->zoom_sample /= 2;
77 gui->zoombar->sample_zoom->update(edl->local_session->zoom_sample);
78 zoom_sample(edl->local_session->zoom_sample);
84 int MWindow::zoom_sample(int64_t zoom_sample)
86 CLAMP(zoom_sample, 1, 0x100000);
87 edl->local_session->zoom_sample = zoom_sample;
90 TimelinePane *pane = gui->get_focused_pane();
91 samplemovement(edl->local_session->view_start[pane->number], pane->number);
95 void MWindow::find_cursor()
97 TimelinePane *pane = gui->get_focused_pane();
98 edl->local_session->view_start[pane->number] =
99 Units::round((edl->local_session->get_selectionend(1) +
100 edl->local_session->get_selectionstart(1)) /
102 edl->session->sample_rate /
103 edl->local_session->zoom_sample -
104 (double)pane->canvas->get_w() /
107 if(edl->local_session->view_start[pane->number] < 0)
108 edl->local_session->view_start[pane->number] = 0;
112 void MWindow::fit_selection()
114 if(EQUIV(edl->local_session->get_selectionstart(1),
115 edl->local_session->get_selectionend(1)))
117 double total_samples = edl->tracks->total_length() *
118 edl->session->sample_rate;
119 TimelinePane *pane = gui->get_focused_pane();
120 for(edl->local_session->zoom_sample = 1;
121 pane->canvas->get_w() * edl->local_session->zoom_sample < total_samples;
122 edl->local_session->zoom_sample *= 2)
127 double total_samples = (edl->local_session->get_selectionend(1) -
128 edl->local_session->get_selectionstart(1)) *
129 edl->session->sample_rate;
130 TimelinePane *pane = gui->get_focused_pane();
131 for(edl->local_session->zoom_sample = 1;
132 pane->canvas->get_w() * edl->local_session->zoom_sample < total_samples;
133 edl->local_session->zoom_sample *= 2)
137 edl->local_session->zoom_sample = MIN(0x100000,
138 edl->local_session->zoom_sample);
139 zoom_sample(edl->local_session->zoom_sample);
143 void MWindow::fit_autos()
145 float min = 0, max = 0;
149 if(EQUIV(edl->local_session->get_selectionstart(1),
150 edl->local_session->get_selectionend(1)))
153 end = edl->tracks->total_length();
156 // Test autos in highlighting only
158 start = edl->local_session->get_selectionstart(1);
159 end = edl->local_session->get_selectionend(1);
162 // Adjust min and max
163 edl->tracks->get_automation_extents(&min, &max, start, end);
164 //printf("MWindow::fit_autos %f %f\n", min, max);
167 float range = max - min;
168 // No automation visible
174 float pad = range * 0.33;
177 edl->local_session->automation_min = min;
178 edl->local_session->automation_max = max;
180 // Show range in zoombar
181 gui->zoombar->update();
184 gui->draw_overlays(1);
188 void MWindow::expand_autos()
190 float range = edl->local_session->automation_max -
191 edl->local_session->automation_min;
192 float center = range / 2 +
193 edl->local_session->automation_min;
194 if(EQUIV(range, 0)) range = 0.002;
195 edl->local_session->automation_min = center - range;
196 edl->local_session->automation_max = center + range;
197 gui->zoombar->update_autozoom();
198 gui->draw_overlays(1);
201 void MWindow::shrink_autos()
203 float range = edl->local_session->automation_max -
204 edl->local_session->automation_min;
205 float center = range / 2 +
206 edl->local_session->automation_min;
207 float new_range = range / 4;
208 edl->local_session->automation_min = center - new_range;
209 edl->local_session->automation_max = center + new_range;
210 gui->zoombar->update_autozoom();
211 gui->draw_overlays(1);
215 void MWindow::zoom_autos(float min, float max)
217 edl->local_session->automation_min = min;
218 edl->local_session->automation_max = max;
219 gui->zoombar->update_autozoom();
220 gui->draw_overlays(1);
224 void MWindow::zoom_amp(int64_t zoom_amp)
226 edl->local_session->zoom_y = zoom_amp;
227 gui->draw_canvas(0, 0);
228 gui->flash_canvas(0);
229 gui->update_patchbay();
233 void MWindow::zoom_track(int64_t zoom_track)
236 edl->local_session->zoom_y = (int64_t)((float)edl->local_session->zoom_y *
238 edl->local_session->zoom_track);
239 CLAMP(edl->local_session->zoom_y, MIN_AMP_ZOOM, MAX_AMP_ZOOM);
242 double scale = (double)zoom_track / edl->local_session->zoom_track;
243 edl->local_session->zoom_track = zoom_track;
245 // shift row position
246 for(int i = 0; i < TOTAL_PANES; i++)
248 edl->local_session->track_start[i] *= scale;
250 edl->tracks->update_y_pixels(theme);
251 gui->draw_trackmovement();
252 //printf("MWindow::zoom_track %d %d\n", edl->local_session->zoom_y, edl->local_session->zoom_track);
255 void MWindow::trackmovement(int offset, int pane_number)
257 edl->local_session->track_start[pane_number] += offset;
258 if(edl->local_session->track_start[pane_number] < 0)
259 edl->local_session->track_start[pane_number] = 0;
261 if(pane_number == TOP_RIGHT_PANE ||
262 pane_number == TOP_LEFT_PANE)
264 edl->local_session->track_start[TOP_LEFT_PANE] =
265 edl->local_session->track_start[TOP_RIGHT_PANE] =
266 edl->local_session->track_start[pane_number];
269 if(pane_number == BOTTOM_RIGHT_PANE ||
270 pane_number == BOTTOM_LEFT_PANE)
272 edl->local_session->track_start[BOTTOM_LEFT_PANE] =
273 edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
274 edl->local_session->track_start[pane_number];
278 edl->tracks->update_y_pixels(theme);
279 gui->draw_trackmovement();
282 void MWindow::move_up(int64_t distance)
284 TimelinePane *pane = gui->get_focused_pane();
285 if(distance == 0) distance = edl->local_session->zoom_track;
287 trackmovement(-distance, pane->number);
290 void MWindow::move_down(int64_t distance)
292 TimelinePane *pane = gui->get_focused_pane();
293 if(distance == 0) distance = edl->local_session->zoom_track;
295 trackmovement(distance, pane->number);
298 int MWindow::goto_end()
300 TimelinePane *pane = gui->get_focused_pane();
301 int64_t old_view_start = edl->local_session->view_start[pane->number];
303 if(edl->tracks->total_length() > (double)pane->canvas->get_w() *
304 edl->local_session->zoom_sample /
305 edl->session->sample_rate)
307 edl->local_session->view_start[pane->number] =
308 Units::round(edl->tracks->total_length() *
309 edl->session->sample_rate /
310 edl->local_session->zoom_sample -
311 pane->canvas->get_w() /
316 edl->local_session->view_start[pane->number] = 0;
319 if(gui->shift_down())
321 edl->local_session->set_selectionend(edl->tracks->total_length());
325 edl->local_session->set_selectionstart(edl->tracks->total_length());
326 edl->local_session->set_selectionend(edl->tracks->total_length());
329 if(edl->local_session->view_start[pane->number] != old_view_start)
331 samplemovement(edl->local_session->view_start[pane->number], pane->number);
332 gui->draw_samplemovement();
335 update_plugin_guis();
337 gui->update_patchbay();
338 gui->update_cursor();
339 gui->activate_timeline();
340 gui->zoombar->update();
341 gui->update_timebar(1);
342 cwindow->update(1, 0, 0, 0, 1);
346 int MWindow::goto_start()
348 TimelinePane *pane = gui->get_focused_pane();
349 int64_t old_view_start = edl->local_session->view_start[pane->number];
351 edl->local_session->view_start[pane->number] = 0;
352 if(gui->shift_down())
354 edl->local_session->set_selectionstart(0);
358 edl->local_session->set_selectionstart(0);
359 edl->local_session->set_selectionend(0);
362 if(edl->local_session->view_start[pane->number] != old_view_start)
364 samplemovement(edl->local_session->view_start[pane->number], pane->number);
365 gui->draw_samplemovement();
368 update_plugin_guis();
369 gui->update_patchbay();
370 gui->update_cursor();
371 gui->activate_timeline();
372 gui->zoombar->update();
373 gui->update_timebar(1);
374 cwindow->update(1, 0, 0, 0, 1);
378 int MWindow::goto_position(double position)
380 TimelinePane *pane = gui->get_focused_pane();
381 int64_t old_view_start = edl->local_session->view_start[pane->number];
382 edl->local_session->set_selectionstart(position);
383 edl->local_session->set_selectionend(position);
385 int64_t new_view_start = edl->local_session->view_start[pane->number];
386 if(new_view_start != old_view_start)
387 samplemovement(new_view_start, pane->number);
388 update_plugin_guis();
389 gui->update_patchbay();
390 gui->update_cursor();
391 gui->activate_timeline();
392 gui->zoombar->update();
393 gui->update_timebar(1);
394 cwindow->update(1, 0, 0, 0, 1);
398 int MWindow::samplemovement(int64_t view_start, int pane_number)
400 if( view_start < 0 ) view_start = 0;
401 edl->local_session->view_start[pane_number] = view_start;
402 if(edl->local_session->view_start[pane_number] < 0)
403 edl->local_session->view_start[pane_number] = 0;
405 if(pane_number == TOP_LEFT_PANE ||
406 pane_number == BOTTOM_LEFT_PANE)
408 edl->local_session->view_start[TOP_LEFT_PANE] =
409 edl->local_session->view_start[BOTTOM_LEFT_PANE] =
410 edl->local_session->view_start[pane_number];
414 edl->local_session->view_start[TOP_RIGHT_PANE] =
415 edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
416 edl->local_session->view_start[pane_number];
419 gui->draw_samplemovement();
424 int MWindow::move_left(int64_t distance)
426 TimelinePane *pane = gui->get_focused_pane();
428 distance = pane->canvas->get_w() /
430 edl->local_session->view_start[pane->number] -= distance;
431 samplemovement(edl->local_session->view_start[pane->number],
436 int MWindow::move_right(int64_t distance)
438 TimelinePane *pane = gui->get_focused_pane();
440 distance = pane->canvas->get_w() /
442 edl->local_session->view_start[pane->number] += distance;
443 samplemovement(edl->local_session->view_start[pane->number],
448 void MWindow::select_all()
450 edl->local_session->set_selectionstart(0);
451 edl->local_session->set_selectionend(edl->tracks->total_length());
452 gui->update(0, 1, 1, 1, 0, 1, 0);
453 gui->activate_timeline();
454 cwindow->update(1, 0, 0, 0, 1);
455 update_plugin_guis();
458 int MWindow::next_label(int shift_down)
461 Labels *labels = edl->labels;
463 // Test for label under cursor position
464 for(current = labels->first;
465 current && !edl->equivalent(current->position,
466 edl->local_session->get_selectionend(1));
470 // Test for label before cursor position
472 for(current = labels->last;
473 current && current->position > edl->local_session->get_selectionend(1);
477 // Test for label after cursor position
479 current = labels->first;
487 edl->local_session->set_selectionend(current->position);
489 edl->local_session->set_selectionstart(
490 edl->local_session->get_selectionend(1));
492 update_plugin_guis();
493 TimelinePane *pane = gui->get_focused_pane();
494 if(edl->local_session->get_selectionend(1) >=
495 (double)edl->local_session->view_start[pane->number] *
496 edl->local_session->zoom_sample /
497 edl->session->sample_rate +
498 pane->canvas->time_visible() ||
499 edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
500 edl->local_session->zoom_sample /
501 edl->session->sample_rate)
503 samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
504 edl->session->sample_rate /
505 edl->local_session->zoom_sample -
506 pane->canvas->get_w() /
509 cwindow->update(1, 0, 0, 0, 0);
513 gui->update_patchbay();
514 gui->update_timebar(0);
517 gui->zoombar->update();
518 gui->flash_canvas(1);
519 cwindow->update(1, 0, 0, 0, 1);
529 int MWindow::prev_label(int shift_down)
532 Labels *labels = edl->labels;
534 // Test for label under cursor position
535 for(current = labels->first;
536 current && !edl->equivalent(current->position,
537 edl->local_session->get_selectionstart(1));
541 // Test for label after cursor position
543 for(current = labels->first;
545 current->position < edl->local_session->get_selectionstart(1);
549 // Test for label before cursor position
551 current = labels->last;
553 // Get previous label
558 edl->local_session->set_selectionstart(current->position);
560 edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
562 update_plugin_guis();
563 // Scroll the display
564 TimelinePane *pane = gui->get_focused_pane();
565 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
566 edl->local_session->zoom_sample /
567 edl->session->sample_rate +
568 pane->canvas->time_visible()
570 edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
571 edl->local_session->zoom_sample /
572 edl->session->sample_rate)
574 samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
575 edl->session->sample_rate /
576 edl->local_session->zoom_sample -
577 pane->canvas->get_w() /
580 cwindow->update(1, 0, 0, 0, 0);
583 // Don't scroll the display
585 gui->update_patchbay();
586 gui->update_timebar(0);
589 gui->zoombar->update();
590 gui->flash_canvas(1);
591 cwindow->update(1, 0, 0, 0, 1);
606 int MWindow::next_edit_handle(int shift_down)
608 double position = edl->local_session->get_selectionend(1);
609 Units::fix_double(&position);
610 double new_position = INFINITY;
611 // Test for edit handles after cursor position
612 for (Track *track = edl->tracks->first; track; track = track->next)
616 for (Edit *edit = track->edits->first; edit; edit = edit->next)
618 double edit_end = track->from_units(edit->startproject + edit->length);
619 Units::fix_double(&edit_end);
620 if (edit_end > position && edit_end < new_position)
621 new_position = edit_end;
626 if(new_position != INFINITY)
629 edl->local_session->set_selectionend(new_position);
630 //printf("MWindow::next_edit_handle %d\n", shift_down);
632 edl->local_session->set_selectionstart(
633 edl->local_session->get_selectionend(1));
635 update_plugin_guis();
636 TimelinePane *pane = gui->get_focused_pane();
637 if(edl->local_session->get_selectionend(1) >=
638 (double)edl->local_session->view_start[pane->number] *
639 edl->local_session->zoom_sample /
640 edl->session->sample_rate +
641 pane->canvas->time_visible() ||
642 edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start[pane->number] *
643 edl->local_session->zoom_sample /
644 edl->session->sample_rate)
646 samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
647 edl->session->sample_rate /
648 edl->local_session->zoom_sample -
649 pane->canvas->get_w() /
652 cwindow->update(1, 0, 0, 0, 0);
656 gui->update_patchbay();
657 gui->update_timebar(0);
660 gui->zoombar->update();
661 gui->flash_canvas(1);
662 cwindow->update(1, 0, 0, 0, 1);
672 int MWindow::prev_edit_handle(int shift_down)
674 double position = edl->local_session->get_selectionstart(1);
675 double new_position = -1;
676 Units::fix_double(&position);
677 // Test for edit handles before cursor position
678 for (Track *track = edl->tracks->first; track; track = track->next)
682 for (Edit *edit = track->edits->first; edit; edit = edit->next)
684 double edit_end = track->from_units(edit->startproject);
685 Units::fix_double(&edit_end);
686 if (edit_end < position && edit_end > new_position)
687 new_position = edit_end;
692 if(new_position != -1)
695 edl->local_session->set_selectionstart(new_position);
696 //printf("MWindow::next_edit_handle %d\n", shift_down);
698 edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
700 update_plugin_guis();
701 // Scroll the display
702 TimelinePane *pane = gui->get_focused_pane();
703 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start[pane->number] *
704 edl->local_session->zoom_sample /
705 edl->session->sample_rate +
706 pane->canvas->time_visible()
708 edl->local_session->get_selectionstart(1) < edl->local_session->view_start[pane->number] *
709 edl->local_session->zoom_sample /
710 edl->session->sample_rate)
712 samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
713 edl->session->sample_rate /
714 edl->local_session->zoom_sample -
715 pane->canvas->get_w() /
718 cwindow->update(1, 0, 0, 0, 0);
721 // Don't scroll the display
723 gui->update_patchbay();
724 gui->update_timebar(0);
727 gui->zoombar->update();
728 gui->flash_canvas(1);
729 cwindow->update(1, 0, 0, 0, 1);
746 int MWindow::expand_y()
748 int result = edl->local_session->zoom_y * 2;
749 result = MIN(result, MAX_AMP_ZOOM);
751 gui->zoombar->update();
755 int MWindow::zoom_in_y()
757 int result = edl->local_session->zoom_y / 2;
758 result = MAX(result, MIN_AMP_ZOOM);
760 gui->zoombar->update();
764 int MWindow::expand_t()
766 int result = edl->local_session->zoom_track * 2;
767 result = MIN(result, MAX_TRACK_ZOOM);
769 gui->zoombar->update();
773 int MWindow::zoom_in_t()
775 int result = edl->local_session->zoom_track / 2;
776 result = MAX(result, MIN_TRACK_ZOOM);
778 gui->zoombar->update();
782 void MWindow::split_x()
784 gui->resource_thread->stop_draw(1);
786 if(gui->pane[TOP_RIGHT_PANE])
788 gui->delete_x_pane(theme->mcanvas_w);
789 edl->local_session->x_pane = -1;
793 gui->create_x_pane(theme->mcanvas_w / 2);
794 edl->local_session->x_pane = theme->mcanvas_w / 2;
797 gui->mainmenu->update_toggles(0);
798 gui->update_pane_dividers();
799 gui->update_cursor();
800 // required to get new widgets to appear
803 gui->resource_thread->start_draw();
806 void MWindow::split_y()
808 gui->resource_thread->stop_draw(1);
809 if(gui->pane[BOTTOM_LEFT_PANE])
811 gui->delete_y_pane(theme->mcanvas_h);
812 edl->local_session->y_pane = -1;
816 gui->create_y_pane(theme->mcanvas_h / 2);
817 edl->local_session->y_pane = theme->mcanvas_h / 2;
820 gui->mainmenu->update_toggles(0);
821 gui->update_pane_dividers();
822 gui->update_cursor();
823 // required to get new widgets to appear
825 gui->resource_thread->start_draw();