r870: Merge 2.1:
[cinelerra_cv.git] / cinelerra / tracks.C
blob53aa2aa6d0cb2ac218910e25946d4a1bc8a72880
1 #include "atrack.h"
2 #include "automation.h"
3 #include "cursor.h"
4 #include "bchash.h"
5 #include "edit.h"
6 #include "edits.h"
7 #include "edl.h"
8 #include "edlsession.h"
9 #include "file.h"
10 #include "filexml.h"
11 #include "intauto.h"
12 #include "intautos.h"
13 #include "localsession.h"
14 #include "module.h"
15 #include "panauto.h"
16 #include "panautos.h"
17 #include "patchbay.h"
18 #include "mainsession.h"
19 #include "theme.h"
20 #include "track.h"
21 #include "trackcanvas.h"
22 #include "tracks.h"
23 #include "transportque.inc"
24 #include "vtrack.h"
25 #include <string.h>
27 Tracks::Tracks(EDL *edl)
28  : List<Track>()
30         this->edl = edl;
33 Tracks::Tracks()
34  : List<Track>()
39 Tracks::~Tracks()
41         delete_all_tracks();
49 void Tracks::equivalent_output(Tracks *tracks, double *result)
51         if(total_playable_vtracks() != tracks->total_playable_vtracks())
52         {
53                 *result = 0;
54         }
55         else
56         {
57                 Track *current = first;
58                 Track *that_current = tracks->first;
59                 while(current || that_current)
60                 {
61 // Get next video track
62                         while(current && current->data_type != TRACK_VIDEO)
63                                 current = NEXT;
65                         while(that_current && that_current->data_type != TRACK_VIDEO)
66                                 that_current = that_current->next;
68 // One doesn't exist but the other does
69                         if((!current && that_current) ||
70                                 (current && !that_current))
71                         {
72                                 *result = 0;
73                                 break;
74                         }
75                         else
76 // Both exist
77                         if(current && that_current)
78                         {
79                                 current->equivalent_output(that_current, result);
80                                 current = NEXT;
81                                 that_current = that_current->next;
82                         }
83                 }
84         }
90 void Tracks::get_affected_edits(ArrayList<Edit*> *drag_edits, double position, Track *start_track)
92         drag_edits->remove_all();
94         for(Track *track = start_track;
95                 track;
96                 track = track->next)
97         {
98 //printf("Tracks::get_affected_edits 1 %p %d %d\n", track, track->data_type, track->record);
99                 if(track->record)
100                 {
101                         for(Edit *edit = track->edits->first; edit; edit = edit->next)
102                         {
103                                 double startproject = track->from_units(edit->startproject);
104 //printf("Tracks::get_affected_edits 1 %d\n", edl->equivalent(startproject, position));
105                                 if(edl->equivalent(startproject, position))
106                                 {
107                                         drag_edits->append(edit);
108                                         break;
109                                 }
110                         }
111                 }
112         }
116 void Tracks::get_automation_extents(float *min, 
117         float *max,
118         double start,
119         double end)
121         *min = 0;
122         *max = 0;
123         int coords_undefined = 1;
124         for(Track *current = first; current; current = NEXT)
125         {
126                 if(current->record)
127                 {
128                         current->automation->get_extents(min,
129                                 max,
130                                 &coords_undefined,
131                                 current->to_units(start, 1),
132                                 current->to_units(end, 1));
133                 }
134         }
138 void Tracks::copy_from(Tracks *tracks)
140         Track *new_track;
142         delete_all_tracks();
143         for(Track *current = tracks->first; current; current = NEXT)
144         {
145                 switch(current->data_type)
146                 {
147                         case TRACK_AUDIO: 
148                                 new_track = add_audio_track(0, 0); 
149                                 break;
150                         case TRACK_VIDEO: 
151                                 new_track = add_video_track(0, 0); 
152                                 break;
153                 }
154                 new_track->copy_from(current);
155         }
158 Tracks& Tracks::operator=(Tracks &tracks)
160 printf("Tracks::operator= 1\n");
161         copy_from(&tracks);
162         return *this;
165 int Tracks::load(FileXML *xml, int &track_offset, uint32_t load_flags)
167 // add the appropriate type of track
168         char string[BCTEXTLEN];
169         Track *track = 0;
170         sprintf(string, "");
171         
172         xml->tag.get_property("TYPE", string);
174         if((load_flags & LOAD_ALL) == LOAD_ALL ||
175                 (load_flags & LOAD_EDITS))
176         {
177                 if(!strcmp(string, "VIDEO"))
178                 {
179                         add_video_track(0, 0);
180                 }
181                 else
182                 {
183                         add_audio_track(0, 0);    // default to audio
184                 }
185                 track = last;
186         }
187         else
188         {
189                 track = get_item_number(track_offset);
190                 track_offset++;
191         }
193 // load it
194         if(track) track->load(xml, track_offset, load_flags);
196         return 0;
199 Track* Tracks::add_audio_track(int above, Track *dst_track)
201         int pixel;
202         ATrack* new_track = new ATrack(edl, this);
203         if(!dst_track)
204         {
205                 dst_track = (above ? first : last);
206         }
208         if(above)
209         {
210                 insert_before(dst_track, (Track*)new_track);
211         }
212         else
213         {
214                 insert_after(dst_track, (Track*)new_track);
215 // Shift effects referenced below the destination track
216         }
218 // Shift effects referenced below the new track
219         for(Track *track = last; 
220                 track && track != new_track; 
221                 track = track->previous)
222         {
223                 change_modules(number_of(track) - 1, number_of(track), 0);
224         }
227         new_track->create_objects();
228         new_track->set_default_title();
230         int current_pan = 0;
231         for(Track *current = first; 
232                 current != (Track*)new_track; 
233                 current = NEXT)
234         {
235                 if(current->data_type == TRACK_AUDIO) current_pan++;
236                 if(current_pan >= edl->session->audio_channels) current_pan = 0;
237         }
241         PanAuto* pan_auto = 
242                 (PanAuto*)new_track->automation->autos[AUTOMATION_PAN]->default_auto;
243         pan_auto->values[current_pan] = 1.0;
245         BC_Pan::calculate_stick_position(edl->session->audio_channels, 
246                 edl->session->achannel_positions, 
247                 pan_auto->values, 
248                 MAX_PAN, 
249                 PAN_RADIUS,
250                 pan_auto->handle_x,
251                 pan_auto->handle_y);
252         return new_track;
255 Track* Tracks::add_video_track(int above, Track *dst_track)
257         int pixel;
258         VTrack* new_track = new VTrack(edl, this);
259         if(!dst_track)
260                 dst_track = (above ? first : last);
262         if(above)
263         {
264                 insert_before(dst_track, (Track*)new_track);
265         }
266         else
267         {
268                 insert_after(dst_track, (Track*)new_track);
269         }
273 // Shift effects referenced below the new track
274         for(Track *track = last; 
275                 track && track != new_track; 
276                 track = track->previous)
277         {
278                 change_modules(number_of(track) - 1, number_of(track), 0);
279         }
283         new_track->create_objects();
284         new_track->set_default_title();
285         return new_track;
289 int Tracks::delete_track(Track *track)
291         if (!track)
292                 return 0;
294         int old_location = number_of(track);
295         detach_shared_effects(old_location);
297 // Shift effects referencing effects below the deleted track
298         for(Track *current = track; 
299                 current;
300                 current = NEXT)
301         {
302                 change_modules(number_of(current), number_of(current) - 1, 0);
303         }
304         if(track) delete track;
306         return 0;
309 int Tracks::detach_shared_effects(int module)
311         for(Track *current = first; current; current = NEXT)
312         {
313                 current->detach_shared_effects(module);
314         }
316         return 0;
319 int Tracks::total_of(int type)
321         int result = 0;
322         IntAuto *mute_keyframe = 0;
323         
324         for(Track *current = first; current; current = NEXT)
325         {
326                 long unit_start = current->to_units(edl->local_session->get_selectionstart(1), 0);
327                 mute_keyframe = 
328                         (IntAuto*)current->automation->autos[AUTOMATION_MUTE]->get_prev_auto(
329                         unit_start, 
330                         PLAY_FORWARD,
331                         (Auto* &)mute_keyframe);
333                 result += 
334                         (current->play && type == PLAY) ||
335                         (current->record && type == RECORD) ||
336                         (current->gang && type == GANG) ||
337                         (current->draw && type == DRAW) ||
338                         (mute_keyframe->value && type == MUTE) ||
339                         (current->expand_view && type == EXPAND);
340         }
341         return result;
344 int Tracks::recordable_audio_tracks()
346         int result = 0;
347         for(Track *current = first; current; current = NEXT)
348                 if(current->data_type == TRACK_AUDIO && current->record) result++;
349         return result;
352 int Tracks::recordable_video_tracks()
354         int result = 0;
355         for(Track *current = first; current; current = NEXT)
356         {
357                 if(current->data_type == TRACK_VIDEO && current->record) result++;
358         }
359         return result;
363 int Tracks::playable_audio_tracks()
365         int result = 0;
367         for(Track *current = first; current; current = NEXT)
368         {
369                 if(current->data_type == TRACK_AUDIO && current->play)
370                 {
371                         result++;
372                 }
373         }
375         return result;
378 int Tracks::playable_video_tracks()
380         int result = 0;
382         for(Track *current = first; current; current = NEXT)
383         {
384                 if(current->data_type == TRACK_VIDEO && current->play)
385                 {
386                         result++;
387                 }
388         }
389         return result;
392 int Tracks::total_audio_tracks()
394         int result = 0;
395         for(Track *current = first; current; current = NEXT)
396                 if(current->data_type == TRACK_AUDIO) result++;
397         return result;
400 int Tracks::total_video_tracks()
402         int result = 0;
403         for(Track *current = first; current; current = NEXT)
404                 if(current->data_type == TRACK_VIDEO) result++;
405         return result;
408 double Tracks::total_playable_length() 
410         double total = 0;
411         for(Track *current = first; current; current = NEXT)
412         {
413                 double length = current->get_length();
414                 if(length > total) total = length;
415         }
416         return total; 
419 double Tracks::total_recordable_length() 
421         double total = 0;
422         for(Track *current = first; current; current = NEXT)
423         {
424                 if(current->record)
425                 {
426                         double length = current->get_length();
427                         if(length > total) total = length;
428                 }
429         }
430         return total; 
433 double Tracks::total_length() 
435         double total = 0;
436         for(Track *current = first; current; current = NEXT)
437         {
438                 if(current->get_length() > total) total = current->get_length();
439         }
440         return total; 
443 double Tracks::total_video_length() 
445         double total = 0;
446         for(Track *current = first; current; current = NEXT)
447         {
448                 if(current->data_type == TRACK_VIDEO &&
449                         current->get_length() > total) total = current->get_length();
450         }
451         return total; 
455 void Tracks::translate_camera(float offset_x, float offset_y)
457         for(Track *current = first; current; current = NEXT)
458         {
459                 if(current->data_type == TRACK_VIDEO)
460                 {
461                         ((VTrack*)current)->translate(offset_x, offset_y, 1);
462                 }
463         }
465 void Tracks::translate_projector(float offset_x, float offset_y)
467         for(Track *current = first; current; current = NEXT)
468         {
469                 if(current->data_type == TRACK_VIDEO)
470                 {
471                         ((VTrack*)current)->translate(offset_x, offset_y, 0);
472                 }
473         }
476 void Tracks::update_y_pixels(Theme *theme)
478         int y = -edl->local_session->track_start;
479         for(Track *current = first; current; current = NEXT)
480         {
481 //printf("Tracks::update_y_pixels %d\n", y);
482                 current->y_pixel = y;
483                 y += current->vertical_span(theme);
484         }
487 int Tracks::dump()
489         for(Track* current = first; current; current = NEXT)
490         {
491                 printf("  Track: %x\n", current);
492                 current->dump();
493                 printf("\n");
494         }
495         return 0;
498 void Tracks::select_all(int type,
499                 int value)
501         for(Track* current = first; current; current = NEXT)
502         {
503                 double position = edl->local_session->get_selectionstart(1);
505                 if(type == PLAY) current->play = value;
506                 if(type == RECORD) current->record = value;
507                 if(type == GANG) current->gang = value;
508                 if(type == DRAW) current->draw = value;
509                 
510                 if(type == MUTE)
511                 {
512                         ((IntAuto*)current->automation->autos[AUTOMATION_MUTE]->get_auto_for_editing(position))->value = value;
513                 }
515                 if(type == EXPAND) current->expand_view = value;
516         }
560 // ===================================== file operations
562 int Tracks::popup_transition(int cursor_x, int cursor_y)
564         int result = 0;
565         for(Track* current = first; current && !result; current = NEXT)
566         {
567                 result = current->popup_transition(cursor_x, cursor_y);
568         }
569         return result;
573 int Tracks::change_channels(int oldchannels, int newchannels)
575         for(Track *current = first; current; current = NEXT)
576         { current->change_channels(oldchannels, newchannels); }
577         return 0;
582 int Tracks::totalpixels()
584         int result = 0;
585         for(Track* current = first; current; current = NEXT)
586         {
587                 result += edl->local_session->zoom_track;
588         }
589         return result;
592 int Tracks::number_of(Track *track)
594         int i = 0;
595         for(Track *current = first; current && current != track; current = NEXT)
596         {
597                 i++;
598         }
599         return i;
602 Track* Tracks::number(int number)
604         Track *current;
605         int i = 0;
606         for(current = first; current && i < number; current = NEXT)
607         {
608                 i++;
609         }
610         return current;
614 int Tracks::total_playable_vtracks()
616         int result = 0;
617         for(Track *current = first; current; current = NEXT)
618         {
619                 if(current->data_type == TRACK_VIDEO && current->play) result++;
620         }
621         return result;