2009-10-05 Pierre d'Herbemont <pdherbemont@webkit.org>
[WebKit.git] / WebCore / html / HTMLMediaElement.h
1 /*
2  * Copyright (C) 2007, 2008, 2009 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 willRemove();
61     virtual void removedFromDocument();
62     virtual void attach();
63     virtual void recalcStyle(StyleChange);
64     
65     MediaPlayer* player() const { return m_player.get(); }
66     
67     virtual bool isVideo() const { return false; }
68     virtual bool hasVideo() const { return false; }
69     virtual bool hasAudio() const;
70
71     void rewind(float timeDelta);
72     void returnToRealtime();
73
74     // Eventually overloaded in HTMLVideoElement
75     virtual bool supportsFullscreen() const { return false; };
76     virtual bool supportsSave() const;
77     
78     PlatformMedia platformMedia() const;
79
80     void scheduleLoad();
81     
82     virtual void defaultEventHandler(Event*);
83     
84     // Pauses playback without changing any states or generating events
85     void setPausedInternal(bool);
86     
87     MediaPlayer::MovieLoadType movieLoadType() const;
88     
89     bool inActiveDocument() const { return m_inActiveDocument; }
90     
91 // DOM API
92 // error state
93     PassRefPtr<MediaError> error() const;
94
95 // network state
96     KURL src() const;
97     void setSrc(const String&);
98     String currentSrc() const;
99
100     enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_LOADED, NETWORK_NO_SOURCE };
101     NetworkState networkState() const;
102     bool autobuffer() const;    
103     void setAutobuffer(bool);
104
105     PassRefPtr<TimeRanges> buffered() const;
106     void load(ExceptionCode&);
107     String canPlayType(const String& mimeType) const;
108
109 // ready state
110     enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA };
111     ReadyState readyState() const;
112     bool seeking() const;
113
114 // playback state
115     float currentTime() const;
116     void setCurrentTime(float, ExceptionCode&);
117     float startTime() const;
118     float duration() const;
119     bool paused() const;
120     float defaultPlaybackRate() const;
121     void setDefaultPlaybackRate(float);
122     float playbackRate() const;
123     void setPlaybackRate(float);
124     bool webkitPreservesPitch() const;
125     void setWebkitPreservesPitch(bool);
126     PassRefPtr<TimeRanges> played();
127     PassRefPtr<TimeRanges> seekable() const;
128     bool ended() const;
129     bool autoplay() const;    
130     void setAutoplay(bool b);
131     bool loop() const;    
132     void setLoop(bool b);
133     void play();
134     void pause();
135     
136 // controls
137     bool controls() const;
138     void setControls(bool);
139     float volume() const;
140     void setVolume(float, ExceptionCode&);
141     bool muted() const;
142     void setMuted(bool);
143     void togglePlayState();
144     void beginScrubbing();
145     void endScrubbing();
146
147     const IntRect screenRect();
148
149     bool canPlay() const;
150
151     float percentLoaded() const;
152
153 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
154     void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; }
155     void deliverNotification(MediaPlayerProxyNotificationType notification);
156     void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
157     String initialURL();
158     virtual void finishParsingChildren();
159 #endif
160
161     bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
162     
163     void enterFullscreen();
164     void exitFullscreen();
165
166 protected:
167     float getTimeOffsetAttribute(const QualifiedName&, float valueOnError) const;
168     void setTimeOffsetAttribute(const QualifiedName&, float value);
169     
170     virtual void documentWillBecomeInactive();
171     virtual void documentDidBecomeActive();
172     virtual void mediaVolumeDidChange();
173     
174     void setReadyState(MediaPlayer::ReadyState);
175     void setNetworkState(MediaPlayer::NetworkState);
176     
177 private: // MediaPlayerClient
178     virtual void mediaPlayerNetworkStateChanged(MediaPlayer*);
179     virtual void mediaPlayerReadyStateChanged(MediaPlayer*);
180     virtual void mediaPlayerTimeChanged(MediaPlayer*);
181     virtual void mediaPlayerVolumeChanged(MediaPlayer*);
182     virtual void mediaPlayerDurationChanged(MediaPlayer*);
183     virtual void mediaPlayerRateChanged(MediaPlayer*);
184     virtual void mediaPlayerSawUnsupportedTracks(MediaPlayer*);
185     virtual void mediaPlayerRepaint(MediaPlayer*);
186     virtual void mediaPlayerSizeChanged(MediaPlayer*);
187 #if USE(ACCELERATED_COMPOSITING)
188     virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*);
189     virtual GraphicsLayer* mediaPlayerGraphicsLayer(MediaPlayer*);
190 #endif
191
192 private:
193     void loadTimerFired(Timer<HTMLMediaElement>*);
194     void asyncEventTimerFired(Timer<HTMLMediaElement>*);
195     void progressEventTimerFired(Timer<HTMLMediaElement>*);
196     void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
197     void startPlaybackProgressTimer();
198     void startProgressEventTimer();
199     void stopPeriodicTimers();
200
201     void seek(float time, ExceptionCode&);
202     void finishSeek();
203     void checkIfSeekNeeded();
204     void addPlayedRange(float start, float end);
205     
206     void scheduleTimeupdateEvent(bool periodicEvent);
207     void scheduleProgressEvent(const AtomicString& eventName);
208     void scheduleEvent(const AtomicString& eventName);
209     void enqueueEvent(RefPtr<Event> event);
210     
211     // loading
212     void selectMediaResource();
213     void loadResource(const KURL&, ContentType&);
214     void scheduleNextSourceChild();
215     void loadNextSourceChild();
216     void userCancelledLoad();
217     bool havePotentialSourceChild();
218     void noneSupported();
219     void mediaEngineError(PassRefPtr<MediaError> err);
220     void cancelPendingEventsAndCallbacks();
221
222     enum InvalidSourceAction { DoNothing, Complain };
223     bool isSafeToLoadURL(const KURL&, InvalidSourceAction);
224     KURL selectNextSourceChild(ContentType*, InvalidSourceAction);
225
226     // These "internal" functions do not check user gesture restrictions.
227     void loadInternal();
228     void playInternal();
229     void pauseInternal();
230
231     void prepareForLoad();
232     
233     bool processingUserGesture() const;
234     bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; }
235     void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; }
236     void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; }
237
238     void updateVolume();
239     void updatePlayState();
240     bool potentiallyPlaying() const;
241     bool endedPlayback() const;
242     bool stoppedDueToErrors() const;
243     bool pausedForUserInteraction() const;
244
245     float minTimeSeekable() const;
246     float maxTimeSeekable() const;
247
248     // Restrictions to change default behaviors. This is a effectively a compile time choice at the moment
249     //  because there are no accessor methods.
250     enum BehaviorRestrictions {
251         NoRestrictions = 0,
252         RequireUserGestureForLoadRestriction = 1 << 0,
253         RequireUserGestureForRateChangeRestriction = 1 << 1,
254     };
255
256 protected:
257     Timer<HTMLMediaElement> m_loadTimer;
258     Timer<HTMLMediaElement> m_asyncEventTimer;
259     Timer<HTMLMediaElement> m_progressEventTimer;
260     Timer<HTMLMediaElement> m_playbackProgressTimer;
261     Vector<RefPtr<Event> > m_pendingEvents;
262     RefPtr<TimeRanges> m_playedTimeRanges;
263     
264     float m_playbackRate;
265     float m_defaultPlaybackRate;
266     bool m_webkitPreservesPitch;
267     NetworkState m_networkState;
268     ReadyState m_readyState;
269     String m_currentSrc;
270     
271     RefPtr<MediaError> m_error;
272
273     float m_volume;
274     float m_lastSeekTime;
275     
276     unsigned m_previousProgress;
277     double m_previousProgressTime;
278
279     // the last time a timeupdate event was sent (wall clock)
280     double m_lastTimeUpdateEventWallTime;
281
282     // the last time a timeupdate event was sent in movie time
283     float m_lastTimeUpdateEventMovieTime;
284     
285     // loading state
286     enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
287     LoadState m_loadState;
288     HTMLSourceElement *m_currentSourceNode;
289     
290     OwnPtr<MediaPlayer> m_player;
291
292     BehaviorRestrictions m_restrictions;
293
294     bool m_playing;
295
296     // counter incremented while processing a callback from the media player, so we can avoid
297     //  calling the media engine recursively
298     int m_processingMediaPlayerCallback;
299
300     bool m_processingLoad : 1;
301     bool m_delayingTheLoadEvent : 1;
302     bool m_haveFiredLoadedData : 1;
303     bool m_inActiveDocument : 1;
304     bool m_autoplaying : 1;
305     bool m_muted : 1;
306     bool m_paused : 1;
307     bool m_seeking : 1;
308
309     // data has not been loaded since sending a "stalled" event
310     bool m_sentStalledEvent : 1;
311
312     // time has not changed since sending an "ended" event
313     bool m_sentEndEvent : 1;
314
315     bool m_pausedInternal : 1;
316
317     // Not all media engines provide enough information about a file to be able to
318     // support progress events so setting m_sendProgressEvents disables them 
319     bool m_sendProgressEvents : 1;
320
321     bool m_isFullscreen : 1;
322
323 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
324     bool m_needWidgetUpdate : 1;
325 #endif
326 };
327
328 } //namespace
329
330 #endif
331 #endif