Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add Remote Control command support to HTLMediaElement
https://bugs.webkit.org/show_bug.cgi?id=129926

Reviewed by Eric Carlson.

Support the new MediaSession remote control commands by pulling in code from
MediaControlElementTypes to control scanning.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
* html/HTMLMediaElement.h:
* html/MediaController.cpp:
(MediaController::beginScanning): Moved from MediaControlElementTypes.
(MediaController::endScanning): Ditto.
* html/MediaController.h:
* html/MediaControllerInterface.h:

Remove all the scanning code from MediaControlSeekButtonElement.
* html/shadow/MediaControlElementTypes.cpp:
(WebCore::MediaControlSeekButtonElement::MediaControlSeekButtonElement):
(WebCore::MediaControlSeekButtonElement::setActive):
* html/shadow/MediaControlElementTypes.h:

Canonical link: https://commits.webkit.org/148217@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@165628 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
jernoble committed Mar 14, 2014
1 parent 7136abb commit cbcc664
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 74 deletions.
25 changes: 25 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,28 @@
2014-03-07 Jer Noble <jer.noble@apple.com>

Add Remote Control command support to HTLMediaElement
https://bugs.webkit.org/show_bug.cgi?id=129926

Reviewed by Eric Carlson.

Support the new MediaSession remote control commands by pulling in code from
MediaControlElementTypes to control scanning.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
* html/HTMLMediaElement.h:
* html/MediaController.cpp:
(MediaController::beginScanning): Moved from MediaControlElementTypes.
(MediaController::endScanning): Ditto.
* html/MediaController.h:
* html/MediaControllerInterface.h:

Remove all the scanning code from MediaControlSeekButtonElement.
* html/shadow/MediaControlElementTypes.cpp:
(WebCore::MediaControlSeekButtonElement::MediaControlSeekButtonElement):
(WebCore::MediaControlSeekButtonElement::setActive):
* html/shadow/MediaControlElementTypes.h:

2014-03-14 Krzysztof Czech <k.czech@samsung.com>

Move WebSpeech code to use std::unique_ptr
Expand Down
84 changes: 82 additions & 2 deletions Source/WebCore/html/HTMLMediaElement.cpp
Expand Up @@ -146,6 +146,11 @@

namespace WebCore {

static const double SeekRepeatDelay = 0.1;
static const double SeekTime = 0.2;
static const double ScanRepeatDelay = 1.5;
static const double ScanMaximumRate = 8;

static void setFlags(unsigned& value, unsigned flags)
{
value |= flags;
Expand Down Expand Up @@ -261,6 +266,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
, m_loadTimer(this, &HTMLMediaElement::loadTimerFired)
, m_progressEventTimer(this, &HTMLMediaElement::progressEventTimerFired)
, m_playbackProgressTimer(this, &HTMLMediaElement::playbackProgressTimerFired)
, m_scanTimer(this, &HTMLMediaElement::scanTimerFired)
, m_playedTimeRanges()
, m_asyncEventQueue(*this)
, m_playbackRate(1.0f)
Expand Down Expand Up @@ -294,6 +300,9 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
, m_fragmentStartTime(MediaPlayer::invalidTime())
, m_fragmentEndTime(MediaPlayer::invalidTime())
, m_pendingActionFlags(0)
, m_actionAfterScan(Nothing)
, m_scanType(Scan)
, m_scanDirection(Forward)
, m_playing(false)
, m_isWaitingUntilMediaCanStart(false)
, m_shouldDelayLoadEvent(false)
Expand Down Expand Up @@ -3006,6 +3015,56 @@ void HTMLMediaElement::endScrubbing()
setPausedInternal(false);
}

void HTMLMediaElement::beginScanning(ScanDirection direction)
{
m_scanType = supportsScanning() ? Scan : Seek;
m_scanDirection = direction;

if (m_scanType == Seek) {
// Scanning by seeking requires the video to be paused during scanning.
m_actionAfterScan = paused() ? Nothing : Play;
pause();
} else {
// Scanning by scanning requires the video to be playing during scanninging.
m_actionAfterScan = paused() ? Pause : Nothing;
play();
setPlaybackRate(nextScanRate());
}

m_scanTimer.start(0, m_scanType == Seek ? SeekRepeatDelay : ScanRepeatDelay);
}

void HTMLMediaElement::endScanning()
{
if (m_scanType == Scan)
setPlaybackRate(defaultPlaybackRate());

if (m_actionAfterScan == Play)
play();
else if (m_actionAfterScan == Pause)
pause();

if (m_scanTimer.isActive())
m_scanTimer.stop();
}

double HTMLMediaElement::nextScanRate()
{
double rate = std::min(ScanMaximumRate, fabs(playbackRate() * 2));
if (m_scanDirection == Backward)
rate *= -1;
return rate;
}

void HTMLMediaElement::scanTimerFired(Timer<HTMLMediaElement>&)
{
if (m_scanType == Seek) {
double seekTime = m_scanDirection == Forward ? SeekTime : -SeekTime;
setCurrentTime(currentTime() + seekTime);
} else
setPlaybackRate(nextScanRate());
}

// The spec says to fire periodic timeupdate events (those sent while playing) every
// "15 to 250ms", we choose the slowest frequency
static const double maxTimeupdateEventFrequency = 0.25;
Expand Down Expand Up @@ -5889,8 +5948,29 @@ String HTMLMediaElement::mediaSessionTitle() const

void HTMLMediaElement::didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType command)
{
// FIXME(129926): Add Remote Control support to HTMLMediaElement
UNUSED_PARAM(command);
switch (command) {
case MediaSession::PlayCommand:
play();
break;
case MediaSession::PauseCommand:
pause();
break;
case MediaSession::TogglePlayPauseCommand:
canPlay() ? play() : pause();
break;
case MediaSession::BeginSeekingBackwardCommand:
beginScanning(Backward);
break;
case MediaSession::BeginSeekingForwardCommand:
beginScanning(Forward);
break;
case MediaSession::EndSeekingBackwardCommand:
case MediaSession::EndSeekingForwardCommand:
endScanning();
break;
default:
{ } // Do nothing
}
}

}
Expand Down
17 changes: 16 additions & 1 deletion Source/WebCore/html/HTMLMediaElement.h
Expand Up @@ -249,7 +249,11 @@ class HTMLMediaElement
void togglePlayState();
virtual void beginScrubbing() override;
virtual void endScrubbing() override;


