diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/mohawk/livingbooks.cpp | 2 | ||||
-rw-r--r-- | engines/mohawk/myst_areas.cpp | 16 | ||||
-rw-r--r-- | engines/mohawk/myst_stacks/channelwood.cpp | 8 | ||||
-rw-r--r-- | engines/mohawk/myst_stacks/dni.cpp | 18 | ||||
-rw-r--r-- | engines/mohawk/myst_stacks/mechanical.cpp | 46 | ||||
-rw-r--r-- | engines/mohawk/myst_stacks/myst.cpp | 92 | ||||
-rw-r--r-- | engines/mohawk/myst_stacks/stoneship.cpp | 20 | ||||
-rw-r--r-- | engines/mohawk/riven.cpp | 22 | ||||
-rw-r--r-- | engines/mohawk/riven_external.cpp | 52 | ||||
-rw-r--r-- | engines/mohawk/riven_scripts.cpp | 8 | ||||
-rw-r--r-- | engines/mohawk/video.cpp | 531 | ||||
-rw-r--r-- | engines/mohawk/video.h | 274 |
12 files changed, 651 insertions, 438 deletions
diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp index 14ce4bab52..6874f2420e 100644 --- a/engines/mohawk/livingbooks.cpp +++ b/engines/mohawk/livingbooks.cpp @@ -3791,7 +3791,7 @@ LBMovieItem::~LBMovieItem() { void LBMovieItem::update() { if (_playing) { VideoHandle videoHandle = _vm->_video->findVideoHandle(_resourceId); - if (videoHandle == NULL_VID_HANDLE || _vm->_video->endOfVideo(videoHandle)) + if (!videoHandle || videoHandle->endOfVideo()) done(true); } diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp index 4a3001774a..fcfb55e3b3 100644 --- a/engines/mohawk/myst_areas.cpp +++ b/engines/mohawk/myst_areas.cpp @@ -223,20 +223,20 @@ VideoHandle MystResourceType6::playMovie() { VideoHandle handle = _vm->_video->findVideoHandle(_videoFile); // If the video is not running, play it - if (handle == NULL_VID_HANDLE || _vm->_video->endOfVideo(handle)) { + if (!handle || handle->endOfVideo()) { handle = _vm->_video->playMovie(_videoFile, _left, _top, _loop); if (_direction == -1) { - _vm->_video->seekToTime(handle, _vm->_video->getDuration(handle)); - _vm->_video->setVideoRate(handle, -1); + handle->seek(handle->getDuration()); + handle->setRate(-1); } } else { // Resume the video - _vm->_video->pauseMovie(handle, false); + handle->pause(false); } if (_playBlocking) { _vm->_video->waitUntilMovieEnds(handle); - handle = NULL_VID_HANDLE; + return VideoHandle(); } return handle; @@ -249,13 +249,13 @@ void MystResourceType6::handleCardChange() { bool MystResourceType6::isPlaying() { VideoHandle handle = _vm->_video->findVideoHandle(_videoFile); - return handle != NULL_VID_HANDLE && !_vm->_video->endOfVideo(handle); + return handle && !handle->endOfVideo(); } void MystResourceType6::pauseMovie(bool pause) { VideoHandle handle = _vm->_video->findVideoHandle(_videoFile); - if (handle != NULL_VID_HANDLE && !_vm->_video->endOfVideo(handle)) - _vm->_video->pauseMovie(handle, pause); + if (handle && !handle->endOfVideo()) + handle->pause(pause); } MystResourceType7::MystResourceType7(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResource(vm, rlstStream, parent) { diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp index 2dd5745550..0bd8100c84 100644 --- a/engines/mohawk/myst_stacks/channelwood.cpp +++ b/engines/mohawk/myst_stacks/channelwood.cpp @@ -303,9 +303,9 @@ void Channelwood::o_bridgeToggle(uint16 op, uint16 var, uint16 argc, uint16 *arg // Toggle bridge state if (_state.waterPumpBridgeState) - _vm->_video->setVideoBounds(bridge, Audio::Timestamp(0, 3050, 600), Audio::Timestamp(0, 6100, 600)); + bridge->setBounds(Audio::Timestamp(0, 3050, 600), Audio::Timestamp(0, 6100, 600)); else - _vm->_video->setVideoBounds(bridge, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 3050, 600)); + bridge->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 3050, 600)); _vm->_video->waitUntilMovieEnds(bridge); } @@ -321,9 +321,9 @@ void Channelwood::o_pipeExtend(uint16 op, uint16 var, uint16 argc, uint16 *argv) // Toggle pipe state if (_state.pipeState) - _vm->_video->setVideoBounds(pipe, Audio::Timestamp(0, 3040, 600), Audio::Timestamp(0, 6080, 600)); + pipe->setBounds(Audio::Timestamp(0, 3040, 600), Audio::Timestamp(0, 6080, 600)); else - _vm->_video->setVideoBounds(pipe, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 3040, 600)); + pipe->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 3040, 600)); _vm->_video->waitUntilMovieEnds(pipe); _vm->_sound->resumeBackgroundMyst(); diff --git a/engines/mohawk/myst_stacks/dni.cpp b/engines/mohawk/myst_stacks/dni.cpp index 3eb3c40cbb..44d5ecef96 100644 --- a/engines/mohawk/myst_stacks/dni.cpp +++ b/engines/mohawk/myst_stacks/dni.cpp @@ -103,14 +103,14 @@ void Dni::o_handPage(uint16 op, uint16 var, uint16 argc, uint16 *argv) { VideoHandle atrus = _vm->_video->findVideoHandle(_video); // Good ending and Atrus asked to give page - if (_globals.ending == 1 && _vm->_video->getTime(atrus) > (uint)Audio::Timestamp(0, 6801, 600).msecs()) { + if (_globals.ending == 1 && atrus && atrus->getTime() > (uint)Audio::Timestamp(0, 6801, 600).msecs()) { _globals.ending = 2; _globals.heldPage = 0; _vm->setMainCursor(kDefaultMystCursor); // Play movie end (atrus leaving) - _vm->_video->setVideoBounds(atrus, Audio::Timestamp(0, 14813, 600), _vm->_video->getDuration(atrus)); - _vm->_video->setVideoLooping(atrus, false); + atrus->setBounds(Audio::Timestamp(0, 14813, 600), atrus->getDuration()); + atrus->setLooping(false); _atrusLeft = true; _waitForLoop = false; @@ -122,7 +122,7 @@ void Dni::atrusLeft_run() { if (_vm->_system->getMillis() > _atrusLeftTime + 63333) { _video = _vm->wrapMovieFilename("atrus2", kDniStack); VideoHandle atrus = _vm->_video->playMovie(_video, 215, 77); - _vm->_video->setVideoBounds(atrus, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 98000, 600)); + atrus->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 98000, 600)); _waitForLoop = true; _loopStart = 73095; @@ -140,8 +140,8 @@ void Dni::atrusLeft_run() { void Dni::loopVideo_run() { if (!_vm->_video->isVideoPlaying()) { VideoHandle atrus = _vm->_video->playMovie(_video, 215, 77); - _vm->_video->setVideoBounds(atrus, Audio::Timestamp(0, _loopStart, 600), Audio::Timestamp(0, _loopEnd, 600)); - _vm->_video->setVideoLooping(atrus, true); + atrus->setBounds(Audio::Timestamp(0, _loopStart, 600), Audio::Timestamp(0, _loopEnd, 600)); + atrus->setLooping(true); _waitForLoop = false; } @@ -156,13 +156,13 @@ void Dni::atrus_run() { if (!_vm->_video->isVideoPlaying()) { _video = _vm->wrapMovieFilename("atr1page", kDniStack); VideoHandle atrus = _vm->_video->playMovie(_video, 215, 77, true); - _vm->_video->setVideoBounds(atrus, Audio::Timestamp(0, 7388, 600), Audio::Timestamp(0, 14700, 600)); + atrus->setBounds(Audio::Timestamp(0, 7388, 600), Audio::Timestamp(0, 14700, 600)); } } else if (_globals.ending != 3 && _globals.ending != 4) { if (_globals.heldPage == 13) { _video = _vm->wrapMovieFilename("atr1page", kDniStack); VideoHandle atrus = _vm->_video->playMovie(_video, 215, 77); - _vm->_video->setVideoBounds(atrus, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 14700, 600)); + atrus->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 14700, 600)); _waitForLoop = true; _loopStart = 7388; @@ -174,7 +174,7 @@ void Dni::atrus_run() { } else { _video = _vm->wrapMovieFilename("atr1nopg", kDniStack); VideoHandle atrus = _vm->_video->playMovie(_video, 215, 77); - _vm->_video->setVideoBounds(atrus, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 46175, 600)); + atrus->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 46175, 600)); _waitForLoop = true; _loopStart = 30656; diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp index b5d1285435..5a180bd5b0 100644 --- a/engines/mohawk/myst_stacks/mechanical.cpp +++ b/engines/mohawk/myst_stacks/mechanical.cpp @@ -319,9 +319,9 @@ void Mechanical::o_fortressStaircaseMovie(uint16 op, uint16 var, uint16 argc, ui VideoHandle staircase = _vm->_video->playMovie(_vm->wrapMovieFilename("hhstairs", kMechanicalStack), 174, 222); if (_state.staircaseState) { - _vm->_video->setVideoBounds(staircase, Audio::Timestamp(0, 840, 600), Audio::Timestamp(0, 1680, 600)); + staircase->setBounds(Audio::Timestamp(0, 840, 600), Audio::Timestamp(0, 1680, 600)); } else { - _vm->_video->setVideoBounds(staircase, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 840, 600)); + staircase->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 840, 600)); } _vm->_video->waitUntilMovieEnds(staircase); @@ -572,7 +572,7 @@ void Mechanical::o_elevatorWindowMovie(uint16 op, uint16 var, uint16 argc, uint1 debugC(kDebugScript, "Opcode %d Movie Time Index %d to %d", op, startTime, endTime); VideoHandle window = _vm->_video->playMovie(_vm->wrapMovieFilename("ewindow", kMechanicalStack), 253, 0); - _vm->_video->setVideoBounds(window, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600)); + window->setBounds(Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600)); _vm->_video->waitUntilMovieEnds(window); } @@ -645,7 +645,7 @@ void Mechanical::o_elevatorTopMovie(uint16 op, uint16 var, uint16 argc, uint16 * debugC(kDebugScript, "Opcode %d Movie Time Index %d to %d", op, startTime, endTime); VideoHandle window = _vm->_video->playMovie(_vm->wrapMovieFilename("hcelev", kMechanicalStack), 206, 38); - _vm->_video->setVideoBounds(window, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600)); + window->setBounds(Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600)); _vm->_video->waitUntilMovieEnds(window); } @@ -653,7 +653,7 @@ void Mechanical::o_fortressRotationSetPosition(uint16 op, uint16 var, uint16 arg debugC(kDebugScript, "Opcode %d: Set fortress position", op); VideoHandle gears = _fortressRotationGears->playMovie(); - uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(gears), 600).totalNumberOfFrames(); + uint32 moviePosition = Audio::Timestamp(gears->getTime(), 600).totalNumberOfFrames(); // Myst ME short movie workaround, explained in o_fortressRotation_init if (_fortressRotationShortMovieWorkaround) { @@ -788,9 +788,8 @@ void Mechanical::o_elevatorRotation_init(uint16 op, uint16 var, uint16 argc, uin void Mechanical::fortressRotation_run() { VideoHandle gears = _fortressRotationGears->playMovie(); - double oldRate = _vm->_video->getVideoRate(gears).toDouble(); - - uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(gears), 600).totalNumberOfFrames(); + double oldRate = gears->getRate().toDouble(); + uint32 moviePosition = Audio::Timestamp(gears->getTime(), 600).totalNumberOfFrames(); // Myst ME short movie workaround, explained in o_fortressRotation_init if (_fortressRotationShortMovieWorkaround) { @@ -837,19 +836,19 @@ void Mechanical::fortressRotation_run() { newRate = CLIP<double>(newRate, -2.5, 2.5); - _vm->_video->setVideoRate(gears, Common::Rational((int)(newRate * 1000.0), 1000)); + gears->setRate(Common::Rational((int)(newRate * 1000.0), 1000)); _gearsWereRunning = true; } else if (_gearsWereRunning) { // The fortress has stopped. Set its new position _fortressPosition = (moviePosition + 900) / 1800 % 4; - _vm->_video->setVideoRate(gears, 0); + gears->setRate(0); if (!_fortressRotationShortMovieWorkaround) { - _vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * _fortressPosition, 600)); + gears->seek(Audio::Timestamp(0, 1800 * _fortressPosition, 600)); } else { - _vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * (_fortressPosition % 2), 600)); + gears->seek(Audio::Timestamp(0, 1800 * (_fortressPosition % 2), 600)); } _vm->_sound->playSoundBlocking(_fortressRotationSounds[_fortressPosition]); @@ -864,9 +863,9 @@ void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uin _fortressRotationGears = static_cast<MystResourceType6 *>(_invokingResource); VideoHandle gears = _fortressRotationGears->playMovie(); - _vm->_video->setVideoLooping(gears, true); - _vm->_video->seekToTime(gears, Audio::Timestamp(0, 1800 * _fortressPosition, 600)); - _vm->_video->setVideoRate(gears, 0); + gears->setLooping(true); + gears->seek(Audio::Timestamp(0, 1800 * _fortressPosition, 600)); + gears->setRate(0); _fortressRotationSounds[0] = argv[0]; _fortressRotationSounds[1] = argv[1]; @@ -884,7 +883,7 @@ void Mechanical::o_fortressRotation_init(uint16 op, uint16 var, uint16 argc, uin // ScummVM simulates a longer movie by counting the number of times the movie // looped and adding that time to the current movie position. // Hence allowing the fortress position to be properly computed. - uint32 movieDuration = _vm->_video->getDuration(gears).convertToFramerate(600).totalNumberOfFrames(); + uint32 movieDuration = gears->getDuration().convertToFramerate(600).totalNumberOfFrames(); if (movieDuration == 3680) { _fortressRotationShortMovieWorkaround = true; _fortressRotationShortMovieCount = 0; @@ -924,8 +923,8 @@ void Mechanical::fortressSimulation_run() { _fortressSimulationStartup->pauseMovie(true); VideoHandle holo = _fortressSimulationHolo->playMovie(); - _vm->_video->setVideoLooping(holo, true); - _vm->_video->setVideoRate(holo, 0); + holo->setLooping(true); + holo->setRate(0); _vm->_cursor->showCursor(); @@ -933,9 +932,8 @@ void Mechanical::fortressSimulation_run() { } else { VideoHandle holo = _fortressSimulationHolo->playMovie(); - double oldRate = _vm->_video->getVideoRate(holo).toDouble(); - - uint32 moviePosition = Audio::Timestamp(_vm->_video->getTime(holo), 600).totalNumberOfFrames(); + double oldRate = holo->getRate().toDouble(); + uint32 moviePosition = Audio::Timestamp(holo->getTime(), 600).totalNumberOfFrames(); int32 positionInQuarter = 900 - (moviePosition + 900) % 1800; @@ -968,15 +966,15 @@ void Mechanical::fortressSimulation_run() { newRate = CLIP<double>(newRate, -2.5, 2.5); - _vm->_video->setVideoRate(holo, Common::Rational((int)(newRate * 1000.0), 1000)); + holo->setRate(Common::Rational((int)(newRate * 1000.0), 1000)); _gearsWereRunning = true; } else if (_gearsWereRunning) { // The fortress has stopped. Set its new position uint16 simulationPosition = (moviePosition + 900) / 1800 % 4; - _vm->_video->setVideoRate(holo, 0); - _vm->_video->seekToTime(holo, Audio::Timestamp(0, 1800 * simulationPosition, 600)); + holo->setRate(0); + holo->seek(Audio::Timestamp(0, 1800 * simulationPosition, 600)); _vm->_sound->playSoundBlocking( _fortressRotationSounds[simulationPosition]); _gearsWereRunning = false; diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp index ca6e7c0ee5..d674f37703 100644 --- a/engines/mohawk/myst_stacks/myst.cpp +++ b/engines/mohawk/myst_stacks/myst.cpp @@ -51,8 +51,6 @@ Myst::Myst(MohawkEngine_Myst *vm) : _dockVaultState = 0; _cabinDoorOpened = 0; _cabinMatchState = 2; - _cabinGaugeMovie = NULL_VID_HANDLE; - _cabinFireMovie = NULL_VID_HANDLE; _matchBurning = false; _tree = 0; _treeAlcove = 0; @@ -1136,7 +1134,7 @@ void Myst::o_clockWheelsExecute(uint16 op, uint16 var, uint16 argc, uint16 *argv // Gears rise up VideoHandle gears = _vm->_video->playMovie(_vm->wrapMovieFilename("gears", kMystStack), 305, 33); - _vm->_video->setVideoBounds(gears, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 650, 600)); + gears->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 650, 600)); _vm->_video->waitUntilMovieEnds(gears); @@ -1148,7 +1146,7 @@ void Myst::o_clockWheelsExecute(uint16 op, uint16 var, uint16 argc, uint16 *argv // Gears sink down VideoHandle gears = _vm->_video->playMovie(_vm->wrapMovieFilename("gears", kMystStack), 305, 33); - _vm->_video->setVideoBounds(gears, Audio::Timestamp(0, 700, 600), Audio::Timestamp(0, 1300, 600)); + gears->setBounds(Audio::Timestamp(0, 700, 600), Audio::Timestamp(0, 1300, 600)); _vm->_video->waitUntilMovieEnds(gears); _state.clockTowerBridgeOpen = 0; @@ -1192,14 +1190,14 @@ void Myst::o_imagerPlayButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) // Mountains disappearing Common::String file = _vm->wrapMovieFilename("vltmntn", kMystStack); VideoHandle mountain = _vm->_video->playMovie(file, 159, 96, false); - _vm->_video->setVideoBounds(mountain, Audio::Timestamp(0, 11180, 600), Audio::Timestamp(0, 16800, 600)); + mountain->setBounds(Audio::Timestamp(0, 11180, 600), Audio::Timestamp(0, 16800, 600)); _state.imagerActive = 0; } else { // Mountains appearing Common::String file = _vm->wrapMovieFilename("vltmntn", kMystStack); VideoHandle mountain = _vm->_video->playMovie(file, 159, 96, false); - _vm->_video->setVideoBounds(mountain, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 11180, 600)); + mountain->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 11180, 600)); _state.imagerActive = 1; } @@ -1212,20 +1210,20 @@ void Myst::o_imagerPlayButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) // Water disappearing VideoHandle water = _imagerMovie->playMovie(); - _vm->_video->setVideoBounds(water, Audio::Timestamp(0, 4204, 600), Audio::Timestamp(0, 6040, 600)); - _vm->_video->setVideoLooping(water, false); + water->setBounds(Audio::Timestamp(0, 4204, 600), Audio::Timestamp(0, 6040, 600)); + water->setLooping(false); _state.imagerActive = 0; } else { // Water appearing VideoHandle water = _imagerMovie->playMovie(); - _vm->_video->setVideoBounds(water, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 1814, 600)); + water->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 1814, 600)); _vm->_video->waitUntilMovieEnds(water); // Water looping water = _imagerMovie->playMovie(); - _vm->_video->setVideoBounds(water, Audio::Timestamp(0, 1814, 600), Audio::Timestamp(0, 4204, 600)); - _vm->_video->setVideoLooping(water, true); + water->setBounds(Audio::Timestamp(0, 1814, 600), Audio::Timestamp(0, 4204, 600)); + water->setLooping(true); _state.imagerActive = 1; } @@ -1902,7 +1900,7 @@ Common::Rational Myst::boilerComputeGaugeRate(uint16 pressure, uint32 delay) { } void Myst::boilerResetGauge(const Common::Rational &rate) { - if (_vm->_video->endOfVideo(_cabinGaugeMovie)) { + if (!_cabinGaugeMovie || _cabinGaugeMovie->endOfVideo()) { if (_vm->getCurCard() == 4098) { _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 96); } else { @@ -1914,10 +1912,10 @@ void Myst::boilerResetGauge(const Common::Rational &rate) { if (rate > 0) goTo = Audio::Timestamp(0, 0, 600); else - goTo = _vm->_video->getDuration(_cabinGaugeMovie); + goTo = _cabinGaugeMovie->getDuration(); - _vm->_video->seekToTime(_cabinGaugeMovie, goTo); - _vm->_video->setVideoRate(_cabinGaugeMovie, rate); + _cabinGaugeMovie->seek(goTo); + _cabinGaugeMovie->setRate(rate); } void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -1931,10 +1929,10 @@ void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) { + if (_cabinGaugeMovie && !_cabinGaugeMovie->endOfVideo()) { uint16 delay = treeNextMoveDelay(_state.cabinValvePosition); Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); - _vm->_video->setVideoRate(_cabinGaugeMovie, rate); + _cabinGaugeMovie->setRate(rate); } } else if (_state.cabinValvePosition > 0) @@ -2006,10 +2004,10 @@ void Myst::o_boilerDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) { + if (_cabinGaugeMovie && !_cabinGaugeMovie->endOfVideo()) { uint16 delay = treeNextMoveDelay(_state.cabinValvePosition); Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); - _vm->_video->setVideoRate(_cabinGaugeMovie, rate); + _cabinGaugeMovie->setRate(rate); } } else { @@ -2117,7 +2115,7 @@ void Myst::tree_run() { // Check if alcove is accessible treeSetAlcoveAccessible(); - if (_cabinGaugeMovie != NULL_VID_HANDLE) { + if (_cabinGaugeMovie) { Common::Rational rate = boilerComputeGaugeRate(pressure, delay); boilerResetGauge(rate); } @@ -2247,12 +2245,12 @@ void Myst::rocketCheckSolution() { // Book appearing Common::String movieFile = _vm->wrapMovieFilename("selenbok", kMystStack); _rocketLinkBook = _vm->_video->playMovie(movieFile, 224, 41); - _vm->_video->setVideoBounds(_rocketLinkBook, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 660, 600)); + _rocketLinkBook->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 660, 600)); _vm->_video->waitUntilMovieEnds(_rocketLinkBook); // Book looping closed _rocketLinkBook = _vm->_video->playMovie(movieFile, 224, 41, true); - _vm->_video->setVideoBounds(_rocketLinkBook, Audio::Timestamp(0, 660, 600), Audio::Timestamp(0, 3500, 600)); + _rocketLinkBook->setBounds(Audio::Timestamp(0, 660, 600), Audio::Timestamp(0, 3500, 600)); _tempVar = 1; } @@ -2367,7 +2365,7 @@ void Myst::o_rocketOpenBook(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Rocket open link book", op); // Flyby movie - _vm->_video->setVideoBounds(_rocketLinkBook, Audio::Timestamp(0, 3500, 600), Audio::Timestamp(0, 13100, 600)); + _rocketLinkBook->setBounds(Audio::Timestamp(0, 3500, 600), Audio::Timestamp(0, 13100, 600)); // Set linkable _tempVar = 2; @@ -2890,7 +2888,7 @@ void Myst::clockGearForwardOneStep(uint16 gear) { // Set video bounds uint16 gearPosition = _clockGearsPositions[gear] - 1; _clockGearsVideos[gear] = _vm->_video->playMovie(_vm->wrapMovieFilename(videos[gear], kMystStack), x[gear], y[gear]); - _vm->_video->setVideoBounds(_clockGearsVideos[gear], + _clockGearsVideos[gear]->setBounds( Audio::Timestamp(0, startTime[gearPosition], 600), Audio::Timestamp(0, endTime[gearPosition], 600)); } @@ -2903,7 +2901,7 @@ void Myst::clockWeightDownOneStep() { // Set video bounds if (updateVideo) { _clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0); - _vm->_video->setVideoBounds(_clockWeightVideo, + _clockWeightVideo->setBounds( Audio::Timestamp(0, _clockWeightPosition, 600), Audio::Timestamp(0, _clockWeightPosition + 246, 600)); } @@ -2931,7 +2929,7 @@ void Myst::o_clockLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) // Let movies stop playing for (uint i = 0; i < ARRAYSIZE(videos); i++) { VideoHandle handle = _vm->_video->findVideoHandle(_vm->wrapMovieFilename(videos[i], kMystStack)); - if (handle != NULL_VID_HANDLE) + if (handle) _vm->_video->delayUntilMovieEnds(handle); } @@ -2957,7 +2955,7 @@ void Myst::clockGearsCheckSolution() { // Make weight go down _vm->_sound->replaceSoundMyst(9113); _clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0); - _vm->_video->setVideoBounds(_clockWeightVideo, + _clockWeightVideo->setBounds( Audio::Timestamp(0, _clockWeightPosition, 600), Audio::Timestamp(0, 2214, 600)); _vm->_video->waitUntilMovieEnds(_clockWeightVideo); @@ -3011,7 +3009,7 @@ void Myst::clockReset() { // Let movies stop playing for (uint i = 0; i < ARRAYSIZE(videos); i++) { VideoHandle handle = _vm->_video->findVideoHandle(_vm->wrapMovieFilename(videos[i], kMystStack)); - if (handle != NULL_VID_HANDLE) + if (handle) _vm->_video->delayUntilMovieEnds(handle); } @@ -3025,8 +3023,8 @@ void Myst::clockReset() { // Gear closing movie VideoHandle handle = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wggat", kMystStack) , 195, 225); - _vm->_video->seekToTime(handle, _vm->_video->getDuration(handle)); - _vm->_video->setVideoRate(handle, -1); + handle->seek(handle->getDuration()); + handle->setRate(-1); _vm->_video->waitUntilMovieEnds(handle); // Redraw gear @@ -3041,8 +3039,8 @@ void Myst::clockResetWeight() { _clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0); // Play the movie backwards, weight going up - _vm->_video->seekToTime(_clockWeightVideo, Audio::Timestamp(0, _clockWeightPosition, 600)); - _vm->_video->setVideoRate(_clockWeightVideo, -1); + _clockWeightVideo->seek(Audio::Timestamp(0, _clockWeightPosition, 600)); + _clockWeightVideo->setRate(-1); // Reset position _clockWeightPosition = 0; @@ -3058,7 +3056,7 @@ void Myst::clockResetGear(uint16 gear) { uint16 gearPosition = _clockGearsPositions[gear] - 1; if (gearPosition != 2) { _clockGearsVideos[gear] = _vm->_video->playMovie(_vm->wrapMovieFilename(videos[gear], kMystStack), x[gear], y[gear]); - _vm->_video->setVideoBounds(_clockGearsVideos[gear], + _clockGearsVideos[gear]->setBounds( Audio::Timestamp(0, time[gearPosition], 600), Audio::Timestamp(0, time[2], 600)); } @@ -3289,8 +3287,8 @@ void Myst::imager_run() { if (_state.imagerActive && _state.imagerSelection == 67) { VideoHandle water = _imagerMovie->playMovie(); - _vm->_video->setVideoBounds(water, Audio::Timestamp(0, 1814, 600), Audio::Timestamp(0, 4204, 600)); - _vm->_video->setVideoLooping(water, true); + water->setBounds(Audio::Timestamp(0, 1814, 600), Audio::Timestamp(0, 4204, 600)); + water->setLooping(true); } } @@ -3581,7 +3579,7 @@ void Myst::o_boilerMovies_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) void Myst::boilerFireInit() { if (_vm->getCurCard() == 4098) { _cabinFireMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279, true); - _vm->_video->pauseMovie(_cabinFireMovie, true); + _cabinFireMovie->pause(true); _vm->redrawArea(305); boilerFireUpdate(true); @@ -3593,18 +3591,18 @@ void Myst::boilerFireInit() { } void Myst::boilerFireUpdate(bool init) { - uint position = _vm->_video->getTime(_cabinFireMovie); + uint position = _cabinFireMovie->getTime(); if (_state.cabinPilotLightLit == 1) { if (_state.cabinValvePosition == 0) { if (position > (uint)Audio::Timestamp(0, 200, 600).msecs() || init) { - _vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 100, 600)); - _vm->_video->pauseMovie(_cabinFireMovie, false); + _cabinFireMovie->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 100, 600)); + _cabinFireMovie->pause(false); } } else { if (position < (uint)Audio::Timestamp(0, 200, 600).msecs() || init) { - _vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 201, 600), Audio::Timestamp(0, 1900, 600)); - _vm->_video->pauseMovie(_cabinFireMovie, false); + _cabinFireMovie->setBounds(Audio::Timestamp(0, 201, 600), Audio::Timestamp(0, 1900, 600)); + _cabinFireMovie->pause(false); } } } @@ -3620,7 +3618,7 @@ void Myst::boilerGaugeInit() { Audio::Timestamp frame; if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition > 12) - frame = _vm->_video->getDuration(_cabinGaugeMovie); + frame = _cabinGaugeMovie->getDuration(); else frame = Audio::Timestamp(0, 0, 600); @@ -3685,13 +3683,13 @@ void Myst::greenBook_run() { _vm->_video->playMovie(file, 314, 76); } else { VideoHandle book = _vm->_video->playMovie(file, 314, 76, true); - _vm->_video->setVideoBounds(book, Audio::Timestamp(0, loopStart, 600), Audio::Timestamp(0, loopEnd, 600)); + book->setBounds(Audio::Timestamp(0, loopStart, 600), Audio::Timestamp(0, loopEnd, 600)); _tempVar = 0; } } else if (_tempVar == 2 && !_vm->_video->isVideoPlaying()) { VideoHandle book = _vm->_video->playMovie(file, 314, 76); - _vm->_video->setVideoBounds(book, Audio::Timestamp(0, loopStart, 600), Audio::Timestamp(0, loopEnd, 600)); - _vm->_video->setVideoLooping(book, true); + book->setBounds(Audio::Timestamp(0, loopStart, 600), Audio::Timestamp(0, loopEnd, 600)); + book->setLooping(true); _tempVar = 0; } } @@ -3750,8 +3748,8 @@ void Myst::o_treeEntry_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { void Myst::o_boiler_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Exit boiler card", op); - _cabinGaugeMovie = NULL_VID_HANDLE; - _cabinFireMovie = NULL_VID_HANDLE; + _cabinGaugeMovie = VideoHandle(); + _cabinFireMovie = VideoHandle(); } void Myst::o_generatorControlRoom_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp index d8dbeef641..fe9fdbab42 100644 --- a/engines/mohawk/myst_stacks/stoneship.cpp +++ b/engines/mohawk/myst_stacks/stoneship.cpp @@ -426,7 +426,7 @@ void Stoneship::o_cabinBookMovie(uint16 op, uint16 var, uint16 argc, uint16 *arg uint16 endTime = argv[1]; VideoHandle book = _vm->_video->playMovie(_vm->wrapMovieFilename("bkroom", kStoneshipStack), 159, 99); - _vm->_video->setVideoBounds(book, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600)); + book->setBounds(Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, endTime, 600)); _vm->_video->waitUntilMovieEnds(book); } @@ -597,9 +597,9 @@ void Stoneship::o_hologramPlayback(uint16 op, uint16 var, uint16 argc, uint16 *a if (_hologramTurnedOn) { if (_hologramDisplayPos) endPoint = _hologramDisplayPos; - _vm->_video->setVideoBounds(displayMovie, Audio::Timestamp(0, startPoint, 600), Audio::Timestamp(0, endPoint, 600)); + displayMovie->setBounds(Audio::Timestamp(0, startPoint, 600), Audio::Timestamp(0, endPoint, 600)); } else { - _vm->_video->setVideoBounds(displayMovie, Audio::Timestamp(0, startPoint, 600), Audio::Timestamp(0, endPoint, 600)); + displayMovie->setBounds(Audio::Timestamp(0, startPoint, 600), Audio::Timestamp(0, endPoint, 600)); } _vm->_video->delayUntilMovieEnds(displayMovie); @@ -674,19 +674,19 @@ void Stoneship::o_chestValveVideos(uint16 op, uint16 var, uint16 argc, uint16 *a if (_state.chestValveState) { // Valve closing VideoHandle valve = _vm->_video->playMovie(movie, 97, 267); - _vm->_video->setVideoBounds(valve, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 350, 600)); + valve->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 350, 600)); _vm->_video->waitUntilMovieEnds(valve); } else if (_state.chestWaterState) { // Valve opening, spilling water VideoHandle valve = _vm->_video->playMovie(movie, 97, 267); - _vm->_video->setVideoBounds(valve, Audio::Timestamp(0, 350, 600), Audio::Timestamp(0, 650, 600)); + valve->setBounds(Audio::Timestamp(0, 350, 600), Audio::Timestamp(0, 650, 600)); _vm->_video->waitUntilMovieEnds(valve); _vm->_sound->playSound(3132); for (uint i = 0; i < 25; i++) { valve = _vm->_video->playMovie(movie, 97, 267); - _vm->_video->setVideoBounds(valve, Audio::Timestamp(0, 650, 600), Audio::Timestamp(0, 750, 600)); + valve->setBounds(Audio::Timestamp(0, 650, 600), Audio::Timestamp(0, 750, 600)); _vm->_video->waitUntilMovieEnds(valve); } @@ -694,8 +694,8 @@ void Stoneship::o_chestValveVideos(uint16 op, uint16 var, uint16 argc, uint16 *a } else { // Valve opening VideoHandle valve = _vm->_video->playMovie(movie, 97, 267); - _vm->_video->seekToTime(valve, Audio::Timestamp(0, 350, 600)); - _vm->_video->setVideoRate(valve, -1); + valve->seek(Audio::Timestamp(0, 350, 600)); + valve->setRate(-1); _vm->_video->waitUntilMovieEnds(valve); } } @@ -717,13 +717,13 @@ void Stoneship::o_trapLockOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) Common::String movie = _vm->wrapMovieFilename("openloc", kStoneshipStack); VideoHandle lock = _vm->_video->playMovie(movie, 187, 71); - _vm->_video->setVideoBounds(lock, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 750, 600)); + lock->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 750, 600)); _vm->_video->waitUntilMovieEnds(lock); _vm->_sound->playSound(2143); lock = _vm->_video->playMovie(movie, 187, 71); - _vm->_video->setVideoBounds(lock, Audio::Timestamp(0, 750, 600), Audio::Timestamp(0, 10000, 600)); + lock->setBounds(Audio::Timestamp(0, 750, 600), Audio::Timestamp(0, 10000, 600)); _vm->_video->waitUntilMovieEnds(lock); if (_state.pumpState != 4) diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index a7fe12b9e1..898f68c581 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -828,7 +828,7 @@ static void sunnersTopStairsTimer(MohawkEngine_Riven *vm) { VideoHandle oldHandle = vm->_video->findVideoHandleRiven(1); uint32 timerTime = 500; - if (oldHandle == NULL_VID_HANDLE || vm->_video->endOfVideo(oldHandle)) { + if (!oldHandle || oldHandle->endOfVideo()) { uint32 &sunnerTime = vm->_vars["jsunnertime"]; if (sunnerTime == 0) { @@ -836,7 +836,7 @@ static void sunnersTopStairsTimer(MohawkEngine_Riven *vm) { } else if (sunnerTime < vm->getTotalPlayTime()) { VideoHandle handle = vm->_video->playMovieRiven(vm->_rnd->getRandomNumberRng(1, 3)); - timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(2, 15) * 1000; + timerTime = handle->getDuration().msecs() + vm->_rnd->getRandomNumberRng(2, 15) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -858,7 +858,7 @@ static void sunnersMidStairsTimer(MohawkEngine_Riven *vm) { VideoHandle oldHandle = vm->_video->findVideoHandleRiven(1); uint32 timerTime = 500; - if (oldHandle == NULL_VID_HANDLE || vm->_video->endOfVideo(oldHandle)) { + if (!oldHandle || oldHandle->endOfVideo()) { uint32 &sunnerTime = vm->_vars["jsunnertime"]; if (sunnerTime == 0) { @@ -874,7 +874,7 @@ static void sunnersMidStairsTimer(MohawkEngine_Riven *vm) { VideoHandle handle = vm->_video->playMovieRiven(movie); - timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(1, 10) * 1000; + timerTime = handle->getDuration().msecs() + vm->_rnd->getRandomNumberRng(1, 10) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -896,7 +896,7 @@ static void sunnersLowerStairsTimer(MohawkEngine_Riven *vm) { VideoHandle oldHandle = vm->_video->findVideoHandleRiven(1); uint32 timerTime = 500; - if (oldHandle == NULL_VID_HANDLE || vm->_video->endOfVideo(oldHandle)) { + if (!oldHandle || oldHandle->endOfVideo()) { uint32 &sunnerTime = vm->_vars["jsunnertime"]; if (sunnerTime == 0) { @@ -904,7 +904,7 @@ static void sunnersLowerStairsTimer(MohawkEngine_Riven *vm) { } else if (sunnerTime < vm->getTotalPlayTime()) { VideoHandle handle = vm->_video->playMovieRiven(vm->_rnd->getRandomNumberRng(3, 5)); - timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(1, 30) * 1000; + timerTime = handle->getDuration().msecs() + vm->_rnd->getRandomNumberRng(1, 30) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -926,7 +926,7 @@ static void sunnersBeachTimer(MohawkEngine_Riven *vm) { VideoHandle oldHandle = vm->_video->findVideoHandleRiven(3); uint32 timerTime = 500; - if (oldHandle == NULL_VID_HANDLE || vm->_video->endOfVideo(oldHandle)) { + if (!oldHandle || oldHandle->endOfVideo()) { uint32 &sunnerTime = vm->_vars["jsunnertime"]; if (sunnerTime == 0) { @@ -938,7 +938,7 @@ static void sunnersBeachTimer(MohawkEngine_Riven *vm) { vm->_video->activateMLST(mlstID, vm->getCurCard()); VideoHandle handle = vm->_video->playMovieRiven(mlstID); - timerTime = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(1, 30) * 1000; + timerTime = handle->getDuration().msecs() + vm->_rnd->getRandomNumberRng(1, 30) * 1000; } sunnerTime = timerTime + vm->getTotalPlayTime(); @@ -969,7 +969,7 @@ void MohawkEngine_Riven::installCardTimer() { } void MohawkEngine_Riven::doVideoTimer(VideoHandle handle, bool force) { - assert(handle != NULL_VID_HANDLE); + assert(handle); uint16 id = _scriptMan->getStoredMovieOpcodeID(); @@ -977,7 +977,7 @@ void MohawkEngine_Riven::doVideoTimer(VideoHandle handle, bool force) { return; // Run the opcode if we can at this point - if (force || _video->getTime(handle) >= _scriptMan->getStoredMovieOpcodeTime()) + if (force || handle->getTime() >= _scriptMan->getStoredMovieOpcodeTime()) _scriptMan->runStoredMovieOpcode(); } @@ -1003,7 +1003,7 @@ void MohawkEngine_Riven::checkSunnerAlertClick() { // If the alert video is no longer playing, we have nothing left to do VideoHandle handle = _video->findVideoHandleRiven(1); - if (handle == NULL_VID_HANDLE || _video->endOfVideo(handle)) + if (!handle || handle->endOfVideo()) return; sunners = 1; diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index cda0683028..c859248055 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -229,7 +229,7 @@ void RivenExternal::runCredits(uint16 video, uint32 delay) { VideoHandle videoHandle = _vm->_video->findVideoHandleRiven(video); while (!_vm->shouldQuit() && _vm->_gfx->getCurCreditsImage() <= 320) { - if (_vm->_video->getCurFrame(videoHandle) >= (int32)_vm->_video->getFrameCount(videoHandle) - 1) { + if (videoHandle->getCurFrame() >= (int32)videoHandle->getFrameCount() - 1) { if (nextCreditsFrameStart == 0) { // Set us up to start after delay ms nextCreditsFrameStart = _vm->_system->getMillis() + delay; @@ -265,10 +265,10 @@ void RivenExternal::runDomeCheck() { // Check if we clicked while the golden frame was showing VideoHandle video = _vm->_video->findVideoHandleRiven(1); - assert(video != NULL_VID_HANDLE); + assert(video); - int32 curFrame = _vm->_video->getCurFrame(video); - int32 frameCount = _vm->_video->getFrameCount(video); + int32 curFrame = video->getCurFrame(); + int32 frameCount = video->getFrameCount(); // The final frame of the video is the 'golden' frame (double meaning: the // frame that is the magic one is the one with the golden symbol) but we @@ -857,8 +857,12 @@ void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) { _vm->_video->playMovieRiven(7); } } else { - _vm->_video->disableMovieRiven(7); - _vm->_video->disableMovieRiven(8); + VideoHandle handle = _vm->_video->findVideoHandleRiven(7); + if (handle) + handle->setEnabled(false); + handle = _vm->_video->findVideoHandleRiven(8); + if (handle) + handle->setEnabled(false); } } @@ -1149,8 +1153,8 @@ void RivenExternal::lowerPins() { // Play the video of the pins going down VideoHandle handle = _vm->_video->playMovieRiven(upMovie); - assert(handle != NULL_VID_HANDLE); - _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 550, 600)); + assert(handle); + handle->setBounds(Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 550, 600)); _vm->_video->waitUntilMovieEnds(handle); upMovie = 0; @@ -1181,8 +1185,8 @@ void RivenExternal::xgrotatepins(uint16 argc, uint16 *argv) { // Play the video of the pins rotating VideoHandle handle = _vm->_video->playMovieRiven(_vm->_vars["gupmoov"]); - assert(handle != NULL_VID_HANDLE); - _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 1215, 600)); + assert(handle); + handle->setBounds(Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 1215, 600)); _vm->_video->waitUntilMovieEnds(handle); } @@ -1265,9 +1269,9 @@ void RivenExternal::xgpincontrols(uint16 argc, uint16 *argv) { // Actually play the movie VideoHandle handle = _vm->_video->playMovieRiven(pinMovieCodes[imagePos - 1]); - assert(handle != NULL_VID_HANDLE); + assert(handle); uint32 startTime = 9630 - pinPos * 600; - _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 550, 600)); + handle->setBounds(Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 550, 600)); _vm->_video->waitUntilMovieEnds(handle); // Update the relevant variables @@ -1343,8 +1347,8 @@ void RivenExternal::xgrviewer(uint16 argc, uint16 *argv) { // Now play the movie VideoHandle handle = _vm->_video->playMovieRiven(1); - assert(handle != NULL_VID_HANDLE); - _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600)); + assert(handle); + handle->setBounds(Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600)); _vm->_video->waitUntilMovieEnds(handle); // Set the new position and let the card's scripts take over again @@ -1412,8 +1416,8 @@ void RivenExternal::xglviewer(uint16 argc, uint16 *argv) { // Now play the movie VideoHandle handle = _vm->_video->playMovieRiven(1); - assert(handle != NULL_VID_HANDLE); - _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600)); + assert(handle); + handle->setBounds(Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600)); _vm->_video->waitUntilMovieEnds(handle); // Set the new position to the variable @@ -1467,7 +1471,7 @@ static void catherineViewerIdleTimer(MohawkEngine_Riven *vm) { VideoHandle videoHandle = vm->_video->playMovieRiven(30); // Reset the timer - vm->installTimer(&catherineViewerIdleTimer, vm->_video->getDuration(videoHandle).msecs() + vm->_rnd->getRandomNumber(60) * 1000); + vm->installTimer(&catherineViewerIdleTimer, videoHandle->getDuration().msecs() + vm->_rnd->getRandomNumber(60) * 1000); } void RivenExternal::xglview_prisonon(uint16 argc, uint16 *argv) { @@ -1507,7 +1511,7 @@ void RivenExternal::xglview_prisonon(uint16 argc, uint16 *argv) { _vm->_video->activateMLST(cathMovie, _vm->getCurCard()); VideoHandle videoHandle = _vm->_video->playMovieRiven(30); - timeUntilNextMovie = _vm->_video->getDuration(videoHandle).msecs() + _vm->_rnd->getRandomNumber(60) * 1000; + timeUntilNextMovie = videoHandle->getDuration().msecs() + _vm->_rnd->getRandomNumber(60) * 1000; } else { // Otherwise, just redraw the imager timeUntilNextMovie = _vm->_rnd->getRandomNumberRng(10, 20) * 1000; @@ -1986,7 +1990,7 @@ void RivenExternal::xschool280_playwhark(uint16 argc, uint16 *argv) { Audio::Timestamp startTime = Audio::Timestamp(0, (11560 / 19) * (*posVar), 600); *posVar += number; // Adjust to the end Audio::Timestamp endTime = Audio::Timestamp(0, (11560 / 19) * (*posVar), 600); - _vm->_video->setVideoBounds(handle, startTime, endTime); + handle->setBounds(startTime, endTime); _vm->_video->waitUntilMovieEnds(handle); if (*posVar > 19) { @@ -2059,7 +2063,7 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) { debug(0, "\tHotspot = %d -> %d", argv[3], hotspotMap[argv[3] - 1]); // Just let the video play while we wait until Gehn opens the trap book for us - while (_vm->_video->getTime(video) < startTime && !_vm->shouldQuit()) { + while (video->getTime() < startTime && !_vm->shouldQuit()) { if (_vm->_video->updateMovies()) _vm->_system->updateScreen(); @@ -2084,7 +2088,7 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) { // OK, Gehn has opened the trap book and has asked us to go in. Let's watch // and see what the player will do... - while (_vm->_video->getTime(video) < endTime && !_vm->shouldQuit()) { + while (video->getTime() < endTime && !_vm->shouldQuit()) { bool updateScreen = _vm->_video->updateMovies(); Common::Event event; @@ -2335,7 +2339,7 @@ static void rebelPrisonWindowTimer(MohawkEngine_Riven *vm) { VideoHandle handle = vm->_video->playMovieRiven(movie); // Ensure the next video starts after this one ends - uint32 timeUntilNextVideo = vm->_video->getDuration(handle).msecs() + vm->_rnd->getRandomNumberRng(38, 58) * 1000; + uint32 timeUntilNextVideo = handle->getDuration().msecs() + vm->_rnd->getRandomNumberRng(38, 58) * 1000; // Save the time in case we leave the card and return vm->_vars["rvillagetime"] = timeUntilNextVideo + vm->getTotalPlayTime(); @@ -2434,7 +2438,7 @@ void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) { static const uint32 timeIntervals[] = { 4320, 3440, 2560, 1760, 880, 0 }; uint16 movieCode = telescopeCover ? 1 : 2; VideoHandle handle = _vm->_video->playMovieRiven(movieCode); - _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[telescopePos], 600), Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600)); + handle->setBounds(Audio::Timestamp(0, timeIntervals[telescopePos], 600), Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600)); _vm->_sound->playSound(14); // Play the moving sound _vm->_video->waitUntilMovieEnds(handle); @@ -2467,7 +2471,7 @@ void RivenExternal::xtexterior300_telescopeup(uint16 argc, uint16 *argv) { static const uint32 timeIntervals[] = { 0, 800, 1680, 2560, 3440, 4320 }; uint16 movieCode = _vm->_vars["ttelecover"] ? 4 : 5; VideoHandle handle = _vm->_video->playMovieRiven(movieCode); - _vm->_video->setVideoBounds(handle, Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600), Audio::Timestamp(0, timeIntervals[telescopePos], 600)); + handle->setBounds(Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600), Audio::Timestamp(0, timeIntervals[telescopePos], 600)); _vm->_sound->playSound(14); // Play the moving sound _vm->_video->waitUntilMovieEnds(handle); diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index 29ee5cd50b..caa235ec8b 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -493,7 +493,9 @@ void RivenScript::changeStack(uint16 op, uint16 argc, uint16 *argv) { // Command 28: disable a movie void RivenScript::disableMovie(uint16 op, uint16 argc, uint16 *argv) { - _vm->_video->disableMovieRiven(argv[0]); + VideoHandle handle = _vm->_video->findVideoHandleRiven(argv[0]); + if (handle) + handle->setEnabled(false); } // Command 29: disable all movies @@ -503,7 +505,9 @@ void RivenScript::disableAllMovies(uint16 op, uint16 argc, uint16 *argv) { // Command 31: enable a movie void RivenScript::enableMovie(uint16 op, uint16 argc, uint16 *argv) { - _vm->_video->enableMovieRiven(argv[0]); + VideoHandle handle = _vm->_video->findVideoHandleRiven(argv[0]); + if (handle) + handle->setEnabled(true); } // Command 32: play foreground movie - blocking (movie_id) diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp index 3f27e4a1a4..577f8a1a27 100644 --- a/engines/mohawk/video.cpp +++ b/engines/mohawk/video.cpp @@ -24,6 +24,7 @@ #include "mohawk/resource.h" #include "mohawk/video.h" +#include "common/algorithm.h" #include "common/debug.h" #include "common/events.h" #include "common/textconsole.h" @@ -37,19 +38,79 @@ namespace Mohawk { -void VideoEntry::clear() { - video = 0; - x = 0; - y = 0; - loop = false; - enabled = false; - start = Audio::Timestamp(0, 1); - filename.clear(); - id = -1; +VideoEntry::VideoEntry() : _video(0), _id(-1), _x(0), _y(0), _loop(false), _enabled(true) { } -bool VideoEntry::endOfVideo() { - return !video || video->endOfVideo(); +VideoEntry::VideoEntry(Video::VideoDecoder *video, const Common::String &fileName) : _video(video), _fileName(fileName), _id(-1), _x(0), _y(0), _loop(false), _enabled(true) { +} + +VideoEntry::VideoEntry(Video::VideoDecoder *video, int id) : _video(video), _id(id), _x(0), _y(0), _loop(false), _enabled(true) { +} + +VideoEntry::~VideoEntry() { + close(); +} + +void VideoEntry::close() { + delete _video; + _video = 0; +} + +bool VideoEntry::endOfVideo() const { + return !isOpen() || _video->endOfVideo(); +} + +int VideoEntry::getCurFrame() const { + assert(_video); + return _video->getCurFrame(); +} + +uint32 VideoEntry::getFrameCount() const { + assert(_video); + return _video->getFrameCount(); +} + +uint32 VideoEntry::getTime() const { + assert(_video); + return _video->getTime(); +} + +Audio::Timestamp VideoEntry::getDuration() const { + assert(_video); + return _video->getDuration(); +} + +Common::Rational VideoEntry::getRate() const { + assert(_video); + return _video->getRate(); +} + +void VideoEntry::setBounds(const Audio::Timestamp &start, const Audio::Timestamp &end) { + assert(_video); + _start = start; + _video->setEndTime(end); + _video->seek(start); +} + +void VideoEntry::seek(const Audio::Timestamp &time) { + assert(_video); + _video->seek(time); +} + +void VideoEntry::setRate(const Common::Rational &rate) { + assert(_video); + _video->setRate(rate); +} + +void VideoEntry::pause(bool isPaused) { + assert(_video); + _video->pauseVideo(isPaused); +} + +VideoHandle::VideoHandle(VideoEntryPtr ptr) : _ptr(ptr) { +} + +VideoHandle::VideoHandle(const VideoHandle &handle) : _ptr(handle._ptr) { } VideoManager::VideoManager(MohawkEngine* vm) : _vm(vm) { @@ -62,41 +123,42 @@ VideoManager::~VideoManager() { } void VideoManager::pauseVideos() { - for (uint16 i = 0; i < _videoStreams.size(); i++) - if (_videoStreams[i].video) - _videoStreams[i]->pauseVideo(true); + for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++) + (*it)->pause(true); } void VideoManager::resumeVideos() { - for (uint16 i = 0; i < _videoStreams.size(); i++) - if (_videoStreams[i].video) - _videoStreams[i]->pauseVideo(false); + for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++) + (*it)->pause(false); } void VideoManager::stopVideos() { - for (uint16 i = 0; i < _videoStreams.size(); i++) - delete _videoStreams[i].video; + for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++) + (*it)->close(); - _videoStreams.clear(); + _videos.clear(); } -void VideoManager::playMovieBlocking(const Common::String &filename, uint16 x, uint16 y, bool clearScreen) { - VideoHandle videoHandle = createVideoHandle(filename, x, y, false); - if (videoHandle == NULL_VID_HANDLE) +void VideoManager::playMovieBlocking(const Common::String &fileName, uint16 x, uint16 y, bool clearScreen) { + VideoEntryPtr ptr = open(fileName); + if (!ptr) return; + ptr->setX(x); + ptr->setY(y); + // Clear screen if requested if (clearScreen) { _vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0)); _vm->_system->updateScreen(); } - waitUntilMovieEnds(videoHandle); + waitUntilMovieEnds(ptr); } -void VideoManager::playMovieBlockingCentered(const Common::String &filename, bool clearScreen) { - VideoHandle videoHandle = createVideoHandle(filename, 0, 0, false); - if (videoHandle == NULL_VID_HANDLE) +void VideoManager::playMovieBlockingCentered(const Common::String &fileName, bool clearScreen) { + VideoEntryPtr ptr = open(fileName); + if (!ptr) return; // Clear screen if requested @@ -105,19 +167,23 @@ void VideoManager::playMovieBlockingCentered(const Common::String &filename, boo _vm->_system->updateScreen(); } - _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2; - _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2; + ptr->setX((_vm->_system->getWidth() - ptr->_video->getWidth()) / 2); + ptr->setY((_vm->_system->getHeight() - ptr->_video->getHeight()) / 2); - waitUntilMovieEnds(videoHandle); + waitUntilMovieEnds(ptr); } void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) { - if (videoHandle == NULL_VID_HANDLE) + if (!videoHandle) return; + // Sanity check + if (videoHandle._ptr->isLooping()) + error("Called waitUntilMovieEnds() on a looping video"); + bool continuePlaying = true; - while (!_videoStreams[videoHandle].endOfVideo() && !_vm->shouldQuit() && continuePlaying) { + while (!videoHandle->endOfVideo() && !_vm->shouldQuit() && continuePlaying) { if (updateMovies()) _vm->_system->updateScreen(); @@ -149,12 +215,22 @@ void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) { _vm->_system->delayMillis(10); } - delete _videoStreams[videoHandle].video; - _videoStreams[videoHandle].clear(); + // Ensure it's removed + removeEntry(videoHandle._ptr); } void VideoManager::delayUntilMovieEnds(VideoHandle videoHandle) { - while (!_videoStreams[videoHandle].endOfVideo() && !_vm->shouldQuit()) { + // FIXME: Why is this separate from waitUntilMovieEnds? + // It seems to only cut out the event loop (which is bad). + + if (!videoHandle) + return; + + // Sanity check + if (videoHandle._ptr->isLooping()) + error("Called delayUntilMovieEnds() on a looping video"); + + while (!videoHandle->endOfVideo() && !_vm->shouldQuit()) { if (updateMovies()) _vm->_system->updateScreen(); @@ -162,73 +238,89 @@ void VideoManager::delayUntilMovieEnds(VideoHandle videoHandle) { _vm->_system->delayMillis(10); } - delete _videoStreams[videoHandle].video; - _videoStreams[videoHandle].clear(); + // Ensure it's removed + removeEntry(videoHandle._ptr); } -VideoHandle VideoManager::playMovie(const Common::String &filename, int16 x, int16 y, bool loop) { - VideoHandle videoHandle = createVideoHandle(filename, x, y, loop); - if (videoHandle == NULL_VID_HANDLE) - return NULL_VID_HANDLE; +VideoHandle VideoManager::playMovie(const Common::String &fileName, int16 x, int16 y, bool loop) { + VideoEntryPtr ptr = open(fileName); + if (!ptr) + return VideoHandle(); + + ptr->setLooping(loop); // Center x if requested + // FIXME: Move to a playMovieCentered() if (x < 0) - _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2; + ptr->setX((_vm->_system->getWidth() - ptr->_video->getWidth()) / 2); + else + ptr->setX(x); // Center y if requested + // FIXME: Move to a playMovieCentered() if (y < 0) - _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2; + ptr->setY((_vm->_system->getHeight() - ptr->_video->getHeight()) / 2); + else + ptr->setY(y); - return videoHandle; + return ptr; } VideoHandle VideoManager::playMovie(uint16 id, int16 x, int16 y, bool loop) { - VideoHandle videoHandle = createVideoHandle(id, x, y, loop); - if (videoHandle == NULL_VID_HANDLE) - return NULL_VID_HANDLE; + VideoEntryPtr ptr = open(id); + if (!ptr) + return VideoHandle(); + + ptr->setLooping(loop); // Center x if requested + // FIXME: Move to a playMovieCentered() if (x < 0) - _videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2; + ptr->setX((_vm->_system->getWidth() - ptr->_video->getWidth()) / 2); + else + ptr->setX(x); // Center y if requested + // FIXME: Move to a playMovieCentered() if (y < 0) - _videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->getHeight()) / 2; + ptr->setY((_vm->_system->getHeight() - ptr->_video->getHeight()) / 2); + else + ptr->setY(y); - return videoHandle; + return ptr; } bool VideoManager::updateMovies() { bool updateScreen = false; - for (uint32 i = 0; i < _videoStreams.size() && !_vm->shouldQuit(); i++) { - // Skip deleted videos - if (!_videoStreams[i].video) - continue; - - // Remove any videos that are over - if (_videoStreams[i].endOfVideo()) { - if (_videoStreams[i].loop) { - _videoStreams[i]->seek(_videoStreams[i].start); + for (VideoList::iterator it = _videos.begin(); it != _videos.end(); ) { + // Check of the video has reached the end + if ((*it)->endOfVideo()) { + if ((*it)->isLooping()) { + // Seek back if looping + (*it)->seek((*it)->getStart()); } else { - // Check the video time one last time before deleting it - _vm->doVideoTimer(i, true); - delete _videoStreams[i].video; - _videoStreams[i].clear(); + // Done; close and continue on + (*it)->close(); + it = _videos.erase(it); continue; } } - // Nothing more to do if we're paused - if (_videoStreams[i]->isPaused()) + Video::VideoDecoder *video = (*it)->_video; + + // Ignore paused videos + if (video->isPaused()) { + it++; continue; + } // Check if we need to draw a frame - if (_videoStreams[i]->needsUpdate()) { - const Graphics::Surface *frame = _videoStreams[i]->decodeNextFrame(); + if (video->needsUpdate()) { + const Graphics::Surface *frame = video->decodeNextFrame(); Graphics::Surface *convertedFrame = 0; - if (frame && _videoStreams[i].enabled) { + if (frame && (*it)->isEnabled()) { Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat(); if (frame->format != pixelFormat) { @@ -236,25 +328,25 @@ bool VideoManager::updateMovies() { // support in the codec. Set _enableDither if shows up. if (pixelFormat.bytesPerPixel == 1) { warning("Cannot convert high color video frame to 8bpp"); - delete _videoStreams[i].video; - _videoStreams[i].clear(); + (*it)->close(); + it = _videos.erase(it); continue; } // Convert to the current screen format - convertedFrame = frame->convertTo(pixelFormat, _videoStreams[i]->getPalette()); + convertedFrame = frame->convertTo(pixelFormat, video->getPalette()); frame = convertedFrame; - } else if (pixelFormat.bytesPerPixel == 1 && _videoStreams[i]->hasDirtyPalette()) { + } else if (pixelFormat.bytesPerPixel == 1 && video->hasDirtyPalette()) { // Set the palette when running in 8bpp mode only // Don't do this for Myst, which has its own per-stack handling if (_vm->getGameType() != GType_MYST) - _vm->_system->getPaletteManager()->setPalette(_videoStreams[i]->getPalette(), 0, 256); + _vm->_system->getPaletteManager()->setPalette(video->getPalette(), 0, 256); } // Clip the width/height to make sure we stay on the screen (Myst does this a few times) - uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x); - uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y); - _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height); + uint16 width = MIN<int32>(video->getWidth(), _vm->_system->getWidth() - (*it)->getX()); + uint16 height = MIN<int32>(video->getHeight(), _vm->_system->getHeight() - (*it)->getY()); + _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, (*it)->getX(), (*it)->getY(), width, height); // We've drawn something to the screen, make sure we update it updateScreen = true; @@ -268,7 +360,10 @@ bool VideoManager::updateMovies() { } // Check the video time - _vm->doVideoTimer(i, false); + _vm->doVideoTimer(*it, false); + + // Remember to increase the iterator + it++; } // Return true if we need to update the screen @@ -323,251 +418,175 @@ void VideoManager::clearMLST() { } VideoHandle VideoManager::playMovieRiven(uint16 id) { - for (uint16 i = 0; i < _mlstRecords.size(); i++) + for (uint16 i = 0; i < _mlstRecords.size(); i++) { if (_mlstRecords[i].code == id) { debug(1, "Play tMOV %d (non-blocking) at (%d, %d) %s, Volume = %d", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0 ? "looping" : "non-looping", _mlstRecords[i].volume); - return createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].loop != 0, _mlstRecords[i].volume); + + VideoEntryPtr ptr = open(_mlstRecords[i].movieID, _mlstRecords[i].volume); + if (ptr) { + ptr->setX(_mlstRecords[i].left); + ptr->setY(_mlstRecords[i].top); + ptr->setLooping(_mlstRecords[i].loop != 0); + } + + return ptr; } + } - return NULL_VID_HANDLE; + return VideoHandle(); } void VideoManager::playMovieBlockingRiven(uint16 id) { - for (uint16 i = 0; i < _mlstRecords.size(); i++) + for (uint16 i = 0; i < _mlstRecords.size(); i++) { if (_mlstRecords[i].code == id) { debug(1, "Play tMOV %d (blocking) at (%d, %d), Volume = %d", _mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, _mlstRecords[i].volume); - VideoHandle videoHandle = createVideoHandle(_mlstRecords[i].movieID, _mlstRecords[i].left, _mlstRecords[i].top, false); - waitUntilMovieEnds(videoHandle); + VideoEntryPtr ptr = open(_mlstRecords[i].movieID, _mlstRecords[i].volume); + ptr->setX(_mlstRecords[i].left); + ptr->setY(_mlstRecords[i].top); + waitUntilMovieEnds(ptr); return; } + } } void VideoManager::stopMovieRiven(uint16 id) { debug(2, "Stopping movie %d", id); - for (uint16 i = 0; i < _mlstRecords.size(); i++) - if (_mlstRecords[i].code == id) - for (uint16 j = 0; j < _videoStreams.size(); j++) - if (_mlstRecords[i].movieID == _videoStreams[j].id) { - delete _videoStreams[j].video; - _videoStreams[j].clear(); - return; - } -} - -void VideoManager::enableMovieRiven(uint16 id) { - debug(2, "Enabling movie %d", id); - for (uint16 i = 0; i < _mlstRecords.size(); i++) - if (_mlstRecords[i].code == id) - for (uint16 j = 0; j < _videoStreams.size(); j++) - if (_mlstRecords[i].movieID == _videoStreams[j].id) { - _videoStreams[j].enabled = true; - return; - } -} - -void VideoManager::disableMovieRiven(uint16 id) { - debug(2, "Disabling movie %d", id); - for (uint16 i = 0; i < _mlstRecords.size(); i++) - if (_mlstRecords[i].code == id) - for (uint16 j = 0; j < _videoStreams.size(); j++) - if (_mlstRecords[i].movieID == _videoStreams[j].id) { - _videoStreams[j].enabled = false; - return; - } + VideoHandle handle = findVideoHandleRiven(id); + if (handle) + removeEntry(handle._ptr); } void VideoManager::disableAllMovies() { debug(2, "Disabling all movies"); - for (uint16 i = 0; i < _videoStreams.size(); i++) - _videoStreams[i].enabled = false; + for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++) + (*it)->setEnabled(false); } -VideoHandle VideoManager::createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop, uint16 volume) { - // First, check to see if that video is already playing - for (uint32 i = 0; i < _videoStreams.size(); i++) - if (_videoStreams[i].id == id) - return i; +VideoEntryPtr VideoManager::open(uint16 id, int volume) { + // If this video is already playing, return that handle + VideoHandle oldHandle = findVideoHandle(id); + if (oldHandle._ptr) + return oldHandle._ptr; // Otherwise, create a new entry - Video::QuickTimeDecoder *decoder = new Video::QuickTimeDecoder(); - decoder->setChunkBeginOffset(_vm->getResourceOffset(ID_TMOV, id)); - decoder->loadStream(_vm->getResource(ID_TMOV, id)); - decoder->setVolume((volume >= 256) ? 255 : volume); - - VideoEntry entry; - entry.clear(); - entry.video = decoder; - entry.x = x; - entry.y = y; - entry.id = id; - entry.loop = loop; - entry.enabled = true; + Video::QuickTimeDecoder *video = new Video::QuickTimeDecoder(); + video->setChunkBeginOffset(_vm->getResourceOffset(ID_TMOV, id)); + video->loadStream(_vm->getResource(ID_TMOV, id)); + + // Set the volume + video->setVolume(CLIP(volume, 0, 255)); + + // Create the entry + VideoEntryPtr entry(new VideoEntry(video, id)); // Enable dither if necessary checkEnableDither(entry); - entry->start(); + // Add it to the video list + _videos.push_back(entry); - // Search for any deleted videos so we can take a formerly used slot - for (uint32 i = 0; i < _videoStreams.size(); i++) - if (!_videoStreams[i].video) { - _videoStreams[i] = entry; - return i; - } + // Start the video + entry->_video->start(); - // Otherwise, just add it to the list - _videoStreams.push_back(entry); - return _videoStreams.size() - 1; + return entry; } -VideoHandle VideoManager::createVideoHandle(const Common::String &filename, uint16 x, uint16 y, bool loop, byte volume) { - // First, check to see if that video is already playing - for (uint32 i = 0; i < _videoStreams.size(); i++) - if (_videoStreams[i].filename == filename) - return i; +VideoEntryPtr VideoManager::open(const Common::String &fileName, int volume) { + // If this video is already playing, return that entry + VideoHandle oldHandle = findVideoHandle(fileName); + if (oldHandle._ptr) + return oldHandle._ptr; // Otherwise, create a new entry - VideoEntry entry; - entry.clear(); - entry.video = new Video::QuickTimeDecoder(); - entry.x = x; - entry.y = y; - entry.filename = filename; - entry.loop = loop; - entry.enabled = true; - - Common::File *file = new Common::File(); - if (!file->open(filename)) { - delete file; - return NULL_VID_HANDLE; + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName); + if (!stream) + return VideoEntryPtr(); + + Video::VideoDecoder *video = new Video::QuickTimeDecoder(); + if (!video->loadStream(stream)) { + // FIXME: Better error handling + delete video; + return VideoEntryPtr(); } - entry->loadStream(file); + // Set the volume + video->setVolume(CLIP(volume, 0, 255)); + + // Create the entry + VideoEntryPtr entry(new VideoEntry(video, fileName)); // Enable dither if necessary checkEnableDither(entry); - entry->setVolume(volume); - entry->start(); + // Add it to the video list + _videos.push_back(entry); - // Search for any deleted videos so we can take a formerly used slot - for (uint32 i = 0; i < _videoStreams.size(); i++) - if (!_videoStreams[i].video) { - _videoStreams[i] = entry; - return i; - } + // Start the video + entry->_video->start(); - // Otherwise, just add it to the list - _videoStreams.push_back(entry); - return _videoStreams.size() - 1; + return entry; } VideoHandle VideoManager::findVideoHandleRiven(uint16 id) { for (uint16 i = 0; i < _mlstRecords.size(); i++) if (_mlstRecords[i].code == id) - for (uint32 j = 0; j < _videoStreams.size(); j++) - if (_videoStreams[j].video && _mlstRecords[i].movieID == _videoStreams[j].id) - return j; + for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++) + if ((*it)->getID() == _mlstRecords[i].movieID) + return *it; - return NULL_VID_HANDLE; + return VideoHandle(); } VideoHandle VideoManager::findVideoHandle(uint16 id) { - if (!id) - return NULL_VID_HANDLE; + if (id == 0) + return VideoHandle(); - for (uint32 i = 0; i < _videoStreams.size(); i++) - if (_videoStreams[i].video && _videoStreams[i].id == id) - return i; + for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++) + if ((*it)->getID() == id) + return *it; - return NULL_VID_HANDLE; + return VideoHandle(); } -VideoHandle VideoManager::findVideoHandle(const Common::String &filename) { - if (filename.empty()) - return NULL_VID_HANDLE; - - for (uint32 i = 0; i < _videoStreams.size(); i++) - if (_videoStreams[i].video && _videoStreams[i].filename.equalsIgnoreCase(filename)) - return i; - - return NULL_VID_HANDLE; -} +VideoHandle VideoManager::findVideoHandle(const Common::String &fileName) { + if (fileName.empty()) + return VideoHandle(); -int VideoManager::getCurFrame(VideoHandle handle) { - assert(handle != NULL_VID_HANDLE); - return _videoStreams[handle]->getCurFrame(); -} - -uint32 VideoManager::getFrameCount(VideoHandle handle) { - assert(handle != NULL_VID_HANDLE); - return _videoStreams[handle]->getFrameCount(); -} - -uint32 VideoManager::getTime(VideoHandle handle) { - assert(handle != NULL_VID_HANDLE); - return _videoStreams[handle]->getTime(); -} + for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++) + if ((*it)->getFileName().equalsIgnoreCase(fileName)) + return *it; -Audio::Timestamp VideoManager::getDuration(VideoHandle handle) { - assert(handle != NULL_VID_HANDLE); - return _videoStreams[handle]->getDuration(); -} - -bool VideoManager::endOfVideo(VideoHandle handle) { - assert(handle != NULL_VID_HANDLE); - return _videoStreams[handle].endOfVideo(); + return VideoHandle(); } bool VideoManager::isVideoPlaying() { - for (uint32 i = 0; i < _videoStreams.size(); i++) - if (!_videoStreams[i].endOfVideo()) + for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++) + if (!(*it)->endOfVideo()) return true; return false; } -void VideoManager::setVideoBounds(VideoHandle handle, Audio::Timestamp start, Audio::Timestamp end) { - assert(handle != NULL_VID_HANDLE); - _videoStreams[handle].start = start; - _videoStreams[handle]->setEndTime(end); - _videoStreams[handle]->seek(start); -} - -void VideoManager::drawVideoFrame(VideoHandle handle, Audio::Timestamp time) { - assert(handle != NULL_VID_HANDLE); - _videoStreams[handle]->seek(time); +void VideoManager::drawVideoFrame(VideoHandle handle, const Audio::Timestamp &time) { + // FIXME: This should be done separately from the "playing" + // videos eventually. + assert(handle); + handle->seek(time); updateMovies(); - delete _videoStreams[handle].video; - _videoStreams[handle].clear(); -} - -void VideoManager::seekToTime(VideoHandle handle, Audio::Timestamp time) { - assert(handle != NULL_VID_HANDLE); - _videoStreams[handle]->seek(time); -} - -void VideoManager::setVideoLooping(VideoHandle handle, bool loop) { - assert(handle != NULL_VID_HANDLE); - _videoStreams[handle].loop = loop; -} - -Common::Rational VideoManager::getVideoRate(VideoHandle handle) const { - assert(handle != NULL_VID_HANDLE); - return _videoStreams[handle]->getRate(); + handle->close(); } -void VideoManager::setVideoRate(VideoHandle handle, const Common::Rational &rate) { - assert(handle != NULL_VID_HANDLE); - _videoStreams[handle]->setRate(rate); +VideoManager::VideoList::iterator VideoManager::findEntry(VideoEntryPtr ptr) { + return Common::find(_videos.begin(), _videos.end(), ptr); } -void VideoManager::pauseMovie(VideoHandle handle, bool pause) { - assert(handle != NULL_VID_HANDLE); - _videoStreams[handle]->pauseVideo(pause); +void VideoManager::removeEntry(VideoEntryPtr ptr) { + VideoManager::VideoList::iterator it = findEntry(ptr); + if (it != _videos.end()) + _videos.erase(it); } -void VideoManager::checkEnableDither(VideoEntry &entry) { +void VideoManager::checkEnableDither(VideoEntryPtr &entry) { // If we're not dithering, bail out if (!_enableDither) return; @@ -575,13 +594,13 @@ void VideoManager::checkEnableDither(VideoEntry &entry) { // Set the palette byte palette[256 * 3]; g_system->getPaletteManager()->grabPalette(palette, 0, 256); - entry->setDitheringPalette(palette); + entry->_video->setDitheringPalette(palette); - if (entry->getPixelFormat().bytesPerPixel != 1) { - if (entry.filename.empty()) - error("Failed to set dither for video %d", entry.id); + if (entry->_video->getPixelFormat().bytesPerPixel != 1) { + if (entry->getFileName().empty()) + error("Failed to set dither for video tMOV %d", entry->getID()); else - error("Failed to set dither for video %s", entry.filename.c_str()); + error("Failed to set dither for video %s", entry->getFileName().c_str()); } } diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h index deb09afe6b..70eecb8175 100644 --- a/engines/mohawk/video.h +++ b/engines/mohawk/video.h @@ -23,9 +23,17 @@ #ifndef MOHAWK_VIDEO_H #define MOHAWK_VIDEO_H +#include "audio/timestamp.h" #include "common/array.h" +#include "common/list.h" +#include "common/noncopyable.h" +#include "common/ptr.h" +#include "common/rational.h" #include "graphics/pixelformat.h" -#include "video/video_decoder.h" + +namespace Video { +class VideoDecoder; +} namespace Mohawk { @@ -43,29 +51,219 @@ struct MLSTRecord { uint16 u1; }; -struct VideoEntry { +/** + * A video monitored by the VideoManager + */ +class VideoEntry : private Common::NonCopyable { + // The private members should be able to be manipulated by VideoManager + friend class VideoManager; + +private: + // Hide the destructor/constructor + // Only VideoManager should be allowed + VideoEntry(); + VideoEntry(Video::VideoDecoder *video, const Common::String &fileName); + VideoEntry(Video::VideoDecoder *video, int id); + +public: + ~VideoEntry(); + + /** + * Convenience implicit cast to bool + */ + operator bool() const { return isOpen(); } + + /** + * Is the video open? + */ + bool isOpen() const { return _video != 0; } + + /** + * Close the video + */ + void close(); + + /** + * Has the video reached its end? + */ + bool endOfVideo() const; + + /** + * Get the X position of where the video is displayed + */ + uint16 getX() const { return _x; } + + /** + * Get the Y position of where the video is displayed + */ + uint16 getY() const { return _y; } + + /** + * Is the video looping? + */ + bool isLooping() const { return _loop; } + + /** + * Is the video enabled? (Drawing to the screen) + */ + bool isEnabled() const { return _enabled; } + + /** + * Get the start time of the video bounds + */ + const Audio::Timestamp &getStart() const { return _start; } + + /** + * Get the file name of the video, or empty if by ID + */ + const Common::String &getFileName() const { return _fileName; } + + /** + * Get the ID of the video, or -1 if by file name + */ + int getID() const { return _id; } + + /** + * Get the current frame of the video + */ + int getCurFrame() const; + + /** + * Get the frame count of the video + */ + uint32 getFrameCount() const; + + /** + * Get the current time position of the video + */ + uint32 getTime() const; + + /** + * Get the duration of the video + */ + Audio::Timestamp getDuration() const; + + /** + * Get the current playback rate of the videos + */ + Common::Rational getRate() const; + + /** + * Move the x position of the video + */ + void setX(uint16 x) { _x = x; } + + /** + * Move the y position of the video + */ + void setY(uint16 y) { _y = y; } + + /** + * Set the start time when using video bounds + */ + void setStart(const Audio::Timestamp &start) { _start = start; } + + /** + * Set the video to loop (true) or not (false) + */ + void setLooping(bool loop) { _loop = loop; } + + /** + * Set the video's enabled status + */ + void setEnabled(bool enabled) { _enabled = enabled; } + + /** + * Set the bounds of the video + * + * This automatically seeks to the start time + */ + void setBounds(const Audio::Timestamp &start, const Audio::Timestamp &end); + + /** + * Seek to the given time + */ + void seek(const Audio::Timestamp &time); + + /** + * Set the playback rate + */ + void setRate(const Common::Rational &rate); + + /** + * Pause the video + */ + void pause(bool isPaused); + +private: + // Non-changing variables + Video::VideoDecoder *_video; + Common::String _fileName; // External video files + int _id; // Internal Mohawk files + // Playback variables - Video::VideoDecoder *video; - uint16 x; - uint16 y; - bool loop; - bool enabled; - Audio::Timestamp start; - - // Identification - Common::String filename; // External video files - int id; // Internal Mohawk files - - // Helper functions - Video::VideoDecoder *operator->() const { assert(video); return video; } // TODO: Remove this eventually - void clear(); - bool endOfVideo(); + uint16 _x; + uint16 _y; + bool _loop; + bool _enabled; + Audio::Timestamp _start; }; -typedef int32 VideoHandle; +typedef Common::SharedPtr<VideoEntry> VideoEntryPtr; + +/** + * A handle for manipulating a video + */ +class VideoHandle { + // The private members should be able to be manipulated by VideoManager + friend class VideoManager; + +public: + /** + * Default constructor + */ + VideoHandle() {} + + /** + * Copy constructor + */ + VideoHandle(const VideoHandle &handle); + + /** + * Is this handle pointing to a valid video entry? + */ + bool isValid() const { return _ptr && _ptr->isOpen(); } + + /** + * Convenience implicit cast to bool + */ + operator bool() const { return isValid(); } + + /** + * Simple equality operator + */ + bool operator==(const VideoHandle &other) const { return _ptr.get() == other._ptr.get(); } -enum { - NULL_VID_HANDLE = -1 + /** + * Simple inequality operator + */ + bool operator!=(const VideoHandle &other) const { return !(*this == other); } + + /** + * Convenience operator-> override to give direct access to the VideoEntry + */ + VideoEntryPtr operator->() const { return _ptr; } + +private: + /** + * Constructor for internal VideoManager use + */ + VideoHandle(VideoEntryPtr ptr); + + /** + * The video entry this is associated with + */ + VideoEntryPtr _ptr; }; class VideoManager { @@ -87,31 +285,18 @@ public: // Riven-related functions void activateMLST(uint16 mlstId, uint16 card); void clearMLST(); - void enableMovieRiven(uint16 id); - void disableMovieRiven(uint16 id); void disableAllMovies(); VideoHandle playMovieRiven(uint16 id); - void stopMovieRiven(uint16 id); void playMovieBlockingRiven(uint16 id); VideoHandle findVideoHandleRiven(uint16 id); + void stopMovieRiven(uint16 id); // Handle functions VideoHandle findVideoHandle(uint16 id); - VideoHandle findVideoHandle(const Common::String &filename); - int getCurFrame(VideoHandle handle); - uint32 getFrameCount(VideoHandle handle); - uint32 getTime(VideoHandle handle); - Audio::Timestamp getDuration(VideoHandle videoHandle); - bool endOfVideo(VideoHandle handle); - void setVideoBounds(VideoHandle handle, Audio::Timestamp start, Audio::Timestamp end); - void drawVideoFrame(VideoHandle handle, Audio::Timestamp time); - void seekToTime(VideoHandle handle, Audio::Timestamp time); - void setVideoLooping(VideoHandle handle, bool loop); - Common::Rational getVideoRate(VideoHandle handle) const; - void setVideoRate(VideoHandle handle, const Common::Rational &rate); - void waitUntilMovieEnds(VideoHandle videoHandle); - void delayUntilMovieEnds(VideoHandle videoHandle); - void pauseMovie(VideoHandle videoHandle, bool pause); + VideoHandle findVideoHandle(const Common::String &fileName); + void waitUntilMovieEnds(VideoHandle handle); + void delayUntilMovieEnds(VideoHandle handle); + void drawVideoFrame(VideoHandle handle, const Audio::Timestamp &time); private: MohawkEngine *_vm; @@ -120,14 +305,19 @@ private: Common::Array<MLSTRecord> _mlstRecords; // Keep tabs on any videos playing - Common::Array<VideoEntry> _videoStreams; + typedef Common::List<VideoEntryPtr> VideoList; + VideoList _videos; - VideoHandle createVideoHandle(uint16 id, uint16 x, uint16 y, bool loop, uint16 volume = 0xff); - VideoHandle createVideoHandle(const Common::String &filename, uint16 x, uint16 y, bool loop, byte volume = 0xff); + // Utility functions for managing entries + VideoEntryPtr open(uint16 id, int volume = 0xFF); + VideoEntryPtr open(const Common::String &fileName, int volume = 0xFF); + + VideoList::iterator findEntry(VideoEntryPtr ptr); + void removeEntry(VideoEntryPtr ptr); // Dithering control bool _enableDither; - void checkEnableDither(VideoEntry &entry); + void checkEnableDither(VideoEntryPtr &entry); }; } // End of namespace Mohawk |