00001 #include "atrack.h"
00002 #include "automation.h"
00003 #include "cursor.h"
00004 #include "clip.h"
00005 #include "bchash.h"
00006 #include "edit.h"
00007 #include "edits.h"
00008 #include "edl.h"
00009 #include "edlsession.h"
00010 #include "file.h"
00011 #include "filexml.h"
00012 #include "intauto.h"
00013 #include "intautos.h"
00014 #include "localsession.h"
00015 #include "module.h"
00016 #include "panauto.h"
00017 #include "panautos.h"
00018 #include "patchbay.h"
00019 #include "mainsession.h"
00020 #include "theme.h"
00021 #include "track.h"
00022 #include "trackcanvas.h"
00023 #include "tracks.h"
00024 #include "transportque.inc"
00025 #include "vtrack.h"
00026 #include <string.h>
00027
00028 Tracks::Tracks(EDL *edl)
00029 : List<Track>()
00030 {
00031 this->edl = edl;
00032 }
00033
00034 Tracks::Tracks()
00035 : List<Track>()
00036 {
00037 }
00038
00039
00040 Tracks::~Tracks()
00041 {
00042 delete_all_tracks();
00043 }
00044
00045
00046
00047
00048
00049
00050 void Tracks::equivalent_output(Tracks *tracks, double *result)
00051 {
00052 if(total_playable_vtracks() != tracks->total_playable_vtracks())
00053 {
00054 *result = 0;
00055 }
00056 else
00057 {
00058 Track *current = first;
00059 Track *that_current = tracks->first;
00060 while(current || that_current)
00061 {
00062
00063 while(current && current->data_type != TRACK_VIDEO)
00064 current = NEXT;
00065
00066 while(that_current && that_current->data_type != TRACK_VIDEO)
00067 that_current = that_current->next;
00068
00069
00070 if((!current && that_current) ||
00071 (current && !that_current))
00072 {
00073 *result = 0;
00074 break;
00075 }
00076 else
00077
00078 if(current && that_current)
00079 {
00080 current->equivalent_output(that_current, result);
00081 current = NEXT;
00082 that_current = that_current->next;
00083 }
00084 }
00085 }
00086 }
00087
00088
00089
00090
00091 void Tracks::get_affected_edits(ArrayList<Edit*> *drag_edits, double position, Track *start_track)
00092 {
00093 drag_edits->remove_all();
00094
00095 for(Track *track = start_track;
00096 track;
00097 track = track->next)
00098 {
00099
00100 if(track->record)
00101 {
00102 for(Edit *edit = track->edits->first; edit; edit = edit->next)
00103 {
00104 double startproject = track->from_units(edit->startproject);
00105
00106 if(edl->equivalent(startproject, position))
00107 {
00108 drag_edits->append(edit);
00109 break;
00110 }
00111 }
00112 }
00113 }
00114
00115 }
00116
00117 void Tracks::get_automation_extents(float *min,
00118 float *max,
00119 double start,
00120 double end,
00121 int autogrouptype)
00122 {
00123 *min = 0;
00124 *max = 0;
00125 int coords_undefined = 1;
00126 for(Track *current = first; current; current = NEXT)
00127 {
00128 if(current->record)
00129 {
00130 current->automation->get_extents(min,
00131 max,
00132 &coords_undefined,
00133 current->to_units(start, 0),
00134 current->to_units(end, 1),
00135 autogrouptype);
00136 }
00137 }
00138 }
00139
00140
00141 void Tracks::copy_from(Tracks *tracks)
00142 {
00143 Track *new_track;
00144
00145 delete_all_tracks();
00146 for(Track *current = tracks->first; current; current = NEXT)
00147 {
00148 switch(current->data_type)
00149 {
00150 case TRACK_AUDIO:
00151 new_track = add_audio_track(0, 0);
00152 break;
00153 case TRACK_VIDEO:
00154 new_track = add_video_track(0, 0);
00155 break;
00156 }
00157 new_track->copy_from(current);
00158 }
00159 }
00160
00161 Tracks& Tracks::operator=(Tracks &tracks)
00162 {
00163 printf("Tracks::operator= 1\n");
00164 copy_from(&tracks);
00165 return *this;
00166 }
00167
00168 int Tracks::load(FileXML *xml, int &track_offset, uint32_t load_flags)
00169 {
00170
00171 char string[BCTEXTLEN];
00172 Track *track = 0;
00173 sprintf(string, "");
00174
00175 xml->tag.get_property("TYPE", string);
00176
00177 if((load_flags & LOAD_ALL) == LOAD_ALL ||
00178 (load_flags & LOAD_EDITS))
00179 {
00180 if(!strcmp(string, "VIDEO"))
00181 {
00182 add_video_track(0, 0);
00183 }
00184 else
00185 {
00186 add_audio_track(0, 0);
00187 }
00188 track = last;
00189 }
00190 else
00191 {
00192 track = get_item_number(track_offset);
00193 track_offset++;
00194 }
00195
00196
00197 if(track) track->load(xml, track_offset, load_flags);
00198
00199 return 0;
00200 }
00201
00202 Track* Tracks::add_audio_track(int above, Track *dst_track)
00203 {
00204 int pixel;
00205 ATrack* new_track = new ATrack(edl, this);
00206 if(!dst_track)
00207 {
00208 dst_track = (above ? first : last);
00209 }
00210
00211 if(above)
00212 {
00213 insert_before(dst_track, (Track*)new_track);
00214 }
00215 else
00216 {
00217 insert_after(dst_track, (Track*)new_track);
00218
00219 }
00220
00221
00222 for(Track *track = last;
00223 track && track != new_track;
00224 track = track->previous)
00225 {
00226 change_modules(number_of(track) - 1, number_of(track), 0);
00227 }
00228
00229
00230 new_track->create_objects();
00231 new_track->set_default_title();
00232
00233 int current_pan = 0;
00234 for(Track *current = first;
00235 current != (Track*)new_track;
00236 current = NEXT)
00237 {
00238 if(current->data_type == TRACK_AUDIO) current_pan++;
00239 if(current_pan >= edl->session->audio_channels) current_pan = 0;
00240 }
00241
00242
00243
00244 PanAuto* pan_auto =
00245 (PanAuto*)new_track->automation->autos[AUTOMATION_PAN]->default_auto;
00246 pan_auto->values[current_pan] = 1.0;
00247
00248 BC_Pan::calculate_stick_position(edl->session->audio_channels,
00249 edl->session->achannel_positions,
00250 pan_auto->values,
00251 MAX_PAN,
00252 PAN_RADIUS,
00253 pan_auto->handle_x,
00254 pan_auto->handle_y);
00255 return new_track;
00256 }
00257
00258 Track* Tracks::add_video_track(int above, Track *dst_track)
00259 {
00260 int pixel;
00261 VTrack* new_track = new VTrack(edl, this);
00262 if(!dst_track)
00263 dst_track = (above ? first : last);
00264
00265 if(above)
00266 {
00267 insert_before(dst_track, (Track*)new_track);
00268 }
00269 else
00270 {
00271 insert_after(dst_track, (Track*)new_track);
00272 }
00273
00274
00275
00276
00277 for(Track *track = last;
00278 track && track != new_track;
00279 track = track->previous)
00280 {
00281 change_modules(number_of(track) - 1, number_of(track), 0);
00282 }
00283
00284
00285
00286 new_track->create_objects();
00287 new_track->set_default_title();
00288 return new_track;
00289 }
00290
00291
00292 int Tracks::delete_track(Track *track)
00293 {
00294 if (!track)
00295 return 0;
00296
00297 int old_location = number_of(track);
00298 detach_shared_effects(old_location);
00299
00300
00301 for(Track *current = track;
00302 current;
00303 current = NEXT)
00304 {
00305 change_modules(number_of(current), number_of(current) - 1, 0);
00306 }
00307 if(track) delete track;
00308
00309 return 0;
00310 }
00311
00312 int Tracks::detach_shared_effects(int module)
00313 {
00314 for(Track *current = first; current; current = NEXT)
00315 {
00316 current->detach_shared_effects(module);
00317 }
00318
00319 return 0;
00320 }
00321
00322 int Tracks::total_of(int type)
00323 {
00324 int result = 0;
00325 IntAuto *mute_keyframe = 0;
00326
00327 for(Track *current = first; current; current = NEXT)
00328 {
00329 long unit_start = current->to_units(edl->local_session->get_selectionstart(1), 0);
00330 mute_keyframe =
00331 (IntAuto*)current->automation->autos[AUTOMATION_MUTE]->get_prev_auto(
00332 unit_start,
00333 PLAY_FORWARD,
00334 (Auto* &)mute_keyframe);
00335
00336 result +=
00337 (current->play && type == PLAY) ||
00338 (current->record && type == RECORD) ||
00339 (current->gang && type == GANG) ||
00340 (current->draw && type == DRAW) ||
00341 (mute_keyframe->value && type == MUTE) ||
00342 (current->expand_view && type == EXPAND);
00343 }
00344 return result;
00345 }
00346
00347 int Tracks::recordable_audio_tracks()
00348 {
00349 int result = 0;
00350 for(Track *current = first; current; current = NEXT)
00351 if(current->data_type == TRACK_AUDIO && current->record) result++;
00352 return result;
00353 }
00354
00355 int Tracks::recordable_video_tracks()
00356 {
00357 int result = 0;
00358 for(Track *current = first; current; current = NEXT)
00359 {
00360 if(current->data_type == TRACK_VIDEO && current->record) result++;
00361 }
00362 return result;
00363 }
00364
00365
00366 int Tracks::playable_audio_tracks()
00367 {
00368 int result = 0;
00369
00370 for(Track *current = first; current; current = NEXT)
00371 {
00372 if(current->data_type == TRACK_AUDIO && current->play)
00373 {
00374 result++;
00375 }
00376 }
00377
00378 return result;
00379 }
00380
00381 int Tracks::playable_video_tracks()
00382 {
00383 int result = 0;
00384
00385 for(Track *current = first; current; current = NEXT)
00386 {
00387 if(current->data_type == TRACK_VIDEO && current->play)
00388 {
00389 result++;
00390 }
00391 }
00392 return result;
00393 }
00394
00395 int Tracks::total_audio_tracks()
00396 {
00397 int result = 0;
00398 for(Track *current = first; current; current = NEXT)
00399 if(current->data_type == TRACK_AUDIO) result++;
00400 return result;
00401 }
00402
00403 int Tracks::total_video_tracks()
00404 {
00405 int result = 0;
00406 for(Track *current = first; current; current = NEXT)
00407 if(current->data_type == TRACK_VIDEO) result++;
00408 return result;
00409 }
00410
00411 double Tracks::total_playable_length()
00412 {
00413 double total = 0;
00414 for(Track *current = first; current; current = NEXT)
00415 {
00416 double length = current->get_length();
00417 if(length > total) total = length;
00418 }
00419 return total;
00420 }
00421
00422 double Tracks::total_recordable_length()
00423 {
00424 double total = 0;
00425 for(Track *current = first; current; current = NEXT)
00426 {
00427 if(current->record)
00428 {
00429 double length = current->get_length();
00430 if(length > total) total = length;
00431 }
00432 }
00433 return total;
00434 }
00435
00436 double Tracks::total_length()
00437 {
00438 double total = 0;
00439 for(Track *current = first; current; current = NEXT)
00440 {
00441 if(current->get_length() > total) total = current->get_length();
00442 }
00443 return total;
00444 }
00445
00446 double Tracks::total_audio_length()
00447 {
00448 double total = 0;
00449 for(Track *current = first; current; current = NEXT)
00450 {
00451 if(current->data_type == TRACK_AUDIO &&
00452 current->get_length() > total) total = current->get_length();
00453 }
00454 return total;
00455 }
00456
00457 double Tracks::total_video_length()
00458 {
00459 double total = 0;
00460 for(Track *current = first; current; current = NEXT)
00461 {
00462 if(current->data_type == TRACK_VIDEO &&
00463 current->get_length() > total) total = current->get_length();
00464 }
00465 return total;
00466 }
00467
00468 double Tracks::total_length_framealigned(double fps)
00469 {
00470 if (total_audio_tracks() && total_video_tracks())
00471 return MIN(floor(total_audio_length() * fps), floor(total_video_length() * fps)) / fps;
00472
00473 if (total_audio_tracks())
00474 return floor(total_audio_length() * fps) / fps;
00475
00476 if (total_video_tracks())
00477 return floor(total_video_length() * fps) / fps;
00478
00479 return 0;
00480 }
00481
00482 void Tracks::translate_camera(float offset_x, float offset_y)
00483 {
00484 for(Track *current = first; current; current = NEXT)
00485 {
00486 if(current->data_type == TRACK_VIDEO)
00487 {
00488 ((VTrack*)current)->translate(offset_x, offset_y, 1);
00489 }
00490 }
00491 }
00492 void Tracks::translate_projector(float offset_x, float offset_y)
00493 {
00494 for(Track *current = first; current; current = NEXT)
00495 {
00496 if(current->data_type == TRACK_VIDEO)
00497 {
00498 ((VTrack*)current)->translate(offset_x, offset_y, 0);
00499 }
00500 }
00501 }
00502
00503 void Tracks::update_y_pixels(Theme *theme)
00504 {
00505 int y = -edl->local_session->track_start;
00506 for(Track *current = first; current; current = NEXT)
00507 {
00508
00509 current->y_pixel = y;
00510 y += current->vertical_span(theme);
00511 }
00512 }
00513
00514 int Tracks::dump()
00515 {
00516 for(Track* current = first; current; current = NEXT)
00517 {
00518 printf(" Track: %x\n", current);
00519 current->dump();
00520 printf("\n");
00521 }
00522 return 0;
00523 }
00524
00525 void Tracks::select_all(int type,
00526 int value)
00527 {
00528 for(Track* current = first; current; current = NEXT)
00529 {
00530 double position = edl->local_session->get_selectionstart(1);
00531
00532 if(type == PLAY) current->play = value;
00533 if(type == RECORD) current->record = value;
00534 if(type == GANG) current->gang = value;
00535 if(type == DRAW) current->draw = value;
00536
00537 if(type == MUTE)
00538 {
00539 ((IntAuto*)current->automation->autos[AUTOMATION_MUTE]->get_auto_for_editing(position))->value = value;
00540 }
00541
00542 if(type == EXPAND) current->expand_view = value;
00543 }
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 int Tracks::popup_transition(int cursor_x, int cursor_y)
00590 {
00591 int result = 0;
00592 for(Track* current = first; current && !result; current = NEXT)
00593 {
00594 result = current->popup_transition(cursor_x, cursor_y);
00595 }
00596 return result;
00597 }
00598
00599
00600 int Tracks::change_channels(int oldchannels, int newchannels)
00601 {
00602 for(Track *current = first; current; current = NEXT)
00603 { current->change_channels(oldchannels, newchannels); }
00604 return 0;
00605 }
00606
00607
00608
00609 int Tracks::totalpixels()
00610 {
00611 int result = 0;
00612 for(Track* current = first; current; current = NEXT)
00613 {
00614 result += edl->local_session->zoom_track;
00615 }
00616 return result;
00617 }
00618
00619 int Tracks::number_of(Track *track)
00620 {
00621 int i = 0;
00622 for(Track *current = first; current && current != track; current = NEXT)
00623 {
00624 i++;
00625 }
00626 return i;
00627 }
00628
00629 Track* Tracks::number(int number)
00630 {
00631 Track *current;
00632 int i = 0;
00633 for(current = first; current && i < number; current = NEXT)
00634 {
00635 i++;
00636 }
00637 return current;
00638 }
00639
00640
00641 int Tracks::total_playable_vtracks()
00642 {
00643 int result = 0;
00644 for(Track *current = first; current; current = NEXT)
00645 {
00646 if(current->data_type == TRACK_VIDEO && current->play) result++;
00647 }
00648 return result;
00649 }