qtmobility/plugins/multimedia/qt7/qt7playersession.mm
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
    44 
    44 
    45 #include "qt7backend.h"
    45 #include "qt7backend.h"
    46 
    46 
    47 #include "qt7playersession.h"
    47 #include "qt7playersession.h"
    48 #include "qt7playercontrol.h"
    48 #include "qt7playercontrol.h"
    49 #include "qt7videooutputcontrol.h"
    49 #include "qt7videooutput.h"
    50 
    50 
       
    51 #include <QtNetwork/qnetworkcookie.h>
    51 #include <qmediaplaylistnavigator.h>
    52 #include <qmediaplaylistnavigator.h>
    52 
    53 
    53 #include <CoreFoundation/CoreFoundation.h>
    54 #include <CoreFoundation/CoreFoundation.h>
       
    55 #include <Foundation/Foundation.h>
       
    56 
       
    57 #include <QtCore/qdatetime.h>
    54 
    58 
    55 #include <QtCore/qurl.h>
    59 #include <QtCore/qurl.h>
    56 #include <QtCore/qdebug.h>
    60 #include <QtCore/qdebug.h>
    57 
    61 
    58 QT_USE_NAMESPACE
    62 QT_USE_NAMESPACE
    65 }
    69 }
    66 
    70 
    67 - (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session;
    71 - (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session;
    68 - (void) setMovie:(QTMovie *)movie;
    72 - (void) setMovie:(QTMovie *)movie;
    69 - (void) processEOS:(NSNotification *)notification;
    73 - (void) processEOS:(NSNotification *)notification;
    70 - (void) processStateChange:(NSNotification *)notification;
    74 - (void) processLoadStateChange:(NSNotification *)notification;
       
    75 - (void) processVolumeChange:(NSNotification *)notification;
       
    76 - (void) processNaturalSizeChange :(NSNotification *)notification;
    71 @end
    77 @end
    72 
    78 
    73 @implementation QTMovieObserver
    79 @implementation QTMovieObserver
    74 
    80 
    75 - (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session
    81 - (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session
    92     }
    98     }
    93 
    99 
    94     m_movie = movie;
   100     m_movie = movie;
    95 
   101 
    96     if (movie) {
   102     if (movie) {
    97         [[NSNotificationCenter defaultCenter] addObserver: self selector:
   103         [[NSNotificationCenter defaultCenter] addObserver:self
    98             @selector(processEOS:) name: QTMovieDidEndNotification object: m_movie];
   104                                                  selector:@selector(processEOS:)
    99 
   105                                                      name:QTMovieDidEndNotification
   100         [[NSNotificationCenter defaultCenter] addObserver: self selector:
   106                                                    object:m_movie];
   101             @selector(processStateChange:) name: QTMovieLoadStateDidChangeNotification object: m_movie];
   107 
   102 
   108         [[NSNotificationCenter defaultCenter] addObserver:self
   103         [[NSNotificationCenter defaultCenter] addObserver: self selector:
   109                                                  selector:@selector(processLoadStateChange:)
   104             @selector(processVolumeChange:) name: QTMovieVolumeDidChangeNotification object: m_movie];
   110                                                      name:QTMovieLoadStateDidChangeNotification
   105 
   111                                                    object:m_movie];
       
   112 
       
   113         [[NSNotificationCenter defaultCenter] addObserver:self
       
   114                                                  selector:@selector(processVolumeChange:)
       
   115                                                      name:QTMovieVolumeDidChangeNotification
       
   116                                                    object:m_movie];
       
   117 
       
   118         [[NSNotificationCenter defaultCenter] addObserver:self
       
   119                                                  selector:@selector(processNaturalSizeChange:)
       
   120                                                      name:
       
   121 #if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6)
       
   122                                                           QTMovieNaturalSizeDidChangeNotification
       
   123 #else
       
   124                                                           QTMovieEditedNotification
       
   125 #endif
       
   126                                                    object:m_movie];
   106         [movie retain];
   127         [movie retain];
   107     }
   128     }
   108 }
   129 }
   109 
   130 
   110 - (void) processEOS:(NSNotification *)notification
   131 - (void) processEOS:(NSNotification *)notification
   111 {
   132 {
   112     Q_UNUSED(notification);
   133     Q_UNUSED(notification);
   113     m_session->processEOS();
   134     QMetaObject::invokeMethod(m_session, "processEOS", Qt::AutoConnection);
   114 }
   135 }
   115 
   136 
   116 - (void) processStateChange:(NSNotification *)notification
   137 - (void) processLoadStateChange:(NSNotification *)notification
   117 {
   138 {
   118     Q_UNUSED(notification);
   139     Q_UNUSED(notification);
   119     m_session->processStateChange();
   140     QMetaObject::invokeMethod(m_session, "processLoadStateChange", Qt::AutoConnection);
   120 }
   141 }
   121 
   142 
   122 - (void) processVolumeChange:(NSNotification *)notification
   143 - (void) processVolumeChange:(NSNotification *)notification
   123 {
   144 {
   124     Q_UNUSED(notification);
   145     Q_UNUSED(notification);
   125     m_session->processVolumeChange();
   146     QMetaObject::invokeMethod(m_session, "processVolumeChange", Qt::AutoConnection);
   126 }
   147 }
   127 
   148 
       
   149 - (void) processNaturalSizeChange :(NSNotification *)notification
       
   150 {
       
   151     Q_UNUSED(notification);
       
   152     QMetaObject::invokeMethod(m_session, "processNaturalSizeChange", Qt::AutoConnection);
       
   153 }
   128 
   154 
   129 @end
   155 @end
   130 
   156 
   131 static CFStringRef qString2CFStringRef(const QString &string)
   157 static inline NSString *qString2CFStringRef(const QString &string)
   132 {
   158 {
   133     return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
   159     return [NSString stringWithCharacters:reinterpret_cast<const UniChar *>(string.unicode()) length:string.length()];
   134                                         string.length());
       
   135 }
   160 }
   136 
   161 
   137 QT7PlayerSession::QT7PlayerSession(QObject *parent)
   162 QT7PlayerSession::QT7PlayerSession(QObject *parent)
   138    : QObject(parent)
   163    : QObject(parent)
   139    , m_QTMovie(0)
   164    , m_QTMovie(0)
   142    , m_mediaStream(0)
   167    , m_mediaStream(0)
   143    , m_videoOutput(0)
   168    , m_videoOutput(0)
   144    , m_muted(false)
   169    , m_muted(false)
   145    , m_volume(100)
   170    , m_volume(100)
   146    , m_rate(1.0)
   171    , m_rate(1.0)
       
   172    , m_duration(0)
       
   173    , m_videoAvailable(false)
       
   174    , m_audioAvailable(false)
   147 {
   175 {
   148     m_movieObserver = [[QTMovieObserver alloc] initWithPlayerSession:this];
   176     m_movieObserver = [[QTMovieObserver alloc] initWithPlayerSession:this];
   149 }
   177 }
   150 
   178 
   151 QT7PlayerSession::~QT7PlayerSession()
   179 QT7PlayerSession::~QT7PlayerSession()
   152 {
   180 {
   153     [(QTMovieObserver*)m_movieObserver setMovie:nil];
   181     [(QTMovieObserver*)m_movieObserver setMovie:nil];
   154     [(QTMovieObserver*)m_movieObserver release];
   182     [(QTMovieObserver*)m_movieObserver release];
       
   183     [(QTMovie*)m_QTMovie release];
   155 }
   184 }
   156 
   185 
   157 void *QT7PlayerSession::movie() const
   186 void *QT7PlayerSession::movie() const
   158 {
   187 {
   159     return m_QTMovie;
   188     return m_QTMovie;
   162 void QT7PlayerSession::setVideoOutput(QT7VideoOutput *output)
   191 void QT7PlayerSession::setVideoOutput(QT7VideoOutput *output)
   163 {
   192 {
   164     if (m_videoOutput == output)
   193     if (m_videoOutput == output)
   165         return;
   194         return;
   166 
   195 
   167     qDebug() << "set output" << output;
   196     if (m_videoOutput)
   168 
       
   169     if (m_videoOutput) {
       
   170         m_videoOutput->setEnabled(false);
       
   171         m_videoOutput->setMovie(0);
   197         m_videoOutput->setMovie(0);
   172     }
       
   173 
   198 
   174     m_videoOutput = output;
   199     m_videoOutput = output;
   175 
   200 
   176     if (m_videoOutput) {
   201     if (m_videoOutput && m_state != QMediaPlayer::StoppedState)
   177         m_videoOutput->setEnabled(m_QTMovie != 0);
       
   178         m_videoOutput->setMovie(m_QTMovie);
   202         m_videoOutput->setMovie(m_QTMovie);
   179     }
   203 }
   180 }
       
   181 
       
   182 
   204 
   183 qint64 QT7PlayerSession::position() const
   205 qint64 QT7PlayerSession::position() const
   184 {
   206 {
   185     if (!m_QTMovie || m_state == QMediaPlayer::PausedState)
   207     if (!m_QTMovie || m_state == QMediaPlayer::PausedState)
   186         return m_currentTime;
   208         return m_currentTime;
   268     [(QTMovie*)m_QTMovie setCurrentTime:newQTTime];
   290     [(QTMovie*)m_QTMovie setCurrentTime:newQTTime];
   269 }
   291 }
   270 
   292 
   271 void QT7PlayerSession::play()
   293 void QT7PlayerSession::play()
   272 {
   294 {
       
   295     if (m_videoOutput)
       
   296         m_videoOutput->setMovie(m_QTMovie);
       
   297 
   273     float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
   298     float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
   274     [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate];
   299     [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate];
   275 
   300 
   276     if (m_state != QMediaPlayer::PlayingState)
   301     if (m_state != QMediaPlayer::PlayingState)
   277         emit stateChanged(m_state = QMediaPlayer::PlayingState);
   302         emit stateChanged(m_state = QMediaPlayer::PlayingState);
   278 }
   303 }
   279 
   304 
   280 void QT7PlayerSession::pause()
   305 void QT7PlayerSession::pause()
   281 {
   306 {
       
   307     if (m_videoOutput)
       
   308         m_videoOutput->setMovie(m_QTMovie);
       
   309 
   282     m_state = QMediaPlayer::PausedState;
   310     m_state = QMediaPlayer::PausedState;
   283 
   311 
   284     [(QTMovie*)m_QTMovie setRate:0];
   312     [(QTMovie*)m_QTMovie setRate:0];
   285 
   313 
   286     emit stateChanged(m_state);
   314     emit stateChanged(m_state);
   290 {
   318 {
   291     m_state = QMediaPlayer::StoppedState;
   319     m_state = QMediaPlayer::StoppedState;
   292 
   320 
   293     [(QTMovie*)m_QTMovie setRate:0];
   321     [(QTMovie*)m_QTMovie setRate:0];
   294     setPosition(0);
   322     setPosition(0);
       
   323 
       
   324     if (m_videoOutput)
       
   325         m_videoOutput->setMovie(0);
   295 
   326 
   296     if (m_state == QMediaPlayer::StoppedState)
   327     if (m_state == QMediaPlayer::StoppedState)
   297         emit stateChanged(m_state);
   328         emit stateChanged(m_state);
   298 }
   329 }
   299 
   330 
   329 
   360 
   330 void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream)
   361 void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream)
   331 {
   362 {
   332     AutoReleasePool pool;
   363     AutoReleasePool pool;
   333 
   364 
       
   365     qDebug() << "SetMedia" << content.canonicalUrl();
       
   366 
   334     if (m_QTMovie) {
   367     if (m_QTMovie) {
   335         [(QTMovieObserver*)m_movieObserver setMovie:nil];
   368         [(QTMovieObserver*)m_movieObserver setMovie:nil];
   336 
   369 
   337         if (m_videoOutput) {
   370         if (m_videoOutput)
   338             m_videoOutput->setEnabled(false);
       
   339             m_videoOutput->setMovie(0);
   371             m_videoOutput->setMovie(0);
   340         }
       
   341 
   372 
   342         [(QTMovie*)m_QTMovie release];
   373         [(QTMovie*)m_QTMovie release];
   343         m_QTMovie = 0;
   374         m_QTMovie = 0;
   344     }
   375     }
   345 
   376 
   346     m_resources = content;
   377     m_resources = content;
   347     m_mediaStream = stream;
   378     m_mediaStream = stream;
   348     m_mediaStatus = QMediaPlayer::NoMedia;
   379     m_mediaStatus = QMediaPlayer::NoMedia;
   349 
   380 
   350     QUrl url;
   381     QNetworkRequest request;
   351 
       
   352     if (!content.isNull())
   382     if (!content.isNull())
   353         url = content.canonicalUrl();
   383         request = content.canonicalResource().request();
   354     else
   384     else
   355         return;
   385         return;
   356 
   386 
       
   387     QVariant cookies = request.header(QNetworkRequest::CookieHeader);
       
   388     if (cookies.isValid()) {
       
   389         NSHTTPCookieStorage *store = [NSHTTPCookieStorage sharedHTTPCookieStorage];
       
   390         QList<QNetworkCookie> cookieList = cookies.value<QList<QNetworkCookie> >();
       
   391 
       
   392         foreach (const QNetworkCookie &requestCookie, cookieList) {
       
   393             NSMutableDictionary *p = [NSMutableDictionary dictionaryWithObjectsAndKeys:
       
   394                                qString2CFStringRef(requestCookie.name()), NSHTTPCookieName,
       
   395                                qString2CFStringRef(requestCookie.value()), NSHTTPCookieValue,
       
   396                                qString2CFStringRef(requestCookie.domain()), NSHTTPCookieDomain,
       
   397                                qString2CFStringRef(requestCookie.path()), NSHTTPCookiePath,
       
   398                                nil
       
   399                                ];
       
   400             if (requestCookie.isSessionCookie())
       
   401                 [p setObject:[NSString stringWithUTF8String:"TRUE"] forKey:NSHTTPCookieDiscard];
       
   402             else
       
   403                 [p setObject:[NSDate dateWithTimeIntervalSince1970:requestCookie.expirationDate().toTime_t()] forKey:NSHTTPCookieExpires];
       
   404 
       
   405             [store setCookie:[NSHTTPCookie cookieWithProperties:p]];
       
   406         }
       
   407     }
       
   408 
       
   409 
       
   410     QUrl requestUrl = request.url();
       
   411     if (requestUrl.scheme().isEmpty())
       
   412         requestUrl.setScheme(QLatin1String("file"));
       
   413 
       
   414     qDebug() << "Play" << requestUrl;
       
   415 
   357     NSError *err = 0;
   416     NSError *err = 0;
   358     QTDataReference *dataRef = 0;
   417     NSString *urlString = qString2CFStringRef(requestUrl.toString());
   359 
       
   360     if ( url.scheme() == "file" ) {
       
   361         NSString *nsFileName = (NSString *)qString2CFStringRef( url.toLocalFile() );
       
   362         dataRef = [QTDataReference dataReferenceWithReferenceToFile:nsFileName];
       
   363     } else {
       
   364         NSString *urlString = (NSString *)qString2CFStringRef( url.toString() );
       
   365         NSURL *url = [NSURL URLWithString: urlString];
       
   366         dataRef = [QTDataReference dataReferenceWithReferenceToURL:url];
       
   367     }
       
   368 
   418 
   369     NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys:
   419     NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys:
   370                 dataRef, QTMovieDataReferenceAttribute,
   420                 [NSURL URLWithString:urlString], QTMovieURLAttribute,
   371                 [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute,
   421                 [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute,
   372                 [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute,
   422                 [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute,
   373                 [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute,
   423                 [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute,
   374                 [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute,
   424                 [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute,
   375                 nil];
   425                 nil];
   384         qWarning() << "QT7PlayerSession::setMedia error" << description;
   434         qWarning() << "QT7PlayerSession::setMedia error" << description;
   385         emit error(QMediaPlayer::FormatError, description );
   435         emit error(QMediaPlayer::FormatError, description );
   386     } else {
   436     } else {
   387         [(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie];
   437         [(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie];
   388 
   438 
   389         if (m_videoOutput) {            
   439         if (m_state != QMediaPlayer::StoppedState && m_videoOutput)
   390             m_videoOutput->setMovie(m_QTMovie);
   440             m_videoOutput->setMovie(m_QTMovie);
   391             m_videoOutput->setEnabled(true);
   441 
   392         }
   442         processLoadStateChange();
   393         processStateChange();
       
   394 
   443 
   395         [(QTMovie*)m_QTMovie setMuted:m_muted];
   444         [(QTMovie*)m_QTMovie setMuted:m_muted];
   396         setVolume(m_volume);
   445         setVolume(m_volume);
   397     }
   446     }
   398 }
   447 }
   416 }
   465 }
   417 
   466 
   418 void QT7PlayerSession::processEOS()
   467 void QT7PlayerSession::processEOS()
   419 {    
   468 {    
   420     m_mediaStatus = QMediaPlayer::EndOfMedia;
   469     m_mediaStatus = QMediaPlayer::EndOfMedia;
       
   470     if (m_videoOutput)
       
   471         m_videoOutput->setMovie(0);
   421     emit stateChanged(m_state = QMediaPlayer::StoppedState);
   472     emit stateChanged(m_state = QMediaPlayer::StoppedState);
   422     emit mediaStatusChanged(m_mediaStatus);
   473     emit mediaStatusChanged(m_mediaStatus);
   423 }
   474 }
   424 
   475 
   425 void QT7PlayerSession::processStateChange()
   476 void QT7PlayerSession::processLoadStateChange()
   426 {
   477 {
       
   478     if (!m_QTMovie)
       
   479         return;
       
   480 
   427     signed long state = [[(QTMovie*)m_QTMovie attributeForKey:QTMovieLoadStateAttribute]
   481     signed long state = [[(QTMovie*)m_QTMovie attributeForKey:QTMovieLoadStateAttribute]
   428                          longValue];
   482                          longValue];
   429     //qDebug() << "new State:" << state;
   483     qDebug() << "Moview load state changed:" << state;
   430 
   484 
   431 #ifndef QUICKTIME_C_API_AVAILABLE
   485 #ifndef QUICKTIME_C_API_AVAILABLE
   432     enum {
   486     enum {
   433       kMovieLoadStateError          = -1L,
   487       kMovieLoadStateError          = -1L,
   434       kMovieLoadStateLoading        = 1000,
   488       kMovieLoadStateLoading        = 1000,
   449     else if (state >= kMovieLoadStateLoading)
   503     else if (state >= kMovieLoadStateLoading)
   450         newStatus = isPlaying ? QMediaPlayer::StalledMedia : QMediaPlayer::LoadingMedia;
   504         newStatus = isPlaying ? QMediaPlayer::StalledMedia : QMediaPlayer::LoadingMedia;
   451 
   505 
   452     if (state == kMovieLoadStateError) {
   506     if (state == kMovieLoadStateError) {
   453         newStatus = QMediaPlayer::InvalidMedia;
   507         newStatus = QMediaPlayer::InvalidMedia;
   454         emit error(QMediaPlayer::FormatError, tr("Playback failed"));
   508         if (m_videoOutput)
   455     }
   509             m_videoOutput->setMovie(0);
   456 
   510 
   457     if (newStatus != m_mediaStatus) {
   511         emit error(QMediaPlayer::FormatError, tr("Failed to load media"));
   458         switch (newStatus) {
   512         emit stateChanged(m_state = QMediaPlayer::StoppedState);
   459         case QMediaPlayer::BufferedMedia:
   513     }
   460         case QMediaPlayer::BufferingMedia:
   514 
   461             //delayed playback start is necessary for network sources
   515     if (state >= kMovieLoadStatePlayable &&
   462             if (m_state == QMediaPlayer::PlayingState) {
   516         m_state == QMediaPlayer::PlayingState &&
   463                 QMetaObject::invokeMethod(this, "play", Qt::QueuedConnection);
   517         [(QTMovie*)m_QTMovie rate] == 0) {
   464             }
   518             QMetaObject::invokeMethod(this, "play", Qt::QueuedConnection);
   465             //fall
   519     }
   466         case QMediaPlayer::LoadedMedia:
   520 
   467         case QMediaPlayer::LoadingMedia:
   521     if (state >= kMovieLoadStateLoaded) {
   468             emit durationChanged(duration());
   522         qint64 currentDuration = duration();
   469             emit audioAvailableChanged(isAudioAvailable());
   523         if (m_duration != currentDuration)
   470             emit videoAvailableChanged(isVideoAvailable());
   524             emit durationChanged(m_duration = currentDuration);
   471             break;
   525 
   472         case QMediaPlayer::InvalidMedia:
   526         if (m_audioAvailable != isAudioAvailable())
   473             emit stateChanged(m_state = QMediaPlayer::StoppedState);
   527             emit audioAvailableChanged(m_audioAvailable = !m_audioAvailable);
   474         default:
   528 
   475             break;
   529         if (m_videoAvailable != isVideoAvailable())
   476         }
   530             emit videoAvailableChanged(m_videoAvailable = !m_videoAvailable);
   477 
   531     }
       
   532 
       
   533     if (newStatus != m_mediaStatus)
   478         emit mediaStatusChanged(m_mediaStatus = newStatus);
   534         emit mediaStatusChanged(m_mediaStatus = newStatus);
   479     }
       
   480 }
   535 }
   481 
   536 
   482 void QT7PlayerSession::processVolumeChange()
   537 void QT7PlayerSession::processVolumeChange()
   483 {
   538 {
   484     if (!m_QTMovie)
   539     if (!m_QTMovie)
   489     if (newVolume != m_volume) {
   544     if (newVolume != m_volume) {
   490         emit volumeChanged(m_volume = newVolume);
   545         emit volumeChanged(m_volume = newVolume);
   491     }
   546     }
   492 }
   547 }
   493 
   548 
       
   549 void QT7PlayerSession::processNaturalSizeChange()
       
   550 {
       
   551     NSSize size = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue];
       
   552     qDebug() << "Native size changed:" << QSize(size.width, size.height);
       
   553 
       
   554     if (m_videoOutput)
       
   555         m_videoOutput->updateNaturalSize(QSize(size.width, size.height));
       
   556 }
       
   557 
   494 #include "moc_qt7playersession.cpp"
   558 #include "moc_qt7playersession.cpp"