diff options
Diffstat (limited to 'Source/WebCore/html/HTMLMediaElement.h')
-rw-r--r-- | Source/WebCore/html/HTMLMediaElement.h | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h new file mode 100644 index 0000000..9778fd4 --- /dev/null +++ b/Source/WebCore/html/HTMLMediaElement.h @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HTMLMediaElement_h +#define HTMLMediaElement_h + +#if ENABLE(VIDEO) + +#include "HTMLElement.h" +#include "ActiveDOMObject.h" +#include "MediaCanStartListener.h" +#include "MediaPlayer.h" + +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +#include "MediaPlayerProxy.h" +#endif + +namespace WebCore { + +class Event; +class HTMLSourceElement; +class MediaError; +class KURL; +class TimeRanges; +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) +class Widget; +#endif + +// FIXME: The inheritance from MediaPlayerClient here should be private inheritance. +// But it can't be until the Chromium WebMediaPlayerClientImpl class is fixed so it +// no longer depends on typecasting a MediaPlayerClient to an HTMLMediaElement. + +class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, private MediaCanStartListener, private ActiveDOMObject { +public: + MediaPlayer* player() const { return m_player.get(); } + + virtual bool isVideo() const = 0; + virtual bool hasVideo() const { return false; } + virtual bool hasAudio() const; + + void rewind(float timeDelta); + void returnToRealtime(); + + // Eventually overloaded in HTMLVideoElement + virtual bool supportsFullscreen() const { return false; }; + + virtual bool supportsSave() const; + + PlatformMedia platformMedia() const; +#if USE(ACCELERATED_COMPOSITING) + PlatformLayer* platformLayer() const; +#endif + + void scheduleLoad(); + + MediaPlayer::MovieLoadType movieLoadType() const; + + bool inActiveDocument() const { return m_inActiveDocument; } + +// DOM API +// error state + PassRefPtr<MediaError> error() const; + +// network state + void setSrc(const String&); + String currentSrc() const; + + enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_NO_SOURCE }; + NetworkState networkState() const; + + String preload() const; + void setPreload(const String&); + + PassRefPtr<TimeRanges> buffered() const; + void load(bool isUserGesture, ExceptionCode&); + String canPlayType(const String& mimeType) const; + +// ready state + enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA }; + ReadyState readyState() const; + bool seeking() const; + +// playback state + float currentTime() const; + void setCurrentTime(float, ExceptionCode&); + float startTime() const; + float duration() const; + bool paused() const; + float defaultPlaybackRate() const; + void setDefaultPlaybackRate(float); + float playbackRate() const; + void setPlaybackRate(float); + bool webkitPreservesPitch() const; + void setWebkitPreservesPitch(bool); + PassRefPtr<TimeRanges> played(); + PassRefPtr<TimeRanges> seekable() const; + bool ended() const; + bool autoplay() const; + void setAutoplay(bool b); + bool loop() const; + void setLoop(bool b); + void play(bool isUserGesture); + void pause(bool isUserGesture); + +// captions + bool webkitHasClosedCaptions() const; + bool webkitClosedCaptionsVisible() const; + void setWebkitClosedCaptionsVisible(bool); + +#if ENABLE(MEDIA_STATISTICS) +// Statistics + unsigned long webkitAudioBytesDecoded() const; + unsigned long webkitVideoBytesDecoded() const; +#endif + +// controls + bool controls() const; + void setControls(bool); + float volume() const; + void setVolume(float, ExceptionCode&); + bool muted() const; + void setMuted(bool); + void togglePlayState(); + void beginScrubbing(); + void endScrubbing(); + + bool canPlay() const; + + float percentLoaded() const; + +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) + void allocateMediaPlayerIfNecessary(); + void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; } + void deliverNotification(MediaPlayerProxyNotificationType notification); + void setMediaPlayerProxy(WebMediaPlayerProxy* proxy); + void getPluginProxyParams(KURL& url, Vector<String>& names, Vector<String>& values); + virtual void finishParsingChildren(); + void createMediaPlayerProxy(); + void updateWidget(PluginCreationOption); +#endif + + bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); } + + bool isFullscreen() const { return m_isFullscreen; } + void enterFullscreen(); + void exitFullscreen(); + + bool hasClosedCaptions() const; + bool closedCaptionsVisible() const; + void setClosedCaptionsVisible(bool); + + bool processingUserGesture() const; + + void sourceWillBeRemoved(HTMLSourceElement*); + void sourceWasAdded(HTMLSourceElement*); + +protected: + HTMLMediaElement(const QualifiedName&, Document*); + virtual ~HTMLMediaElement(); + + virtual void parseMappedAttribute(Attribute*); + virtual bool isURLAttribute(Attribute*) const; + virtual void attach(); + + virtual void willMoveToNewOwnerDocument(); + virtual void didMoveToNewOwnerDocument(); + + enum DisplayMode { Unknown, None, Poster, Video }; + DisplayMode displayMode() const { return m_displayMode; } + virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; } + +private: + virtual void attributeChanged(Attribute*, bool preserveDecls); + virtual bool rendererIsNeeded(RenderStyle*); + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + virtual void recalcStyle(StyleChange); + + virtual void defaultEventHandler(Event*); + + // ActiveDOMObject functions. + virtual bool canSuspend() const; + virtual void suspend(ReasonForSuspension); + virtual void resume(); + virtual void stop(); + virtual bool hasPendingActivity() const; + + virtual void mediaVolumeDidChange(); + + virtual void updateDisplayState() { } + + void setReadyState(MediaPlayer::ReadyState); + void setNetworkState(MediaPlayer::NetworkState); + + virtual Document* mediaPlayerOwningDocument(); + virtual void mediaPlayerNetworkStateChanged(MediaPlayer*); + virtual void mediaPlayerReadyStateChanged(MediaPlayer*); + virtual void mediaPlayerTimeChanged(MediaPlayer*); + virtual void mediaPlayerVolumeChanged(MediaPlayer*); + virtual void mediaPlayerMuteChanged(MediaPlayer*); + virtual void mediaPlayerDurationChanged(MediaPlayer*); + virtual void mediaPlayerRateChanged(MediaPlayer*); + virtual void mediaPlayerPlaybackStateChanged(MediaPlayer*); + virtual void mediaPlayerSawUnsupportedTracks(MediaPlayer*); + virtual void mediaPlayerRepaint(MediaPlayer*); + virtual void mediaPlayerSizeChanged(MediaPlayer*); +#if USE(ACCELERATED_COMPOSITING) + virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*); + virtual void mediaPlayerRenderingModeChanged(MediaPlayer*); +#endif + virtual void mediaPlayerEngineUpdated(MediaPlayer*); + + void loadTimerFired(Timer<HTMLMediaElement>*); + void asyncEventTimerFired(Timer<HTMLMediaElement>*); + void progressEventTimerFired(Timer<HTMLMediaElement>*); + void playbackProgressTimerFired(Timer<HTMLMediaElement>*); + void startPlaybackProgressTimer(); + void startProgressEventTimer(); + void stopPeriodicTimers(); + + void seek(float time, ExceptionCode&); + void finishSeek(); + void checkIfSeekNeeded(); + void addPlayedRange(float start, float end); + + void scheduleTimeupdateEvent(bool periodicEvent); + void scheduleEvent(const AtomicString& eventName); + + // loading + void selectMediaResource(); + void loadResource(const KURL&, ContentType&); + void scheduleNextSourceChild(); + void loadNextSourceChild(); + void userCancelledLoad(); + bool havePotentialSourceChild(); + void noneSupported(); + void mediaEngineError(PassRefPtr<MediaError> err); + void cancelPendingEventsAndCallbacks(); + void waitForSourceChange(); + + enum InvalidSourceAction { DoNothing, Complain }; + bool isSafeToLoadURL(const KURL&, InvalidSourceAction); + KURL selectNextSourceChild(ContentType*, InvalidSourceAction); + + // These "internal" functions do not check user gesture restrictions. + void loadInternal(); + void playInternal(); + void pauseInternal(); + + void prepareForLoad(); + void allowVideoRendering(); + + bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; } + void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; } + void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; } + + void updateVolume(); + void updatePlayState(); + bool potentiallyPlaying() const; + bool endedPlayback() const; + bool stoppedDueToErrors() const; + bool pausedForUserInteraction() const; + bool couldPlayIfEnoughData() const; + + float minTimeSeekable() const; + float maxTimeSeekable() const; + + // Pauses playback without changing any states or generating events + void setPausedInternal(bool); + + virtual void mediaCanStart(); + + void setShouldDelayLoadEvent(bool); + + void invalidateCachedTime(); + void refreshCachedTime() const; + + // Restrictions to change default behaviors. This is effectively a compile time choice at the moment + // because there are no accessor functions. + enum BehaviorRestrictions { + NoRestrictions = 0, + RequireUserGestureForLoadRestriction = 1 << 0, + RequireUserGestureForRateChangeRestriction = 1 << 1, + }; + + Timer<HTMLMediaElement> m_loadTimer; + Timer<HTMLMediaElement> m_asyncEventTimer; + Timer<HTMLMediaElement> m_progressEventTimer; + Timer<HTMLMediaElement> m_playbackProgressTimer; + Vector<RefPtr<Event> > m_pendingEvents; + RefPtr<TimeRanges> m_playedTimeRanges; + + float m_playbackRate; + float m_defaultPlaybackRate; + bool m_webkitPreservesPitch; + NetworkState m_networkState; + ReadyState m_readyState; + ReadyState m_readyStateMaximum; + String m_currentSrc; + + RefPtr<MediaError> m_error; + + float m_volume; + float m_lastSeekTime; + + unsigned m_previousProgress; + double m_previousProgressTime; + + // the last time a timeupdate event was sent (wall clock) + double m_lastTimeUpdateEventWallTime; + + // the last time a timeupdate event was sent in movie time + float m_lastTimeUpdateEventMovieTime; + + // loading state + enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement }; + LoadState m_loadState; + HTMLSourceElement* m_currentSourceNode; + Node* m_nextChildNodeToConsider; + Node* sourceChildEndOfListValue() { return static_cast<Node*>(this); } + + OwnPtr<MediaPlayer> m_player; +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) + RefPtr<Widget> m_proxyWidget; +#endif + + BehaviorRestrictions m_restrictions; + + MediaPlayer::Preload m_preload; + + DisplayMode m_displayMode; + + // Counter incremented while processing a callback from the media player, so we can avoid + // calling the media engine recursively. + int m_processingMediaPlayerCallback; + + mutable float m_cachedTime; + mutable double m_cachedTimeWallClockUpdateTime; + mutable double m_minimumWallClockTimeToCacheMediaTime; + + bool m_playing : 1; + bool m_isWaitingUntilMediaCanStart : 1; + bool m_shouldDelayLoadEvent : 1; + bool m_haveFiredLoadedData : 1; + bool m_inActiveDocument : 1; + bool m_autoplaying : 1; + bool m_muted : 1; + bool m_paused : 1; + bool m_seeking : 1; + + // data has not been loaded since sending a "stalled" event + bool m_sentStalledEvent : 1; + + // time has not changed since sending an "ended" event + bool m_sentEndEvent : 1; + + bool m_pausedInternal : 1; + + // Not all media engines provide enough information about a file to be able to + // support progress events so setting m_sendProgressEvents disables them + bool m_sendProgressEvents : 1; + + bool m_isFullscreen : 1; + bool m_closedCaptionsVisible : 1; + +#if ENABLE(PLUGIN_PROXY_FOR_VIDEO) + bool m_needWidgetUpdate : 1; +#endif + + bool m_dispatchingCanPlayEvent : 1; + bool m_loadInitiatedByUserGesture : 1; + bool m_completelyLoaded : 1; +}; + +} //namespace + +#endif +#endif |