LCOV - code coverage report
Current view: top level - libreoffice/avmedia/source/framework - soundhandler.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 141 0.0 %
Date: 2012-12-27 Functions: 0 22 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "soundhandler.hxx"
      21             : 
      22             : #include <comphelper/mediadescriptor.hxx>
      23             : 
      24             : #include <com/sun/star/io/XInputStream.hpp>
      25             : #include <com/sun/star/frame/DispatchResultState.hpp>
      26             : 
      27             : #include <comphelper/sequenceashashmap.hxx>
      28             : #include <rtl/ustrbuf.hxx>
      29             : 
      30             : #include <cppuhelper/typeprovider.hxx>
      31             : #include <cppuhelper/factory.hxx>
      32             : 
      33             : namespace avmedia{
      34             : 
      35             : //*****************************************************************************************************************
      36             : //  XInterface, XTypeProvider, XServiceInfo
      37             : //*****************************************************************************************************************
      38             : 
      39           0 : void SAL_CALL SoundHandler::acquire() throw()
      40             : {
      41             :        /* Don't use mutex in methods of XInterface! */
      42           0 :        OWeakObject::acquire();
      43           0 : }
      44             : 
      45           0 : void SAL_CALL SoundHandler::release() throw()
      46             : {
      47             :        /* Don't use mutex in methods of XInterface! */
      48           0 :        OWeakObject::release();
      49           0 : }
      50             : 
      51           0 : css::uno::Any SAL_CALL SoundHandler::queryInterface( const css::uno::Type& aType ) throw( css::uno::RuntimeException )
      52             : {
      53             :        /* Attention: Don't use mutex or guard in this method!!! Is a method of XInterface.     */
      54             :         /* Ask for my own supported interfaces ...*/
      55             :        css::uno::Any aReturn( ::cppu::queryInterface( aType,
      56             :                static_cast< css::lang::XTypeProvider* >(this),
      57             :                static_cast< css::lang::XServiceInfo* >(this),
      58             :                static_cast< css::frame::XNotifyingDispatch* >(this),
      59             :                static_cast< css::frame::XDispatch* >(this),
      60           0 :                static_cast< css::document::XExtendedFilterDetection* >(this)));
      61             :        /* If searched interface not supported by this class ... */
      62           0 :        if ( aReturn.hasValue() == sal_False )
      63             :        {
      64             :                /* ... ask baseclass for interfaces! */
      65           0 :                aReturn = OWeakObject::queryInterface( aType );
      66             :        }
      67             :         /* Return result of this search. */
      68           0 :        return aReturn;
      69             : }
      70             : 
      71           0 : css::uno::Sequence< sal_Int8 > SAL_CALL SoundHandler::getImplementationId() throw( css::uno::RuntimeException )
      72             : {
      73             :     /* Create one Id for all instances of this class.                                               */
      74             :     /* Use ethernet address to do this! (sal_True)                                                  */
      75             :     /* Optimize this method                                                                         */
      76             :     /* We initialize a static variable only one time. And we don't must use a mutex at every call!  */
      77             :     /* For the first call; pID is NULL - for the second call pID is different from NULL!            */
      78             :     static ::cppu::OImplementationId* pID = NULL ;
      79           0 :     if ( pID == NULL )
      80             :     {
      81             :         /* Ready for multithreading; get global mutex for first call of this method only! see before   */
      82           0 :         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
      83             :         /* Control these pointer again ... it can be, that another instance will be faster then these! */
      84           0 :         if ( pID == NULL )
      85             :         {
      86             :             /* Create a new static ID ... */
      87           0 :             static ::cppu::OImplementationId aID( sal_False );
      88             :             /* ... and set his address to static pointer! */
      89           0 :             pID = &aID ;
      90           0 :         }
      91             :     }
      92           0 :     return pID->getImplementationId();
      93             : }
      94             : 
      95           0 : css::uno::Sequence< css::uno::Type > SAL_CALL SoundHandler::getTypes() throw( css::uno::RuntimeException )
      96             : {
      97             :     /* Optimize this method !                                       */
      98             :     /* We initialize a static variable only one time.               */
      99             :     /* And we don't must use a mutex at every call!                 */
     100             :     /* For the first call; pTypeCollection is NULL -                */
     101             :     /* for the second call pTypeCollection is different from NULL!  */
     102             :     static ::cppu::OTypeCollection* pTypeCollection = NULL ;
     103           0 :     if ( pTypeCollection == NULL )
     104             :     {
     105             :         /* Ready for multithreading; get global mutex for first call of this method only! see before   */
     106           0 :         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
     107             :         /* Control these pointer again ... it can be, that another instance will be faster then these! */
     108           0 :         if ( pTypeCollection == NULL )
     109             :         {
     110             :             /* Create a static typecollection ...           */
     111             :             static ::cppu::OTypeCollection aTypeCollection
     112             :                 (
     113           0 :                     ::getCppuType(( const ::com::sun::star::uno::Reference< css::lang::XTypeProvider >*)NULL ),
     114           0 :                     ::getCppuType(( const ::com::sun::star::uno::Reference< css::lang::XServiceInfo >*)NULL ),
     115           0 :                     ::getCppuType(( const ::com::sun::star::uno::Reference< css::frame::XNotifyingDispatch >*)NULL ),
     116           0 :                     ::getCppuType(( const ::com::sun::star::uno::Reference< css::frame::XDispatch >*)NULL ),
     117           0 :                     ::getCppuType(( const ::com::sun::star::uno::Reference< css::document::XExtendedFilterDetection >*)NULL )
     118           0 :                 );
     119             :             /* ... and set his address to static pointer! */
     120           0 :             pTypeCollection = &aTypeCollection ;
     121           0 :         }
     122             :     }
     123           0 :     return pTypeCollection->getTypes();
     124             : }
     125             : 
     126             : #define IMPLEMENTATIONNAME_SOUNDHANDLER OUString("com.sun.star.comp.framework.SoundHandler")
     127             : #define SERVICENAME_CONTENTHANDLER OUString("com.sun.star.frame.ContentHandler")
     128             : 
     129             : /*===========================================================================================================*/
     130             : /* XServiceInfo */
     131             : /*===========================================================================================================*/
     132           0 : OUString SAL_CALL SoundHandler::getImplementationName() throw( css::uno::RuntimeException )
     133             : {
     134           0 :     return impl_getStaticImplementationName();
     135             : }
     136             : 
     137             : /*===========================================================================================================*/
     138             : /* XServiceInfo */
     139             : /*===========================================================================================================*/
     140           0 : sal_Bool SAL_CALL SoundHandler::supportsService( const OUString& sServiceName ) throw( css::uno::RuntimeException )
     141             : {
     142             :     /* Set default return value. */
     143           0 :     bool bReturn = sal_False ;
     144             :     /* Get names of all supported servicenames. */
     145           0 :     css::uno::Sequence < OUString >  seqServiceNames       =   getSupportedServiceNames();
     146           0 :     const OUString*                        pArray          =   seqServiceNames.getConstArray();
     147           0 :     sal_Int32                              nCounter        =   0;
     148           0 :     sal_Int32                              nLength         =   seqServiceNames.getLength();
     149             :     /* Search for right name in list. */
     150           0 :     while   (
     151             :               ( nCounter      <       nLength         )       &&
     152             :               ( bReturn       ==      sal_False       )
     153             :             )
     154             :     {
     155             :         /* Is name was found, say "YES, SERVICE IS SUPPORTED." and break loop. */
     156           0 :         if ( pArray[nCounter] == sServiceName )
     157             :         {
     158           0 :             bReturn = sal_True ;
     159             :         }
     160             :         /* Else step to next element in list. */
     161           0 :         ++nCounter;
     162             :     }
     163             :     /* Return state of search. */
     164           0 :     return bReturn;
     165             : }
     166             : 
     167             : /*===========================================================================================================*/
     168             : /* XServiceInfo */
     169             : /*===========================================================================================================*/
     170           0 : css::uno::Sequence< OUString > SAL_CALL SoundHandler::getSupportedServiceNames() throw( css::uno::RuntimeException )
     171             : {
     172           0 :     return impl_getStaticSupportedServiceNames();
     173             : }
     174             : 
     175             : /*===========================================================================================================*/
     176             : /* Helper for XServiceInfo                                                                                   */
     177             : /*===========================================================================================================*/
     178           0 : css::uno::Sequence< OUString > SoundHandler::impl_getStaticSupportedServiceNames()
     179             : {
     180           0 :     css::uno::Sequence< OUString > seqServiceNames( 1 );
     181           0 :     seqServiceNames.getArray() [0] = SERVICENAME_CONTENTHANDLER;
     182           0 :     return seqServiceNames;
     183             : }
     184             : 
     185             : /*===========================================================================================================*/
     186             : /* Helper for XServiceInfo */
     187             : /*===========================================================================================================*/
     188           0 : OUString SoundHandler::impl_getStaticImplementationName()
     189             : {
     190           0 :     return IMPLEMENTATIONNAME_SOUNDHANDLER;
     191             : }
     192             : 
     193           0 : css::uno::Reference< css::uno::XInterface > SAL_CALL SoundHandler::impl_createInstance( const css::uno::Reference< css::lang::XMultiServiceFactory >& xServiceManager ) throw( css::uno::Exception )
     194             : {
     195             :     /* create new instance of service */
     196           0 :     SoundHandler* pClass = new SoundHandler( xServiceManager );
     197             :     /* hold it alive by increasing his ref count!!! */
     198           0 :     css::uno::Reference< css::uno::XInterface > xService( static_cast< ::cppu::OWeakObject* >(pClass), css::uno::UNO_QUERY );
     199             :     /* initialize new service instance ... he can use his own refcount ... we hold it! */
     200           0 :     pClass->impl_initService();
     201             :     /* return new created service as reference */
     202           0 :     return xService;
     203             : }
     204             : 
     205           0 : css::uno::Reference< css::lang::XSingleServiceFactory > SoundHandler::impl_createFactory( const css::uno::Reference< css::lang::XMultiServiceFactory >& xServiceManager )
     206             : {
     207             :     css::uno::Reference< css::lang::XSingleServiceFactory > xReturn ( cppu::createSingleFactory (
     208             :        xServiceManager,
     209             :         SoundHandler::impl_getStaticImplementationName(),
     210             :         SoundHandler::impl_createInstance,
     211             :         SoundHandler::impl_getStaticSupportedServiceNames()
     212             :         )
     213           0 :     );
     214           0 :     return xReturn;
     215             : }
     216             : 
     217           0 : void SAL_CALL SoundHandler::impl_initService()
     218             : {
     219           0 : }
     220             : 
     221             : /*-************************************************************************************************************//**
     222             :     @short      standard ctor
     223             :     @descr      These initialize a new instance of this class with needed informations for work.
     224             : 
     225             :     @seealso    using at owner
     226             : 
     227             :     @param      "xFactory", reference to service manager for creation of new services
     228             :     @return     -
     229             : 
     230             :     @onerror    Show an assertion and do nothing else.
     231             :     @threadsafe yes
     232             : *//*-*************************************************************************************************************/
     233           0 : SoundHandler::SoundHandler( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
     234             :         //  Init baseclasses first
     235             :         :   ThreadHelpBase      (          )
     236             :         ,   ::cppu::OWeakObject (          )
     237             :         // Init member
     238             :     ,   m_bError        ( false    )
     239           0 :         ,   m_xFactory          ( xFactory )
     240             : {
     241           0 :     m_aUpdateTimer.SetTimeoutHdl(LINK(this, SoundHandler, implts_PlayerNotify));
     242           0 : }
     243             : 
     244             : /*-************************************************************************************************************//**
     245             :     @short      standard dtor
     246             :     @descr      -
     247             : 
     248             :     @seealso    -
     249             : 
     250             :     @param      -
     251             :     @return     -
     252             : 
     253             :     @onerror    -
     254             :     @threadsafe -
     255             : *//*-*************************************************************************************************************/
     256           0 : SoundHandler::~SoundHandler()
     257             : {
     258           0 :     if (m_xListener.is())
     259             :     {
     260           0 :         css::frame::DispatchResultEvent aEvent;
     261           0 :         aEvent.State = css::frame::DispatchResultState::FAILURE;
     262           0 :         m_xListener->dispatchFinished(aEvent);
     263           0 :         m_xListener = css::uno::Reference< css::frame::XDispatchResultListener >();
     264             :     }
     265           0 : }
     266             : 
     267             : /*-************************************************************************************************************//**
     268             :     @interface  ::com::sun::star::frame::XDispatch
     269             : 
     270             :     @short      try to load audio file
     271             :     @descr      This method try to load given audio file by URL and play it. We use vcl/Sound class to do that.
     272             :                 Playing of sound is asynchron everytime.
     273             : 
     274             :     @attention  We must hold us alive by ourself ... because we use async. vcl sound player ... but playing is started
     275             :                 in async interface call "dispatch()" too. And caller forget us imediatly. But then our uno ref count
     276             :                 will decreased to 0 and will die. The only solution is to use own reference to our implementation.
     277             :                 But we do it for realy started jobs only and release it during call back of vcl.
     278             : 
     279             :     @seealso    class vcl/Sound
     280             :     @seealso    method implts_PlayerNotify()
     281             : 
     282             :     @param      "aURL"      , URL to dispatch.
     283             :     @param      "lArguments", list of optional arguments.
     284             :     @return     -
     285             : 
     286             :     @onerror    We do nothing.
     287             :     @threadsafe yes
     288             : *//*-*************************************************************************************************************/
     289           0 : void SAL_CALL SoundHandler::dispatchWithNotification(const css::util::URL&                                             aURL      ,
     290             :                                                      const css::uno::Sequence< css::beans::PropertyValue >&            lDescriptor,
     291             :                                                      const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw(css::uno::RuntimeException)
     292             : {
     293             :     // SAFE {
     294           0 :     const ::osl::MutexGuard aLock( m_aLock );
     295             : 
     296             :     {
     297             :     //close streams otherwise on windows we can't reopen the file in the
     298             :     //media player when we pass the url to directx as it'll already be open
     299           0 :         ::comphelper::MediaDescriptor aDescriptor(lDescriptor);
     300             : 
     301             :     css::uno::Reference< css::io::XInputStream > xInputStream =
     302           0 :         aDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_INPUTSTREAM(),
     303           0 :         css::uno::Reference< css::io::XInputStream >());
     304           0 :     if (xInputStream.is()) xInputStream->closeInput();
     305             :     }
     306             : 
     307             :     // If player currently used for other dispatch() requests ...
     308             :     // cancel it by calling stop()!
     309           0 :     m_aUpdateTimer.Stop();
     310           0 :     if (m_xPlayer.is())
     311             :     {
     312           0 :         if (m_xPlayer->isPlaying())
     313           0 :             m_xPlayer->stop();
     314           0 :         m_xPlayer.clear();
     315             :     }
     316             : 
     317             :     // Try to initialize player.
     318           0 :     m_xListener = xListener;
     319             :     try
     320             :     {
     321           0 :         m_bError = false;
     322           0 :         m_xPlayer.set( avmedia::MediaWindow::createPlayer( aURL.Complete ), css::uno::UNO_QUERY_THROW );
     323             :         // OK- we can start async playing ...
     324             :         // Count this request and initialize self-holder against dieing by uno ref count ...
     325           0 :         m_xSelfHold = css::uno::Reference< css::uno::XInterface >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
     326           0 :         m_xPlayer->start();
     327           0 :         m_aUpdateTimer.SetTimeout( 200 );
     328           0 :         m_aUpdateTimer.Start();
     329             :     }
     330           0 :     catch( css::uno::Exception& e )
     331             :     {
     332           0 :         m_bError = true;
     333             :         (void)e;
     334           0 :         m_xPlayer.clear();
     335           0 :     }
     336             : 
     337             :     // } SAFE
     338           0 : }
     339             : 
     340           0 : void SAL_CALL SoundHandler::dispatch( const css::util::URL&                                  aURL       ,
     341             :                                       const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::uno::RuntimeException )
     342             : {
     343           0 :     dispatchWithNotification(aURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >());
     344           0 : }
     345             : 
     346             : /*-************************************************************************************************************//**
     347             :     @interface  ::com::sun::star::document::XExtendedFilterDetection
     348             : 
     349             :     @short      try to detect file (given as argument included in "lDescriptor")
     350             :     @descr      We try to detect, if given file could be handled by this class and is a well known one.
     351             :                 If it is - we return right internal type name - otherwise we return nothing!
     352             :                 So call can search for another detect service and ask him too.
     353             : 
     354             :     @attention  a) We don't need any mutex here ... because we don't use any member!
     355             :                 b) Dont' use internal player instance "m_pPlayer" to detect given sound file!
     356             :                    It's not neccessary to do that ... and we can use temp. variable to do the same.
     357             :                    This way is easy - we don't must synchronize it with currently played sounds!
     358             :                    Another reason to do so ... We are a listener on our internal ma_Player object.
     359             :                    If you would call "IsSoundFile()" on this instance, he would call us back and
     360             :                    we make some uneccssary things ...
     361             : 
     362             :     @seealso    -
     363             : 
     364             :     @param      "lDescriptor", description of file to detect
     365             :     @return     Internal type name which match this file ... or nothing if it is unknown.
     366             : 
     367             :     @onerror    We return nothing.
     368             :     @threadsafe yes
     369             : *//*-*************************************************************************************************************/
     370           0 : OUString SAL_CALL SoundHandler::detect( css::uno::Sequence< css::beans::PropertyValue >& lDescriptor ) throw( css::uno::RuntimeException )
     371             : {
     372             :     // Our default is "nothing". So we can return it, if detection failed or fily type is realy unknown.
     373           0 :     OUString sTypeName;
     374             : 
     375             :     // Analyze given descriptor to find filename or input stream or ...
     376           0 :     ::comphelper::MediaDescriptor aDescriptor(lDescriptor);
     377           0 :     OUString                      sURL       = aDescriptor.getUnpackedValueOrDefault(::comphelper::MediaDescriptor::PROP_URL(), OUString());
     378             : 
     379           0 :     if (
     380           0 :         (sURL.getLength()           ) &&
     381           0 :         (avmedia::MediaWindow::isMediaURL(sURL))
     382             :        )
     383             :     {
     384             :         // If the file type is supported depends on the OS, so...
     385             :         // I think we can the following ones:
     386             :         //  a) look for given extension of url to map our type decision HARD CODED!!!
     387             :         //  b) return preferred type every time... it's easy :-)
     388           0 :         sTypeName = "wav_Wave_Audio_File";
     389           0 :         aDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME()] <<= sTypeName;
     390           0 :         aDescriptor >> lDescriptor;
     391             :     }
     392             : 
     393             :     // Return our decision.
     394           0 :     return sTypeName;
     395             : }
     396             : 
     397             : /*-************************************************************************************************************//**
     398             :     @short      call back of sound player
     399             :     @descr      Our player call us back to give us some informations.
     400             :                 We use this informations to callback our might existing listener.
     401             : 
     402             :     @seealso    method dispatchWithNotification()
     403             : 
     404             :     @param      -
     405             :     @return     0 everytime ... it doesnt matter for us.
     406             : 
     407             :     @onerror    -
     408             :     @threadsafe yes
     409             : *//*-*************************************************************************************************************/
     410           0 : IMPL_LINK_NOARG(SoundHandler, implts_PlayerNotify)
     411             : {
     412             :     // SAFE {
     413           0 :     ::osl::ClearableMutexGuard aLock( m_aLock );
     414             : 
     415           0 :     if (m_xPlayer.is() && m_xPlayer->isPlaying() && m_xPlayer->getMediaTime() < m_xPlayer->getDuration())
     416             :     {
     417           0 :         m_aUpdateTimer.Start();
     418           0 :         return 0L;
     419             :     }
     420           0 :     m_xPlayer.clear();
     421             : 
     422             :     // We use m_xSelfHold to let us die ... but we must live till real finishing of this method too!!!
     423             :     // So we SHOULD use another "self-holder" temp. to provide that ...
     424           0 :     css::uno::Reference< css::uno::XInterface > xOperationHold = m_xSelfHold;
     425           0 :     m_xSelfHold = css::uno::Reference< css::uno::XInterface >();
     426             : 
     427             :     // notify might existing listener
     428             :     // And forget this listener!
     429             :     // Because the corresponding dispatch was finished.
     430           0 :     if (m_xListener.is())
     431             :     {
     432           0 :         css::frame::DispatchResultEvent aEvent;
     433           0 :         if (!m_bError)
     434           0 :             aEvent.State = css::frame::DispatchResultState::SUCCESS;
     435             :         else
     436           0 :             aEvent.State = css::frame::DispatchResultState::FAILURE;
     437           0 :         m_xListener->dispatchFinished(aEvent);
     438           0 :         m_xListener = css::uno::Reference< css::frame::XDispatchResultListener >();
     439             :     }
     440             : 
     441             :     // } SAFE
     442             :     //release aLock before end of method at which point xOperationHold goes out of scope and pThis dies
     443           0 :     aLock.clear();
     444           0 :     return 0;
     445             : }
     446             : 
     447             : } // namespace framework
     448             : 
     449           0 : extern "C" SAL_DLLPUBLIC_EXPORT void* SAL_CALL avmedia_component_getFactory(const sal_Char* pImplementationName, void* pServiceManager, void* /*pRegistryKey*/ )
     450             : {
     451           0 :     void* pReturn = NULL;
     452           0 :     if  (pServiceManager !=  NULL )
     453             :     {
     454             :         /* Define variables which are used in following macros. */
     455           0 :         css::uno::Reference< ::com::sun::star::lang::XSingleServiceFactory > xFactory;
     456           0 :         css::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager;
     457           0 :             xServiceManager = reinterpret_cast< ::com::sun::star::lang::XMultiServiceFactory* >( pServiceManager )  ;
     458             : 
     459           0 :         if ( avmedia::SoundHandler::impl_getStaticImplementationName().equals( OUString::createFromAscii( pImplementationName ) ) )
     460           0 :             xFactory = avmedia::SoundHandler::impl_createFactory( xServiceManager );
     461             : 
     462           0 :         if ( xFactory.is() == sal_True )
     463             :         {
     464           0 :             xFactory->acquire();
     465           0 :             pReturn = xFactory.get();
     466           0 :         }
     467             :     }
     468             :     /* Return with result of this operation. */
     469           0 :     return pReturn;
     470             : }
     471             : 
     472             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10