bump product version to 6.3.0.0.beta1
[LibreOffice.git] / avmedia / source / framework / soundhandler.cxx
blob0b580399eb15d67aede4104d61e4264050260f97
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "soundhandler.hxx"
22 #include <unotools/mediadescriptor.hxx>
24 #include <com/sun/star/io/XInputStream.hpp>
25 #include <com/sun/star/frame/DispatchResultState.hpp>
27 #include <rtl/ustrbuf.hxx>
29 #include <cppuhelper/queryinterface.hxx>
30 #include <cppuhelper/typeprovider.hxx>
31 #include <cppuhelper/factory.hxx>
32 #include <cppuhelper/supportsservice.hxx>
34 namespace avmedia{
37 // XInterface, XTypeProvider, XServiceInfo
40 void SAL_CALL SoundHandler::acquire() throw()
42 /* Don't use mutex in methods of XInterface! */
43 OWeakObject::acquire();
46 void SAL_CALL SoundHandler::release() throw()
48 /* Don't use mutex in methods of XInterface! */
49 OWeakObject::release();
52 css::uno::Any SAL_CALL SoundHandler::queryInterface( const css::uno::Type& aType )
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 static_cast< css::document::XExtendedFilterDetection* >(this)));
62 /* If searched interface not supported by this class ... */
63 if ( !aReturn.hasValue() )
65 /* ... ask baseclass for interfaces! */
66 aReturn = OWeakObject::queryInterface( aType );
68 /* Return result of this search. */
69 return aReturn;
72 css::uno::Sequence< sal_Int8 > SAL_CALL SoundHandler::getImplementationId()
74 return css::uno::Sequence<sal_Int8>();
77 css::uno::Sequence< css::uno::Type > SAL_CALL SoundHandler::getTypes()
79 static ::cppu::OTypeCollection aTypeCollection(
80 cppu::UnoType<css::lang::XTypeProvider>::get(),
81 cppu::UnoType<css::lang::XServiceInfo>::get(),
82 cppu::UnoType<css::frame::XNotifyingDispatch>::get(),
83 cppu::UnoType<css::frame::XDispatch>::get(),
84 cppu::UnoType<css::document::XExtendedFilterDetection>::get());
86 return aTypeCollection.getTypes();
89 #define IMPLEMENTATIONNAME_SOUNDHANDLER OUString("com.sun.star.comp.framework.SoundHandler")
91 /*===========================================================================================================*/
92 /* XServiceInfo */
93 /*===========================================================================================================*/
94 OUString SAL_CALL SoundHandler::getImplementationName()
96 return IMPLEMENTATIONNAME_SOUNDHANDLER;
99 // XServiceInfo
100 sal_Bool SAL_CALL SoundHandler::supportsService( const OUString& sServiceName )
102 return cppu::supportsService(this, sServiceName);
105 // XServiceInfo
106 css::uno::Sequence< OUString > SAL_CALL SoundHandler::getSupportedServiceNames()
108 return { "com.sun.star.frame.ContentHandler" };
111 /*-************************************************************************************************************
112 @short standard ctor
113 @descr These initialize a new instance of this class with needed information for work.
115 @seealso using at owner
117 @param "xFactory", reference to service manager for creation of new services
118 @onerror Show an assertion and do nothing else.
119 @threadsafe yes
120 *//*-*************************************************************************************************************/
121 SoundHandler::SoundHandler()
122 // Init baseclasses first
123 : ThreadHelpBase ( )
124 , ::cppu::OWeakObject ( )
125 // Init member
126 , m_bError ( false )
127 , m_aUpdateIdle ( "avmedia SoundHandler Update" )
129 m_aUpdateIdle.SetInvokeHandler(LINK(this, SoundHandler, implts_PlayerNotify));
132 /*-************************************************************************************************************
133 @short standard dtor
134 *//*-*************************************************************************************************************/
135 SoundHandler::~SoundHandler()
137 if (m_xListener.is())
139 css::frame::DispatchResultEvent aEvent;
140 aEvent.State = css::frame::DispatchResultState::FAILURE;
141 m_xListener->dispatchFinished(aEvent);
142 m_xListener.clear();
146 /*-************************************************************************************************************
147 @interface css::frame::XDispatch
149 @short try to load audio file
150 @descr This method try to load given audio file by URL and play it. We use vcl/Sound class to do that.
151 Playing of sound is asynchron every time.
153 @attention We must hold us alive by ourself ... because we use async. vcl sound player ... but playing is started
154 in async interface call "dispatch()" too. And caller forget us immediately. But then our uno ref count
155 will decreased to 0 and will die. The only solution is to use own reference to our implementation.
156 But we do it for really started jobs only and release it during call back of vcl.
158 @seealso class vcl/Sound
159 @seealso method implts_PlayerNotify()
161 @param "aURL" , URL to dispatch.
162 @param "lArguments", list of optional arguments.
163 @onerror We do nothing.
164 @threadsafe yes
165 *//*-*************************************************************************************************************/
166 void SAL_CALL SoundHandler::dispatchWithNotification(const css::util::URL& aURL ,
167 const css::uno::Sequence< css::beans::PropertyValue >& lDescriptor,
168 const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
170 // SAFE {
171 const ::osl::MutexGuard aLock( m_aLock );
173 utl::MediaDescriptor aDescriptor(lDescriptor);
176 //close streams otherwise on windows we can't reopen the file in the
177 //media player when we pass the url to directx as it'll already be open
178 css::uno::Reference< css::io::XInputStream > xInputStream =
179 aDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_INPUTSTREAM(),
180 css::uno::Reference< css::io::XInputStream >());
181 if (xInputStream.is()) xInputStream->closeInput();
184 // If player currently used for other dispatch() requests ...
185 // cancel it by calling stop()!
186 m_aUpdateIdle.Stop();
187 if (m_xPlayer.is())
189 if (m_xPlayer->isPlaying())
190 m_xPlayer->stop();
191 m_xPlayer.clear();
194 // Try to initialize player.
195 m_xListener = xListener;
198 m_bError = false;
199 m_xPlayer.set( avmedia::MediaWindow::createPlayer( aURL.Complete, aDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_REFERRER(), OUString()) ), css::uno::UNO_SET_THROW );
200 // OK- we can start async playing ...
201 // Count this request and initialize self-holder against dying by uno ref count ...
202 m_xSelfHold.set(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
203 m_xPlayer->start();
204 m_aUpdateIdle.SetPriority( TaskPriority::HIGH_IDLE );
205 m_aUpdateIdle.Start();
207 catch( css::uno::Exception& )
209 m_bError = true;
210 m_xPlayer.clear();
213 // } SAFE
216 void SAL_CALL SoundHandler::dispatch( const css::util::URL& aURL ,
217 const css::uno::Sequence< css::beans::PropertyValue >& lArguments )
219 dispatchWithNotification(aURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >());
222 /*-************************************************************************************************************
223 @interface css::document::XExtendedFilterDetection
225 @short try to detect file (given as argument included in "lDescriptor")
226 @descr We try to detect, if given file could be handled by this class and is a well known one.
227 If it is - we return right internal type name - otherwise we return nothing!
228 So call can search for another detect service and ask him too.
230 @attention a) We don't need any mutex here ... because we don't use any member!
231 b) Don't use internal player instance "m_pPlayer" to detect given sound file!
232 It's not necessary to do that ... and we can use temp. variable to do the same.
233 This way is easy - we don't must synchronize it with currently played sounds!
234 Another reason to do so ... We are a listener on our internal ma_Player object.
235 If you would call "IsSoundFile()" on this instance, he would call us back and
236 we make some unnecessary things ...
237 @param "lDescriptor", description of file to detect
238 @return Internal type name which match this file ... or nothing if it is unknown.
240 @onerror We return nothing.
241 @threadsafe yes
242 *//*-*************************************************************************************************************/
243 OUString SAL_CALL SoundHandler::detect( css::uno::Sequence< css::beans::PropertyValue >& lDescriptor )
245 // Our default is "nothing". So we can return it, if detection failed or file type is really unknown.
246 OUString sTypeName;
248 // Analyze given descriptor to find filename or input stream or ...
249 utl::MediaDescriptor aDescriptor(lDescriptor);
250 OUString sURL = aDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_URL(), OUString());
251 OUString sReferer = aDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_REFERRER(), OUString());
253 if (
254 !sURL.isEmpty() &&
255 (avmedia::MediaWindow::isMediaURL(sURL, sReferer))
258 // If the file type is supported depends on the OS, so...
259 // I think we can the following ones:
260 // a) look for given extension of url to map our type decision HARD CODED!!!
261 // b) return preferred type every time... it's easy :-)
262 sTypeName = "wav_Wave_Audio_File";
263 aDescriptor[utl::MediaDescriptor::PROP_TYPENAME()] <<= sTypeName;
264 aDescriptor >> lDescriptor;
267 // Return our decision.
268 return sTypeName;
271 /*-************************************************************************************************************
272 @short call back of sound player
273 @descr Our player call us back to give us some information.
274 We use this information to callback our might existing listener.
276 @seealso method dispatchWithNotification()
277 @return 0 every time... it doesn't matter for us.
278 @threadsafe yes
279 *//*-*************************************************************************************************************/
280 IMPL_LINK_NOARG(SoundHandler, implts_PlayerNotify, Timer *, void)
282 // SAFE {
283 ::osl::ClearableMutexGuard aLock( m_aLock );
285 if (m_xPlayer.is() && m_xPlayer->isPlaying() && m_xPlayer->getMediaTime() < m_xPlayer->getDuration())
287 m_aUpdateIdle.Start();
288 return;
290 m_xPlayer.clear();
292 // We use m_xSelfHold to let us die ... but we must live till real finishing of this method too!!!
293 // So we SHOULD use another "self-holder" temp. to provide that ...
294 css::uno::Reference< css::uno::XInterface > xOperationHold = m_xSelfHold;
295 m_xSelfHold.clear();
297 // notify might existing listener
298 // And forget this listener!
299 // Because the corresponding dispatch was finished.
300 if (m_xListener.is())
302 css::frame::DispatchResultEvent aEvent;
303 if (!m_bError)
304 aEvent.State = css::frame::DispatchResultState::SUCCESS;
305 else
306 aEvent.State = css::frame::DispatchResultState::FAILURE;
307 m_xListener->dispatchFinished(aEvent);
308 m_xListener.clear();
311 // } SAFE
312 //release aLock before end of method at which point xOperationHold goes out of scope and pThis dies
313 aLock.clear();
316 } // namespace framework
319 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
320 com_sun_star_comp_framework_SoundHandler_get_implementation(css::uno::XComponentContext*,
321 css::uno::Sequence<css::uno::Any> const &)
323 return cppu::acquire(new avmedia::SoundHandler);
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */