Make Remote Control commands testable
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Mar 2014 21:08:24 +0000 (21:08 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Mar 2014 21:08:24 +0000 (21:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=130358

Reviewed by Jer Noble.

Source/WebCore:

Test: media/video-remote-control-playpause.html

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::mediaPlayerTimeChanged): Call session->clientWillPausePlayback.
(WebCore::HTMLMediaElement::didReceiveRemoteControlCommand): Log the command.

* platform/audio/MediaSession.cpp:
(WebCore::MediaSessionClient::mediaSessionTitle): Move from header file.
(WebCore::MediaSessionClient::mediaSessionDuration): Ditto.
(WebCore::MediaSessionClient::mediaSessionCurrentTime): Ditto.
* platform/audio/MediaSession.h:

* platform/audio/MediaSessionManager.cpp:
(WebCore::MediaSessionManager::MediaSessionManager): Get rid of m_activeSession.
(WebCore::MediaSessionManager::removeSession): No need to clear m_activeSession because
    we use the m_sessions vector.
(WebCore::MediaSessionManager::sessionWillBeginPlayback): setCurrentSession takes a
    MediaSession&.
(WebCore::MediaSessionManager::sessionWillEndPlayback): Keep m_sessions sorted so playing
    sessions are before paused sessions.
(WebCore::MediaSessionManager::setCurrentSession): Move the session that is beginning to
    play to the head of m_sessions.
(WebCore::MediaSessionManager::currentSession): Return m_sessions[0] or nullptr.
(WebCore::MediaSessionManager::didReceiveRemoteControlCommand):
* platform/audio/MediaSessionManager.h:

* platform/audio/ios/MediaSessionManagerIOS.mm: Include MediaPlayer.h.

* testing/Internals.cpp:
(WebCore::Internals::postRemoteControlCommand): New.
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

* media/video-remote-control-playpause-expected.txt: Added.
* media/video-remote-control-playpause.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@165916 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/media/video-remote-control-playpause-expected.txt [new file with mode: 0644]
LayoutTests/media/video-remote-control-playpause.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/platform/audio/MediaSession.cpp
Source/WebCore/platform/audio/MediaSession.h
Source/WebCore/platform/audio/MediaSessionManager.cpp
Source/WebCore/platform/audio/MediaSessionManager.h
Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl

index 7aeaae0..2064a7a 100644 (file)
@@ -1,3 +1,13 @@
+2014-03-19  Eric Carlson  <eric.carlson@apple.com>
+
+        Make Remote Control commands testable
+        https://bugs.webkit.org/show_bug.cgi?id=130358
+
+        Reviewed by Jer Noble.
+
+        * media/video-remote-control-playpause-expected.txt: Added.
+        * media/video-remote-control-playpause.html: Added.
+
 2014-03-19  Thiago de Barros Lacerda  <thiago.lacerda@openbossa.org>
 
         Improving webkitGetUserMedia error handling and error messages
diff --git a/LayoutTests/media/video-remote-control-playpause-expected.txt b/LayoutTests/media/video-remote-control-playpause-expected.txt
new file mode 100644 (file)
index 0000000..65f584b
--- /dev/null
@@ -0,0 +1,63 @@
+  
+Test play and pause with "remote control" interface.
+
+EVENT(canplaythrough)
+EVENT(canplaythrough)
+
+** Play both videos, the last one started (video[1]) should get focus...
+RUN(videos[0].play())
+RUN(videos[1].play())
+
+EVENT(playing)
+EVENT(playing)
+
+** Send a pause command, it should go to video[1].
+RUN(internals.postRemoteControlCommand('pause'))
+
+EVENT(pause)
+EXPECTED (event.target.id == 'two') OK
+EXPECTED (videos[0].paused == 'false') OK
+EXPECTED (videos[1].paused == 'true') OK
+
+** Pause video[0], so they both stop playing...
+RUN(videos[0].pause())
+
+EVENT(pause)
+EXPECTED (event.target.id == 'one') OK
+EXPECTED (videos[0].paused == 'true') OK
+EXPECTED (videos[1].paused == 'true') OK
+
+** Seek so video[1] will pause automatically when playback ends.
+RUN(videos[0].currentTime = 0)
+RUN(videos[1].currentTime = 5.5)
+
+EVENT(seeked)
+EVENT(seeked)
+
+** Send a play command, it should go to videos[0] because it was playing most recently.
+RUN(internals.postRemoteControlCommand('play'))
+
+EVENT(playing)
+EXPECTED (event.target.id == 'one') OK
+
+** Start videos[1], wait for it to pause at duration.
+RUN(videos[1].play())
+
+EVENT(playing)
+EXPECTED (event.target.id == 'two') OK
+
+EVENT(pause)
+EXPECTED (event.target.id == 'two') OK
+EXPECTED (videos[0].paused == 'false') OK
+EXPECTED (videos[1].paused == 'true') OK
+
+** Send a pause command, videos[0] is still playing so it should get the command.
+RUN(internals.postRemoteControlCommand('pause'))
+
+EVENT(pause)
+EXPECTED (event.target.id == 'one') OK
+EXPECTED (videos[0].paused == 'true') OK
+EXPECTED (videos[1].paused == 'true') OK
+
+END OF TEST
+
diff --git a/LayoutTests/media/video-remote-control-playpause.html b/LayoutTests/media/video-remote-control-playpause.html
new file mode 100644 (file)
index 0000000..e5bd330
--- /dev/null
@@ -0,0 +1,146 @@
+<html>
+    <head>
+        <script src=media-file.js></script>
+        <script src=video-test.js></script>
+        <script>
+            var playCount = 0;
+            var pauseCount = 0;
+            var seekedCount = 0;
+            var playThroughCount = 0;
+            var videos = [];
+
+            function logEvent(evt)
+            {
+                consoleWrite("EVENT(" + evt.type + ")");
+            }
+
+            function ended(evt)
+            {
+                logEvent(evt);
+            }
+
+            function seeked(evt)
+            {
+                logEvent(evt);
+
+                switch (++seekedCount)
+                {
+                case 2:
+                    consoleWrite("<br>** Send a play command, it should go to videos[0] because it was playing most recently.");
+                    run("internals.postRemoteControlCommand('play')");
+                    consoleWrite("");
+                    break;
+                }
+            }
+
+            function pause(evt)
+            {
+                logEvent(evt);
+
+                switch (++pauseCount)
+                {
+                case 1:
+                    testExpected("event.target.id", "two");
+                    testExpected("videos[0].paused", false);
+                    testExpected("videos[1].paused", true);
+                    consoleWrite("<br>** Pause video[0], so they both stop playing...");
+                    run("videos[0].pause()");
+                    consoleWrite("");
+                    break;
+                case 2:
+                    testExpected("event.target.id", "one");
+                    testExpected("videos[0].paused", true);
+                    testExpected("videos[1].paused", true);
+
+                    consoleWrite("<br>** Seek so video[1] will pause automatically when playback ends.");
+                    
+                    var seekTime = (videos[1].duration - .5).toFixed(1);
+                    run("videos[0].currentTime = 0");
+                    run("videos[1].currentTime = " + seekTime);
+                    consoleWrite("");
+                    break;
+                case 3:
+                    testExpected("event.target.id", "two");
+                    testExpected("videos[0].paused", false);
+                    testExpected("videos[1].paused", true);
+
+                    consoleWrite("<br>** Send a pause command, videos[0] is still playing so it should get the command.");
+                    run("internals.postRemoteControlCommand('pause')");
+                    consoleWrite("");
+                    break;
+                case 4:
+                    testExpected("event.target.id", "one");
+                    testExpected("videos[0].paused", true);
+                    testExpected("videos[1].paused", true);
+                    consoleWrite("");
+                    endTest();
+                    break;
+                case 4:
+                }
+            }
+
+            function playing(evt)
+            {
+                logEvent(evt);
+
+                switch (++playCount)
+                {
+                case 2:
+                    consoleWrite("<br>** Send a pause command, it should go to video[1].");
+                    run("internals.postRemoteControlCommand('pause')");
+                    consoleWrite("");
+                    break;
+                case 3:
+                    testExpected("event.target.id", "one");
+                    consoleWrite("<br>** Start videos[1], wait for it to pause at duration.");
+                    run("videos[1].play()");
+                    consoleWrite("");
+                    break;
+                case 4:
+                    testExpected("event.target.id", "two");
+                    consoleWrite("");
+                    break;
+                }
+            }
+
+            function canplaythrough(evt)
+            {
+                logEvent(evt);
+
+                if (++playThroughCount < 2)
+                    return;
+
+                consoleWrite("<br>** Play both videos, the last one started (video[1]) should get focus...");
+                run("videos[0].play()");
+                run("videos[1].play()");
+
+                consoleWrite("");
+            }
+
+            function start()
+            {
+                if (!window.internals) {
+                    failTest('This test requires window.internals.');
+                    return;
+                }
+
+                videos = document.getElementsByTagName('video');
+                for (var i = 0; i < videos.length; ++i) {
+                    video = videos[i];
+                    video.addEventListener("canplaythrough", canplaythrough);
+                    video.addEventListener('playing', playing);
+                    video.addEventListener('pause', pause);
+                    video.addEventListener('seeked', seeked);
+                    video.addEventListener('ended');
+                    video.src = findMediaFile("video", "content/test");
+                }
+            }
+        </script>
+    </head>
+
+    <body onload="start()">
+        <video controls id="one"></video>
+        <video controls id="two"></video>
+        <p>Test play and pause with "remote control" interface.</p>
+    </body>
+</html>
index 84ec78b..f92f9d6 100644 (file)
@@ -1,3 +1,43 @@
+2014-03-19  Eric Carlson  <eric.carlson@apple.com>
+
+        Make Remote Control commands testable
+        https://bugs.webkit.org/show_bug.cgi?id=130358
+
+        Reviewed by Jer Noble.
+
+        Test: media/video-remote-control-playpause.html
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::mediaPlayerTimeChanged): Call session->clientWillPausePlayback.
+        (WebCore::HTMLMediaElement::didReceiveRemoteControlCommand): Log the command.
+
+        * platform/audio/MediaSession.cpp:
+        (WebCore::MediaSessionClient::mediaSessionTitle): Move from header file.
+        (WebCore::MediaSessionClient::mediaSessionDuration): Ditto.
+        (WebCore::MediaSessionClient::mediaSessionCurrentTime): Ditto.
+        * platform/audio/MediaSession.h:
+
+        * platform/audio/MediaSessionManager.cpp:
+        (WebCore::MediaSessionManager::MediaSessionManager): Get rid of m_activeSession.
+        (WebCore::MediaSessionManager::removeSession): No need to clear m_activeSession because 
+            we use the m_sessions vector.
+        (WebCore::MediaSessionManager::sessionWillBeginPlayback): setCurrentSession takes a 
+            MediaSession&.
+        (WebCore::MediaSessionManager::sessionWillEndPlayback): Keep m_sessions sorted so playing
+            sessions are before paused sessions.
+        (WebCore::MediaSessionManager::setCurrentSession): Move the session that is beginning to
+            play to the head of m_sessions.
+        (WebCore::MediaSessionManager::currentSession): Return m_sessions[0] or nullptr.
+        (WebCore::MediaSessionManager::didReceiveRemoteControlCommand):
+        * platform/audio/MediaSessionManager.h:
+
+        * platform/audio/ios/MediaSessionManagerIOS.mm: Include MediaPlayer.h.
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::postRemoteControlCommand): New.
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2014-03-19  Thiago de Barros Lacerda  <thiago.lacerda@openbossa.org>
 
         Improving webkitGetUserMedia error handling and error messages
