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

Generated by: LCOV version 1.10