Commits

Anonymous committed b1e0b15

avmedia101: added GStreamer backend for Unix

Comments (0)

Files changed (33)

avmedia/prj/build.lst

 av  avmedia\source\framework	nmake	-	all	av_framework	        								NULL
 av  avmedia\source\win	    	nmake	-	all	av_win	            									NULL
 av	avmedia\source\java			nmake	-	all	av_java	            									NULL
-av	avmedia\source\xine			nmake	-	all	av_xine	            									NULL
 av	avmedia\source\quicktime	nmake	-	all	av_quicktime											NULL
-av	avmedia\util				nmake	-	all	av_util av_viewer av_framework av_win av_java av_quicktime av_xine	NULL
+av	avmedia\source\gstreamer	nmake	-	all	av_gstreamer	            							NULL
+av	avmedia\util				nmake	-	all	av_util av_viewer av_framework av_win av_java av_quicktime av_gstreamer	NULL

avmedia/source/gstreamer/exports.dxp

+component_getImplementationEnvironment
+component_writeInfo
+component_getFactory

avmedia/source/gstreamer/gstcommon.hxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: GSTREAMERcommon.hxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _GSTCOMMON_HXX
+#define _GSTCOMMON_HXX
+
+#include <osl/mutex.hxx>
+#include <rtl/ustring.hxx>
+#include <tools/debug.hxx>
+#include <tools/stream.hxx>
+#include <tools/string.hxx>
+#include <tools/urlobj.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include <cppuhelper/implbase3.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/factory.hxx>
+
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/awt/MouseButton.hpp>
+#include <com/sun/star/media/XManager.hpp>
+
+#include <memory>
+
+#define AVMEDIA_GSTREAMER_MANAGER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Manager_GStreamer"
+#define AVMEDIA_GSTREAMER_MANAGER_SERVICENAME "com.sun.star.media.Manager_GStreamer"
+
+#define AVMEDIA_GSTREAMER_PLAYER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Player_GStreamer"
+#define AVMEDIA_GSTREAMER_PLAYER_SERVICENAME "com.sun.star.media.Player_GStreamer"
+
+#define AVMEDIA_GSTREAMER_WINDOW_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.Window_GStreamer"
+#define AVMEDIA_GSTREAMER_WINDOW_SERVICENAME "com.sun.star.media.Window_GStreamer"
+
+#define AVMEDIA_GSTREAMER_FRAMEGRABBER_IMPLEMENTATIONNAME "com.sun.star.comp.avmedia.FrameGrabber_GStreamer"
+#define AVMEDIA_GSTREAMER_FRAMEGRABBER_SERVICENAME "com.sun.star.media.FrameGrabber_GStreamer"
+
+#endif // _GSTCOMMOM_HXX

