r914: Fix a long outstanding bug regarding dragndroping
[cinelerra_cv/mob.git] / cinelerra / tracks.C
blobee54639db28953a6e668355663f743ef4a43645a
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,
120         int autogrouptype)
122         *min = 0;
123         *max = 0;
124         int coords_undefined = 1;
125         for(Track *current = first; current; current = NEXT)
126         {
127                 if(current->record)
128                 {
129                         current->automation->get_extents(min,
130                                 max,
131                                 &coords_undefined,
132                                 current->to_units(start, 1),
133                                 current->to_units(end, 1),
134                                 autogrouptype);
135                 }
136         }
140 void Tracks::copy_from(Tracks *tracks)
142         Track *new_track;
144         delete_all_tracks();
145         for(Track *current = tracks->first; current; current = NEXT)
146         {
147                 switch(current->data_type)
148                 {
149                         case TRACK_AUDIO: 
150                                 new_track = add_audio_track(0, 0); 
151                                 break;
152                         case TRACK_VIDEO: 
153                                 new_track = add_video_track(0, 0); 
154                                 break;
155                 }
156                 new_track->copy_from(current);
157         }
160 Tracks& Tracks::operator=(Tracks &tracks)
162 printf("Tracks::operator= 1\n");
163         copy_from(&tracks);
164         return *this;
167 int Tracks::load(FileXML *xml, int &track_offset, uint32_t load_flags)
169 // add the appropriate type of track
170         char string[BCTEXTLEN];
171         Track *track = 0;
172         sprintf(string, "");
173         
174         xml->tag.get_property("TYPE", string);
176         if((load_flags & LOAD_ALL) == LOAD_ALL ||
177                 (load_flags & LOAD_EDITS))
178         {
179                 if(!strcmp(string, "VIDEO"))
180                 {
181                         add_video_track(0, 0);
182                 }
183                 else
184                 {
185                         add_audio_track(0, 0);    // default to audio
186                 }
187                 track = last;
188         }
189         else
190         {
191                 track = get_item_number(track_offset);
192                 track_offset++;
193         }
195 // load it
196         if(track) track->load(xml, track_offset, load_flags);
198         return 0;
201 Track* Tracks::add_audio_track(int above, Track *dst_track)
203         int pixel;
204         ATrack* new_track = new ATrack(edl, this);
205         if(!dst_track)
206         {
207                 dst_track = (above ? first : last);
208         }
210         if(above)
211         {
212                 insert_before(dst_track, (Track*)new_track);
213         }
214         else
215         {
216                 insert_after(dst_track, (Track*)new_track);
217 // Shift effects referenced below the destination track
218         }
220 // Shift effects referenced below the new track
221         for(Track *track = last; 
222                 track && track != new_track; 
223                 track = track->previous)
224         {
225                 change_modules(number_of(track) - 1, number_of(track), 0);
226         }
229         new_track->create_objects();
230         new_track->set_default_title();
232         int current_pan = 0;
233         for(Track *current = first; 
234                 current != (Track*)new_track; 
235                 current = NEXT)
236         {
237                 if(current->data_type == TRACK_AUDIO) current_pan++;
238                 if(current_pan >= edl->session->audio_channels) current_pan = 0;
239         }
243         PanAuto* pan_auto = 
244                 (PanAuto*)new_track->automation->autos[AUTOMATION_PAN]->default_auto;
245         pan_auto->values[current_pan] = 1.0;
247         BC_Pan::calculate_stick_position(edl->session->audio_channels, 
248                 edl->session->achannel_positions, 
249                 pan_auto->values, 
250                 MAX_PAN, 
251                 PAN_RADIUS,
252                 pan_auto->handle_x,
253                 pan_auto->handle_y);
254         return new_track;
257 Track* Tracks::add_video_track(int above, Track *dst_track)
259         int pixel;
260         VTrack* new_track = new VTrack(edl, this);
261         if(!dst_track)
262                 dst_track = (above ? first : last);
264         if(above)
265         {
266                 insert_before(dst_track, (Track*)new_track);
267         }
268         else
269         {
270                 insert_after(dst_track, (Track*)new_track);
271         }
275 // Shift effects referenced below the new track
276         for(Track *track = last; 
277                 track && track != new_track; 
278                 track = track->previous)
279         {
280                 change_modules(number_of(track) - 1, number_of(track), 0);
281         }
285         new_track->create_objects();
286         new_track->set_default_title();
287         return new_track;
291 int Tracks::delete_track(Track *track)
293         if (!track)
294                 return 0;
296         int old_location = number_of(track);
297         detach_shared_effects(old_location);
299 // Shift effects referencing effects below the deleted track
300         for(Track *current = track; 
301                 current;
302                 current = NEXT)
303         {
304                 change_modules(number_of(current), number_of(current) - 1, 0);
305         }
306         if(track) delete track;
308         return 0;
311 int Tracks::detach_shared_effects(int module)
313         for(Track *current = first; current; current = NEXT)
314         {
315                 current->detach_shared_effects(module);
316         }
318         return 0;
321 int Tracks::total_of(int type)
323         int result = 0;
324         IntAuto *mute_keyframe = 0;
325         
326         for(Track *current = first; current; current = NEXT)
327         {
328                 long unit_start = current->to_units(edl->local_session->get_selectionstart(1), 0);
329                 mute_keyframe = 
330                         (IntAuto*)current->automation->autos[AUTOMATION_MUTE]->get_prev_auto(
331                         unit_start, 
332                         PLAY_FORWARD,
333                         (Auto* &)mute_keyframe);
335                 result += 
336                         (current->play && type == PLAY) ||
337                         (current->record && type == RECORD) ||
338                         (current->gang && type == GANG) ||
339                         (current->draw && type == DRAW) ||
340                         (mute_keyframe->value && type == MUTE) ||
341                         (current->expand_view && type == EXPAND);
342         }
343         return result;
346 int Tracks::recordable_audio_tracks()
348         int result = 0;
349         for(Track *current = first; current; current = NEXT)
350                 if(current->data_type == TRACK_AUDIO && current->record) result++;
351         return result;
354 int Tracks::recordable_video_tracks()
356         int result = 0;
357         for(Track *current = first; current; current = NEXT)
358         {
359                 if(current->data_type == TRACK_VIDEO && current->record) result++;
360         }
361         return result;
365 int Tracks::playable_audio_tracks()
367         int result = 0;
369         for(Track *current = first; current; current = NEXT)
370         {
371                 if(current->data_type == TRACK_AUDIO && current->play)
372                 {
373                         result++;
374                 }
375         }
377         return result;
380 int Tracks::playable_video_tracks()
382         int result = 0;
384         for(Track *current = first; current; current = NEXT)
385         {
386                 if(current->data_type == TRACK_VIDEO && current->play)
387                 {
388                         result++;
389                 }
390         }
391         return result;
394 int Tracks::total_audio_tracks()
396         int result = 0;
397         for(Track *current = first; current; current = NEXT)
398                 if(current->data_type == TRACK_AUDIO) result++;
399         return result;
402 int Tracks::total_video_tracks()
404         int result = 0;
405         for(Track *current = first; current; current = NEXT)
406                 if(current->data_type == TRACK_VIDEO) result++;
407         return result;
410 double Tracks::total_playable_length() 
412         double total = 0;
413         for(Track *current = first; current; current = NEXT)
414         {
415                 double length = current->get_length();
416                 if(length > total) total = length;
417         }
418         return total; 
421 double Tracks::total_recordable_length() 
423         double total = 0;
424         for(Track *current = first; current; current = NEXT)
425         {
426                 if(current->record)
427                 {
428                         double length = current->get_length();
429                         if(length > total) total = length;
430                 }
431         }
432         return total; 
435 double Tracks::total_length() 
437         double total = 0;
438         for(Track *current = first; current; current = NEXT)
439         {
440                 if(current->get_length() > total) total = current->get_length();
441         }
442         return total; 
445 double Tracks::total_video_length() 
447         double total = 0;
448         for(Track *current = first; current; current = NEXT)
449         {
450                 if(current->data_type == TRACK_VIDEO &&
451                         current->get_length() > total) total = current->get_length();
452         }
453         return total; 
457 void Tracks::translate_camera(float offset_x, float offset_y)
459         for(Track *current = first; current; current = NEXT)
460         {
461                 if(current->data_type == TRACK_VIDEO)
462                 {
463                         ((VTrack*)current)->translate(offset_x, offset_y, 1);
464                 }
465         }
467 void Tracks::translate_projector(float offset_x, float offset_y)
469         for(Track *current = first; current; current = NEXT)
470         {
471                 if(current->data_type == TRACK_VIDEO)
472                 {
473                         ((VTrack*)current)->translate(offset_x, offset_y, 0);
474                 }
475         }
478 void Tracks::update_y_pixels(Theme *theme)
480         int y = -edl->local_session->track_start;
481         for(Track *current = first; current; current = NEXT)
482         {
483 //printf("Tracks::update_y_pixels %d\n", y);
484                 current->y_pixel = y;
485                 y += current->vertical_span(theme);
486         }
489 int Tracks::dump()
491         for(Track* current = first; current; current = NEXT)
492         {
493                 printf("  Track: %x\n", current);
494                 current->dump();
495                 printf("\n");
496         }
497         return 0;
500 void Tracks::select_all(int type,
501                 int value)
503         for(Track* current = first; current; current = NEXT)
504         {
505                 double position = edl->local_session->get_selectionstart(1);
507                 if(type == PLAY) current->play = value;
508                 if(type == RECORD) current->record = value;
509                 if(type == GANG) current->gang = value;
510                 if(type == DRAW) current->draw = value;
511                 
512                 if(type == MUTE)
513                 {
514                         ((IntAuto*)current->automation->autos[AUTOMATION_MUTE]->get_auto_for_editing(position))->value = value;
515                 }
517                 if(type == EXPAND) current->expand_view = value;
518         }
562 // ===================================== file operations
564 int Tracks::popup_transition(int cursor_x, int cursor_y)
566         int result = 0;
567         for(Track* current = first; current && !result; current = NEXT)
568         {
569                 result = current->popup_transition(cursor_x, cursor_y);
570         }
571         return result;
575 int Tracks::change_channels(int oldchannels, int newchannels)
577         for(Track *current = first; current; current = NEXT)
578         { current->change_channels(oldchannels, newchannels); }
579         return 0;
584 int Tracks::totalpixels()
586         int result = 0;
587         for(Track* current = first; current; current = NEXT)
588         {
589                 result += edl->local_session->zoom_track;
590         }
591         return result;
594 int Tracks::number_of(Track *track)
596         int i = 0;
597         for(Track *current = first; current && current != track; current = NEXT)
598         {
599                 i++;
600         }
601         return i;
604 Track* Tracks::number(int number)
606         Track *current;
607         int i = 0;
608         for(current = first; current && i < number; current = NEXT)
609         {
610                 i++;
611         }
612         return current;
616 int Tracks::total_playable_vtracks()
618         int result = 0;
619         for(Track *current = first; current; current = NEXT)
620         {
621                 if(current->data_type == TRACK_VIDEO && current->play) result++;
622         }
623         return result;