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

Generated by: LCOV version 1.11