1 /*
2  * Copyright (C) 2012 Sibi Antony (Phonon/QT4 implementation)
3  * Copyright (C) 2015 Georg Zotti (Reactivated with QT5 classes)
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18  */
19 
20 #include "StelVideoMgr.hpp"
21 #include "StelMainView.hpp"
22 #include <QDebug>
23 #include <QDir>
24 #ifdef ENABLE_MEDIA
25 	#include <QGraphicsVideoItem>
26 	#include <QMediaPlayer>
27 	#include <QTimer>
28 	#include <QApplication>
29 	#include "StelApp.hpp"
30 	#include "StelFader.hpp"
31 #endif
32 
33 
StelVideoMgr()34 StelVideoMgr::StelVideoMgr() : StelModule()
35 {
36     setObjectName("StelVideoMgr");
37 #ifdef ENABLE_MEDIA
38     // in case the property has not been set, getProperty() returns invalid.
39     verbose= (qApp->property("verbose") == true);
40 #endif
41 }
42 
43 #ifdef ENABLE_MEDIA
~StelVideoMgr()44 StelVideoMgr::~StelVideoMgr()
45 {
46 	for (const auto& id : videoObjects.keys())
47 	{
48 		dropVideo(id);
49 	}
50 }
51 
loadVideo(const QString & filename,const QString & id,const float x,const float y,const bool show,const float alpha)52 void StelVideoMgr::loadVideo(const QString& filename, const QString& id, const float x, const float y, const bool show, const float alpha)
53 {
54 	if (videoObjects.contains(id))
55 	{
56 		qWarning() << "[StelVideoMgr] Video object with ID" << id << "already exists, dropping it";
57 		dropVideo(id);
58 	}
59 
60 	videoObjects[id] = new VideoPlayer;
61 	videoObjects[id]->videoItem= new QGraphicsVideoItem();
62 	// This sets a tiny size so that if window should appear before proper resize, it should not disturb.
63 	videoObjects[id]->videoItem->setSize(QSizeF(1,1));
64 
65 	videoObjects[id]->player = new QMediaPlayer(Q_NULLPTR, QMediaPlayer::VideoSurface);
66 	videoObjects[id]->duration=-1; // -1 to signal "unknown".
67 	videoObjects[id]->resolution=QSize(); // initialize with "invalid" empty resolution, we must detect this when player is starting!
68 	videoObjects[id]->keepVisible=false;
69 	videoObjects[id]->needResize=true; // resolution and target frame not yet known.
70 	videoObjects[id]->simplePlay=true;
71 	videoObjects[id]->targetFrameSize=QSizeF(); // start with invalid, depends on parameters given in playVideo(), playPopoutVideo() and resolution detected only after playing started.
72 	videoObjects[id]->popupOrigin=QPointF();
73 	videoObjects[id]->popupTargetCenter=QPointF();
74 	videoObjects[id]->player->setProperty("Stel_id", id); // allow tracking of log messages and access of members.
75 	videoObjects[id]->player->setVideoOutput(videoObjects[id]->videoItem);
76 	videoObjects[id]->videoItem->setOpacity(alpha);
77 #ifndef Q_OS_WIN
78 	// There is a notable difference: on Windows this causes a crash. On Linux, it is required, else the movie frame is visible before proper resize.
79 	videoObjects[id]->videoItem->setVisible(show);
80 #endif
81 	videoObjects[id]->lastPos=-1;
82 
83 	// A few connections are not really needed, they are signals we don't use. TBD: Remove or keep commented out?
84 	connect(videoObjects[id]->player, SIGNAL(bufferStatusChanged(int)), this, SLOT(handleBufferStatusChanged(int)));
85 	connect(videoObjects[id]->player, SIGNAL(durationChanged(qint64)), this, SLOT(handleDurationChanged(qint64))); // (CRITICALLY IMPORTANT!)
86 	connect(videoObjects[id]->player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(handleError(QMediaPlayer::Error)));
87 	connect(videoObjects[id]->player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(handleMediaStatusChanged(QMediaPlayer::MediaStatus)));
88 	//connect(videoObjects[id]->player, SIGNAL(positionChanged(qint64)), this, SLOT(handlePositionChanged(qint64)));
89 	// we test isSeekable() where needed, so only debug log entry. --> And we may use the signal however now during blocking load below!
90 	connect(videoObjects[id]->player, SIGNAL(seekableChanged(bool)), this, SLOT(handleSeekableChanged(bool)));
91 	connect(videoObjects[id]->player, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(handleStateChanged(QMediaPlayer::State)));
92 	connect(videoObjects[id]->player, SIGNAL(videoAvailableChanged(bool)), this, SLOT(handleVideoAvailableChanged(bool)));
93 	connect(videoObjects[id]->player, SIGNAL(audioAvailableChanged(bool)), this, SLOT(handleAudioAvailableChanged(bool)));
94 	connect(videoObjects[id]->player, SIGNAL(mutedChanged(bool)), this, SLOT(handleMutedChanged(bool)));
95 	connect(videoObjects[id]->player, SIGNAL(volumeChanged(int)), this, SLOT(handleVolumeChanged(int)));
96 	connect(videoObjects[id]->player, SIGNAL(availabilityChanged(bool)), this, SLOT(handleAvailabilityChanged(bool)));
97 	connect(videoObjects[id]->player, SIGNAL(availabilityChanged(QMultimedia::AvailabilityStatus)), this, SLOT(handleAvailabilityChanged(QMultimedia::AvailabilityStatus)));
98 
99 	// Only this is triggered also on Windows. Lets us read resolution etc. (CRITICALLY IMPORTANT!)
100 	connect(videoObjects[id]->player, SIGNAL(metaDataChanged()), this, SLOT(handleMetaDataChanged()));
101 	// That signal would require less overhead, but is not triggered under Windows and apparently also not on MacOS X. (QTBUG-42034.)
102 	// If this becomes available/bugfixed, it should be preferred as being more elegant.
103 	// connect(videoObjects[id]->player, SIGNAL(metaDataChanged(QString,QVariant)), this, SLOT(handleMetaDataChanged(QString,QVariant)));
104 
105 	// We need an absolute pathname here.
106 	QMediaContent content(QUrl::fromLocalFile(QFileInfo(filename).absoluteFilePath()));
107 	videoObjects[id]->player->setMedia(content);
108 	if (verbose)
109 	{
110 		qDebug() << "Loading " << content.canonicalUrl();
111 		qDebug() << "Media Resources queried from player:";
112 		qDebug() << "\tSTATUS:        " << videoObjects[id]->player->mediaStatus();
113 		qDebug() << "\tFile:          " << videoObjects[id]->player->currentMedia().canonicalUrl();
114 	}
115 //	qDebug() << "scene->addItem...";
116 	StelMainView::getInstance().scene()->addItem(videoObjects[id]->videoItem);
117 //	qDebug() << "scene->addItem OK";
118 
119 	videoObjects[id]->videoItem->setPos(x, y);
120 	// DEFAULT SIZE: show a tiny frame. This gets updated to native resolution as soon as resolution becomes known. Needed?
121 	//videoObjects[id]->videoItem->setSize(QSizeF(1, 1));
122 
123 	// after many troubles with incompletely loaded files we attempt a blocking load from https://wiki.qt.io/Seek_in_Sound_File
124 	// This may be no longer required. But please keep the block here for testing/reactivation if necessary.
125 //	if (! videoObjects[id]->player->isSeekable())
126 //	{
127 //		qDebug() << "Not Seekable!";
128 //		if (verbose)
129 //			qDebug() << "Blocking load ...";
130 //		QEventLoop loop;
131 //		QTimer timer;
132 //		qDebug() << "Not Seekable: setSingleShot";
133 //		timer.setSingleShot(true);
134 //		timer.setInterval(5000); // 5 seconds, may be too long?
135 //		qDebug() << "Not Seekable: connect...";
136 //		loop.connect(&timer, SIGNAL (timeout()), &loop, SLOT (quit()) );
137 //		loop.connect(videoObjects[id]->player, SIGNAL (seekableChanged(bool)), &loop, SLOT (quit()));
138 //		qDebug() << "Not Seekable: loop...";
139 //		loop.exec();
140 //		if (verbose)
141 //			qDebug() << "Blocking load finished, should be seekable now or 5s are over.";
142 //	}
143 
144 	if (verbose)
145 		qDebug() << "Loaded video" << id << "for pos " << x << "/" << y << "Size" << videoObjects[id]->videoItem->size();
146 	videoObjects[id]->player->setPosition(0); // This should force triggering a metadataAvailable() with resolution update.
147 	if (show)
148 		videoObjects[id]->player->play();
149 	else
150 		videoObjects[id]->player->pause();
151 }
152 
playVideo(const QString & id,const bool keepVisibleAtEnd)153 void StelVideoMgr::playVideo(const QString& id, const bool keepVisibleAtEnd)
154 {
155 	if (videoObjects.contains(id))
156 	{
157 		videoObjects[id]->keepVisible=keepVisibleAtEnd;
158 		if (videoObjects[id]->player!=Q_NULLPTR)
159 		{
160 			// if already playing, stop and play from the start
161 			if (videoObjects[id]->player->state() == QMediaPlayer::PlayingState)
162 			{
163 				videoObjects[id]->player->stop();
164 			}
165 #ifndef Q_OS_WIN
166 			// On Linux, we may have made movie frame invisible during loadVideo().
167 			videoObjects[id]->videoItem->setVisible(true);
168 #endif
169 
170 			// otherwise just play it, or resume playing paused video.
171 			if (videoObjects[id]->player->state() == QMediaPlayer::PausedState)
172 				videoObjects[id]->lastPos=videoObjects[id]->player->position() - 1;
173 			else
174 				videoObjects[id]->lastPos=-1;
175 
176 			videoObjects[id]->simplePlay=true;
177 			videoObjects[id]->player->play();
178 			if (verbose)
179 				qDebug() << "StelVideoMgr::playVideo(): playing " << id << videoObjects[id]->player->state() << " - media: " << videoObjects[id]->player->mediaStatus();
180 		}
181 	}
182 	else qDebug() << "StelVideoMgr::playVideo(" << id << "): no such video";
183 }
184 
185 
186 //! Play a video which has previously been loaded with loadVideo with a complex start/end effect.
187 //! The video appears to grow out from @param fromX/ @param fromY
188 //! within @param popupDuration to size @param finalSizeX/@param finalSizeY, and
189 //! shrinks back towards @param fromX/@param fromY at the end during @param popdownDuration.
190 //! @param id the identifier used when @name loadVideo() was called
191 //! @param fromX X position of starting point, counted from left of window. May be absolute pixel coordinate (if >1) or relative to screen size (0<X<1)
192 //! @param fromY Y position of starting point, counted from top of window. May be absolute pixel coordinate (if >1) or relative to screen size (0<Y<1)
193 //! @param atCenterX X position of center of final video frame, counted from left of window. May be absolute pixel coordinate (if >1) or relative to screen size (0<X<1)
194 //! @param atCenterY Y position of center of final video frame, counted from top of window. May be absolute pixel coordinate (if >1) or relative to screen size (0<Y<1)
195 //! @param finalSizeX X size (width)  of final video frame. May be absolute (if >1) or relative to window size (0<X<1). If -1, scale proportional from @param finalSizeY.
196 //! @param finalSizeY Y size (height) of final video frame. May be absolute (if >1) or relative to window size (0<Y<1). If -1, scale proportional from @param finalSizeX.
197 //! @param popupDuration duration of growing start transition (seconds)
198 //! @param popdownDuration duration of shrinking end transition (seconds)
199 //! @param frozenInTransition true if video should be paused during growing/shrinking transition.
playVideoPopout(const QString & id,float fromX,float fromY,float atCenterX,float atCenterY,float finalSizeX,float finalSizeY,float popupDuration,bool frozenInTransition)200 void StelVideoMgr::playVideoPopout(const QString& id, float fromX, float fromY, float atCenterX, float atCenterY,
201 		     float finalSizeX, float finalSizeY, float popupDuration, bool frozenInTransition)
202 {
203 	if (verbose)
204 		qDebug() << "\n\n====Configuring playVideoPopout(): " << id;
205 	if (videoObjects.contains(id))
206 	{
207 		videoObjects[id]->keepVisible=frozenInTransition;
208 		if (videoObjects[id]->player!=Q_NULLPTR)
209 		{
210 			// if already playing, stop and play from the start
211 			if (videoObjects[id]->player->state() == QMediaPlayer::PlayingState)
212 			{
213 				qDebug() << "playVideoPopout(): stop the playing video";
214 				videoObjects[id]->player->stop();
215 			}
216 
217 			// prepare (1) target frame size, (2) XY start position, and (3) end position:
218 			// (1) Target frame size.
219 			// if finalSizeX or finalSizeY <= 1 we scale proportional to mainview!
220 			// Note that finalSizeX or finalSizeY thus cannot be set to 1.0, i.e. single-pixel rows/columns!
221 			// This is likely not tragic, else set to 1.0001
222 			int viewportWidth=StelMainView::getInstance().size().width();
223 			int viewportHeight=StelMainView::getInstance().size().height();
224 
225 			if (finalSizeX>0 && finalSizeX<=1)
226 				finalSizeX*=viewportWidth;
227 			if (finalSizeY>0 && finalSizeY<=1)
228 				finalSizeY*=viewportHeight;
229 
230 			if (verbose)
231 				qDebug() << "playVideoPopout() finalSize: "<< finalSizeX << "x" << finalSizeY;
232 
233 			QSize videoSize=videoObjects[id]->resolution;
234 			if (verbose)
235 				qDebug() << "playVideoPopout(): video resolution detected=" << videoSize;
236 
237 			if (!videoSize.isValid() && (finalSizeX==-1 || finalSizeY==-1))
238 			{
239 				// This should not happen, is a real problem.
240 				qDebug() << "StelVideoMgr::playVideoPopout()" << id << ": size (resolution) not yet determined, cannot resize with -1 argument. Sorry, command stops here...";
241 				return;
242 			}
243 			float aspectRatio=(float)videoSize.width()/(float)videoSize.height();
244 			if (verbose)
245 				qDebug() << "StelVideoMgr::playVideoPopout(): computed aspect ratio:" << aspectRatio;
246 			if (finalSizeX!=-1.0f && finalSizeY!=-1.0f)
247 				videoObjects[id]->videoItem->setAspectRatioMode(Qt::IgnoreAspectRatio);
248 			else
249 			{
250 				videoObjects[id]->videoItem->setAspectRatioMode(Qt::KeepAspectRatio);
251 				if (finalSizeX==-1.0f && finalSizeY==-1.0f)
252 				{
253 					finalSizeX=videoSize.height();
254 					finalSizeY=videoSize.width();
255 				}
256 				else if (finalSizeY==-1.0f)
257 					finalSizeY=finalSizeX/aspectRatio;
258 				else if (finalSizeX==-1.0f)
259 					finalSizeX=finalSizeY*aspectRatio;
260 			}
261 			if (verbose)
262 				qDebug() << "StelVideoMgr::playVideoPopout(): Resetting target frame size to :" << finalSizeX << "x" << finalSizeY;
263 			videoObjects[id]->targetFrameSize= QSizeF(finalSizeX, finalSizeY); // size in Pixels
264 
265 			// (2) start position:
266 			if (fromX>0 && fromX<1)
267 				fromX *= viewportWidth;
268 			if (fromY>0 && fromY<1)
269 				fromY *= viewportHeight;
270 			videoObjects[id]->popupOrigin= QPointF(fromX, fromY); // Pixel coordinates of popout point.
271 			if (verbose)
272 				qDebug() << "StelVideoMgr::playVideoPopout(): Resetting start position to :" << fromX << "/" << fromY;
273 
274 
275 			// (3) center of target frame
276 			if (atCenterX>0 && atCenterX<1)
277 				atCenterX *= viewportWidth;
278 			if (atCenterY>0 && atCenterY<1)
279 				atCenterY *= viewportHeight;
280 			videoObjects[id]->popupTargetCenter= QPointF(atCenterX, atCenterY); // Pixel coordinates of frame center
281 			if (verbose)
282 				qDebug() << "StelVideoMgr::playVideoPopout(): Resetting target position to :" << atCenterX << "/" << atCenterY;
283 
284 			// (4) configure fader
285 			videoObjects[id]->fader.setDuration(1000.0f*popupDuration);
286 
287 			// (5) TRIGGER!
288 			videoObjects[id]->simplePlay=false;
289 			videoObjects[id]->fader=true;
290 			videoObjects[id]->videoItem->setVisible(true);
291 			videoObjects[id]->lastPos=-1;
292 			videoObjects[id]->player->setPosition(0);
293 			videoObjects[id]->player->play();
294 
295 			if (verbose)
296 				qDebug() << "StelVideoMgr::playVideoPopout(): fader triggered.";
297 		}
298 	}
299 	else qDebug() << "StelVideoMgr::playVideoPopout(" << id << "): no such video";
300 }
301 
302 
pauseVideo(const QString & id)303 void StelVideoMgr::pauseVideo(const QString& id)
304 {
305 	if (videoObjects.contains(id))
306 	{
307 		if (videoObjects[id]->player!=Q_NULLPTR)
308 		{
309 			// Maybe we can only pause while already playing?
310 			if (videoObjects[id]->player->state()==QMediaPlayer::StoppedState)
311 				videoObjects[id]->player->play();
312 
313 			if (verbose)
314 				qDebug() << "StelVideoMgr::pauseVideo() ...";
315 			videoObjects[id]->player->pause();
316 		}
317 	}
318 	else qDebug() << "StelVideoMgr::pauseVideo()" << id << ": no such video";
319 }
320 
stopVideo(const QString & id)321 void StelVideoMgr::stopVideo(const QString& id)
322 {
323 	if (videoObjects.contains(id))
324 	{
325 		if (videoObjects[id]->player!=Q_NULLPTR)
326 		{
327 			videoObjects[id]->player->stop();
328 		}
329 	}
330 	else qDebug() << "StelVideoMgr::stopVideo()" << id << ": no such video";
331 }
332 
seekVideo(const QString & id,const qint64 ms,bool pause)333 void StelVideoMgr::seekVideo(const QString& id, const qint64 ms, bool pause)
334 {
335 	if (verbose)
336 		qDebug() << "StelVideoMgr::seekVideo: " << id << " to:" << ms <<  (pause ? " (pausing)" : " (playing)");
337 	if (videoObjects.contains(id))
338 	{
339 		if (videoObjects[id]->player!=Q_NULLPTR)
340 		{
341 			if (videoObjects[id]->player->isSeekable())
342 			{
343 				videoObjects[id]->player->setPosition(ms);
344 				// Seek capability depends on the backend used and likely media codec.
345 			}
346 			else
347 			{
348 				qDebug() << "[StelVideoMgr] Cannot seek media source" << id;
349 			}
350 			// visual update only happens if we play. So even with pause set, we must play to freeze the frame!
351 			videoObjects[id]->player->play();
352 			if (pause)
353 				videoObjects[id]->player->pause();
354 		}
355 	}
356 	else qDebug() << "StelVideoMgr::seekVideo()" << id << ": no such video";
357 }
358 
dropVideo(const QString & id)359 void StelVideoMgr::dropVideo(const QString& id)
360 {
361 	if (!videoObjects.contains(id))
362 		return;
363 	if (videoObjects[id]->player!=Q_NULLPTR)
364 	{
365 		if (verbose)
366 			qDebug() << "About to drop (unload) video " << id << "(" << videoObjects[id]->player->mediaStatus() << ")";
367 		videoObjects[id]->player->stop();
368 		StelMainView::getInstance().scene()->removeItem(videoObjects[id]->videoItem);
369 		delete videoObjects[id]->player;
370 		delete videoObjects[id]->videoItem;
371 		delete videoObjects[id];
372 		videoObjects.remove(id);
373 	}
374 }
375 
376 // setVideoXY(100, 200, false): absolute, as before
377 // setVideoXY(100, 200, true): shift 100 right, 200 down
378 // setVideoXY(0.5, 0.25, false): (on fullHD), set to (960/270)
379 // setVideoXY(0.5, 0.25, true): (on fullHD), shift by (960/270)
380 // setVideoXY(600, 0.25, false): (on fullHD), set to (600/270)
381 // setVideoXY(600, 0.25, true): (on fullHD), shift by (600/270)
setVideoXY(const QString & id,const float x,const float y,const bool relative)382 void StelVideoMgr::setVideoXY(const QString& id, const float x, const float y, const bool relative)
383 {
384 	if (videoObjects.contains(id))
385 	{
386 		if (videoObjects[id]->videoItem!=Q_NULLPTR)
387 		{
388 			// if w or h < 1 we scale proportional to mainview!
389 			int viewportWidth=StelMainView::getInstance().size().width();
390 			int viewportHeight=StelMainView::getInstance().size().height();
391 			float newX=x;
392 			float newY=y;
393 			if (x>-1 && x<1)
394 				newX *= viewportWidth;
395 			if (y>-1 && y<1)
396 				newY *= viewportHeight;
397 			if (relative)
398 			{
399 				QPointF pos = videoObjects[id]->videoItem->pos();
400 				videoObjects[id]->videoItem->setPos(pos.x()+newX, pos.y()+newY);
401 			}
402 			else
403 				videoObjects[id]->videoItem->setPos(newX, newY);
404 			if (verbose)
405 				qDebug() << "Setting video XY= " << newX << "/" << newY << (relative? "(relative)":"");
406 		}
407 	}
408 	else qDebug() << "StelVideoMgr::setVideoXY()" << id << ": no such video";
409 }
410 
setVideoAlpha(const QString & id,const float alpha)411 void StelVideoMgr::setVideoAlpha(const QString& id, const float alpha)
412 {
413 	if (videoObjects.contains(id))
414 	{
415 		if (videoObjects[id]->videoItem!=Q_NULLPTR)
416 		{
417 			videoObjects[id]->videoItem->setOpacity(alpha);
418 		}
419 	}
420 	else qDebug() << "StelVideoMgr::setVideoAlpha()" << id << ": no such video";
421 }
422 
resizeVideo(const QString & id,float w,float h)423 void StelVideoMgr::resizeVideo(const QString& id, float w, float h)
424 {
425 	if (videoObjects.contains(id))
426 	{
427 		if (videoObjects[id]->videoItem!=Q_NULLPTR)
428 		{
429 			// if w or h <= 1 we scale proportional to mainview!
430 			// Note that w or h thus cannot be set to 1.0, i.e. single-pixel rows/columns!
431 			// This is likely not tragic, else set to 1.0001
432 			int viewportWidth=StelMainView::getInstance().size().width();
433 			int viewportHeight=StelMainView::getInstance().size().height();
434 
435 			if (w>0 && w<=1)
436 				w*=viewportWidth;
437 			if (h>0 && h<=1)
438 				h*=viewportHeight;
439 
440 			QSize videoSize=videoObjects[id]->resolution;
441 			if (verbose)
442 				qDebug() << "resizeVideo(): native resolution=" << videoSize;
443 
444 			if (!videoSize.isValid() && (w==-1 || h==-1))
445 			{
446 				if (verbose)
447 					qDebug() << "StelVideoMgr::resizeVideo()" << id << ": size not yet determined, cannot resize with -1 argument. We do that in next update().";
448 				// mark necessity of deferred resize.
449 				videoObjects[id]->needResize=true;
450 				videoObjects[id]->targetFrameSize=QSizeF(w, h); // w|h can be -1 or >1, no longer 0<(w|h)<1.
451 				return;
452 			}
453 			float aspectRatio=(float)videoSize.width()/(float)videoSize.height();
454 			if (verbose)
455 				qDebug() << "aspect ratio:" << aspectRatio; // 1 for invalid size.
456 			if (w!=-1.0f && h!=-1.0f)
457 				videoObjects[id]->videoItem->setAspectRatioMode(Qt::IgnoreAspectRatio);
458 			else
459 			{
460 				videoObjects[id]->videoItem->setAspectRatioMode(Qt::KeepAspectRatio);
461 				if (w==-1.0f && h==-1.0f)
462 				{
463 					h=videoSize.height();
464 					w=videoSize.width();
465 				}
466 				else if (h==-1.0f)
467 					h=w/aspectRatio;
468 				else if (w==-1.0f)
469 					w=h*aspectRatio;
470 			}
471 			if (verbose)
472 				qDebug() << "Resizing to:" << w << "x" << h;
473 			videoObjects[id]->targetFrameSize=QSizeF(w, h); // w|h cannot be -1 or >1 here.
474 			videoObjects[id]->videoItem->setSize(QSizeF(w, h));
475 			videoObjects[id]->needResize=false;
476 		}
477 	}
478 	else qDebug() << "StelVideoMgr::resizeVideo()" << id << ": no such video";
479 }
480 
showVideo(const QString & id,const bool show)481 void StelVideoMgr::showVideo(const QString& id, const bool show)
482 {
483 	if (videoObjects.contains(id))
484 	{
485 		if (videoObjects[id]->videoItem!=Q_NULLPTR)
486 		{
487 			videoObjects[id]->videoItem->setVisible(show);
488 		}
489 	}
490 	else qDebug() << "StelVideoMgr::showVideo()" << id << ": no such video";
491 }
492 
getVideoDuration(const QString & id) const493 qint64 StelVideoMgr::getVideoDuration(const QString& id) const
494 {
495 	if (videoObjects.contains(id))
496 	{
497 		return videoObjects[id]->duration;
498 	}
499 	else qDebug() << "StelVideoMgr::getDuration()" << id << ": no such video";
500 	return -1;
501 }
502 
getVideoPosition(const QString & id) const503 qint64 StelVideoMgr::getVideoPosition(const QString& id) const
504 {
505 	if (videoObjects.contains(id))
506 	{
507 		return videoObjects[id]->player->position();
508 	}
509 	else qDebug() << "StelVideoMgr::getPosition()" << id << ": no such video";
510 	return -1;
511 }
512 
513 //! returns native resolution (in pixels) of loaded video. Returned value may be invalid before video has been fully loaded.
getVideoResolution(const QString & id) const514 QSize StelVideoMgr::getVideoResolution(const QString& id) const
515 {
516 	if (videoObjects.contains(id))
517 	{
518 		return videoObjects[id]->resolution;
519 	}
520 	else qDebug() << "StelVideoMgr::getResolution()" << id << ": no such video";
521 	return QSize();
522 }
523 
getVideoWidth(const QString & id) const524 int StelVideoMgr::getVideoWidth(const QString& id) const
525 {
526 	if (videoObjects.contains(id))
527 	{
528 		if (videoObjects[id]->resolution.isValid())
529 			return videoObjects[id]->resolution.width();
530 		else
531 			return -1;
532 	}
533 	else qDebug() << "StelVideoMgr::getWidth()" << id << ": no such video";
534 	return -1;
535 }
536 
getVideoHeight(const QString & id) const537 int StelVideoMgr::getVideoHeight(const QString& id) const
538 {
539 	if (videoObjects.contains(id))
540 	{
541 		if (videoObjects[id]->resolution.isValid())
542 			return videoObjects[id]->resolution.height();
543 		else
544 			return -1;
545 	}
546 	else qDebug() << "StelVideoMgr::getHeight()" << id << ": no such video";
547 	return -1;
548 }
549 
550 
muteVideo(const QString & id,bool mute)551 void StelVideoMgr::muteVideo(const QString& id, bool mute)
552 {
553 	if (videoObjects.contains(id))
554 	{
555 		if (videoObjects[id]->player!=Q_NULLPTR)
556 		{
557 			videoObjects[id]->player->setMuted(mute);
558 		}
559 	}
560 	else qDebug() << "StelVideoMgr::mute()" << id << ": no such video";
561 }
562 
setVideoVolume(const QString & id,int newVolume)563 void StelVideoMgr::setVideoVolume(const QString& id, int newVolume)
564 {
565 	if (videoObjects.contains(id))
566 	{
567 		if (videoObjects[id]->player!=Q_NULLPTR)
568 		{
569 			videoObjects[id]->player->setVolume(newVolume);
570 		}
571 	}
572 	else qDebug() << "StelVideoMgr::setVolume()" << id << ": no such video";
573 }
574 
getVideoVolume(const QString & id) const575 int StelVideoMgr::getVideoVolume(const QString& id) const
576 {
577 	int volume=-1;
578 	if (videoObjects.contains(id))
579 	{
580 		if (videoObjects[id]->player!=Q_NULLPTR)
581 		{
582 			volume=videoObjects[id]->player->volume();
583 		}
584 	}
585 	else qDebug() << "StelVideoMgr::getVolume()" << id << ": no such video";
586 	return volume;
587 }
588 
isVideoPlaying(const QString & id) const589 bool StelVideoMgr::isVideoPlaying(const QString& id) const
590 {
591 	bool playing=false;
592 	if (videoObjects.contains(id))
593 	{
594 		if (videoObjects[id]->player!=Q_NULLPTR)
595 		{
596 			playing= (videoObjects[id]->player->state() == QMediaPlayer::PlayingState );
597 		}
598 	}
599 	else qDebug() << "StelVideoMgr::isPlaying()" << id << ": no such video";
600 	return playing;
601 }
602 
603 
604 /* *************************************************
605  * Signal handlers for all signals of QMediaPlayer. Usually for now this only writes a message to logfile.
606  */
handleAudioAvailableChanged(bool available)607 void StelVideoMgr::handleAudioAvailableChanged(bool available)
608 {
609 	if (verbose)
610 		qDebug() << "StelVideoMgr: " << this->sender()->property("Stel_id").toString() << ": Audio is now available:" << available;
611 }
612 // It seems this is never called in practice.
handleBufferStatusChanged(int percentFilled)613 void StelVideoMgr::handleBufferStatusChanged(int percentFilled)
614 {
615 	if (verbose)
616 		qDebug() << "StelVideoMgr: " << QObject::sender()->property("Stel_id").toString() << ": Buffer filled (%):" << percentFilled;
617 }
618 
handleDurationChanged(qint64 duration)619 void StelVideoMgr::handleDurationChanged(qint64 duration)
620 {
621 	QString id=QObject::sender()->property("Stel_id").toString();
622 	if (verbose)
623 		qDebug() << "StelVideoMgr: " << id << ": Duration changed to:" << duration;
624 	if (videoObjects.contains(id))
625 	{
626 		videoObjects[id]->duration=duration;
627 	}
628 }
handleError(QMediaPlayer::Error error)629 void StelVideoMgr::handleError(QMediaPlayer::Error error)
630 {
631 	if (verbose)
632 		qDebug() << "StelVideoMgr: " << QObject::sender()->property("Stel_id").toString() << ":  error:" << error;
633 }
634 
635 /*
636 // This gets called in loadVideo with player->setMedia(content). Unnecessary, disabled.
637 void StelVideoMgr::handleCurrentMediaChanged(const QMediaContent & media)
638 {
639 	qDebug() << "QMediaplayer: " << QObject::sender()->property("Stel_id").toString() << ": Current media changed:" << media.canonicalUrl();
640 }
641 
642 // This gets called in loadVideo with player->setMedia(content). Unnecessary, disabled.
643 void StelVideoMgr::handleMediaChanged(const QMediaContent & media)
644 {
645 	qDebug() << "QMediaPlayer: " << QObject::sender()->property("Stel_id").toString() << ": Media changed:" << media.canonicalUrl();
646 }
647 */
648 
649 // This may have been useful to trigger the pause-at-end if it was fast enough.
650 // It seems that this is too slow! At EndOfMedia the player window disappears, then reappears. This is ugly!
651 // Currently we deal with polling status changes within update().
handleMediaStatusChanged(QMediaPlayer::MediaStatus status)652 void StelVideoMgr::handleMediaStatusChanged(QMediaPlayer::MediaStatus status) // debug-log messages
653 {
654 	QString id=QObject::sender()->property("Stel_id").toString();
655 	if (verbose)
656 		qDebug() << "StelVideoMgr: " << id << ":  MediaStatus changed to:" << status;
657 }
658 
handleMutedChanged(bool muted)659 void StelVideoMgr::handleMutedChanged(bool muted)
660 {
661 	if (verbose)
662 		qDebug() << "StelVideoMgr: " << QObject::sender()->property("Stel_id").toString() << ":  mute changed:" << muted;
663 }
664 
665 
666 
667 /* // USELESS. This is called not often enough (could be configured), but update() is better suited to check for video-at-end.
668 void StelVideoMgr::handlePositionChanged(qint64 position)
669 {
670     QString senderId=QObject::sender()->property("Stel_id").toString();
671     qDebug() << "StelVideoMgr: " << senderId << ":  position changed to (ms):" << position;
672     // We could deal with the keep-visible here, however this is not called often enough by default, and we have update anyways
673     if ((position==videoObjects[senderId]->duration) && (videoObjects[senderId]->keepVisible))
674     {
675         videoObjects[senderId]->player->setPosition(videoObjects[senderId]->duration - 1);
676         videoObjects[senderId]->player->pause();
677         qDebug() << " ---> paused at end as requested" ;
678     }
679 }
680 */
681 
682 // USELESS?
handleSeekableChanged(bool seekable)683 void StelVideoMgr::handleSeekableChanged(bool seekable)
684 {
685 	if (verbose)
686 		qDebug() << "StelVideoMgr: handleSeekableChanged()" << QObject::sender()->property("Stel_id").toString() << ":  seekable changed to:" << seekable;
687 }
handleStateChanged(QMediaPlayer::State state)688 void StelVideoMgr::handleStateChanged(QMediaPlayer::State state)
689 {
690 	QString senderId=QObject::sender()->property("Stel_id").toString();
691 	if (verbose)
692 		qDebug() << "StelVideoMgr: " << senderId << ":  state changed to:" << state
693 			 << "(Media Status: " << videoObjects[senderId]->player->mediaStatus() << ")";
694 }
695 
handleVideoAvailableChanged(bool videoAvailable)696 void StelVideoMgr::handleVideoAvailableChanged(bool videoAvailable)
697 {
698 	QString senderId=QObject::sender()->property("Stel_id").toString();
699 	if (verbose)
700 		qDebug() << "StelVideoMgr: " << senderId << ":  Video available:" << videoAvailable;
701 	// Sometimes it appears the video has not fully loaded when popup stars, and the movie is not shown.
702 	// Maybe force showing here? --> NO, breaks our own logic...
703 	//videoObjects[senderId]->videoItem->setVisible(videoAvailable);
704 }
705 
handleVolumeChanged(int volume)706 void StelVideoMgr::handleVolumeChanged(int volume)
707 {
708 	if (verbose)
709 		qDebug() << "StelVideoMgr: " << QObject::sender()->property("Stel_id").toString() << ":  volume changed to:" << volume;
710 }
711 
handleAvailabilityChanged(bool available)712 void StelVideoMgr::handleAvailabilityChanged(bool available)
713 {
714 	if (verbose)
715 		qDebug() << "StelVideoMgr::handleAvailabilityChanged(bool) " << QObject::sender()->property("Stel_id").toString() << ":  available:" << available;
716 }
717 
handleAvailabilityChanged(QMultimedia::AvailabilityStatus availability)718 void StelVideoMgr::handleAvailabilityChanged(QMultimedia::AvailabilityStatus availability)
719 {
720 	if (verbose)
721 		qDebug() << "StelVideoMgr::availabilityChanged(QMultimedia::AvailabilityStatus) " << QObject::sender()->property("Stel_id").toString() << ":  availability:" << availability;
722 }
723 
724 
725 
726 // The signal sequence (at least on Windows7/MinGW/Qt5.4) seems to be:
727 // metadatachanged() as soon as video has been loaded. But Result: no metadata.
728 // After media has started playing and frame is already growing,
729 // audioAvailable() (but no audio in this movie...)
730 // videoAvailable() (true)
731 // durationChanged() --> only now duration becomes known!
732 // status changed: QMediaPlayer::BufferedMedia
733 // metadataAvailablechanged(true): Duration, PixelAspectRatio(unknown!), Resolution(unknown!), Videobitrate, VideoFramerate
734 // metadataChanged() now true, and finally here also PixelAspectRatio and Resolution are known.
735 // Then periodically, positionChanged(). We can skip that because in update() we can check position() if required.
736 // Sequence is the same on Win/MSVC and Qt5.3.2, so metadataChanged(.,.) is NOT called on Windows.
737 // This is also already observed on MacOSX and listed as QTBUG-42034.
738 // This signal is sent several times during replay because min/max rates often change, and we must go through the metadata list each time. We avoid setting resolution more than once.
handleMetaDataChanged()739 void StelVideoMgr::handleMetaDataChanged()
740 {
741 	QString id=QObject::sender()->property("Stel_id").toString();
742 	if (verbose)
743 		qDebug() << "StelVideoMgr: " << id << ":  Metadata changed (global notification).";
744 
745 	if (videoObjects.contains(id) && videoObjects[id]->player->isMetaDataAvailable())
746 	{
747 		if (verbose)
748 			qDebug() << "StelVideoMgr: " << id << ":  Following metadata are available:";
749 		QStringList metadataList=videoObjects[id]->player->availableMetaData();
750 		for (const auto& md : metadataList)
751 		{
752 			QString key = md.toLocal8Bit().constData();
753 			if (verbose)
754 				qDebug() << "\t" << key << "==>" << videoObjects[id]->player->metaData(key);
755 
756 			if ((key=="Resolution") && !(videoObjects[id]->resolution.isValid()))
757 			{
758 				if (verbose)
759 					qDebug() << "StelVideoMgr: Resolution becomes available: " << videoObjects[id]->player->metaData(key).toSize();
760 				videoObjects[id]->resolution=videoObjects[id]->player->metaData(key).toSize();
761 			}
762 		}
763 	}
764 	else if (videoObjects.contains(id) && !(videoObjects[id]->player->isMetaDataAvailable()) &&verbose)
765 		qDebug() << "StelVideoMgr::handleMetaDataChanged()" << id << ": no metadata now.";
766 	else
767 		qDebug() << "StelVideoMgr::handleMetaDataChanged()" << id << ": no such video - this is absurd.";
768 }
769 
770 
771 
772 /*
773 // Either this signal or metadataChanged() must be evaluated. On Linux, both are fired, on Windows only the (void) version.
774 // I (GZ) cannot say which may work on MacOSX, but will disable this for now, the required data handling is done in handleMetaDataChanged(void).
775 void StelVideoMgr::handleMetaDataChanged(const QString & key, const QVariant & value)
776 {
777     qDebug() << "!!! StelVideoMgr::handleMetadataChanged(.,.): Is this called on Windows when built with MSVC? ";  // NOT WITH MinGW and Qt5.4!!!
778     qDebug() << "THIS IS TO ENSURE YOU SEE A CRASH! (If you see it, be happy!) CURRENTLY THE SIGNAL IS NOT SENT ON WINDOWS WHEN BUILT WITH minGW Qt5.4 and not with MSVC on Qt5.3.2";
779     Q_ASSERT(0); // Remove the Q_ASSERT and write a comment that it works on (which) Windows/Mac/...!
780     QString id=QObject::sender()->property("Stel_id").toString();
781     qDebug() << "StelVideoMgr: " << id << ":  Metadata change:" << key << "=>" << value;
782     if (key=="Resolution")
783     {
784         qDebug() << "hah, resolution becomes available!";
785         if (videoObjects.contains(id))
786         {
787             videoObjects[id]->resolution=value.toSize();
788             videoObjects[id]->videoItem->setSize(videoObjects[id]->resolution);
789         }
790 	else qDebug() << "StelVideoMgr::handleMetaDataChanged(.,.)" << id << ": no such video - this is absurd.";
791     }
792 }
793 */
794 
795 
796 // update() has only to deal with the faders in all videos, and (re)set positions and sizes of video windows.
update(double deltaTime)797 void StelVideoMgr::update(double deltaTime)
798 {
799 	for (auto voIter = videoObjects.constBegin(); voIter != videoObjects.constEnd(); ++voIter)
800 	{
801 		QMediaPlayer::MediaStatus mediaStatus = (*voIter)->player->mediaStatus();
802 		QString id=voIter.key();
803 		// Maybe we have verbose as int with levels of verbosity, and output the next line with verbose>=2?
804 		if (verbose)
805 			qDebug() << "StelVideoMgr::update() for" << id << ": PlayerState:" << (*voIter)->player->state() << "MediaStatus: " << mediaStatus;
806 
807 		// fader must be updated here, else the video may not be visible when not yet fully loaded?
808 		(*voIter)->fader.update(static_cast<int>(deltaTime*1000));
809 
810 		// It seems we need a more thorough analysis of MediaStatus!
811 		// In all not-ready status we immediately leave further handling, usually in the hope that loading is successful really soon.
812 		switch (mediaStatus)
813 		{
814 			case QMediaPlayer::UnknownMediaStatus:
815 			case QMediaPlayer::NoMedia:
816 			case QMediaPlayer::InvalidMedia:
817 			case QMediaPlayer::LoadingMedia:
818 			case QMediaPlayer::StalledMedia:
819 				if (verbose)
820 					qDebug() << "StelVideoMgr::update(): " << id  << mediaStatus << "\t==> no further update action";
821 				continue;
822 			case QMediaPlayer::LoadedMedia:
823 			case QMediaPlayer::BufferingMedia:
824 			case QMediaPlayer::BufferedMedia:
825 			case QMediaPlayer::EndOfMedia:
826 			default:
827 				break;
828 		}
829 
830 //		if (verbose)
831 //			qDebug() << "update() Still alive";
832 
833 		// First fix targetFrameSize if needed and possible.
834 		if ((*voIter)->needResize && ((*voIter)->resolution.isValid()))
835 		{
836 			// we have buffered our final size (which may be relative to screen size) in targetFrameSize. So, simply
837 			resizeVideo(voIter.key(), (*voIter)->targetFrameSize.width(), (*voIter)->targetFrameSize.height());
838 		}
839 
840 		// if keepVisible, pause video if already close to end.
841 		if ((*voIter)->simplePlay)
842 		{
843 			if ( ((*voIter)->keepVisible) &&  ((*voIter)->duration > 0) &&  ((*voIter)->player->position() >= ((*voIter)->duration - 250))   )
844 			{
845 				if (verbose)
846 					qDebug() << "update(): pausing" << id << "at end";
847 				(*voIter)->player->pause();
848 			}
849 
850 			continue;
851 		}
852 
853 		if ((*voIter)->player->state()==QMediaPlayer::StoppedState)
854 			continue;
855 
856 		// the rest of the loop is only needed if we are in popup playing mode.
857 
858 		QSizeF currentFrameSize= (*voIter)->fader.getInterstate() * (*voIter)->targetFrameSize;
859 		QPointF frameCenter=  (*voIter)->popupOrigin +  ( (*voIter)->popupTargetCenter - (*voIter)->popupOrigin ) *  (*voIter)->fader.getInterstate();
860 		QPointF frameXY=frameCenter - 0.5*QPointF(currentFrameSize.width(), currentFrameSize.height());
861 		(*voIter)->videoItem->setPos(frameXY);
862 		(*voIter)->videoItem->setSize(currentFrameSize);
863 		if (verbose)
864 			qDebug() << "StelVideoMgr::update(): Video" << id << "at" << (*voIter)->player->position()
865 				 << ", player state=" << (*voIter)->player->state() << ", media status=" << (*voIter)->player->mediaStatus();
866 		int newPos=(*voIter)->player->position();
867 //		if ((newPos==(*voIter)->lastPos) && ((*voIter)->player->state()==QMediaPlayer::PlayingState))
868 //		{
869 //			// I (GZ) have no idea how this can happen, but it does, every couple of runs.
870 //			// I see this happen only in the grow-while-play phase, but I see no logical error.
871 //			// It seemed to indicate not-fully-loaded, but this would have been caught in the intro test.
872 //			// But this even can happen if MediaStatus==BufferedMedia, i.e. fully loaded. Really a shame!
873 //			// TODO: check with every version of Qt whether this can still happen.
874 //			// SILLY! Of course if Stellarium framerate > video framerate...
875 //			if (verbose)
876 //			{
877 //				qDebug() << "StelVideoMgr::update(): player state" << (*voIter)->player->state() << "with MediaStatus" << mediaStatus;
878 //				qDebug() << "This should not be: video should play but position" << newPos << "does not increase? Bumping video.";
879 //			}
880 //			//(*voIter)->player->stop(); // GZ Dec2: Do we really need to stop?
881 //			(*voIter)->player->setPosition(newPos+1); // GZ Dec2 flipped 2 lines.
882 //			(*voIter)->player->play();
883 //			qDebug() << "We had an issue with a stuck mediaplayer, should play again!";
884 //		}
885 		(*voIter)->lastPos=newPos;
886 
887 		if (verbose)
888 			qDebug() << "StelVideoMgr::update(): fader at " << (*voIter)->fader.getInterstate()  << "; update frame size " << currentFrameSize << "to XY" << frameXY;
889 
890 		// if we want still videos during transition, we must grow/shrink paused, and run only when reached full size.
891 		// We must detect a frame close to end, pause there, and trigger the fader back to 0.
892 		if ((*voIter)->keepVisible)
893 		{
894 			if ((*voIter)->fader.getInterstate()==0.0f)
895 			{ // interstate is >0 on startup, so 0 is reached only at end of loop. we can send stop here.
896 				(*voIter)->player->stop(); // this immediately hides the video window.
897 				(*voIter)->simplePlay=true; // to reset
898 				(*voIter)->keepVisible=false;
899 			}
900 			else if ((*voIter)->fader.getInterstate()<1.0f)
901 			{
902 				if (verbose)
903 					qDebug() << "StelVideoMgr::update(): not fully grown: pausing video at start or end!";
904 				(*voIter)->player->pause();
905 			}
906 			else if (((*voIter)->duration > 0) && ((*voIter)->player->position() >= ((*voIter)->duration - 250))) // allow stop 250ms before end. 100ms was too short!
907 			{
908 				if (verbose)
909 					qDebug() << "StelVideoMgr::update(): position " << (*voIter)->player->position() << "close to end of duration " << (*voIter)->duration << "--> pause and shutdown with fader ";
910 				(*voIter)->player->pause();
911 				// TBD: If we set some very last frame position here, it takes a very long while to seek (may disturb/flicker!)
912 				// (*voIter)->player->setPosition((*voIter)->duration-10);
913 				(*voIter)->fader=false; // trigger shutdown (sending again does not disturb)
914 			}
915 			else if (((*voIter)->player->state() != QMediaPlayer::PlayingState))
916 			{
917 				if (verbose)
918 					qDebug() << "StelVideoMgr::update(): fully grown: play!";
919 				(*voIter)->player->play();
920 			}
921 		}
922 		// If the videos come with their own fade-in/-out, this can be played during transitions. (keepVisible configured to false)
923 		// In this case we must trigger shrinking *before* end of video!
924 		else
925 		{
926 			if ((*voIter)->fader.getInterstate()>0.0f)
927 			{
928 				if (((*voIter)->player->state() != QMediaPlayer::PlayingState))
929 					(*voIter)->player->play();
930 				if (( ((*voIter)->duration > 0) &&  ((*voIter)->player->position() >= ((*voIter)->duration - (*voIter)->fader.getDuration() - 200))))
931 				{
932 					if (verbose)
933 						qDebug() << "StelVideoMgr::update(): position " << (*voIter)->player->position() << "close to end of duration " << (*voIter)->duration <<
934 							    "minus fader duration " << (*voIter)->fader.getDuration() << "--> shutdown with fader ";
935 					(*voIter)->fader=false; // trigger shutdown (sending again does not disturb)
936 				}
937 			}
938 			else // interstate==0: end of everything.
939 			{
940 				if (verbose)
941 					qDebug() << "StelVideoMgr::update(): Stopping at Interstate " << (*voIter)->fader.getInterstate();
942 				(*voIter)->player->stop();  // immediately hides video window.
943 				(*voIter)->simplePlay=true; // reset
944 			}
945 		}
946 	}
947 }
948 
949 
950 
951 #else
loadVideo(const QString & filename,const QString & id,float x,float y,bool show,float alpha)952 void StelVideoMgr::loadVideo(const QString& filename, const QString& id, float x, float y, bool show, float alpha)
953 {
954 	qWarning() << "[StelVideoMgr] This build of Stellarium does not support video - cannot load video" << QDir::toNativeSeparators(filename) << id << x << y << show << alpha;
955 }
~StelVideoMgr()956 StelVideoMgr::~StelVideoMgr() {;}
update(double)957 void StelVideoMgr::update(double){;}
playVideo(const QString &,const bool)958 void StelVideoMgr::playVideo(const QString&, const bool) {;}
playVideoPopout(const QString &,float,float,float,float,float,float,float,bool)959 void StelVideoMgr::playVideoPopout(const QString&, float, float, float, float, float, float, float, bool){;}
pauseVideo(const QString &)960 void StelVideoMgr::pauseVideo(const QString&) {;}
stopVideo(const QString &)961 void StelVideoMgr::stopVideo(const QString&) {;}
dropVideo(const QString &)962 void StelVideoMgr::dropVideo(const QString&) {;}
seekVideo(const QString &,qint64,bool)963 void StelVideoMgr::seekVideo(const QString&, qint64, bool) {;}
setVideoXY(const QString &,float,float,const bool)964 void StelVideoMgr::setVideoXY(const QString&, float, float, const bool) {;}
setVideoAlpha(const QString &,float)965 void StelVideoMgr::setVideoAlpha(const QString&, float) {;}
resizeVideo(const QString &,float,float)966 void StelVideoMgr::resizeVideo(const QString&, float, float) {;}
showVideo(const QString &,bool)967 void StelVideoMgr::showVideo(const QString&, bool) {;}
968 // New functions for 0.15
getVideoDuration(const QString &) const969 qint64 StelVideoMgr::getVideoDuration(const QString&)const{return -1;}
getVideoPosition(const QString &) const970 qint64 StelVideoMgr::getVideoPosition(const QString&)const{return -1;}
getVideoResolution(const QString &) const971 QSize StelVideoMgr::getVideoResolution(const QString&)const{return QSize(0,0);}
getVideoWidth(const QString &) const972 int StelVideoMgr::getVideoWidth(const QString&)const{return -1;}
getVideoHeight(const QString &) const973 int StelVideoMgr::getVideoHeight(const QString&)const{return -1;}
muteVideo(const QString &,bool)974 void StelVideoMgr::muteVideo(const QString&, bool){;}
setVideoVolume(const QString &,int)975 void StelVideoMgr::setVideoVolume(const QString&, int){;}
getVideoVolume(const QString &) const976 int StelVideoMgr::getVideoVolume(const QString&)const{return -1;}
isVideoPlaying(const QString & id) const977 bool StelVideoMgr::isVideoPlaying(const QString& id) const
978 {
979 	Q_UNUSED(id)
980 	return false;
981 }
982 
983 #endif // ENABLE_MEDIA
984 
985 
986