r827: Fix a crash when no audio output device can be opened.
[cinelerra_cv.git] / cinelerra / mwindowmove.C
blobafcc8615efa47ff21a2df5f98fc8dc3269dad45a
1 #include "clip.h"
2 #include "cplayback.h"
3 #include "cwindow.h"
4 #include "cwindowgui.h"
5 #include "edl.h"
6 #include "edlsession.h"
7 #include "labels.h"
8 #include "localsession.h"
9 #include "maincursor.h"
10 #include "mainsession.h"
11 #include "mtimebar.h"
12 #include "mwindow.h"
13 #include "mwindowgui.h"
14 #include "patchbay.h"
15 #include "playbackengine.h"
16 #include "plugin.h"
17 #include "samplescroll.h"
18 #include "trackcanvas.h"
19 #include "tracks.h"
20 #include "transportque.h"
21 #include "zoombar.h"
22 #include "edits.h"
24 void MWindow::update_plugins()
26 // Show plugins which are visible and hide plugins which aren't
27 // Update plugin pointers in plugin servers
31 int MWindow::expand_sample(double fixed_sample)
33         if(gui)
34         {
35                 if(edl->local_session->zoom_sample < 0x100000)
36                 {
38                         int64_t new_zoom_sample = edl->local_session->zoom_sample * 2;
39                         int64_t view_start;
40                         if (fixed_sample < 0)
41                                 view_start = -1;
42                         else
43                         {
44                                 double viewstart_position = (double)edl->local_session->view_start * 
45                                         edl->local_session->zoom_sample /
46                                         edl->session->sample_rate * 2 - fixed_sample;
47                                 view_start = Units::round(viewstart_position *
48                                         edl->session->sample_rate /
49                                         new_zoom_sample);
50                         }
51                         
52                         zoom_sample(new_zoom_sample, view_start);
53                 }
54         }
55         return 0;
58 int MWindow::zoom_in_sample(double fixed_sample)
60         if(gui)
61         {
62                 if(edl->local_session->zoom_sample > 1)
63                 {
64                         int64_t new_zoom_sample = edl->local_session->zoom_sample / 2;
65                         int64_t view_start;
66                         if (fixed_sample < 0)
67                                 view_start = -1;
68                         else
69                         {
70                                 double viewstart_position = (double)edl->local_session->view_start * 
71                                         edl->local_session->zoom_sample /
72                                         edl->session->sample_rate;
73                                 viewstart_position = viewstart_position + (fixed_sample - viewstart_position) / 2;
75                                 view_start = Units::round(viewstart_position *
76                                         edl->session->sample_rate /
77                                         new_zoom_sample);
78                         }
79                         
80                         zoom_sample(new_zoom_sample, view_start);
81                 }
82         }
83         return 0;
86 int MWindow::zoom_sample(int64_t zoom_sample, int64_t view_start)
88         CLIP(zoom_sample, 1, 0x100000);
89         edl->local_session->zoom_sample = zoom_sample;
90         if (view_start < 0)
91                 find_cursor();
92         else
93                 edl->local_session->view_start = view_start;
94                         
95         gui->get_scrollbars();
97         if(!gui->samplescroll) edl->local_session->view_start = 0;
98         samplemovement(edl->local_session->view_start);
99         gui->zoombar->sample_zoom->update(zoom_sample);
100         return 0;
103 void MWindow::find_cursor()
105 //      if((edl->local_session->selectionend > 
106 //              (double)gui->canvas->get_w() * 
107 //              edl->local_session->zoom_sample / 
108 //              edl->session->sample_rate) ||
109 //              (edl->local_session->selectionstart > 
110 //              (double)gui->canvas->get_w() * 
111 //              edl->local_session->zoom_sample / 
112 //              edl->session->sample_rate))
113 //      {
114                 edl->local_session->view_start = 
115                         Units::round((edl->local_session->get_selectionend(1) + 
116                         edl->local_session->get_selectionstart(1)) / 
117                         2 *
118                         edl->session->sample_rate /
119                         edl->local_session->zoom_sample - 
120                         (double)gui->canvas->get_w() / 
121                         2);
122 //      }
123 //      else
124 //              edl->local_session->view_start = 0;
126 //printf("MWindow::find_cursor %f\n", edl->local_session->view_start);
127         if(edl->local_session->view_start < 0) edl->local_session->view_start = 0;
131 void MWindow::fit_selection()
133         if(EQUIV(edl->local_session->get_selectionstart(1),
134                 edl->local_session->get_selectionend(1)))
135         {
136                 double total_samples = edl->tracks->total_length() * 
137                         edl->session->sample_rate;
138                 for(edl->local_session->zoom_sample = 1; 
139                         gui->canvas->get_w() * edl->local_session->zoom_sample < total_samples; 
140                         edl->local_session->zoom_sample *= 2)
141                         ;
142         }
143         else
144         {
145                 double total_samples = (edl->local_session->get_selectionend(1) - 
146                         edl->local_session->get_selectionstart(1)) * 
147                         edl->session->sample_rate;
148                 for(edl->local_session->zoom_sample = 1; 
149                         gui->canvas->get_w() * edl->local_session->zoom_sample < total_samples; 
150                         edl->local_session->zoom_sample *= 2)
151                         ;
152         }
154         edl->local_session->zoom_sample = MIN(0x100000, 
155                 edl->local_session->zoom_sample);
156         zoom_sample(edl->local_session->zoom_sample);
160 void MWindow::fit_autos()
162         float min = 0, max = 0;
163         double start, end;
165 // Test all autos
166         if(EQUIV(edl->local_session->get_selectionstart(1),
167                 edl->local_session->get_selectionend(1)))
168         {
169                 start = 0;
170                 end = edl->tracks->total_length();
171         }
172         else
173 // Test autos in highlighting only
174         {
175                 start = edl->local_session->get_selectionstart(1);
176                 end = edl->local_session->get_selectionend(1);
177         }
179 // Adjust min and max
180         edl->tracks->get_automation_extents(&min, &max, start, end);
181 //printf("MWindow::fit_autos %f %f\n", min, max);
183 // Pad
184         float range = max - min;
185 // No automation visible
186         if(range < 0.001)
187         {
188                 min -= 1;
189                 max += 1;
190         }
191         float pad = range * 0.33;
192         min -= pad;
193         max += pad;
194         edl->local_session->automation_min = min;
195         edl->local_session->automation_max = max;
197 // Show range in zoombar
198         gui->zoombar->update();
200 // Draw
201         gui->canvas->draw_overlays();
202         gui->canvas->flash();
206 void MWindow::expand_autos()
208         float range = edl->local_session->automation_max - 
209                 edl->local_session->automation_min;
210         float center = range / 2 + 
211                 edl->local_session->automation_min;
212         if(EQUIV(range, 0)) range = 0.002;
213         edl->local_session->automation_min = center - range;
214         edl->local_session->automation_max = center + range;
215         gui->zoombar->update_autozoom();
216         gui->canvas->draw_overlays();
217         gui->canvas->flash();
220 void MWindow::shrink_autos()
222         float range = edl->local_session->automation_max - 
223                 edl->local_session->automation_min;
224         float center = range / 2 + 
225                 edl->local_session->automation_min;
226         float new_range = range / 4;
227         edl->local_session->automation_min = center - new_range;
228         edl->local_session->automation_max = center + new_range;
229         gui->zoombar->update_autozoom();
230         gui->canvas->draw_overlays();
231         gui->canvas->flash();
235 void MWindow::zoom_amp(int64_t zoom_amp)
237         edl->local_session->zoom_y = zoom_amp;
238         gui->canvas->draw(0, 0);
239         gui->canvas->flash();
240         gui->patchbay->update();
241         gui->flush();
244 void MWindow::zoom_track(int64_t zoom_track)
246         edl->local_session->zoom_y = (int64_t)((float)edl->local_session->zoom_y * 
247                 zoom_track / 
248                 edl->local_session->zoom_track);
249         CLAMP(edl->local_session->zoom_y, MIN_AMP_ZOOM, MAX_AMP_ZOOM);
250         edl->local_session->zoom_track = zoom_track;
251         trackmovement(edl->local_session->track_start);
252 //printf("MWindow::zoom_track %d %d\n", edl->local_session->zoom_y, edl->local_session->zoom_track);
255 void MWindow::trackmovement(int track_start)
257         edl->local_session->track_start = track_start;
258         if(edl->local_session->track_start < 0) edl->local_session->track_start = 0;
259         edl->tracks->update_y_pixels(theme);
260         gui->get_scrollbars();
261         gui->canvas->draw(0, 0);
262         gui->patchbay->update();
263         gui->canvas->flash();
264         gui->flush();
267 void MWindow::move_up(int64_t distance)
269         if(!gui->trackscroll) return;
270         if(distance == 0) distance = edl->local_session->zoom_track;
271         edl->local_session->track_start -= distance;
272         trackmovement(edl->local_session->track_start);
275 void MWindow::move_down(int64_t distance)
277         if(!gui->trackscroll) return;
278         if(distance == 0) distance = edl->local_session->zoom_track;
279         edl->local_session->track_start += distance;
280         trackmovement(edl->local_session->track_start);
283 int MWindow::goto_end()
285         int64_t old_view_start = edl->local_session->view_start;
287         if(edl->tracks->total_length() > (double)gui->canvas->get_w() * 
288                 edl->local_session->zoom_sample / 
289                 edl->session->sample_rate)
290         {
291                 edl->local_session->view_start = 
292                         Units::round(edl->tracks->total_length() * 
293                                 edl->session->sample_rate /
294                                 edl->local_session->zoom_sample - 
295                                 gui->canvas->get_w() / 
296                                 2);
297         }
298         else
299         {
300                 edl->local_session->view_start = 0;
301         }
303         if(gui->shift_down())
304         {
305                 edl->local_session->set_selectionend(edl->tracks->total_length());
306         }
307         else
308         {
309                 edl->local_session->set_selectionstart(edl->tracks->total_length());
310                 edl->local_session->set_selectionend(edl->tracks->total_length());
311         }
313         if(edl->local_session->view_start != old_view_start) 
314                 samplemovement(edl->local_session->view_start);
316         update_plugin_guis();
317         gui->patchbay->update();
318         gui->cursor->update();
319         gui->canvas->activate();
320         gui->zoombar->update();
321         cwindow->update(1, 0, 0, 0, 0);
322         return 0;
325 int MWindow::goto_start()
327         int64_t old_view_start = edl->local_session->view_start;
329         edl->local_session->view_start = 0;
330         if(gui->shift_down())
331         {
332                 edl->local_session->set_selectionstart(0);
333         }
334         else
335         {
336                 edl->local_session->set_selectionstart(0);
337                 edl->local_session->set_selectionend(0);
338         }
340         if(edl->local_session->view_start != old_view_start)
341                 samplemovement(edl->local_session->view_start);
343         update_plugin_guis();
344         gui->patchbay->update();
345         gui->cursor->update();
346         gui->canvas->activate();
347         gui->zoombar->update();
348         cwindow->update(1, 0, 0, 0, 0);
349         return 0;
352 int MWindow::samplemovement(int64_t view_start)
354         edl->local_session->view_start = view_start;
355         if(edl->local_session->view_start < 0) edl->local_session->view_start = 0;
356         gui->canvas->draw();
357         gui->cursor->show();
358         gui->canvas->flash();
359         gui->timebar->update();
360         gui->zoombar->update();
362         if(gui->samplescroll) gui->samplescroll->set_position();
363         return 0;
366 int MWindow::move_left(int64_t distance)
368         if(!distance) 
369                 distance = gui->canvas->get_w() / 
370                         10;
371         edl->local_session->view_start -= distance;
372         if(edl->local_session->view_start < 0) edl->local_session->view_start = 0;
373         samplemovement(edl->local_session->view_start);
374         return 0;
377 int MWindow::move_right(int64_t distance)
379         if(!distance) 
380                 distance = gui->canvas->get_w() / 
381                         10;
382         edl->local_session->view_start += distance;
383         samplemovement(edl->local_session->view_start);
384         return 0;
387 void MWindow::select_all()
389         edl->local_session->set_selectionstart(0);
390         edl->local_session->set_selectionend(edl->tracks->total_length());
391         gui->update(0, 1, 1, 1, 0, 1, 0);
392         gui->canvas->activate();
393         cwindow->update(1, 0, 0);
396 int MWindow::next_label()
398         Label *current = edl->labels->next_label(
399                         edl->local_session->get_selectionstart(1));
401         if(current)
402         {
404                 edl->local_session->set_selectionend(current->position);
405                 if(!gui->shift_down()) 
406                         edl->local_session->set_selectionstart(
407                                 edl->local_session->get_selectionend(1));
409                 if(edl->local_session->get_selectionend(1) >= 
410                         (double)edl->local_session->view_start *
411                         edl->local_session->zoom_sample /
412                         edl->session->sample_rate + 
413                         gui->canvas->time_visible() ||
414                         edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start *
415                         edl->local_session->zoom_sample /
416                         edl->session->sample_rate)
417                 {
418                         samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
419                                 edl->session->sample_rate /
420                                 edl->local_session->zoom_sample - 
421                                 gui->canvas->get_w() / 
422                                 2));
423                         cwindow->update(1, 0, 0, 0, 0);
424                 }
425                 else
426                 {
427                         update_plugin_guis();
428                         gui->patchbay->update();
429                         gui->timebar->update();
430                         gui->cursor->hide();
431                         gui->cursor->draw();
432                         gui->zoombar->update();
433                         gui->canvas->flash();
434                         gui->flush();
435                         cwindow->update(1, 0, 0);
436                 }
437         }
438         else
439         {
440                 goto_end();
441         }
442         return 0;
445 int MWindow::prev_label()
447         Label *current = edl->labels->prev_label(
448                         edl->local_session->get_selectionstart(1));;
450         if(current)
451         {
452                 edl->local_session->set_selectionstart(current->position);
453                 if(!gui->shift_down()) 
454                         edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
456 // Scroll the display
457                 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start *
458                         edl->local_session->zoom_sample /
459                         edl->session->sample_rate + 
460                         gui->canvas->time_visible() 
461                 ||
462                         edl->local_session->get_selectionstart(1) < edl->local_session->view_start *
463                         edl->local_session->zoom_sample /
464                         edl->session->sample_rate)
465                 {
466                         samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
467                                 edl->session->sample_rate /
468                                 edl->local_session->zoom_sample - 
469                                 gui->canvas->get_w() / 
470                                 2));
471                         cwindow->update(1, 0, 0, 0, 0);
472                 }
473                 else
474 // Don't scroll the display
475                 {
476                         update_plugin_guis();
477                         gui->patchbay->update();
478                         gui->timebar->update();
479                         gui->cursor->hide();
480                         gui->cursor->draw();
481                         gui->zoombar->update();
482                         gui->canvas->flash();
483                         gui->flush();
484                         cwindow->update(1, 0, 0);
485                 }
486         }
487         else
488         {
489                 goto_start();
490         }
491         return 0;
494 int MWindow::next_edit_handle()
496         double position = edl->local_session->get_selectionend(1);
497         double new_position = INFINITY;
498 // Test for edit handles after cursor position
499         for (Track *track = edl->tracks->first; track; track = track->next)
500         {
501                 if (track->record)
502                 {
503                         for (Edit *edit = track->edits->first; edit; edit = edit->next)
504                         {
505                                 double edit_end = track->from_units(edit->startproject + edit->length);
506                                 if (edit_end > position && edit_end < new_position)
507                                         new_position = edit_end;
508                         }
509                 }
510         }
512         if(new_position != INFINITY)
513         {
515                 edl->local_session->set_selectionend(new_position);
516                 if(!gui->shift_down()) 
517                         edl->local_session->set_selectionstart(
518                                 edl->local_session->get_selectionend(1));
520                 if(edl->local_session->get_selectionend(1) >= 
521                         (double)edl->local_session->view_start *
522                         edl->local_session->zoom_sample /
523                         edl->session->sample_rate + 
524                         gui->canvas->time_visible() ||
525                         edl->local_session->get_selectionend(1) < (double)edl->local_session->view_start *
526                         edl->local_session->zoom_sample /
527                         edl->session->sample_rate)
528                 {
529                         samplemovement((int64_t)(edl->local_session->get_selectionend(1) *
530                                 edl->session->sample_rate /
531                                 edl->local_session->zoom_sample - 
532                                 gui->canvas->get_w() / 
533                                 2));
534                         cwindow->update(1, 0, 0, 0, 0);
535                 }
536                 else
537                 {
538                         update_plugin_guis();
539                         gui->patchbay->update();
540                         gui->timebar->update();
541                         gui->cursor->hide();
542                         gui->cursor->draw();
543                         gui->zoombar->update();
544                         gui->canvas->flash();
545                         gui->flush();
546                         cwindow->update(1, 0, 0);
547                 }
548         }
549         else
550         {
551                 goto_end();
552         }
553         return 0;
556 int MWindow::prev_edit_handle()
558         double position = edl->local_session->get_selectionstart(1);
559         double new_position = -1;
560 // Test for edit handles before cursor position
561         for (Track *track = edl->tracks->first; track; track = track->next)
562         {
563                 if (track->record)
564                 {
565                         for (Edit *edit = track->edits->first; edit; edit = edit->next)
566                         {
567                                 double edit_end = track->from_units(edit->startproject);
568                                 if (edit_end < position && edit_end > new_position)
569                                         new_position = edit_end;
570                         }
571                 }
572         }
574         if(new_position != -1)
575         {
577                 edl->local_session->set_selectionstart(new_position);
578                 if(!gui->shift_down()) 
579                         edl->local_session->set_selectionend(edl->local_session->get_selectionstart(1));
581 // Scroll the display
582                 if(edl->local_session->get_selectionstart(1) >= edl->local_session->view_start *
583                         edl->local_session->zoom_sample /
584                         edl->session->sample_rate + 
585                         gui->canvas->time_visible() 
586                 ||
587                         edl->local_session->get_selectionstart(1) < edl->local_session->view_start *
588                         edl->local_session->zoom_sample /
589                         edl->session->sample_rate)
590                 {
591                         samplemovement((int64_t)(edl->local_session->get_selectionstart(1) *
592                                 edl->session->sample_rate /
593                                 edl->local_session->zoom_sample - 
594                                 gui->canvas->get_w() / 
595                                 2));
596                         cwindow->update(1, 0, 0, 0, 0);
597                 }
598                 else
599 // Don't scroll the display
600                 {
601                         update_plugin_guis();
602                         gui->patchbay->update();
603                         gui->timebar->update();
604                         gui->cursor->hide();
605                         gui->cursor->draw();
606                         gui->zoombar->update();
607                         gui->canvas->flash();
608                         gui->flush();
609                         cwindow->update(1, 0, 0);
610                 }
611         }
612         else
613         {
614                 goto_start();
615         }
616         return 0;
621 int MWindow::expand_y()
623         int result = edl->local_session->zoom_y * 2;
624         result = MIN(result, MAX_AMP_ZOOM);
625         zoom_amp(result);
626         gui->zoombar->update();
627         return 0;
630 int MWindow::zoom_in_y()
632         int result = edl->local_session->zoom_y / 2;
633         result = MAX(result, MIN_AMP_ZOOM);
634         zoom_amp(result);
635         gui->zoombar->update();
636         return 0;
639 int MWindow::expand_t()
641         int result = edl->local_session->zoom_track * 2;
642         result = MIN(result, MAX_TRACK_ZOOM);
643         zoom_track(result);
644         gui->zoombar->update();
645         return 0;
648 int MWindow::zoom_in_t()
650         int result = edl->local_session->zoom_track / 2;
651         result = MAX(result, MIN_TRACK_ZOOM);
652         zoom_track(result);
653         gui->zoombar->update();
654         return 0;