1 // PlaybackManager.cpp 2 3 #include <algobase.h> 4 #include <stdio.h> 5 6 #include <Message.h> 7 #include <OS.h> 8 #include <Window.h> 9 10 #include "EventQueue.h" 11 #include "MessageEvent.h" 12 #include "PlaybackListener.h" 13 14 #include "PlaybackManager.h" 15 16 //#define TRACE_NODE_MANAGER 17 #ifdef TRACE_NODE_MANAGER 18 # define TRACE(x...) printf(x) 19 # define ERROR(x...) fprintf(stderr, x) 20 #else 21 # define TRACE(x...) 22 # define ERROR(x...) fprintf(stderr, x) 23 #endif 24 25 void 26 tdebug(const char* str) 27 { 28 TRACE("[%lx, %lld] ", find_thread(NULL), system_time()); 29 TRACE(str); 30 } 31 32 33 struct PlaybackManager::PlayingState { 34 int64 start_frame; 35 int64 end_frame; 36 int64 frame_count; 37 int64 first_visible_frame; 38 int64 last_visible_frame; 39 int64 max_frame_count; 40 int32 play_mode; 41 int32 loop_mode; 42 bool looping_enabled; 43 int64 current_frame; // Playlist frame 44 int64 range_index; // playing range index of current_frame 45 int64 activation_frame; // absolute video frame 46 }; 47 48 49 struct PlaybackManager::SpeedInfo { 50 int64 activation_frame; // absolute video frame 51 bigtime_t activation_time; // performance time 52 float speed; // speed to be used for calculations, 53 // is 1.0 if not playing 54 float set_speed; // speed set by the user 55 }; 56 57 58 // #pragma mark - PlaybackManager 59 60 61 PlaybackManager::PlaybackManager() 62 : BLooper("playback manager"), 63 fStates(10), 64 fSpeeds(10), 65 fCurrentAudioTime(0), 66 fCurrentVideoTime(0), 67 fPerformanceTime(0), 68 fFrameRate(1.0), 69 fStopPlayingFrame(-1), 70 fListeners(), 71 fNoAudio(false) 72 { 73 Run(); 74 } 75 76 77 PlaybackManager::~PlaybackManager() 78 { 79 Cleanup(); 80 } 81 82 83 void 84 PlaybackManager::Init(float frameRate, int32 loopingMode, bool loopingEnabled, 85 float playbackSpeed, int32 playMode, int32 currentFrame) 86 { 87 // cleanup first 88 Cleanup(); 89 90 // set the new frame rate 91 fFrameRate = frameRate; 92 fCurrentAudioTime = 0; 93 fCurrentVideoTime = 0; 94 fPerformanceTime = 0; 95 fStopPlayingFrame = -1; 96 97 // set up the initial speed 98 SpeedInfo* speed = new SpeedInfo; 99 speed->activation_frame = 0; 100 speed->activation_time = 0; 101 speed->speed = playbackSpeed; 102 speed->set_speed = playbackSpeed; 103 _PushSpeedInfo(speed); 104 105 // set up the initial state 106 PlayingState* state = new PlayingState; 107 state->frame_count = Duration(); 108 state->start_frame = 0; 109 state->end_frame = 0; 110 state->first_visible_frame = 0; 111 state->last_visible_frame = 0; 112 state->max_frame_count = state->frame_count; 113 114 state->play_mode = MODE_PLAYING_PAUSED_FORWARD; 115 state->loop_mode = loopingMode; 116 state->looping_enabled = loopingEnabled; 117 state->current_frame = currentFrame; 118 state->activation_frame = 0; 119 fStates.AddItem(state); 120 121 TRACE("initial state pushed: state count: %ld\n", fStates.CountItems()); 122 123 // notify the listeners 124 NotifyPlayModeChanged(PlayMode()); 125 NotifyLoopModeChanged(LoopMode()); 126 NotifyLoopingEnabledChanged(IsLoopingEnabled()); 127 NotifyVideoBoundsChanged(VideoBounds()); 128 NotifyFPSChanged(FramesPerSecond()); 129 NotifySpeedChanged(Speed()); 130 NotifyCurrentFrameChanged(CurrentFrame()); 131 SetPlayMode(playMode); 132 } 133 134 135 void 136 PlaybackManager::Cleanup() 137 { 138 // delete states 139 for (int32 i = 0; PlayingState* state = _StateAt(i); i++) 140 delete state; 141 fStates.MakeEmpty(); 142 143 // delete speed infos 144 for (int32 i = 0; SpeedInfo* speed = _SpeedInfoAt(i); i++) 145 delete speed; 146 fSpeeds.MakeEmpty(); 147 } 148 149 150 void 151 PlaybackManager::MessageReceived(BMessage* message) 152 { 153 switch (message->what) { 154 case MSG_EVENT: 155 SetPerformanceTime(TimeForRealTime(system_time())); 156 //TRACE("MSG_EVENT: rt: %lld, pt: %lld\n", system_time(), fPerformanceTime); 157 break; 158 159 case MSG_PLAYBACK_FORCE_UPDATE: 160 { 161 int64 frame; 162 if (message->FindInt64("frame", &frame) < B_OK) 163 frame = CurrentFrame(); 164 SetCurrentFrame(frame); 165 break; 166 } 167 168 case MSG_PLAYBACK_SET_RANGE: 169 { 170 int64 startFrame = _LastState()->start_frame; 171 int64 endFrame = _LastState()->end_frame; 172 message->FindInt64("start frame", &startFrame); 173 message->FindInt64("end frame", &endFrame); 174 if (startFrame != _LastState()->start_frame 175 || endFrame != _LastState()->end_frame) { 176 PlayingState* state = new PlayingState(*_LastState()); 177 state->start_frame = startFrame; 178 state->end_frame = endFrame; 179 _PushState(state, true); 180 } 181 break; 182 } 183 184 case MSG_PLAYBACK_SET_VISIBLE: 185 { 186 int64 startFrame = _LastState()->first_visible_frame; 187 int64 endFrame = _LastState()->last_visible_frame; 188 message->FindInt64("start frame", &startFrame); 189 message->FindInt64("end frame", &endFrame); 190 if (startFrame != _LastState()->first_visible_frame 191 || endFrame != _LastState()->last_visible_frame) { 192 PlayingState* state = new PlayingState(*_LastState()); 193 state->first_visible_frame = startFrame; 194 state->last_visible_frame = endFrame; 195 _PushState(state, true); 196 } 197 break; 198 } 199 200 case MSG_PLAYBACK_SET_LOOP_MODE: 201 { 202 int32 loopMode = _LastState()->loop_mode; 203 message->FindInt32("mode", &loopMode); 204 if (loopMode != _LastState()->loop_mode) { 205 PlayingState* state = new PlayingState(*_LastState()); 206 state->loop_mode = loopMode; 207 _PushState(state, true); 208 } 209 break; 210 } 211 212 // other messages 213 default: 214 BLooper::MessageReceived(message); 215 break; 216 } 217 } 218 219 // #pragma mark - playback control 220 221 222 void 223 PlaybackManager::StartPlaying(bool atBeginning) 224 { 225 int32 playMode = PlayMode(); 226 if (playMode == MODE_PLAYING_PAUSED_FORWARD) 227 SetPlayMode(MODE_PLAYING_FORWARD, !atBeginning); 228 if (playMode == MODE_PLAYING_PAUSED_BACKWARD) 229 SetPlayMode(MODE_PLAYING_BACKWARD, !atBeginning); 230 } 231 232 233 void 234 PlaybackManager::StopPlaying() 235 { 236 int32 playMode = PlayMode(); 237 if (playMode == MODE_PLAYING_FORWARD) 238 SetPlayMode(MODE_PLAYING_PAUSED_FORWARD, true); 239 if (playMode == MODE_PLAYING_BACKWARD) 240 SetPlayMode(MODE_PLAYING_PAUSED_BACKWARD, true); 241 } 242 243 244 void 245 PlaybackManager::TogglePlaying(bool atBeginning) 246 { 247 // playmodes (paused <-> playing) are the negative of each other 248 SetPlayMode(-PlayMode(), !atBeginning); 249 } 250 251 252 void 253 PlaybackManager::PausePlaying() 254 { 255 if (PlayMode() > 0) 256 TogglePlaying(); 257 } 258 259 260 bool 261 PlaybackManager::IsPlaying() const 262 { 263 return (PlayMode() > 0); 264 } 265 266 267 int32 268 PlaybackManager::PlayMode() const 269 { 270 if (!_LastState()) 271 return MODE_PLAYING_PAUSED_FORWARD; 272 return _LastState()->play_mode; 273 } 274 275 276 int32 277 PlaybackManager::LoopMode() const 278 { 279 if (!_LastState()) 280 return LOOPING_ALL; 281 return _LastState()->loop_mode; 282 } 283 284 285 bool 286 PlaybackManager::IsLoopingEnabled() const 287 { 288 if (!_LastState()) 289 return true; 290 return _LastState()->looping_enabled; 291 } 292 293 294 int32 295 PlaybackManager::CurrentFrame() const 296 { 297 return PlaylistFrameAtFrame(FrameForTime(fPerformanceTime)); 298 } 299 300 301 float 302 PlaybackManager::Speed() const 303 { 304 if (!_LastState()) 305 return 1.0; 306 return _LastSpeedInfo()->set_speed; 307 } 308 309 310 void 311 PlaybackManager::SetFramesPerSecond(float framesPerSecond) 312 { 313 if (framesPerSecond != fFrameRate) { 314 fFrameRate = framesPerSecond; 315 NotifyFPSChanged(fFrameRate); 316 } 317 } 318 319 320 float 321 PlaybackManager::FramesPerSecond() const 322 { 323 return fFrameRate; 324 } 325 326 327 void 328 PlaybackManager::FrameDropped() const 329 { 330 NotifyFrameDropped(); 331 } 332 333 334 void 335 PlaybackManager::DurationChanged() 336 { 337 if (!_LastState()) 338 return; 339 int32 frameCount = Duration(); 340 if (frameCount != _LastState()->frame_count) { 341 PlayingState* state = new PlayingState(*_LastState()); 342 state->frame_count = frameCount; 343 state->max_frame_count = frameCount; 344 345 _PushState(state, true); 346 } 347 } 348 349 /*! Creates a new playing state that equals the previous one aside from 350 its current frame which is set to /frame/. 351 The new state will be activated as soon as possible. */ 352 void 353 PlaybackManager::SetCurrentFrame(int64 frame) 354 { 355 if (_LastState()->current_frame == frame) 356 return; 357 PlayingState* newState = new PlayingState(*_LastState()); 358 newState->current_frame = frame; 359 _PushState(newState, false); 360 } 361 362 363 /*! Creates a new playing state that equals the previous one aside from 364 its playing mode which is set to /mode/. 365 The new state will be activated as soon as possible. 366 If /continuePlaying/ is true and the new state is a `not stopped' 367 state, playing continues at the frame the last state reaches when the 368 new state becomes active (or the next frame in the playing range). 369 If /continuePlaying/ is false, playing starts at the beginning of the 370 playing range (taking the playing direction into consideration). */ 371 void 372 PlaybackManager::SetPlayMode(int32 mode, bool continuePlaying) 373 { 374 //printf("PlaybackManager::SetPlayMode(%ld, %d)\n", mode, continuePlaying); 375 PlayingState* newState = new PlayingState(*_LastState()); 376 newState->play_mode = mode; 377 // Jump to the playing start frame if we should not continue, where we 378 // stop. 379 if (!continuePlaying && !(_PlayingDirectionFor(newState) == 0)) 380 newState->current_frame = _PlayingStartFrameFor(newState); 381 _PushState(newState, continuePlaying); 382 NotifyPlayModeChanged(mode); 383 } 384 385 386 /*! Creates a new playing state that equals the previous one aside from 387 its loop mode which is set to /mode/. 388 The new state will be activated as soon as possible. 389 If /continuePlaying/ is true and the new state is a `not stopped' 390 state, playing continues at the frame the last state reaches when the 391 new state becomes active (or the next frame in the playing range). 392 If /continuePlaying/ is false, playing starts at the beginning of the 393 playing range (taking the playing direction into consideration). */ 394 void 395 PlaybackManager::SetLoopMode(int32 mode, bool continuePlaying) 396 { 397 PlayingState* newState = new PlayingState(*_LastState()); 398 newState->loop_mode = mode; 399 // Jump to the playing start frame if we should not continue, where we 400 // stop. 401 if (!continuePlaying && !(_PlayingDirectionFor(newState) == 0)) 402 newState->current_frame = _PlayingStartFrameFor(newState); 403 _PushState(newState, continuePlaying); 404 NotifyLoopModeChanged(mode); 405 } 406 407 408 /* Creates a new playing state that equals the previous one aside from 409 its looping enabled flag which is set to /enabled/. 410 The new state will be activated as soon as possible. 411 If /continuePlaying/ is true and the new state is a `not stopped' 412 state, playing continues at the frame the last state reaches when the 413 new state becomes active (or the next frame in the playing range). 414 If /continuePlaying/ is false, playing starts at the beginning of the 415 playing range (taking the playing direction into consideration). */ 416 void 417 PlaybackManager::SetLoopingEnabled(bool enabled, bool continuePlaying) 418 { 419 PlayingState* newState = new PlayingState(*_LastState()); 420 newState->looping_enabled = enabled; 421 // Jump to the playing start frame if we should not continue, where we 422 // stop. 423 if (!continuePlaying && !(_PlayingDirectionFor(newState) == 0)) 424 newState->current_frame = _PlayingStartFrameFor(newState); 425 _PushState(newState, continuePlaying); 426 NotifyLoopingEnabledChanged(enabled); 427 } 428 429 430 void 431 PlaybackManager::SetSpeed(float speed) 432 { 433 SpeedInfo* lastSpeed = _LastSpeedInfo(); 434 if (speed != lastSpeed->set_speed) { 435 SpeedInfo* info = new SpeedInfo(*lastSpeed); 436 info->activation_frame = NextFrame(); 437 info->set_speed = speed; 438 if (_PlayingDirectionFor(_StateAtFrame(info->activation_frame)) != 0) 439 info->speed = info->set_speed; 440 else 441 info->speed = 1.0; 442 _PushSpeedInfo(info); 443 } 444 } 445 446 447 // #pragma mark - 448 449 450 /*! Returns the first frame at which a new playing state could become active, 451 that is the first frame for that neither the audio nor the video producer 452 have fetched data.*/ 453 int64 454 PlaybackManager::NextFrame() const 455 { 456 if (fNoAudio) 457 return FrameForTime(fCurrentVideoTime - 1) + 1; 458 459 return FrameForTime(max((bigtime_t)fCurrentAudioTime, 460 (bigtime_t)fCurrentVideoTime) - 1) + 1; 461 } 462 463 464 //! Returns the Playlist frame for NextFrame(). 465 int64 466 PlaybackManager::NextPlaylistFrame() const 467 { 468 return PlaylistFrameAtFrame(NextFrame()); 469 } 470 471 472 int64 473 PlaybackManager::FirstPlaybackRangeFrame() 474 { 475 PlayingState* state = _StateAtFrame(CurrentFrame()); 476 switch (state->loop_mode) { 477 case LOOPING_RANGE: 478 return state->start_frame; 479 case LOOPING_SELECTION: 480 // TODO: ... 481 return 0; 482 case LOOPING_VISIBLE: 483 return state->first_visible_frame; 484 485 case LOOPING_ALL: 486 default: 487 return 0; 488 } 489 } 490 491 492 int64 493 PlaybackManager::LastPlaybackRangeFrame() 494 { 495 PlayingState* state = _StateAtFrame(CurrentFrame()); 496 switch (state->loop_mode) { 497 case LOOPING_RANGE: 498 return state->end_frame; 499 case LOOPING_SELECTION: 500 // TODO: ... 501 return state->frame_count - 1; 502 case LOOPING_VISIBLE: 503 return state->last_visible_frame; 504 505 case LOOPING_ALL: 506 default: 507 return state->frame_count - 1; 508 } 509 } 510 511 512 // #pragma mark - 513 514 515 int64 516 PlaybackManager::StartFrameAtFrame(int64 frame) 517 { 518 return _StateAtFrame(frame)->start_frame; 519 } 520 521 522 int64 523 PlaybackManager::StartFrameAtTime(bigtime_t time) 524 { 525 return _StateAtTime(time)->start_frame; 526 } 527 528 529 int64 530 PlaybackManager::EndFrameAtFrame(int64 frame) 531 { 532 return _StateAtTime(frame)->end_frame; 533 } 534 535 536 int64 537 PlaybackManager::EndFrameAtTime(bigtime_t time) 538 { 539 return _StateAtTime(time)->end_frame; 540 } 541 542 543 int64 544 PlaybackManager::FrameCountAtFrame(int64 frame) 545 { 546 return _StateAtTime(frame)->frame_count; 547 } 548 549 550 int64 551 PlaybackManager::FrameCountAtTime(bigtime_t time) 552 { 553 return _StateAtTime(time)->frame_count; 554 } 555 556 557 int32 558 PlaybackManager::PlayModeAtFrame(int64 frame) 559 { 560 return _StateAtTime(frame)->play_mode; 561 } 562 563 564 int32 565 PlaybackManager::PlayModeAtTime(bigtime_t time) 566 { 567 return _StateAtTime(time)->play_mode; 568 } 569 570 571 int32 572 PlaybackManager::LoopModeAtFrame(int64 frame) 573 { 574 return _StateAtTime(frame)->loop_mode; 575 } 576 577 578 int32 579 PlaybackManager::LoopModeAtTime(bigtime_t time) 580 { 581 return _StateAtTime(time)->loop_mode; 582 } 583 584 585 /*! Returns which Playlist frame should be displayed at (performance) video 586 frame /frame/. Additionally the playing direction (0, 1, -1) is returned, 587 as well as if a new playing state becomes active with this frame. 588 A new playing state is installed, if either some data directly concerning 589 the playing (play mode, loop mode, playing ranges, selection...) or the 590 Playlist has changed. */ 591 int64 592 PlaybackManager::PlaylistFrameAtFrame(int64 frame, int32& playingDirection, 593 bool& newState) const 594 { 595 //TRACE("PlaybackManager::PlaylistFrameAtFrame(%lld)\n", frame); 596 PlayingState* state = _StateAtFrame(frame); 597 newState = (state->activation_frame == frame); 598 playingDirection = _PlayingDirectionFor(state); 599 //TRACE("playing state: activation frame: %lld, current frame: %lld, dir: %ld\n", 600 //state->activation_frame, state->current_frame, state->play_mode); 601 // The first part of the index calculation is invariable for a state. We 602 // could add it to the state data. 603 int64 result = state->current_frame; 604 if (playingDirection != 0) { 605 // int64 index = _RangeFrameForFrame(state, state->current_frame) 606 int64 index = state->range_index 607 + (frame - state->activation_frame) * playingDirection; 608 result = _FrameForRangeFrame(state, index); 609 } 610 //TRACE("PlaybackManager::PlaylistFrameAtFrame() done: %lld\n", result); 611 //printf("PlaybackManager::PlaylistFrameAtFrame(%lld): %lld, direction: %ld\n", 612 // frame, result, playingDirection); 613 return result; 614 } 615 616 617 int64 618 PlaybackManager::PlaylistFrameAtFrame(int64 frame, int32& playingDirection) const 619 { 620 bool newState; 621 return PlaylistFrameAtFrame(frame, playingDirection, newState); 622 } 623 624 625 int64 626 PlaybackManager::PlaylistFrameAtFrame(int64 frame) const 627 { 628 bool newState; 629 int32 playingDirection; 630 return PlaylistFrameAtFrame(frame, playingDirection, newState); 631 } 632 633 634 /*! Returns the index of the next frame after /startFrame/ at which a 635 playing state or speed change occurs or /endFrame/, if this happens to be 636 earlier. */ 637 int64 638 PlaybackManager::NextChangeFrame(int64 startFrame, int64 endFrame) const 639 { 640 int32 startIndex = _IndexForFrame(startFrame); 641 int32 endIndex = _IndexForFrame(endFrame); 642 if (startIndex < endIndex) 643 endFrame = _StateAt(startIndex + 1)->activation_frame; 644 startIndex = _SpeedInfoIndexForFrame(startFrame); 645 endIndex = _SpeedInfoIndexForFrame(endFrame); 646 if (startIndex < endIndex) 647 endFrame = _SpeedInfoAt(startIndex + 1)->activation_frame; 648 return endFrame; 649 } 650 651 652 /*! Returns the next time after /startTime/ at which a playing state or 653 speed change occurs or /endTime/, if this happens to be earlier. */ 654 bigtime_t 655 PlaybackManager::NextChangeTime(bigtime_t startTime, bigtime_t endTime) const 656 { 657 int32 startIndex = _IndexForTime(startTime); 658 int32 endIndex = _IndexForTime(endTime); 659 if (startIndex < endIndex) 660 endTime = TimeForFrame(_StateAt(startIndex + 1)->activation_frame); 661 startIndex = _SpeedInfoIndexForTime(startTime); 662 endIndex = _SpeedInfoIndexForTime(endTime); 663 if (startIndex < endIndex) 664 endTime = TimeForFrame(_SpeedInfoAt(startIndex + 1)->activation_frame); 665 return endTime; 666 } 667 668 669 /*! Returns a contiguous Playlist frame interval for a given frame interval. 670 The returned interval may be smaller than the supplied one. Therefore 671 the supplied /endFrame/ is adjusted. 672 The value written to /xEndFrame/ is the first frame that doesn't belong 673 to the interval. /playingDirection/ may either be -1 for backward, 674 1 for forward or 0 for not playing. */ 675 void 676 PlaybackManager::GetPlaylistFrameInterval(int64 startFrame, int64& endFrame, 677 int64& xStartFrame, int64& xEndFrame, int32& playingDirection) const 678 { 679 // limit the interval to one state and speed info 680 endFrame = NextChangeFrame(startFrame, endFrame); 681 // init return values 682 xStartFrame = PlaylistFrameAtFrame(startFrame); 683 xEndFrame = xStartFrame; 684 playingDirection = _PlayingDirectionFor(_StateAtFrame(startFrame)); 685 // Step through the interval and check whether the respective Playlist 686 // frames belong to the Playlist interval. 687 bool endOfInterval = false; 688 int64 intervalLength = 0; 689 while (startFrame < endFrame && !endOfInterval) { 690 intervalLength++; 691 startFrame++; 692 xEndFrame += playingDirection; 693 endOfInterval = (PlaylistFrameAtFrame(startFrame) != xEndFrame); 694 } 695 // order the interval bounds, if playing backwards 696 if (xStartFrame > xEndFrame) { 697 swap(xStartFrame, xEndFrame); 698 xStartFrame++; 699 xEndFrame++; 700 } 701 } 702 703 704 /*! The same as GetPlaylistFrameInterval() just for time instead of frame 705 intervals. Note, that /startTime/ and /endTime/ measure 706 performance times whereas /xStartTime/ and /xEndTime/ specifies an 707 Playlist time interval. In general it does not hold 708 xEndTime - xStartTime == endTime - startTime, even if playing (think 709 of a playing speed != 1.0). */ 710 void 711 PlaybackManager::GetPlaylistTimeInterval(bigtime_t startTime, 712 bigtime_t& endTime, bigtime_t& xStartTime, bigtime_t& xEndTime, 713 float& playingSpeed) const 714 { 715 // Get the frames that bound the given time interval. The end frame might 716 // be greater than necessary, but that doesn't harm. 717 int64 startFrame = FrameForTime(startTime); 718 int64 endFrame = FrameForTime(endTime) + 1; 719 SpeedInfo* info = _SpeedInfoForFrame(startFrame); 720 // Get the Playlist frame interval that belongs to the frame interval. 721 int64 xStartFrame; 722 int64 xEndFrame; 723 int32 playingDirection; 724 GetPlaylistFrameInterval(startFrame, endFrame, xStartFrame, xEndFrame, 725 playingDirection); 726 // Calculate the performance time interval end/length. 727 bigtime_t endTimeForFrame = TimeForFrame(endFrame); 728 endTime = min(endTime, endTimeForFrame); 729 bigtime_t intervalLength = endTime - startTime; 730 731 // Finally determine the time bounds for the Playlist interval (depending 732 // on the playing direction). 733 switch (playingDirection) { 734 // forward 735 case 1: 736 { 737 // xStartTime = PlaylistTimeForFrame(xStartFrame) 738 // + startTime - TimeForFrame(startFrame); 739 // xEndTime = xStartTime + intervalLength; 740 741 // TODO: The current method does not handle the times the same way. 742 // It may happen, that for the same performance time different 743 // Playlist times (within a frame) are returned when passing it 744 // one time as a start time and another time as an end time. 745 xStartTime = PlaylistTimeForFrame(xStartFrame) 746 + bigtime_t(double(startTime - TimeForFrame(startFrame)) 747 * info->speed); 748 xEndTime = xStartTime 749 + bigtime_t((double)intervalLength * info->speed); 750 break; 751 } 752 // backward 753 case -1: 754 { 755 // xEndTime = PlaylistTimeForFrame(xEndFrame) 756 // - startTime + TimeForFrame(startFrame); 757 // xStartTime = xEndTime - intervalLength; 758 759 xEndTime = PlaylistTimeForFrame(xEndFrame) 760 - bigtime_t(double(startTime - TimeForFrame(startFrame)) 761 * info->speed); 762 xStartTime = xEndTime 763 - bigtime_t((double)intervalLength * info->speed); 764 break; 765 } 766 // not playing 767 case 0: 768 default: 769 xStartTime = PlaylistTimeForFrame(xStartFrame); 770 xEndTime = xStartTime; 771 break; 772 } 773 playingSpeed = (float)playingDirection * info->speed; 774 } 775 776 777 /*! Returns the frame that is being performed at the supplied time. 778 It holds TimeForFrame(frame) <= time < TimeForFrame(frame + 1). */ 779 int64 780 PlaybackManager::FrameForTime(bigtime_t time) const 781 { 782 //TRACE("PlaybackManager::FrameForTime(%lld)\n", time); 783 // return (int64)((double)time * (double)fFrameRate / 1000000.0); 784 // In order to avoid problems caused by rounding errors, we check 785 // if for the resulting frame holds 786 // TimeForFrame(frame) <= time < TimeForFrame(frame + 1). 787 // int64 frame = (int64)((double)time * (double)fFrameRate / 1000000.0); 788 SpeedInfo* info = _SpeedInfoForTime(time); 789 if (!info) { 790 fprintf(stderr, "PlaybackManager::FrameForTime() - no SpeedInfo!\n"); 791 return 0; 792 } 793 int64 frame = (int64)(((double)time - info->activation_time) 794 * (double)fFrameRate * info->speed / 1000000.0) 795 + info->activation_frame; 796 if (TimeForFrame(frame) > time) 797 frame--; 798 else if (TimeForFrame(frame + 1) <= time) 799 frame++; 800 //TRACE("PlaybackManager::FrameForTime() done: %lld\n", frame); 801 //printf("PlaybackManager::FrameForTime(%lld): %lld\n", time, frame); 802 return frame; 803 } 804 805 806 /*! Returns the time at which the supplied frame should be performed (started 807 to be performed). */ 808 bigtime_t 809 PlaybackManager::TimeForFrame(int64 frame) const 810 { 811 // return (bigtime_t)((double)frame * 1000000.0 / (double)fFrameRate); 812 SpeedInfo* info = _SpeedInfoForFrame(frame); 813 if (!info) { 814 fprintf(stderr, "PlaybackManager::TimeForFrame() - no SpeedInfo!\n"); 815 return 0; 816 } 817 // return (bigtime_t)((double)(frame - info->activation_frame) * 1000000.0 818 // / ((double)fFrameRate * info->speed)) 819 // + info->activation_time; 820 bigtime_t result = (bigtime_t)((double)(frame - info->activation_frame) * 1000000.0 821 / ((double)fFrameRate * info->speed)) + info->activation_time; 822 //fprintf(stderr, "PlaybackManager::TimeForFrame(%lld): %lld\n", frame, result); 823 return result; 824 } 825 826 827 /*! Returns the Playlist frame for an Playlist time. 828 It holds PlaylistTimeForFrame(frame) <= time < 829 PlaylistTimeForFrame(frame + 1). */ 830 int64 831 PlaybackManager::PlaylistFrameForTime(bigtime_t time) const 832 { 833 // In order to avoid problems caused by rounding errors, we check 834 // if for the resulting frame holds 835 // PlaylistTimeForFrame(frame) <= time < PlaylistTimeForFrame(frame + 1). 836 int64 frame = (int64)((double)time * (double)fFrameRate / 1000000.0); 837 if (TimeForFrame(frame) > time) 838 frame--; 839 else if (TimeForFrame(frame + 1) <= time) 840 frame++; 841 return frame; 842 } 843 844 845 //! Returns the Playlist start time for an Playlist frame. 846 bigtime_t 847 PlaybackManager::PlaylistTimeForFrame(int64 frame) const 848 { 849 return (bigtime_t)((double)frame * 1000000.0 / (double)fFrameRate); 850 } 851 852 853 //! To be called when done with all activities concerning audio before /time/. 854 void 855 PlaybackManager::SetCurrentAudioTime(bigtime_t time) 856 { 857 TRACE("PlaybackManager::SetCurrentAudioTime(%lld)\n", time); 858 bigtime_t lastFrameTime = _TimeForLastFrame(); 859 fCurrentAudioTime = time; 860 // _UpdateStates(); 861 bigtime_t newLastFrameTime = _TimeForLastFrame(); 862 if (lastFrameTime != newLastFrameTime) { 863 bigtime_t eventTime = RealTimeForTime(newLastFrameTime); 864 EventQueue::Default().AddEvent(new MessageEvent(eventTime, this)); 865 _CheckStopPlaying(); 866 } 867 } 868 869 870 //! To be called when done with all activities concerning video before /frame/. 871 void 872 PlaybackManager::SetCurrentVideoFrame(int64 frame) 873 { 874 SetCurrentVideoTime(TimeForFrame(frame)); 875 } 876 877 878 //! To be called when done with all activities concerning video before /time/. 879 void 880 PlaybackManager::SetCurrentVideoTime(bigtime_t time) 881 { 882 TRACE("PlaybackManager::SetCurrentVideoTime(%lld)\n", time); 883 bigtime_t lastFrameTime = _TimeForLastFrame(); 884 fCurrentVideoTime = time; 885 // _UpdateStates(); 886 bigtime_t newLastFrameTime = _TimeForLastFrame(); 887 if (lastFrameTime != newLastFrameTime) { 888 bigtime_t eventTime = RealTimeForTime(newLastFrameTime); 889 EventQueue::Default().AddEvent(new MessageEvent(eventTime, this)); 890 _CheckStopPlaying(); 891 } 892 } 893 894 895 //! To be called as soon as video frame /frame/ is being performed. 896 void 897 PlaybackManager::SetPerformanceFrame(int64 frame) 898 { 899 SetPerformanceFrame(TimeForFrame(frame)); 900 } 901 902 903 /*! Similar to SetPerformanceTime() just with a time instead of a frame 904 argument. */ 905 void 906 PlaybackManager::SetPerformanceTime(bigtime_t time) 907 { 908 int32 oldCurrentFrame = CurrentFrame(); 909 fPerformanceTime = time; 910 _UpdateStates(); 911 _UpdateSpeedInfos(); 912 int32 currentFrame = CurrentFrame(); 913 914 //printf("PlaybackManager::SetPerformanceTime(%lld): %ld -> %ld\n", 915 // time, oldCurrentFrame, currentFrame); 916 917 if (currentFrame != oldCurrentFrame) 918 NotifyCurrentFrameChanged(currentFrame); 919 } 920 921 922 // #pragma mark - Listeners 923 924 925 void 926 PlaybackManager::AddListener(PlaybackListener* listener) 927 { 928 if (!listener) 929 return; 930 931 if (!Lock()) 932 return; 933 934 if (!fListeners.HasItem(listener) && fListeners.AddItem(listener)) { 935 // bring listener up2date, if we have been initialized 936 if (_LastState()) { 937 listener->PlayModeChanged(PlayMode()); 938 listener->LoopModeChanged(LoopMode()); 939 listener->LoopingEnabledChanged(IsLoopingEnabled()); 940 listener->VideoBoundsChanged(VideoBounds()); 941 listener->FramesPerSecondChanged(FramesPerSecond()); 942 listener->SpeedChanged(Speed()); 943 listener->CurrentFrameChanged(CurrentFrame()); 944 } 945 } 946 947 Unlock(); 948 } 949 950 951 void 952 PlaybackManager::RemoveListener(PlaybackListener* listener) 953 { 954 if (listener && Lock()) { 955 fListeners.RemoveItem(listener); 956 Unlock(); 957 } 958 } 959 960 961 void 962 PlaybackManager::NotifyPlayModeChanged(int32 mode) const 963 { 964 for (int32 i = 0; 965 PlaybackListener* listener = (PlaybackListener*)fListeners.ItemAt(i); 966 i++) { 967 listener->PlayModeChanged(mode); 968 } 969 } 970 971 972 void 973 PlaybackManager::NotifyLoopModeChanged(int32 mode) const 974 { 975 for (int32 i = 0; 976 PlaybackListener* listener = (PlaybackListener*)fListeners.ItemAt(i); 977 i++) { 978 listener->LoopModeChanged(mode); 979 } 980 } 981 982 983 void 984 PlaybackManager::NotifyLoopingEnabledChanged(bool enabled) const 985 { 986 for (int32 i = 0; 987 PlaybackListener* listener = (PlaybackListener*)fListeners.ItemAt(i); 988 i++) { 989 listener->LoopingEnabledChanged(enabled); 990 } 991 } 992 993 994 void 995 PlaybackManager::NotifyVideoBoundsChanged(BRect bounds) const 996 { 997 for (int32 i = 0; 998 PlaybackListener* listener = (PlaybackListener*)fListeners.ItemAt(i); 999 i++) { 1000 listener->VideoBoundsChanged(bounds); 1001 } 1002 } 1003 1004 1005 void 1006 PlaybackManager::NotifyFPSChanged(float fps) const 1007 { 1008 for (int32 i = 0; 1009 PlaybackListener* listener = (PlaybackListener*)fListeners.ItemAt(i); 1010 i++) { 1011 listener->FramesPerSecondChanged(fps); 1012 } 1013 } 1014 1015 1016 void 1017 PlaybackManager::NotifyCurrentFrameChanged(int32 frame) const 1018 { 1019 for (int32 i = 0; 1020 PlaybackListener* listener = (PlaybackListener*)fListeners.ItemAt(i); 1021 i++) { 1022 listener->CurrentFrameChanged(frame); 1023 } 1024 } 1025 1026 1027 void 1028 PlaybackManager::NotifySpeedChanged(float speed) const 1029 { 1030 for (int32 i = 0; 1031 PlaybackListener* listener = (PlaybackListener*)fListeners.ItemAt(i); 1032 i++) { 1033 listener->SpeedChanged(speed); 1034 } 1035 } 1036 1037 1038 void 1039 PlaybackManager::NotifyFrameDropped() const 1040 { 1041 for (int32 i = 0; 1042 PlaybackListener* listener = (PlaybackListener*)fListeners.ItemAt(i); 1043 i++) { 1044 listener->FrameDropped(); 1045 } 1046 } 1047 1048 1049 void 1050 PlaybackManager::NotifyStopFrameReached() const 1051 { 1052 // not currently implemented in PlaybackListener interface 1053 } 1054 1055 1056 void 1057 PlaybackManager::PrintState(PlayingState* state) 1058 { 1059 TRACE("state: activation frame: %lld, current frame: %lld, " 1060 "start frame: %lld, end frame: %lld, frame count: %lld, " 1061 "first visible: %lld, last visible: %lld, selection (...), " 1062 "play mode: %ld, loop mode: %ld\n", 1063 state->activation_frame, 1064 state->current_frame, 1065 state->start_frame, 1066 state->end_frame, 1067 state->frame_count, 1068 state->first_visible_frame, 1069 state->last_visible_frame, 1070 // state->selection, 1071 state->play_mode, 1072 state->loop_mode); 1073 } 1074 1075 1076 void 1077 PlaybackManager::PrintStateAtFrame(int64 frame) 1078 { 1079 TRACE("frame %lld: ", frame); 1080 PrintState(_StateAtFrame(frame)); 1081 } 1082 1083 1084 /*! Appends the supplied state to the list of states. If the state would 1085 become active at the same time as _LastState() the latter is removed 1086 and deleted. However, the activation time for the new state is adjusted, 1087 so that it is >= that of the last state and >= the current audio and 1088 video time. If the additional parameter /adjustCurrentFrame/ is true, 1089 the new state's current frame is tried to be set to the frame that is 1090 reached at the time the state will become active. In every case 1091 it is ensured that the current frame lies within the playing range 1092 (if playing). */ 1093 void 1094 PlaybackManager::_PushState(PlayingState* state, bool adjustCurrentFrame) 1095 { 1096 // if (!_LastState()) 1097 // debugger("PlaybackManager::_PushState() used before Init()\n"); 1098 1099 TRACE("PlaybackManager::_PushState()\n"); 1100 if (state) { 1101 // unset fStopPlayingFrame 1102 int64 oldStopPlayingFrame = fStopPlayingFrame; 1103 fStopPlayingFrame = -1; 1104 // get last state 1105 PlayingState* lastState = _LastState(); 1106 int64 activationFrame = max(max(state->activation_frame, 1107 lastState->activation_frame), 1108 NextFrame()); 1109 TRACE(" state activation frame: %lld, last state activation frame: %lld, " 1110 "NextFrame(): %lld\n", state->activation_frame, lastState->activation_frame, 1111 NextFrame()); 1112 1113 int64 currentFrame = 0; 1114 // remember the current frame, if necessary 1115 if (adjustCurrentFrame) 1116 currentFrame = PlaylistFrameAtFrame(activationFrame); 1117 // check whether it is active 1118 // (NOTE: We may want to keep the last state, if it is not active, 1119 // but then the new state should become active after the last one. 1120 // Thus we had to replace `NextFrame()' with `activationFrame'.) 1121 if (lastState->activation_frame >= NextFrame()) { 1122 // it isn't -- remove it 1123 fStates.RemoveItem(fStates.CountItems() - 1); 1124 TRACE("deleting last \n"); 1125 PrintState(lastState); 1126 delete lastState; 1127 } else { 1128 // it is -- keep it 1129 } 1130 // adjust the new state's current frame and activation frame 1131 if (adjustCurrentFrame) 1132 state->current_frame = currentFrame; 1133 int32 playingDirection = _PlayingDirectionFor(state); 1134 if (playingDirection != 0) { 1135 state->current_frame 1136 = _NextFrameInRange(state, state->current_frame); 1137 } else { 1138 // If not playing, we check at least, if the current frame lies 1139 // within the interval [0, max_frame_count). 1140 if (state->current_frame >= state->max_frame_count) 1141 state->current_frame = state->max_frame_count - 1; 1142 if (state->current_frame < 0) 1143 state->current_frame = 0; 1144 } 1145 state->range_index = _RangeFrameForFrame(state, state->current_frame); 1146 state->activation_frame = activationFrame; 1147 fStates.AddItem(state); 1148 PrintState(state); 1149 TRACE("_PushState: state count: %ld\n", fStates.CountItems()); 1150 // push a new speed info 1151 SpeedInfo* speedInfo = new SpeedInfo(*_LastSpeedInfo()); 1152 if (playingDirection == 0) 1153 speedInfo->speed = 1.0; 1154 else 1155 speedInfo->speed = speedInfo->set_speed; 1156 speedInfo->activation_frame = state->activation_frame; 1157 _PushSpeedInfo(speedInfo); 1158 // If the new state is a playing state and looping is turned off, 1159 // determine when playing shall stop. 1160 if (playingDirection != 0 && !state->looping_enabled) { 1161 int64 startFrame, endFrame, frameCount; 1162 _GetPlayingBoundsFor(state, startFrame, endFrame, frameCount); 1163 if (playingDirection == -1) 1164 swap(startFrame, endFrame); 1165 // If we shall stop at the frame we start, set the current frame 1166 // to the beginning of the range. 1167 // We have to take care, since this state may equal the one 1168 // before (or probably differs in just one (unimportant) 1169 // parameter). This happens for instance, if the user changes the 1170 // data or start/end frame... while playing. In this case setting 1171 // the current frame to the start frame is unwanted. Therefore 1172 // we check whether the previous state was intended to stop 1173 // at the activation frame of this state. 1174 if (oldStopPlayingFrame != state->activation_frame 1175 && state->current_frame == endFrame && frameCount > 1) { 1176 state->current_frame = startFrame; 1177 state->range_index 1178 = _RangeFrameForFrame(state, state->current_frame); 1179 } 1180 if (playingDirection == 1) { // forward 1181 fStopPlayingFrame = state->activation_frame 1182 + frameCount - state->range_index - 1; 1183 } else { // backwards 1184 fStopPlayingFrame = state->activation_frame 1185 + state->range_index; 1186 } 1187 _CheckStopPlaying(); 1188 } 1189 } 1190 TRACE("PlaybackManager::_PushState() done\n"); 1191 } 1192 1193 1194 /*! Removes and deletes all states that are obsolete, that is which stopped 1195 being active at or before the current audio and video time. */ 1196 void 1197 PlaybackManager::_UpdateStates() 1198 { 1199 // int32 firstActive = min(_IndexForTime(fCurrentAudioTime), 1200 // _IndexForTime(fCurrentVideoTime)); 1201 // Performance time should always be the least one. 1202 int32 firstActive = _IndexForTime(fPerformanceTime); 1203 //TRACE("firstActive: %ld, numStates: %ld\n", firstActive, fStates.CountItems()); 1204 for (int32 i = 0; i < firstActive; i++) 1205 delete _StateAt(i); 1206 if (firstActive > 0) 1207 { 1208 fStates.RemoveItems(0, firstActive); 1209 TRACE("_UpdateStates: states removed: %ld, state count: %ld\n", 1210 firstActive, fStates.CountItems()); 1211 } 1212 } 1213 1214 1215 /*! Returns the index of the state, that is active at frame /frame/. 1216 The index of the first frame (0) is returned, if /frame/ is even less 1217 than the frame at which this state becomes active. */ 1218 int32 1219 PlaybackManager::_IndexForFrame(int64 frame) const 1220 { 1221 int32 index = 0; 1222 PlayingState* state; 1223 while (((state = _StateAt(index + 1))) && state->activation_frame <= frame) 1224 index++; 1225 return index; 1226 } 1227 1228 /*! Returns the index of the state, that is active at time /time/. 1229 The index of the first frame (0) is returned, if /time/ is even less 1230 than the time at which this state becomes active. */ 1231 int32 1232 PlaybackManager::_IndexForTime(bigtime_t time) const 1233 { 1234 return _IndexForFrame(FrameForTime(time)); 1235 } 1236 1237 1238 //! Returns the state that reflects the most recent changes. 1239 PlaybackManager::PlayingState* 1240 PlaybackManager::_LastState() const 1241 { 1242 return _StateAt(fStates.CountItems() - 1); 1243 } 1244 1245 1246 PlaybackManager::PlayingState* 1247 PlaybackManager::_StateAt(int32 index) const 1248 { 1249 return (PlayingState*)fStates.ItemAt(index); 1250 } 1251 1252 1253 PlaybackManager::PlayingState* 1254 PlaybackManager::_StateAtFrame(int64 frame) const 1255 { 1256 return _StateAt(_IndexForFrame(frame)); 1257 } 1258 1259 1260 PlaybackManager::PlayingState* 1261 PlaybackManager::_StateAtTime(bigtime_t time) const 1262 { 1263 return _StateAt(_IndexForTime(time)); 1264 } 1265 1266 1267 int32 1268 PlaybackManager::_PlayingDirectionFor(int32 playingMode) 1269 { 1270 int32 direction = 0; 1271 switch (playingMode) { 1272 case MODE_PLAYING_FORWARD: 1273 direction = 1; 1274 break; 1275 case MODE_PLAYING_BACKWARD: 1276 direction = -1; 1277 break; 1278 case MODE_PLAYING_PAUSED_FORWARD: 1279 case MODE_PLAYING_PAUSED_BACKWARD: 1280 break; 1281 } 1282 return direction; 1283 } 1284 1285 1286 int32 1287 PlaybackManager::_PlayingDirectionFor(PlayingState* state) 1288 { 1289 return _PlayingDirectionFor(state->play_mode); 1290 } 1291 1292 1293 /*! Returns the Playlist frame range that bounds the playing range of a given 1294 state. 1295 \a startFrame is the lower and \a endFrame the upper bound of the range, 1296 and \a frameCount the number of frames in the range; it is guaranteed to 1297 be >= 1, even for an empty selection. */ 1298 void 1299 PlaybackManager::_GetPlayingBoundsFor(PlayingState* state, int64& startFrame, 1300 int64& endFrame, int64& frameCount) 1301 { 1302 switch (state->loop_mode) { 1303 case LOOPING_ALL: 1304 startFrame = 0; 1305 endFrame = max(startFrame, state->frame_count - 1); 1306 frameCount = endFrame - startFrame + 1; 1307 break; 1308 case LOOPING_RANGE: 1309 startFrame = state->start_frame; 1310 endFrame = state->end_frame; 1311 frameCount = endFrame - startFrame + 1; 1312 break; 1313 // case LOOPING_SELECTION: 1314 // if (!state->selection.IsEmpty()) { 1315 // startFrame = state->selection.FirstIndex(); 1316 // endFrame = state->selection.LastIndex(); 1317 // frameCount = state->selection.CountIndices(); 1318 //TRACE(" LOOPING_SELECTION: %lld - %lld (%lld)\n", startFrame, endFrame, 1319 //frameCount); 1320 // } else { 1321 // startFrame = state->current_frame; 1322 // endFrame = state->current_frame; 1323 // frameCount = 1; 1324 // } 1325 // break; 1326 case LOOPING_VISIBLE: 1327 startFrame = state->first_visible_frame; 1328 endFrame = state->last_visible_frame; 1329 frameCount = endFrame - startFrame + 1; 1330 break; 1331 } 1332 } 1333 1334 1335 /*! Returns the frame at which playing would start for a given playing 1336 state. If the playing mode for the supplied state specifies a stopped 1337 or undefined mode, the result is the state's current frame. */ 1338 int64 1339 PlaybackManager::_PlayingStartFrameFor(PlayingState* state) 1340 { 1341 int64 startFrame, endFrame, frameCount, frame = 0; 1342 _GetPlayingBoundsFor(state, startFrame, endFrame, frameCount); 1343 switch (_PlayingDirectionFor(state)) { 1344 case -1: 1345 frame = endFrame; 1346 break; 1347 case 1: 1348 frame = startFrame; 1349 break; 1350 default: 1351 frame = state->current_frame; 1352 break; 1353 } 1354 return frame; 1355 } 1356 1357 1358 /*! Returns the frame at which playing would end for a given playing 1359 state. If the playing mode for the supplied state specifies a stopped 1360 or undefined mode, the result is the state's current frame. */ 1361 int64 1362 PlaybackManager::_PlayingEndFrameFor(PlayingState* state) 1363 { 1364 int64 startFrame, endFrame, frameCount, frame = 0; 1365 _GetPlayingBoundsFor(state, startFrame, endFrame, frameCount); 1366 switch (_PlayingDirectionFor(state)) { 1367 case -1: 1368 frame = startFrame; 1369 break; 1370 case 1: 1371 frame = endFrame; 1372 break; 1373 default: 1374 frame = state->current_frame; 1375 break; 1376 } 1377 return frame; 1378 } 1379 1380 1381 /*! Returns the index that the supplied frame has within a playing range. 1382 If the state specifies a not-playing mode, 0 is returned. The supplied 1383 frame has to lie within the bounds of the playing range, but it doesn't 1384 need to be contained, e.g. if the range is not contiguous. In this case 1385 the index of the next frame within the range (in playing direction) is 1386 returned. */ 1387 int64 1388 PlaybackManager::_RangeFrameForFrame(PlayingState* state, int64 frame) 1389 { 1390 TRACE("PlaybackManager::_RangeFrameForFrame(%lld)\n", frame); 1391 int64 startFrame, endFrame, frameCount; 1392 int64 index = 0; 1393 _GetPlayingBoundsFor(state, startFrame, endFrame, frameCount); 1394 TRACE(" start frame: %lld, end frame: %lld, frame count: %lld\n", 1395 startFrame, endFrame, frameCount); 1396 switch (state->loop_mode) { 1397 case LOOPING_ALL: 1398 case LOOPING_RANGE: 1399 case LOOPING_VISIBLE: 1400 index = frame - startFrame; 1401 break; 1402 } 1403 TRACE("PlaybackManager::_RangeFrameForFrame() done: %lld\n", index); 1404 return index; 1405 } 1406 1407 1408 /*! Returns the Playlist frame for a playing range index. /index/ doesn't need 1409 to be in the playing range -- it is mapped into. */ 1410 int64 1411 PlaybackManager::_FrameForRangeFrame(PlayingState* state, int64 index) 1412 { 1413 TRACE("PlaybackManager::_FrameForRangeFrame(%lld)\n", index); 1414 int64 startFrame, endFrame, frameCount; 1415 _GetPlayingBoundsFor(state, startFrame, endFrame, frameCount); 1416 TRACE(" frame range: %lld - %lld, count: %lld\n", startFrame, endFrame, 1417 frameCount); 1418 // map the index into the index interval of the playing range 1419 if (frameCount > 0) 1420 index = (index % frameCount + frameCount) % frameCount; 1421 else 1422 index = 0; 1423 // get the frame for the index 1424 int32 frame = startFrame; 1425 switch (state->loop_mode) { 1426 case LOOPING_ALL: 1427 case LOOPING_RANGE: 1428 case LOOPING_VISIBLE: 1429 frame = startFrame + index; 1430 break; 1431 } 1432 TRACE("PlaybackManager::_FrameForRangeFrame() done: %ld\n", frame); 1433 return frame; 1434 } 1435 1436 1437 /*! Given an arbitrary Playlist frame this function returns the next frame within 1438 the playing range for the supplied playing state. */ 1439 int64 1440 PlaybackManager::_NextFrameInRange(PlayingState* state, int64 frame) 1441 { 1442 int64 newFrame = frame; 1443 int64 startFrame, endFrame, frameCount; 1444 _GetPlayingBoundsFor(state, startFrame, endFrame, frameCount); 1445 if (frame < startFrame || frame > endFrame) 1446 newFrame = _PlayingStartFrameFor(state); 1447 else { 1448 int64 index = _RangeFrameForFrame(state, frame); 1449 newFrame = _FrameForRangeFrame(state, index); 1450 if (newFrame > frame && _PlayingDirectionFor(state) == -1) 1451 newFrame = _FrameForRangeFrame(state, index - 1); 1452 } 1453 return newFrame; 1454 } 1455 1456 1457 void 1458 PlaybackManager::_PushSpeedInfo(SpeedInfo* info) 1459 { 1460 if (info) { 1461 // check the last state 1462 if (SpeedInfo* lastSpeed = _LastSpeedInfo()) { 1463 // set the activation time 1464 info->activation_time = TimeForFrame(info->activation_frame); 1465 // Remove the last state, if it won't be activated. 1466 if (lastSpeed->activation_frame == info->activation_frame) { 1467 //fprintf(stderr, " replacing last speed info\n"); 1468 fSpeeds.RemoveItem(lastSpeed); 1469 delete lastSpeed; 1470 } 1471 } 1472 fSpeeds.AddItem(info); 1473 //fprintf(stderr, " speed info pushed: activation frame: %lld, " 1474 //"activation time: %lld, speed: %f\n", info->activation_frame, 1475 //info->activation_time, info->speed); 1476 // ... 1477 } 1478 } 1479 1480 1481 PlaybackManager::SpeedInfo* 1482 PlaybackManager::_LastSpeedInfo() const 1483 { 1484 return (SpeedInfo*)fSpeeds.ItemAt(fSpeeds.CountItems() - 1); 1485 } 1486 1487 1488 PlaybackManager::SpeedInfo* 1489 PlaybackManager::_SpeedInfoAt(int32 index) const 1490 { 1491 return (SpeedInfo*)fSpeeds.ItemAt(index); 1492 } 1493 1494 1495 int32 1496 PlaybackManager::_SpeedInfoIndexForFrame(int64 frame) const 1497 { 1498 int32 index = 0; 1499 SpeedInfo* info; 1500 while (((info = _SpeedInfoAt(index + 1))) 1501 && info->activation_frame <= frame) { 1502 index++; 1503 } 1504 //fprintf(stderr, "PlaybackManager::_SpeedInfoIndexForFrame(%lld): %ld\n", 1505 //frame, index); 1506 return index; 1507 } 1508 1509 1510 int32 1511 PlaybackManager::_SpeedInfoIndexForTime(bigtime_t time) const 1512 { 1513 int32 index = 0; 1514 SpeedInfo* info; 1515 while (((info = _SpeedInfoAt(index + 1))) 1516 && info->activation_time <= time) { 1517 index++; 1518 } 1519 //fprintf(stderr, "PlaybackManager::_SpeedInfoIndexForTime(%lld): %ld\n", 1520 //time, index); 1521 return index; 1522 } 1523 1524 1525 PlaybackManager::SpeedInfo* 1526 PlaybackManager::_SpeedInfoForFrame(int64 frame) const 1527 { 1528 return _SpeedInfoAt(_SpeedInfoIndexForFrame(frame)); 1529 } 1530 1531 1532 PlaybackManager::SpeedInfo* 1533 PlaybackManager::_SpeedInfoForTime(bigtime_t time) const 1534 { 1535 return _SpeedInfoAt(_SpeedInfoIndexForTime(time)); 1536 } 1537 1538 1539 void 1540 PlaybackManager::_UpdateSpeedInfos() 1541 { 1542 int32 firstActive = _SpeedInfoIndexForTime(fPerformanceTime); 1543 for (int32 i = 0; i < firstActive; i++) 1544 delete _SpeedInfoAt(i); 1545 if (firstActive > 0) 1546 fSpeeds.RemoveItems(0, firstActive); 1547 //fprintf(stderr, " speed infos 0 - %ld removed\n", firstActive); 1548 } 1549 1550 1551 /*! Returns the end time for the last video frame that the video and the 1552 audio producer both have completely processed. */ 1553 bigtime_t 1554 PlaybackManager::_TimeForLastFrame() const 1555 { 1556 if (fNoAudio) 1557 return TimeForFrame(FrameForTime(fCurrentVideoTime)); 1558 1559 return TimeForFrame(FrameForTime(min((bigtime_t)fCurrentAudioTime, 1560 (bigtime_t)fCurrentVideoTime))); 1561 } 1562 1563 1564 /*! Returns the start time for the first video frame for which 1565 neither the video nor the audio producer have fetched data. */ 1566 bigtime_t 1567 PlaybackManager::_TimeForNextFrame() const 1568 { 1569 return TimeForFrame(NextFrame()); 1570 } 1571 1572 1573 void 1574 PlaybackManager::_CheckStopPlaying() 1575 { 1576 //printf("_CheckStopPlaying() - %lld, next: %lld\n", fStopPlayingFrame, NextFrame()); 1577 if (fStopPlayingFrame >= 0 && fStopPlayingFrame <= NextFrame()) { 1578 StopPlaying(); 1579 NotifyStopFrameReached(); 1580 } 1581 } 1582 1583