avmedia/source/gstreamer/gstframegrabber.cxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: framegrabber.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "gstframegrabber.hxx"
+#include "gstplayer.hxx"
+
+#include <vcl/graph.hxx>
+#include <vcl/bmpacc.hxx>
+
+using namespace ::com::sun::star;
+
+namespace avmedia { namespace gst {
+
+const gulong GRAB_TIMEOUT = 10000000;
+
+// ----------------
+// - FrameGrabber -
+// ----------------
+
+FrameGrabber::FrameGrabber( GString* pURI ) :
+    Player( pURI  ),
+    mpFrameMutex( g_mutex_new() ),
+    mpFrameCond( g_cond_new() ),
+    mpLastPixbuf( NULL ),
+    mbIsInGrabMode( false )
+{
+}
+
+// ------------------------------------------------------------------------------
+
+FrameGrabber::~FrameGrabber()
+{
+    if( g_atomic_pointer_get( &mpPlayer ) )
+    {
+        implQuitThread();
+    }
+
+    // thread has ended, so that no more synchronization is necessary
+    if( mpLastPixbuf )
+    {
+        g_object_unref( mpLastPixbuf );
+        mpLastPixbuf = NULL;
+    }
+
+    g_cond_free( mpFrameCond );
+    g_mutex_free( mpFrameMutex );
+}
+
+// ------------------------------------------------------------------------------
+
+FrameGrabber* FrameGrabber::create( const GString* pURI )
+{
+    FrameGrabber* pFrameGrabber = NULL;
+
+    if( pURI && pURI->len )
+    {
+        // safely initialize GLib threading framework
+        try
+        {
+            if( !g_thread_supported() )
+            {
+                g_thread_init( NULL );
+            }
+        }
+        catch( ... )
+        {}
+
+        if( g_thread_supported() )
+        {
+            pFrameGrabber = new FrameGrabber( g_string_new( pURI->str ) );
+
+            // wait until thread signals that it has finished initialization
+            if( pFrameGrabber->mpThread )
+            {
+                g_mutex_lock( pFrameGrabber->mpMutex );
+
+                while( !pFrameGrabber->implIsInitialized() )
+                {
+                    g_cond_wait( pFrameGrabber->mpCond, pFrameGrabber->mpMutex );
+                }
+
+                g_mutex_unlock( pFrameGrabber->mpMutex );
+            }
+            
+            GstElement* pPixbufSink = gst_element_factory_make( "gdkpixbufsink", NULL );
+
+            // check if player pipeline and GdkPixbufSink could be initialized
+            if( !pFrameGrabber->mpPlayer || !pPixbufSink )
+            {
+                delete pFrameGrabber;
+                pFrameGrabber = NULL;
+            }
+            else
+            {
+                g_object_set( pFrameGrabber->mpPlayer, "audio-sink", gst_element_factory_make( "fakesink", NULL ), NULL );
+                g_object_set( pFrameGrabber->mpPlayer, "video-sink", pPixbufSink, NULL );
+            }
+        }
+    }
+
+    return( pFrameGrabber );
+}
+
+// ------------------------------------------------------------------------------
+
+gboolean FrameGrabber::busCallback( GstBus* pBus, GstMessage* pMsg )
+{
+    bool bDone = false;
+
+    if( pMsg && pMsg->structure )
+    {
+        GstStructure* pStruct = pMsg->structure;
+        const gchar* pStructName = gst_structure_get_name( pStruct );
+
+        if( ( ::std::string( pStructName ).find( "pixbuf" ) != ::std::string::npos ) &&
+            gst_structure_has_field ( pStruct, "pixbuf") )
+        {
+            bool bFrameGrabbed = false;
+
+            g_mutex_lock( mpFrameMutex );
+
+            if( mbIsInGrabMode && ( getMediaTime() >= mfGrabTime ) )
+            {
+                OSL_TRACE( "Grabbing frame at %fs", getMediaTime() );
+
+                if( mpLastPixbuf )
+                {
+                    g_object_unref( mpLastPixbuf );
+                    mpLastPixbuf = NULL;
+                }
+
+                mpLastPixbuf = GDK_PIXBUF( g_value_dup_object( gst_structure_get_value( pStruct, "pixbuf" ) ) );
+                bFrameGrabbed = true;
+            }
+
+            g_mutex_unlock( mpFrameMutex );
+            
+            if( bFrameGrabbed )
+            {
+                g_cond_signal( mpFrameCond );
+            }
+
+            bDone = true;
+        }
+    }
+
+    return( bDone || Player::busCallback( pBus, pMsg ) );
+}
+
+// ------------------------------------------------------------------------------
+
+uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMediaTime )
+    throw (uno::RuntimeException)
+{
+    uno::Reference< graphic::XGraphic > xRet;
+
+    if( implInitPlayer() )
+    {
+        OSL_TRACE( "Trying to grab frame at %fs", fMediaTime );
+
+        GTimeVal aTimeoutTime;
+
+        g_get_current_time( &aTimeoutTime );
+        g_time_val_add( &aTimeoutTime, GRAB_TIMEOUT );
+        setMediaTime( fMediaTime );
+        start();
+
+        if( isPlaying() )
+        {
+            g_mutex_lock( mpFrameMutex );
+
+            mbIsInGrabMode = true;
+            mfGrabTime = fMediaTime;
+            g_cond_timed_wait( mpFrameCond, mpFrameMutex, &aTimeoutTime );
+            mbIsInGrabMode = false;
+
+            g_mutex_unlock( mpFrameMutex );
+
+            stop();
+        }
+
+        OSL_ENSURE( g_atomic_pointer_get( &mpLastPixbuf ), "FrameGrabber timed out without receiving a Pixbuf" );
+
+        if( g_atomic_pointer_get( &mpLastPixbuf ) )
+        {
+            OSL_TRACE( "FrameGrabber received a GdkPixbuf");
+
+            g_mutex_lock( mpFrameMutex );
+
+            const int nWidth = gdk_pixbuf_get_width( mpLastPixbuf );
+            const int nHeight = gdk_pixbuf_get_height( mpLastPixbuf );
+            const int nChannels = gdk_pixbuf_get_n_channels( mpLastPixbuf );
+            const guchar* pBuffer = gdk_pixbuf_get_pixels( mpLastPixbuf );
+
+            if( pBuffer && ( nWidth > 0 ) && ( nHeight > 0 ) )
+            {
+                Bitmap aFrame( Size( nWidth, nHeight), 24 );
+                bool bInit = false;
+
+                if( ( gdk_pixbuf_get_colorspace( mpLastPixbuf ) == GDK_COLORSPACE_RGB ) &&
+                    ( nChannels >= 3 ) && ( nChannels <= 4 ) &&
+                    ( gdk_pixbuf_get_bits_per_sample( mpLastPixbuf ) == 8 ) )
+                {
+                    BitmapWriteAccess* pAcc = aFrame.AcquireWriteAccess();
+
+                    if( pAcc )
+                    {
+                        BitmapColor aPixel( 0, 0, 0 );
+                        const int nRowStride = gdk_pixbuf_get_rowstride( mpLastPixbuf );
+                        const bool bAlpha = ( nChannels == 4  );
+
+                        for( int nRow = 0; nRow < nHeight; ++nRow )
+                        {
+                            guchar* pCur = const_cast< guchar* >( pBuffer + nRow * nRowStride );
+
+                            for( int nCol = 0; nCol < nWidth; ++nCol )
+                            {
+                                aPixel.SetRed( *pCur++ );
+                                aPixel.SetGreen( *pCur++ );
+                                aPixel.SetBlue( *pCur++ );
+
+                                // ignore alpha channel
+                                if( bAlpha )
+                                {
+                                    ++pCur;
+                                }
+
+                                pAcc->SetPixel( nRow, nCol, aPixel );
+                            }
+                        }
+
+                        aFrame.ReleaseAccess( pAcc );
+                        bInit = true;
+                    }
+                }
+
+                if( !bInit )
+                {
+                    aFrame.Erase( Color( COL_BLACK ) );
+                }
+
+                xRet = Graphic( aFrame ).GetXGraphic();
+            }
+
+            g_object_unref( mpLastPixbuf );
+            mpLastPixbuf = NULL;
+
+            g_mutex_unlock( mpFrameMutex );
+        }
+    }
+    
+    return xRet;
+}
+
+// ------------------------------------------------------------------------------
+
+::rtl::OUString SAL_CALL FrameGrabber::getImplementationName(  )
+    throw (uno::RuntimeException)
+{
+    return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_GSTREAMER_FRAMEGRABBER_IMPLEMENTATIONNAME ) );
+}
+
+// ------------------------------------------------------------------------------
+
+sal_Bool SAL_CALL FrameGrabber::supportsService( const ::rtl::OUString& ServiceName )
+    throw (uno::RuntimeException)
+{
+    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( AVMEDIA_GSTREAMER_FRAMEGRABBER_SERVICENAME ) );
+}
+
+// ------------------------------------------------------------------------------
+
+uno::Sequence< ::rtl::OUString > SAL_CALL FrameGrabber::getSupportedServiceNames(  )
+    throw (uno::RuntimeException)
+{
+    uno::Sequence< ::rtl::OUString > aRet(1);
+    aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( AVMEDIA_GSTREAMER_FRAMEGRABBER_SERVICENAME ) );
+
+    return aRet;
+}
+
+} // namespace win
+} // namespace avmedia

avmedia/source/gstreamer/gstframegrabber.hxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: framegrabber.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _FRAMEGRABBER_HXX
+#define _FRAMEGRABBER_HXX
+
+#include "gstplayer.hxx"
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#ifndef _COM_SUN_STAR_MEDIA_XFRAMEGRABBER_HDL_
+#include "com/sun/star/media/XFrameGrabber.hdl"
+#endif
+
+namespace avmedia { namespace gst {
+
+// ----------------
+// - FrameGrabber -
+// ----------------
+
+class FrameGrabber : public Player,
+                     public ::cppu::WeakImplHelper2 < ::com::sun::star::media::XFrameGrabber,
+                                                      ::com::sun::star::lang::XServiceInfo >
+{
+public:
+
+    // static create method instead of public Ctor
+    static FrameGrabber* create( const GString* pUri );
+
+    ~FrameGrabber();
+
+    // XFrameGrabber
+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > SAL_CALL grabFrame( double fMediaTime ) throw (::com::sun::star::uno::RuntimeException);
+
+    // XServiceInfo
+    virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException);
+    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
+    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (::com::sun::star::uno::RuntimeException);
+
+protected: FrameGrabber( GString* pURI = NULL );
+
+    virtual gboolean busCallback( GstBus* pBus,
+                                  GstMessage* pMsg );
+
+private: FrameGrabber( const FrameGrabber& );
+    FrameGrabber& operator=( const FrameGrabber& );
+
+    GMutex* mpFrameMutex;
+    GCond* mpFrameCond;
+    GdkPixbuf* mpLastPixbuf;
+    double mfGrabTime;
+    bool mbIsInGrabMode;
+};
+
+} // namespace gst 
+} // namespace avmedia
+
+#endif // _FRAMEGRABBER_HXX

