qtmobility/plugins/multimedia/qt7/qt7playersession.mm
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
--- a/qtmobility/plugins/multimedia/qt7/qt7playersession.mm	Fri Jun 11 14:26:25 2010 +0300
+++ b/qtmobility/plugins/multimedia/qt7/qt7playersession.mm	Wed Jun 23 19:08:38 2010 +0300
@@ -46,11 +46,15 @@
 
 #include "qt7playersession.h"
 #include "qt7playercontrol.h"
-#include "qt7videooutputcontrol.h"
+#include "qt7videooutput.h"
 
+#include <QtNetwork/qnetworkcookie.h>
 #include <qmediaplaylistnavigator.h>
 
 #include <CoreFoundation/CoreFoundation.h>
+#include <Foundation/Foundation.h>
+
+#include <QtCore/qdatetime.h>
 
 #include <QtCore/qurl.h>
 #include <QtCore/qdebug.h>
@@ -67,7 +71,9 @@
 - (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session;
 - (void) setMovie:(QTMovie *)movie;
 - (void) processEOS:(NSNotification *)notification;
-- (void) processStateChange:(NSNotification *)notification;
+- (void) processLoadStateChange:(NSNotification *)notification;
+- (void) processVolumeChange:(NSNotification *)notification;
+- (void) processNaturalSizeChange :(NSNotification *)notification;
 @end
 
 @implementation QTMovieObserver
@@ -94,15 +100,30 @@
     m_movie = movie;
 
     if (movie) {
-        [[NSNotificationCenter defaultCenter] addObserver: self selector:
-            @selector(processEOS:) name: QTMovieDidEndNotification object: m_movie];
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(processEOS:)
+                                                     name:QTMovieDidEndNotification
+                                                   object:m_movie];
+
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(processLoadStateChange:)
+                                                     name:QTMovieLoadStateDidChangeNotification
+                                                   object:m_movie];
 
-        [[NSNotificationCenter defaultCenter] addObserver: self selector:
-            @selector(processStateChange:) name: QTMovieLoadStateDidChangeNotification object: m_movie];
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(processVolumeChange:)
+                                                     name:QTMovieVolumeDidChangeNotification
+                                                   object:m_movie];
 
-        [[NSNotificationCenter defaultCenter] addObserver: self selector:
-            @selector(processVolumeChange:) name: QTMovieVolumeDidChangeNotification object: m_movie];
-
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(processNaturalSizeChange:)
+                                                     name:
+#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6)
+                                                          QTMovieNaturalSizeDidChangeNotification
+#else
+                                                          QTMovieEditedNotification
+#endif
+                                                   object:m_movie];
         [movie retain];
     }
 }
@@ -110,28 +131,32 @@
 - (void) processEOS:(NSNotification *)notification
 {
     Q_UNUSED(notification);
-    m_session->processEOS();
+    QMetaObject::invokeMethod(m_session, "processEOS", Qt::AutoConnection);
 }
 
-- (void) processStateChange:(NSNotification *)notification
+- (void) processLoadStateChange:(NSNotification *)notification
 {
     Q_UNUSED(notification);
-    m_session->processStateChange();
+    QMetaObject::invokeMethod(m_session, "processLoadStateChange", Qt::AutoConnection);
 }
 
 - (void) processVolumeChange:(NSNotification *)notification
 {
     Q_UNUSED(notification);
-    m_session->processVolumeChange();
+    QMetaObject::invokeMethod(m_session, "processVolumeChange", Qt::AutoConnection);
 }
 
+- (void) processNaturalSizeChange :(NSNotification *)notification
+{
+    Q_UNUSED(notification);
+    QMetaObject::invokeMethod(m_session, "processNaturalSizeChange", Qt::AutoConnection);
+}
 
 @end
 
-static CFStringRef qString2CFStringRef(const QString &string)
+static inline NSString *qString2CFStringRef(const QString &string)
 {
-    return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
-                                        string.length());
+    return [NSString stringWithCharacters:reinterpret_cast<const UniChar *>(string.unicode()) length:string.length()];
 }
 
 QT7PlayerSession::QT7PlayerSession(QObject *parent)
@@ -144,6 +169,9 @@
    , m_muted(false)
    , m_volume(100)
    , m_rate(1.0)
+   , m_duration(0)
+   , m_videoAvailable(false)
+   , m_audioAvailable(false)
 {
     m_movieObserver = [[QTMovieObserver alloc] initWithPlayerSession:this];
 }
