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
39namespace WebCore {
40
41class Event;
42class HTMLSourceElement;
43class MediaError;
44class KURL;
45class TimeRanges;
46
47class HTMLMediaElement : public HTMLElement, public MediaPlayerClient {
48public:
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
176protected:
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
190private: // 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
206private:
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
269protected:
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