1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
31 #include <cppuhelper/supportsservice.hxx>
33 #include <rtl/string.hxx>
34 #include <salhelper/thread.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/syschild.hxx>
37 #include <vcl/sysdata.hxx>
39 #include "gstplayer.hxx"
40 #include "gstframegrabber.hxx"
41 #include "gstwindow.hxx"
43 #ifdef AVMEDIA_GST_0_10
44 # define AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_GStreamer_0_10"
45 # define AVMEDIA_GST_PLAYER_SERVICENAME "com.sun.star.media.Player_GStreamer_0_10"
47 # include <gst/video/videooverlay.h>
48 # define AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_GStreamer"
49 # define AVMEDIA_GST_PLAYER_SERVICENAME "com.sun.star.media.Player_GStreamer"
52 #include <gst/pbutils/missing-plugins.h>
53 #include <gst/pbutils/pbutils.h>
56 # if OSL_DEBUG_LEVEL > 2
57 #ifdef AVMEDIA_GST_0_10
58 # define AVVERSION "gst 0.10: "
60 # define AVVERSION "gst 1.0: "
62 #define DBG(...) do { fprintf (stderr, "%s", AVVERSION); fprintf (stderr, __VA_ARGS__); fprintf (stderr, "\n"); } while (0);
68 using namespace ::com::sun::star
;
70 namespace avmedia
{ namespace gstreamer
{
76 explicit FlagGuard(bool & flag
): flag_(flag
) { flag_
= true; }
78 ~FlagGuard() { flag_
= false; }
84 class MissingPluginInstallerThread
: public salhelper::Thread
{
86 MissingPluginInstallerThread(): Thread("MissingPluginInstaller") {}
89 void execute() SAL_OVERRIDE
;
92 class MissingPluginInstaller
{
93 friend class MissingPluginInstallerThread
;
96 MissingPluginInstaller(): launchNewThread_(true), inCleanUp_(false) {}
98 ~MissingPluginInstaller();
100 void report(rtl::Reference
<Player
> const & source
, GstMessage
* message
);
102 // Player::~Player calls Player::disposing calls
103 // MissingPluginInstaller::detach, so do not take Player by rtl::Reference
104 // here (which would bump its refcount back from 0 to 1):
105 void detach(Player
const * source
);
111 MissingPluginInstaller
, launchUi
, MissingPluginInstallerThread
*);
114 std::set
<OString
> reported_
;
115 std::map
<OString
, std::set
<rtl::Reference
<Player
>>> queued_
;
116 rtl::Reference
<MissingPluginInstallerThread
> currentThread_
;
117 std::vector
<OString
> currentDetails_
;
118 std::set
<rtl::Reference
<Player
>> currentSources_
;
119 bool launchNewThread_
;
123 MissingPluginInstaller::~MissingPluginInstaller() {
124 osl::MutexGuard
g(mutex_
);
125 SAL_WARN_IF(currentThread_
.is(), "avmedia.gstreamer", "unjoined thread");
129 void MissingPluginInstaller::report(
130 rtl::Reference
<Player
> const & source
, GstMessage
* message
)
132 // assert(gst_is_missing_plugin_message(message));
133 gchar
* det
= gst_missing_plugin_message_get_installer_detail(message
);
134 if (det
== nullptr) {
137 "gst_missing_plugin_message_get_installer_detail failed");
140 std::size_t len
= std::strlen(det
);
141 if (len
> sal_uInt32(SAL_MAX_INT32
)) {
142 SAL_WARN("avmedia.gstreamer", "detail string too long");
146 OString
detStr(det
, len
);
148 rtl::Reference
<MissingPluginInstallerThread
> join
;
149 rtl::Reference
<MissingPluginInstallerThread
> launch
;
151 osl::MutexGuard
g(mutex_
);
152 if (reported_
.find(detStr
) != reported_
.end()) {
155 auto & i
= queued_
[detStr
];
156 bool fresh
= i
.empty();
158 if (!(fresh
&& launchNewThread_
)) {
161 join
= currentThread_
;
162 currentThread_
= new MissingPluginInstallerThread
;
164 FlagGuard
f(inCleanUp_
);
165 currentSources_
.clear();
168 launchNewThread_
= false;
169 launch
= currentThread_
;
175 Application::PostUserEvent(
176 LINK(this, MissingPluginInstaller
, launchUi
), launch
.get());
179 void eraseSource(std::set
<rtl::Reference
<Player
>> & set
, Player
const * source
)
181 auto i
= std::find_if(
182 set
.begin(), set
.end(),
183 [source
](rtl::Reference
<Player
> const & el
) {
184 return el
.get() == source
;
186 if (i
!= set
.end()) {
191 void MissingPluginInstaller::detach(Player
const * source
) {
192 rtl::Reference
<MissingPluginInstallerThread
> join
;
194 osl::MutexGuard
g(mutex_
);
196 // Guard against ~MissingPluginInstaller with erroneously un-joined
197 // currentThread_ (thus non-empty currentSources_) calling
198 // destructor of currentSources_, calling ~Player, calling here,
199 // which would use currentSources_ while it is already being
203 for (auto i
= queued_
.begin(); i
!= queued_
.end();) {
204 eraseSource(i
->second
, source
);
205 if (i
->second
.empty()) {
206 i
= queued_
.erase(i
);
211 if (currentThread_
.is()) {
212 assert(!currentSources_
.empty());
213 eraseSource(currentSources_
, source
);
214 if (currentSources_
.empty()) {
215 join
= currentThread_
;
216 currentThread_
.clear();
217 launchNewThread_
= true;
222 // missing cancelability of gst_install_plugins_sync
227 void MissingPluginInstaller::processQueue() {
228 assert(!queued_
.empty());
229 assert(currentDetails_
.empty());
230 for (auto i
= queued_
.begin(); i
!= queued_
.end(); ++i
) {
231 reported_
.insert(i
->first
);
232 currentDetails_
.push_back(i
->first
);
233 currentSources_
.insert(i
->second
.begin(), i
->second
.end());
239 MissingPluginInstaller
, launchUi
, MissingPluginInstallerThread
*, thread
)
241 rtl::Reference
<MissingPluginInstallerThread
> ref(thread
, SAL_NO_ACQUIRE
);
243 // not thread safe; hopefully fine to consistently call from our event
244 // loop (which is the only reason to have this
245 // Application::PostUserEvent diversion, in case
246 // MissingPluginInstaller::report might be called from outside our event
247 // loop), and hopefully fine to call gst_is_missing_plugin_message and
248 // gst_missing_plugin_message_get_installer_detail before calling
254 struct TheMissingPluginInstaller
:
255 public rtl::Static
<MissingPluginInstaller
, TheMissingPluginInstaller
>
258 void MissingPluginInstallerThread::execute() {
259 MissingPluginInstaller
& inst
= TheMissingPluginInstaller::get();
261 std::vector
<OString
> details
;
263 osl::MutexGuard
g(inst
.mutex_
);
264 assert(!inst
.currentDetails_
.empty());
265 details
.swap(inst
.currentDetails_
);
267 std::vector
<char *> args
;
268 for (auto const & i
: details
) {
269 args
.push_back(const_cast<char *>(i
.getStr()));
271 args
.push_back(nullptr);
272 gst_install_plugins_sync(args
.data(), nullptr);
274 osl::MutexGuard
g(inst
.mutex_
);
275 if (inst
.queued_
.empty() || inst
.launchNewThread_
) {
276 inst
.launchNewThread_
= true;
289 Player::Player( const uno::Reference
< lang::XMultiServiceFactory
>& rxMgr
) :
290 GstPlayer_BASE( m_aMutex
),
293 mbFakeVideo (false ),
294 mnUnmutedVolume( 0 ),
295 mbPlayPending ( false ),
298 mbInitialized( false ),
307 // Initialize GStreamer library
309 char name
[] = "libreoffice";
310 char *arguments
[] = { name
};
311 char** argv
= arguments
;
312 GError
* pError
= NULL
;
314 mbInitialized
= gst_init_check( &argc
, &argv
, &pError
);
316 DBG( "%p Player::Player", this );
320 // TODO: throw an exception?
321 DBG( "%p Player::Player error '%s'", this, pError
->message
);
322 g_error_free (pError
);
330 DBG( "%p Player::~Player", this );
335 void SAL_CALL
Player::disposing()
337 TheMissingPluginInstaller::get().detach(this);
339 ::osl::MutexGuard
aGuard(m_aMutex
);
343 DBG( "%p Player::disposing", this );
345 // Release the elements and pipeline
350 gst_element_set_state( mpPlaybin
, GST_STATE_NULL
);
351 g_object_unref( G_OBJECT( mpPlaybin
) );
357 g_object_unref( G_OBJECT ( mpXOverlay
) );
364 g_source_remove(mnWatchID
);
369 static gboolean
pipeline_bus_callback( GstBus
*, GstMessage
*message
, gpointer data
)
371 Player
* pPlayer
= static_cast<Player
*>(data
);
373 pPlayer
->processMessage( message
);
378 static GstBusSyncReply
pipeline_bus_sync_handler( GstBus
*, GstMessage
* message
, gpointer data
)
380 Player
* pPlayer
= static_cast<Player
*>(data
);
382 return pPlayer
->processSyncMessage( message
);
385 void Player::processMessage( GstMessage
*message
)
387 switch( GST_MESSAGE_TYPE( message
) ) {
388 case GST_MESSAGE_EOS
:
389 gst_element_set_state( mpPlaybin
, GST_STATE_READY
);
390 mbPlayPending
= false;
394 case GST_MESSAGE_STATE_CHANGED
:
395 if( message
->src
== GST_OBJECT( mpPlaybin
) ) {
396 GstState newstate
, pendingstate
;
398 gst_message_parse_state_changed (message
, NULL
, &newstate
, &pendingstate
);
400 if( newstate
== GST_STATE_PAUSED
&&
401 pendingstate
== GST_STATE_VOID_PENDING
&&
403 gst_video_overlay_expose( mpXOverlay
);
406 mbPlayPending
= ((newstate
== GST_STATE_READY
) || (newstate
== GST_STATE_PAUSED
));
413 static gboolean
wrap_element_query_position (GstElement
*element
, GstFormat format
, gint64
*cur
)
415 #ifdef AVMEDIA_GST_0_10
416 GstFormat my_format
= format
;
417 return gst_element_query_position( element
, &my_format
, cur
) && my_format
== format
&& *cur
> 0L;
419 return gst_element_query_position( element
, format
, cur
);
423 static gboolean
wrap_element_query_duration (GstElement
*element
, GstFormat format
, gint64
*duration
)
425 #ifdef AVMEDIA_GST_0_10
426 GstFormat my_format
= format
;
427 return gst_element_query_duration( element
, &my_format
, duration
) && my_format
== format
&& *duration
> 0L;
429 return gst_element_query_duration( element
, format
, duration
);
433 GstBusSyncReply
Player::processSyncMessage( GstMessage
*message
)
435 // DBG( "%p processSyncMessage has handle: %s", this, GST_MESSAGE_TYPE_NAME( message ) );
437 #if OSL_DEBUG_LEVEL > 0
438 if ( GST_MESSAGE_TYPE( message
) == GST_MESSAGE_ERROR
)
443 gst_message_parse_error( message
, &error
, &error_debug
);
446 "gstreamer error: '" << error
->message
<< "' debug: '"
447 << error_debug
<< "'");
451 #ifdef AVMEDIA_GST_0_10
452 if (message
->structure
&&
453 !strcmp( gst_structure_get_name( message
->structure
), "prepare-xwindow-id" ) )
455 if (gst_is_video_overlay_prepare_window_handle_message (message
) )
458 DBG( "%p processSyncMessage prepare window id: %s %d", this,
459 GST_MESSAGE_TYPE_NAME( message
), (int)mnWindowID
);
461 g_object_unref( G_OBJECT ( mpXOverlay
) );
462 g_object_set( GST_MESSAGE_SRC( message
), "force-aspect-ratio", FALSE
, NULL
);
463 mpXOverlay
= GST_VIDEO_OVERLAY( GST_MESSAGE_SRC( message
) );
464 g_object_ref( G_OBJECT ( mpXOverlay
) );
465 if ( mnWindowID
!= 0 )
466 gst_video_overlay_set_window_handle( mpXOverlay
, mnWindowID
);
470 #ifdef AVMEDIA_GST_0_10
471 if( GST_MESSAGE_TYPE( message
) == GST_MESSAGE_STATE_CHANGED
) {
472 if( message
->src
== GST_OBJECT( mpPlaybin
) ) {
473 GstState newstate
, pendingstate
;
475 gst_message_parse_state_changed (message
, NULL
, &newstate
, &pendingstate
);
477 DBG( "%p state change received, new state %d pending %d", this,
478 (int)newstate
, (int)pendingstate
);
479 if( newstate
== GST_STATE_PAUSED
&&
480 pendingstate
== GST_STATE_VOID_PENDING
) {
482 DBG( "%p change to paused received", this );
484 if( mnDuration
== 0) {
485 gint64 gst_duration
= 0L;
486 if( wrap_element_query_duration( mpPlaybin
, GST_FORMAT_TIME
, &gst_duration
) )
487 mnDuration
= gst_duration
;
491 GList
*pStreamInfo
= NULL
;
493 g_object_get( G_OBJECT( mpPlaybin
), "stream-info", &pStreamInfo
, NULL
);
495 for ( ; pStreamInfo
!= NULL
; pStreamInfo
= pStreamInfo
->next
) {
496 GObject
*pInfo
= G_OBJECT( pStreamInfo
->data
);
502 g_object_get( pInfo
, "type", &nType
, NULL
);
503 GEnumValue
*pValue
= g_enum_get_value( G_PARAM_SPEC_ENUM( g_object_class_find_property( G_OBJECT_GET_CLASS( pInfo
), "type" ) )->enum_class
,
506 if( !g_ascii_strcasecmp( pValue
->value_nick
, "video" ) ) {
507 GstStructure
*pStructure
;
510 g_object_get( pInfo
, "object", &pPad
, NULL
);
511 pStructure
= gst_caps_get_structure( GST_PAD_CAPS( pPad
), 0 );
513 gst_structure_get_int( pStructure
, "width", &mnWidth
);
514 gst_structure_get_int( pStructure
, "height", &mnHeight
);
515 DBG( "queried size: %d x %d", mnWidth
, mnHeight
);
517 g_object_unref (pPad
);
521 maSizeCondition
.set();
526 // We get to use the exciting new playbin2 ! (now known as playbin)
527 if( GST_MESSAGE_TYPE( message
) == GST_MESSAGE_ASYNC_DONE
) {
528 if( mnDuration
== 0) {
529 gint64 gst_duration
= 0L;
530 if( wrap_element_query_duration( mpPlaybin
, GST_FORMAT_TIME
, &gst_duration
) )
531 mnDuration
= gst_duration
;
536 g_signal_emit_by_name( mpPlaybin
, "get-video-pad", 0, &pad
);
541 GstCaps
*caps
= gst_pad_get_current_caps( pad
);
543 if( gst_structure_get( gst_caps_get_structure( caps
, 0 ),
544 "width", G_TYPE_INT
, &w
,
545 "height", G_TYPE_INT
, &h
,
550 DBG( "queried size: %d x %d", mnWidth
, mnHeight
);
552 maSizeCondition
.set();
554 gst_caps_unref( caps
);
555 g_object_unref( pad
);
559 } else if (gst_is_missing_plugin_message(message
)) {
560 TheMissingPluginInstaller::get().report(this, message
);
562 // an error occurred, set condition so that OOo thread doesn't wait for us
563 maSizeCondition
.set();
565 } else if( GST_MESSAGE_TYPE( message
) == GST_MESSAGE_ERROR
) {
568 // an error occurred, set condition so that OOo thread doesn't wait for us
569 maSizeCondition
.set();
576 void Player::preparePlaybin( const OUString
& rURL
, GstElement
*pSink
)
580 if( mpPlaybin
!= NULL
) {
581 gst_element_set_state( mpPlaybin
, GST_STATE_NULL
);
582 mbPlayPending
= false;
583 g_object_unref( mpPlaybin
);
586 mpPlaybin
= gst_element_factory_make( "playbin", NULL
);
587 if( pSink
!= NULL
) // used for getting preferred size etc.
589 g_object_set( G_OBJECT( mpPlaybin
), "video-sink", pSink
, NULL
);
595 OString ascURL
= OUStringToOString( rURL
, RTL_TEXTENCODING_UTF8
);
596 g_object_set( G_OBJECT( mpPlaybin
), "uri", ascURL
.getStr() , NULL
);
598 pBus
= gst_element_get_bus( mpPlaybin
);
601 g_source_remove(mnWatchID
);
604 mnWatchID
= gst_bus_add_watch( pBus
, pipeline_bus_callback
, this );
606 DBG( "%p set sync handler", this );
607 #ifdef AVMEDIA_GST_0_10
608 gst_bus_set_sync_handler( pBus
, pipeline_bus_sync_handler
, this );
610 gst_bus_set_sync_handler( pBus
, pipeline_bus_sync_handler
, this, NULL
);
612 g_object_unref( pBus
);
615 bool Player::create( const OUString
& rURL
)
619 // create all the elements and link them
621 DBG("create player, URL: %s", OUStringToOString( rURL
, RTL_TEXTENCODING_UTF8
).getStr());
623 if( mbInitialized
&& !rURL
.isEmpty() )
625 // fakesink for pre-roll & sizing ...
626 preparePlaybin( rURL
, gst_element_factory_make( "fakesink", NULL
) );
628 gst_element_set_state( mpPlaybin
, GST_STATE_PAUSED
);
629 mbPlayPending
= false;
644 void SAL_CALL
Player::start()
645 throw (uno::RuntimeException
, std::exception
)
647 ::osl::MutexGuard
aGuard(m_aMutex
);
649 // set the pipeline state to READY and run the loop
650 if( mbInitialized
&& NULL
!= mpPlaybin
)
652 gst_element_set_state( mpPlaybin
, GST_STATE_PLAYING
);
653 mbPlayPending
= true;
659 void SAL_CALL
Player::stop()
660 throw (uno::RuntimeException
, std::exception
)
662 ::osl::MutexGuard
aGuard(m_aMutex
);
664 // set the pipeline in PAUSED STATE
666 gst_element_set_state( mpPlaybin
, GST_STATE_PAUSED
);
668 mbPlayPending
= false;
669 DBG( "stop %p", mpPlaybin
);
674 sal_Bool SAL_CALL
Player::isPlaying()
675 throw (uno::RuntimeException
, std::exception
)
677 ::osl::MutexGuard
aGuard(m_aMutex
);
679 bool bRet
= mbPlayPending
;
681 // return whether the pipeline is in PLAYING STATE or not
682 if( !mbPlayPending
&& mbInitialized
&& mpPlaybin
)
684 bRet
= GST_STATE_PLAYING
== GST_STATE( mpPlaybin
);
687 DBG( "isPlaying %d", bRet
);
694 double SAL_CALL
Player::getDuration()
695 throw (uno::RuntimeException
, std::exception
)
697 ::osl::MutexGuard
aGuard(m_aMutex
);
699 // slideshow checks for non-zero duration, so cheat here
700 double duration
= 0.01;
702 if( mpPlaybin
&& mnDuration
> 0 ) {
703 duration
= mnDuration
/ GST_SECOND
;
711 void SAL_CALL
Player::setMediaTime( double fTime
)
712 throw (uno::RuntimeException
, std::exception
)
714 ::osl::MutexGuard
aGuard(m_aMutex
);
717 gint64 gst_position
= llround (fTime
* GST_SECOND
);
719 gst_element_seek( mpPlaybin
, 1.0,
722 GST_SEEK_TYPE_SET
, gst_position
,
723 GST_SEEK_TYPE_NONE
, 0 );
725 gst_element_set_state( mpPlaybin
, GST_STATE_PAUSED
);
727 DBG( "seek to: %" SAL_PRIdINT64
" ns original: %lf s", gst_position
, fTime
);
733 double SAL_CALL
Player::getMediaTime()
734 throw (uno::RuntimeException
, std::exception
)
736 ::osl::MutexGuard
aGuard(m_aMutex
);
738 double position
= 0.0;
741 // get current position in the stream
743 if( wrap_element_query_position( mpPlaybin
, GST_FORMAT_TIME
, &gst_position
) )
744 position
= gst_position
/ GST_SECOND
;
750 void SAL_CALL
Player::setPlaybackLoop( sal_Bool bSet
)
751 throw (uno::RuntimeException
, std::exception
)
753 ::osl::MutexGuard
aGuard(m_aMutex
);
754 // TODO check how to do with GST
760 sal_Bool SAL_CALL
Player::isPlaybackLoop()
761 throw (uno::RuntimeException
, std::exception
)
763 ::osl::MutexGuard
aGuard(m_aMutex
);
764 // TODO check how to do with GST
770 void SAL_CALL
Player::setMute( sal_Bool bSet
)
771 throw (uno::RuntimeException
, std::exception
)
773 ::osl::MutexGuard
aGuard(m_aMutex
);
775 DBG( "set mute: %d muted: %d unmuted volume: %lf", bSet
, mbMuted
, mnUnmutedVolume
);
777 // change the volume to 0 or the unmuted volume
778 if( mpPlaybin
&& mbMuted
!= bool(bSet
) )
780 double nVolume
= mnUnmutedVolume
;
786 g_object_set( G_OBJECT( mpPlaybin
), "volume", nVolume
, NULL
);
794 sal_Bool SAL_CALL
Player::isMute()
795 throw (uno::RuntimeException
, std::exception
)
797 ::osl::MutexGuard
aGuard(m_aMutex
);
804 void SAL_CALL
Player::setVolumeDB( sal_Int16 nVolumeDB
)
805 throw (uno::RuntimeException
, std::exception
)
807 ::osl::MutexGuard
aGuard(m_aMutex
);
809 mnUnmutedVolume
= pow( 10.0, nVolumeDB
/ 20.0 );
811 DBG( "set volume: %d gst volume: %lf", nVolumeDB
, mnUnmutedVolume
);
814 if( !mbMuted
&& mpPlaybin
)
816 g_object_set( G_OBJECT( mpPlaybin
), "volume", (gdouble
) mnUnmutedVolume
, NULL
);
822 sal_Int16 SAL_CALL
Player::getVolumeDB()
823 throw (uno::RuntimeException
, std::exception
)
825 ::osl::MutexGuard
aGuard(m_aMutex
);
827 sal_Int16
nVolumeDB(0);
830 double nGstVolume
= 0.0;
832 g_object_get( G_OBJECT( mpPlaybin
), "volume", &nGstVolume
, NULL
);
834 nVolumeDB
= (sal_Int16
) ( 20.0*log10 ( nGstVolume
) );
842 awt::Size SAL_CALL
Player::getPreferredPlayerWindowSize()
843 throw (uno::RuntimeException
, std::exception
)
845 ::osl::MutexGuard
aGuard(m_aMutex
);
847 awt::Size
aSize( 0, 0 );
849 if( maURL
.isEmpty() )
851 DBG( "%p Player::getPreferredPlayerWindowSize - empty URL => 0x0", this );
855 DBG( "%p pre-Player::getPreferredPlayerWindowSize, member %d x %d", this, mnWidth
, mnHeight
);
857 TimeValue aTimeout
= { 10, 0 };
858 #if OSL_DEBUG_LEVEL > 2
859 osl::Condition::Result aResult
=
861 maSizeCondition
.wait( &aTimeout
);
863 DBG( "%p Player::getPreferredPlayerWindowSize after waitCondition %d, member %d x %d", this, aResult
, mnWidth
, mnHeight
);
865 if( mnWidth
!= 0 && mnHeight
!= 0 ) {
866 aSize
.Width
= mnWidth
;
867 aSize
.Height
= mnHeight
;
875 uno::Reference
< ::media::XPlayerWindow
> SAL_CALL
Player::createPlayerWindow( const uno::Sequence
< uno::Any
>& rArguments
)
876 throw (uno::RuntimeException
, std::exception
)
878 ::osl::MutexGuard
aGuard(m_aMutex
);
880 uno::Reference
< ::media::XPlayerWindow
> xRet
;
881 awt::Size
aSize( getPreferredPlayerWindowSize() );
884 preparePlaybin( maURL
, NULL
);
886 DBG( "Player::createPlayerWindow %d %d length: %d", aSize
.Width
, aSize
.Height
, rArguments
.getLength() );
888 if( aSize
.Width
> 0 && aSize
.Height
> 0 )
890 ::avmedia::gstreamer::Window
* pWindow
= new ::avmedia::gstreamer::Window( mxMgr
, *this );
894 if( rArguments
.getLength() > 2 )
896 sal_IntPtr pIntPtr
= 0;
897 rArguments
[ 2 ] >>= pIntPtr
;
898 SystemChildWindow
*pParentWindow
= reinterpret_cast< SystemChildWindow
* >( pIntPtr
);
899 const SystemEnvData
* pEnvData
= pParentWindow
? pParentWindow
->GetSystemData() : NULL
;
900 OSL_ASSERT(pEnvData
);
903 mnWindowID
= pEnvData
->aWindow
;
904 DBG( "set window id to %d XOverlay %p\n", (int)mnWindowID
, mpXOverlay
);
905 gst_element_set_state( mpPlaybin
, GST_STATE_PAUSED
);
906 if ( mpXOverlay
!= NULL
)
907 gst_video_overlay_set_window_handle( mpXOverlay
, mnWindowID
);
917 uno::Reference
< media::XFrameGrabber
> SAL_CALL
Player::createFrameGrabber()
918 throw (uno::RuntimeException
, std::exception
)
920 ::osl::MutexGuard
aGuard(m_aMutex
);
921 FrameGrabber
* pFrameGrabber
= NULL
;
922 const awt::Size
aPrefSize( getPreferredPlayerWindowSize() );
924 if( ( aPrefSize
.Width
> 0 ) && ( aPrefSize
.Height
> 0 ) )
925 pFrameGrabber
= FrameGrabber::create( maURL
);
926 DBG( "created FrameGrabber %p", pFrameGrabber
);
928 return pFrameGrabber
;
933 OUString SAL_CALL
Player::getImplementationName()
934 throw (uno::RuntimeException
, std::exception
)
936 return OUString( AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME
);
941 sal_Bool SAL_CALL
Player::supportsService( const OUString
& ServiceName
)
942 throw (uno::RuntimeException
, std::exception
)
944 return cppu::supportsService(this, ServiceName
);
949 uno::Sequence
< OUString
> SAL_CALL
Player::getSupportedServiceNames()
950 throw (uno::RuntimeException
, std::exception
)
952 uno::Sequence
< OUString
> aRet(1);
953 aRet
[0] = AVMEDIA_GST_PLAYER_SERVICENAME
;
958 } // namespace gstreamer
959 } // namespace avmedia
961 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */