ALL: synced with ScummVM
This commit is contained in:
parent
e76e3f3b3d
commit
1a07a23294
17 changed files with 260 additions and 43 deletions
|
@ -98,7 +98,7 @@ LoopingAudioStream::LoopingAudioStream(RewindableAudioStream *stream, uint loops
|
|||
// TODO: Properly indicate error
|
||||
_loops = _completeIterations = 1;
|
||||
}
|
||||
if (stream->endOfData()) {
|
||||
if (stream->endOfStream()) {
|
||||
// Apparently this is an empty stream
|
||||
_loops = _completeIterations = 1;
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ int LoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
|
|||
_loops = _completeIterations = 1;
|
||||
return samplesRead;
|
||||
}
|
||||
if (_parent->endOfData()) {
|
||||
if (_parent->endOfStream()) {
|
||||
// Apparently this is an empty stream
|
||||
_loops = _completeIterations = 1;
|
||||
}
|
||||
|
@ -134,7 +134,11 @@ int LoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
|
|||
}
|
||||
|
||||
bool LoopingAudioStream::endOfData() const {
|
||||
return (_loops != 0 && (_completeIterations == _loops));
|
||||
return (_loops != 0 && _completeIterations == _loops) || _parent->endOfData();
|
||||
}
|
||||
|
||||
bool LoopingAudioStream::endOfStream() const {
|
||||
return _loops != 0 && _completeIterations == _loops;
|
||||
}
|
||||
|
||||
AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, uint loops) {
|
||||
|
@ -189,7 +193,7 @@ int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
|
|||
int framesRead = _parent->readBuffer(buffer, framesLeft);
|
||||
_pos = _pos.addFrames(framesRead);
|
||||
|
||||
if (framesRead < framesLeft && _parent->endOfData()) {
|
||||
if (framesRead < framesLeft && _parent->endOfStream()) {
|
||||
// TODO: Proper error indication.
|
||||
_done = true;
|
||||
return framesRead;
|
||||
|
@ -216,6 +220,18 @@ int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
|
|||
}
|
||||
}
|
||||
|
||||
bool SubLoopingAudioStream::endOfData() const {
|
||||
// We're out of data if this stream is finished or the parent
|
||||
// has run out of data for now.
|
||||
return _done || _parent->endOfData();
|
||||
}
|
||||
|
||||
bool SubLoopingAudioStream::endOfStream() const {
|
||||
// The end of the stream has been reached only when we've gone
|
||||
// through all the iterations.
|
||||
return _done;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark --- SubSeekableAudioStream ---
|
||||
#pragma mark -
|
||||
|
@ -315,18 +331,27 @@ public:
|
|||
virtual int readBuffer(int16 *buffer, const int numSamples);
|
||||
virtual bool isStereo() const { return _stereo; }
|
||||
virtual int getRate() const { return _rate; }
|
||||
|
||||
virtual bool endOfData() const {
|
||||
//Common::StackLock lock(_mutex);
|
||||
return _queue.empty();
|
||||
Common::StackLock lock(_mutex);
|
||||
return _queue.empty() || _queue.front()._stream->endOfData();
|
||||
}
|
||||
|
||||
virtual bool endOfStream() const {
|
||||
Common::StackLock lock(_mutex);
|
||||
return _finished && _queue.empty();
|
||||
}
|
||||
virtual bool endOfStream() const { return _finished && _queue.empty(); }
|
||||
|
||||
// Implement the QueuingAudioStream API
|
||||
virtual void queueAudioStream(AudioStream *stream, DisposeAfterUse::Flag disposeAfterUse);
|
||||
virtual void finish() { _finished = true; }
|
||||
|
||||
virtual void finish() {
|
||||
Common::StackLock lock(_mutex);
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
uint32 numQueuedStreams() const {
|
||||
//Common::StackLock lock(_mutex);
|
||||
Common::StackLock lock(_mutex);
|
||||
return _queue.size();
|
||||
}
|
||||
};
|
||||
|
@ -356,11 +381,17 @@ int QueuingAudioStreamImpl::readBuffer(int16 *buffer, const int numSamples) {
|
|||
AudioStream *stream = _queue.front()._stream;
|
||||
samplesDecoded += stream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded);
|
||||
|
||||
if (stream->endOfData()) {
|
||||
// Done with the stream completely
|
||||
if (stream->endOfStream()) {
|
||||
StreamHolder tmp = _queue.pop();
|
||||
if (tmp._disposeAfterUse == DisposeAfterUse::YES)
|
||||
delete stream;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Done with data but not the stream, bail out
|
||||
if (stream->endOfData())
|
||||
break;
|
||||
}
|
||||
|
||||
return samplesDecoded;
|
||||
|
@ -416,12 +447,14 @@ public:
|
|||
return samplesRead;
|
||||
}
|
||||
|
||||
bool endOfData() const { return _parentStream->endOfData() || _samplesRead >= _totalSamples; }
|
||||
bool endOfData() const { return _parentStream->endOfData() || reachedLimit(); }
|
||||
bool endOfStream() const { return _parentStream->endOfStream() || reachedLimit(); }
|
||||
bool isStereo() const { return _parentStream->isStereo(); }
|
||||
int getRate() const { return _parentStream->getRate(); }
|
||||
|
||||
private:
|
||||
int getChannels() const { return isStereo() ? 2 : 1; }
|
||||
bool reachedLimit() const { return _samplesRead >= _totalSamples; }
|
||||
|
||||
AudioStream *_parentStream;
|
||||
DisposeAfterUse::Flag _disposeAfterUse;
|
||||
|
|
|
@ -118,6 +118,7 @@ public:
|
|||
|
||||
int readBuffer(int16 *buffer, const int numSamples);
|
||||
bool endOfData() const;
|
||||
bool endOfStream() const;
|
||||
|
||||
bool isStereo() const { return _parent->isStereo(); }
|
||||
int getRate() const { return _parent->getRate(); }
|
||||
|
@ -247,7 +248,8 @@ public:
|
|||
DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
|
||||
|
||||
int readBuffer(int16 *buffer, const int numSamples);
|
||||
bool endOfData() const { return _done; }
|
||||
bool endOfData() const;
|
||||
bool endOfStream() const;
|
||||
|
||||
bool isStereo() const { return _parent->isStereo(); }
|
||||
int getRate() const { return _parent->getRate(); }
|
||||
|
@ -287,7 +289,8 @@ public:
|
|||
|
||||
int getRate() const { return _parent->getRate(); }
|
||||
|
||||
bool endOfData() const { return (_pos >= _length) || _parent->endOfStream(); }
|
||||
bool endOfData() const { return (_pos >= _length) || _parent->endOfData(); }
|
||||
bool endOfStream() const { return (_pos >= _length) || _parent->endOfStream(); }
|
||||
|
||||
bool seek(const Timestamp &where);
|
||||
|
||||
|
|
|
@ -117,6 +117,7 @@ AudioStream *AACDecoder::decodeFrame(Common::SeekableReadStream &stream) {
|
|||
inBufferPos += frameInfo.bytesconsumed;
|
||||
}
|
||||
|
||||
audioStream->finish();
|
||||
return audioStream;
|
||||
}
|
||||
|
||||
|
|
|
@ -2607,6 +2607,7 @@ AudioStream *QDM2Stream::decodeFrame(Common::SeekableReadStream &stream) {
|
|||
while (qdm2_decodeFrame(stream, audioStream))
|
||||
;
|
||||
|
||||
audioStream->finish();
|
||||
return audioStream;
|
||||
}
|
||||
|
||||
|
|
|
@ -414,8 +414,15 @@ void QuickTimeAudioDecoder::QuickTimeAudioTrack::skipSamples(const Timestamp &le
|
|||
}
|
||||
|
||||
void QuickTimeAudioDecoder::QuickTimeAudioTrack::findEdit(const Timestamp &position) {
|
||||
for (_curEdit = 0; _curEdit < _parentTrack->editCount - 1 && position > Timestamp(0, _parentTrack->editList[_curEdit].timeOffset, _decoder->_timeScale); _curEdit++)
|
||||
;
|
||||
// Go through the edits look for where we find out we need to be. As long
|
||||
// as the position is >= to the edit's start time, it is considered to be in that
|
||||
// edit. seek() already figured out if we reached the last edit, so we don't need
|
||||
// to handle that case here.
|
||||
for (_curEdit = 0; _curEdit < _parentTrack->editCount - 1; _curEdit++) {
|
||||
Timestamp nextEditTime(0, _parentTrack->editList[_curEdit + 1].timeOffset, _decoder->_timeScale);
|
||||
if (position < nextEditTime)
|
||||
break;
|
||||
}
|
||||
|
||||
enterNewEdit(position);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
// Set up a stack cookie to avoid crashes due to too few stack set by users
|
||||
static const char *stack_cookie __attribute__((used)) = "$STACK: 600000";
|
||||
|
||||
// Create our OSystem instance
|
||||
g_system = new OSystem_AmigaOS();
|
||||
assert(g_system);
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
# Special target to create an AmigaOS snapshot installation
|
||||
amigaos4dist: $(EXECUTABLE)
|
||||
mkdir -p $(AMIGAOS4PATH)
|
||||
mkdir -p $(AMIGAOS4PATH)/themes
|
||||
mkdir -p $(AMIGAOS4PATH)/extras
|
||||
$(STRIP) $(EXECUTABLE) -o $(AMIGAOS4PATH)/$(EXECUTABLE)
|
||||
cp ${srcdir}/icons/residualvm.info $(AMIGAOS4PATH)/$(EXECUTABLE).info
|
||||
cp $(DIST_FILES_THEMES) $(AMIGAOS4PATH)/themes/
|
||||
amigaosdist: $(EXECUTABLE)
|
||||
mkdir -p $(AMIGAOSPATH)
|
||||
mkdir -p $(AMIGAOSPATH)/themes
|
||||
mkdir -p $(AMIGAOSPATH)/extras
|
||||
$(STRIP) $(EXECUTABLE) -o $(AMIGAOSPATH)/$(EXECUTABLE)
|
||||
cp ${srcdir}/icons/residualvm.info $(AMIGAOSPATH)/$(EXECUTABLE).info
|
||||
cp $(DIST_FILES_THEMES) $(AMIGAOSPATH)/themes/
|
||||
ifdef DIST_FILES_ENGINEDATA
|
||||
cp $(DIST_FILES_ENGINEDATA) $(AMIGAOS4PATH)/extras/
|
||||
cp $(DIST_FILES_ENGINEDATA) $(AMIGAOSPATH)/extras/
|
||||
endif
|
||||
cp $(DIST_FILES_DOCS) $(AMIGAOS4PATH)
|
||||
cp $(DIST_FILES_DOCS) $(AMIGAOSPATH)
|
||||
|
||||
# Special target to cross create an AmigaOS snapshot installation
|
||||
amigaos4cross: $(EXECUTABLE)
|
||||
amigaoscross: $(EXECUTABLE)
|
||||
mkdir -p ResidualVM
|
||||
mkdir -p ResidualVM/themes
|
||||
mkdir -p ResidualVM/extras
|
||||
|
|
|
@ -56,6 +56,9 @@
|
|||
* to properly work in exports (i.e. release tar balls etc.).
|
||||
*/
|
||||
const char *gScummVMVersion = SCUMMVM_VERSION;
|
||||
#ifdef __amigaos4__
|
||||
static const char *version_cookie __attribute__((used)) = "$VER: ScummVM " SCUMMVM_VERSION " (" __DATE__ ", " __TIME__ ")";
|
||||
#endif
|
||||
#ifdef __PLAYSTATION2__
|
||||
const char *gScummVMBuildDate = "Git Master"; /* ScummVM Git Master */
|
||||
const char *gScummVMVersionDate = SCUMMVM_VERSION " - PlayStation2";
|
||||
|
|
|
@ -597,7 +597,7 @@ void ConfigManager::setActiveDomain(const String &domName) {
|
|||
_activeDomain = 0;
|
||||
} else {
|
||||
assert(isValidDomainName(domName));
|
||||
_activeDomain = & _gameDomains[domName];
|
||||
_activeDomain = &_gameDomains[domName];
|
||||
}
|
||||
_activeDomainName = domName;
|
||||
}
|
||||
|
@ -626,6 +626,10 @@ void ConfigManager::addMiscDomain(const String &domName) {
|
|||
void ConfigManager::removeGameDomain(const String &domName) {
|
||||
assert(!domName.empty());
|
||||
assert(isValidDomainName(domName));
|
||||
if (domName == _activeDomainName) {
|
||||
_activeDomainName.clear();
|
||||
_activeDomain = 0;
|
||||
}
|
||||
_gameDomains.erase(domName);
|
||||
}
|
||||
|
||||
|
@ -638,6 +642,10 @@ void ConfigManager::removeMiscDomain(const String &domName) {
|
|||
|
||||
void ConfigManager::renameGameDomain(const String &oldName, const String &newName) {
|
||||
renameDomain(oldName, newName, _gameDomains);
|
||||
if (_activeDomainName == oldName) {
|
||||
_activeDomainName = newName;
|
||||
_activeDomain = &_gameDomains[newName];
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigManager::renameMiscDomain(const String &oldName, const String &newName) {
|
||||
|
|
4
configure
vendored
4
configure
vendored
|
@ -175,7 +175,7 @@ _as="as"
|
|||
_windres=windres
|
||||
_stagingpath="staging"
|
||||
_win32path="C:/residualvm"
|
||||
_amigaos4path="Games:ResidualVM"
|
||||
_amigaospath="Games:ResidualVM"
|
||||
_staticlibpath=
|
||||
_sdlconfig=sdl-config
|
||||
_freetypeconfig=freetype-config
|
||||
|
@ -4572,7 +4572,7 @@ WINDRES := $_windres
|
|||
WINDRESFLAGS := $WINDRESFLAGS
|
||||
STAGINGPATH=$_stagingpath
|
||||
WIN32PATH=$_win32path
|
||||
AMIGAOS4PATH=$_amigaos4path
|
||||
AMIGAOSPATH=$_amigaospath
|
||||
STATICLIBPATH=$_staticlibpath
|
||||
|
||||
BACKEND := $_backend
|
||||
|
|
|
@ -122,7 +122,7 @@ bool cleanupPirated(ADGameDescList &matched) {
|
|||
|
||||
// We ruled out all variants and now have nothing
|
||||
if (matched.empty()) {
|
||||
warning("Illegitimate game copy detected. We give no support in such cases %d", matched.size());
|
||||
warning("Illegitimate game copy detected. We provide no support in such cases");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,97 @@
|
|||
|
||||
namespace Graphics {
|
||||
|
||||
/** Template to expand from an n-bit component to an 8-bit component */
|
||||
template<int depth>
|
||||
struct ColorComponent {
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ColorComponent<0> {
|
||||
static inline uint expand(uint value) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ColorComponent<1> {
|
||||
static inline uint expand(uint value) {
|
||||
value &= 1;
|
||||
return value |
|
||||
(value << 1) |
|
||||
(value << 2) |
|
||||
(value << 3) |
|
||||
(value << 4) |
|
||||
(value << 5) |
|
||||
(value << 6) |
|
||||
(value << 7);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ColorComponent<2> {
|
||||
static inline uint expand(uint value) {
|
||||
value &= 3;
|
||||
return value |
|
||||
(value << 2) |
|
||||
(value << 4) |
|
||||
(value << 6);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ColorComponent<3> {
|
||||
static inline uint expand(uint value) {
|
||||
value &= 7;
|
||||
return (value << 5) |
|
||||
(value << 2) |
|
||||
(value >> 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ColorComponent<4> {
|
||||
static inline uint expand(uint value) {
|
||||
value &= 15;
|
||||
return value |
|
||||
(value << 4);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ColorComponent<5> {
|
||||
static inline uint expand(uint value) {
|
||||
value &= 31;
|
||||
return (value << 3) |
|
||||
(value >> 2);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ColorComponent<6> {
|
||||
static inline uint expand(uint value) {
|
||||
value &= 63;
|
||||
return (value << 2) |
|
||||
(value >> 4);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ColorComponent<7> {
|
||||
static inline uint expand(uint value) {
|
||||
value &= 127;
|
||||
return (value << 1) |
|
||||
(value >> 6);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ColorComponent<8> {
|
||||
static inline uint expand(uint value) {
|
||||
return value & 255;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A pixel format description.
|
||||
*
|
||||
|
@ -91,16 +182,16 @@ struct PixelFormat {
|
|||
}
|
||||
|
||||
inline void colorToRGB(uint32 color, uint8 &r, uint8 &g, uint8 &b) const {
|
||||
r = ((color >> rShift) << rLoss) & 0xFF;
|
||||
g = ((color >> gShift) << gLoss) & 0xFF;
|
||||
b = ((color >> bShift) << bLoss) & 0xFF;
|
||||
r = expand(rBits(), color >> rShift);
|
||||
g = expand(gBits(), color >> gShift);
|
||||
b = expand(bBits(), color >> bShift);
|
||||
}
|
||||
|
||||
inline void colorToARGB(uint32 color, uint8 &a, uint8 &r, uint8 &g, uint8 &b) const {
|
||||
a = (aBits() == 0) ? 0xFF : (((color >> aShift) << aLoss) & 0xFF);
|
||||
r = ((color >> rShift) << rLoss) & 0xFF;
|
||||
g = ((color >> gShift) << gLoss) & 0xFF;
|
||||
b = ((color >> bShift) << bLoss) & 0xFF;
|
||||
a = (aBits() == 0) ? 0xFF : expand(aBits(), color >> aShift);
|
||||
r = expand(rBits(), color >> rShift);
|
||||
g = expand(gBits(), color >> gShift);
|
||||
b = expand(bBits(), color >> bShift);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -142,6 +233,33 @@ struct PixelFormat {
|
|||
inline uint aMax() const {
|
||||
return (1 << aBits()) - 1;
|
||||
}
|
||||
|
||||
/** Expand a given bit-depth component to a full 8-bit component */
|
||||
static inline uint expand(uint bits, uint color) {
|
||||
switch (bits) {
|
||||
case 0:
|
||||
return ColorComponent<0>::expand(color);
|
||||
case 1:
|
||||
return ColorComponent<1>::expand(color);
|
||||
case 2:
|
||||
return ColorComponent<2>::expand(color);
|
||||
case 3:
|
||||
return ColorComponent<3>::expand(color);
|
||||
case 4:
|
||||
return ColorComponent<4>::expand(color);
|
||||
case 5:
|
||||
return ColorComponent<5>::expand(color);
|
||||
case 6:
|
||||
return ColorComponent<6>::expand(color);
|
||||
case 7:
|
||||
return ColorComponent<7>::expand(color);
|
||||
case 8:
|
||||
return ColorComponent<8>::expand(color);
|
||||
}
|
||||
|
||||
// Unsupported
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // End of namespace Graphics
|
||||
|
|
|
@ -84,7 +84,7 @@ enum {
|
|||
|
||||
static const char *savePeriodLabels[] = { _s("Never"), _s("every 5 mins"), _s("every 10 mins"), _s("every 15 mins"), _s("every 30 mins"), 0 };
|
||||
static const int savePeriodValues[] = { 0, 5 * 60, 10 * 60, 15 * 60, 30 * 60, -1 };
|
||||
static const char *outputRateLabels[] = { _s("<default>"), _s("8 kHz"), _s("11kHz"), _s("22 kHz"), _s("44 kHz"), _s("48 kHz"), 0 };
|
||||
static const char *outputRateLabels[] = { _s("<default>"), _s("8 kHz"), _s("11 kHz"), _s("22 kHz"), _s("44 kHz"), _s("48 kHz"), 0 };
|
||||
static const int outputRateValues[] = { 0, 8000, 11025, 22050, 44100, 48000, -1 };
|
||||
|
||||
OptionsDialog::OptionsDialog(const Common::String &domain, int x, int y, int w, int h)
|
||||
|
@ -890,10 +890,10 @@ void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefi
|
|||
|
||||
// SoundFont
|
||||
if (g_system->getOverlayWidth() > 320)
|
||||
_soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _("SoundFont:"), _("SoundFont is supported by some audio cards, Fluidsynth and Timidity"), kChooseSoundFontCmd);
|
||||
_soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _("SoundFont:"), _("SoundFont is supported by some audio cards, FluidSynth and Timidity"), kChooseSoundFontCmd);
|
||||
else
|
||||
_soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _c("SoundFont:", "lowres"), _("SoundFont is supported by some audio cards, Fluidsynth and Timidity"), kChooseSoundFontCmd);
|
||||
_soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", _c("None", "soundfont"), _("SoundFont is supported by some audio cards, Fluidsynth and Timidity"));
|
||||
_soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _c("SoundFont:", "lowres"), _("SoundFont is supported by some audio cards, FluidSynth and Timidity"), kChooseSoundFontCmd);
|
||||
_soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", _c("None", "soundfont"), _("SoundFont is supported by some audio cards, FluidSynth and Timidity"));
|
||||
|
||||
_soundFontClearButton = addClearButton(boss, prefix + "mcFontClearButton", kClearSoundFontCmd);
|
||||
|
||||
|
|
|
@ -52,11 +52,16 @@ CinepakDecoder::CinepakDecoder(int bitsPerPixel) : Codec() {
|
|||
_curFrame.strips = NULL;
|
||||
_y = 0;
|
||||
|
||||
if (bitsPerPixel == 8)
|
||||
if (bitsPerPixel == 8) {
|
||||
_pixelFormat = Graphics::PixelFormat::createFormatCLUT8();
|
||||
else
|
||||
} else {
|
||||
_pixelFormat = g_system->getScreenFormat();
|
||||
|
||||
// Default to a 32bpp format, if in 8bpp mode
|
||||
if (_pixelFormat.bytesPerPixel == 1)
|
||||
_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
|
||||
}
|
||||
|
||||
// Create a lookup for the clip function
|
||||
// This dramatically improves the performance of the color conversion
|
||||
_clipTableBuf = new byte[1024];
|
||||
|
|
|
@ -49,7 +49,6 @@ class RenderModeTestSuite : public CxxTest::TestSuite {
|
|||
* Notably, the output should not be in mixed case.
|
||||
*/
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("FMTOWNS")), "fmtowns", 7);
|
||||
TS_ASSERT_DIFFERS(Common::getRenderModeCode(Common::parseRenderMode("FMTOWNS")), "fmtowns");
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("CGA")), "cga", 3);
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("vga")), "vga", 3);
|
||||
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("Ega")), "ega", 3);
|
||||
|
|
|
@ -778,6 +778,31 @@ void VideoDecoder::setEndTime(const Audio::Timestamp &endTime) {
|
|||
}
|
||||
}
|
||||
|
||||
void VideoDecoder::setEndFrame(uint frame) {
|
||||
VideoTrack *track = 0;
|
||||
|
||||
for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) {
|
||||
if ((*it)->getTrackType() == Track::kTrackTypeVideo) {
|
||||
// We only allow this when one video track is present
|
||||
if (track)
|
||||
return;
|
||||
|
||||
track = (VideoTrack *)*it;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find a video track, we can't set the final frame (of course)
|
||||
if (!track)
|
||||
return;
|
||||
|
||||
Audio::Timestamp time = track->getFrameTime(frame + 1);
|
||||
|
||||
if (time < 0)
|
||||
return;
|
||||
|
||||
setEndTime(time);
|
||||
}
|
||||
|
||||
VideoDecoder::Track *VideoDecoder::getTrack(uint track) {
|
||||
if (track > _internalTracks.size())
|
||||
return 0;
|
||||
|
|
|
@ -213,6 +213,17 @@ public:
|
|||
*/
|
||||
void setEndTime(const Audio::Timestamp &endTime);
|
||||
|
||||
/**
|
||||
* Set the end frame.
|
||||
*
|
||||
* The passed frame will be the last frame to show.
|
||||
*
|
||||
* Like seekToFrame(), this only works when one video track is present,
|
||||
* and that track supports getFrameTime(). This calls setEndTime()
|
||||
* internally.
|
||||
*/
|
||||
void setEndFrame(uint frame);
|
||||
|
||||
/**
|
||||
* Get the stop time of the video (if not set, zero)
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue