]> git.saurik.com Git - wxWidgets.git/blame - src/unix/mediactrl.cpp
Rename wxGetFileType to wxGetFileKind
[wxWidgets.git] / src / unix / mediactrl.cpp
CommitLineData
ddc90a8d 1/////////////////////////////////////////////////////////////////////////////
0c5c0375
RN
2// Name: unix/mediactrl.cpp
3// Purpose: Built-in Media Backends for Unix
ddc90a8d
RN
4// Author: Ryan Norton <wxprojects@comcast.net>
5// Modified by:
6// Created: 02/04/05
7// RCS-ID: $Id$
8// Copyright: (c) 2004-2005 Ryan Norton
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12//===========================================================================
13// DECLARATIONS
14//===========================================================================
15
16//---------------------------------------------------------------------------
17// Pre-compiled header stuff
18//---------------------------------------------------------------------------
19
20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21#pragma implementation "mediactrl.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28#pragma hdrstop
29#endif
30
31//---------------------------------------------------------------------------
32// Includes
33//---------------------------------------------------------------------------
34#include "wx/mediactrl.h"
35
36//---------------------------------------------------------------------------
37// Compilation guard
38//---------------------------------------------------------------------------
39#if wxUSE_MEDIACTRL
40
0c5c0375
RN
41//===========================================================================
42// BACKEND DECLARATIONS
43//===========================================================================
44
45//---------------------------------------------------------------------------
46//
47// wxGStreamerMediaBackend
48//
dae87f93
RN
49//TODO:
50//TODO: This is really not the best way to play-stop -
51//TODO: it should just have one playbin and stick with it the whole
52//TODO: instance of wxGStreamerMediaBackend - but stopping appears
53//TODO: to invalidate the playbin object...
54//TODO:
55//
0c5c0375
RN
56//---------------------------------------------------------------------------
57#if wxUSE_GSTREAMER
58
59//---------------------------------------------------------------------------
60// GStreamer Includes
61//---------------------------------------------------------------------------
62#include <gst/gst.h>
63#include <gst/xoverlay/xoverlay.h>
64
65#include <string.h> //strstr
66
67#include "wx/log.h"
1e22656e 68#include "wx/msgdlg.h"
0c5c0375
RN
69
70#ifdef __WXGTK__
71 //for <gdk/gdkx.h>/related for GDK_WINDOW_XWINDOW
1e22656e
RN
72# include "wx/gtk/win_gtk.h"
73# include <gtk/gtksignal.h>
b4a345a6 74//# include <gst/gconf/gconf.h> //gstreamer gnome interface
0c5c0375
RN
75#endif
76
1e22656e 77
0c5c0375
RN
78class WXDLLIMPEXP_MEDIA wxGStreamerMediaBackend : public wxMediaBackend
79{
80public:
81
82 wxGStreamerMediaBackend();
83 ~wxGStreamerMediaBackend();
84
85 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
86 wxWindowID id,
87 const wxPoint& pos,
88 const wxSize& size,
89 long style,
90 const wxValidator& validator,
91 const wxString& name);
92
93 virtual bool Play();
94 virtual bool Pause();
95 virtual bool Stop();
96
97 virtual bool Load(const wxString& fileName);
98 virtual bool Load(const wxURI& location);
99
100 virtual wxMediaState GetState();
101
102 virtual bool SetPosition(wxLongLong where);
103 virtual wxLongLong GetPosition();
104 virtual wxLongLong GetDuration();
105
106 virtual void Move(int x, int y, int w, int h);
107 wxSize GetVideoSize() const;
108
109 virtual double GetPlaybackRate();
110 virtual bool SetPlaybackRate(double dRate);
111
112 void Cleanup();
113
114 static void OnFinish(GstElement *play, gpointer data);
115 static void OnError (GstElement *play, GstElement *src,
116 GError *err, gchar *debug,
117 gpointer data);
1e22656e
RN
118 static void OnVideoCapsReady(GstPad* pad, GParamSpec* pspec, gpointer data);
119
120 static bool TransCapsToVideoSize(wxGStreamerMediaBackend* be, GstPad* caps);
121 void PostRecalcSize();
122
123#ifdef __WXGTK__
124 static gint OnGTKRealize(GtkWidget* theWidget, wxGStreamerMediaBackend* be);
125#endif
0c5c0375
RN
126
127 GstElement* m_player; //GStreamer media element
1e22656e
RN
128
129 wxSize m_videoSize;
130 wxControl* m_ctrl;
131
1e22656e 132 wxLongLong m_nPausedPos;
0c5c0375
RN
133
134 DECLARE_DYNAMIC_CLASS(wxGStreamerMediaBackend);
135};
136
137
138//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
139//
140// wxGStreamerMediaBackend
141//
142//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
143
144IMPLEMENT_DYNAMIC_CLASS(wxGStreamerMediaBackend, wxMediaBackend);
145
dae87f93
RN
146//---------------------------------------------------------------------------
147// wxGStreamerMediaBackend Constructor
148//
149// Sets m_player to NULL signifying we havn't loaded anything yet
150//---------------------------------------------------------------------------
1e22656e 151wxGStreamerMediaBackend::wxGStreamerMediaBackend() : m_player(NULL), m_videoSize(0,0)
0c5c0375
RN
152{
153}
154
dae87f93
RN
155//---------------------------------------------------------------------------
156// wxGStreamerMediaBackend Destructor
157//
158// Stops/cleans up memory
159//---------------------------------------------------------------------------
0c5c0375
RN
160wxGStreamerMediaBackend::~wxGStreamerMediaBackend()
161{
1e22656e
RN
162 Cleanup();
163}
164
dae87f93
RN
165//---------------------------------------------------------------------------
166// wxGStreamerMediaBackend::OnGTKRealize
167//
168// If the window wasn't realized when Load was called, this is the
169// callback for when it is.
170//
171// 1) Installs GTK idle handler if it doesn't exist
172// 2) Yeilds to avoid an X11 bug (?)
173// 3) Tells GStreamer to play the video in our control
174//---------------------------------------------------------------------------
1e22656e
RN
175#ifdef __WXGTK__
176
177#ifdef __WXDEBUG__
178
179#if wxUSE_THREADS
180# define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
181#else
182# define DEBUG_MAIN_THREAD
183#endif
184#else
185#define DEBUG_MAIN_THREAD
186#endif // Debug
187
188extern void wxapp_install_idle_handler();
189extern bool g_isIdle;
190extern bool g_mainThreadLocked;
191
192gint wxGStreamerMediaBackend::OnGTKRealize(GtkWidget* theWidget,
193 wxGStreamerMediaBackend* be)
194{
195 DEBUG_MAIN_THREAD
196
197 if (g_isIdle)
198 wxapp_install_idle_handler();
199
dae87f93 200 wxYield(); //FIXME: X Server gets an error if I don't do this or a messagebox beforehand?!?!??
1e22656e
RN
201
202 GdkWindow *window = GTK_PIZZA(theWidget)->bin_window;
203 wxASSERT(window);
204
b4a345a6
RN
205 GstElement* videosink;
206 g_object_get (G_OBJECT (be->m_player), "video-sink", &videosink, NULL);
207
208 gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(videosink),
209 GDK_WINDOW_XWINDOW( window )
1e22656e
RN
210 );
211
212 return 0;
213}
214
215
216#endif
217
dae87f93
RN
218//---------------------------------------------------------------------------
219// wxGStreamerMediaBackend::Cleanup
220//
221// Frees the gstreamer interfaces if there were any created
dae87f93 222//---------------------------------------------------------------------------
1e22656e
RN
223void wxGStreamerMediaBackend::Cleanup()
224{
225 if(m_player && GST_IS_OBJECT(m_player))
226 {
1e22656e
RN
227 gst_element_set_state (m_player, GST_STATE_NULL);
228 gst_object_unref (GST_OBJECT (m_player));
1e22656e 229 }
0c5c0375
RN
230}
231
dae87f93
RN
232//---------------------------------------------------------------------------
233// wxGStreamerMediaBackend::CreateControl
234//
235// Initializes GStreamer and creates the wx side of our media control
236//---------------------------------------------------------------------------
0c5c0375
RN
237bool wxGStreamerMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
238 wxWindowID id,
239 const wxPoint& pos,
240 const wxSize& size,
241 long style,
242 const wxValidator& validator,
243 const wxString& name)
244{
245 //init gstreamer
246 gst_init(NULL, NULL);
1e22656e
RN
247
248 m_ctrl = ctrl;
0c5c0375 249
1e22656e 250 return m_ctrl->wxControl::Create(parent, id, pos, size,
0c5c0375 251 style, //remove borders???
1e22656e
RN
252 validator, name);
253}
0c5c0375 254
dae87f93
RN
255//---------------------------------------------------------------------------
256// wxGStreamerMediaBackend::TransCapsToVideoSize
257//
258// Gets the size of our video (in wxSize) from a GstPad
259//---------------------------------------------------------------------------
1e22656e
RN
260bool wxGStreamerMediaBackend::TransCapsToVideoSize(wxGStreamerMediaBackend* be, GstPad* pad)
261{
262 const GstCaps* caps = GST_PAD_CAPS (pad);
263 if(caps)
264 {
0c5c0375 265
1e22656e
RN
266 const GstStructure *s;
267 s = gst_caps_get_structure (caps, 0);
268 wxASSERT(s);
0c5c0375 269
1e22656e
RN
270 gst_structure_get_int (s, "width", &be->m_videoSize.x);
271 gst_structure_get_int (s, "height", &be->m_videoSize.y);
0c5c0375 272
1e22656e
RN
273 const GValue *par;
274 par = gst_structure_get_value (s, "pixel-aspect-ratio");
0c5c0375 275
1e22656e
RN
276 if (par)
277 {
278 int num = gst_value_get_fraction_numerator (par),
279 den = gst_value_get_fraction_denominator (par);
280
281 //TODO: maybe better fraction normalization...
282 if (num > den)
283 be->m_videoSize.x = (int) ((float) num * be->m_videoSize.x / den);
284 else
285 be->m_videoSize.y = (int) ((float) den * be->m_videoSize.y / num);
286 }
287
288 be->PostRecalcSize();
289 return true;
290 }//end if caps
291
292 return false;
293}
294
dae87f93
RN
295//---------------------------------------------------------------------------
296// wxGStreamerMediaBackend::PostRecalcSize
297//
298// Forces parent to recalc its layout if it has sizers to update
299// to the new video size
300//---------------------------------------------------------------------------
1e22656e
RN
301void wxGStreamerMediaBackend::PostRecalcSize()
302{
303 m_ctrl->InvalidateBestSize();
304 m_ctrl->GetParent()->Layout();
305 m_ctrl->GetParent()->Refresh();
306 m_ctrl->GetParent()->Update();
0c5c0375
RN
307}
308
dae87f93
RN
309//---------------------------------------------------------------------------
310// wxGStreamerMediaBackend::OnFinish
311//
312// Called by gstreamer when the media is done playing
313//
314// 1) Send a wxEVT_MEDIA_STOP to the control
315// 2) If veteod, break out
316// 3) really stop the media
317// 4) Send a wxEVT_MEDIA_FINISHED to the control
318//---------------------------------------------------------------------------
0c5c0375
RN
319void wxGStreamerMediaBackend::OnFinish(GstElement *play, gpointer data)
320{
321 wxGStreamerMediaBackend* m_parent = (wxGStreamerMediaBackend*) data;
322
323 wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
324 m_parent->m_ctrl->GetId());
325 m_parent->m_ctrl->ProcessEvent(theEvent);
326
327 if(theEvent.IsAllowed())
328 {
329 bool bOk = m_parent->Stop();
330 wxASSERT(bOk);
331
332 //send the event to our child
333 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
334 m_parent->m_ctrl->GetId());
335 m_parent->m_ctrl->ProcessEvent(theEvent);
336 }
337}
338
dae87f93
RN
339//---------------------------------------------------------------------------
340// wxGStreamerMediaBackend::OnError
341//
342// Called by gstreamer when an error is encountered playing the media
343//
344// TODO: Make this better - maybe some more intelligent wxLog stuff
345//---------------------------------------------------------------------------
0c5c0375
RN
346void wxGStreamerMediaBackend::OnError(GstElement *play,
347 GstElement *src,
348 GError *err,
349 gchar *debug,
350 gpointer data)
351{
1e22656e 352 wxMessageBox(wxString::Format(wxT("Error in wxMediaCtrl!\nError Message:%s"), wxString(err->message, wxConvLocal).c_str()));
0c5c0375
RN
353}
354
355
dae87f93
RN
356//---------------------------------------------------------------------------
357// wxGStreamerMediaBackend::Load (File version)
358//
359// Just calls the URI version
360//---------------------------------------------------------------------------
0c5c0375
RN
361bool wxGStreamerMediaBackend::Load(const wxString& fileName)
362{
1e22656e
RN
363 return Load(
364 wxURI(
365 wxString( wxT("file://") ) + fileName
366 )
0c5c0375
RN
367 );
368}
369
dae87f93
RN
370//---------------------------------------------------------------------------
371// wxGStreamerMediaBackend::OnVideoCapsReady
372//
373// Called by gstreamer when the video caps for the media is ready
374//---------------------------------------------------------------------------
1e22656e
RN
375void wxGStreamerMediaBackend::OnVideoCapsReady(GstPad* pad, GParamSpec* pspec, gpointer data)
376{
377 wxGStreamerMediaBackend::TransCapsToVideoSize((wxGStreamerMediaBackend*) data, pad);
378}
379
dae87f93
RN
380//---------------------------------------------------------------------------
381// wxGStreamerMediaBackend::Load (URI version)
382//
383// 1) Stops/Cleanups the previous instance if there is any
384// 2) Creates the gstreamer interfaces - playbin and xvimagesink for video
b4a345a6
RN
385// 3) If there is no playbin bail out
386// 4) Set up the error and end-of-stream callbacks for our player
387// 5) Make sure our video sink can support the x overlay interface
388// 6) Make sure the passed URI is valid and tell playbin to load it
389// 7) Use the xoverlay extension to tell gstreamer to play in our window
390// 8) Get the video size - pause required to set the stream in action
dae87f93 391//---------------------------------------------------------------------------
0c5c0375
RN
392bool wxGStreamerMediaBackend::Load(const wxURI& location)
393{
dae87f93 394 //1
0c5c0375 395 Cleanup();
1e22656e 396
dae87f93 397 //2
1e22656e 398 m_player = gst_element_factory_make ("playbin", "play");
1e22656e 399
dae87f93 400 //3
b4a345a6 401 if (!m_player)
1e22656e
RN
402 return false;
403
b4a345a6 404 //4
1e22656e
RN
405 g_signal_connect (m_player, "eos", G_CALLBACK (OnError), this);
406 g_signal_connect (m_player, "error", G_CALLBACK (OnFinish), this);
0c5c0375 407
b4a345a6
RN
408 //5
409//#ifdef __WXGTK__
410 //use gnome-specific gstreamer extensions
411// GstElement* videosink = gst_gconf_get_default_video_sink();
412//#else
413 GstElement* videosink = gst_element_factory_make ("xvimagesink", "videosink");
414 if ( !GST_IS_OBJECT(videosink) )
415 videosink = gst_element_factory_make ("ximagesink", "videosink");
416//#endif
417 wxASSERT( GST_IS_X_OVERLAY(videosink) );
418 if ( ! GST_IS_X_OVERLAY(videosink) )
1e22656e 419 return false;
b4a345a6
RN
420
421 g_object_set (G_OBJECT (m_player),
422 "video-sink", videosink,
423// "audio-sink", m_audiosink,
424 NULL);
425 //6
1e22656e
RN
426 wxString locstring = location.BuildUnescapedURI();
427 wxASSERT(gst_uri_protocol_is_valid("file"));
428 wxASSERT(gst_uri_is_valid(locstring.mb_str()));
0c5c0375 429
1e22656e 430 g_object_set (G_OBJECT (m_player), "uri", (const char*)locstring.mb_str(), NULL);
dae87f93 431
b4a345a6 432 //7
1e22656e
RN
433#ifdef __WXGTK__
434 if(!GTK_WIDGET_REALIZED(m_ctrl->m_wxwindow))
435 {
436 //Not realized yet - set to connect at realization time
437 gtk_signal_connect( GTK_OBJECT(m_ctrl->m_wxwindow),
438 "realize",
439 GTK_SIGNAL_FUNC(wxGStreamerMediaBackend::OnGTKRealize),
440 (gpointer) this );
441 }
442 else
443 {
444 wxYield(); //see realize callback...
445 GdkWindow *window = GTK_PIZZA(m_ctrl->m_wxwindow)->bin_window;
446 wxASSERT(window);
447#endif
0c5c0375 448
1e22656e 449
b4a345a6 450 gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(videosink),
1e22656e
RN
451#ifdef __WXGTK__
452 GDK_WINDOW_XWINDOW( window )
453#else
454 ctrl->GetHandle()
455#endif
456 );
457
458#ifdef __WXGTK__
459 } //end else block
460#endif
dae87f93 461
b4a345a6 462 //8
1e22656e
RN
463 wxASSERT(gst_element_set_state (m_player,
464 GST_STATE_PAUSED) == GST_STATE_SUCCESS);
465
466 const GList *list = NULL;
467 g_object_get (G_OBJECT (m_player), "stream-info", &list, NULL);
468
469 for ( ; list != NULL; list = list->next)
470 {
471 GObject *info = (GObject *) list->data;
472 gint type;
473 GParamSpec *pspec;
474 GEnumValue *val;
475 GstPad *pad = NULL;
476
477 g_object_get (info, "type", &type, NULL);
478 pspec = g_object_class_find_property (
479 G_OBJECT_GET_CLASS (info), "type");
480 val = g_enum_get_value (G_PARAM_SPEC_ENUM (pspec)->enum_class, type);
481
482 if (strstr (val->value_name, "VIDEO"))
483 {
484 //Newer gstreamer 0.8+ is SUPPOSED to have "object"...
485 //but a lot of old plugins still use "pad" :)
486 pspec = g_object_class_find_property (
487 G_OBJECT_GET_CLASS (info), "object");
488
489 if (!pspec)
490 g_object_get (info, "pad", &pad, NULL);
491 else
492 g_object_get (info, "object", &pad, NULL);
493
494 pad = (GstPad *) GST_PAD_REALIZE (pad);
495 wxASSERT(pad);
496
497 if(!wxGStreamerMediaBackend::TransCapsToVideoSize(this, pad));
498 {
499 //wait for those caps to get ready
500 g_signal_connect(
501 pad,
502 "notify::caps",
503 G_CALLBACK(wxGStreamerMediaBackend::OnVideoCapsReady),
504 this);
505 }
506 }//end if video
507 else
508 {
509 m_videoSize = wxSize(0,0);
510 PostRecalcSize();
511 }
512 }//end searching through info list
513
514 m_nPausedPos = 0;
515 return true;
0c5c0375
RN
516}
517
dae87f93
RN
518//---------------------------------------------------------------------------
519// wxGStreamerMediaBackend::Play
520//
521// Sets the stream to a playing state
522//---------------------------------------------------------------------------
0c5c0375
RN
523bool wxGStreamerMediaBackend::Play()
524{
525 if (gst_element_set_state (m_player, GST_STATE_PLAYING)
526 != GST_STATE_SUCCESS)
527 return false;
528 return true;
529}
530
dae87f93
RN
531//---------------------------------------------------------------------------
532// wxGStreamerMediaBackend::Pause
533//
534// Marks where we paused and pauses the stream
535//---------------------------------------------------------------------------
0c5c0375
RN
536bool wxGStreamerMediaBackend::Pause()
537{
1e22656e 538 m_nPausedPos = GetPosition();
0c5c0375
RN
539 if (gst_element_set_state (m_player, GST_STATE_PAUSED)
540 != GST_STATE_SUCCESS)
541 return false;
542 return true;
543}
544
dae87f93
RN
545//---------------------------------------------------------------------------
546// wxGStreamerMediaBackend::Stop
547//
548// Pauses the stream and sets the position to 0
549//---------------------------------------------------------------------------
0c5c0375
RN
550bool wxGStreamerMediaBackend::Stop()
551{
552 if (gst_element_set_state (m_player,
1e22656e 553 GST_STATE_PAUSED) != GST_STATE_SUCCESS)
0c5c0375 554 return false;
1e22656e 555 return wxGStreamerMediaBackend::SetPosition(0);
0c5c0375
RN
556}
557
dae87f93
RN
558//---------------------------------------------------------------------------
559// wxGStreamerMediaBackend::GetState
560//
561// Gets the state of the stream
562//---------------------------------------------------------------------------
0c5c0375
RN
563wxMediaState wxGStreamerMediaBackend::GetState()
564{
565 switch(GST_STATE(m_player))
566 {
567 case GST_STATE_PLAYING:
568 return wxMEDIASTATE_PLAYING;
569 case GST_STATE_PAUSED:
1e22656e
RN
570 if (m_nPausedPos == 0)
571 return wxMEDIASTATE_STOPPED;
572 else
573 return wxMEDIASTATE_PAUSED;
0c5c0375
RN
574 default://case GST_STATE_READY:
575 return wxMEDIASTATE_STOPPED;
576 }
577}
578
dae87f93
RN
579//---------------------------------------------------------------------------
580// wxGStreamerMediaBackend::GetPosition
581//
582// If paused, returns our marked position - otherwise it queries the
583// GStreamer playbin for the position and returns that
584//
585//TODO:
586//TODO: In lue of the last big TODO, when you pause and seek gstreamer
587//TODO: doesn't update the position sometimes, so we need to keep track of whether
588//TODO: we have paused or not and keep track of the time after the pause
589//TODO: and whenever the user seeks while paused
590//TODO:
591//---------------------------------------------------------------------------
0c5c0375
RN
592wxLongLong wxGStreamerMediaBackend::GetPosition()
593{
1e22656e
RN
594 if(GetState() != wxMEDIASTATE_PLAYING)
595 return m_nPausedPos;
596 else
597 {
598 gint64 pos;
599 GstFormat fmtTime = GST_FORMAT_TIME;
600
601 if (!gst_element_query (m_player, GST_QUERY_POSITION, &fmtTime, &pos))
602 return 0;
603 return pos / GST_MSECOND ;
604 }
0c5c0375
RN
605}
606
dae87f93
RN
607//---------------------------------------------------------------------------
608// wxGStreamerMediaBackend::SetPosition
609//
610// Sets the position of the stream
611// Note that GST_MSECOND is 1000000 (GStreamer uses nanoseconds - so
612// there is 1000000 nanoseconds in a millisecond)
613//
614// If paused marks where we seeked to
615//---------------------------------------------------------------------------
616bool wxGStreamerMediaBackend::SetPosition(wxLongLong where)
617{
618 if( gst_element_seek (m_player, (GstSeekType) (GST_SEEK_METHOD_SET |
619 GST_FORMAT_TIME | GST_SEEK_FLAG_FLUSH),
620 where.GetValue() * GST_MSECOND ) )
621 {
622 if (GetState() != wxMEDIASTATE_PLAYING)
623 m_nPausedPos = where;
624
625 return true;
626 }
627
628 return false;
629}
630
631//---------------------------------------------------------------------------
632// wxGStreamerMediaBackend::GetDuration
633//
634// Obtains the total time of our stream
635//---------------------------------------------------------------------------
0c5c0375
RN
636wxLongLong wxGStreamerMediaBackend::GetDuration()
637{
638 gint64 length;
639 GstFormat fmtTime = GST_FORMAT_TIME;
640
641 if(!gst_element_query(m_player, GST_QUERY_TOTAL, &fmtTime, &length))
642 return 0;
643 return length / GST_MSECOND ;
644}
645
dae87f93
RN
646//---------------------------------------------------------------------------
647// wxGStreamerMediaBackend::Move
648//
649// Called when the window is moved - GStreamer takes care of this
650// for us so nothing is needed
651//---------------------------------------------------------------------------
0c5c0375
RN
652void wxGStreamerMediaBackend::Move(int x, int y, int w, int h)
653{
654}
655
dae87f93
RN
656//---------------------------------------------------------------------------
657// wxGStreamerMediaBackend::GetVideoSize
658//
659// Returns our cached video size from Load/OnVideoCapsReady
660//---------------------------------------------------------------------------
0c5c0375 661wxSize wxGStreamerMediaBackend::GetVideoSize() const
1e22656e
RN
662{
663 return m_videoSize;
0c5c0375
RN
664}
665
dae87f93
RN
666//---------------------------------------------------------------------------
667// wxGStreamerMediaBackend::GetPlaybackRate
668// wxGStreamerMediaBackend::SetPlaybackRate
1e22656e 669//
dae87f93 670// Obtains/Sets the playback rate of the stream
1e22656e 671//
dae87f93
RN
672//TODO: PlaybackRate not currently supported via playbin directly -
673//TODO: Ronald S. Bultje noted on gstreamer-devel:
674//TODO:
675//TODO: Like "play at twice normal speed"? Or "play at 25 fps and 44,1 kHz"? As
676//TODO: for the first, yes, we have elements for that, btu they"re not part of
677//TODO: playbin. You can create a bin (with a ghost pad) containing the actual
678//TODO: video/audiosink and the speed-changing element for this, and set that
679//TODO: element as video-sink or audio-sink property in playbin. The
680//TODO: audio-element is called "speed", the video-element is called "videodrop"
681//TODO: (although that appears to be deprecated in favour of "videorate", which
682//TODO: again cannot do this, so this may not work at all in the end). For
683//TODO: forcing frame/samplerates, see audioscale and videorate. Audioscale is
684//TODO: part of playbin.
685//---------------------------------------------------------------------------
0c5c0375
RN
686double wxGStreamerMediaBackend::GetPlaybackRate()
687{
1e22656e
RN
688 //not currently supported via playbin
689 return 1.0;
0c5c0375
RN
690}
691
692bool wxGStreamerMediaBackend::SetPlaybackRate(double dRate)
693{
1e22656e
RN
694 //not currently supported via playbin
695 return false;
0c5c0375
RN
696}
697
698#endif //wxUSE_GSTREAMER
699
ddc90a8d
RN
700//in source file that contains stuff you don't directly use
701#include <wx/html/forcelnk.h>
702FORCE_LINK_ME(basewxmediabackends);
703
704#endif //wxUSE_MEDIACTRL
705
706
707
708
709