plugins/multimedia/qt7/mediaplayer/qt7playersession.mm
changeset 5 603d3f8b6302
equal deleted inserted replaced
3:e4ebb16b39ea 5:603d3f8b6302
       
     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"