[iOS] do not pause video when entering background while playing to external device
authoreric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 May 2014 01:47:20 +0000 (01:47 +0000)
committereric.carlson@apple.com <eric.carlson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 May 2014 01:47:20 +0000 (01:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=132374

Reviewed by Jer Noble.

Source/WebCore:
* WebCore.exp.in: Update beginInterruption signature.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::canOverrideBackgroundPlaybackRestriction): New, return true when
    playing to external device.
* html/HTMLMediaElement.h:

* platform/audio/MediaSession.cpp:
(WebCore::MediaSession::beginInterruption): Add interruption type to beginInterruption.
* platform/audio/MediaSession.h:

* platform/audio/MediaSessionManager.cpp:
(WebCore::MediaSessionManager::beginInterruption): Ditto.
(WebCore::MediaSessionManager::applicationWillEnterBackground): Ditto.
(WebCore::MediaSessionManager::systemWillSleep): Ditto.
* platform/audio/MediaSessionManager.h:

* platform/audio/ios/AudioDestinationIOS.h:
* platform/audio/ios/MediaSessionManagerIOS.mm:
(-[WebMediaSessionHelper interruption:]): Ditto.

* platform/audio/mac/AudioDestinationMac.h: Make most methods private. Add
    canOverrideBackgroundPlaybackRestriction. Add missing overrides.
* testing/Internals.cpp:
(WebCore::Internals::beginMediaSessionInterruption): Pass interruption type.

Source/webkit:
* WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in:

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

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
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/AudioDestinationIOS.h
Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm
Source/WebCore/platform/audio/mac/AudioDestinationMac.h
Source/WebCore/testing/Internals.cpp
Source/WebKit/ChangeLog
Source/WebKit/WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in

index 6c08e34..1df0a4c 100644 (file)
@@ -1,3 +1,36 @@
+2014-04-30  Eric Carlson  <eric.carlson@apple.com>
+
+        [iOS] do not pause video when entering background while playing to external device
+        https://bugs.webkit.org/show_bug.cgi?id=132374
+
+        Reviewed by Jer Noble.
+
+        * WebCore.exp.in: Update beginInterruption signature.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::canOverrideBackgroundPlaybackRestriction): New, return true when
+            playing to external device.
+        * html/HTMLMediaElement.h:
+
+        * platform/audio/MediaSession.cpp:
+        (WebCore::MediaSession::beginInterruption): Add interruption type to beginInterruption.
+        * platform/audio/MediaSession.h:
+
+        * platform/audio/MediaSessionManager.cpp:
+        (WebCore::MediaSessionManager::beginInterruption): Ditto.
+        (WebCore::MediaSessionManager::applicationWillEnterBackground): Ditto.
+        (WebCore::MediaSessionManager::systemWillSleep): Ditto.
+        * platform/audio/MediaSessionManager.h:
+
+        * platform/audio/ios/AudioDestinationIOS.h:
+        * platform/audio/ios/MediaSessionManagerIOS.mm:
+        (-[WebMediaSessionHelper interruption:]): Ditto.
+
+        * platform/audio/mac/AudioDestinationMac.h: Make most methods private. Add 
+            canOverrideBackgroundPlaybackRestriction. Add missing overrides.
+        * testing/Internals.cpp:
+        (WebCore::Internals::beginMediaSessionInterruption): Pass interruption type.
+
 2014-04-30  Manuel Rego Casasnovas  <rego@igalia.com>
 
         Unreviewed, rolling out r167879 and r167942.
index 0cbf3eb..2c64fa9 100644 (file)
@@ -801,7 +801,7 @@ __ZN7WebCore19MediaSessionManager12restrictionsENS_12MediaSession9MediaTypeE
 __ZN7WebCore19MediaSessionManager13sharedManagerEv
 __ZN7WebCore19MediaSessionManager14addRestrictionENS_12MediaSession9MediaTypeEj
 __ZN7WebCore19MediaSessionManager15endInterruptionENS_12MediaSession20EndInterruptionFlagsE
-__ZN7WebCore19MediaSessionManager17beginInterruptionEv
+__ZN7WebCore19MediaSessionManager17beginInterruptionENS_12MediaSession16InterruptionTypeE
 __ZN7WebCore19MediaSessionManager17removeRestrictionENS_12MediaSession9MediaTypeEj
 __ZN7WebCore19MediaSessionManager30didReceiveRemoteControlCommandENS_12MediaSession24RemoteControlCommandTypeE
 __ZN7WebCore19MediaSessionManager9addClientEPNS_25MediaSessionManagerClientE
index 2605e65..3b432f0 100644 (file)
@@ -6181,6 +6181,15 @@ void HTMLMediaElement::didReceiveRemoteControlCommand(MediaSession::RemoteContro
     }
 }
 
