3
Copyright (c) Goran Sterjov
5
This file is part of the GStreamer Playbin Wrapper.
6
Derived from the Dissent Project.
8
GStreamer Playbin Wrapper is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
13
The Dissent Project is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with the Dissent Project; if not, write to the Free Software
20
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
using System.Runtime.InteropServices;
33
// media engine enumerations
34
public enum MediaStatus { Playing, Stopped, Paused, Loaded, Unloaded }
35
public enum MediaEvents { EndOfStream, Error, Buffering, Volume, Seek }
37
// media engine event handlers
38
public delegate void EngineEventHandler (object o, EngineEventArgs args);
39
public delegate void EngineStateHandler (object o, EngineStateArgs args);
44
/// The GStreamer Playbin.
49
// engine callbacks from the C wrapper
50
delegate void eosCallback (IntPtr engine);
51
delegate void errorCallback (IntPtr engine, string error, string debug);
52
delegate void bufferCallback (IntPtr engine, int prog);
55
errorCallback error_cb;
56
bufferCallback buffer_cb;
61
MediaStatus status = MediaStatus.Unloaded;
63
EngineVideoInfo videoInfo = null;
65
/// <summary>Raised when an event occurs. ie: EndOfStream, Error, etc.</summary>
66
public event EngineEventHandler EventChanged;
68
/// <summary>Raised when the playbin state changes. ie: Playing, Paused, etc.</summary>
69
public event EngineStateHandler StateChanged;
72
/// Load the GStreamer library and attach it
73
/// to the specified window.
75
public bool Initiate (ulong x_window_id)
78
// load the gstreamer library
79
IntPtr ptr = gst_binding_init (x_window_id);
81
if(ptr == IntPtr.Zero)
83
throwError ("Failed to load the Gstreamer library");
86
else engine = new HandleRef (this, ptr);
90
eos_cb = new eosCallback (onEos);
91
error_cb = new errorCallback (onError);
92
buffer_cb = new bufferCallback (onBuffer);
94
gst_binding_set_eos_cb (engine, eos_cb);
95
gst_binding_set_error_cb (engine, error_cb);
96
gst_binding_set_buffer_cb (engine, buffer_cb);
99
status = MediaStatus.Stopped;
105
/// Load the GStreamer library.
107
public bool Initiate ()
117
/// Disposes the GStreamer library.
119
public void Dispose ()
122
gst_binding_deinit (engine);
123
ChangeState (MediaStatus.Unloaded);
127
/// Loads the specified path into the GStreamer library.
129
public bool Load (string uri)
131
if (!isStopped) Stop ();
132
gst_binding_load (engine, uri);
133
//ChangeState (MediaStatus.Loaded);
134
ChangeState (MediaStatus.Paused);
139
/// Plays the loaded media file.
143
if (!isPlaying && !isUnloaded) {
144
gst_binding_play (engine);
145
ChangeState (MediaStatus.Playing);
150
/// Pauses the loaded media file.
155
gst_binding_pause (engine);
156
ChangeState (MediaStatus.Paused);
161
/// Stops the loaded media file and unloads it.
165
if (isPlaying || isPaused) {
166
gst_binding_unload (engine);
168
ChangeState (MediaStatus.Stopped);
174
/// Changes the window to which video playback is attached to.
176
public void SetWindow (ulong window_id)
178
gst_binding_set_xid (engine, window_id);
184
/// Seeks to the nearest millisecond on the media file.
186
public void Seek (TimeSpan time)
188
if (isUnloaded) return;
189
gst_binding_set_position (engine, (ulong) time.TotalMilliseconds);
190
ChangeEvent (MediaEvents.Seek, null, 0);
195
/// Seeks to the nearest millisecond on the media file.
197
public void Seek (double milliseconds)
199
TimeSpan time = TimeSpan.FromMilliseconds (milliseconds);
207
/// Returns the current position that the media file is on.
209
public TimeSpan CurrentPosition
213
if (!isPlaying && !isPaused)
214
return TimeSpan.Zero;
216
double pos = (double) gst_binding_get_position (engine);
217
return TimeSpan.FromMilliseconds (pos);
223
/// Returns the total duration of the media file.
225
public TimeSpan Duration
229
return TimeSpan.Zero;
231
double dur = (double) gst_binding_get_duration (engine);
232
return TimeSpan.FromMilliseconds (dur);
237
/// Returns information on the video stream, or null if it's not available
239
public EngineVideoInfo VideoInfo
245
if (videoInfo == null) {
246
IntPtr ptr = gst_binding_get_video_info (engine);
247
if (ptr == IntPtr.Zero)
250
videoInfo = new EngineVideoInfo();
251
Marshal.PtrToStructure(ptr, videoInfo);
259
/// Returns the current volume of the GStreamer library.
263
get{ return (double) gst_binding_get_volume (engine); }
266
gst_binding_set_volume (engine, (int) value);
267
ChangeEvent (MediaEvents.Volume, null, 0);
274
/// Returns a value determining if the media file is a video file.
278
get{ return !isUnloaded ? gst_binding_has_video (engine) : false; }
282
/// Returns the current status of the media engine.
284
public MediaStatus CurrentStatus
286
get { return status; }
292
// throws an error to the global error handler
293
void throwError (string message)
295
EngineEventArgs args = new EngineEventArgs (MediaEvents.Error, message, 0);
296
if(EventChanged != null) EventChanged(this, args);
300
// the stream has ended
301
void onEos (IntPtr engine)
303
ChangeEvent (MediaEvents.EndOfStream, null, 0);
307
// an error in the gstreamer pipeline has occured
308
void onError (IntPtr engine, string error, string debug)
310
throwError (error + "\n\nDebug Message:\n" + debug);
311
ChangeState (MediaStatus.Stopped);
312
ChangeEvent (MediaEvents.Error, error, 0);
316
// the gstreamer pipeline is being buffered
317
void onBuffer (IntPtr engine, int prog)
320
buffer_fin = prog >= 100;
321
ChangeEvent (MediaEvents.Buffering, "Buffering", (double)prog);
326
// throw the media state changed event
327
void ChangeState(MediaStatus state)
330
EngineStateArgs args = new EngineStateArgs (state);
331
if(StateChanged != null) StateChanged(this, args);
334
// throw the media event changed event
335
void ChangeEvent(MediaEvents engineEvent, string message, double percent)
337
EngineEventArgs args = new EngineEventArgs (engineEvent, message, percent);
338
if(EventChanged != null) EventChanged(this, args);
342
// private convenience properties
343
bool isPlaying { get{ return status == MediaStatus.Playing; } }
344
bool isPaused { get{ return status == MediaStatus.Paused; } }
345
bool isStopped { get{ return status == MediaStatus.Stopped; } }
346
bool isUnloaded { get{ return status == MediaStatus.Unloaded; } }
350
// core engine functions
351
[DllImport("gstreamer_playbin")]
352
static extern IntPtr gst_binding_init (ulong xwin);
353
[DllImport("gstreamer_playbin")]
354
static extern void gst_binding_deinit (HandleRef play);
355
[DllImport("gstreamer_playbin")]
356
static extern void gst_binding_load (HandleRef play, string uri);
357
[DllImport("gstreamer_playbin")]
358
static extern void gst_binding_play (HandleRef play);
359
[DllImport("gstreamer_playbin")]
360
static extern void gst_binding_pause (HandleRef play);
361
[DllImport("gstreamer_playbin")]
362
static extern void gst_binding_unload (HandleRef play);
363
[DllImport("gstreamer_playbin")]
364
static extern void gst_binding_set_xid (HandleRef play, ulong xid);
367
// engine property functions
368
[DllImport("gstreamer_playbin")]
369
static extern ulong gst_binding_get_duration (HandleRef play);
370
[DllImport("gstreamer_playbin")]
371
static extern IntPtr gst_binding_get_video_info (HandleRef play);
372
[DllImport("gstreamer_playbin")]
373
static extern ulong gst_binding_get_position (HandleRef play);
374
[DllImport("gstreamer_playbin")]
375
static extern int gst_binding_get_volume (HandleRef play);
376
[DllImport("gstreamer_playbin")]
377
static extern void gst_binding_set_position (HandleRef play, ulong pos);
378
[DllImport("gstreamer_playbin")]
379
static extern void gst_binding_set_volume (HandleRef play, int vol);
380
[DllImport("gstreamer_playbin")]
381
static extern bool gst_binding_has_video (HandleRef play);
385
[DllImport("gstreamer_playbin")]
386
static extern void gst_binding_set_eos_cb (HandleRef play, eosCallback cb);
387
[DllImport("gstreamer_playbin")]
388
static extern void gst_binding_set_error_cb (HandleRef play, errorCallback cb);
389
[DllImport("gstreamer_playbin")]
390
static extern void gst_binding_set_buffer_cb (HandleRef play, bufferCallback cb);
397
/// Arguments for a raised event.
399
public sealed class EngineEventArgs
401
MediaEvents engine_event;
405
public EngineEventArgs (MediaEvents engine_event, string message, double buffer)
407
this.engine_event = engine_event;
408
this.message = message;
409
this.buffer = buffer;
412
public MediaEvents Event { get{ return engine_event; } }
413
public string Message { get{ return message; } }
414
public double BufferingPercent { get{ return buffer; } }
421
/// Arguments for a raised state.
423
public sealed class EngineStateArgs
427
public EngineStateArgs (MediaStatus state)
432
public MediaStatus State { get{ return state; } }
435
[StructLayout(LayoutKind.Sequential)]
436
public class EngineVideoInfo
442
public int Width { get{ return width; } }
443
public int Height { get{ return height; } }
444
public float AspectRatio { get { return (float)width/height; } }
445
public float FrameRate { get{ return frame_rate; } }
447
public override string ToString () { return "Width=" + width + ", Height=" + height + ", FrameRate=" + frame_rate; }