avmedia/source/gstreamer/gstmanager.cxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: manager.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "gstmanager.hxx"
+#include "gstplayer.hxx"
+
+using namespace ::com::sun::star;
+
+namespace avmedia
+{
+namespace gst
+{
+// ----------------
+// - Manager -
+// ----------------
+
+Manager::Manager( const uno::Reference< lang::XMultiServiceFactory >& rxMgr ) :
+    mxMgr( rxMgr )
+{}
+
+// ------------------------------------------------------------------------------
+
+Manager::~Manager()
+{}
+
+// ------------------------------------------------------------------------------
+
+uno::Reference< media::XPlayer > SAL_CALL Manager::createPlayer( const ::rtl::OUString& rURL )
+     throw( uno::RuntimeException )
+{
+    return( ::avmedia::gst::Player::create( rURL ) );
+}
+
+// ------------------------------------------------------------------------------
+
+::rtl::OUString SAL_CALL Manager::getImplementationName()
+     throw( uno::RuntimeException )
+{
+    return( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_GSTREAMER_MANAGER_IMPLEMENTATIONNAME ) ) );
+}
+
+// ------------------------------------------------------------------------------
+
+sal_Bool SAL_CALL Manager::supportsService( const ::rtl::OUString& ServiceName )
+     throw( uno::RuntimeException )
+{
+    return( ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( AVMEDIA_GSTREAMER_MANAGER_SERVICENAME ) ) );
+}
+
+// ------------------------------------------------------------------------------
+
+uno::Sequence< ::rtl::OUString > SAL_CALL Manager::getSupportedServiceNames()
+     throw( uno::RuntimeException )
+{
+    uno::Sequence< ::rtl::OUString > aRet( 1 );
+    aRet[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_GSTREAMER_MANAGER_SERVICENAME ) );
+
+    return( aRet );
+}
+} // namespace gst
+} // namespace avmedia

avmedia/source/gstreamer/gstmanager.hxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: manager.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _GSTMANAGER_HXX
+#define _GSTMANAGER_HXX
+
+#include "gstcommon.hxx"
+
+#ifndef _COM_SUN_STAR_MEDIA_XMANAGER_HDL_
+#include "com/sun/star/media/XManager.hdl"
+#endif
+
+// -----------
+// - Manager -
+// -----------
+
+namespace avmedia
+{
+namespace gst
+{
+class Manager : public ::cppu::WeakImplHelper2< ::com::sun::star::media::XManager,
+                                                ::com::sun::star::lang::XServiceInfo >
+{
+public: Manager( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMgr );
+    ~Manager();
+
+    // XManager
+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::media::XPlayer > SAL_CALL createPlayer(
+        const ::rtl::OUString& aURL )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    // XServiceInfo
+    virtual ::rtl::OUString SAL_CALL getImplementationName()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+
+private:
+
+    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMgr;
+};
+} // namespace gst
+} // namespace avmedia
+
+#endif // _GSTMANAGER_HXX