@@ -152,6 +180,7 @@
 {
     [(QTMovieObserver*)m_movieObserver setMovie:nil];
     [(QTMovieObserver*)m_movieObserver release];
+    [(QTMovie*)m_QTMovie release];
 }
 
 void *QT7PlayerSession::movie() const
@@ -164,22 +193,15 @@
     if (m_videoOutput == output)
         return;
 
-    qDebug() << "set output" << output;
-
-    if (m_videoOutput) {
-        m_videoOutput->setEnabled(false);
+    if (m_videoOutput)
         m_videoOutput->setMovie(0);
-    }
 
     m_videoOutput = output;
 
-    if (m_videoOutput) {
-        m_videoOutput->setEnabled(m_QTMovie != 0);
+    if (m_videoOutput && m_state != QMediaPlayer::StoppedState)
         m_videoOutput->setMovie(m_QTMovie);
-    }
 }
 
-
 qint64 QT7PlayerSession::position() const
 {
     if (!m_QTMovie || m_state == QMediaPlayer::PausedState)
@@ -270,6 +292,9 @@
 
 void QT7PlayerSession::play()
 {
+    if (m_videoOutput)
+        m_videoOutput->setMovie(m_QTMovie);
+
     float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
     [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate];
 
@@ -279,6 +304,9 @@
 
 void QT7PlayerSession::pause()
 {
+    if (m_videoOutput)
+        m_videoOutput->setMovie(m_QTMovie);
+
     m_state = QMediaPlayer::PausedState;
 
     [(QTMovie*)m_QTMovie setRate:0];
@@ -293,6 +321,9 @@
     [(QTMovie*)m_QTMovie setRate:0];
     setPosition(0);
 
+    if (m_videoOutput)
+        m_videoOutput->setMovie(0);
+
     if (m_state == QMediaPlayer::StoppedState)
         emit stateChanged(m_state);
 }
@@ -331,13 +362,13 @@
 {
     AutoReleasePool pool;
 
+    qDebug() << "SetMedia" << content.canonicalUrl();
+
     if (m_QTMovie) {
         [(QTMovieObserver*)m_movieObserver setMovie:nil];
 
-        if (m_videoOutput) {
-            m_videoOutput->setEnabled(false);
+        if (m_videoOutput)
             m_videoOutput->setMovie(0);
-        }
 
         [(QTMovie*)m_QTMovie release];
         m_QTMovie = 0;
@@ -347,27 +378,46 @@
     m_mediaStream = stream;
     m_mediaStatus = QMediaPlayer::NoMedia;
 
-    QUrl url;
-
+    QNetworkRequest request;
     if (!content.isNull())
-        url = content.canonicalUrl();
+        request = content.canonicalResource().request();
     else
         return;
 
-    NSError *err = 0;
-    QTDataReference *dataRef = 0;
+    QVariant cookies = request.header(QNetworkRequest::CookieHeader);
+    if (cookies.isValid()) {
+        NSHTTPCookieStorage *store = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+        QList<QNetworkCookie> cookieList = cookies.value<QList<QNetworkCookie> >();
 
-    if ( url.scheme() == "file" ) {
-        NSString *nsFileName = (NSString *)qString2CFStringRef( url.toLocalFile() );
-        dataRef = [QTDataReference dataReferenceWithReferenceToFile:nsFileName];
-    } else {
-        NSString *urlString = (NSString *)qString2CFStringRef( url.toString() );
-        NSURL *url = [NSURL URLWithString: urlString];
-        dataRef = [QTDataReference dataReferenceWithReferenceToURL:url];
+        foreach (const QNetworkCookie &requestCookie, cookieList) {
+            NSMutableDictionary *p = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+                               qString2CFStringRef(requestCookie.name()), NSHTTPCookieName,
+                               qString2CFStringRef(requestCookie.value()), NSHTTPCookieValue,
+                               qString2CFStringRef(requestCookie.domain()), NSHTTPCookieDomain,
+                               qString2CFStringRef(requestCookie.path()), NSHTTPCookiePath,
+                               nil
+                               ];
+            if (requestCookie.isSessionCookie())
+                [p setObject:[NSString stringWithUTF8String:"TRUE"] forKey:NSHTTPCookieDiscard];
+            else
+                [p setObject:[NSDate dateWithTimeIntervalSince1970:requestCookie.expirationDate().toTime_t()] forKey:NSHTTPCookieExpires];
+
+            [store setCookie:[NSHTTPCookie cookieWithProperties:p]];
+        }
     }
 
+
+    QUrl requestUrl = request.url();
+    if (requestUrl.scheme().isEmpty())
+        requestUrl.setScheme(QLatin1String("file"));
+
+    qDebug() << "Play" << requestUrl;
+
+    NSError *err = 0;
+    NSString *urlString = qString2CFStringRef(requestUrl.toString());
+
     NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys:
-                dataRef, QTMovieDataReferenceAttribute,
+                [NSURL URLWithString:urlString], QTMovieURLAttribute,
                 [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute,
                 [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute,
                 [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute,
@@ -386,11 +436,10 @@
     } else {
         [(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie];
 
-        if (m_videoOutput) {            
+        if (m_state != QMediaPlayer::StoppedState && m_videoOutput)
             m_videoOutput->setMovie(m_QTMovie);
-            m_videoOutput->setEnabled(true);
-        }
-        processStateChange();
+
+        processLoadStateChange();
 
         [(QTMovie*)m_QTMovie setMuted:m_muted];
         setVolume(m_volume);
@@ -418,15 +467,20 @@
 void QT7PlayerSession::processEOS()
 {    
     m_mediaStatus = QMediaPlayer::EndOfMedia;
+    if (m_videoOutput)
+        m_videoOutput->setMovie(0);
     emit stateChanged(m_state = QMediaPlayer::StoppedState);
     emit mediaStatusChanged(m_mediaStatus);
 }
 
-void QT7PlayerSession::processStateChange()
+void QT7PlayerSession::processLoadStateChange()
 {
+    if (!m_QTMovie)
+        return;
+
     signed long state = [[(QTMovie*)m_QTMovie attributeForKey:QTMovieLoadStateAttribute]
                          longValue];
-    //qDebug() << "new State:" << state;
+    qDebug() << "Moview load state changed:" << state;
 
 #ifndef QUICKTIME_C_API_AVAILABLE
     enum {
@@ -451,32 +505,33 @@
 
     if (state == kMovieLoadStateError) {
         newStatus = QMediaPlayer::InvalidMedia;
-        emit error(QMediaPlayer::FormatError, tr("Playback failed"));
+        if (m_videoOutput)
+            m_videoOutput->setMovie(0);
+
+        emit error(QMediaPlayer::FormatError, tr("Failed to load media"));
+        emit stateChanged(m_state = QMediaPlayer::StoppedState);
+    }
+
+    if (state >= kMovieLoadStatePlayable &&
+        m_state == QMediaPlayer::PlayingState &&
+        [(QTMovie*)m_QTMovie rate] == 0) {
+            QMetaObject::invokeMethod(this, "play", Qt::QueuedConnection);
     }
 
-    if (newStatus != m_mediaStatus) {
-        switch (newStatus) {
-        case QMediaPlayer::BufferedMedia:
-        case QMediaPlayer::BufferingMedia:
-            //delayed playback start is necessary for network sources
-            if (m_state == QMediaPlayer::PlayingState) {
-                QMetaObject::invokeMethod(this, "play", Qt::QueuedConnection);
-            }
-            //fall
-        case QMediaPlayer::LoadedMedia:
-        case QMediaPlayer::LoadingMedia:
-            emit durationChanged(duration());
-            emit audioAvailableChanged(isAudioAvailable());
-            emit videoAvailableChanged(isVideoAvailable());
-            break;
-        case QMediaPlayer::InvalidMedia:
-            emit stateChanged(m_state = QMediaPlayer::StoppedState);
-        default:
-            break;
-        }
+    if (state >= kMovieLoadStateLoaded) {
+        qint64 currentDuration = duration();
+        if (m_duration != currentDuration)
+            emit durationChanged(m_duration = currentDuration);
 
+        if (m_audioAvailable != isAudioAvailable())
+            emit audioAvailableChanged(m_audioAvailable = !m_audioAvailable);
+
+        if (m_videoAvailable != isVideoAvailable())
+            emit videoAvailableChanged(m_videoAvailable = !m_videoAvailable);
+    }
+
+    if (newStatus != m_mediaStatus)
         emit mediaStatusChanged(m_mediaStatus = newStatus);
-    }
 }
 
 void QT7PlayerSession::processVolumeChange()
@@ -491,4 +546,13 @@
     }
 }
 
+void QT7PlayerSession::processNaturalSizeChange()
+{
+    NSSize size = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue];
+    qDebug() << "Native size changed:" << QSize(size.width, size.height);
+
+    if (m_videoOutput)
+        m_videoOutput->updateNaturalSize(QSize(size.width, size.height));
+}
+
 #include "moc_qt7playersession.cpp"