Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef HTMLMediaElement_h
     27 #define HTMLMediaElement_h
     28 
     29 #if ENABLE(VIDEO)
     30 
     31 #include "HTMLElement.h"
     32 #include "MediaPlayer.h"
     33 #include "Timer.h"
     34 
     35 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     36 #include "MediaPlayerProxy.h"
     37 #endif
     38 
     39 namespace WebCore {
     40 
     41 class Event;
     42 class HTMLSourceElement;
     43 class MediaError;
     44 class KURL;
     45 class TimeRanges;
     46 
     47 class HTMLMediaElement : public HTMLElement, public MediaPlayerClient {
     48 public:
     49     HTMLMediaElement(const QualifiedName&, Document*);
     50     virtual ~HTMLMediaElement();
     51 
     52     bool checkDTD(const Node* newChild);
     53 
     54     void attributeChanged(Attribute*, bool preserveDecls);
     55     void parseMappedAttribute(MappedAttribute *);
     56 
     57     virtual bool rendererIsNeeded(RenderStyle*);
     58     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
     59     virtual void insertedIntoDocument();
     60     virtual void removedFromDocument();
     61     virtual void attach();
     62     virtual void recalcStyle(StyleChange);
     63 
     64     MediaPlayer* player() const { return m_player.get(); }
     65 
     66     virtual bool isVideo() const { return false; }
     67     virtual bool hasVideo() const { return false; }
     68     virtual bool hasAudio() const;
     69 
     70     void rewind(float timeDelta);
     71     void returnToRealtime();
     72 
     73     // Eventually overloaded in HTMLVideoElement
     74     virtual bool supportsFullscreen() const { return false; };
     75     virtual bool supportsSave() const;
     76 
     77     PlatformMedia platformMedia() const;
     78 
     79     void scheduleLoad();
     80 
     81     virtual void defaultEventHandler(Event*);
     82 
     83     // Pauses playback without changing any states or generating events
     84     void setPausedInternal(bool);
     85 
     86     MediaPlayer::MovieLoadType movieLoadType() const;
     87 
     88     bool inActiveDocument() const { return m_inActiveDocument; }
     89 
     90 // DOM API
     91 // error state
     92     PassRefPtr<MediaError> error() const;
     93 
     94 // network state
     95     KURL src() const;
     96     void setSrc(const String&);
     97     String currentSrc() const;
     98 
     99     enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_LOADED, NETWORK_NO_SOURCE };
    100     NetworkState networkState() const;
    101     bool autobuffer() const;
    102     void setAutobuffer(bool);
    103 
    104     PassRefPtr<TimeRanges> buffered() const;
    105     void load(bool isUserGesture, ExceptionCode&);
    106     String canPlayType(const String& mimeType) const;
    107 
    108 // ready state
    109     enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA };
    110     ReadyState readyState() const;
    111     bool seeking() const;
    112 
    113 // playback state
    114     float currentTime() const;
    115     void setCurrentTime(float, ExceptionCode&);
    116     float startTime() const;
    117     float duration() const;
    118     bool paused() const;
    119     float defaultPlaybackRate() const;
    120     void setDefaultPlaybackRate(float);
    121     float playbackRate() const;
    122     void setPlaybackRate(float);
    123     bool webkitPreservesPitch() const;
    124     void setWebkitPreservesPitch(bool);
    125     PassRefPtr<TimeRanges> played();
    126     PassRefPtr<TimeRanges> seekable() const;
    127     bool ended() const;
    128     bool autoplay() const;
    129     void setAutoplay(bool b);
    130     bool loop() const;
    131     void setLoop(bool b);
    132     void play(bool isUserGesture);
    133     void pause(bool isUserGesture);
    134 
    135 // captions
    136     bool webkitHasClosedCaptions() const;
    137     bool webkitClosedCaptionsVisible() const;
    138     void setWebkitClosedCaptionsVisible(bool);
    139 
    140 // controls
    141     bool controls() const;
    142     void setControls(bool);
    143     float volume() const;
    144     void setVolume(float, ExceptionCode&);
    145     bool muted() const;
    146     void setMuted(bool);
    147     void togglePlayState();
    148     void beginScrubbing();
    149     void endScrubbing();
    150 
    151     const IntRect screenRect();
    152 
    153     bool canPlay() const;
    154 
    155     float percentLoaded() const;
    156 
    157 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
    158     void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; }
    159     void deliverNotification(MediaPlayerProxyNotificationType notification);
    160     void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
    161     String initialURL();
    162     virtual void finishParsingChildren();
    163 #endif
    164 
    165     bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
    166 
    167     void enterFullscreen();
    168     void exitFullscreen();
    169 
    170     bool hasClosedCaptions() const;
    171     bool closedCaptionsVisible() const;
    172     void setClosedCaptionsVisible(bool);
    173 
    174     bool processingUserGesture() const;
    175 
    176 protected:
    177     float getTimeOffsetAttribute(const QualifiedName&, float valueOnError) const;
    178     void setTimeOffsetAttribute(const QualifiedName&, float value);
    179 
    180     virtual void documentWillBecomeInactive();
    181     virtual void documentDidBecomeActive();
    182     virtual void mediaVolumeDidChange();
    183 
    184     void setReadyState(MediaPlayer::ReadyState);
    185     void setNetworkState(MediaPlayer::NetworkState);
    186 
    187     virtual void willMoveToNewOwnerDocument();
    188     virtual void didMoveToNewOwnerDocument();
    189 
    190 private: // MediaPlayerClient
    191     virtual void mediaPlayerNetworkStateChanged(MediaPlayer*);
    192     virtual void mediaPlayerReadyStateChanged(MediaPlayer*);
    193     virtual void mediaPlayerTimeChanged(MediaPlayer*);
    194     virtual void mediaPlayerVolumeChanged(MediaPlayer*);
    195     virtual void mediaPlayerMuteChanged(MediaPlayer*);
    196     virtual void mediaPlayerDurationChanged(MediaPlayer*);
    197     virtual void mediaPlayerRateChanged(MediaPlayer*);
    198     virtual void mediaPlayerSawUnsupportedTracks(MediaPlayer*);
    199     virtual void mediaPlayerRepaint(MediaPlayer*);
    200     virtual void mediaPlayerSizeChanged(MediaPlayer*);
    201 #if USE(ACCELERATED_COMPOSITING)
    202     virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*);
    203     virtual GraphicsLayer* mediaPlayerGraphicsLayer(MediaPlayer*);
    204 #endif
    205 
    206 private:
    207     void loadTimerFired(Timer<HTMLMediaElement>*);
    208     void asyncEventTimerFired(Timer<HTMLMediaElement>*);
    209     void progressEventTimerFired(Timer<HTMLMediaElement>*);
    210     void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
    211     void startPlaybackProgressTimer();
    212     void startProgressEventTimer();
    213     void stopPeriodicTimers();
    214 
    215     void seek(float time, ExceptionCode&);
    216     void finishSeek();
    217     void checkIfSeekNeeded();
    218     void addPlayedRange(float start, float end);
    219 
    220     void scheduleTimeupdateEvent(bool periodicEvent);
    221     void scheduleEvent(const AtomicString& eventName);
    222 
    223     // loading
    224     void selectMediaResource();
    225     void loadResource(const KURL&, ContentType&);
    226     void scheduleNextSourceChild();
    227     void loadNextSourceChild();
    228     void userCancelledLoad();
    229     bool havePotentialSourceChild();
    230     void noneSupported();
    231     void mediaEngineError(PassRefPtr<MediaError> err);
    232     void cancelPendingEventsAndCallbacks();
    233     void waitForSourceChange();
    234 
    235     enum InvalidSourceAction { DoNothing, Complain };
    236     bool isSafeToLoadURL(const KURL&, InvalidSourceAction);
    237     KURL selectNextSourceChild(ContentType*, InvalidSourceAction);
    238 
    239     // These "internal" functions do not check user gesture restrictions.
    240     void loadInternal();
    241     void playInternal();
    242     void pauseInternal();
    243 
    244     void prepareForLoad();
    245 
    246     bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; }
    247     void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; }
    248     void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; }
    249 
    250     void updateVolume();
    251     void updatePlayState();
    252     bool potentiallyPlaying() const;
    253     bool endedPlayback() const;
    254     bool stoppedDueToErrors() const;
    255     bool pausedForUserInteraction() const;
    256     bool couldPlayIfEnoughData() const;
    257 
    258     float minTimeSeekable() const;
    259     float maxTimeSeekable() const;
    260 
    261     // Restrictions to change default behaviors. This is a effectively a compile time choice at the moment
    262     //  because there are no accessor methods.
    263     enum BehaviorRestrictions {
    264         NoRestrictions = 0,
    265         RequireUserGestureForLoadRestriction = 1 << 0,
    266         RequireUserGestureForRateChangeRestriction = 1 << 1,
    267     };
    268 
    269 protected:
    270     Timer<HTMLMediaElement> m_loadTimer;
    271     Timer<HTMLMediaElement> m_asyncEventTimer;
    272     Timer<HTMLMediaElement> m_progressEventTimer;
    273     Timer<HTMLMediaElement> m_playbackProgressTimer;
    274     Vector<RefPtr<Event> > m_pendingEvents;
    275     RefPtr<TimeRanges> m_playedTimeRanges;
    276 
    277     float m_playbackRate;
    278     float m_defaultPlaybackRate;
    279     bool m_webkitPreservesPitch;
    280     NetworkState m_networkState;
    281     ReadyState m_readyState;
    282     String m_currentSrc;
    283 
    284     RefPtr<MediaError> m_error;
    285 
    286     float m_volume;
    287     float m_lastSeekTime;
    288 
    289     unsigned m_previousProgress;
    290     double m_previousProgressTime;
    291 
    292     // the last time a timeupdate event was sent (wall clock)
    293     double m_lastTimeUpdateEventWallTime;
    294 
    295     // the last time a timeupdate event was sent in movie time
    296     float m_lastTimeUpdateEventMovieTime;
    297 
    298     // loading state
    299     enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
    300     LoadState m_loadState;
    301     HTMLSourceElement *m_currentSourceNode;
    302 
    303     OwnPtr<MediaPlayer> m_player;
    304 
    305     BehaviorRestrictions m_restrictions;
    306 
    307     bool m_playing;
    308 
    309     // counter incremented while processing a callback from the media player, so we can avoid
    310     //  calling the media engine recursively
    311     int m_processingMediaPlayerCallback;
    312 
    313     bool m_processingLoad : 1;
    314     bool m_delayingTheLoadEvent : 1;
    315     bool m_haveFiredLoadedData : 1;
    316     bool m_inActiveDocument : 1;
    317     bool m_autoplaying : 1;
    318     bool m_muted : 1;
    319     bool m_paused : 1;
    320     bool m_seeking : 1;
    321 
    322     // data has not been loaded since sending a "stalled" event
    323     bool m_sentStalledEvent : 1;
    324 
    325     // time has not changed since sending an "ended" event
    326     bool m_sentEndEvent : 1;
    327 
    328     bool m_pausedInternal : 1;
    329 
    330     // Not all media engines provide enough information about a file to be able to
    331     // support progress events so setting m_sendProgressEvents disables them
    332     bool m_sendProgressEvents : 1;
    333 
    334     bool m_isFullscreen : 1;
    335     bool m_closedCaptionsVisible : 1;
    336 
    337 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
    338     bool m_needWidgetUpdate : 1;
    339 #endif
    340 };
    341 
    342 } //namespace
    343 
    344 #endif
    345 #endif
    346