virtual void beginScanning(ScanDirection) override;
virtual void endScanning() override;
double nextScanRate();

virtual bool canPlay() const override;

double percentLoaded() const;
Expand Down Expand Up @@ -583,6 +587,7 @@ class HTMLMediaElement
void loadTimerFired(Timer<HTMLMediaElement>&);
void progressEventTimerFired(Timer<HTMLMediaElement>&);
void playbackProgressTimerFired(Timer<HTMLMediaElement>&);
void scanTimerFired(Timer<HTMLMediaElement>&);
void startPlaybackProgressTimer();
void startProgressEventTimer();
void stopPeriodicTimers();
Expand Down Expand Up @@ -703,6 +708,7 @@ class HTMLMediaElement
Timer<HTMLMediaElement> m_loadTimer;
Timer<HTMLMediaElement> m_progressEventTimer;
Timer<HTMLMediaElement> m_playbackProgressTimer;
Timer<HTMLMediaElement> m_scanTimer;
RefPtr<TimeRanges> m_playedTimeRanges;
GenericEventQueue m_asyncEventQueue;

Expand Down Expand Up @@ -769,6 +775,15 @@ class HTMLMediaElement
typedef unsigned PendingActionFlags;
PendingActionFlags m_pendingActionFlags;

enum ActionAfterScanType {
Nothing, Play, Pause
};
ActionAfterScanType m_actionAfterScan;

enum ScanType { Seek, Scan };
ScanType m_scanType;
ScanDirection m_scanDirection;

bool m_playing : 1;
bool m_isWaitingUntilMediaCanStart : 1;
bool m_shouldDelayLoadEvent : 1;
Expand Down
12 changes: 12 additions & 0 deletions Source/WebCore/html/MediaController.cpp
Expand Up @@ -612,6 +612,18 @@ void MediaController::endScrubbing()
m_clock->start();
}

void MediaController::beginScanning(ScanDirection direction)
{
for (auto& mediaElement : m_mediaElements)
mediaElement->beginScanning(direction);
}

void MediaController::endScanning()
{
for (auto& mediaElement : m_mediaElements)
mediaElement->endScanning();
}