avmedia/source/gstreamer/gstplayer.cxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: player.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "gstplayer.hxx"
+#include "gstwindow.hxx"
+#include "gstframegrabber.hxx"
+#include <stdio.h>
+#include <unistd.h>
+#include <math.h>
+#include <string>
+#include <gst/gstelement.h>
+#include <gst/interfaces/xoverlay.h>
+
+using namespace ::com::sun::star;
+
+namespace avmedia
+{
+namespace gst
+{
+const double NANO_TIME_FACTOR = 1000000000.0;
+
+const long      VIDEO_DEFAULT_WIDTH = 256;
+const long      VIDEO_DEFAULT_HEIGHT = 192;
+
+// ----------------
+// - GstBusSource -
+// ----------------
+
+struct GstBusSource : public GSource
+{
+    GstBus* mpBus;
+
+    GstBusSource() :
+        mpBus( NULL )
+    {}
+
+    ~GstBusSource()
+    {}
+};
+
+// ---------------
+// - Player -
+// ---------------
+Player::Player( GString* pURI ) :
+    mpMutex( g_mutex_new() ),
+    mpCond( g_cond_new() ),
+    mpThread( NULL ),
+    mpContext( NULL ),
+    mpLoop( NULL ),
+    mpPlayer( NULL ),
+    mpURI( pURI ),
+    mpPlayerWindow( NULL ),
+    mnIsVideoSource( 0 ),
+    mnVideoWidth( 0 ),
+    mnVideoHeight( 0 ),
+    mnInitialized( 0 ),
+    mnVolumeDB( 0 ),
+    mnLooping( 0 ),
+    mnQuit( 0 ),
+    mnVideoWindowSet( 0 )
+{
+    // initialize GStreamer framework only once
+    static bool bGstInitialized = false;
+
+    if( !bGstInitialized )
+    {
+        gst_init( NULL, NULL );
+        bGstInitialized = true;
+    }
+
+    if( pURI )
+    {
+        OSL_TRACE( ">>> --------------------------------" );
+        OSL_TRACE( ">>> Creating Player object with URL: %s", pURI->str );
+
+        mpThread = g_thread_create( Player::implThreadFunc, this, true, NULL );
+    }
+}
+
+// ------------------------------------------------------------------------------
+
+Player::~Player()
+{
+    if( g_atomic_pointer_get( &mpPlayer ) )
+    {
+        implQuitThread();
+    }
+
+    // cleanup
+    g_cond_free( mpCond );
+    g_mutex_free( mpMutex );
+    g_string_free( mpURI, false );
+}
+
+// ------------------------------------------------------------------------------
+Player* Player::create( const ::rtl::OUString& rURL )
+{
+    Player* pPlayer = NULL;
+
+    if( rURL.getLength() )
+    {
+        // safely initialize GLib threading framework
+        try
+        {
+            if( !g_thread_supported() )
+            {
+                g_thread_init( NULL );
+            }
+        }
+        catch( ... )
+        {}
+
+        if( g_thread_supported() )
+        {
+            const INetURLObject aURL( rURL );
+
+            if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
+            {
+                GString* pURI = g_string_new( ::rtl::OUStringToOString(
+                                                 aURL.GetMainURL( INetURLObject::NO_DECODE ),
+                                                 RTL_TEXTENCODING_UTF8 ).getStr() );
+
+                if( pURI->len )
+                {
+                    pPlayer = new Player( pURI );
+
+                    // wait until thread signals that it has finished initialization
+                    if( pPlayer->mpThread )
+                    {
+                        g_mutex_lock( pPlayer->mpMutex );
+
+                        while( !pPlayer->implIsInitialized() )
+                        {
+                            g_cond_wait( pPlayer->mpCond, pPlayer->mpMutex );
+                        }
+
+                        g_mutex_unlock( pPlayer->mpMutex );
+                    }
+
+                    // check if player pipeline could be initialized
+                    if( !pPlayer->mpPlayer )
+                    {
+                        delete pPlayer;
+                        pPlayer = NULL;
+                    }
+                }
+                else
+                {
+                    g_string_free( pURI, false );
+                }
+            }
+        }
+    }
+
+    return( pPlayer );
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::start()
+     throw( uno::RuntimeException )
+{
+    if( implInitPlayer() && !isPlaying() )
+    {
+        gst_element_set_state( mpPlayer, GST_STATE_PLAYING );
+    }
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::stop()
+     throw( uno::RuntimeException )
+{
+    if( implInitPlayer() && isPlaying() )
+    {
+        gst_element_set_state( mpPlayer, GST_STATE_PAUSED );
+    }
+}
+
+// ------------------------------------------------------------------------------
+sal_Bool SAL_CALL Player::isPlaying()
+     throw( uno::RuntimeException )
+{
+    GstState aState = GST_STATE_NULL;
+
+    if( mpPlayer )
+    {
+        gst_element_get_state( mpPlayer, &aState, NULL, GST_CLOCK_TIME_NONE );
+    }
+
+    return( GST_STATE_PLAYING == aState );
+}
+
+// ------------------------------------------------------------------------------
+double SAL_CALL Player::getDuration()
+     throw( uno::RuntimeException )
+{
+    gint64 nDuration = 0;
+
+    if( implInitPlayer() )
+    {
+        GstFormat aFormat = GST_FORMAT_TIME;
+
+        if( !gst_element_query_duration( mpPlayer, &aFormat, &nDuration ) ||
+           ( GST_FORMAT_TIME != aFormat ) ||
+           ( nDuration < 0 ) )
+        {
+            nDuration = 0;
+        }
+    }
+
+    return( static_cast< double >( nDuration ) / NANO_TIME_FACTOR );
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::setMediaTime( double fTime )
+     throw( uno::RuntimeException )
+{
+    if( implInitPlayer() )
+    {
+        fTime = ::std::min( ::std::max( fTime, 0.0 ), getDuration() );
+
+        gst_element_seek_simple( mpPlayer, GST_FORMAT_TIME,
+                                (GstSeekFlags) ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT ),
+                                static_cast< gint64 >( fTime * NANO_TIME_FACTOR ) );
+    }
+}
+
+// ------------------------------------------------------------------------------
+double SAL_CALL Player::getMediaTime()
+     throw( uno::RuntimeException )
+{
+    double fRet = 0.0;
+
+    if( implInitPlayer() )
+    {
+        GstFormat aFormat = GST_FORMAT_TIME;
+        gint64 nCurTime = 0;
+
+        if( gst_element_query_position( mpPlayer, &aFormat, &nCurTime ) &&
+           ( GST_FORMAT_TIME == aFormat ) &&
+           ( nCurTime >= 0 ) )
+        {
+            fRet = static_cast< double >( nCurTime ) / NANO_TIME_FACTOR;
+        }
+    }
+
+    return( fRet );
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::setStopTime( double /* fTime */ )
+     throw( uno::RuntimeException )
+{
+    if( implInitPlayer() )
+    {
+        // TBD!!!
+    }
+}
+
+// ------------------------------------------------------------------------------
+double SAL_CALL Player::getStopTime()
+     throw( uno::RuntimeException )
+{
+    double fRet = 0.0;
+
+    if( implInitPlayer() )
+    {
+        // TBD!!!
+        fRet = getDuration();
+    }
+
+    return( fRet );
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::setRate( double /* fRate */ )
+     throw( uno::RuntimeException )
+{
+    if( implInitPlayer() )
+    {
+        // TBD!!!
+    }
+}
+
+// ------------------------------------------------------------------------------
+double SAL_CALL Player::getRate()
+     throw( uno::RuntimeException )
+{
+    double fRet = 1.0;
+
+    if( implInitPlayer() )
+    {
+        // TBD!!!;
+    }
+
+    return( fRet );
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::setPlaybackLoop( sal_Bool bSet )
+     throw( uno::RuntimeException )
+{
+    g_atomic_int_set( &mnLooping, bSet ? 1 : 0 );
+}
+
+// ------------------------------------------------------------------------------
+sal_Bool SAL_CALL Player::isPlaybackLoop()
+     throw( uno::RuntimeException )
+{
+    return( g_atomic_int_get( &mnLooping ) > 0 );
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::setMute( sal_Bool bSet )
+     throw( uno::RuntimeException )
+{
+    if( implInitPlayer() && ( bSet != isMute() ) )
+    {
+        if( bSet )
+        {
+            g_object_set( mpPlayer, "volume", 0.0, NULL );
+        }
+        else
+        {
+            setVolumeDB( mnVolumeDB );
+        }
+    }
+}
+
+// ------------------------------------------------------------------------------
+sal_Bool SAL_CALL Player::isMute()
+     throw( uno::RuntimeException )
+{
+    gdouble fGstVolume = 1.0;
+
+    if( implInitPlayer() )
+    {
+        g_object_get( mpPlayer, "volume", &fGstVolume, NULL );
+    }
+
+    return( 0.0 == fGstVolume );
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
+     throw( uno::RuntimeException )
+{
+    g_atomic_int_set( &mnVolumeDB, nVolumeDB );
+
+    if( implInitPlayer() )
+    {
+        // maximum gain for gstreamer volume is 10
+        double fGstVolume = pow( 10.0, static_cast< double >( ::std::min(
+                                                                  nVolumeDB, static_cast< sal_Int16 >( 20 ) ) / 20.0 ) );
+
+        g_object_set( mpPlayer, "volume", fGstVolume, NULL );
+    }
+}
+
+// ------------------------------------------------------------------------------
+sal_Int16 SAL_CALL Player::getVolumeDB()
+     throw( uno::RuntimeException )
+{
+    return( static_cast< sal_Int16 >( g_atomic_int_get( &mnVolumeDB ) ) );
+}
+
+// ------------------------------------------------------------------------------
+awt::Size SAL_CALL Player::getPreferredPlayerWindowSize()
+     throw( uno::RuntimeException )
+{
+    awt::Size aSize( 0, 0 );
+
+    if( implInitPlayer() && ( g_atomic_int_get( &mnIsVideoSource ) > 0 ) )
+    {
+        aSize.Width = g_atomic_int_get( &mnVideoWidth );
+        aSize.Height = g_atomic_int_get( &mnVideoHeight );
+
+        // if we have a video source, but no size is given => use default size
+        if( ( aSize.Width <= 0 ) || ( aSize.Height <= 0 ) )
+        {
+            aSize.Width = VIDEO_DEFAULT_WIDTH;
+            aSize.Height = VIDEO_DEFAULT_HEIGHT;
+        }
+    }
+
+    OSL_TRACE( ">>> Requested preferred video size is: %d x %d pixel", aSize.Width, aSize.Height );
+
+    return( aSize );
+}
+
+// ------------------------------------------------------------------------------
+uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow(
+    const uno::Sequence< uno::Any >& rArguments )
+     throw( uno::RuntimeException )
+{
+    uno::Reference< ::media::XPlayerWindow > xRet;
+    awt::Size aSize( getPreferredPlayerWindowSize() );
+
+    OSL_ENSURE( !g_atomic_pointer_get( &mpPlayerWindow ), "::avmedia::gst::Player already has a player window" );
+
+    if( ( aSize.Width > 0 ) && ( aSize.Height > 0 ) )
+    {
+        Window* pPlayerWindow = new Window( *this );
+
+        xRet = pPlayerWindow;
+
+        if( !pPlayerWindow->create( rArguments ) )
+        {
+            xRet.clear();
+        }
+        else
+        {
+            GstElement* pVideoSink = gst_element_factory_make( "xvimagesink", NULL );
+
+            if( !pVideoSink )
+            {
+                pVideoSink = gst_element_factory_make( "ximagesink", NULL );
+            }
+
+            if( pVideoSink )
+            {
+                GstState aOldState = GST_STATE_NULL;
+
+                mpPlayerWindow = pPlayerWindow;
+                gst_element_get_state( mpPlayer, &aOldState, NULL, GST_CLOCK_TIME_NONE );
+                gst_element_set_state( mpPlayer, GST_STATE_READY );
+                g_object_set( mpPlayer, "video-sink", pVideoSink, NULL );
+                gst_element_set_state( mpPlayer, aOldState );
+            }
+        }
+    }
+
+    return( xRet );
+}
+
+// ------------------------------------------------------------------------------
+uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber()
+     throw( ::com::sun::star::uno::RuntimeException )
+{
+    FrameGrabber* pFrameGrabber = NULL;
+    const awt::Size aPrefSize( getPreferredPlayerWindowSize() );
+
+    if( ( aPrefSize.Width > 0 ) && ( aPrefSize.Height > 0 ) )
+    {
+        pFrameGrabber = FrameGrabber::create( mpURI );
+    }
+
+    return( pFrameGrabber );
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::dispose()
+     throw( uno::RuntimeException )
+{
+    if( mpPlayer )
+    {
+        stop();
+        implQuitThread();
+    }
+
+    OSL_ASSERT( NULL == mpPlayer );
+}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::addEventListener( const uno::Reference< lang::XEventListener >& /*rxListener*/ )
+     throw( uno::RuntimeException )
+{}
+
+// ------------------------------------------------------------------------------
+void SAL_CALL Player::removeEventListener( const uno::Reference< lang::XEventListener >& /*rxListener*/ )
+     throw( uno::RuntimeException )
+{}
+
+// ------------------------------------------------------------------------------
+::rtl::OUString SAL_CALL Player::getImplementationName()
+     throw( uno::RuntimeException )
+{
+    return( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_GSTREAMER_PLAYER_IMPLEMENTATIONNAME ) ) );
+}
+
+// ------------------------------------------------------------------------------
+sal_Bool SAL_CALL Player::supportsService( const ::rtl::OUString& ServiceName )
+     throw( uno::RuntimeException )
+{
+    return( ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( AVMEDIA_GSTREAMER_PLAYER_SERVICENAME ) ) );
+}
+
+// ------------------------------------------------------------------------------
+uno::Sequence< ::rtl::OUString > SAL_CALL Player::getSupportedServiceNames()
+     throw( uno::RuntimeException )
+{
+    uno::Sequence< ::rtl::OUString > aRet( 1 );
+    aRet[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( AVMEDIA_GSTREAMER_PLAYER_SERVICENAME ) );
+
+    return( aRet );
+}
+
+// ------------------------------------------------------------------------------
+void Player::implQuitThread()
+{
+    if( mpThread )
+    {
+        // set quit flag to 1 so that the main loop will be quit in idle
+        // handler the next time it is called from the thread's main loop
+        g_atomic_int_add( &mnQuit, 1 );
+
+        // wait until loop and as such the thread has quit
+        g_thread_join( mpThread );
+        mpThread = NULL;
+    }
+}
+
+// ------------------------------------------------------------------------------
+bool Player::implInitPlayer()
+{
+    bool bRet = false;
+
+    if( mpPlayer )
+    {
+        GstState aState = GST_STATE_NULL;
+
+        if( gst_element_get_state( mpPlayer, &aState, NULL, GST_CLOCK_TIME_NONE ) == GST_STATE_CHANGE_SUCCESS )
+        {
+            bRet = ( GST_STATE_PAUSED == aState ) || ( GST_STATE_PLAYING == aState );
+
+            if( !bRet )
+            {
+                gst_element_set_state( mpPlayer, GST_STATE_PAUSED );
+                bRet = ( gst_element_get_state( mpPlayer, &aState, NULL,
+                                                GST_CLOCK_TIME_NONE ) == GST_STATE_CHANGE_SUCCESS ) &&
+                    ( GST_STATE_PAUSED == aState );
+            }
+        }
+    }
+
+    return( bRet );
+}
+
+// ------------------------------------------------------------------------------
+gboolean Player::implBusPrepare( GSource* pSource,
+                                 gint* pTimeout )
+{
+    if( pTimeout )
+    {
+        *pTimeout = 0;
+    }
+
+    return( implBusCheck( pSource ) );
+}
+
+// ------------------------------------------------------------------------------
+gboolean Player::implBusCheck( GSource* pSource )
+{
+    GstBusSource* pBusSource = static_cast< GstBusSource* >( pSource );
+
+    return( pBusSource &&
+           GST_IS_BUS( pBusSource->mpBus ) &&
+           gst_bus_have_pending( GST_BUS_CAST( pBusSource->mpBus ) ) );
+}
+
+// ------------------------------------------------------------------------------
+gboolean Player::implBusDispatch( GSource* pSource,
+                                  GSourceFunc /*aCallback*/,
+                                  gpointer pData )
+{
+    GstBusSource* pBusSource = static_cast< GstBusSource* >( pSource );
+    gboolean bRet = false;
+
+    if( pData && pBusSource && GST_IS_BUS( pBusSource->mpBus ) )
+    {
+        GstMessage* pMsg = gst_bus_pop( pBusSource->mpBus );
+
+        if( pMsg )
+        {
+            bRet = static_cast< Player* >( pData )->busCallback( pBusSource->mpBus, pMsg );
+            gst_message_unref( pMsg );
+        }
+    }
+
+    return( bRet );
+}
+
+// ------------------------------------------------------------------------------
+void Player::implBusFinalize( GSource* pSource )
+{
+    GstBusSource* pBusSource = static_cast< GstBusSource* >( pSource );
+
+    if( pBusSource && pBusSource->mpBus )
+    {
+        gst_object_unref( pBusSource->mpBus );
+        pBusSource->mpBus = NULL;
+    }
+}
+
+// ------------------------------------------------------------------------------
+gboolean Player::busCallback( GstBus* /*pBus*/,
+                              GstMessage* pMsg )
+{
+    if( pMsg && mpLoop )
+    {
+        switch( GST_MESSAGE_TYPE( pMsg ) )
+        {
+            case ( GST_MESSAGE_EOS ):
+            {
+                if( g_atomic_int_get( &mnLooping ) > 0 )
+                {
+                    setMediaTime( 0.0 );
+                    start();
+                }
+                else
+                {
+                    stop();
+                }
+            }
+            break;
+
+            case ( GST_MESSAGE_ERROR ):
+            {
+                gchar* pDebug;
+                GError* pErr;
+
+                gst_message_parse_error( pMsg, &pErr, &pDebug );
+                fprintf( stderr, "Error: %s\n", pErr->message );
+
+                g_free( pDebug );
+                g_error_free( pErr );
+            }
+            break;
+
+            default:
+            {
+                break;
+            }
+        }
+    }
+
+    return( true );
+}
+
+// ------------------------------------------------------------------------------
+gboolean Player::implIdleFunc( gpointer pData )
+{
+    return( pData ? static_cast< Player* >( pData )->idle() : true );
+}
+
+// ------------------------------------------------------------------------------
+gpointer Player::implThreadFunc( gpointer pData )
+{
+    return( pData ? static_cast< Player* >( pData )->run() : NULL );
+}
+
+// ------------------------------------------------------------------------------
+GstBusSyncReply Player::implHandleCreateWindowFunc( GstBus* pBus,
+                                                    GstMessage* pMsg,
+                                                    gpointer pData )
+{
+    return( pData ? static_cast< Player* >( pData )->handleCreateWindow( pBus, pMsg ) : GST_BUS_PASS );
+}
+
+// ------------------------------------------------------------------------------
+void Player::implHandleNewElementFunc( GstBin* /* pBin */,
+                                       GstElement* pElement,
+                                       gpointer pData )
+{
+    if( pElement )
+    {
+#ifdef DEBUG
+        gchar* pElementName = gst_element_get_name( pElement );
+
+        if( pElementName )
+        {
+            OSL_TRACE( ">>> Bin has element: %s", pElementName );
+            g_free( pElementName );
+        }
+#endif
+
+        if( GST_IS_BIN( pElement ) )
+        {
+            // set this handler in case we have a GstBin element
+            g_signal_connect( GST_BIN( pElement ), "element-added",
+                              G_CALLBACK( Player::implHandleNewElementFunc ), pData );
+        }
+
+        // watch for all pads that are going to be added to this element;
+        g_signal_connect( pElement, "pad-added",
+                          G_CALLBACK( Player::implHandleNewPadFunc ), pData );
+    }
+}
+
+// ------------------------------------------------------------------------------
+void Player::implHandleNewPadFunc( GstElement* pElement,
+                                   GstPad* pPad,
+                                   gpointer pData )
+{
+    Player* pPlayer = static_cast< Player* >( pData );
+
+    if( pPlayer && pElement && pPad )
+    {
+#ifdef DEBUG
+        gchar* pElementName = gst_element_get_name( pElement );
+        gchar* pPadName = gst_pad_get_name( pPad );
+
+        OSL_TRACE( ">>> Element %s has pad: %s", pElementName, pPadName );
+
+        g_free( pPadName );
+        g_free( pElementName );
+#endif
+
+        GstCaps* pCaps = gst_pad_get_caps( pPad );
+
+        // we are interested only in getting video properties
+        // width and height or if we have a video source at all
+        if( pCaps )
+        {
+            for( gint i = 0, nSize = gst_caps_get_size( pCaps ); i < nSize; ++i )
+            {
+                const GstStructure* pStruct = gst_caps_get_structure( pCaps, i );
+
+                if( pStruct )
+                {
+                    const gchar* pStructName = gst_structure_get_name( pStruct );
+
+#ifdef DEBUG
+                    OSL_TRACE( "\t>>> Pad has structure: %s", pStructName );
+
+                    for( gint n = 0, nFields = gst_structure_n_fields( pStruct ); n < nFields; ++n )
+                    {
+                        OSL_TRACE( "\t\t>>> Structure has field: %s", gst_structure_nth_field_name( pStruct, n ) );
+                    }
+#endif
+
+                    // just look for structures having 'video' in their names
+                    if( ::std::string( pStructName ).find( "video" ) != ::std::string::npos )
+                    {
+                        g_atomic_int_set( &pPlayer->mnIsVideoSource, 1 );
+
+                        for( gint n = 0, nFields = gst_structure_n_fields( pStruct ); n < nFields; ++n )
+                        {
+                            const gchar* pFieldName = gst_structure_nth_field_name( pStruct, n );
+                            gint nValue;
+
+                            if( ( ::std::string( pFieldName ).find( "width" ) != ::std::string::npos ) &&
+                               gst_structure_get_int( pStruct, pFieldName, &nValue ) )
+                            {
+                                g_atomic_int_set( &pPlayer->mnVideoWidth,
+                                                 ::std::max( (gint) g_atomic_int_get(
+                                                                &pPlayer->mnVideoWidth ), nValue ) );
+                            }
+                            else if( ( ::std::string( pFieldName ).find( "height" ) != ::std::string::npos ) &&
+                                    gst_structure_get_int( pStruct, pFieldName, &nValue ) )
+                            {
+                                g_atomic_int_set( &pPlayer->mnVideoHeight,
+                                                 ::std::max( g_atomic_int_get( &pPlayer->mnVideoHeight ), nValue ) );
+                            }
+                        }
+                    }
+                }
+            }
+
+            gst_caps_unref( pCaps );
+        }
+    }
+}
+
+// ------------------------------------------------------------------------------
+gboolean Player::idle()
+{
+    // test if main loop should quit and set flag mnQuit to 1
+    bool bQuit = g_atomic_int_compare_and_exchange( &mnQuit, 1, 1 );
+
+    if( bQuit )
+    {
+        // set mnQuit back to 0 to avoid mutiple g_main_loop_quit calls
+        // in case Player::idle() is called again later;
+        // the flag should have been set only once within Ctor called from
+        // the application thread
+        g_atomic_int_add( &mnQuit, -1 );
+        g_main_loop_quit( mpLoop );
+    }
+
+    // don't eat up all cpu time
+    usleep( 1000 );
+
+    return( true );
+}
+
+// ------------------------------------------------------------------------------
+gpointer Player::run()
+{
+    static GSourceFuncs aSourceFuncs =
+    {
+        Player::implBusPrepare,
+        Player::implBusCheck,
+        Player::implBusDispatch,
+        Player::implBusFinalize,
+        NULL,
+        NULL
+    };
+
+    if( NULL != ( mpPlayer = gst_element_factory_make( "playbin", NULL ) ) )
+    {
+        // initialization
+        // no mutex necessary since initialization
+        // is synchronous until loop is started
+        mpContext = g_main_context_new();
+        mpLoop = g_main_loop_new( mpContext, false );
+
+        // add idle callback
+        GSource* pIdleSource = g_idle_source_new();
+        g_source_set_callback( pIdleSource, Player::implIdleFunc, this, NULL );
+        g_source_attach( pIdleSource, mpContext );
+
+        // add bus callback
+        GSource* pBusSource = g_source_new( &aSourceFuncs, sizeof( GstBusSource ) );
+        static_cast< GstBusSource* >( pBusSource )->mpBus = gst_pipeline_get_bus( GST_PIPELINE( mpPlayer ) );
+        g_source_set_callback( pBusSource, NULL, this, NULL );
+        g_source_attach( pBusSource, mpContext );
+
+        // add bus sync handler to intercept video window creation for setting our own window
+        gst_bus_set_sync_handler( static_cast< GstBusSource* >( pBusSource )->mpBus,
+                                  Player::implHandleCreateWindowFunc, this );
+
+        // watch for all elements (and pads) that will be added to the playbin,
+        // in order to retrieve properties like video width and height
+        g_signal_connect( GST_BIN( mpPlayer ), "element-added",
+                          G_CALLBACK( Player::implHandleNewElementFunc ), this );
+
+        // set source URI for player
+        g_object_set( mpPlayer, "uri", mpURI->str, NULL );
+
+        // set video fake sink first, since we only create a player without window here
+        // and don't want to have the gstreamer default window appearing
+        g_object_set( mpPlayer, "video-sink", gst_element_factory_make( "fakesink", NULL ), NULL );
+
+        // set state of player to READY or destroy object in case of FAILURE
+        if( gst_element_set_state( mpPlayer, GST_STATE_READY ) == GST_STATE_CHANGE_FAILURE )
+        {
+            gst_object_unref( mpPlayer );
+            mpPlayer = NULL;
+        }
+
+        g_atomic_int_add( &mnInitialized, 1 );
+        g_cond_signal( mpCond );
+
+        // run the main loop
+        g_main_loop_run( mpLoop );
+
+        // clenanup
+        // no mutex necessary since other thread joined us (this thread)
+        // after setting the quit flag
+        if( mpPlayer )
+        {
+            gst_element_set_state( mpPlayer, GST_STATE_NULL );
+            gst_object_unref( mpPlayer );
+            mpPlayer = NULL;
+        }
+
+        g_main_loop_unref( mpLoop );
+        mpLoop = NULL;
+
+        g_source_destroy( pBusSource );
+        g_source_unref( pBusSource );
+
+        g_source_destroy( pIdleSource );
+        g_source_unref( pIdleSource );
+
+        g_main_context_unref( mpContext );
+        mpContext = NULL;
+    }
+    else
+    {
+        g_atomic_int_add( &mnInitialized, 1 );
+        g_cond_signal( mpCond );
+    }
+
+    return( NULL );
+}
+
+// ------------------------------------------------------------------------------
+GstBusSyncReply Player::handleCreateWindow( GstBus* /* pBus */,
+                                            GstMessage* pMsg )
+{
+    GstBusSyncReply eRet = GST_BUS_PASS;
+
+    if( pMsg &&
+       ( GST_MESSAGE_TYPE( pMsg ) == GST_MESSAGE_ELEMENT ) &&
+       gst_structure_has_name( pMsg->structure, "prepare-xwindow-id" ) &&
+       g_atomic_pointer_get( &mpPlayerWindow ) )
+    {
+        OSL_TRACE( ">>> Got Request to create XOverlay" );
+
+        gst_x_overlay_set_xwindow_id( GST_X_OVERLAY( GST_MESSAGE_SRC( pMsg ) ),
+                                     static_cast< Window* >( g_atomic_pointer_get(
+                                                                &mpPlayerWindow ) )->getXWindowHandle() );
+
+        gst_message_unref( pMsg );
+        eRet = GST_BUS_DROP;
+    }
+
+    return( eRet );
+}
+}     // namespace gst
+} // namespace avmedia

avmedia/source/gstreamer/gstplayer.hxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: player.hxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _GSTPLAYER_HXX
+#define _GSTPLAYER_HXX
+
+#include "gstcommon.hxx"
+#include <glib.h>
+#include <gst/gst.h>
+
+#include "com/sun/star/media/XPlayer.hdl"
+
+namespace avmedia
+{
+namespace gst
+{
+class Window;
+
+// ---------------
+// - Player_Impl -
+// ---------------
+
+class Player : public ::cppu::WeakImplHelper3< ::com::sun::star::media::XPlayer,
+                                               ::com::sun::star::lang::XComponent,
+                                               ::com::sun::star::lang::XServiceInfo >
+{
+public:
+
+    // static create method instead of public Ctor
+    static Player* create( const ::rtl::OUString& rURL );
+
+    ~Player();
+
+    // XPlayer
+    virtual void SAL_CALL start()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual void SAL_CALL stop()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual sal_Bool SAL_CALL isPlaying()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual double SAL_CALL getDuration()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual void SAL_CALL setMediaTime( double fTime )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual double SAL_CALL getMediaTime()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual void SAL_CALL setStopTime( double fTime )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual double SAL_CALL getStopTime()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual void SAL_CALL setRate( double fRate )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual double SAL_CALL getRate()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual void SAL_CALL setPlaybackLoop( sal_Bool bSet )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual sal_Bool SAL_CALL isPlaybackLoop()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual void SAL_CALL setMute( sal_Bool bSet )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual sal_Bool SAL_CALL isMute()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual void SAL_CALL setVolumeDB( sal_Int16 nVolumeDB )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual sal_Int16 SAL_CALL getVolumeDB()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual ::com::sun::star::awt::Size SAL_CALL getPreferredPlayerWindowSize()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::media::XPlayerWindow > SAL_CALL createPlayerWindow(
+        const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::media::XFrameGrabber > SAL_CALL createFrameGrabber()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    // XComponent
+    virtual void SAL_CALL dispose()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual void SAL_CALL addEventListener(
+        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& xListener )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual void SAL_CALL removeEventListener(
+        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    // XServiceInfo
+    virtual ::rtl::OUString SAL_CALL getImplementationName()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
+     throw( ::com::sun::star::uno::RuntimeException );
+
+    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
+     throw( ::com::sun::star::uno::RuntimeException );
+
+
+protected: Player( GString* pURI = NULL );
+
+    virtual gboolean busCallback( GstBus* pBus,
+                                  GstMessage* pMsg );
+
+    virtual gboolean idle();
+
+    virtual gpointer run();
+
+    virtual GstBusSyncReply handleCreateWindow( GstBus* pBus,
+                                                GstMessage* pMsg );
+
+    void implQuitThread();
+
+    bool implInitPlayer();
+
+    bool implIsInitialized() const
+    {
+        return( g_atomic_int_get( &mnInitialized ) > 0 );
+    }
+
+
+private: Player( const Player& ) {}
+
+    Player & operator=( const Player& )
+    {
+        return( *this );
+    }
+
+    static gboolean implBusPrepare( GSource* pSource,
+                                    gint* pTimeout );
+
+    static gboolean implBusCheck( GSource* pSource );
+
+    static gboolean implBusDispatch( GSource* pSource,
+                                     GSourceFunc aCallback,
+                                     gpointer pData );
+
+    static void implBusFinalize( GSource* pSource );
+
+    static gboolean implIdleFunc( gpointer pData );
+
+    static gpointer implThreadFunc( gpointer pData );
+
+    static GstBusSyncReply implHandleCreateWindowFunc( GstBus* pBus,
+                                                       GstMessage* pMsg,
+                                                       gpointer pDData );
+
+    static void implHandleNewElementFunc( GstBin* pBin,
+                                          GstElement* pElement,
+                                          gpointer pData );
+
+    static void implHandleNewPadFunc( GstElement* pElem,
+                                      GstPad* pPad,
+                                      gpointer pData );
+
+protected:
+
+    GMutex* mpMutex;
+    GCond* mpCond;
+    GThread* mpThread;
+    GMainContext* mpContext;
+    GMainLoop* mpLoop;
+    GstElement* mpPlayer;
+    GString* mpURI;
+
+private:
+
+    ::avmedia::gst::Window* mpPlayerWindow;
+    volatile gint mnIsVideoSource;
+    volatile gint mnVideoWidth;
+    volatile gint mnVideoHeight;
+    volatile gint mnInitialized;
+    volatile gint mnVolumeDB;
+    volatile gint mnLooping;
+    volatile gint mnQuit;
+    volatile gint mnVideoWindowSet;
+};
+}     // namespace gst
+} // namespace avmedia
+
+#endif // _GSTPLAYER_HXX

avmedia/source/gstreamer/gstuno.cxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: xineuno.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "gstcommon.hxx"
+#include "gstmanager.hxx"
+
+using namespace ::com::sun::star;
+
+// -------------------
+// - factory methods -
+// -------------------
+
+static uno::Reference< uno::XInterface > SAL_CALL create_MediaPlayer( const uno::Reference< lang::XMultiServiceFactory >& rxFact )
+{
+	return uno::Reference< uno::XInterface >( *new ::avmedia::gst::Manager( rxFact ) );
+}
+
+// ------------------------------------------
+// - component_getImplementationEnvironment -
+// ------------------------------------------
+
+extern "C" void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ )
+{
+	*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+// -----------------------
+// - component_writeInfo -
+// -----------------------
+
+extern "C" sal_Bool SAL_CALL component_writeInfo( void* /* pServiceManager */, void* pRegistryKey )
+{
+	sal_Bool bRet = sal_False;
+
+	if( pRegistryKey )
+	{
+		try
+		{
+			uno::Reference< registry::XRegistryKey > xNewKey1(
+				static_cast< registry::XRegistryKey* >( pRegistryKey )->createKey(                                
+                ::rtl::OUString::createFromAscii(
+                    "/" AVMEDIA_GSTREAMER_MANAGER_IMPLEMENTATIONNAME "/UNO/SERVICES/"
+                    AVMEDIA_GSTREAMER_MANAGER_SERVICENAME ) ) );
+            
+			bRet = sal_True;
+		}
+		catch( registry::InvalidRegistryException& )
+		{
+			OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
+		}
+	}
+
+	return bRet;
+}
+
+// ------------------------
+// - component_getFactory -
+// ------------------------
+
+extern "C" void* SAL_CALL component_getFactory( const sal_Char* pImplName, void* pServiceManager, void* /* pRegistryKey */ )
+{
+	uno::Reference< lang::XSingleServiceFactory > xFactory;
+	void*									pRet = 0;
+
+	if( rtl_str_compare( pImplName, AVMEDIA_GSTREAMER_MANAGER_IMPLEMENTATIONNAME ) == 0 )
+	{
+		const ::rtl::OUString aServiceName( ::rtl::OUString::createFromAscii( AVMEDIA_GSTREAMER_MANAGER_SERVICENAME ) );
+
+		xFactory = uno::Reference< lang::XSingleServiceFactory >( ::cppu::createSingleFactory(
+						reinterpret_cast< lang::XMultiServiceFactory* >( pServiceManager ),
+						::rtl::OUString::createFromAscii( AVMEDIA_GSTREAMER_MANAGER_IMPLEMENTATIONNAME ),
+						create_MediaPlayer, uno::Sequence< ::rtl::OUString >( &aServiceName, 1 ) ) );
+	}
+
+	if( xFactory.is() )
+	{
+		xFactory->acquire();
+		pRet = xFactory.get();
+	}
+
+	return pRet;
+}

avmedia/source/gstreamer/gstwindow.cxx

+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: window.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org.  If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LG;;PLv3 License.
+ *
+ ************************************************************************/
+
+#include <tools/prex.h>
+#include <tools/postx.h>
+
+#include <com/sun/star/awt/SystemPointer.hdl>
+
+#include "gstwindow.hxx"
+#include "gstplayer.hxx"
+#include <vcl/syschild.hxx>
+#include <vcl/sysdata.hxx>
+
+using namespace ::com::sun::star;
+
+namespace avmedia
+{
+namespace gst
+{
+// ---------------------
+// - PlayerChildWindow -
+// ---------------------
+
+class PlayerChildWindow : public SystemChildWindow
+{
+public:
+
+                    PlayerChildWindow( Window* pParent );
+                    ~PlayerChildWindow();
+
+protected:
+
+    virtual void    MouseMove( const MouseEvent& rMEvt );
+    virtual void    MouseButtonDown( const MouseEvent& rMEvt );
+    virtual void    MouseButtonUp( const MouseEvent& rMEvt );
+    virtual void    KeyInput( const KeyEvent& rKEvt );
+    virtual void    KeyUp( const KeyEvent& rKEvt );
+    virtual void    Command( const CommandEvent& rCEvt );
+};
+
+// ---------------------------------------------------------------------
+
+PlayerChildWindow::PlayerChildWindow( Window* pParent ) :
+    SystemChildWindow( pParent, WB_CLIPCHILDREN )
+{
+}
+
+// ---------------------------------------------------------------------
+
+PlayerChildWindow::~PlayerChildWindow()
+{
+}
+
+// ---------------------------------------------------------------------
+
+void PlayerChildWindow::MouseMove( const MouseEvent& rMEvt )
+{
+    const MouseEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ),
+                                        rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), rMEvt.GetModifier() );
+
+    SystemChildWindow::MouseMove( rMEvt );
+    GetParent()->MouseMove( aTransformedEvent );
+}
+
+// ---------------------------------------------------------------------
+
+void PlayerChildWindow::MouseButtonDown( const MouseEvent& rMEvt )
+{
+    const MouseEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ),
+                                        rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), rMEvt.GetModifier() );
+
+    SystemChildWindow::MouseButtonDown( rMEvt );
+    GetParent()->MouseButtonDown( aTransformedEvent );
+}
+
+// ---------------------------------------------------------------------
+
+void PlayerChildWindow::MouseButtonUp( const MouseEvent& rMEvt )
+{
+    const MouseEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ),
+                                        rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), rMEvt.GetModifier() );
+
+    SystemChildWindow::MouseButtonUp( rMEvt );
+    GetParent()->MouseButtonUp( aTransformedEvent );
+}
+
+// ---------------------------------------------------------------------
+
+void PlayerChildWindow::KeyInput( const KeyEvent& rKEvt )
+{
+    SystemChildWindow::KeyInput( rKEvt );
+    GetParent()->KeyInput( rKEvt );
+}
+