r956: README.BUILD - add more library recommendations
[cinelerra_cv/ct.git] / cinelerra / tracks.C
blob2f90298fdb5895144143351d13a86ef65449789a
1 #include "atrack.h"
2 #include "automation.h"
3 #include "cursor.h"
4 #include "clip.h"
5 #include "bchash.h"
6 #include "edit.h"
7 #include "edits.h"
8 #include "edl.h"
9 #include "edlsession.h"
10 #include "file.h"
11 #include "filexml.h"
12 #include "intauto.h"
13 #include "intautos.h"
14 #include "localsession.h"
15 #include "module.h"
16 #include "panauto.h"
17 #include "panautos.h"
18 #include "patchbay.h"
19 #include "mainsession.h"
20 #include "theme.h"
21 #include "track.h"
22 #include "trackcanvas.h"
23 #include "tracks.h"
24 #include "transportque.inc"
25 #include "vtrack.h"
26 #include <string.h>
28 Tracks::Tracks(EDL *edl)
29  : List<Track>()
31         this->edl = edl;
34 Tracks::Tracks()
35  : List<Track>()
40 Tracks::~Tracks()
42         delete_all_tracks();
50 void Tracks::equivalent_output(Tracks *tracks, double *result)
52         if(total_playable_vtracks() != tracks->total_playable_vtracks())
53         {
54                 *result = 0;
55         }
56         else
57         {
58                 Track *current = first;
59                 Track *that_current = tracks->first;
60                 while(current || that_current)
61                 {
62 // Get next video track
63                         while(current && current->data_type != TRACK_VIDEO)
64                                 current = NEXT;
66                         while(that_current && that_current->data_type != TRACK_VIDEO)
67                                 that_current = that_current->next;
69 // One doesn't exist but the other does
70                         if((!current && that_current) ||
71                                 (current && !that_current))
72                         {
73                                 *result = 0;
74                                 break;
75                         }
76                         else
77 // Both exist
78                         if(current && that_current)
79                         {
80                                 current->equivalent_output(that_current, result);
81                                 current = NEXT;
82                                 that_current = that_current->next;
83                         }
84                 }
85         }
91 void Tracks::get_affected_edits(ArrayList<Edit*> *drag_edits, double position, Track *start_track)
93         drag_edits->remove_all();
95         for(Track *track = start_track;
96                 track;
97                 track = track->next)
98         {
99 //printf("Tracks::get_affected_edits 1 %p %d %d\n", track, track->data_type, track->record);
100                 if(track->record)
101                 {
102                         for(Edit *edit = track->edits->first; edit; edit = edit->next)
103                         {
104                                 double startproject = track->from_units(edit->startproject);
105 //printf("Tracks::get_affected_edits 1 %d\n", edl->equivalent(startproject, position));
106                                 if(edl->equivalent(startproject, position))
107                                 {
108                                         drag_edits->append(edit);
109                                         break;
110                                 }
111                         }
112                 }
113         }
117 void Tracks::get_automation_extents(float *min, 
118         float *max,
119         double start,
120         double end,
121         int autogrouptype)
123         *min = 0;
124         *max = 0;
125         int coords_undefined = 1;
126         for(Track *current = first; current; current = NEXT)
127         {
128                 if(current->record)
129                 {
130                         current->automation->get_extents(min,
131                                 max,
132                                 &coords_undefined,
133                                 current->to_units(start, 0),
134                                 current->to_units(end, 1),
135                                 autogrouptype);
136                 }
137         }
141 void Tracks::copy_from(Tracks *tracks)
143         Track *new_track;
145         delete_all_tracks();
146         for(Track *current = tracks->first; current; current = NEXT)
147         {
148                 switch(current->data_type)
149                 {
150                         case TRACK_AUDIO: 
151                                 new_track = add_audio_track(0, 0); 
152                                 break;
153                         case TRACK_VIDEO: 
154                                 new_track = add_video_track(0, 0); 
155                                 break;
156                 }
157                 new_track->copy_from(current);
158         }
161 Tracks& Tracks::operator=(Tracks &tracks)
163 printf("Tracks::operator= 1\n");
164         copy_from(&tracks);
165         return *this;
168 int Tracks::load(FileXML *xml, int &track_offset, uint32_t load_flags)
170 // add the appropriate type of track
171         char string[BCTEXTLEN];
172         Track *track = 0;
173         sprintf(string, "");
174         
175         xml->tag.get_property("TYPE", string);
177         if((load_flags & LOAD_ALL) == LOAD_ALL ||
178                 (load_flags & LOAD_EDITS))
179         {
180                 if(!strcmp(string, "VIDEO"))
181                 {
182                         add_video_track(0, 0);
183                 }
184                 else
185                 {
186                         add_audio_track(0, 0);    // default to audio
187                 }
188                 track = last;
189         }
190         else
191         {
192                 track = get_item_number(track_offset);
193                 track_offset++;
194         }
196 // load it
197         if(track) track->load(xml, track_offset, load_flags);
199         return 0;
202 Track* Tracks::add_audio_track(int above, Track *dst_track)
204         int pixel;
205         ATrack* new_track = new ATrack(edl, this);
206         if(!dst_track)
207         {
208                 dst_track = (above ? first : last);
209         }
211         if(above)
212         {
213                 insert_before(dst_track, (Track*)new_track);
214         }
215         else
216         {
217                 insert_after(dst_track, (Track*)new_track);
218 // Shift effects referenced below the destination track
219         }
221 // Shift effects referenced below the new track
222         for(Track *track = last; 
223                 track && track != new_track; 
224                 track = track->previous)
225         {
226                 change_modules(number_of(track) - 1, number_of(track), 0);
227         }
230         new_track->create_objects();
231         new_track->set_default_title();
233         int current_pan = 0;
234         for(Track *current = first; 
235                 current != (Track*)new_track; 
236                 current = NEXT)
237         {
238                 if(current->data_type == TRACK_AUDIO) current_pan++;
239                 if(current_pan >= edl->session->audio_channels) current_pan = 0;
240         }
244         PanAuto* pan_auto = 
245                 (PanAuto*)new_track->automation->autos[AUTOMATION_PAN]->default_auto;
246         pan_auto->values[current_pan] = 1.0;
248         BC_Pan::calculate_stick_position(edl->session->audio_channels, 
249                 edl->session->achannel_positions, 
250                 pan_auto->values, 
251                 MAX_PAN, 
252                 PAN_RADIUS,
253                 pan_auto->handle_x,
254                 pan_auto->handle_y);
255         return new_track;
258 Track* Tracks::add_video_track(int above, Track *dst_track)
260         int pixel;
261         VTrack* new_track = new VTrack(edl, this);
262         if(!dst_track)
263                 dst_track = (above ? first : last);
265         if(above)
266         {
267                 insert_before(dst_track, (Track*)new_track);
268         }
269         else
270         {
271                 insert_after(dst_track, (Track*)new_track);
272         }
276 // Shift effects referenced below the new track
277         for(Track *track = last; 
278                 track && track != new_track; 
279                 track = track->previous)
280         {
281                 change_modules(number_of(track) - 1, number_of(track), 0);
282         }
286         new_track->create_objects();
287         new_track->set_default_title();
288         return new_track;
292 int Tracks::delete_track(Track *track)
294         if (!track)
295                 return 0;
297         int old_location = number_of(track);
298         detach_shared_effects(old_location);
300 // Shift effects referencing effects below the deleted track
301         for(Track *current = track; 
302                 current;
303                 current = NEXT)
304         {
305                 change_modules(number_of(current), number_of(current) - 1, 0);
306         }
307         if(track) delete track;
309         return 0;
312 int Tracks::detach_shared_effects(int module)
314         for(Track *current = first; current; current = NEXT)
315         {
316                 current->detach_shared_effects(module);
317         }
319         return 0;
322 int Tracks::total_of(int type)
324         int result = 0;
325         IntAuto *mute_keyframe = 0;
326         
327         for(Track *current = first; current; current = NEXT)
328         {
329                 long unit_start = current->to_units(edl->local_session->get_selectionstart(1), 0);
330                 mute_keyframe = 
331                         (IntAuto*)current->automation->autos[AUTOMATION_MUTE]->get_prev_auto(
332                         unit_start, 
333                         PLAY_FORWARD,
334                         (Auto* &)mute_keyframe);
336                 result += 
337                         (current->play && type == PLAY) ||
338                         (current->record && type == RECORD) ||
339                         (current->gang && type == GANG) ||
340                         (current->draw && type == DRAW) ||
341                         (mute_keyframe->value && type == MUTE) ||
342                         (current->expand_view && type == EXPAND);
343         }
344         return result;
347 int Tracks::recordable_audio_tracks()
349         int result = 0;
350         for(Track *current = first; current; current = NEXT)
351                 if(current->data_type == TRACK_AUDIO && current->record) result++;
352         return result;
355 int Tracks::recordable_video_tracks()
357         int result = 0;
358         for(Track *current = first; current; current = NEXT)
359         {
360                 if(current->data_type == TRACK_VIDEO && current->record) result++;
361         }
362         return result;
366 int Tracks::playable_audio_tracks()
368         int result = 0;
370         for(Track *current = first; current; current = NEXT)
371         {
372                 if(current->data_type == TRACK_AUDIO && current->play)
373                 {
374                         result++;
375                 }
376         }
378         return result;
381 int Tracks::playable_video_tracks()
383         int result = 0;
385         for(Track *current = first; current; current = NEXT)
386         {
387                 if(current->data_type == TRACK_VIDEO && current->play)
388                 {
389                         result++;
390                 }
391         }
392         return result;
395 int Tracks::total_audio_tracks()
397         int result = 0;
398         for(Track *current = first; current; current = NEXT)
399                 if(current->data_type == TRACK_AUDIO) result++;
400         return result;
403 int Tracks::total_video_tracks()
405         int result = 0;
406         for(Track *current = first; current; current = NEXT)
407                 if(current->data_type == TRACK_VIDEO) result++;
408         return result;
411 double Tracks::total_playable_length() 
413         double total = 0;
414         for(Track *current = first; current; current = NEXT)
415         {
416                 double length = current->get_length();
417                 if(length > total) total = length;
418         }
419         return total; 
422 double Tracks::total_recordable_length() 
424         double total = 0;
425         for(Track *current = first; current; current = NEXT)
426         {
427                 if(current->record)
428                 {
429                         double length = current->get_length();
430                         if(length > total) total = length;
431                 }
432         }
433         return total; 
436 double Tracks::total_length() 
438         double total = 0;
439         for(Track *current = first; current; current = NEXT)
440         {
441                 if(current->get_length() > total) total = current->get_length();
442         }
443         return total; 
446 double Tracks::total_audio_length() 
448         double total = 0;
449         for(Track *current = first; current; current = NEXT)
450         {
451                 if(current->data_type == TRACK_AUDIO &&
452                         current->get_length() > total) total = current->get_length();
453         }
454         return total; 
457 double Tracks::total_video_length() 
459         double total = 0;
460         for(Track *current = first; current; current = NEXT)
461         {
462                 if(current->data_type == TRACK_VIDEO &&
463                         current->get_length() > total) total = current->get_length();
464         }
465         return total; 
468 double Tracks::total_length_framealigned(double fps)
470         if (total_audio_tracks() && total_video_tracks())
471                 return MIN(floor(total_audio_length() * fps), floor(total_video_length() * fps)) / fps;
473         if (total_audio_tracks())
474                 return floor(total_audio_length() * fps) / fps;
476         if (total_video_tracks())
477                 return floor(total_video_length() * fps) / fps;
479         return 0;
482 void Tracks::translate_camera(float offset_x, float offset_y)
484         for(Track *current = first; current; current = NEXT)
485         {
486                 if(current->data_type == TRACK_VIDEO)
487                 {
488                         ((VTrack*)current)->translate(offset_x, offset_y, 1);
489                 }
490         }
492 void Tracks::translate_projector(float offset_x, float offset_y)
494         for(Track *current = first; current; current = NEXT)
495         {
496                 if(current->data_type == TRACK_VIDEO)
497                 {
498                         ((VTrack*)current)->translate(offset_x, offset_y, 0);
499                 }
500         }
503 void Tracks::update_y_pixels(Theme *theme)
505         int y = -edl->local_session->track_start;
506         for(Track *current = first; current; current = NEXT)
507         {
508 //printf("Tracks::update_y_pixels %d\n", y);
509                 current->y_pixel = y;
510                 y += current->vertical_span(theme);
511         }
514 int Tracks::dump()
516         for(Track* current = first; current; current = NEXT)
517         {
518                 printf("  Track: %x\n", current);
519                 current->dump();
520                 printf("\n");
521         }
522         return 0;
525 void Tracks::select_all(int type,
526                 int value)
528         for(Track* current = first; current; current = NEXT)
529         {
530                 double position = edl->local_session->get_selectionstart(1);
532                 if(type == PLAY) current->play = value;
533                 if(type == RECORD) current->record = value;
534                 if(type == GANG) current->gang = value;
535                 if(type == DRAW) current->draw = value;
536                 
537                 if(type == MUTE)
538                 {
539                         ((IntAuto*)current->automation->autos[AUTOMATION_MUTE]->get_auto_for_editing(position))->value = value;
540                 }
542                 if(type == EXPAND) current->expand_view = value;
543         }
587 // ===================================== file operations
589 int Tracks::popup_transition(int cursor_x, int cursor_y)
591         int result = 0;
592         for(Track* current = first; current && !result; current = NEXT)
593         {
594                 result = current->popup_transition(cursor_x, cursor_y);
595         }
596         return result;
600 int Tracks::change_channels(int oldchannels, int newchannels)
602         for(Track *current = first; current; current = NEXT)
603         { current->change_channels(oldchannels, newchannels); }
604         return 0;
609 int Tracks::totalpixels()
611         int result = 0;
612         for(Track* current = first; current; current = NEXT)
613         {
614                 result += edl->local_session->zoom_track;
615         }
616         return result;
619 int Tracks::number_of(Track *track)
621         int i = 0;
622         for(Track *current = first; current && current != track; current = NEXT)
623         {
624                 i++;
625         }
626         return i;
629 Track* Tracks::number(int number)
631         Track *current;
632         int i = 0;
633         for(current = first; current && i < number; current = NEXT)
634         {
635                 i++;
636         }
637         return current;
641 int Tracks::total_playable_vtracks()
643         int result = 0;
644         for(Track *current = first; current; current = NEXT)
645         {
646                 if(current->data_type == TRACK_VIDEO && current->play) result++;
647         }
648         return result;