MOHAWK: Make video handles actual objects

This commit is contained in:
Matthew Hoops 2015-07-15 23:59:21 -04:00
parent 95b1288329
commit 7e6c8be7db
12 changed files with 660 additions and 447 deletions

View File

@ -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);
}

View File

@ -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) {

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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,27 +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(ptr);
}
void VideoManager::playMovieBlockingCentered(const Common::String &fileName, bool clearScreen) {
VideoEntryPtr ptr = open(fileName);
if (!ptr)
return;
// Clear screen if requested
@ -91,33 +167,23 @@ void VideoManager::playMovieBlocking(const Common::String &filename, uint16 x, u
_vm->_system->updateScreen();
}
waitUntilMovieEnds(videoHandle);
}
ptr->setX((_vm->_system->getWidth() - ptr->_video->getWidth()) / 2);
ptr->setY((_vm->_system->getHeight() - ptr->_video->getHeight()) / 2);
void VideoManager::playMovieBlockingCentered(const Common::String &filename, bool clearScreen) {
VideoHandle videoHandle = createVideoHandle(filename, 0, 0, false);
if (videoHandle == NULL_VID_HANDLE)
return;
// Clear screen if requested
if (clearScreen) {
_vm->_system->fillScreen(_vm->_system->getScreenFormat().RGBToColor(0, 0, 0));
_vm->_system->updateScreen();
}
_videoStreams[videoHandle].x = (_vm->_system->getWidth() - _videoStreams[videoHandle]->getWidth()) / 2;
_videoStreams[videoHandle].y = (_vm->_system->getHeight() - _videoStreams[videoHandle]->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);
}
return NULL_VID_HANDLE;
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 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);
Video::QuickTimeDecoder *video = new Video::QuickTimeDecoder();
video->setChunkBeginOffset(_vm->getResourceOffset(ID_TMOV, id));
video->loadStream(_vm->getResource(ID_TMOV, id));
VideoEntry entry;
entry.clear();
entry.video = decoder;
entry.x = x;
entry.y = y;
entry.id = id;
entry.loop = loop;
entry.enabled = true;
// 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::SeekableReadStream *stream = SearchMan.createReadStreamForMember(fileName);
if (!stream)
return VideoEntryPtr();
Common::File *file = new Common::File();
if (!file->open(filename)) {
delete file;
return NULL_VID_HANDLE;
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;
VideoHandle VideoManager::findVideoHandle(const Common::String &fileName) {
if (fileName.empty())
return VideoHandle();
for (uint32 i = 0; i < _videoStreams.size(); i++)
if (_videoStreams[i].video && _videoStreams[i].filename.equalsIgnoreCase(filename))
return i;
for (VideoList::iterator it = _videos.begin(); it != _videos.end(); it++)
if ((*it)->getFileName().equalsIgnoreCase(fileName))
return *it;
return NULL_VID_HANDLE;
}
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();
}
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();
handle->close();
}
void VideoManager::seekToTime(VideoHandle handle, Audio::Timestamp time) {
assert(handle != NULL_VID_HANDLE);
_videoStreams[handle]->seek(time);
VideoManager::VideoList::iterator VideoManager::findEntry(VideoEntryPtr ptr) {
return Common::find(_videos.begin(), _videos.end(), ptr);
}
void VideoManager::setVideoLooping(VideoHandle handle, bool loop) {
assert(handle != NULL_VID_HANDLE);
_videoStreams[handle].loop = loop;
void VideoManager::removeEntry(VideoEntryPtr ptr) {
VideoManager::VideoList::iterator it = findEntry(ptr);
if (it != _videos.end())
_videos.erase(it);
}
Common::Rational VideoManager::getVideoRate(VideoHandle handle) const {
assert(handle != NULL_VID_HANDLE);
return _videoStreams[handle]->getRate();
}
void VideoManager::setVideoRate(VideoHandle handle, const Common::Rational &rate) {
assert(handle != NULL_VID_HANDLE);
_videoStreams[handle]->setRate(rate);
}
void VideoManager::pauseMovie(VideoHandle handle, bool pause) {
assert(handle != NULL_VID_HANDLE);
_videoStreams[handle]->pauseVideo(pause);
}
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());
}
}

View File

@ -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;
enum {
NULL_VID_HANDLE = -1
/**
* 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(); }
/**
* 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