Fourth set of 50 GPL attribution for CV-Contributors added +
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / vtrack.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * Copyright (C) 2003-2016 Cinelerra CV contributors
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include "asset.h"
24 #include "autoconf.h"
25 #include "cache.h"
26 #include "clip.h"
27 #include "datatype.h"
28 #include "edit.h"
29 #include "edits.h"
30 #include "edl.h"
31 #include "edlsession.h"
32 #include "filexml.h"
33 #include "floatauto.h"
34 #include "floatautos.h"
35 #include "language.h"
36 #include "localsession.h"
37 #include "patch.h"
38 #include "mainsession.h"
39 #include "theme.h"
40 #include "trackcanvas.h"
41 #include "tracks.h"
42 #include "transportque.inc"
43 #include "units.h"
44 #include "vautomation.h"
45 #include "vedit.h"
46 #include "vedits.h"
47 #include "vframe.h"
48 #include "vmodule.h"
49 #include "vpluginset.h"
50 #include "vtrack.h"
51
52 VTrack::VTrack(EDL *edl, Tracks *tracks)
53  : Track(edl, tracks)
54 {
55         data_type = TRACK_VIDEO;
56         data_h = edl->local_session->zoom_vtrack;
57         draw = 1;
58 }
59
60 VTrack::~VTrack()
61 {
62 }
63
64 void VTrack::create_objects()
65 {
66         Track::create_objects();
67         automation = new VAutomation(edl, this);
68         automation->create_objects();
69         edits = new VEdits(edl, this);
70 }
71
72 // Used by PlaybackEngine
73 void VTrack::synchronize_params(Track *track)
74 {
75         Track::synchronize_params(track);
76         //VTrack *vtrack = (VTrack*)track;
77 }
78
79 // Used by EDL::operator=
80 int VTrack::copy_settings(Track *track)
81 {
82         Track::copy_settings(track);
83         //VTrack *vtrack = (VTrack*)track;
84         return 0;
85 }
86
87 int VTrack::vertical_span(Theme *theme)
88 {
89         int track_h = Track::vertical_span(theme);
90         int patch_h = theme->title_h;
91         if( expand_view )
92                 patch_h += theme->play_h + theme->fade_h + theme->mode_h;
93         return MAX(track_h, patch_h);
94 }
95
96
97 PluginSet* VTrack::new_plugins()
98 {
99         return new VPluginSet(edl, this);
100 }
101
102 int VTrack::load_defaults(BC_Hash *defaults)
103 {
104         Track::load_defaults(defaults);
105         return 0;
106 }
107
108 void VTrack::set_default_title()
109 {
110         Track *current = ListItem<Track>::list->first;
111         int i;
112         for(i = 0; current; current = NEXT)
113         {
114                 if(current->data_type == TRACK_VIDEO) i++;
115         }
116         sprintf(title, _("Video %d"), i);
117         BC_Resources::encode_to_utf8(title, BCTEXTLEN);
118 }
119
120 int64_t VTrack::to_units(double position, int round)
121 {
122         return round ? Units::round(position * edl->session->frame_rate) :
123                 Units::to_int64(position * edl->session->frame_rate + 1e-6);
124 }
125
126 double VTrack::to_doubleunits(double position)
127 {
128         return position * edl->session->frame_rate;
129 }
130
131
132 double VTrack::from_units(int64_t position)
133 {
134         return (double)position / edl->session->frame_rate;
135 }
136
137
138
139
140 int VTrack::identical(int64_t sample1, int64_t sample2)
141 {
142 // Units of frames
143         if(labs(sample1 - sample2) <= 1) return 1; else return 0;
144 }
145
146 int VTrack::save_header(FileXML *file)
147 {
148         file->tag.set_property("TYPE", "VIDEO");
149         return 0;
150 }
151
152 int VTrack::save_derived(FileXML *file)
153 {
154         return 0;
155 }
156
157 int VTrack::load_header(FileXML *file, uint32_t load_flags)
158 {
159         return 0;
160 }
161
162 int VTrack::load_derived(FileXML *file, uint32_t load_flags)
163 {
164         return 0;
165 }
166
167
168 int VTrack::direct_copy_possible(int64_t start, int direction, int use_nudge)
169 {
170         if(use_nudge) start += nudge;
171
172 // Track size must equal output size
173         if(track_w != edl->session->output_w || track_h != edl->session->output_h)
174                 return 0;
175
176         if(has_speed()) return 0;
177
178 // No automation must be present in the track
179         if(!automation->direct_copy_possible(start, direction))
180                 return 0;
181
182 // No plugin must be present
183         if(plugin_used(start, direction))
184                 return 0;
185
186 // No transition
187         if(get_current_transition(start, direction, 0, 0))
188                 return 0;
189
190         return 1;
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 int VTrack::create_derived_objs(int flash)
210 {
211         edits = new VEdits(edl, this);
212         return 0;
213 }
214
215
216 // int VTrack::get_dimensions(double &view_start,
217 //      double &view_units,
218 //      double &zoom_units)
219 // {
220 //      view_start = edl->local_session->view_start * edl->session->frame_rate;
221 //      view_units = 0;
222 //      zoom_units = edl->local_session->zoom_sample / edl->session->sample_rate * edl->session->frame_rate;
223 //      return 0;
224 // }
225
226 int VTrack::copy_derived(int64_t start, int64_t end, FileXML *xml)
227 {
228 // automation is copied in the Track::copy
229         return 0;
230 }
231
232 int VTrack::copy_automation_derived(AutoConf *auto_conf, int64_t start, int64_t end, FileXML *file)
233 {
234         return 0;
235 }
236
237 int VTrack::paste_derived(int64_t start, int64_t end, int64_t total_length, FileXML *xml, int &current_channel)
238 {
239         return 0;
240 }
241
242 int VTrack::paste_output(int64_t startproject, int64_t endproject, int64_t startsource, int64_t endsource, int layer, Asset *asset)
243 {
244         return 0;
245 }
246
247 int VTrack::clear_derived(int64_t start, int64_t end)
248 {
249         return 0;
250 }
251
252 int VTrack::paste_automation_derived(int64_t start, int64_t end, int64_t total_length, FileXML *xml, int shift_autos, int &current_pan)
253 {
254         return 0;
255 }
256
257 int VTrack::clear_automation_derived(AutoConf *auto_conf, int64_t start, int64_t end, int shift_autos)
258 {
259         return 0;
260 }
261
262 int VTrack::draw_autos_derived(float view_start, float zoom_units, AutoConf *auto_conf)
263 {
264         return 0;
265 }
266
267
268 int VTrack::select_auto_derived(float zoom_units, float view_start, AutoConf *auto_conf, int cursor_x, int cursor_y)
269 {
270         return 0;
271 }
272
273
274 int VTrack::move_auto_derived(float zoom_units, float view_start, AutoConf *auto_conf, int cursor_x, int cursor_y, int shift_down)
275 {
276         return 0;
277 }
278
279 int VTrack::draw_floating_autos_derived(float view_start, float zoom_units, AutoConf *auto_conf, int flash)
280 {
281         return 0;
282 }
283
284 int VTrack::is_playable(int64_t position, int direction)
285 {
286         int result = 0;
287         float in_x, in_y, in_w, in_h;
288         float out_x, out_y, out_w, out_h;
289
290         calculate_output_transfer(position,
291                 direction,
292                 in_x, in_y, in_w, in_h,
293                 out_x, out_y, out_w, out_h);
294
295 //printf("VTrack::is_playable %0.0f %0.0f %0.0f %0.0f %0.0f %0.0f %0.0f %0.0f\n",
296 //in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h);
297         if(out_w > 0 && out_h > 0)
298                 result = 1;
299         return result;
300 }
301
302 void VTrack::calculate_input_transfer(int asset_w, int asset_h,
303         int64_t position, int direction,
304         float &in_x, float &in_y, float &in_w, float &in_h,
305         float &out_x, float &out_y, float &out_w, float &out_h)
306 {
307         float auto_x, auto_y, auto_z;
308         float camera_z = 1.;
309         float camera_x = asset_w / 2.;
310         float camera_y = asset_h / 2.;
311 // camera and output coords
312         float x[6], y[6];
313
314 //printf("VTrack::calculate_input_transfer %jd\n", position);
315
316 // get camera center in asset
317         automation->get_camera(&auto_x, &auto_y, &auto_z,
318                 position, direction);
319
320         camera_z *= auto_z;
321         camera_x += auto_x;
322         camera_y += auto_y;
323
324 // get camera coords on asset
325         x[0] = camera_x - (float)track_w / 2 / camera_z;
326         y[0] = camera_y - (float)track_h / 2 / camera_z;
327         x[1] = x[0] + (float)track_w / camera_z;
328         y[1] = y[0] + (float)track_h / camera_z;
329
330 // get asset coords on camera
331         x[2] = 0;
332         y[2] = 0;
333         x[3] = track_w;
334         y[3] = track_h;
335
336 // crop asset coords on camera
337         if(x[0] < 0)
338         {
339                 x[2] -= x[0] * camera_z;
340                 x[0] = 0;
341         }
342         if(y[0] < 0)
343         {
344                 y[2] -= y[0] * camera_z;
345                 y[0] = 0;
346         }
347         if(x[1] > asset_w)
348         {
349                 x[3] -= (x[1] - asset_w) * camera_z;
350                 x[1] = asset_w;
351         }
352         if(y[1] > asset_h)
353         {
354                 y[3] -= (y[1] - asset_h) * camera_z;
355                 y[1] = asset_h;
356         }
357
358 // get output bounding box
359         out_x = x[2];
360         out_y = y[2];
361         out_w = x[3] - x[2];
362         out_h = y[3] - y[2];
363
364         in_x = x[0];
365         in_y = y[0];
366         in_w = x[1] - x[0];
367         in_h = y[1] - y[0];
368 // printf("VTrack::calculate_input_transfer %f %f %f %f -> %f %f %f %f\n",
369 // in_x, in_y, in_w, in_h,
370 // out_x, out_y, out_w, out_h);
371 }
372
373 void VTrack::calculate_output_transfer(int64_t position, int direction,
374         float &in_x, float &in_y, float &in_w, float &in_h,
375         float &out_x, float &out_y, float &out_w, float &out_h)
376 {
377         float center_x, center_y, center_z;
378         float x[4], y[4];
379
380         x[0] = 0;
381         y[0] = 0;
382         x[1] = track_w;
383         y[1] = track_h;
384
385         automation->get_projector(&center_x,
386                 &center_y,
387                 &center_z,
388                 position,
389                 direction);
390
391         center_x += edl->session->output_w / 2;
392         center_y += edl->session->output_h / 2;
393
394         x[2] = center_x - (track_w / 2) * center_z;
395         y[2] = center_y - (track_h / 2) * center_z;
396         x[3] = x[2] + track_w * center_z;
397         y[3] = y[2] + track_h * center_z;
398
399 // Clip to boundaries of output
400         if(x[2] < 0)
401         {
402                 x[0] -= (x[2] - 0) / center_z;
403                 x[2] = 0;
404         }
405         if(y[2] < 0)
406         {
407                 y[0] -= (y[2] - 0) / center_z;
408                 y[2] = 0;
409         }
410         if(x[3] > edl->session->output_w)
411         {
412                 x[1] -= (x[3] - edl->session->output_w) / center_z;
413                 x[3] = edl->session->output_w;
414         }
415         if(y[3] > edl->session->output_h)
416         {
417                 y[1] -= (y[3] - edl->session->output_h) / center_z;
418                 y[3] = edl->session->output_h;
419         }
420
421         in_x = x[0];
422         in_y = y[0];
423         in_w = x[1] - x[0];
424         in_h = y[1] - y[0];
425         out_x = x[2];
426         out_y = y[2];
427         out_w = x[3] - x[2];
428         out_h = y[3] - y[2];
429 // printf("VTrack::calculate_output_transfer %f %f %f %f -> %f %f %f %f\n",
430 // in_x, in_y, in_w, in_h,
431 // out_x, out_y, out_w, out_h);
432 }
433
434
435
436 int VTrack::get_projection(float &in_x1, float &in_y1, float &in_x2, float &in_y2,
437         float &out_x1, float &out_y1, float &out_x2, float &out_y2,
438         int frame_w, int frame_h, int64_t real_position, int direction)
439 {
440         float center_x, center_y, center_z;
441         float x[4], y[4];
442
443         automation->get_projector(&center_x,
444                 &center_y,
445                 &center_z,
446                 real_position,
447                 direction);
448
449         x[0] = y[0] = 0;
450         x[1] = frame_w;
451         y[1] = frame_h;
452
453         center_x += edl->session->output_w / 2;
454         center_y += edl->session->output_h / 2;
455
456         x[2] = center_x - (frame_w / 2) * center_z;
457         y[2] = center_y - (frame_h / 2) * center_z;
458         x[3] = x[2] + frame_w * center_z;
459         y[3] = y[2] + frame_h * center_z;
460
461         if(x[2] < 0)
462         {
463                 x[0] -= x[2] / center_z;
464                 x[2] = 0;
465         }
466         if(y[2] < 0)
467         {
468                 y[0] -= y[2] / center_z;
469                 y[2] = 0;
470         }
471         if(x[3] > edl->session->output_w)
472         {
473                 x[1] -= (x[3] - edl->session->output_w) / center_z;
474                 x[3] = edl->session->output_w;
475         }
476         if(y[3] > edl->session->output_h)
477         {
478                 y[1] -= (y[3] - edl->session->output_h) / center_z;
479                 y[3] = edl->session->output_h;
480         }
481
482         in_x1 = x[0];  in_y1 = y[0];  in_x2 = x[1];  in_y2 = y[1];
483         out_x1 = x[2]; out_y1 = y[2]; out_x2 = x[3]; out_y2 = y[3];
484         return 0;
485 }
486
487
488
489 static inline void addto_value(FloatAuto *fauto, float offset)
490 {
491         fauto->set_value(fauto->get_value() + offset);
492 }
493
494 static inline void multiply_value(FloatAuto *fauto, float scale)
495 {
496         fauto->set_value(fauto->get_value() * scale);
497 }
498
499
500 void VTrack::set_fauto_xy(int fauto, float x, float y)
501 {
502 // set default keyframe
503         FloatAuto *xdft = (FloatAuto *)automation->autos[fauto+0]->default_auto;
504         FloatAuto *ydft = (FloatAuto *)automation->autos[fauto+1]->default_auto;
505         xdft->set_value(x);
506         ydft->set_value(y);
507 // set everyone else
508         FloatAuto *xauto = (FloatAuto *)automation->autos[fauto+0]->first;
509         FloatAuto *yauto = (FloatAuto *)automation->autos[fauto+1]->first;
510         for( ; xauto; xauto=(FloatAuto *)xauto->next ) xauto->set_value(x);
511         for( ; yauto; yauto=(FloatAuto *)yauto->next ) yauto->set_value(y);
512 }
513
514 void VTrack::translate(int fauto, float dx, float dy, int all)
515 {
516         if( all ) {
517                 addto_value((FloatAuto*)automation->autos[fauto+0]->default_auto, dx);
518                 addto_value((FloatAuto*)automation->autos[fauto+1]->default_auto, dy);
519                 FloatAutos **fautos = (FloatAutos **)&automation->autos;
520                 FloatAuto *xauto = (FloatAuto *)fautos[fauto+0]->first;
521                 FloatAuto *yauto = (FloatAuto *)fautos[fauto+1]->first;
522                 for( ; xauto; xauto=(FloatAuto *)xauto->next ) addto_value(xauto, dx);
523                 for( ; yauto; yauto=(FloatAuto *)yauto->next ) addto_value(yauto, dy);
524         }
525         else {
526                 FloatAutos **fautos = (FloatAutos **)&automation->autos;
527                 FloatAuto *xauto = (FloatAuto *)fautos[fauto+0]->get_auto_for_editing(-1, 1);
528                 FloatAuto *yauto = (FloatAuto *)fautos[fauto+1]->get_auto_for_editing(-1, 1);
529                 addto_value(xauto, dx);
530                 addto_value(yauto, dy);
531         }
532 }
533