Changeset 165552 in webkit


Ignore:
Timestamp:
Mar 13, 2014 11:24:06 AM (10 years ago)
Author:
eric.carlson@apple.com
Message:

[iOS] Sync media playback with now playing
https://bugs.webkit.org/show_bug.cgi?id=130172

Reviewed by Jer Noble.

  • html/HTMLMediaElement.cpp:

(WebCore::HTMLMediaElement::play): Move clientWillBeginPlayback to

playInternal so it is called every time playback begins.

(WebCore::HTMLMediaElement::playInternal): Call clientWillBeginPlayback.
(WebCore::HTMLMediaElement::pause): Move clientWillPausePlayback to

playInternal so it is called every time playback begins.

(WebCore::HTMLMediaElement::playInternal): Call clientWillPausePlayback.
(WebCore::HTMLMediaElement::mediaSessionTitle): New. Return the 'title' attribute,

or currenSrc if that is empty.

  • html/HTMLMediaElement.h:

(WebCore::HTMLMediaElement::mediaSessionDuration): Return duration.
(WebCore::HTMLMediaElement::mediaSessionCurrentTime): Return current time.

  • platform/audio/MediaSession.cpp:

(WebCore::MediaSession::clientWillPausePlayback): New, passthrough to the

media element.

(WebCore::MediaSession::title): Ditto.
(WebCore::MediaSession::duration): Ditto.
(WebCore::MediaSession::currentTime): Ditto.

  • platform/audio/MediaSession.h:

(WebCore::MediaSessionClient::mediaSessionTitle):
(WebCore::MediaSessionClient::mediaSessionDuration):
(WebCore::MediaSessionClient::mediaSessionCurrentTime):

  • platform/audio/MediaSessionManager.cpp:

(WebCore::MediaSessionManager::MediaSessionManager): Initialize m_activeSession.
(WebCore::MediaSessionManager::removeSession): Set m_activeSession if the session

being removed is currently active.

(WebCore::MediaSessionManager::sessionWillBeginPlayback): Set m_activeSession.

  • platform/audio/MediaSessionManager.h:

(WebCore::MediaSessionManager::sessionWillEndPlayback):
(WebCore::MediaSessionManager::setCurrentSession):
(WebCore::MediaSessionManager::currentSession):

  • platform/audio/ios/MediaSessionManagerIOS.h:
  • platform/audio/ios/MediaSessionManagerIOS.mm:

(WebCore::MediaSessionManageriOS::sessionWillBeginPlayback): Call updateNowPlayingInfo.
(WebCore::MediaSessionManageriOS::sessionWillEndPlayback): Ditto.
(WebCore::MediaSessionManageriOS::updateNowPlayingInfo): Update MPNowPlayingInfoCenter

with the current media item's title, duration, and current time.

(-[WebMediaSessionHelper initWithCallback:]): Turn on deliver of remote control

