mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 841493 - Move HTMLMediaElement to WebIDL, r=Ms2ger
This commit is contained in:
parent
eb3d295f7f
commit
f1041ff584
@ -27,6 +27,8 @@
|
||||
#include "DecoderTraits.h"
|
||||
#include "MediaMetadataManager.h"
|
||||
#include "AudioChannelAgent.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
|
||||
// Define to output information on decoding and painting framerate
|
||||
/* #define DEBUG_FRAME_RATE 1 */
|
||||
@ -42,6 +44,8 @@ class MediaDecoder;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MediaError;
|
||||
|
||||
class HTMLMediaElement : public nsGenericHTMLElement,
|
||||
public nsIObserver,
|
||||
public MediaDecoderOwner,
|
||||
@ -318,12 +322,194 @@ public:
|
||||
*/
|
||||
virtual void FireTimeUpdate(bool aPeriodic) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
MediaStream* GetSrcMediaStream()
|
||||
MediaStream* GetSrcMediaStream() const
|
||||
{
|
||||
NS_ASSERTION(mSrcStream, "Don't call this when not playing a stream");
|
||||
return mSrcStream->GetStream();
|
||||
}
|
||||
|
||||
// WebIDL
|
||||
|
||||
MediaError* GetError() const
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
|
||||
// XPCOM GetSrc() is OK
|
||||
void SetSrc(const nsAString& aSrc, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::src, aSrc, aRv);
|
||||
}
|
||||
|
||||
// XPCOM GetCurrentSrc() is OK
|
||||
|
||||
// XPCOM GetCrossorigin() is OK
|
||||
void SetCrossorigin(const nsAString& aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::crossorigin, aValue, aRv);
|
||||
}
|
||||
|
||||
uint16_t NetworkState() const
|
||||
{
|
||||
return mNetworkState;
|
||||
}
|
||||
|
||||
// XPCOM GetPreload() is OK
|
||||
void SetPreload(const nsAString& aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::preload, aValue, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<TimeRanges> Buffered() const;
|
||||
|
||||
// XPCOM Load() is OK
|
||||
|
||||
// XPCOM CanPlayType() is OK
|
||||
|
||||
uint16_t ReadyState() const
|
||||
{
|
||||
return mReadyState;
|
||||
}
|
||||
|
||||
bool Seeking() const;
|
||||
|
||||
double CurrentTime() const;
|
||||
|
||||
void SetCurrentTime(double aCurrentTime, ErrorResult& aRv);
|
||||
|
||||
double Duration() const;
|
||||
|
||||
bool Paused() const
|
||||
{
|
||||
return mPaused;
|
||||
}
|
||||
|
||||
double DefaultPlaybackRate() const
|
||||
{
|
||||
return mDefaultPlaybackRate;
|
||||
}
|
||||
|
||||
void SetDefaultPlaybackRate(double aDefaultPlaybackRate, ErrorResult& aRv);
|
||||
|
||||
double PlaybackRate() const
|
||||
{
|
||||
return mPlaybackRate;
|
||||
}
|
||||
|
||||
void SetPlaybackRate(double aPlaybackRate, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<TimeRanges> Played();
|
||||
|
||||
already_AddRefed<TimeRanges> Seekable() const;
|
||||
|
||||
bool Ended();
|
||||
|
||||
bool Autoplay() const
|
||||
{
|
||||
return GetBoolAttr(nsGkAtoms::autoplay);
|
||||
}
|
||||
|
||||
void SetAutoplay(bool aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLBoolAttr(nsGkAtoms::autoplay, aValue, aRv);
|
||||
}
|
||||
|
||||
bool Loop() const
|
||||
{
|
||||
return GetBoolAttr(nsGkAtoms::loop);
|
||||
}
|
||||
|
||||
void SetLoop(bool aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLBoolAttr(nsGkAtoms::loop, aValue, aRv);
|
||||
}
|
||||
|
||||
void Play(ErrorResult& aRv);
|
||||
|
||||
void Pause(ErrorResult& aRv);
|
||||
|
||||
bool Controls() const
|
||||
{
|
||||
return GetBoolAttr(nsGkAtoms::controls);
|
||||
}
|
||||
|
||||
void SetControls(bool aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLBoolAttr(nsGkAtoms::controls, aValue, aRv);
|
||||
}
|
||||
|
||||
double Volume() const
|
||||
{
|
||||
return mVolume;
|
||||
}
|
||||
|
||||
void SetVolume(double aVolume, ErrorResult& aRv);
|
||||
|
||||
bool Muted() const
|
||||
{
|
||||
return mMuted;
|
||||
}
|
||||
|
||||
// XPCOM SetMuted() is OK
|
||||
|
||||
bool DefaultMuted() const
|
||||
{
|
||||
return GetBoolAttr(nsGkAtoms::muted);
|
||||
}
|
||||
|
||||
void SetDefaultMuted(bool aMuted, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLBoolAttr(nsGkAtoms::muted, aMuted, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMMediaStream> GetMozSrcObject() const;
|
||||
|
||||
void SetMozSrcObject(DOMMediaStream& aValue);
|
||||
|
||||
double InitialTime();
|
||||
|
||||
bool MozPreservesPitch() const
|
||||
{
|
||||
return mPreservesPitch;
|
||||
}
|
||||
|
||||
// XPCOM MozPreservesPitch() is OK
|
||||
|
||||
bool MozAutoplayEnabled() const
|
||||
{
|
||||
return mAutoplayEnabled;
|
||||
}
|
||||
|
||||
already_AddRefed<DOMMediaStream> MozCaptureStream(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMMediaStream> MozCaptureStreamUntilEnded(ErrorResult& aRv);
|
||||
|
||||
bool MozAudioCaptured() const
|
||||
{
|
||||
return mAudioCaptured;
|
||||
}
|
||||
|
||||
uint32_t GetMozChannels(ErrorResult& aRv) const;
|
||||
|
||||
uint32_t GetMozSampleRate(ErrorResult& aRv) const;
|
||||
|
||||
uint32_t GetMozFrameBufferLength(ErrorResult& aRv) const;
|
||||
|
||||
void SetMozFrameBufferLength(uint32_t aValue, ErrorResult& aRv);
|
||||
|
||||
JSObject* MozGetMetadata(JSContext* aCx, ErrorResult& aRv);
|
||||
|
||||
void MozLoadFrom(HTMLMediaElement& aOther, ErrorResult& aRv);
|
||||
|
||||
double MozFragmentEnd();
|
||||
|
||||
// XPCOM GetMozAudioChannelType() is OK
|
||||
|
||||
void SetMozAudioChannelType(const nsAString& aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::mozaudiochannel, aValue, aRv);
|
||||
}
|
||||
|
||||
protected:
|
||||
class MediaLoadListener;
|
||||
class StreamListener;
|
||||
@ -335,7 +521,7 @@ protected:
|
||||
public:
|
||||
WakeLockBoolWrapper(bool val = false) : mValue(val), mOuter(NULL), mWakeLock(NULL) {}
|
||||
void SetOuter(HTMLMediaElement* outer) { mOuter = outer; }
|
||||
operator bool() { return mValue; }
|
||||
operator bool() const { return mValue; }
|
||||
WakeLockBoolWrapper& operator=(bool val);
|
||||
bool operator !() const { return !mValue; }
|
||||
private:
|
||||
@ -654,7 +840,7 @@ protected:
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
|
||||
// Error attribute
|
||||
nsCOMPtr<nsIDOMMediaError> mError;
|
||||
nsRefPtr<MediaError> mError;
|
||||
|
||||
// The current media load ID. This is incremented every time we start a
|
||||
// new load. Async events note the ID when they're first sent, and only fire
|
||||
|
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/HTMLMediaElementBinding.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
@ -442,21 +443,35 @@ NS_IMPL_BOOL_ATTR(HTMLMediaElement, DefaultMuted, muted)
|
||||
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLMediaElement, Preload, preload, NULL)
|
||||
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLMediaElement, MozAudioChannelType, mozaudiochannel, "normal")
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::GetMozSrcObject(nsIDOMMediaStream** aStream)
|
||||
already_AddRefed<DOMMediaStream>
|
||||
HTMLMediaElement::GetMozSrcObject() const
|
||||
{
|
||||
NS_ASSERTION(!mSrcAttrStream || mSrcAttrStream->GetStream(),
|
||||
"MediaStream should have been set up properly");
|
||||
nsRefPtr<DOMMediaStream> stream = mSrcAttrStream;
|
||||
return stream.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::GetMozSrcObject(nsIDOMMediaStream** aStream)
|
||||
{
|
||||
nsRefPtr<DOMMediaStream> stream = GetMozSrcObject();
|
||||
stream.forget(aStream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::SetMozSrcObject(DOMMediaStream& aValue)
|
||||
{
|
||||
mSrcAttrStream = &aValue;
|
||||
Load();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::SetMozSrcObject(nsIDOMMediaStream* aStream)
|
||||
{
|
||||
mSrcAttrStream = static_cast<DOMMediaStream*>(aStream);
|
||||
Load();
|
||||
DOMMediaStream* stream = static_cast<DOMMediaStream*>(aStream);
|
||||
SetMozSrcObject(*stream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -477,13 +492,23 @@ NS_IMETHODIMP HTMLMediaElement::GetError(nsIDOMMediaError * *aError)
|
||||
}
|
||||
|
||||
/* readonly attribute boolean ended; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetEnded(bool *aEnded)
|
||||
bool
|
||||
HTMLMediaElement::Ended()
|
||||
{
|
||||
if (mSrcStream) {
|
||||
*aEnded = GetSrcMediaStream()->IsFinished();
|
||||
} else if (mDecoder) {
|
||||
*aEnded = mDecoder->IsEnded();
|
||||
return GetSrcMediaStream()->IsFinished();
|
||||
}
|
||||
|
||||
if (mDecoder) {
|
||||
return mDecoder->IsEnded();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::GetEnded(bool* aEnded)
|
||||
{
|
||||
*aEnded = Ended();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -499,8 +524,7 @@ NS_IMETHODIMP HTMLMediaElement::GetCurrentSrc(nsAString & aCurrentSrc)
|
||||
/* readonly attribute unsigned short networkState; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetNetworkState(uint16_t* aNetworkState)
|
||||
{
|
||||
*aNetworkState = mNetworkState;
|
||||
|
||||
*aNetworkState = NetworkState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -682,6 +706,7 @@ NS_IMETHODIMP HTMLMediaElement::Load()
|
||||
{
|
||||
if (mIsRunningLoadMethod)
|
||||
return NS_OK;
|
||||
|
||||
SetPlayedOrSeeked(false);
|
||||
mIsRunningLoadMethod = true;
|
||||
AbortExistingLoads();
|
||||
@ -689,6 +714,7 @@ NS_IMETHODIMP HTMLMediaElement::Load()
|
||||
QueueSelectResourceTask();
|
||||
ResetState();
|
||||
mIsRunningLoadMethod = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1173,79 +1199,110 @@ nsresult HTMLMediaElement::LoadWithChannel(nsIChannel *aChannel,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::MozLoadFrom(nsIDOMHTMLMediaElement* aOther)
|
||||
void
|
||||
HTMLMediaElement::MozLoadFrom(HTMLMediaElement& aOther, ErrorResult& aRv)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOther);
|
||||
|
||||
// Make sure we don't reenter during synchronous abort events.
|
||||
if (mIsRunningLoadMethod)
|
||||
return NS_OK;
|
||||
if (mIsRunningLoadMethod) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIsRunningLoadMethod = true;
|
||||
AbortExistingLoads();
|
||||
mIsRunningLoadMethod = false;
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aOther);
|
||||
HTMLMediaElement* other = static_cast<HTMLMediaElement*>(content.get());
|
||||
if (!other || !other->mDecoder)
|
||||
return NS_OK;
|
||||
if (!aOther.mDecoder) {
|
||||
return;
|
||||
}
|
||||
|
||||
ChangeDelayLoadStatus(true);
|
||||
|
||||
mLoadingSrc = other->mLoadingSrc;
|
||||
nsresult rv = InitializeDecoderAsClone(other->mDecoder);
|
||||
if (NS_FAILED(rv)) {
|
||||
mLoadingSrc = aOther.mLoadingSrc;
|
||||
aRv = InitializeDecoderAsClone(aOther.mDecoder);
|
||||
if (aRv.Failed()) {
|
||||
ChangeDelayLoadStatus(false);
|
||||
return rv;
|
||||
return;
|
||||
}
|
||||
|
||||
SetPlaybackRate(mDefaultPlaybackRate);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("loadstart"));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
NS_IMETHODIMP HTMLMediaElement::MozLoadFrom(nsIDOMHTMLMediaElement* aOther)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOther);
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aOther);
|
||||
HTMLMediaElement* other = static_cast<HTMLMediaElement*>(content.get());
|
||||
|
||||
if (!other) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
MozLoadFrom(*other, rv);
|
||||
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
/* readonly attribute unsigned short readyState; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetReadyState(uint16_t* aReadyState)
|
||||
{
|
||||
*aReadyState = mReadyState;
|
||||
*aReadyState = ReadyState();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute boolean seeking; */
|
||||
bool
|
||||
HTMLMediaElement::Seeking() const
|
||||
{
|
||||
return mDecoder && mDecoder->IsSeeking();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::GetSeeking(bool* aSeeking)
|
||||
{
|
||||
*aSeeking = mDecoder && mDecoder->IsSeeking();
|
||||
|
||||
*aSeeking = Seeking();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute double currentTime; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetCurrentTime(double *aCurrentTime)
|
||||
double
|
||||
HTMLMediaElement::CurrentTime() const
|
||||
{
|
||||
if (mSrcStream) {
|
||||
*aCurrentTime = MediaTimeToSeconds(GetSrcMediaStream()->GetCurrentTime());
|
||||
} else if (mDecoder) {
|
||||
*aCurrentTime = mDecoder->GetCurrentTime();
|
||||
} else {
|
||||
*aCurrentTime = 0.0;
|
||||
return MediaTimeToSeconds(GetSrcMediaStream()->GetCurrentTime());
|
||||
}
|
||||
|
||||
if (mDecoder) {
|
||||
return mDecoder->GetCurrentTime();
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::GetCurrentTime(double* aCurrentTime)
|
||||
{
|
||||
*aCurrentTime = CurrentTime();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::SetCurrentTime(double aCurrentTime)
|
||||
void
|
||||
HTMLMediaElement::SetCurrentTime(double aCurrentTime, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(aCurrentTime == aCurrentTime);
|
||||
|
||||
StopSuspendingAfterFirstFrame();
|
||||
|
||||
if (mSrcStream) {
|
||||
// do nothing since streams aren't seekable; we effectively clamp to
|
||||
// the current time.
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCurrentPlayRangeStart != -1.0) {
|
||||
double rangeEndTime = 0;
|
||||
GetCurrentTime(&rangeEndTime);
|
||||
double rangeEndTime = CurrentTime();
|
||||
LOG(PR_LOG_DEBUG, ("%p Adding \'played\' a range : [%f, %f]", this, mCurrentPlayRangeStart, rangeEndTime));
|
||||
// Multiple seek without playing, or seek while playing.
|
||||
if (mCurrentPlayRangeStart != rangeEndTime) {
|
||||
@ -1255,18 +1312,14 @@ NS_IMETHODIMP HTMLMediaElement::SetCurrentTime(double aCurrentTime)
|
||||
|
||||
if (!mDecoder) {
|
||||
LOG(PR_LOG_DEBUG, ("%p SetCurrentTime(%f) failed: no decoder", this, aCurrentTime));
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) {
|
||||
LOG(PR_LOG_DEBUG, ("%p SetCurrentTime(%f) failed: no source", this, aCurrentTime));
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
// Detect for a NaN and invalid values.
|
||||
if (aCurrentTime != aCurrentTime) {
|
||||
LOG(PR_LOG_DEBUG, ("%p SetCurrentTime(%f) failed: bad time", this, aCurrentTime));
|
||||
return NS_ERROR_FAILURE;
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clamp the time to [0, duration] as required by the spec.
|
||||
@ -1280,54 +1333,78 @@ NS_IMETHODIMP HTMLMediaElement::SetCurrentTime(double aCurrentTime)
|
||||
// The media backend is responsible for dispatching the timeupdate
|
||||
// event if it changes the playback position as a result of the seek.
|
||||
LOG(PR_LOG_DEBUG, ("%p SetCurrentTime(%f) starting seek", this, aCurrentTime));
|
||||
nsresult rv = mDecoder->Seek(clampedTime);
|
||||
aRv = mDecoder->Seek(clampedTime);
|
||||
// Start a new range at position we seeked to.
|
||||
mCurrentPlayRangeStart = mDecoder->GetCurrentTime();
|
||||
|
||||
// We changed whether we're seeking so we need to AddRemoveSelfReference.
|
||||
AddRemoveSelfReference();
|
||||
}
|
||||
|
||||
return rv;
|
||||
NS_IMETHODIMP HTMLMediaElement::SetCurrentTime(double aCurrentTime)
|
||||
{
|
||||
// Detect for a NaN and invalid values.
|
||||
if (aCurrentTime != aCurrentTime) {
|
||||
LOG(PR_LOG_DEBUG, ("%p SetCurrentTime(%f) failed: bad time", this, aCurrentTime));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
SetCurrentTime(aCurrentTime, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
/* readonly attribute double duration; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetDuration(double *aDuration)
|
||||
double
|
||||
HTMLMediaElement::Duration() const
|
||||
{
|
||||
if (mSrcStream) {
|
||||
*aDuration = std::numeric_limits<double>::infinity();
|
||||
} else if (mDecoder) {
|
||||
*aDuration = mDecoder->GetDuration();
|
||||
} else {
|
||||
*aDuration = std::numeric_limits<double>::quiet_NaN();
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
if (mDecoder) {
|
||||
return mDecoder->GetDuration();
|
||||
}
|
||||
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::GetDuration(double* aDuration)
|
||||
{
|
||||
*aDuration = Duration();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIDOMHTMLTimeRanges seekable; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetSeekable(nsIDOMTimeRanges** aSeekable)
|
||||
already_AddRefed<TimeRanges>
|
||||
HTMLMediaElement::Seekable() const
|
||||
{
|
||||
nsRefPtr<TimeRanges> ranges = new TimeRanges();
|
||||
if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
|
||||
mDecoder->GetSeekable(ranges);
|
||||
}
|
||||
return ranges.forget();
|
||||
}
|
||||
|
||||
/* readonly attribute nsIDOMHTMLTimeRanges seekable; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetSeekable(nsIDOMTimeRanges** aSeekable)
|
||||
{
|
||||
nsRefPtr<TimeRanges> ranges = Seekable();
|
||||
ranges.forget(aSeekable);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* readonly attribute boolean paused; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetPaused(bool* aPaused)
|
||||
{
|
||||
*aPaused = mPaused;
|
||||
*aPaused = Paused();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute nsIDOMHTMLTimeRanges played; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetPlayed(nsIDOMTimeRanges** aPlayed)
|
||||
already_AddRefed<TimeRanges>
|
||||
HTMLMediaElement::Played()
|
||||
{
|
||||
TimeRanges* ranges = new TimeRanges();
|
||||
NS_ADDREF(*aPlayed = ranges);
|
||||
nsRefPtr<TimeRanges> ranges = new TimeRanges();
|
||||
|
||||
uint32_t timeRangeCount = 0;
|
||||
mPlayed.GetLength(&timeRangeCount);
|
||||
@ -1340,25 +1417,34 @@ NS_IMETHODIMP HTMLMediaElement::GetPlayed(nsIDOMTimeRanges** aPlayed)
|
||||
}
|
||||
|
||||
if (mCurrentPlayRangeStart != -1.0) {
|
||||
double now = 0.0;
|
||||
GetCurrentTime(&now);
|
||||
double now = CurrentTime();
|
||||
if (mCurrentPlayRangeStart != now) {
|
||||
ranges->Add(mCurrentPlayRangeStart, now);
|
||||
}
|
||||
}
|
||||
|
||||
ranges->Normalize();
|
||||
return ranges.forget();
|
||||
}
|
||||
|
||||
/* readonly attribute nsIDOMHTMLTimeRanges played; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetPlayed(nsIDOMTimeRanges** aPlayed)
|
||||
{
|
||||
nsRefPtr<TimeRanges> ranges = Played();
|
||||
ranges.forget(aPlayed);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void pause (); */
|
||||
NS_IMETHODIMP HTMLMediaElement::Pause()
|
||||
void
|
||||
HTMLMediaElement::Pause(ErrorResult& aRv)
|
||||
{
|
||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
|
||||
LOG(PR_LOG_DEBUG, ("Loading due to Pause()"));
|
||||
nsresult rv = Load();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRv = Load();
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
} else if (mDecoder) {
|
||||
mDecoder->Pause();
|
||||
}
|
||||
@ -1376,25 +1462,32 @@ NS_IMETHODIMP HTMLMediaElement::Pause()
|
||||
FireTimeUpdate(false);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("pause"));
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
NS_IMETHODIMP HTMLMediaElement::Pause()
|
||||
{
|
||||
ErrorResult rv;
|
||||
Pause(rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
/* attribute double volume; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetVolume(double* aVolume)
|
||||
{
|
||||
*aVolume = mVolume;
|
||||
|
||||
*aVolume = Volume();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::SetVolume(double aVolume)
|
||||
void
|
||||
HTMLMediaElement::SetVolume(double aVolume, ErrorResult& aRv)
|
||||
{
|
||||
if (!(aVolume >= 0.0 && aVolume <= 1.0))
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
if (aVolume < 0.0 || aVolume > 1.0) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aVolume == mVolume)
|
||||
return NS_OK;
|
||||
return;
|
||||
|
||||
mVolume = aVolume;
|
||||
|
||||
@ -1409,30 +1502,51 @@ NS_IMETHODIMP HTMLMediaElement::SetVolume(double aVolume)
|
||||
}
|
||||
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("volumechange"));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
NS_IMETHODIMP HTMLMediaElement::SetVolume(double aVolume)
|
||||
{
|
||||
ErrorResult rv;
|
||||
SetVolume(aVolume, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
HTMLMediaElement::GetMozChannels(ErrorResult& aRv) const
|
||||
{
|
||||
if (!mDecoder && !mAudioStream) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mChannels;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::GetMozChannels(uint32_t* aMozChannels)
|
||||
{
|
||||
if (!mDecoder && !mAudioStream) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
ErrorResult rv;
|
||||
*aMozChannels = GetMozChannels(rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
*aMozChannels = mChannels;
|
||||
return NS_OK;
|
||||
uint32_t
|
||||
HTMLMediaElement::GetMozSampleRate(ErrorResult& aRv) const
|
||||
{
|
||||
if (!mDecoder && !mAudioStream) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mRate;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::GetMozSampleRate(uint32_t* aMozSampleRate)
|
||||
{
|
||||
if (!mDecoder && !mAudioStream) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
*aMozSampleRate = mRate;
|
||||
return NS_OK;
|
||||
ErrorResult rv;
|
||||
*aMozSampleRate = GetMozSampleRate(rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
// Helper struct with arguments for our hash iterator.
|
||||
@ -1467,57 +1581,90 @@ HTMLMediaElement::BuildObjectFromTags(nsCStringHashKey::KeyType aKey,
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::MozGetMetadata(JSContext* cx, JS::Value* aValue)
|
||||
JSObject*
|
||||
HTMLMediaElement::MozGetMetadata(JSContext* cx, ErrorResult& aRv)
|
||||
{
|
||||
if (mReadyState < nsIDOMHTMLMediaElement::HAVE_METADATA) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject* tags = JS_NewObject(cx, NULL, NULL, NULL);
|
||||
if (!tags) {
|
||||
return NS_ERROR_FAILURE;
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
if (mTags) {
|
||||
MetadataIterCx iter = {cx, tags, false};
|
||||
mTags->EnumerateRead(BuildObjectFromTags, static_cast<void*>(&iter));
|
||||
if (iter.error) {
|
||||
NS_WARNING("couldn't create metadata object!");
|
||||
return NS_ERROR_FAILURE;
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
*aValue = OBJECT_TO_JSVAL(tags);
|
||||
|
||||
return NS_OK;
|
||||
return tags;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::MozGetMetadata(JSContext* cx, JS::Value* aValue)
|
||||
{
|
||||
ErrorResult rv;
|
||||
|
||||
JSObject* obj = MozGetMetadata(cx, rv);
|
||||
if (!rv.Failed()) {
|
||||
MOZ_ASSERT(obj);
|
||||
*aValue = JS::ObjectValue(*obj);
|
||||
}
|
||||
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
HTMLMediaElement::GetMozFrameBufferLength(ErrorResult& aRv) const
|
||||
{
|
||||
// The framebuffer (via MozAudioAvailable events) is only available
|
||||
// when reading vs. writing audio directly.
|
||||
if (!mDecoder) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mDecoder->GetFrameBufferLength();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::GetMozFrameBufferLength(uint32_t* aMozFrameBufferLength)
|
||||
{
|
||||
// The framebuffer (via MozAudioAvailable events) is only available
|
||||
// when reading vs. writing audio directly.
|
||||
if (!mDecoder) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
ErrorResult rv;
|
||||
*aMozFrameBufferLength = GetMozFrameBufferLength(rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
*aMozFrameBufferLength = mDecoder->GetFrameBufferLength();
|
||||
return NS_OK;
|
||||
void
|
||||
HTMLMediaElement::SetMozFrameBufferLength(uint32_t aMozFrameBufferLength, ErrorResult& aRv)
|
||||
{
|
||||
if (!mDecoder) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mDecoder->RequestFrameBufferLength(aMozFrameBufferLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::SetMozFrameBufferLength(uint32_t aMozFrameBufferLength)
|
||||
{
|
||||
if (!mDecoder)
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
|
||||
return mDecoder->RequestFrameBufferLength(aMozFrameBufferLength);
|
||||
ErrorResult rv;
|
||||
SetMozFrameBufferLength(aMozFrameBufferLength, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
/* attribute boolean muted; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetMuted(bool* aMuted)
|
||||
{
|
||||
*aMuted = mMuted;
|
||||
|
||||
*aMuted = Muted();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1543,7 +1690,6 @@ NS_IMETHODIMP HTMLMediaElement::SetMuted(bool aMuted)
|
||||
SetMutedInternal(aMuted);
|
||||
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("volumechange"));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1575,27 +1721,47 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded)
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMMediaStream>
|
||||
HTMLMediaElement::MozCaptureStream(ErrorResult& aRv)
|
||||
{
|
||||
nsRefPtr<DOMMediaStream> stream = CaptureStreamInternal(false);
|
||||
if (!stream) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return stream.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::MozCaptureStream(nsIDOMMediaStream** aStream)
|
||||
{
|
||||
*aStream = CaptureStreamInternal(false).get();
|
||||
if (!*aStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
ErrorResult rv;
|
||||
*aStream = MozCaptureStream(rv).get();
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
already_AddRefed<DOMMediaStream>
|
||||
HTMLMediaElement::MozCaptureStreamUntilEnded(ErrorResult& aRv)
|
||||
{
|
||||
nsRefPtr<DOMMediaStream> stream = CaptureStreamInternal(true);
|
||||
if (!stream) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return stream.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::MozCaptureStreamUntilEnded(nsIDOMMediaStream** aStream)
|
||||
{
|
||||
*aStream = CaptureStreamInternal(true).get();
|
||||
if (!*aStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
ErrorResult rv;
|
||||
*aStream = MozCaptureStreamUntilEnded(rv).get();
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::GetMozAudioCaptured(bool* aCaptured)
|
||||
{
|
||||
*aCaptured = mAudioCaptured;
|
||||
*aCaptured = MozAudioCaptured();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1838,14 +2004,17 @@ void HTMLMediaElement::SetPlayedOrSeeked(bool aValue)
|
||||
NS_FRAME_IS_DIRTY);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::Play()
|
||||
void
|
||||
HTMLMediaElement::Play(ErrorResult& aRv)
|
||||
{
|
||||
StopSuspendingAfterFirstFrame();
|
||||
SetPlayedOrSeeked(true);
|
||||
|
||||
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
|
||||
nsresult rv = Load();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRv = Load();
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mSuspendedForPreloadNone) {
|
||||
ResumeLoad(PRELOAD_ENOUGH);
|
||||
@ -1857,13 +2026,15 @@ NS_IMETHODIMP HTMLMediaElement::Play()
|
||||
SetCurrentTime(0);
|
||||
}
|
||||
if (!mPausedForInactiveDocumentOrChannel) {
|
||||
nsresult rv = mDecoder->Play();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRv = mDecoder->Play();
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mCurrentPlayRangeStart == -1.0) {
|
||||
GetCurrentTime(&mCurrentPlayRangeStart);
|
||||
mCurrentPlayRangeStart = CurrentTime();
|
||||
}
|
||||
|
||||
// TODO: If the playback has ended, then the user agent must set
|
||||
@ -1897,8 +2068,13 @@ NS_IMETHODIMP HTMLMediaElement::Play()
|
||||
// and our preload status.
|
||||
AddRemoveSelfReference();
|
||||
UpdatePreloadAction();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
NS_IMETHODIMP HTMLMediaElement::Play()
|
||||
{
|
||||
ErrorResult rv;
|
||||
Play(rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
HTMLMediaElement::WakeLockBoolWrapper& HTMLMediaElement::WakeLockBoolWrapper::operator=(bool val) {
|
||||
@ -2851,7 +3027,7 @@ void HTMLMediaElement::NotifyAutoplayDataReady()
|
||||
if (mDecoder) {
|
||||
SetPlayedOrSeeked(true);
|
||||
if (mCurrentPlayRangeStart == -1.0) {
|
||||
GetCurrentTime(&mCurrentPlayRangeStart);
|
||||
mCurrentPlayRangeStart = CurrentTime();
|
||||
}
|
||||
mDecoder->Play();
|
||||
} else if (mSrcStream) {
|
||||
@ -3268,7 +3444,8 @@ HTMLMediaElement::CopyInnerTo(Element* aDest)
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult HTMLMediaElement::GetBuffered(nsIDOMTimeRanges** aBuffered)
|
||||
already_AddRefed<TimeRanges>
|
||||
HTMLMediaElement::Buffered() const
|
||||
{
|
||||
nsRefPtr<TimeRanges> ranges = new TimeRanges();
|
||||
if (mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING && mDecoder) {
|
||||
@ -3276,6 +3453,12 @@ nsresult HTMLMediaElement::GetBuffered(nsIDOMTimeRanges** aBuffered)
|
||||
// time ranges we found up till the error.
|
||||
mDecoder->GetBuffered(ranges);
|
||||
}
|
||||
return ranges.forget();
|
||||
}
|
||||
|
||||
nsresult HTMLMediaElement::GetBuffered(nsIDOMTimeRanges** aBuffered)
|
||||
{
|
||||
nsRefPtr<TimeRanges> ranges = Buffered();
|
||||
ranges.forget(aBuffered);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3309,8 +3492,7 @@ void HTMLMediaElement::FireTimeUpdate(bool aPeriodic)
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
double time = 0;
|
||||
GetCurrentTime(&time);
|
||||
double time = CurrentTime();
|
||||
|
||||
// Fire a timeupdate event if this is not a periodic update (i.e. it's a
|
||||
// timeupdate event mandated by the spec), or if it's a periodic update
|
||||
@ -3342,31 +3524,41 @@ void HTMLMediaElement::GetCurrentSpec(nsCString& aString)
|
||||
}
|
||||
|
||||
/* attribute double initialTime; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetInitialTime(double *aTime)
|
||||
double
|
||||
HTMLMediaElement::InitialTime()
|
||||
{
|
||||
// If there is no start fragment then the initalTime is zero.
|
||||
// Clamp to duration if it is greater than duration.
|
||||
double duration = 0.0;
|
||||
nsresult rv = GetDuration(&duration);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
double duration = Duration();
|
||||
|
||||
*aTime = mFragmentStart < 0.0 ? 0.0 : mFragmentStart;
|
||||
if (*aTime > duration) {
|
||||
*aTime = duration;
|
||||
double time = mFragmentStart < 0.0 ? 0.0 : mFragmentStart;
|
||||
if (time > duration) {
|
||||
time = duration;
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::GetInitialTime(double* aTime)
|
||||
{
|
||||
*aTime = InitialTime();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute double mozFragmentEnd; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetMozFragmentEnd(double *aTime)
|
||||
double
|
||||
HTMLMediaElement::MozFragmentEnd()
|
||||
{
|
||||
double duration = 0.0;
|
||||
nsresult rv = GetDuration(&duration);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
double duration = Duration();
|
||||
|
||||
// If there is no end fragment, or the fragment end is greater than the
|
||||
// duration, return the duration.
|
||||
*aTime = (mFragmentEnd < 0.0 || mFragmentEnd > duration) ? duration : mFragmentEnd;
|
||||
return (mFragmentEnd < 0.0 || mFragmentEnd > duration) ? duration : mFragmentEnd;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::GetMozFragmentEnd(double* aTime)
|
||||
{
|
||||
*aTime = MozFragmentEnd();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3394,34 +3586,44 @@ static double ClampPlaybackRate(double aPlaybackRate)
|
||||
/* attribute double defaultPlaybackRate; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetDefaultPlaybackRate(double* aDefaultPlaybackRate)
|
||||
{
|
||||
*aDefaultPlaybackRate = mDefaultPlaybackRate;
|
||||
*aDefaultPlaybackRate = DefaultPlaybackRate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::SetDefaultPlaybackRate(double aDefaultPlaybackRate)
|
||||
void
|
||||
HTMLMediaElement::SetDefaultPlaybackRate(double aDefaultPlaybackRate, ErrorResult& aRv)
|
||||
{
|
||||
if (aDefaultPlaybackRate < 0) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return;
|
||||
}
|
||||
|
||||
mDefaultPlaybackRate = ClampPlaybackRate(aDefaultPlaybackRate);
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("ratechange"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::SetDefaultPlaybackRate(double aDefaultPlaybackRate)
|
||||
{
|
||||
ErrorResult rv;
|
||||
SetDefaultPlaybackRate(aDefaultPlaybackRate, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
/* attribute double playbackRate; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetPlaybackRate(double* aPlaybackRate)
|
||||
{
|
||||
*aPlaybackRate = mPlaybackRate;
|
||||
*aPlaybackRate = PlaybackRate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::SetPlaybackRate(double aPlaybackRate)
|
||||
void
|
||||
HTMLMediaElement::SetPlaybackRate(double aPlaybackRate, ErrorResult& aRv)
|
||||
{
|
||||
// Changing the playback rate of a media that has more than two channels is
|
||||
// not supported.
|
||||
if (aPlaybackRate < 0 || (mChannels > 2 && aPlaybackRate != 1.0)) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return;
|
||||
}
|
||||
|
||||
mPlaybackRate = ClampPlaybackRate(aPlaybackRate);
|
||||
@ -3440,13 +3642,19 @@ NS_IMETHODIMP HTMLMediaElement::SetPlaybackRate(double aPlaybackRate)
|
||||
mDecoder->SetPlaybackRate(mPlaybackRate);
|
||||
}
|
||||
DispatchAsyncEvent(NS_LITERAL_STRING("ratechange"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::SetPlaybackRate(double aPlaybackRate)
|
||||
{
|
||||
ErrorResult rv;
|
||||
SetPlaybackRate(aPlaybackRate, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
/* attribute bool mozPreservesPitch; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetMozPreservesPitch(bool* aPreservesPitch)
|
||||
{
|
||||
*aPreservesPitch = mPreservesPitch;
|
||||
*aPreservesPitch = MozPreservesPitch();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -353,6 +353,11 @@ MOCHITEST_FILES = \
|
||||
test_formData.html \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_MEDIA
|
||||
MOCHITEST_FILES += \
|
||||
test_mozLoadFrom.html \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
MOCHITEST_BROWSER_FILES = \
|
||||
browser_bug649778.js \
|
||||
|
19
content/html/content/test/test_mozLoadFrom.html
Normal file
19
content/html/content/test/test_mozLoadFrom.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for mozLoadFrom</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
try {
|
||||
document.createElement("video").mozLoadFrom({});
|
||||
ok(false, "This should be throw an exception");
|
||||
} catch(e) {
|
||||
ok(true, "This should be throw an exception");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -156,15 +156,15 @@ is(HTMLElement.prototype.MEDIA_ERR_ABORTED, undefined);
|
||||
is(HTMLElement.prototype.MEDIA_ERR_NETWORK, undefined);
|
||||
is(HTMLElement.prototype.MEDIA_ERR_DECODE, undefined);
|
||||
is(HTMLElement.prototype.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
|
||||
todo_is(HTMLMediaElement.prototype.NETWORK_EMPTY, 0, "HTMLMediaElement.prototype.NETWORK_EMPTY");
|
||||
todo_is(HTMLMediaElement.prototype.NETWORK_IDLE, 1, "HTMLMediaElement.prototype.NETWORK_IDLE");
|
||||
todo_is(HTMLMediaElement.prototype.NETWORK_LOADING, 2, "HTMLMediaElement.prototype.NETWORK_LOADING");
|
||||
todo_is(HTMLMediaElement.prototype.NETWORK_NO_SOURCE, 3, "HTMLMediaElement.prototype.NETWORK_NO_SOURCE");
|
||||
todo_is(HTMLMediaElement.prototype.HAVE_NOTHING, 0, "HTMLMediaElement.prototype.HAVE_NOTHING");
|
||||
todo_is(HTMLMediaElement.prototype.HAVE_METADATA, 1, "HTMLMediaElement.prototype.HAVE_METADATA");
|
||||
todo_is(HTMLMediaElement.prototype.HAVE_CURRENT_DATA, 2, "HTMLMediaElement.prototype.HAVE_CURRENT_DATA");
|
||||
todo_is(HTMLMediaElement.prototype.HAVE_FUTURE_DATA, 3, "HTMLMediaElement.prototype.HAVE_FUTURE_DATA");
|
||||
todo_is(HTMLMediaElement.prototype.HAVE_ENOUGH_DATA, 4, "HTMLMediaElement.prototype.HAVE_ENOUGH_DATA");
|
||||
is(HTMLMediaElement.prototype.NETWORK_EMPTY, 0, "HTMLMediaElement.prototype.NETWORK_EMPTY");
|
||||
is(HTMLMediaElement.prototype.NETWORK_IDLE, 1, "HTMLMediaElement.prototype.NETWORK_IDLE");
|
||||
is(HTMLMediaElement.prototype.NETWORK_LOADING, 2, "HTMLMediaElement.prototype.NETWORK_LOADING");
|
||||
is(HTMLMediaElement.prototype.NETWORK_NO_SOURCE, 3, "HTMLMediaElement.prototype.NETWORK_NO_SOURCE");
|
||||
is(HTMLMediaElement.prototype.HAVE_NOTHING, 0, "HTMLMediaElement.prototype.HAVE_NOTHING");
|
||||
is(HTMLMediaElement.prototype.HAVE_METADATA, 1, "HTMLMediaElement.prototype.HAVE_METADATA");
|
||||
is(HTMLMediaElement.prototype.HAVE_CURRENT_DATA, 2, "HTMLMediaElement.prototype.HAVE_CURRENT_DATA");
|
||||
is(HTMLMediaElement.prototype.HAVE_FUTURE_DATA, 3, "HTMLMediaElement.prototype.HAVE_FUTURE_DATA");
|
||||
is(HTMLMediaElement.prototype.HAVE_ENOUGH_DATA, 4, "HTMLMediaElement.prototype.HAVE_ENOUGH_DATA");
|
||||
is(HTMLMediaElement.prototype.MEDIA_ERR_ABORTED, undefined, "HTMLMediaElement.prototype.MEDIA_ERR_ABORTED");
|
||||
is(HTMLMediaElement.prototype.MEDIA_ERR_NETWORK, undefined, "HTMLMediaElement.prototype.MEDIA_ERR_NETWORK");
|
||||
is(HTMLMediaElement.prototype.MEDIA_ERR_DECODE, undefined, "HTMLMediaElement.prototype.MEDIA_ERR_DECODE");
|
||||
|
@ -28,7 +28,7 @@ function doTest() {
|
||||
b.mozSrcObject = "invalid";
|
||||
ok(false, "Setting mozSrcObject to an invalid value should throw.");
|
||||
} catch (e) {
|
||||
todo(e instanceof TypeError, "Exception should be a TypeError");
|
||||
ok(e instanceof TypeError, "Exception should be a TypeError");
|
||||
}
|
||||
is(b.mozSrcObject, stream, "Stream not set to invalid value");
|
||||
is(b.src, newSrc, "src attribute not affected by setting srcObject");
|
||||
|
@ -13,11 +13,11 @@
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function test(element, value, shouldThrow) {
|
||||
var threw = false;
|
||||
var threw = null;
|
||||
try {
|
||||
element.volume = value;
|
||||
} catch (err if err.name == "IndexSizeError") {
|
||||
threw = true;
|
||||
} catch (ex) {
|
||||
threw = ex.name;
|
||||
}
|
||||
is(shouldThrow, threw, "Case: " +element.id+ " setVolume=" + value);
|
||||
}
|
||||
@ -27,12 +27,12 @@ var ids = new Array(document.getElementById('v1'), document.getElementById('a1')
|
||||
|
||||
for (i=0; i<ids.length; i++) {
|
||||
var element = ids[i];
|
||||
test(element, 0.0, false);
|
||||
test(element, 1.0, false);
|
||||
test(element, -0.1, true);
|
||||
test(element, 1.1, true);
|
||||
test(element, undefined, true);
|
||||
test(element, NaN, true);
|
||||
test(element, 0.0, null);
|
||||
test(element, 1.0, null);
|
||||
test(element, -0.1, "IndexSizeError");
|
||||
test(element, 1.1, "IndexSizeError");
|
||||
test(element, undefined, "TypeError");
|
||||
test(element, NaN, "TypeError");
|
||||
}
|
||||
|
||||
</script>
|
||||
|
181
dom/webidl/HTMLMediaElement.webidl
Normal file
181
dom/webidl/HTMLMediaElement.webidl
Normal file
@ -0,0 +1,181 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://www.whatwg.org/specs/web-apps/current-work/#media-elements
|
||||
*
|
||||
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
|
||||
* Opera Software ASA. You are granted a license to use, reproduce
|
||||
* and create derivative works of this document.
|
||||
*/
|
||||
|
||||
interface HTMLMediaElement : HTMLElement {
|
||||
|
||||
// error state
|
||||
readonly attribute MediaError? error;
|
||||
|
||||
// network state
|
||||
[SetterThrows]
|
||||
attribute DOMString src;
|
||||
readonly attribute DOMString currentSrc;
|
||||
|
||||
// Bug 847370 - crossOrigin vs crossorigin.
|
||||
[SetterThrows]
|
||||
attribute DOMString crossorigin;
|
||||
const unsigned short NETWORK_EMPTY = 0;
|
||||
const unsigned short NETWORK_IDLE = 1;
|
||||
const unsigned short NETWORK_LOADING = 2;
|
||||
const unsigned short NETWORK_NO_SOURCE = 3;
|
||||
readonly attribute unsigned short networkState;
|
||||
[SetterThrows]
|
||||
attribute DOMString preload;
|
||||
[Creator]
|
||||
readonly attribute TimeRanges buffered;
|
||||
void load();
|
||||
DOMString canPlayType(DOMString type);
|
||||
|
||||
// ready state
|
||||
const unsigned short HAVE_NOTHING = 0;
|
||||
const unsigned short HAVE_METADATA = 1;
|
||||
const unsigned short HAVE_CURRENT_DATA = 2;
|
||||
const unsigned short HAVE_FUTURE_DATA = 3;
|
||||
const unsigned short HAVE_ENOUGH_DATA = 4;
|
||||
readonly attribute unsigned short readyState;
|
||||
readonly attribute boolean seeking;
|
||||
|
||||
// playback state
|
||||
[SetterThrows]
|
||||
attribute double currentTime;
|
||||
// TODO: Bug 847375 - void fastSeek(double time);
|
||||
readonly attribute unrestricted double duration;
|
||||
// TODO: Bug 847376 - readonly attribute any startDate;
|
||||
readonly attribute boolean paused;
|
||||
[SetterThrows]
|
||||
attribute double defaultPlaybackRate;
|
||||
[SetterThrows]
|
||||
attribute double playbackRate;
|
||||
[Creator]
|
||||
readonly attribute TimeRanges played;
|
||||
[Creator]
|
||||
readonly attribute TimeRanges seekable;
|
||||
readonly attribute boolean ended;
|
||||
[SetterThrows]
|
||||
attribute boolean autoplay;
|
||||
[SetterThrows]
|
||||
attribute boolean loop;
|
||||
[Throws]
|
||||
void play();
|
||||
[Throws]
|
||||
void pause();
|
||||
|
||||
// TODO: Bug 847377 - mediaGroup and MediaController
|
||||
// media controller
|
||||
// attribute DOMString mediaGroup;
|
||||
// attribute MediaController? controller;
|
||||
|
||||
// controls
|
||||
[SetterThrows]
|
||||
attribute boolean controls;
|
||||
[SetterThrows]
|
||||
attribute double volume;
|
||||
attribute boolean muted;
|
||||
[SetterThrows]
|
||||
attribute boolean defaultMuted;
|
||||
|
||||
// TODO: Bug 847379
|
||||
// tracks
|
||||
//readonly attribute AudioTrackList audioTracks;
|
||||
//readonly attribute VideoTrackList videoTracks;
|
||||
//readonly attribute TextTrackList textTracks;
|
||||
//TextTrack addTextTrack(DOMString kind, optional DOMString label, optional DOMString language);
|
||||
};
|
||||
|
||||
// Mozilla extensions:
|
||||
partial interface HTMLMediaElement {
|
||||
attribute MediaStream? mozSrcObject;
|
||||
readonly attribute double initialTime;
|
||||
attribute boolean mozPreservesPitch;
|
||||
readonly attribute boolean mozAutoplayEnabled;
|
||||
|
||||
// Mozilla extension: stream capture
|
||||
[Throws]
|
||||
MediaStream mozCaptureStream();
|
||||
[Throws]
|
||||
MediaStream mozCaptureStreamUntilEnded();
|
||||
readonly attribute boolean mozAudioCaptured;
|
||||
|
||||
// Mozilla extension: extra stream metadata information, used as part
|
||||
// of MozAudioAvailable events and the mozWriteAudio() method. The
|
||||
// mozFrameBufferLength method allows for the size of the framebuffer
|
||||
// used within MozAudioAvailable events to be changed. The new size must
|
||||
// be between 512 and 16384. The default size, for a media element with
|
||||
// audio is (mozChannels * 1024).
|
||||
[GetterThrows]
|
||||
readonly attribute unsigned long mozChannels;
|
||||
[GetterThrows]
|
||||
readonly attribute unsigned long mozSampleRate;
|
||||
[Throws]
|
||||
attribute unsigned long mozFrameBufferLength;
|
||||
|
||||
// Mozilla extension: return embedded metadata from the stream as a
|
||||
// JSObject with key:value pairs for each tag. This can be used by
|
||||
// player interfaces to display the song title, artist, etc.
|
||||
[Throws]
|
||||
object? mozGetMetadata();
|
||||
|
||||
// Mozilla extension: load data from another media element. This is like
|
||||
// load() but we don't run the resource selection algorithm; instead
|
||||
// we just set our source to other's currentSrc. This is optimized
|
||||
// so that this element will get access to all of other's cached/
|
||||
// buffered data. In fact any future data downloaded by this element or
|
||||
// other will be sharable by both elements.
|
||||
[Throws]
|
||||
void mozLoadFrom(HTMLMediaElement other);
|
||||
|
||||
// Mozilla extension: provides access to the fragment end time if
|
||||
// the media element has a fragment URI for the currentSrc, otherwise
|
||||
// it is equal to the media duration.
|
||||
readonly attribute double mozFragmentEnd;
|
||||
|
||||
// Mozilla extension: an audio channel type for media elements.
|
||||
// An exception is thrown if the app tries to change the audio channel type
|
||||
// without the permission (manifest file for B2G apps).
|
||||
// The supported values are:
|
||||
// * normal (default value)
|
||||
// Automatically paused if "notification" or higher priority channel
|
||||
// is played
|
||||
// Use case: normal applications
|
||||
// * content
|
||||
// Automatically paused if "notification" or higher priority channel
|
||||
// is played. Also paused if another app starts using "content"
|
||||
// channel. Using this channel never affects applications using
|
||||
// the "normal" channel.
|
||||
// Use case: video/audio players
|
||||
// * notification
|
||||
// Automatically paused if "alarm" or higher priority channel is played.
|
||||
// Use case: New email, incoming SMS
|
||||
// * alarm
|
||||
// Automatically paused if "telephony" or higher priority channel is
|
||||
// played.
|
||||
// User case: Alarm clock, calendar alarms
|
||||
// * telephony
|
||||
// Automatically paused if "ringer" or higher priority
|
||||
// channel is played.
|
||||
// Use case: dialer, voip
|
||||
// * ringer
|
||||
// Automatically paused if "publicnotification" or higher priority
|
||||
// channel is played.
|
||||
// Use case: dialer, voip
|
||||
// * publicnotification
|
||||
// Always plays in speaker, even when headphones are plugged in.
|
||||
// Use case: Camera shutter sound.
|
||||
[SetterThrows]
|
||||
attribute DOMString mozAudioChannelType;
|
||||
|
||||
// In addition the media element has this new events:
|
||||
// * onmozinterruptbegin - called when the media element is interrupted
|
||||
// because of the audiochannel manager.
|
||||
// * onmozinterruptend - called when the interruption is concluded
|
||||
};
|
@ -96,6 +96,7 @@ webidl_files = \
|
||||
HTMLLIElement.webidl \
|
||||
HTMLLinkElement.webidl \
|
||||
HTMLMapElement.webidl \
|
||||
HTMLMediaElement.webidl \
|
||||
HTMLMenuElement.webidl \
|
||||
HTMLMenuItemElement.webidl \
|
||||
HTMLMetaElement.webidl \
|
||||
|
Loading…
Reference in New Issue
Block a user