1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "titanic/support/movie.h"
24 #include "titanic/core/game_object.h"
25 #include "titanic/events.h"
26 #include "titanic/messages/messages.h"
27 #include "titanic/support/avi_surface.h"
28 #include "titanic/support/screen_manager.h"
29 #include "titanic/support/video_surface.h"
30 #include "titanic/sound/sound_manager.h"
31 #include "titanic/titanic.h"
32 
33 namespace Titanic {
34 
35 #define CLIP_WIDTH 600
36 #define CLIP_WIDTH_REDUCED (CLIP_WIDTH / 2)
37 #define CLIP_HEIGHT 340
38 #define CLIP_HEIGHT_REDUCED (CLIP_HEIGHT / 2)
39 
40 CMovieList *CMovie::_playingMovies;
41 CVideoSurface *CMovie::_movieSurface;
42 
CMovie()43 CMovie::CMovie() : ListItem(), _handled(false), _hasVideoFrame(false) {
44 }
45 
~CMovie()46 CMovie::~CMovie() {
47 	removeFromPlayingMovies();
48 }
49 
init()50 void CMovie::init() {
51 	_playingMovies = new CMovieList();
52 	_movieSurface = nullptr;
53 }
54 
deinit()55 void CMovie::deinit() {
56 	// At this point, there shouldn't be any playing movies left,
57 	// since their owning objects should have freed them
58 	assert(_playingMovies->empty());
59 	delete _playingMovies;
60 	delete _movieSurface;
61 }
62 
addToPlayingMovies()63 void CMovie::addToPlayingMovies() {
64 	if (!isActive())
65 		_playingMovies->push_back(this);
66 }
67 
removeFromPlayingMovies()68 void CMovie::removeFromPlayingMovies() {
69 	_playingMovies->remove(this);
70 }
71 
isActive() const72 bool CMovie::isActive() const {
73 	return _playingMovies->contains(this);
74 }
75 
hasVideoFrame()76 bool CMovie::hasVideoFrame() {
77 	if (_hasVideoFrame) {
78 		_hasVideoFrame = 0;
79 		return true;
80 	} else {
81 		return false;
82 	}
83 }
84 
85 /*------------------------------------------------------------------------*/
86 
OSMovie(const CResourceKey & name,CVideoSurface * surface)87 OSMovie::OSMovie(const CResourceKey &name, CVideoSurface *surface) :
88 		_aviSurface(name), _videoSurface(surface) {
89 	_field18 = 0;
90 	_field24 = 0;
91 	_field28 = 0;
92 	_field2C = 0;
93 
94 	surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight());
95 	_aviSurface.setVideoSurface(surface);
96 }
97 
~OSMovie()98 OSMovie::~OSMovie() {
99 }
100 
play(uint flags,CGameObject * obj)101 void OSMovie::play(uint flags, CGameObject *obj) {
102 	_aviSurface.play(flags, obj);
103 
104 	if (_aviSurface.isPlaying())
105 		movieStarted();
106 }
107 
play(uint startFrame,uint endFrame,uint flags,CGameObject * obj)108 void OSMovie::play(uint startFrame, uint endFrame, uint flags, CGameObject *obj) {
109 	_aviSurface.play(startFrame, endFrame, flags, obj);
110 
111 	if (_aviSurface.isPlaying())
112 		movieStarted();
113 }
114 
play(uint startFrame,uint endFrame,uint initialFrame,uint flags,CGameObject * obj)115 void OSMovie::play(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) {
116 	_aviSurface.play(startFrame, endFrame, initialFrame, flags, obj);
117 
118 	if (_aviSurface.isPlaying())
119 		movieStarted();
120 }
121 
playCutscene(const Rect & drawRect,uint startFrame,uint endFrame)122 bool OSMovie::playCutscene(const Rect &drawRect, uint startFrame, uint endFrame) {
123 	if (!_movieSurface)
124 		_movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 32);
125 
126 	// Set a new event target whilst the clip plays, so standard scene drawing isn't called
127 	CEventTarget eventTarget;
128 	g_vm->_events->addTarget(&eventTarget);
129 
130 	bool result = _aviSurface.playCutscene(drawRect, startFrame, endFrame);
131 
132 	g_vm->_events->removeTarget();
133 	return result;
134 }
135 
pause()136 void OSMovie::pause() {
137 	_aviSurface.pause();
138 }
139 
stop()140 void OSMovie::stop() {
141 	_aviSurface.stop();
142 	removeFromPlayingMovies();
143 }
144 
addEvent(int frameNumber,CGameObject * obj)145 void OSMovie::addEvent(int frameNumber, CGameObject *obj) {
146 	if (_aviSurface.addEvent(&frameNumber, obj)) {
147 		CMovieFrameMsg frameMsg(frameNumber, 0);
148 		frameMsg.execute(obj);
149 	}
150 }
151 
setFrame(uint frameNumber)152 void OSMovie::setFrame(uint frameNumber) {
153 	_aviSurface.setFrame(frameNumber);
154 	_videoSurface->setTransparencySurface(_aviSurface.getSecondarySurface());
155 }
156 
handleEvents(CMovieEventList & events)157 bool OSMovie::handleEvents(CMovieEventList &events) {
158 	// WORKAROUND: If a movie is paused as part of initial
159 	// scene loading, now's the time to un-pause it
160 	_aviSurface.resume();
161 
162 	if (!_aviSurface.isPlaying())
163 		return false;
164 
165 	// Handle updating the frame
166 	while (_aviSurface.isPlaying() && _aviSurface.isNextFrame()) {
167 		_aviSurface.handleEvents(events);
168 		_videoSurface->setTransparencySurface(_aviSurface.getSecondarySurface());
169 
170 		// Flag there's a video frame
171 		_hasVideoFrame = true;
172 	}
173 
174 	return _aviSurface.isPlaying();
175 }
176 
getMovieRangeInfo() const177 const CMovieRangeInfoList *OSMovie::getMovieRangeInfo() const {
178 	return _aviSurface.getMovieRangeInfo();
179 }
180 
setSoundManager(CSoundManager * soundManager)181 void OSMovie::setSoundManager(CSoundManager *soundManager) {
182 	_aviSurface._soundManager = soundManager;
183 }
184 
getFrame() const185 int OSMovie::getFrame() const {
186 	return _aviSurface.getFrame();
187 }
188 
movieStarted()189 void OSMovie::movieStarted() {
190 	//if (_aviSurface._hasAudio)
191 	//	_aviSurface._soundManager->movieStarted();
192 
193 	// Register the movie in the playing list
194 	addToPlayingMovies();
195 	_hasVideoFrame = true;
196 }
197 
setFrameRate(double rate)198 void OSMovie::setFrameRate(double rate) {
199 	_aviSurface.setFrameRate(rate);
200 }
201 
setPlaying(bool playingFlag)202 void OSMovie::setPlaying(bool playingFlag) {
203 	_aviSurface.setPlaying(playingFlag);
204 }
205 
duplicateTransparency() const206 Graphics::ManagedSurface *OSMovie::duplicateTransparency() const {
207 	return _aviSurface.duplicateTransparency();
208 }
209 
210 } // End of namespace Titanic
211