+bool HTMLMediaElement::overrideBackgroundPlaybackRestriction() const
+{
+#if ENABLE(IOS_AIRPLAY)
+    if (m_player && m_player->isCurrentPlaybackTargetWireless())
+        return true;
+#endif
+    return false;
+}
+
 bool HTMLMediaElement::doesHaveAttribute(const AtomicString& attribute, AtomicString* value) const
 {
     QualifiedName attributeName(nullAtom, attribute, nullAtom);
index 32956c3..da8f9df 100644 (file)
@@ -717,6 +717,7 @@ private:
     virtual double mediaSessionCurrentTime() const override { return currentTime(); }
     virtual bool canReceiveRemoteControlCommands() const override { return true; }
     virtual void didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType) override;
+    virtual bool overrideBackgroundPlaybackRestriction() const override;
 
     void registerWithDocument(Document&);
     void unregisterWithDocument(Document&);
index a92235f..e3cc2d4 100644 (file)
@@ -76,10 +76,13 @@ void MediaSession::setState(State state)
     m_state = state;
 }
 
-void MediaSession::beginInterruption()
+void MediaSession::beginInterruption(InterruptionType type)
 {
     LOG(Media, "MediaSession::beginInterruption(%p), state = %s", this, stateName(m_state));
 
+    if (type == EnteringBackground && client().overrideBackgroundPlaybackRestriction())
+        return;
+
     m_stateToRestore = state();
     m_notifyingClient = true;
     client().pausePlayback();
index b69114c..d4e3483 100644 (file)
@@ -57,11 +57,16 @@ public:
     State state() const { return m_state; }
     void setState(State);
 
+    enum InterruptionType {
+        SystemSleep,
+        EnteringBackground,
+        SystemInterruption,
+    };
     enum EndInterruptionFlags {
         NoFlags = 0,
         MayResumePlaying = 1 << 0,
     };
-    void beginInterruption();
+    void beginInterruption(InterruptionType);
     void endInterruption(EndInterruptionFlags);
 
     void applicationWillEnterForeground() const;
@@ -127,6 +132,8 @@ public:
     virtual void setShouldBufferData(bool) { }
     virtual bool elementIsHidden() const { return false; }
 
+    virtual bool overrideBackgroundPlaybackRestriction() const = 0;
+
 protected:
     virtual ~MediaSessionClient() { }
 };
index 4e77298..8464e15 100644 (file)
@@ -81,14 +81,14 @@ int MediaSessionManager::count(MediaSession::MediaType type) const
     return count;
 }
 
-void MediaSessionManager::beginInterruption()
+void MediaSessionManager::beginInterruption(MediaSession::InterruptionType type)
 {
     LOG(Media, "MediaSessionManager::beginInterruption");
 
     m_interrupted = true;
     Vector<MediaSession*> sessions = m_sessions;
     for (auto* session : sessions)
-        session->beginInterruption();
+        session->beginInterruption(type);
 }
 
 void MediaSessionManager::endInterruption(MediaSession::EndInterruptionFlags flags)
@@ -263,7 +263,7 @@ void MediaSessionManager::applicationWillEnterBackground() const
     Vector<MediaSession*> sessions = m_sessions;
     for (auto* session : sessions) {
         if (m_restrictions[session->mediaType()] & BackgroundPlaybackNotPermitted)
-            session->beginInterruption();
+            session->beginInterruption(MediaSession::EnteringBackground);
     }
 }
 
@@ -314,7 +314,7 @@ void MediaSessionManager::systemWillSleep()
         return;
 
     for (auto session : m_sessions)
-        session->beginInterruption();
+        session->beginInterruption(MediaSession::SystemSleep);
 }
 
 void MediaSessionManager::systemDidWake()
index 44340f3..11b2e12 100644 (file)
@@ -60,7 +60,7 @@ public:
     bool has(MediaSession::MediaType) const;
     int count(MediaSession::MediaType) const;
 
-    void beginInterruption();
+    void beginInterruption(MediaSession::InterruptionType);
     void endInterruption(MediaSession::EndInterruptionFlags);
 
     void applicationWillEnterForeground() const;
index e245f3a..807b8ba 100644 (file)
@@ -59,6 +59,7 @@ private:
     virtual MediaSession::MediaType mediaType() const { return MediaSession::WebAudio; }
     virtual bool canReceiveRemoteControlCommands() const { return false; }
     virtual void didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType) { }
+    virtual bool overrideBackgroundPlaybackRestriction() const { return false; }
     virtual void pausePlayback() override { stop(); }
     virtual void resumePlayback() override { start(); }
 
