|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #import <QTKit/QTDataReference.h> |
|
43 #import <QTKit/QTMovie.h> |
|
44 |
|
45 #include "qt7backend.h" |
|
46 |
|
47 #include "qt7playersession.h" |
|
48 #include "qt7playercontrol.h" |
|
49 #include "qt7videooutput.h" |
|
50 |
|
51 #include <QtNetwork/qnetworkcookie.h> |
|
52 #include <qmediaplaylistnavigator.h> |
|
53 |
|
54 #include <CoreFoundation/CoreFoundation.h> |
|
55 #include <Foundation/Foundation.h> |
|
56 |
|
57 #include <QtCore/qdatetime.h> |
|
58 #include <QtCore/qurl.h> |
|
59 |
|
60 #include <QtCore/qdebug.h> |
|
61 |
|
62 QT_USE_NAMESPACE |
|
63 |
|
64 @interface QTMovieObserver : NSObject |
|
65 { |
|
66 @private |
|
67 QT7PlayerSession *m_session; |
|
68 QTMovie *m_movie; |
|
69 } |
|
70 |
|
71 - (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session; |
|
72 - (void) setMovie:(QTMovie *)movie; |
|
73 - (void) processEOS:(NSNotification *)notification; |
|
74 - (void) processLoadStateChange:(NSNotification *)notification; |
|
75 - (void) processVolumeChange:(NSNotification *)notification; |
|
76 - (void) processNaturalSizeChange :(NSNotification *)notification; |
|
77 @end |
|
78 |
|
79 @implementation QTMovieObserver |
|
80 |
|
81 - (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session |
|
82 { |
|
83 if (!(self = [super init])) |
|
84 return nil; |
|
85 |
|
86 self->m_session = session; |
|
87 return self; |
|
88 } |
|
89 |
|
90 - (void) setMovie:(QTMovie *)movie |
|
91 { |
|
92 if (m_movie == movie) |
|
93 return; |
|
94 |
|
95 if (m_movie) { |
|
96 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
|
97 [m_movie release]; |
|
98 } |
|
99 |
|
100 m_movie = movie; |
|
101 |
|
102 if (movie) { |
|
103 [[NSNotificationCenter defaultCenter] addObserver:self |
|
104 selector:@selector(processEOS:) |
|
105 name:QTMovieDidEndNotification |
|
106 object:m_movie]; |
|
107 |
|
108 [[NSNotificationCenter defaultCenter] addObserver:self |
|
109 selector:@selector(processLoadStateChange:) |
|
110 name:QTMovieLoadStateDidChangeNotification |
|
111 object:m_movie]; |
|
112 |
|
113 [[NSNotificationCenter defaultCenter] addObserver:self |
|
114 selector:@selector(processVolumeChange:) |
|
115 name:QTMovieVolumeDidChangeNotification |
|
116 object:m_movie]; |
|
117 |
|
118 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { |
|
119 [[NSNotificationCenter defaultCenter] addObserver:self |
|
120 selector:@selector(processNaturalSizeChange:) |
|
121 name:@"QTMovieNaturalSizeDidChangeNotification" |
|
122 object:m_movie]; |
|
123 |
|
124 } |
|
125 else { |
|
126 [[NSNotificationCenter defaultCenter] addObserver:self |
|
127 selector:@selector(processNaturalSizeChange:) |
|
128 name:QTMovieEditedNotification |
|
129 object:m_movie]; |
|
130 } |
|
131 |
|
132 [movie retain]; |
|
133 } |
|
134 } |
|
135 |
|
136 - (void) processEOS:(NSNotification *)notification |
|
137 { |
|
138 Q_UNUSED(notification); |
|
139 QMetaObject::invokeMethod(m_session, "processEOS", Qt::AutoConnection); |
|
140 } |
|
141 |
|
142 - (void) processLoadStateChange:(NSNotification *)notification |
|
143 { |
|
144 Q_UNUSED(notification); |
|
145 QMetaObject::invokeMethod(m_session, "processLoadStateChange", Qt::AutoConnection); |
|
146 } |
|
147 |
|
148 - (void) processVolumeChange:(NSNotification *)notification |
|
149 { |
|
150 Q_UNUSED(notification); |
|
151 QMetaObject::invokeMethod(m_session, "processVolumeChange", Qt::AutoConnection); |
|
152 } |
|
153 |
|
154 - (void) processNaturalSizeChange :(NSNotification *)notification |
|
155 { |
|
156 Q_UNUSED(notification); |
|
157 QMetaObject::invokeMethod(m_session, "processNaturalSizeChange", Qt::AutoConnection); |
|
158 } |
|
159 |
|
160 @end |
|
161 |
|
162 static inline NSString *qString2CFStringRef(const QString &string) |
|
163 { |
|
164 return [NSString stringWithCharacters:reinterpret_cast<const UniChar *>(string.unicode()) length:string.length()]; |
|
165 } |
|
166 |
|
167 QT7PlayerSession::QT7PlayerSession(QObject *parent) |
|
168 : QObject(parent) |
|
169 , m_QTMovie(0) |
|
170 , m_state(QMediaPlayer::StoppedState) |
|
171 , m_mediaStatus(QMediaPlayer::NoMedia) |
|
172 , m_mediaStream(0) |
|
173 , m_videoOutput(0) |
|
174 , m_muted(false) |
|
175 , m_tryingAsync(false) |
|
176 , m_volume(100) |
|
177 , m_rate(1.0) |
|
178 , m_duration(0) |
|
179 , m_videoAvailable(false) |
|
180 , m_audioAvailable(false) |
|
181 { |
|
182 m_movieObserver = [[QTMovieObserver alloc] initWithPlayerSession:this]; |
|
183 } |
|
184 |
|
185 QT7PlayerSession::~QT7PlayerSession() |
|
186 { |
|
187 [(QTMovieObserver*)m_movieObserver setMovie:nil]; |
|
188 [(QTMovieObserver*)m_movieObserver release]; |
|
189 [(QTMovie*)m_QTMovie release]; |
|
190 } |
|
191 |
|
192 void *QT7PlayerSession::movie() const |
|
193 { |
|
194 return m_QTMovie; |
|
195 } |
|
196 |
|
197 void QT7PlayerSession::setVideoOutput(QT7VideoOutput *output) |
|
198 { |
|
199 if (m_videoOutput == output) |
|
200 return; |
|
201 |
|
202 if (m_videoOutput) |
|
203 m_videoOutput->setMovie(0); |
|
204 |
|
205 m_videoOutput = output; |
|
206 |
|
207 if (m_videoOutput && m_state != QMediaPlayer::StoppedState) |
|
208 m_videoOutput->setMovie(m_QTMovie); |
|
209 } |
|
210 |
|
211 qint64 QT7PlayerSession::position() const |
|
212 { |
|
213 if (!m_QTMovie || m_state == QMediaPlayer::PausedState) |
|
214 return m_currentTime; |
|
215 |
|
216 QTTime qtTime = [(QTMovie*)m_QTMovie currentTime]; |
|
217 quint64 t = static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f); |
|
218 m_currentTime = t; |
|
219 |
|
220 return m_currentTime; |
|
221 } |
|
222 |
|
223 qint64 QT7PlayerSession::duration() const |
|
224 { |
|
225 if (!m_QTMovie) |
|
226 return 0; |
|
227 |
|
228 QTTime qtTime = [(QTMovie*)m_QTMovie duration]; |
|
229 |
|
230 return static_cast<quint64>(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f); |
|
231 } |
|
232 |
|
233 QMediaPlayer::State QT7PlayerSession::state() const |
|
234 { |
|
235 return m_state; |
|
236 } |
|
237 |
|
238 QMediaPlayer::MediaStatus QT7PlayerSession::mediaStatus() const |
|
239 { |
|
240 return m_mediaStatus; |
|
241 } |
|
242 |
|
243 int QT7PlayerSession::bufferStatus() const |
|
244 { |
|
245 return 100; |
|
246 } |
|
247 |
|
248 int QT7PlayerSession::volume() const |
|
249 { |
|
250 return m_volume; |
|
251 } |
|
252 |
|
253 bool QT7PlayerSession::isMuted() const |
|
254 { |
|
255 return m_muted; |
|
256 } |
|
257 |
|
258 bool QT7PlayerSession::isSeekable() const |
|
259 { |
|
260 return true; |
|
261 } |
|
262 |
|
263 qreal QT7PlayerSession::playbackRate() const |
|
264 { |
|
265 return m_rate; |
|
266 } |
|
267 |
|
268 void QT7PlayerSession::setPlaybackRate(qreal rate) |
|
269 { |
|
270 if (qFuzzyCompare(m_rate, rate)) |
|
271 return; |
|
272 |
|
273 m_rate = rate; |
|
274 |
|
275 if (m_QTMovie != 0 && m_state == QMediaPlayer::PlayingState) { |
|
276 AutoReleasePool pool; |
|
277 float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; |
|
278 [(QTMovie*)m_QTMovie setRate:preferredRate * m_rate]; |
|
279 } |
|
280 } |
|
281 |
|
282 void QT7PlayerSession::setPosition(qint64 pos) |
|
283 { |
|
284 if ( !isSeekable() || pos == position()) |
|
285 return; |
|
286 |
|
287 pos = qMin(pos, duration()); |
|
288 |
|
289 QTTime newQTTime = [(QTMovie*)m_QTMovie currentTime]; |
|
290 newQTTime.timeValue = (pos / 1000.0f) * newQTTime.timeScale; |
|
291 [(QTMovie*)m_QTMovie setCurrentTime:newQTTime]; |
|
292 } |
|
293 |
|
294 void QT7PlayerSession::play() |
|
295 { |
|
296 if (m_state == QMediaPlayer::PlayingState) |
|
297 return; |
|
298 |
|
299 m_state = QMediaPlayer::PlayingState; |
|
300 |
|
301 if (m_videoOutput) |
|
302 m_videoOutput->setMovie(m_QTMovie); |
|
303 |
|
304 AutoReleasePool pool; |
|
305 float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; |
|
306 [(QTMovie*)m_QTMovie setRate:preferredRate * m_rate]; |
|
307 |
|
308 emit stateChanged(m_state); |
|
309 } |
|
310 |
|
311 void QT7PlayerSession::pause() |
|
312 { |
|
313 if (m_state == QMediaPlayer::PausedState) |
|
314 return; |
|
315 |
|
316 m_state = QMediaPlayer::PausedState; |
|
317 |
|
318 if (m_videoOutput) |
|
319 m_videoOutput->setMovie(m_QTMovie); |
|
320 |
|
321 [(QTMovie*)m_QTMovie setRate:0]; |
|
322 |
|
323 emit stateChanged(m_state); |
|
324 } |
|
325 |
|
326 void QT7PlayerSession::stop() |
|
327 { |
|
328 if (m_state == QMediaPlayer::StoppedState) |
|
329 return; |
|
330 |
|
331 m_state = QMediaPlayer::StoppedState; |
|
332 |
|
333 [(QTMovie*)m_QTMovie setRate:0]; |
|
334 setPosition(0); |
|
335 |
|
336 if (m_videoOutput) |
|
337 m_videoOutput->setMovie(0); |
|
338 |
|
339 emit stateChanged(m_state); |
|
340 } |
|
341 |
|
342 void QT7PlayerSession::setVolume(int volume) |
|
343 { |
|
344 if (m_volume == volume) |
|
345 return; |
|
346 |
|
347 m_volume = volume; |
|
348 |
|
349 if (m_QTMovie != 0) |
|
350 [(QTMovie*)m_QTMovie setVolume:m_volume / 100.0f]; |
|
351 else |
|
352 emit volumeChanged(m_volume); |
|
353 } |
|
354 |
|
355 void QT7PlayerSession::setMuted(bool muted) |
|
356 { |
|
357 if (m_muted == muted) |
|
358 return; |
|
359 |
|
360 m_muted = muted; |
|
361 |
|
362 if (m_QTMovie != 0) |
|
363 [(QTMovie*)m_QTMovie setMuted:m_muted]; |
|
364 |
|
365 emit mutedChanged(muted); |
|
366 } |
|
367 |
|
368 QMediaContent QT7PlayerSession::media() const |
|
369 { |
|
370 return m_resources; |
|
371 } |
|
372 |
|
373 const QIODevice *QT7PlayerSession::mediaStream() const |
|
374 { |
|
375 return m_mediaStream; |
|
376 } |
|
377 |
|
378 void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) |
|
379 { |
|
380 AutoReleasePool pool; |
|
381 |
|
382 #ifdef QT_DEBUG_QT7 |
|
383 qDebug() << Q_FUNC_INFO << content.canonicalUrl(); |
|
384 #endif |
|
385 |
|
386 if (m_QTMovie) { |
|
387 [(QTMovieObserver*)m_movieObserver setMovie:nil]; |
|
388 |
|
389 if (m_videoOutput) |
|
390 m_videoOutput->setMovie(0); |
|
391 |
|
392 [(QTMovie*)m_QTMovie release]; |
|
393 m_QTMovie = 0; |
|
394 m_resourceHandler.clear(); |
|
395 } |
|
396 |
|
397 m_resources = content; |
|
398 m_mediaStream = stream; |
|
399 m_mediaStatus = QMediaPlayer::NoMedia; |
|
400 |
|
401 if (content.isNull()) |
|
402 return; |
|
403 |
|
404 QNetworkRequest request = content.canonicalResource().request(); |
|
405 |
|
406 QVariant cookies = request.header(QNetworkRequest::CookieHeader); |
|
407 if (cookies.isValid()) { |
|
408 NSHTTPCookieStorage *store = [NSHTTPCookieStorage sharedHTTPCookieStorage]; |
|
409 QList<QNetworkCookie> cookieList = cookies.value<QList<QNetworkCookie> >(); |
|
410 |
|
411 foreach (const QNetworkCookie &requestCookie, cookieList) { |
|
412 NSMutableDictionary *p = [NSMutableDictionary dictionaryWithObjectsAndKeys: |
|
413 qString2CFStringRef(requestCookie.name()), NSHTTPCookieName, |
|
414 qString2CFStringRef(requestCookie.value()), NSHTTPCookieValue, |
|
415 qString2CFStringRef(requestCookie.domain()), NSHTTPCookieDomain, |
|
416 qString2CFStringRef(requestCookie.path()), NSHTTPCookiePath, |
|
417 nil |
|
418 ]; |
|
419 if (requestCookie.isSessionCookie()) |
|
420 [p setObject:[NSString stringWithUTF8String:"TRUE"] forKey:NSHTTPCookieDiscard]; |
|
421 else |
|
422 [p setObject:[NSDate dateWithTimeIntervalSince1970:requestCookie.expirationDate().toTime_t()] forKey:NSHTTPCookieExpires]; |
|
423 |
|
424 [store setCookie:[NSHTTPCookie cookieWithProperties:p]]; |
|
425 } |
|
426 } |
|
427 |
|
428 // Attempt multiple times to open the movie. |
|
429 // First try - attempt open in async mode |
|
430 openMovie(true); |
|
431 } |
|
432 |
|
433 void QT7PlayerSession::openMovie(bool tryAsync) |
|
434 { |
|
435 QUrl requestUrl = m_resources.canonicalResource().request().url(); |
|
436 if (requestUrl.scheme().isEmpty()) |
|
437 requestUrl.setScheme(QLatin1String("file")); |
|
438 |
|
439 #ifdef QT_DEBUG_QT7 |
|
440 qDebug() << Q_FUNC_INFO << requestUrl; |
|
441 #endif |
|
442 |
|
443 NSError *err = 0; |
|
444 NSString *urlString = [NSString stringWithUTF8String:requestUrl.toEncoded().constData()]; |
|
445 |
|
446 NSMutableDictionary *attr = [NSMutableDictionary dictionaryWithObjectsAndKeys: |
|
447 [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute, |
|
448 [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute, |
|
449 [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute, |
|
450 [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute, |
|
451 nil]; |
|
452 |
|
453 |
|
454 if (requestUrl.scheme() == QLatin1String("qrc")) { |
|
455 // Load from Qt resource |
|
456 m_resourceHandler.setResourceFile(QLatin1Char(':') + requestUrl.path()); |
|
457 if (!m_resourceHandler.isValid()) { |
|
458 emit error(QMediaPlayer::FormatError, tr("Attempting to play invalid Qt resource")); |
|
459 return; |
|
460 } |
|
461 |
|
462 CFDataRef resourceData = |
|
463 CFDataCreateWithBytesNoCopy(0, m_resourceHandler.data(), m_resourceHandler.size(), kCFAllocatorNull); |
|
464 |
|
465 QTDataReference *dataReference = |
|
466 [QTDataReference dataReferenceWithReferenceToData:(NSData*)resourceData |
|
467 name:qString2CFStringRef(requestUrl.path()) |
|
468 MIMEType:nil]; |
|
469 |
|
470 [attr setObject:dataReference forKey:QTMovieDataReferenceAttribute]; |
|
471 |
|
472 CFRelease(resourceData); |
|
473 } else { |
|
474 [attr setObject:[NSURL URLWithString:urlString] forKey:QTMovieURLAttribute]; |
|
475 } |
|
476 |
|
477 if (tryAsync && QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { |
|
478 [attr setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenAsyncRequiredAttribute"]; |
|
479 // XXX: This is disabled for now. causes some problems with video playback for some formats |
|
480 // [attr setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenForPlaybackAttribute"]; |
|
481 m_tryingAsync = true; |
|
482 } |
|
483 else |
|
484 m_tryingAsync = false; |
|
485 |
|
486 m_QTMovie = [QTMovie movieWithAttributes:attr error:&err]; |
|
487 if (err != nil) { |
|
488 // First attempt to test for inability to perform async |
|
489 // if ([err code] == QTErrorMovieOpeningCannotBeAsynchronous) { XXX: error code unknown! |
|
490 if (m_tryingAsync) { |
|
491 m_tryingAsync = false; |
|
492 err = nil; |
|
493 [attr removeObjectForKey:@"QTMovieOpenAsyncRequiredAttribute"]; |
|
494 m_QTMovie = [QTMovie movieWithAttributes:attr error:&err]; |
|
495 } |
|
496 } |
|
497 |
|
498 if (err != nil) { |
|
499 m_QTMovie = 0; |
|
500 QString description = QString::fromUtf8([[err localizedDescription] UTF8String]); |
|
501 emit error(QMediaPlayer::FormatError, description); |
|
502 |
|
503 #ifdef QT_DEBUG_QT7 |
|
504 qDebug() << Q_FUNC_INFO << description; |
|
505 #endif |
|
506 } |
|
507 else { |
|
508 [(QTMovie*)m_QTMovie retain]; |
|
509 |
|
510 [(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie]; |
|
511 |
|
512 if (m_state != QMediaPlayer::StoppedState && m_videoOutput) |
|
513 m_videoOutput->setMovie(m_QTMovie); |
|
514 |
|
515 processLoadStateChange(); |
|
516 |
|
517 [(QTMovie*)m_QTMovie setMuted:m_muted]; |
|
518 [(QTMovie*)m_QTMovie setVolume:m_volume / 100.0f]; |
|
519 } |
|
520 } |
|
521 |
|
522 bool QT7PlayerSession::isAudioAvailable() const |
|
523 { |
|
524 if (!m_QTMovie) |
|
525 return false; |
|
526 |
|
527 AutoReleasePool pool; |
|
528 return [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieHasAudioAttribute"] boolValue] == YES; |
|
529 } |
|
530 |
|
531 bool QT7PlayerSession::isVideoAvailable() const |
|
532 { |
|
533 if (!m_QTMovie) |
|
534 return false; |
|
535 |
|
536 AutoReleasePool pool; |
|
537 return [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieHasVideoAttribute"] boolValue] == YES; |
|
538 } |
|
539 |
|
540 void QT7PlayerSession::processEOS() |
|
541 { |
|
542 #ifdef QT_DEBUG_QT7 |
|
543 qDebug() << Q_FUNC_INFO; |
|
544 #endif |
|
545 m_mediaStatus = QMediaPlayer::EndOfMedia; |
|
546 if (m_videoOutput) |
|
547 m_videoOutput->setMovie(0); |
|
548 emit stateChanged(m_state = QMediaPlayer::StoppedState); |
|
549 emit mediaStatusChanged(m_mediaStatus); |
|
550 } |
|
551 |
|
552 void QT7PlayerSession::processLoadStateChange() |
|
553 { |
|
554 if (!m_QTMovie) |
|
555 return; |
|
556 |
|
557 AutoReleasePool pool; |
|
558 |
|
559 long state = [[(QTMovie*)m_QTMovie attributeForKey:QTMovieLoadStateAttribute] longValue]; |
|
560 |
|
561 #ifdef QT_DEBUG_QT7 |
|
562 qDebug() << Q_FUNC_INFO << state; |
|
563 #endif |
|
564 |
|
565 #ifndef QUICKTIME_C_API_AVAILABLE |
|
566 enum { |
|
567 kMovieLoadStateError = -1L, |
|
568 kMovieLoadStateLoading = 1000, |
|
569 kMovieLoadStateLoaded = 2000, |
|
570 kMovieLoadStatePlayable = 10000, |
|
571 kMovieLoadStatePlaythroughOK = 20000, |
|
572 kMovieLoadStateComplete = 100000 |
|
573 }; |
|
574 #endif |
|
575 |
|
576 if (state == kMovieLoadStateError) { |
|
577 if (m_tryingAsync) { |
|
578 NSError *error = [(QTMovie*)m_QTMovie attributeForKey:@"QTMovieLoadStateErrorAttribute"]; |
|
579 if ([error code] == componentNotThreadSafeErr) { |
|
580 // Last Async check, try again with no such flag |
|
581 openMovie(false); |
|
582 } |
|
583 } |
|
584 else { |
|
585 if (m_videoOutput) |
|
586 m_videoOutput->setMovie(0); |
|
587 |
|
588 emit error(QMediaPlayer::FormatError, tr("Failed to load media")); |
|
589 emit mediaStatusChanged(m_mediaStatus = QMediaPlayer::InvalidMedia); |
|
590 emit stateChanged(m_state = QMediaPlayer::StoppedState); |
|
591 } |
|
592 |
|
593 return; |
|
594 } |
|
595 |
|
596 QMediaPlayer::MediaStatus newStatus = QMediaPlayer::NoMedia; |
|
597 bool isPlaying = (m_state != QMediaPlayer::StoppedState); |
|
598 |
|
599 if (state >= kMovieLoadStatePlaythroughOK) { |
|
600 newStatus = isPlaying ? QMediaPlayer::BufferedMedia : QMediaPlayer::LoadedMedia; |
|
601 } else if (state >= kMovieLoadStatePlayable) |
|
602 newStatus = isPlaying ? QMediaPlayer::BufferingMedia : QMediaPlayer::LoadingMedia; |
|
603 else if (state >= kMovieLoadStateLoading) |
|
604 newStatus = isPlaying ? QMediaPlayer::StalledMedia : QMediaPlayer::LoadingMedia; |
|
605 |
|
606 if (state >= kMovieLoadStatePlayable && |
|
607 m_state == QMediaPlayer::PlayingState && |
|
608 [(QTMovie*)m_QTMovie rate] == 0) { |
|
609 |
|
610 float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; |
|
611 |
|
612 [(QTMovie*)m_QTMovie setRate:preferredRate * m_rate]; |
|
613 } |
|
614 |
|
615 if (state >= kMovieLoadStateLoaded) { |
|
616 qint64 currentDuration = duration(); |
|
617 if (m_duration != currentDuration) |
|
618 emit durationChanged(m_duration = currentDuration); |
|
619 |
|
620 if (m_audioAvailable != isAudioAvailable()) |
|
621 emit audioAvailableChanged(m_audioAvailable = !m_audioAvailable); |
|
622 |
|
623 if (m_videoAvailable != isVideoAvailable()) |
|
624 emit videoAvailableChanged(m_videoAvailable = !m_videoAvailable); |
|
625 } |
|
626 |
|
627 if (newStatus != m_mediaStatus) |
|
628 emit mediaStatusChanged(m_mediaStatus = newStatus); |
|
629 } |
|
630 |
|
631 void QT7PlayerSession::processVolumeChange() |
|
632 { |
|
633 if (!m_QTMovie) |
|
634 return; |
|
635 |
|
636 int newVolume = qRound(100.0f * [((QTMovie*)m_QTMovie) volume]); |
|
637 |
|
638 if (newVolume != m_volume) { |
|
639 emit volumeChanged(m_volume = newVolume); |
|
640 } |
|
641 } |
|
642 |
|
643 void QT7PlayerSession::processNaturalSizeChange() |
|
644 { |
|
645 AutoReleasePool pool; |
|
646 NSSize size = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue]; |
|
647 #ifdef QT_DEBUG_QT7 |
|
648 qDebug() << Q_FUNC_INFO << QSize(size.width, size.height); |
|
649 #endif |
|
650 |
|
651 if (m_videoOutput) |
|
652 m_videoOutput->updateNaturalSize(QSize(size.width, size.height)); |
|
653 } |
|
654 |
|
655 #include "moc_qt7playersession.cpp" |