bool MediaController::canPlay() const
{
if (m_paused)
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/html/MediaController.h
Expand Up @@ -98,6 +98,8 @@ class MediaController final : public RefCounted<MediaController>, public MediaCo

virtual void beginScrubbing() override;
virtual void endScrubbing() override;
virtual void beginScanning(ScanDirection) override;
virtual void endScanning() override;

virtual bool canPlay() const override;

Expand Down
7 changes: 7 additions & 0 deletions Source/WebCore/html/MediaControllerInterface.h
Expand Up @@ -84,6 +84,13 @@ class MediaControllerInterface {
virtual void beginScrubbing() = 0;
virtual void endScrubbing() = 0;

enum ScanDirection {
Backward,
Forward,
};
virtual void beginScanning(ScanDirection) = 0;
virtual void endScanning() = 0;

virtual bool canPlay() const = 0;

virtual bool isLiveStream() const = 0;
Expand Down
62 changes: 2 additions & 60 deletions Source/WebCore/html/shadow/MediaControlElementTypes.cpp
Expand Up @@ -46,12 +46,6 @@ using namespace HTMLNames;

class Event;

// FIXME: These constants may need to be tweaked to better match the seeking in the QuickTime plug-in.
static const double cSkipRepeatDelay = 0.1;
static const double cSkipTime = 0.2;
static const double cScanRepeatDelay = 1.5;
static const double cScanMaximumRate = 8;

HTMLMediaElement* parentMediaElement(Node* node)
{
if (!node)
Expand Down Expand Up @@ -168,9 +162,6 @@ void MediaControlMuteButtonElement::updateDisplayType()

MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document& document, MediaControlElementType displayType)
: MediaControlInputElement(document, displayType)
, m_actionOnStop(Nothing)
, m_seekType(Skip)
, m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired)
{
}

Expand All @@ -188,62 +179,13 @@ void MediaControlSeekButtonElement::setActive(bool flag, bool pause)
return;

if (flag)
startTimer();
mediaController()->beginScanning(isForwardButton() ? MediaControllerInterface::Forward : MediaControllerInterface::Backward);
else
stopTimer();
mediaController()->endScanning();

MediaControlInputElement::setActive(flag, pause);
}

void MediaControlSeekButtonElement::startTimer()
{
m_seekType = mediaController()->supportsScanning() ? Scan : Skip;

if (m_seekType == Skip) {
// Seeking by skipping requires the video to be paused during seeking.
m_actionOnStop = mediaController()->paused() ? Nothing : Play;
mediaController()->pause();
} else {
// Seeking by scanning requires the video to be playing during seeking.
m_actionOnStop = mediaController()->paused() ? Pause : Nothing;
mediaController()->play();
mediaController()->setPlaybackRate(nextRate());
}

m_seekTimer.start(0, m_seekType == Skip ? cSkipRepeatDelay : cScanRepeatDelay);
}

void MediaControlSeekButtonElement::stopTimer()
{
if (m_seekType == Scan)
mediaController()->setPlaybackRate(mediaController()->defaultPlaybackRate());

if (m_actionOnStop == Play)
mediaController()->play();
else if (m_actionOnStop == Pause)
mediaController()->pause();

if (m_seekTimer.isActive())
m_seekTimer.stop();
}

double MediaControlSeekButtonElement::nextRate() const
{
double rate = std::min(cScanMaximumRate, fabs(mediaController()->playbackRate() * 2));
if (!isForwardButton())
rate *= -1;
return rate;
}

void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>&)
{
if (m_seekType == Skip) {
double skipTime = isForwardButton() ? cSkipTime : -cSkipTime;
mediaController()->setCurrentTime(mediaController()->currentTime() + skipTime);
} else
mediaController()->setPlaybackRate(nextRate());
}

// ----------------------------

MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document& document)
Expand Down
11 changes: 0 additions & 11 deletions Source/WebCore/html/shadow/MediaControlElementTypes.h
Expand Up @@ -170,17 +170,6 @@ class MediaControlSeekButtonElement : public MediaControlInputElement {

private:
virtual void setActive(bool /*flag*/ = true, bool /*pause*/ = false) override final;

void startTimer();
void stopTimer();
double nextRate() const;
void seekTimerFired(Timer<MediaControlSeekButtonElement>&);

enum ActionType { Nothing, Play, Pause };
ActionType m_actionOnStop;
enum SeekType { Skip, Scan };
SeekType m_seekType;
Timer<MediaControlSeekButtonElement> m_seekTimer;
};

// ----------------------------
Expand Down

0 comments on commit cbcc664

Please sign in to comment.