LibreOffice Module avmedia (master) 1
player.cxx
Go to the documentation of this file.
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 <objbase.h>
21#include <strmif.h>
22#include <control.h>
23#include <uuids.h>
24#include <evcode.h>
25
26#include "player.hxx"
27#include "framegrabber.hxx"
28#include "window.hxx"
31#include <osl/file.hxx>
32#include <rtl/ref.hxx>
33
34constexpr OUStringLiteral AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.Player_DirectX";
35constexpr OUStringLiteral AVMEDIA_WIN_PLAYER_SERVICENAME = u"com.sun.star.media.Player_DirectX";
36
37using namespace ::com::sun::star;
38
39namespace avmedia::win {
40
41static LRESULT CALLBACK MediaPlayerWndProc_2( HWND hWnd,UINT nMsg, WPARAM nPar1, LPARAM nPar2 )
42{
43 Player* pPlayer = reinterpret_cast<Player*>(::GetWindowLongPtrW( hWnd, 0 ));
44 bool bProcessed = true;
45
46 if( pPlayer )
47 {
48 switch( nMsg )
49 {
50 case WM_GRAPHNOTIFY:
51 pPlayer->processEvent();
52 break;
53 default:
54 bProcessed = false;
55 break;
56 }
57 }
58 else
59 bProcessed = false;
60
61 return( bProcessed ? 0 : DefWindowProcW( hWnd, nMsg, nPar1, nPar2 ) );
62}
63
64
67 sal::systools::CoInitializeGuard(COINIT_APARTMENTTHREADED, false,
68 sal::systools::CoInitializeGuard::WhenFailed::NoThrow),
69 mnUnmutedVolume( 0 ),
70 mnFrameWnd( nullptr ),
71 mbMuted( false ),
72 mbLooping( false ),
73 mbAddWindow( true )
74{
75}
76
77
79{
80 if( mnFrameWnd )
81 ::DestroyWindow( mnFrameWnd );
82}
83
84
85void SAL_CALL Player::disposing()
86{
87 ::osl::MutexGuard aGuard(m_aMutex);
88 stop();
89 if( mpME )
90 mpME->SetNotifyWindow( 0, WM_GRAPHNOTIFY, 0);
91}
92
93
94bool Player::create( const OUString& rURL )
95{
96 bool bRet = false;
97
98 if( SUCCEEDED(mpGB.CoCreateInstance(CLSID_FilterGraph, nullptr, CLSCTX_INPROC_SERVER)) )
99 {
100 // Don't use the overlay mixer on Windows Vista
101 // It disables the desktop composition as soon as RenderFile is called
102 // also causes some other problems: video rendering is not reliable
103
104 // tdf#128057: IGraphBuilder::RenderFile seems to fail to handle file URIs properly when
105 // they contain encoded characters like "%23"; so pass system path in that case instead.
106 OUString aFile(rURL);
107 if (aFile.startsWithIgnoreAsciiCase("file:"))
108 osl::FileBase::getSystemPathFromFileURL(rURL, aFile);
109
110 if( SUCCEEDED( mpGB->RenderFile( o3tl::toW(aFile.getStr()), nullptr ) ) &&
111 mpMC.set(mpGB, sal::systools::COM_QUERY) &&
112 mpME.set(mpGB, sal::systools::COM_QUERY) &&
113 mpMP.set(mpGB, sal::systools::COM_QUERY) )
114 {
115 // Video interfaces
116 mpVW.set(mpGB, sal::systools::COM_QUERY);
117 mpBV.set(mpGB, sal::systools::COM_QUERY);
118
119 // Audio interface
120 mpBA.set(mpGB, sal::systools::COM_QUERY);
121
122 if( mpBA )
123 mpBA->put_Volume( mnUnmutedVolume );
124
125 bRet = true;
126 }
127 }
128
129 if( bRet )
130 maURL = rURL;
131 else
132 maURL.clear();
133
134 return bRet;
135}
136
137
138const IVideoWindow* Player::getVideoWindow() const
139{
140 return mpVW;
141}
142
143
144void Player::setNotifyWnd( HWND nNotifyWnd )
145{
146 mbAddWindow = false;
147 if( mpME )
148 mpME->SetNotifyWindow( reinterpret_cast<OAHWND>(nNotifyWnd), WM_GRAPHNOTIFY, reinterpret_cast< LONG_PTR>( this ) );
149}
150
151
153{
154 long nCode;
155 LONG_PTR nParam1, nParam2;
156
157 while( mpME && SUCCEEDED( mpME->GetEvent( &nCode, &nParam1, &nParam2, 0 ) ) )
158 {
159 if( EC_COMPLETE == nCode )
160 {
161 if( mbLooping )
162 {
163 setMediaTime( 0.0 );
164 start();
165 }
166 else
167 {
169 stop();
170 }
171 }
172
173 mpME->FreeEventParams( nCode, nParam1, nParam2 );
174 }
175}
176
177
178void SAL_CALL Player::start( )
179{
180 ::osl::MutexGuard aGuard(m_aMutex);
181 if( mpMC )
182 {
183 if ( mbAddWindow )
184 {
185 static WNDCLASSW* mpWndClass = nullptr;
186 if ( !mpWndClass )
187 {
188 mpWndClass = new WNDCLASSW;
189
190 memset( mpWndClass, 0, sizeof( *mpWndClass ) );
191 mpWndClass->hInstance = GetModuleHandleW( nullptr );
192 mpWndClass->cbWndExtra = sizeof( DWORD );
193 mpWndClass->lpfnWndProc = MediaPlayerWndProc_2;
194 mpWndClass->lpszClassName = L"com_sun_star_media_Sound_Player";
195 mpWndClass->hbrBackground = static_cast<HBRUSH>(::GetStockObject( BLACK_BRUSH ));
196 mpWndClass->hCursor = ::LoadCursor( nullptr, IDC_ARROW );
197
198 RegisterClassW( mpWndClass );
199 }
200 if ( !mnFrameWnd )
201 {
202 mnFrameWnd = CreateWindowW( mpWndClass->lpszClassName, nullptr,
203 0,
204 0, 0, 0, 0,
205 nullptr, nullptr, mpWndClass->hInstance, nullptr );
206 if ( mnFrameWnd )
207 {
208 ::ShowWindow(mnFrameWnd, SW_HIDE);
209 SetWindowLongPtrW( mnFrameWnd, 0, reinterpret_cast<LONG_PTR>(this) );
210 // mpVW->put_Owner( (OAHWND) mnFrameWnd );
212 }
213 }
214 }
215
216 mpMC->Run();
217 }
218}
219
220
221void SAL_CALL Player::stop( )
222{
223 ::osl::MutexGuard aGuard(m_aMutex);
224 if( mpMC )
225 mpMC->Stop();
226}
227
228
230{
231 ::osl::MutexGuard aGuard(m_aMutex);
232
233 OAFilterState eFilterState;
234 bool bRet = false;
235
236 if( mpMC && SUCCEEDED( mpMC->GetState( 10, &eFilterState ) ) )
237 bRet = ( State_Running == eFilterState );
238
239 return bRet;
240}
241
242
243double SAL_CALL Player::getDuration( )
244{
245 ::osl::MutexGuard aGuard(m_aMutex);
246
247 REFTIME aRefTime( 0.0 );
248
249 if( mpMP )
250 mpMP->get_Duration( &aRefTime );
251
252 return aRefTime;
253}
254
255
256void SAL_CALL Player::setMediaTime( double fTime )
257{
258 ::osl::MutexGuard aGuard(m_aMutex);
259
260 if( mpMP )
261 {
262 const bool bPlaying = isPlaying();
263
264 mpMP->put_CurrentPosition( fTime );
265
266 if( !bPlaying && mpMC )
267 mpMC->StopWhenReady();
268 }
269}
270
271
272double SAL_CALL Player::getMediaTime( )
273{
274 ::osl::MutexGuard aGuard(m_aMutex);
275
276 REFTIME aRefTime( 0.0 );
277
278 if( mpMP )
279 mpMP->get_CurrentPosition( &aRefTime );
280
281 return aRefTime;
282}
283
284
286{
287 ::osl::MutexGuard aGuard(m_aMutex);
288
289 mbLooping = bSet;
290}
291
292
294{
295 ::osl::MutexGuard aGuard(m_aMutex);
296
297 return mbLooping;
298}
299
300
301void SAL_CALL Player::setMute( sal_Bool bSet )
302{
303 ::osl::MutexGuard aGuard(m_aMutex);
304
305 if (mpBA && (mbMuted != static_cast<bool>(bSet)))
306 {
307 mbMuted = bSet;
308 mpBA->put_Volume( mbMuted ? -10000 : mnUnmutedVolume );
309 }
310}
311
312
314{
315 ::osl::MutexGuard aGuard(m_aMutex);
316
317 return mbMuted;
318}
319
320
321void SAL_CALL Player::setVolumeDB( sal_Int16 nVolumeDB )
322{
323 ::osl::MutexGuard aGuard(m_aMutex);
324
325 mnUnmutedVolume = static_cast< long >( nVolumeDB ) * 100;
326
327 if( !mbMuted && mpBA )
328 mpBA->put_Volume( mnUnmutedVolume );
329}
330
331
332sal_Int16 SAL_CALL Player::getVolumeDB( )
333{
334 ::osl::MutexGuard aGuard(m_aMutex);
335
336 return static_cast< sal_Int16 >( mnUnmutedVolume / 100 );
337}
338
339
341{
342 ::osl::MutexGuard aGuard(m_aMutex);
343
344 awt::Size aSize( 0, 0 );
345
346 if( mpBV )
347 {
348 long nWidth = 0, nHeight = 0;
349
350 mpBV->GetVideoSize( &nWidth, &nHeight );
351 aSize.Width = nWidth;
352 aSize.Height = nHeight;
353 }
354
355 return aSize;
356}
357
358
359uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( const uno::Sequence< uno::Any >& aArguments )
360{
361 ::osl::MutexGuard aGuard(m_aMutex);
362
363 uno::Reference< ::media::XPlayerWindow > xRet;
364 awt::Size aSize( getPreferredPlayerWindowSize() );
365
366 if( mpVW && aSize.Width > 0 && aSize.Height > 0 )
367 {
368 rtl::Reference<::avmedia::win::Window> pWindow = new ::avmedia::win::Window( *this );
369
370 xRet = pWindow;
371
372 if( !pWindow->create( aArguments ) )
373 xRet.clear();
374 }
375
376 return xRet;
377}
378
379
380uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber( )
381{
382 uno::Reference< media::XFrameGrabber > xRet;
383
384 if( !maURL.isEmpty() )
385 {
387
388 xRet = pGrabber;
389
390 if( !pGrabber->create( maURL ) )
391 xRet.clear();
392 }
393
394 return xRet;
395}
396
397
399{
401}
402
403
404sal_Bool SAL_CALL Player::supportsService( const OUString& ServiceName )
405{
407}
408
409
410uno::Sequence< OUString > SAL_CALL Player::getSupportedServiceNames( )
411{
413}
414
415} // namespace avmedia::win
416
417
418/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal::systools::COMReference< IGraphBuilder > mpGB
Definition: win/player.hxx:97
virtual void SAL_CALL start() override
Definition: player.cxx:178
virtual void SAL_CALL setVolumeDB(sal_Int16 nVolumeDB) override
Definition: player.cxx:321
virtual void SAL_CALL setPlaybackLoop(sal_Bool bSet) override
Definition: player.cxx:285
sal::systools::COMReference< IBasicAudio > mpBA
Definition: win/player.hxx:101
virtual sal_Bool SAL_CALL isMute() override
Definition: player.cxx:313
virtual double SAL_CALL getDuration() override
Definition: player.cxx:243
sal::systools::COMReference< IVideoWindow > mpVW
Definition: win/player.hxx:103
bool create(const OUString &rURL)
Definition: player.cxx:94
virtual sal_Bool SAL_CALL isPlaybackLoop() override
Definition: player.cxx:293
virtual double SAL_CALL getMediaTime() override
Definition: player.cxx:272
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: player.cxx:404
virtual OUString SAL_CALL getImplementationName() override
Definition: player.cxx:398
virtual void SAL_CALL stop() override
Definition: player.cxx:221
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: player.cxx:410
~Player() override
Definition: player.cxx:78
virtual void SAL_CALL setMediaTime(double fTime) override
Definition: player.cxx:256
void setNotifyWnd(HWND nNotifyWnd)
Definition: player.cxx:144
virtual void SAL_CALL disposing() override
Definition: player.cxx:85
virtual css::uno::Reference< css::media::XFrameGrabber > SAL_CALL createFrameGrabber() override
Definition: player.cxx:380
sal::systools::COMReference< IMediaPosition > mpMP
Definition: win/player.hxx:100
const IVideoWindow * getVideoWindow() const
Definition: player.cxx:138
virtual css::uno::Reference< css::media::XPlayerWindow > SAL_CALL createPlayerWindow(const css::uno::Sequence< css::uno::Any > &aArguments) override
sal::systools::COMReference< IBasicVideo > mpBV
Definition: win/player.hxx:102
sal::systools::COMReference< IMediaControl > mpMC
Definition: win/player.hxx:98
virtual void SAL_CALL setMute(sal_Bool bSet) override
Definition: player.cxx:301
virtual sal_Bool SAL_CALL isPlaying() override
Definition: player.cxx:229
virtual css::awt::Size SAL_CALL getPreferredPlayerWindowSize() override
Definition: player.cxx:340
virtual sal_Int16 SAL_CALL getVolumeDB() override
Definition: player.cxx:332
sal::systools::COMReference< IMediaEventEx > mpME
Definition: win/player.hxx:99
mutable::osl::Mutex m_aMutex
float u
#define WM_GRAPHNOTIFY
Definition: gstcommon.hxx:41
std::mutex m_aMutex
static LRESULT CALLBACK MediaPlayerWndProc_2(HWND hWnd, UINT nMsg, WPARAM nPar1, LPARAM nPar2)
Definition: player.cxx:41
::cppu::WeakComponentImplHelper< css::media::XPlayer, css::lang::XServiceInfo > Player_BASE
Definition: win/player.hxx:50
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
#define CALLBACK
constexpr OUStringLiteral AVMEDIA_WIN_PLAYER_SERVICENAME
Definition: player.cxx:35
constexpr OUStringLiteral AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME
Definition: player.cxx:34
unsigned char sal_Bool