index 404df5b..f00e0ed 100644 (file)
@@ -3996,6 +3996,7 @@ void HTMLMediaElement::mediaPlayerTimeChanged(MediaPlayer*)
                 // changes paused to true and fires a simple event named pause at the media element.
                 m_paused = true;
                 scheduleEvent(eventNames().pauseEvent);
+                m_mediaSession->clientWillPausePlayback();
             }
             // Queue a task to fire a simple event named ended at the media element.
             if (!m_sentEndEvent) {
@@ -5975,6 +5976,8 @@ String HTMLMediaElement::mediaSessionTitle() const
 
 void HTMLMediaElement::didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType command)
 {
+    LOG(Media, "HTMLMediaElement::didReceiveRemoteControlCommand(%i)", static_cast<int>(command));
+
     switch (command) {
     case MediaSession::PlayCommand:
         play();
index 599e6f9..8f27b0b 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "HTMLMediaElement.h"
 #include "Logging.h"
+#include "MediaPlayer.h"
 #include "MediaSessionManager.h"
 
 namespace WebCore {
@@ -70,13 +71,13 @@ MediaSession::~MediaSession()
 
 void MediaSession::setState(State state)
 {
-    LOG(Media, "MediaSession::setState - %s", stateName(state));
+    LOG(Media, "MediaSession::setState(%p) - %s", this, stateName(state));
     m_state = state;
 }
 
 void MediaSession::beginInterruption()
 {
-    LOG(Media, "MediaSession::beginInterruption");
+    LOG(Media, "MediaSession::beginInterruption(%p), state = %s", this, stateName(m_state));
 
     m_stateToRestore = state();
     m_notifyingClient = true;
@@ -87,7 +88,7 @@ void MediaSession::beginInterruption()
 
 void MediaSession::endInterruption(EndInterruptionFlags flags)
 {
-    LOG(Media, "MediaSession::endInterruption - flags = %i, stateToRestore = %s", (int)flags, stateName(m_stateToRestore));
+    LOG(Media, "MediaSession::endInterruption(%p) - flags = %i, stateToRestore = %s", this, (int)flags, stateName(m_stateToRestore));
 
     State stateToRestore = m_stateToRestore;
     m_stateToRestore = Idle;
@@ -108,9 +109,12 @@ bool MediaSession::clientWillBeginPlayback()
 
 bool MediaSession::clientWillPausePlayback()
 {
+    LOG(Media, "MediaSession::clientWillPausePlayback(%p)- state = %s", this, stateName(m_state));
     if (state() == Interrupted) {
-        if (!m_notifyingClient)
+        if (!m_notifyingClient) {
             m_stateToRestore = Paused;
+            LOG(Media, "      setting stateToRestore to \"Paused\"");
+        }
         return false;
     }
     
@@ -121,7 +125,7 @@ bool MediaSession::clientWillPausePlayback()
 
 void MediaSession::pauseSession()
 {
-    LOG(Media, "MediaSession::pauseSession");
+    LOG(Media, "MediaSession::pauseSession(%p)", this);
     m_client.pausePlayback();
 }
 
@@ -154,5 +158,20 @@ void MediaSession::didReceiveRemoteControlCommand(RemoteControlCommandType comma
 {
     m_client.didReceiveRemoteControlCommand(command);
 }
+    
+String MediaSessionClient::mediaSessionTitle() const
+{
+    return String();
+}
+
+double MediaSessionClient::mediaSessionDuration() const
+{
+    return MediaPlayer::invalidTime();
+}
+
+double MediaSessionClient::mediaSessionCurrentTime() const
+{
+    return MediaPlayer::invalidTime();
+}
 
 }
index 3a8c1cc..0ef5fa1 100644 (file)
@@ -26,8 +26,8 @@
 #ifndef MediaSession_h
 #define MediaSession_h
 
-#include "MediaPlayer.h"
 #include <wtf/Noncopyable.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -109,9 +109,9 @@ public:
     virtual void resumePlayback() = 0;
     virtual void pausePlayback() = 0;
 
-    virtual String mediaSessionTitle() const { return String(); }
-    virtual double mediaSessionDuration() const { return MediaPlayer::invalidTime(); }
-    virtual double mediaSessionCurrentTime() const { return MediaPlayer::invalidTime(); }
+    virtual String mediaSessionTitle() const;
+    virtual double mediaSessionDuration() const;
+    virtual double mediaSessionCurrentTime() const;
     
     virtual bool canReceiveRemoteControlCommands() const = 0;
     virtual void didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType) = 0;
index 79834f7..1c4522a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -40,8 +40,7 @@ MediaSessionManager& MediaSessionManager::sharedManager()
 #endif
 
 MediaSessionManager::MediaSessionManager()
-    : m_activeSession(nullptr)
-    , m_interrupted(false)
+    : m_interrupted(false)
 {
     resetRestrictions();
 }
@@ -68,7 +67,7 @@ bool MediaSessionManager::has(MediaSession::MediaType type) const
 int MediaSessionManager::count(MediaSession::MediaType type) const
 {
     ASSERT(type >= MediaSession::None && type <= MediaSession::WebAudio);
-    
+
     int count = 0;
     for (auto* session : m_sessions) {
         if (session->mediaType() == type)
@@ -83,7 +82,8 @@ void MediaSessionManager::beginInterruption()
     LOG(Media, "MediaSessionManager::beginInterruption");
 
     m_interrupted = true;
-    for (auto* session : m_sessions)
+    Vector<MediaSession*> sessions = m_sessions;
+    for (auto* session : sessions)
         session->beginInterruption();
 }
 
@@ -92,12 +92,15 @@ void MediaSessionManager::endInterruption(MediaSession::EndInterruptionFlags fla
     LOG(Media, "MediaSessionManager::endInterruption");
 
     m_interrupted = false;
-    for (auto* session : m_sessions)
+    Vector<MediaSession*> sessions = m_sessions;
+    for (auto* session : sessions)
         session->endInterruption(flags);
 }
 
 void MediaSessionManager::addSession(MediaSession& session)
 {
+    LOG(Media, "MediaSessionManager::addSession - %p", &session);
+    
     m_sessions.append(&session);
     if (m_interrupted)
         session.setState(MediaSession::Interrupted);
@@ -115,14 +118,13 @@ void MediaSessionManager::addSession(MediaSession& session)
 
 void MediaSessionManager::removeSession(MediaSession& session)
 {
+    LOG(Media, "MediaSessionManager::removeSession - %p", &session);
+    
     size_t index = m_sessions.find(&session);
     ASSERT(index != notFound);
     if (index == notFound)
         return;
     
-    if (m_activeSession == &session)
-        setCurrentSession(nullptr);
-    
     m_sessions.remove(index);
     updateSessionState();
 
@@ -156,7 +158,9 @@ MediaSessionManager::SessionRestrictions MediaSessionManager::restrictions(Media
 
 void MediaSessionManager::sessionWillBeginPlayback(MediaSession& session)
 {
-    setCurrentSession(&session);
+    LOG(Media, "MediaSessionManager::sessionWillBeginPlayback - %p", &session);
+    
+    setCurrentSession(session);
 
     if (!m_clients.isEmpty() && (session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio)) {
         for (auto& client : m_clients)
@@ -168,7 +172,8 @@ void MediaSessionManager::sessionWillBeginPlayback(MediaSession& session)
     if (!restrictions & ConcurrentPlaybackNotPermitted)
         return;
 
-    for (auto* oneSession : m_sessions) {
+    Vector<MediaSession*> sessions = m_sessions;
+    for (auto* oneSession : sessions) {
         if (oneSession == &session)
             continue;
         if (oneSession->mediaType() != sessionType)
@@ -177,7 +182,68 @@ void MediaSessionManager::sessionWillBeginPlayback(MediaSession& session)
             oneSession->pauseSession();
     }
 }
+    
+void MediaSessionManager::sessionWillEndPlayback(MediaSession& session)
+{
+    LOG(Media, "MediaSessionManager::sessionWillEndPlayback - %p", &session);
+    
+    if (m_sessions.size() < 2)
+        return;
+    
+    size_t pausingSessionIndex = notFound;
+    size_t lastPlayingSessionIndex = notFound;
+    for (size_t i = 0; i < m_sessions.size(); ++i) {
+        MediaSession* oneSession = m_sessions[i];
+        
+        if (oneSession == &session) {
+            pausingSessionIndex = i;
+            continue;
+        }
+        if (oneSession->state() == MediaSession::Playing) {
+            lastPlayingSessionIndex = i;
+            continue;
+        }
+        if (oneSession->state() != MediaSession::Playing)
+            break;
+    }
+    if (lastPlayingSessionIndex == notFound || pausingSessionIndex == notFound)
+        return;
+    
+    if (pausingSessionIndex > lastPlayingSessionIndex)
+        return;
+    
+    m_sessions.remove(pausingSessionIndex);
+    m_sessions.insert(lastPlayingSessionIndex, &session);
+    
+    LOG(Media, "MediaSessionManager::sessionWillEndPlayback - session moved from index %zu to %zu", pausingSessionIndex, lastPlayingSessionIndex);
+}
+
+void MediaSessionManager::setCurrentSession(MediaSession& session)
+{
+    LOG(Media, "MediaSessionManager::setCurrentSession - %p", &session);
+    
+    if (m_sessions.size() < 2)
+        return;
+    
+    size_t index = m_sessions.find(&session);
+    ASSERT(index != notFound);
+    if (!index || index == notFound)
+        return;
 
+    m_sessions.remove(index);
+    m_sessions.insert(0, &session);
+    
+    LOG(Media, "MediaSessionManager::setCurrentSession - session moved from index %zu to 0", index);
+}
+    
+MediaSession* MediaSessionManager::currentSession()
+{
+    if (!m_sessions.size())
+        return nullptr;
+
+    return m_sessions[0];
+}
+    
 bool MediaSessionManager::sessionRestrictsInlineVideoPlayback(const MediaSession& session) const
 {
     MediaSession::MediaType sessionType = session.mediaType();
@@ -190,7 +256,8 @@ bool MediaSessionManager::sessionRestrictsInlineVideoPlayback(const MediaSession
 void MediaSessionManager::applicationWillEnterBackground() const
 {
     LOG(Media, "MediaSessionManager::applicationWillEnterBackground");
-    for (auto* session : m_sessions) {
+    Vector<MediaSession*> sessions = m_sessions;
+    for (auto* session : sessions) {
         if (m_restrictions[session->mediaType()] & BackgroundPlaybackNotPermitted)
             session->beginInterruption();
     }
@@ -199,7 +266,8 @@ void MediaSessionManager::applicationWillEnterBackground() const
 void MediaSessionManager::applicationWillEnterForeground() const
 {
     LOG(Media, "MediaSessionManager::applicationWillEnterForeground");
-    for (auto* session : m_sessions) {
+    Vector<MediaSession*> sessions = m_sessions;
+    for (auto* session : sessions) {
         if (m_restrictions[session->mediaType()] & BackgroundPlaybackNotPermitted)
             session->endInterruption(MediaSession::MayResumePlaying);
     }
@@ -213,9 +281,10 @@ void MediaSessionManager::updateSessionState()
 
 void MediaSessionManager::didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType command)
 {
-    if (!m_activeSession || !m_activeSession->canReceiveRemoteControlCommands())
+    MediaSession* activeSession = currentSession();
+    if (!activeSession || !activeSession->canReceiveRemoteControlCommands())
         return;
-    m_activeSession->didReceiveRemoteControlCommand(command);
+    activeSession->didReceiveRemoteControlCommand(command);
 }
 
 void MediaSessionManager::addClient(MediaSessionManagerClient* client)
index c39b1b6..7c6eafa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -81,7 +81,7 @@ public:
     virtual void resetRestrictions();
 
     virtual void sessionWillBeginPlayback(MediaSession&);
-    virtual void sessionWillEndPlayback(MediaSession&) { }
+    virtual void sessionWillEndPlayback(MediaSession&);
     
     bool sessionRestrictsInlineVideoPlayback(const MediaSession&) const;
 
@@ -101,8 +101,8 @@ protected:
     void addSession(MediaSession&);
     void removeSession(MediaSession&);
     
-    void setCurrentSession(MediaSession* session) { m_activeSession = session; }
-    MediaSession* currentSession() { return m_activeSession; }
+    void setCurrentSession(MediaSession&);
+    MediaSession* currentSession();
     
 private:
     void updateSessionState();
@@ -112,7 +112,6 @@ private:
     Vector<MediaSession*> m_sessions;
     Vector<MediaSessionManagerClient*> m_clients;
     std::unique_ptr<RemoteCommandListener> m_remoteCommandListener;
-    MediaSession* m_activeSession;
     bool m_interrupted;
 };
 
index 3ca2816..8353dc4 100644 (file)
@@ -29,6 +29,7 @@
 #if PLATFORM(IOS)
 
 #import "Logging.h"
+#import "MediaPlayer.h"
 #import "MediaSession.h"
 #import "NotImplemented.h"
 #import "SoftLinking.h"
index 78a4f3c..0e3998b 100644 (file)
@@ -2290,5 +2290,33 @@ void Internals::setMediaSessionRestrictions(const String& mediaTypeString, const
 
     MediaSessionManager::sharedManager().addRestriction(mediaType, restrictions);
 }
-
+    
+void Internals::postRemoteControlCommand(const String& commandString, ExceptionCode& ec)
+{
+    MediaSession::RemoteControlCommandType command;
+    
+    if (equalIgnoringCase(commandString, "Play"))
+        command = MediaSession::PlayCommand;
+    else if (equalIgnoringCase(commandString, "Pause"))
+        command = MediaSession::PauseCommand;
+    else if (equalIgnoringCase(commandString, "Stop"))
+        command = MediaSession::StopCommand;
+    else if (equalIgnoringCase(commandString, "TogglePlayPause"))
+        command = MediaSession::TogglePlayPauseCommand;
+    else if (equalIgnoringCase(commandString, "BeginSeekingBackward"))
+        command = MediaSession::BeginSeekingBackwardCommand;
+    else if (equalIgnoringCase(commandString, "EndSeekingBackward"))
+        command = MediaSession::EndSeekingBackwardCommand;
+    else if (equalIgnoringCase(commandString, "BeginSeekingForward"))
+        command = MediaSession::BeginSeekingForwardCommand;
+    else if (equalIgnoringCase(commandString, "EndSeekingForward"))
+        command = MediaSession::EndSeekingForwardCommand;
+    else {
+        ec = INVALID_ACCESS_ERR;
+        return;
+    }
+    
+    MediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command);
+}
+    
 }
index 5f750fa..6cae899 100644 (file)
@@ -333,7 +333,8 @@ public:
     void endMediaSessionInterruption(const String&);
     void applicationWillEnterForeground() const;
     void applicationWillEnterBackground() const;
-    void setMediaSessionRestrictions(const String& mediaType, const String& restrictions, ExceptionCode& ec);
+    void setMediaSessionRestrictions(const String& mediaType, const String& restrictions, ExceptionCode&);
+    void postRemoteControlCommand(const String&, ExceptionCode&);
 
 private:
     explicit Internals(Document*);
index ccef214..2cc55c7 100644 (file)
     void applicationWillEnterForeground();
     void applicationWillEnterBackground();
     [RaisesException] void setMediaSessionRestrictions(DOMString mediaType, DOMString restrictions);
+    [RaisesException] void postRemoteControlCommand(DOMString command);
 };