2009-10-09 Chris Toshok <toshok@ximian.com>
[moon.git] / src / mediaelement.h
blobb7f8b38b5abb4d496f4431278a4691fe25ca5acb
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * mediaelement.h:
5 * Contact:
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
13 #ifndef __MOON_MEDIAELEMENT_H__
14 #define __MOON_MEDIAELEMENT_H__
16 #include <glib.h>
17 #include <gdk/gdkpixbuf.h>
19 #include "value.h"
20 #include "frameworkelement.h"
21 #include "pipeline.h"
22 #include "downloader.h"
23 #include "mutex.h"
24 #include "enums.h"
26 /* @Namespace=System.Windows.Controls */
27 class MediaElement : public FrameworkElement {
28 friend class MediaElementPropertyValueProvider;
29 private:
30 Mutex mutex;
32 List *streamed_markers_queue; // Thread-safe: Accesses to this field needs to use the mutex.
33 TimelineMarkerCollection *streamed_markers; // Main thread only.
34 ErrorEventArgs *error_args; // Thread-safe: Accesses to this field needs to use the mutex.
35 MediaMarkerFoundClosure *marker_closure;
36 cairo_matrix_t matrix;
37 MediaPlayer *mplayer;
38 PlaylistRoot *playlist;
40 //
41 guint32 marker_timeout;
42 // When checking if a marker has been reached, we need to
43 // know the last time the check was made, to see if
44 // the marker's pts hit the region.
45 guint64 previous_position;
46 // When the position is changed by the client, we store the requested position
47 // here and do the actual seeking async. Note that we might get several seek requests
48 // before the actual seek is done, currently we just seek to the last position requested,
49 // the previous requests are ignored. -1 denotes that there are no pending seeks.
50 TimeSpan seek_to_position;
51 // This is the last seeked to position. Used to never ever return a Position below this value.
52 guint64 seeked_to_position;
53 // This is the position when Pause is called. Since the actually Pause is done async, we must report
54 // this value as the current Position.
55 guint64 paused_position;
57 // Buffering can be caused by:
58 // [1] When the media is opened, we automatically buffer an amount equal to BufferingTime.
59 // - In this case we ask the pipeline how much it has buffered.
61 // [2] When during playback we realize that we don't have enough data.
62 // - In this case we ask the pipelien how much it has buffered.
64 // [3] When we seek, and realize that we don't have enough data.
65 // - In this case the buffering progress is calculated as:
66 // ("last available pts" - "last played pts") / ("seeked to pts" - "last played pts" + BufferingTime)
68 guint64 last_played_pts;
69 guint64 first_pts; // the first pts, starts off at GUINT_MAX
70 int buffering_mode; // if we're in [3] or not: 0 = unknown, 1 = [1], etc.
72 // this is used to know what to do after a Buffering state finishes
73 MediaState prev_state;
75 // The current state of the media element.
76 MediaState state;
78 guint32 flags;
80 void Reinitialize (); // not thread-safe
82 void SetMarkerTimeout (bool start); // not thread-safe
83 static gboolean MarkerTimeout (gpointer context); // not thread-safe
85 // Media event handlers
87 EVENTHANDLER (MediaElement, Opening, PlaylistRoot, EventArgs); // Not thread-safe
88 EVENTHANDLER (MediaElement, OpenCompleted, PlaylistRoot, EventArgs); // Not thread-safe
89 EVENTHANDLER (MediaElement, Seeking, PlaylistRoot, EventArgs); // Not thread-safe
90 EVENTHANDLER (MediaElement, SeekCompleted, PlaylistRoot, EventArgs); // Not thread-safe
91 EVENTHANDLER (MediaElement, Seek, PlaylistRoot, EventArgs); // Not thread-safe
92 EVENTHANDLER (MediaElement, CurrentStateChanged, PlaylistRoot, EventArgs); // Not thread-safe
93 EVENTHANDLER (MediaElement, MediaError, PlaylistRoot, ErrorEventArgs); // Not thread-safe
94 EVENTHANDLER (MediaElement, MediaEnded, PlaylistRoot, EventArgs); // Not thread-safe
95 EVENTHANDLER (MediaElement, DownloadProgressChanged, PlaylistRoot, EventArgs); // Not thread-safe
96 EVENTHANDLER (MediaElement, BufferingProgressChanged, PlaylistRoot, EventArgs); // Not thread-safe
97 EVENTHANDLER (MediaElement, Play, PlaylistRoot, EventArgs); // Not thread-safe
98 EVENTHANDLER (MediaElement, Pause, PlaylistRoot, EventArgs); // Not thread-safe
99 EVENTHANDLER (MediaElement, Stop, PlaylistRoot, EventArgs); // Not thread-safe
100 EVENTHANDLER (MediaElement, BufferUnderflow, PlaylistRoot, EventArgs); // Not thread-safe
101 EVENTHANDLER (MediaElement, EntryChanged, PlaylistRoot, EventArgs); // Not thread-safe
103 EVENTHANDLER (MediaElement, ShuttingDown, Deployment, EventArgs); // Not thread-safe
105 // Fill in information to/from the media, mediaplayer, etc.
106 // Does not change any state
107 void SetProperties (Media *media);
109 void EmitMediaEnded ();
110 void EmitStateChangedAsync ();
111 static void EmitStateChanged (EventObject *obj);
112 static void ReportErrorOccurredCallback (EventObject *obj);
114 void AddStreamedMarker (TimelineMarker *marker); // Thread-safe
115 void AddStreamedMarker (MediaMarker *marker); // Thread-safe
116 static MediaResult AddStreamedMarkerCallback (MediaClosure *closure); // Thread-safe
117 void CheckMarkers (guint64 from, guint64 to, TimelineMarkerCollection *col, bool remove); // Not thread-safe
118 void CheckMarkers (guint64 from, guint64 to); // Not thread-safe
119 void CheckMarkers (); // Not thread-safe
120 void ReadMarkers (Media *media, IMediaDemuxer *demuxer); // Not thread-safe
123 // Private Property Accessors
125 void SetAudioStreamCount (int count);
127 void SetBufferingProgress (double progress);
129 void SetCanPause (bool set);
130 void SetCanSeek (bool set);
132 void SetNaturalVideoHeight (int height);
133 void SetNaturalVideoWidth (int width);
135 void Seek (TimeSpan to); // Not thread-safe.
136 void PlayOrStop (); // Not thread-safe. To the right thing if we can pause, if we have to autoplay, etc.
138 void CreatePlaylist ();
139 void SetPlaylist (PlaylistRoot *playlist); // Adds/removes event handlers
141 protected:
142 virtual ~MediaElement () {}
144 public:
145 /* @GenerateCBinding,GeneratePInvoke */
146 MediaElement ();
147 virtual void Dispose ();
149 // properties
150 /* @PropertyType=MediaAttributeCollection,ManagedPropertyType=Dictionary<string\,string>,AutoCreateValue,ManagedSetterAccess=Internal,GenerateAccessors,Validator=MediaAttributeCollectionValidator */
151 const static int AttributesProperty;
152 /* @PropertyType=gint32,DefaultValue=0,ReadOnly,GenerateAccessors */
153 const static int AudioStreamCountProperty;
154 /* @PropertyType=gint32,Nullable,GenerateAccessors,Validator=AudioStreamIndexValidator */
155 const static int AudioStreamIndexProperty;
156 /* @PropertyType=bool,DefaultValue=true,GenerateAccessors */
157 const static int AutoPlayProperty;
158 /* @PropertyType=double,DefaultValue=0.0,GenerateAccessors,Validator=BalanceValidator */
159 const static int BalanceProperty;
160 /* @PropertyType=double,DefaultValue=0.0,ReadOnly,GenerateAccessors */
161 const static int BufferingProgressProperty;
162 /* @PropertyType=TimeSpan,GenerateAccessors,Validator=BufferingTimeValidator */
163 const static int BufferingTimeProperty;
164 /* @PropertyType=bool,DefaultValue=false,ReadOnly,GenerateAccessors */
165 const static int CanPauseProperty;
166 /* @PropertyType=bool,DefaultValue=false,ReadOnly,GenerateAccessors */
167 const static int CanSeekProperty;
168 /* @PropertyType=double,ReadOnly,DefaultValue=0.0,GenerateAccessors */
169 const static int DownloadProgressProperty;
170 /* @PropertyType=MediaState,ReadOnly,ManagedPropertyType=MediaElementState,DefaultValue=MediaStateClosed,GenerateAccessors */
171 const static int CurrentStateProperty;
172 /* @PropertyType=bool,DefaultValue=false,GenerateAccessors */
173 const static int IsMutedProperty;
174 /* @PropertyType=TimelineMarkerCollection,AutoCreateValue,ManagedFieldAccess=Internal,ManagedSetterAccess=Internal,GenerateAccessors */
175 const static int MarkersProperty;
176 /* @PropertyType=Duration,DefaultValue=Duration::FromSeconds (0),ReadOnly,GenerateAccessors */
177 const static int NaturalDurationProperty;
178 /* @PropertyType=gint32,DefaultValue=0,ReadOnly,GenerateAccessors,Validator=IntGreaterThanZeroValidator */
179 const static int NaturalVideoHeightProperty;
180 /* @PropertyType=gint32,DefaultValue=0,ReadOnly,GenerateAccessors,Validator=IntGreaterThanZeroValidator */
181 const static int NaturalVideoWidthProperty;
182 /* @PropertyType=TimeSpan,AlwaysChange,GenerateAccessors */
183 const static int PositionProperty;
184 /* @PropertyType=Uri,AlwaysChange,ManagedPropertyType=Uri,Nullable,GenerateAccessors */
185 const static int SourceProperty;
186 /* @PropertyType=Stretch,DefaultValue=StretchUniform,GenerateAccessors */
187 const static int StretchProperty;
188 /* @PropertyType=double,DefaultValue=0.5,GenerateAccessors,Validator=VolumeValidator */
189 const static int VolumeProperty;
191 /* @PropertyType=double,DefaultValue=0.0,GenerateAccessors,ReadOnly */
192 const static int DownloadProgressOffsetProperty;
193 /* @PropertyType=double,DefaultValue=0.0,GenerateAccessors,ReadOnly */
194 const static int DroppedFramesPerSecondProperty;
195 /* @PropertyType=double,DefaultValue=0.0,GenerateAccessors,ReadOnly */
196 const static int RenderedFramesPerSecondProperty;
198 // events
199 /* @DelegateType=RoutedEventHandler */
200 const static int BufferingProgressChangedEvent;
201 /* @DelegateType=RoutedEventHandler */
202 const static int CurrentStateChangedEvent;
203 /* @DelegateType=RoutedEventHandler */
204 const static int DownloadProgressChangedEvent;
205 /* @DelegateType=TimelineMarkerRoutedEventHandler */
206 const static int MarkerReachedEvent;
207 /* @DelegateType=RoutedEventHandler */
208 const static int MediaEndedEvent;
209 /* @DelegateType=EventHandler<ExceptionRoutedEventArgs> */
210 const static int MediaFailedEvent;
211 // MediaOpened is raised when media is ready to play (we've already started playing, or, if AutoPlay is false, paused).
212 /* @DelegateType=RoutedEventHandler */
213 const static int MediaOpenedEvent;
214 /* @GenerateManagedEvent=false */
215 const static int MediaInvalidatedEvent;
217 virtual void SetSurface (Surface *surface);
219 MediaPlayer *GetMediaPlayer () { return mplayer; }
221 // overrides
222 virtual void Render (cairo_t *cr, Region *region, bool path_only = false);
223 virtual Point GetTransformOrigin ();
225 virtual Rect GetCoverageBounds ();
226 virtual Size ComputeActualSize ();
227 virtual Size MeasureOverride (Size availableSize);
228 virtual Size ArrangeOverride (Size finalSize);
230 virtual void OnPropertyChanged (PropertyChangedEventArgs *args, MoonError *error);
232 void MediaInvalidate ();
234 void SetSource (Downloader *downloader, const char *PartName);
235 void SetUriSource (Uri *uri); // This is called from OnPropertyChanged
236 /* @GenerateCBinding,GeneratePInvoke,Version=2.0 */
237 void SetStreamSource (ManagedStreamCallbacks *stream);
238 /* @GenerateCBinding,GeneratePInvoke */
239 IMediaDemuxer *SetDemuxerSource (void *context, CloseDemuxerCallback close_demuxer, GetDiagnosticAsyncCallback get_diagnostic, GetFrameAsyncCallback get_sample, OpenDemuxerAsyncCallback open_demuxer, SeekAsyncCallback seek, SwitchMediaStreamAsyncCallback switch_media_stream);
241 /* @GenerateCBinding,GeneratePInvoke */
242 void Pause (); // Not thread-safe
244 /* @GenerateCBinding,GeneratePInvoke */
245 void Play (); // Not thread-safe
247 /* @GenerateCBinding,GeneratePInvoke */
248 void Stop (); // Not thread-safe
250 void ReportErrorOccurred (ErrorEventArgs *args); // Thread safe
251 /* @GenerateCBinding,GeneratePInvoke */
252 void ReportErrorOccurred (const char *args); // Thread safe
254 // State methods
255 bool IsClosed () { return state == MediaStateClosed; }
256 bool IsOpening () { return state == MediaStateOpening; }
257 bool IsBuffering () { return state == MediaStateBuffering; }
258 bool IsPlaying () { return state == MediaStatePlaying; }
259 bool IsPaused () { return state == MediaStatePaused; }
260 bool IsStopped () { return state == MediaStateStopped; }
262 bool IsMissingCodecs (); // Not thread-safe
264 void SetPlayRequested (); // Not thread-safe
266 static const char *GetStateName (MediaState state); // Thread-safe
268 MediaState GetState () { return state; } // Thread-safe
269 void SetState (MediaState state); // Thread-safe
271 virtual bool EnableAntiAlias ();
274 // Public Property Accessors
276 void SetAttributes (MediaAttributeCollection *attrs);
277 MediaAttributeCollection *GetAttributes ();
279 int GetAudioStreamCount ();
281 void SetAudioStreamIndex (gint32 index);
282 void SetAudioStreamIndex (gint32* index);
283 gint32* GetAudioStreamIndex ();
285 void SetAutoPlay (bool set);
286 bool GetAutoPlay ();
288 void SetBalance (double balance);
289 double GetBalance ();
291 double GetBufferingProgress ();
293 void SetBufferingTime (TimeSpan time);
294 TimeSpan GetBufferingTime ();
296 bool GetCanPause ();
297 bool GetCanSeek ();
299 void SetCurrentState (MediaState state);
300 MediaState GetCurrentState ();
302 void SetIsMuted (bool set);
303 bool GetIsMuted ();
305 void SetMarkers (TimelineMarkerCollection *markers);
306 TimelineMarkerCollection *GetMarkers ();
308 void SetNaturalDuration (Duration *duration);
309 Duration *GetNaturalDuration ();
311 int GetNaturalVideoHeight ();
312 int GetNaturalVideoWidth ();
314 void SetPosition (TimeSpan position);
315 TimeSpan GetPosition ();
317 void SetVolume (double volume);
318 double GetVolume ();
320 void SetDownloadProgressOffset (double value);
321 double GetDownloadProgressOffset ();
323 void SetRenderedFramesPerSecond (double value);
324 double GetRenderedFramesPerSecond ();
326 void SetDroppedFramesPerSecond (double value);
327 double GetDroppedFramesPerSecond ();
329 double GetDownloadProgress ();
330 void SetDownloadProgress (double progress);
332 void SetSource (Uri *uri);
333 void SetSource (Uri uri);
334 Uri *GetSource ();
336 void SetStretch (Stretch stretch);
337 Stretch GetStretch ();
341 * MediaElementPropertyValueProvider
344 class MediaElementPropertyValueProvider : public FrameworkElementProvider {
345 private:
346 Value *position;
347 Value *current_state;
348 Value *rendered_frames_per_second;
349 Value *dropped_frames_per_second;
351 Value *GetPosition ();
352 Value *GetCurrentState ();
353 Value *GetRenderedFramesPerSecond ();
354 Value *GetDroppedFramesPerSecond ();
355 public:
356 MediaElementPropertyValueProvider (MediaElement *obj, PropertyPrecedence precedence);
357 virtual ~MediaElementPropertyValueProvider ();
358 virtual Value *GetPropertyValue (DependencyProperty *property);
361 #endif /* __MEDIAELEMENT_H__ */