index d42206b..71dd444 100644 (file)
@@ -282,7 +282,7 @@ void MediaSessionManageriOS::updateNowPlayingInfo()
             return;
 
         if (type == AVAudioSessionInterruptionTypeBegan)
-            _callback->beginInterruption();
+            _callback->beginInterruption(MediaSession::SystemInterruption);
         else
             _callback->endInterruption(flags);
 
index 47fa9f6..408fbc0 100644 (file)
@@ -44,15 +44,6 @@ public:
     AudioDestinationMac(AudioIOCallback&, float sampleRate);
     virtual ~AudioDestinationMac();
 
-    virtual void start() override;
-    virtual void stop() override;
-    virtual bool isPlaying() override { return m_isPlaying; }
-
-    virtual void pausePlayback() override { stop(); }
-    virtual void resumePlayback() override { start(); }
-
-    virtual float sampleRate() const override { return m_sampleRate; }
-
 private:
     void configure();
 
@@ -61,9 +52,19 @@ private:
 
     OSStatus render(UInt32 numberOfFrames, AudioBufferList* ioData);
 
-    virtual MediaSession::MediaType mediaType() const { return MediaSession::WebAudio; }
-    virtual bool canReceiveRemoteControlCommands() const { return false; }
-    virtual void didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType) { }
+    virtual MediaSession::MediaType mediaType() const override { return MediaSession::WebAudio; }
+    virtual bool canReceiveRemoteControlCommands() const override { return false; }
+    virtual void didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType) override { }
+    virtual bool overrideBackgroundPlaybackRestriction() const override { return false; }
+
+    virtual void start() override;
+    virtual void stop() override;
+    virtual bool isPlaying() override { return m_isPlaying; }
+
+    virtual void pausePlayback() override { stop(); }
+    virtual void resumePlayback() override { start(); }
+
+    virtual float sampleRate() const override { return m_sampleRate; }
 
     AudioUnit m_outputUnit;
     AudioIOCallback& m_callback;
index 5c91c9a..e0be09c 100644 (file)
@@ -2216,7 +2216,7 @@ void Internals::initializeMockMediaSource()
 #if ENABLE(VIDEO)
 void Internals::beginMediaSessionInterruption()
 {
-    MediaSessionManager::sharedManager().beginInterruption();
+    MediaSessionManager::sharedManager().beginInterruption(MediaSession::SystemInterruption);
 }
 
 void Internals::endMediaSessionInterruption(const String& flagsString)
index 859d803..dd4eb48 100644 (file)
@@ -1,3 +1,12 @@
+2014-04-30  Eric Carlson  <eric.carlson@apple.com>
+
+        [iOS] do not pause video when entering background while playing to external device
+        https://bugs.webkit.org/show_bug.cgi?id=132374
+
+        Reviewed by Jer Noble.
+
+        * WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in:
+
 2014-04-30  Anders Carlsson  <andersca@apple.com>
 
         Try yet again to fix the build.
index 9f94289..bcfbcd5 100644 (file)
@@ -242,7 +242,7 @@ EXPORTS
         symbolWithPointer(?shadowRoot@Element@WebCore@@QBEPAVShadowRoot@2@XZ, ?shadowRoot@Element@WebCore@@QEBAPEAVShadowRoot@2@XZ)
 #if ENABLE(VIDEO)
         symbolWithPointer(?sharedManager@MediaSessionManager@WebCore@@SAAAV12@XZ, ?sharedManager@MediaSessionManager@WebCore@@SAAEAV12@XZ)
-        symbolWithPointer(?beginInterruption@MediaSessionManager@WebCore@@QAEXXZ, ?beginInterruption@MediaSessionManager@WebCore@@QEAAXXZ)
+        symbolWithPointer(?beginInterruption@MediaSessionManager@WebCore@@QAEXW4InterruptionType@MediaSession@2@@Z, ?beginInterruption@MediaSessionManager@WebCore@@QAEXW4InterruptionType@MediaSession@2@@Z)
         symbolWithPointer(?endInterruption@MediaSessionManager@WebCore@@QAEXW4EndInterruptionFlags@MediaSession@2@@Z, ?endInterruption@MediaSessionManager@WebCore@@QEAAXW4EndInterruptionFlags@MediaSession@2@@Z)
         symbolWithPointer(?addRestriction@MediaSessionManager@WebCore@@QAEXW4MediaType@MediaSession@2@I@Z, ?addRestriction@MediaSessionManager@WebCore@@QEAAXW4MediaType@MediaSession@2@I@Z)
         symbolWithPointer(?removeRestriction@MediaSessionManager@WebCore@@QAEXW4MediaType@MediaSession@2@I@Z, ?removeRestriction@MediaSessionManager@WebCore@@QEAAXW4MediaType@MediaSession@2@I@Z)