events, even though we don't respond to them yet, or Now Playing won't work.

Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r165549 r165552  
     12014-03-12  Eric Carlson  <eric.carlson@apple.com>
     2
     3        [iOS] Sync media playback with now playing
     4        https://bugs.webkit.org/show_bug.cgi?id=130172
     5
     6        Reviewed by Jer Noble.
     7       
     8        * html/HTMLMediaElement.cpp:
     9        (WebCore::HTMLMediaElement::play): Move clientWillBeginPlayback to
     10            playInternal so it is called every time playback begins.
     11        (WebCore::HTMLMediaElement::playInternal): Call clientWillBeginPlayback.
     12        (WebCore::HTMLMediaElement::pause): Move clientWillPausePlayback to
     13            playInternal so it is called every time playback begins.
     14        (WebCore::HTMLMediaElement::playInternal): Call clientWillPausePlayback.
     15        (WebCore::HTMLMediaElement::mediaSessionTitle): New. Return the 'title' attribute,
     16            or currenSrc if that is empty.
     17        * html/HTMLMediaElement.h:
     18        (WebCore::HTMLMediaElement::mediaSessionDuration): Return duration.
     19        (WebCore::HTMLMediaElement::mediaSessionCurrentTime): Return current time.
     20
     21        * platform/audio/MediaSession.cpp:
     22        (WebCore::MediaSession::clientWillPausePlayback): New, passthrough to the
     23            media element.
     24        (WebCore::MediaSession::title): Ditto.
     25        (WebCore::MediaSession::duration): Ditto.
     26        (WebCore::MediaSession::currentTime): Ditto.
     27        * platform/audio/MediaSession.h:
     28        (WebCore::MediaSessionClient::mediaSessionTitle):
     29        (WebCore::MediaSessionClient::mediaSessionDuration):
     30        (WebCore::MediaSessionClient::mediaSessionCurrentTime):
     31
     32        * platform/audio/MediaSessionManager.cpp:
     33        (WebCore::MediaSessionManager::MediaSessionManager): Initialize m_activeSession.
     34        (WebCore::MediaSessionManager::removeSession): Set m_activeSession if the session
     35            being removed is currently active.
     36        (WebCore::MediaSessionManager::sessionWillBeginPlayback): Set m_activeSession.
     37        * platform/audio/MediaSessionManager.h:
     38        (WebCore::MediaSessionManager::sessionWillEndPlayback):
     39        (WebCore::MediaSessionManager::setCurrentSession):
     40        (WebCore::MediaSessionManager::currentSession):
     41
     42        * platform/audio/ios/MediaSessionManagerIOS.h:
     43        * platform/audio/ios/MediaSessionManagerIOS.mm:
     44        (WebCore::MediaSessionManageriOS::sessionWillBeginPlayback): Call updateNowPlayingInfo.
     45        (WebCore::MediaSessionManageriOS::sessionWillEndPlayback): Ditto.
     46        (WebCore::MediaSessionManageriOS::updateNowPlayingInfo): Update MPNowPlayingInfoCenter
     47            with the current media item's title, duration, and current time.
     48        (-[WebMediaSessionHelper initWithCallback:]): Turn on deliver of remote control
     49            events, even though we don't respond to them yet, or Now Playing won't work.
     50
    1512014-03-13  Radu Stavila  <stavila@adobe.com>
    252
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r165344 r165552  
    26852685        removeBehaviorsRestrictionsAfterFirstUserGesture();
    26862686
     2687    playInternal();
     2688}
     2689
     2690void HTMLMediaElement::playInternal()
     2691{
     2692    LOG(Media, "HTMLMediaElement::playInternal");
     2693   
    26872694    if (!m_mediaSession->clientWillBeginPlayback()) {
    26882695        LOG(Media, "  returning because of interruption");
     
    26902697    }
    26912698   
    2692     playInternal();
    2693 }
    2694 
    2695 void HTMLMediaElement::playInternal()
    2696 {
    2697     LOG(Media, "HTMLMediaElement::playInternal");
    2698 
    26992699    // 4.8.10.9. Playing the media resource
    27002700    if (!m_player || m_networkState == NETWORK_EMPTY)
     
    27322732        return;
    27332733
     2734    pauseInternal();
     2735}
     2736
     2737
     2738void HTMLMediaElement::pauseInternal()
     2739{
     2740    LOG(Media, "HTMLMediaElement::pauseInternal");
     2741
    27342742    if (!m_mediaSession->clientWillPausePlayback()) {
    27352743        LOG(Media, "  returning because of interruption");
    27362744        return;
    27372745    }
    2738 
    2739     pauseInternal();
    2740 }
    2741 
    2742 
    2743 void HTMLMediaElement::pauseInternal()
    2744 {
    2745     LOG(Media, "HTMLMediaElement::pauseInternal");
    2746 
     2746   
    27472747    // 4.8.10.9. Playing the media resource
    27482748    if (!m_player || m_networkState == NETWORK_EMPTY) {
     
    58795879        play();
    58805880}
    5881 
    5882 }
    5883 
    5884 #endif
     5881   
     5882String HTMLMediaElement::mediaSessionTitle() const
     5883{
     5884    if (fastHasAttribute(titleAttr))
     5885        return fastGetAttribute(titleAttr);
     5886   
     5887    return m_currentSrc;
     5888}
     5889
     5890}
     5891
     5892#endif
  • trunk/Source/WebCore/html/HTMLMediaElement.h

    r165344 r165552  
    691691#endif
    692692
     693    // MediaSessionClient Overrides
    693694    virtual MediaSession::MediaType mediaType() const override;
    694695    virtual void pausePlayback() override;
    695696    virtual void resumePlayback() override;
     697    virtual String mediaSessionTitle() const override;
     698    virtual double mediaSessionDuration() const override { return duration(); }
     699    virtual double mediaSessionCurrentTime() const override { return currentTime(); }
    696700
    697701    Timer<HTMLMediaElement> m_loadTimer;
  • trunk/Source/WebCore/platform/audio/MediaSession.cpp

    r163971 r165552  
    116116   
    117117    setState(Paused);
     118    MediaSessionManager::sharedManager().sessionWillEndPlayback(*this);
    118119    return true;
    119120}
     
    129130    return m_client.mediaType();
    130131}
     132
     133String MediaSession::title() const
     134{
     135    return m_client.mediaSessionTitle();
     136}
     137
     138double MediaSession::duration() const
     139{
     140    return m_client.mediaSessionDuration();
     141}
     142
     143double MediaSession::currentTime() const
     144{
     145    return m_client.mediaSessionCurrentTime();
     146}
    131147   
    132148}
  • trunk/Source/WebCore/platform/audio/MediaSession.h

    r163390 r165552  
    2727#define MediaSession_h
    2828
     29#include "MediaPlayer.h"
    2930#include <wtf/Noncopyable.h>
    3031
     
    7172
    7273    void pauseSession();
     74   
     75    String title() const;
     76    double duration() const;
     77    double currentTime() const;
    7378
    7479protected:
     
    9095    virtual void resumePlayback() = 0;
    9196    virtual void pausePlayback() = 0;
    92 
     97   
     98    virtual String mediaSessionTitle() const { return String(); }
     99    virtual double mediaSessionDuration() const { return MediaPlayer::invalidTime(); }
     100    virtual double mediaSessionCurrentTime() const { return MediaPlayer::invalidTime(); }
     101   
    93102protected:
    94103    virtual ~MediaSessionClient() { }
  • trunk/Source/WebCore/platform/audio/MediaSessionManager.cpp

    r163657 r165552  
    4141
    4242MediaSessionManager::MediaSessionManager()
    43     : m_interrupted(false)
     43    : m_activeSession(nullptr)
     44    , m_interrupted(false)
    4445{
    4546    resetRestrictions();
     
    110111    if (index == notFound)
    111112        return;
    112 
     113   
     114    if (m_activeSession == &session)
     115        setCurrentSession(nullptr);
     116   
    113117    m_sessions.remove(index);
    114118    updateSessionState();
     
    133137}
    134138
    135 void MediaSessionManager::sessionWillBeginPlayback(const MediaSession& session) const
     139void MediaSessionManager::sessionWillBeginPlayback(const MediaSession& session)
    136140{
     141    setCurrentSession(&session);
     142   
    137143    MediaSession::MediaType sessionType = session.mediaType();
    138144    SessionRestrictions restrictions = m_restrictions[sessionType];
  • trunk/Source/WebCore/platform/audio/MediaSessionManager.h

    r164661 r165552  
    6666    virtual void resetRestrictions();
    6767
    68     void sessionWillBeginPlayback(const MediaSession&) const;
    69 
     68    virtual void sessionWillBeginPlayback(const MediaSession&);
     69    virtual void sessionWillEndPlayback(const MediaSession&) { }
     70   
    7071    bool sessionRestrictsInlineVideoPlayback(const MediaSession&) const;
    7172
     
    8081    void addSession(MediaSession&);
    8182    void removeSession(MediaSession&);
    82 
     83   
     84    void setCurrentSession(const MediaSession* session) { m_activeSession = session; }
     85    const MediaSession* currentSession() { return m_activeSession; }
     86   
    8387private:
    8488    void updateSessionState();
     
    8791
    8892    Vector<MediaSession*> m_sessions;
     93    const MediaSession* m_activeSession;
    8994    bool m_interrupted;
    9095};
  • trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h

    r165028 r165552  
    4949    friend class MediaSessionManager;
    5050
     51    virtual void sessionWillBeginPlayback(const MediaSession&) override;
     52    virtual void sessionWillEndPlayback(const MediaSession&) override;
     53   
     54    void updateNowPlayingInfo();
     55   
    5156    virtual void resetRestrictions() override;
    5257
  • trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm

    r165028 r165552  
    3636#import "WebCoreThreadRun.h"
    3737#import <AVFoundation/AVAudioSession.h>
     38#import <MediaPlayer/MPMediaItem.h>
     39#import <MediaPlayer/MPNowPlayingInfoCenter.h>
    3840#import <UIKit/UIApplication.h>
    3941#import <objc/runtime.h>
     
    4143
    4244SOFT_LINK_FRAMEWORK(AVFoundation)
    43 SOFT_LINK_FRAMEWORK(UIKit)
    44 
    4545SOFT_LINK_CLASS(AVFoundation, AVAudioSession)
    46 
    4746SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionNotification, NSString *)
    4847SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionTypeKey, NSString *)
    4948SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionOptionKey, NSString *)
    50 SOFT_LINK_POINTER(UIKit, UIApplicationWillResignActiveNotification, NSString *)
    51 SOFT_LINK_POINTER(UIKit, UIApplicationWillEnterForegroundNotification, NSString *)
    52 SOFT_LINK_POINTER(UIKit, UIApplicationDidBecomeActiveNotification, NSString *)
    5349
    5450#define AVAudioSession getAVAudioSessionClass()
     
    5652#define AVAudioSessionInterruptionTypeKey getAVAudioSessionInterruptionTypeKey()
    5753#define AVAudioSessionInterruptionOptionKey getAVAudioSessionInterruptionOptionKey()
     54
     55SOFT_LINK_FRAMEWORK(UIKit)
     56SOFT_LINK_CLASS(UIKit, UIApplication)
     57SOFT_LINK_POINTER(UIKit, UIApplicationWillResignActiveNotification, NSString *)
     58SOFT_LINK_POINTER(UIKit, UIApplicationWillEnterForegroundNotification, NSString *)
     59SOFT_LINK_POINTER(UIKit, UIApplicationDidBecomeActiveNotification, NSString *)
     60
     61#define UIApplication getUIApplicationClass()
    5862#define UIApplicationWillResignActiveNotification getUIApplicationWillResignActiveNotification()
    5963#define UIApplicationWillEnterForegroundNotification getUIApplicationWillEnterForegroundNotification()
    6064#define UIApplicationDidBecomeActiveNotification getUIApplicationDidBecomeActiveNotification()
     65
     66SOFT_LINK_FRAMEWORK(MediaPlayer)
     67SOFT_LINK_CLASS(MediaPlayer, MPNowPlayingInfoCenter)
     68SOFT_LINK_POINTER(MediaPlayer, MPMediaItemPropertyTitle, NSString *)
     69SOFT_LINK_POINTER(MediaPlayer, MPMediaItemPropertyPlaybackDuration, NSString *)
     70SOFT_LINK_POINTER(MediaPlayer, MPNowPlayingInfoPropertyElapsedPlaybackTime, NSString *)
     71SOFT_LINK_POINTER(MediaPlayer, MPNowPlayingInfoPropertyPlaybackRate, NSString *)
     72
     73#define MPMediaItemPropertyTitle getMPMediaItemPropertyTitle()
     74#define MPMediaItemPropertyPlaybackDuration getMPMediaItemPropertyPlaybackDuration()
     75#define MPNowPlayingInfoPropertyElapsedPlaybackTime getMPNowPlayingInfoPropertyElapsedPlaybackTime()
     76#define MPNowPlayingInfoPropertyPlaybackRate getMPNowPlayingInfoPropertyPlaybackRate()
    6177
    6278NSString* WebUIApplicationWillResignActiveNotification = @"WebUIApplicationWillResignActiveNotification";
     
    120136}
    121137#endif
     138   
     139void MediaSessionManageriOS::sessionWillBeginPlayback(const MediaSession& session)
     140{
     141    MediaSessionManager::sessionWillBeginPlayback(session);
     142    updateNowPlayingInfo();
     143}
     144   
     145void MediaSessionManageriOS::sessionWillEndPlayback(const MediaSession& session)
     146{
     147    MediaSessionManager::sessionWillEndPlayback(session);
     148    updateNowPlayingInfo();
     149}
     150   
     151void MediaSessionManageriOS::updateNowPlayingInfo()
     152{
     153    MPNowPlayingInfoCenter *nowPlaying = (MPNowPlayingInfoCenter *)[getMPNowPlayingInfoCenterClass() defaultCenter];
     154    const MediaSession* currentSession = this->currentSession();
     155   
     156    if (!currentSession) {
     157        [nowPlaying setNowPlayingInfo:nil];
     158        return;
     159    }
     160   
     161    RetainPtr<NSMutableDictionary> info = adoptNS([[NSMutableDictionary alloc] init]);
     162   
     163    String title = currentSession->title();
     164    if (!title.isEmpty())
     165        [info setValue:static_cast<NSString *>(title) forKey:MPMediaItemPropertyTitle];
     166   
     167    double duration = currentSession->duration();
     168    if (std::isfinite(duration) && duration != MediaPlayer::invalidTime())
     169        [info setValue:@(duration) forKey:MPMediaItemPropertyPlaybackDuration];
     170   
     171    double currentTime = currentSession->currentTime();
     172    if (std::isfinite(currentTime))
     173        [info setValue:@(currentTime) forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
     174   
     175    [info setValue:(currentSession->state() == MediaSession::Playing ? @YES : @NO) forKey:MPNowPlayingInfoPropertyPlaybackRate];
     176    [nowPlaying setNowPlayingInfo:info.get()];
     177}
    122178
    123179} // namespace WebCore
     
    135191    [center addObserver:self selector:@selector(interruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
    136192
    137     // FIXME: These need to be piped through from the UI process in WK2 mode.
    138193    [center addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
    139194    [center addObserver:self selector:@selector(applicationWillEnterForeground:) name:WebUIApplicationWillEnterForegroundNotification object:nil];
     
    142197    [center addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
    143198    [center addObserver:self selector:@selector(applicationWillResignActive:) name:WebUIApplicationWillResignActiveNotification object:nil];
    144 
     199   
     200    // Now playing won't work unless we turn on the delivery of remote control events.
     201    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
     202   
    145203    return self;
    146204}
Note: See TracChangeset for help on using the changeset viewer.