2011-02-01 Adam Barth <abarth@webkit.org>
[WebKit.git] / Source / WebCore / html / HTMLMediaElement.h
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 "ActiveDOMObject.h"
33 #include "MediaCanStartListener.h"
34 #include "MediaPlayer.h"
35
36 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
37 #include "MediaPlayerProxy.h"
38 #endif
39
40 namespace WebCore {
41
42 class Event;
43 class HTMLSourceElement;
44 class MediaError;
45 class KURL;
46 class TimeRanges;
47 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
48 class Widget;
49 #endif
50
51 // FIXME: The inheritance from MediaPlayerClient here should be private inheritance.
52 // But it can't be until the Chromium WebMediaPlayerClientImpl class is fixed so it
53 // no longer depends on typecasting a MediaPlayerClient to an HTMLMediaElement.
54
55 class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, private MediaCanStartListener, private ActiveDOMObject {
56 public:
57     MediaPlayer* player() const { return m_player.get(); }
58     
59     virtual bool isVideo() const = 0;
60     virtual bool hasVideo() const { return false; }
61     virtual bool hasAudio() const;
62
63     void rewind(float timeDelta);
64     void returnToRealtime();
65
66     // Eventually overloaded in HTMLVideoElement
67     virtual bool supportsFullscreen() const { return false; };
68
69     virtual bool supportsSave() const;
70     
71     PlatformMedia platformMedia() const;
72 #if USE(ACCELERATED_COMPOSITING)
73     PlatformLayer* platformLayer() const;
74 #endif
75
76     void scheduleLoad();
77     
78     MediaPlayer::MovieLoadType movieLoadType() const;
79     
80     bool inActiveDocument() const { return m_inActiveDocument; }
81     
82 // DOM API
83 // error state
84     PassRefPtr<MediaError> error() const;
85
86 // network state
87     void setSrc(const String&);
88     String currentSrc() const;
89
90     enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_NO_SOURCE };
91     NetworkState networkState() const;
92     
93     String preload() const;    
94     void setPreload(const String&);
95
96     PassRefPtr<TimeRanges> buffered() const;
97     void load(bool isUserGesture, ExceptionCode&);
98     String canPlayType(const String& mimeType) const;
99
100 // ready state
101     enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA };
102     ReadyState readyState() const;
103     bool seeking() const;
104
105 // playback state
106     float currentTime() const;
107     void setCurrentTime(float, ExceptionCode&);
108     float startTime() const;
109     float duration() const;
110     bool paused() const;
111     float defaultPlaybackRate() const;
112     void setDefaultPlaybackRate(float);
113     float playbackRate() const;
114     void setPlaybackRate(float);
115     bool webkitPreservesPitch() const;
116     void setWebkitPreservesPitch(bool);
117     PassRefPtr<TimeRanges> played();
118     PassRefPtr<TimeRanges> seekable() const;
119     bool ended() const;
120     bool autoplay() const;    
121     void setAutoplay(bool b);
122     bool loop() const;    
123     void setLoop(bool b);
124     void play(bool isUserGesture);
125     void pause(bool isUserGesture);
126
127 // captions
128     bool webkitHasClosedCaptions() const;
129     bool webkitClosedCaptionsVisible() const;
130     void setWebkitClosedCaptionsVisible(bool);
131
132 // controls
133     bool controls() const;
134     void setControls(bool);
135     float volume() const;
136     void setVolume(float, ExceptionCode&);
137     bool muted() const;
138     void setMuted(bool);
139     void togglePlayState();
140     void beginScrubbing();
141     void endScrubbing();
142
143     bool canPlay() const;
144
145     float percentLoaded() const;
146
147 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
148     void allocateMediaPlayerIfNecessary();
149     void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; }
150     void deliverNotification(MediaPlayerProxyNotificationType notification);
151     void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
152     void getPluginProxyParams(KURL& url, Vector<String>& names, Vector<String>& values);
153     virtual void finishParsingChildren();
154     void createMediaPlayerProxy();
155     void updateWidget(PluginCreationOption);
156 #endif
157
158     bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
159     
160     bool isFullscreen() const { return m_isFullscreen; }
161     void enterFullscreen();
162     void exitFullscreen();
163
164     bool hasClosedCaptions() const;
165     bool closedCaptionsVisible() const;
166     void setClosedCaptionsVisible(bool);
167
168     bool processingUserGesture() const;
169
170     void sourceWillBeRemoved(HTMLSourceElement*);
171     void sourceWasAdded(HTMLSourceElement*);
172
173 protected:
174     HTMLMediaElement(const QualifiedName&, Document*);
175     virtual ~HTMLMediaElement();
176
177     virtual void parseMappedAttribute(Attribute*);
178     virtual bool isURLAttribute(Attribute*) const;
179     virtual void attach();
180
181     virtual void willMoveToNewOwnerDocument();
182     virtual void didMoveToNewOwnerDocument();
183
184     enum DisplayMode { Unknown, None, Poster, Video };
185     DisplayMode displayMode() const { return m_displayMode; }
186     virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; }
187
188 private:
189     virtual void attributeChanged(Attribute*, bool preserveDecls);
190     virtual bool rendererIsNeeded(RenderStyle*);
191     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
192     virtual void insertedIntoDocument();
193     virtual void removedFromDocument();
194     virtual void recalcStyle(StyleChange);
195     
196     virtual void defaultEventHandler(Event*);
197     
198     // ActiveDOMObject functions.
199     virtual bool canSuspend() const;
200     virtual void suspend(ReasonForSuspension);
201     virtual void resume();
202     virtual void stop();
203     virtual bool hasPendingActivity() const;
204     
205     virtual void mediaVolumeDidChange();
206
207     virtual void updateDisplayState() { }
208     
209     void setReadyState(MediaPlayer::ReadyState);
210     void setNetworkState(MediaPlayer::NetworkState);
211
212     virtual Document* mediaPlayerOwningDocument();
213     virtual void mediaPlayerNetworkStateChanged(MediaPlayer*);
214     virtual void mediaPlayerReadyStateChanged(MediaPlayer*);
215     virtual void mediaPlayerTimeChanged(MediaPlayer*);
216     virtual void mediaPlayerVolumeChanged(MediaPlayer*);
217     virtual void mediaPlayerMuteChanged(MediaPlayer*);
218     virtual void mediaPlayerDurationChanged(MediaPlayer*);
219     virtual void mediaPlayerRateChanged(MediaPlayer*);
220     virtual void mediaPlayerPlaybackStateChanged(MediaPlayer*);
221     virtual void mediaPlayerSawUnsupportedTracks(MediaPlayer*);
222     virtual void mediaPlayerRepaint(MediaPlayer*);
223     virtual void mediaPlayerSizeChanged(MediaPlayer*);
224 #if USE(ACCELERATED_COMPOSITING)
225     virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*);
226     virtual void mediaPlayerRenderingModeChanged(MediaPlayer*);
227 #endif
228     virtual void mediaPlayerEngineUpdated(MediaPlayer*);
229
230     void loadTimerFired(Timer<HTMLMediaElement>*);
231     void asyncEventTimerFired(Timer<HTMLMediaElement>*);
232     void progressEventTimerFired(Timer<HTMLMediaElement>*);
233     void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
234     void startPlaybackProgressTimer();
235     void startProgressEventTimer();
236     void stopPeriodicTimers();
237
238     void seek(float time, ExceptionCode&);
239     void finishSeek();
240     void checkIfSeekNeeded();
241     void addPlayedRange(float start, float end);
242     
243     void scheduleTimeupdateEvent(bool periodicEvent);
244     void scheduleEvent(const AtomicString& eventName);
245     
246     // loading
247     void selectMediaResource();
248     void loadResource(const KURL&, ContentType&);
249     void scheduleNextSourceChild();
250     void loadNextSourceChild();
251     void userCancelledLoad();
252     bool havePotentialSourceChild();
253     void noneSupported();
254     void mediaEngineError(PassRefPtr<MediaError> err);
255     void cancelPendingEventsAndCallbacks();
256     void waitForSourceChange();
257
258     enum InvalidSourceAction { DoNothing, Complain };
259     bool isSafeToLoadURL(const KURL&, InvalidSourceAction);
260     KURL selectNextSourceChild(ContentType*, InvalidSourceAction);
261
262     // These "internal" functions do not check user gesture restrictions.
263     void loadInternal();
264     void playInternal();
265     void pauseInternal();
266
267     void prepareForLoad();
268     void allowVideoRendering();
269
270     bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; }
271     void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; }
272     void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; }
273
274     void updateVolume();
275     void updatePlayState();
276     bool potentiallyPlaying() const;
277     bool endedPlayback() const;
278     bool stoppedDueToErrors() const;
279     bool pausedForUserInteraction() const;
280     bool couldPlayIfEnoughData() const;
281
282     float minTimeSeekable() const;
283     float maxTimeSeekable() const;
284
285     // Pauses playback without changing any states or generating events
286     void setPausedInternal(bool);
287
288     virtual void mediaCanStart();
289
290     void setShouldDelayLoadEvent(bool);
291
292     void invalidateCachedTime();
293     void refreshCachedTime() const;
294
295     // Restrictions to change default behaviors. This is effectively a compile time choice at the moment
296     // because there are no accessor functions.
297     enum BehaviorRestrictions {
298         NoRestrictions = 0,
299         RequireUserGestureForLoadRestriction = 1 << 0,
300         RequireUserGestureForRateChangeRestriction = 1 << 1,
301     };
302
303     Timer<HTMLMediaElement> m_loadTimer;
304     Timer<HTMLMediaElement> m_asyncEventTimer;
305     Timer<HTMLMediaElement> m_progressEventTimer;
306     Timer<HTMLMediaElement> m_playbackProgressTimer;
307     Vector<RefPtr<Event> > m_pendingEvents;
308     RefPtr<TimeRanges> m_playedTimeRanges;
309     
310     float m_playbackRate;
311     float m_defaultPlaybackRate;
312     bool m_webkitPreservesPitch;
313     NetworkState m_networkState;
314     ReadyState m_readyState;
315     ReadyState m_readyStateMaximum;
316     String m_currentSrc;
317     
318     RefPtr<MediaError> m_error;
319
320     float m_volume;
321     float m_lastSeekTime;
322     
323     unsigned m_previousProgress;
324     double m_previousProgressTime;
325
326     // the last time a timeupdate event was sent (wall clock)
327     double m_lastTimeUpdateEventWallTime;
328
329     // the last time a timeupdate event was sent in movie time
330     float m_lastTimeUpdateEventMovieTime;
331     
332     // loading state
333     enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
334     LoadState m_loadState;
335     HTMLSourceElement* m_currentSourceNode;
336     Node* m_nextChildNodeToConsider;
337     Node* sourceChildEndOfListValue() { return static_cast<Node*>(this); }
338
339     OwnPtr<MediaPlayer> m_player;
340 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
341     RefPtr<Widget> m_proxyWidget;
342 #endif
343
344     BehaviorRestrictions m_restrictions;
345     
346     MediaPlayer::Preload m_preload;
347
348     DisplayMode m_displayMode;
349
350     // Counter incremented while processing a callback from the media player, so we can avoid
351     // calling the media engine recursively.
352     int m_processingMediaPlayerCallback;
353
354     mutable float m_cachedTime;
355     mutable double m_cachedTimeWallClockUpdateTime;
356     mutable double m_minimumWallClockTimeToCacheMediaTime;
357
358     bool m_playing : 1;
359     bool m_isWaitingUntilMediaCanStart : 1;
360     bool m_shouldDelayLoadEvent : 1;
361     bool m_haveFiredLoadedData : 1;
362     bool m_inActiveDocument : 1;
363     bool m_autoplaying : 1;
364     bool m_muted : 1;
365     bool m_paused : 1;
366     bool m_seeking : 1;
367
368     // data has not been loaded since sending a "stalled" event
369     bool m_sentStalledEvent : 1;
370
371     // time has not changed since sending an "ended" event
372     bool m_sentEndEvent : 1;
373
374     bool m_pausedInternal : 1;
375
376     // Not all media engines provide enough information about a file to be able to
377     // support progress events so setting m_sendProgressEvents disables them 
378     bool m_sendProgressEvents : 1;
379
380     bool m_isFullscreen : 1;
381     bool m_closedCaptionsVisible : 1;
382
383 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
384     bool m_needWidgetUpdate : 1;
385 #endif
386
387     bool m_dispatchingCanPlayEvent : 1;
388     bool m_loadInitiatedByUserGesture : 1;
389     bool m_completelyLoaded : 1;
390 };
391
392 } //namespace
393
394 #endif
395 #endif