1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "mediawindow_impl.hxx"
25 #include "mediaevent_impl.hxx"
26 #include "mediamisc.hxx"
27 #include "mediawindow.hrc"
28 #include "helpids.hrc"
29 
30 #include <algorithm>
31 #include <cmath>
32 #include <osl/mutex.hxx>
33 #include <tools/time.hxx>
34 #include <vcl/svapp.hxx>
35 
36 #ifndef _COM_SUN_STAR_AWT_SYSTEMPOINTER_HDL_
37 #include <com/sun/star/awt/SystemPointer.hdl>
38 #endif
39 #ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HDL_
40 #include <com/sun/star/lang/XComponent.hdl>
41 #endif
42 
43 #define AVMEDIA_TOOLBOXITEM_PREV	0x0001
44 #define AVMEDIA_TOOLBOXITEM_PLAY 	0x0002
45 #define AVMEDIA_TOOLBOXITEM_PAUSE 	0x0004
46 #define AVMEDIA_TOOLBOXITEM_STOP 	0x0008
47 #define AVMEDIA_TOOLBOXITEM_NEXT 	0x0010
48 #define AVMEDIA_TOOLBOXITEM_MUTE	0x0100
49 
50 #define AVMEDIA_FFW_PLAYRATE		4
51 
52 using namespace ::com::sun::star;
53 
54 namespace avmedia { namespace priv {
55 
56 // ----------------------
57 // - MediaWindowControl -
58 // ----------------------
59 
MediaWindowControl(Window * pParent)60 MediaWindowControl::MediaWindowControl( Window* pParent ) :
61 	MediaControl( pParent, MEDIACONTROLSTYLE_MULTILINE )
62 {
63 }
64 
65 // ---------------------------------------------------------------------
66 
~MediaWindowControl()67 MediaWindowControl::~MediaWindowControl()
68 {
69 }
70 
71 // ---------------------------------------------------------------------
72 
update()73 void MediaWindowControl::update()
74 {
75 	MediaItem aItem;
76 
77 	static_cast< MediaWindowImpl* >( GetParent() )->updateMediaItem( aItem );
78 	setState( aItem );
79 }
80 
81 // ---------------------------------------------------------------------
82 
execute(const MediaItem & rItem)83 void  MediaWindowControl::execute( const MediaItem& rItem )
84 {
85 	static_cast< MediaWindowImpl* >( GetParent() )->executeMediaItem( rItem );
86 }
87 
88 // --------------------
89 // - MediaChildWindow -
90 // --------------------
91 
MediaChildWindow(Window * pParent)92 MediaChildWindow::MediaChildWindow( Window* pParent ) :
93 	SystemChildWindow( pParent, WB_CLIPCHILDREN )
94 {
95 }
96 
97 // ---------------------------------------------------------------------
98 
~MediaChildWindow()99 MediaChildWindow::~MediaChildWindow()
100 {
101 }
102 
103 // ---------------------------------------------------------------------
104 
MouseMove(const MouseEvent & rMEvt)105 void MediaChildWindow::MouseMove( const MouseEvent& rMEvt )
106 {
107 	const MouseEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ),
108 								  		rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), rMEvt.GetModifier() );
109 
110 	SystemChildWindow::MouseMove( rMEvt );
111 	GetParent()->MouseMove( aTransformedEvent );
112 }
113 
114 // ---------------------------------------------------------------------
115 
MouseButtonDown(const MouseEvent & rMEvt)116 void MediaChildWindow::MouseButtonDown( const MouseEvent& rMEvt )
117 {
118 	const MouseEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ),
119 								  		rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), rMEvt.GetModifier() );
120 
121 	SystemChildWindow::MouseButtonDown( rMEvt );
122 	GetParent()->MouseButtonDown( aTransformedEvent );
123 }
124 
125 // ---------------------------------------------------------------------
126 
MouseButtonUp(const MouseEvent & rMEvt)127 void MediaChildWindow::MouseButtonUp( const MouseEvent& rMEvt )
128 {
129 	const MouseEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ),
130 								  		rMEvt.GetClicks(), rMEvt.GetMode(), rMEvt.GetButtons(), rMEvt.GetModifier() );
131 
132 	SystemChildWindow::MouseButtonUp( rMEvt );
133 	GetParent()->MouseButtonUp( aTransformedEvent );
134 }
135 
136 // ---------------------------------------------------------------------
137 
KeyInput(const KeyEvent & rKEvt)138 void MediaChildWindow::KeyInput( const KeyEvent& rKEvt )
139 {
140 	SystemChildWindow::KeyInput( rKEvt );
141 	GetParent()->KeyInput( rKEvt );
142 }
143 
144 // ---------------------------------------------------------------------
145 
KeyUp(const KeyEvent & rKEvt)146 void MediaChildWindow::KeyUp( const KeyEvent& rKEvt )
147 {
148 	SystemChildWindow::KeyUp( rKEvt );
149 	GetParent()->KeyUp( rKEvt );
150 }
151 
152 // ---------------------------------------------------------------------
153 
Command(const CommandEvent & rCEvt)154 void MediaChildWindow::Command( const CommandEvent& rCEvt )
155 {
156 	const CommandEvent aTransformedEvent( GetParent()->ScreenToOutputPixel( OutputToScreenPixel( rCEvt.GetMousePosPixel() ) ),
157 								  		  rCEvt.GetCommand(), rCEvt.IsMouseEvent(), rCEvt.GetData() );
158 
159 	SystemChildWindow::Command( rCEvt );
160 	GetParent()->Command( aTransformedEvent );
161 }
162 
163 // ----------------------
164 // - MediaWindowImpl -
165 // ----------------------
166 
MediaWindowImpl(Window * pParent,MediaWindow * pMediaWindow,bool bInternalMediaControl)167 MediaWindowImpl::MediaWindowImpl( Window* pParent, MediaWindow* pMediaWindow, bool bInternalMediaControl ) :
168     Control( pParent ),
169     MediaWindowBaseImpl( pMediaWindow ),
170     DropTargetHelper( this ),
171     DragSourceHelper( this ),
172     mxEventsIf( static_cast< ::cppu::OWeakObject* >( mpEvents = new MediaEventListenersImpl( maChildWindow ) ) ),
173 	maChildWindow( this ),
174 	mpMediaWindowControl( bInternalMediaControl ? new MediaWindowControl( this ) : NULL ),
175 	mpEmptyBmpEx( NULL ),
176 	mpAudioBmpEx( NULL )
177 {
178     maChildWindow.SetBackground( Color( COL_BLACK ) );
179 	maChildWindow.SetHelpId( HID_AVMEDIA_PLAYERWINDOW );
180 	maChildWindow.Hide();
181 
182 	if( mpMediaWindowControl )
183 	{
184 		mpMediaWindowControl->SetSizePixel( mpMediaWindowControl->getMinSizePixel() );
185 		mpMediaWindowControl->Show();
186 	}
187 }
188 
189 // ---------------------------------------------------------------------
190 
~MediaWindowImpl()191 MediaWindowImpl::~MediaWindowImpl()
192 {
193 	delete mpEmptyBmpEx;
194 	delete mpAudioBmpEx;
195 	delete mpMediaWindowControl;
196 }
197 
198 // ---------------------------------------------------------------------
199 
cleanUp()200 void MediaWindowImpl::cleanUp()
201 {
202     uno::Reference< media::XPlayerWindow > xPlayerWindow( getPlayerWindow() );
203 
204     mpEvents->cleanUp();
205 
206     if( xPlayerWindow.is() )
207     {
208         xPlayerWindow->removeKeyListener( uno::Reference< awt::XKeyListener >( mxEventsIf, uno::UNO_QUERY ) );
209         xPlayerWindow->removeMouseListener( uno::Reference< awt::XMouseListener >( mxEventsIf, uno::UNO_QUERY ) );
210         xPlayerWindow->removeMouseMotionListener( uno::Reference< awt::XMouseMotionListener >( mxEventsIf, uno::UNO_QUERY ) );
211 
212 		uno::Reference< lang::XComponent > xComponent( xPlayerWindow, uno::UNO_QUERY );
213 
214 		if( xComponent.is() )
215 			xComponent->dispose();
216 
217 		setPlayerWindow( NULL );
218     }
219 
220     MediaWindowBaseImpl::cleanUp();
221 }
222 
223 // ---------------------------------------------------------------------
224 
onURLChanged()225 void MediaWindowImpl::onURLChanged()
226 {
227     if( getPlayer().is() )
228     {
229         uno::Reference< media::XPlayerWindow > xPlayerWindow;
230 
231         const Point         aPoint;
232 		const Size          aSize( maChildWindow.GetSizePixel() );
233         const sal_IntPtr    nWndHandle = (sal_IntPtr) maChildWindow.GetParentWindowHandle( isMediaWindowJavaBased() );
234 
235         try
236         {
237             if( nWndHandle != 0 )
238             {
239                 uno::Sequence< uno::Any > aArgs( 3 );
240 
241                 aArgs[ 0 ] = uno::makeAny( nWndHandle );
242                 aArgs[ 1 ] = uno::makeAny( awt::Rectangle( aPoint.X(), aPoint.Y(), aSize.Width(), aSize.Height() ) );
243                 aArgs[ 2 ] = uno::makeAny( reinterpret_cast< sal_IntPtr >( &maChildWindow ) );
244 
245                 xPlayerWindow = getPlayer()->createPlayerWindow( aArgs );
246             }
247         }
248         catch( uno::RuntimeException )
249         {
250             // happens eg, on MacOSX where Java frames cannot be created from X11 window handles
251         }
252 
253         setPlayerWindow( xPlayerWindow );
254 
255         if( xPlayerWindow.is() )
256         {
257             xPlayerWindow->addKeyListener( uno::Reference< awt::XKeyListener >( mxEventsIf, uno::UNO_QUERY ) );
258             xPlayerWindow->addMouseListener( uno::Reference< awt::XMouseListener >( mxEventsIf, uno::UNO_QUERY ) );
259             xPlayerWindow->addMouseMotionListener( uno::Reference< awt::XMouseMotionListener >( mxEventsIf, uno::UNO_QUERY ) );
260             xPlayerWindow->addFocusListener( uno::Reference< awt::XFocusListener >( mxEventsIf, uno::UNO_QUERY ) );
261         }
262 	}
263 	else
264         setPlayerWindow( NULL );
265 
266 	if( getPlayerWindow().is() )
267 		maChildWindow.Show();
268 	else
269 		maChildWindow.Hide();
270 
271 	if( mpMediaWindowControl )
272 	{
273 		MediaItem aItem;
274 
275 		updateMediaItem( aItem );
276 		mpMediaWindowControl->setState( aItem );
277 	}
278 }
279 
280 // ---------------------------------------------------------------------
281 
update()282 void MediaWindowImpl::update()
283 {
284     uno::Reference< media::XPlayerWindow > xPlayerWindow( getPlayerWindow() );
285 
286 	if( xPlayerWindow.is() )
287         xPlayerWindow->update();
288 }
289 
290 // ---------------------------------------------------------------------
291 
setPosSize(const Rectangle & rRect)292 void MediaWindowImpl::setPosSize( const Rectangle& rRect )
293 {
294     SetPosSizePixel( rRect.TopLeft(), rRect.GetSize() );
295 }
296 
297 // ---------------------------------------------------------------------
298 
setPointer(const Pointer & rPointer)299 void MediaWindowImpl::setPointer( const Pointer& rPointer )
300 {
301     uno::Reference< media::XPlayerWindow >	xPlayerWindow( getPlayerWindow() );
302 
303 	SetPointer( rPointer );
304 	maChildWindow.SetPointer( rPointer );
305 
306 	if( xPlayerWindow.is() )
307 	{
308     	long nPointer;
309 
310 		switch( rPointer.GetStyle() )
311 		{
312 			case( POINTER_CROSS ): nPointer = awt::SystemPointer::CROSS; break;
313 			case( POINTER_HAND ): nPointer = awt::SystemPointer::HAND; break;
314 			case( POINTER_MOVE ): nPointer = awt::SystemPointer::MOVE; break;
315 			case( POINTER_WAIT ): nPointer = awt::SystemPointer::WAIT; break;
316 
317 			default: nPointer = awt::SystemPointer::ARROW; break;
318 		}
319 
320 		xPlayerWindow->setPointerType( nPointer );
321 	}
322 }
323 
324 // ---------------------------------------------------------------------
325 
getPointer() const326 const Pointer& MediaWindowImpl::getPointer() const
327 {
328 	return GetPointer();
329 }
330 
331 // ---------------------------------------------------------------------
332 
hasInternalMediaControl() const333 bool MediaWindowImpl::hasInternalMediaControl() const
334 {
335 	return( mpMediaWindowControl != NULL );
336 }
337 
338 // ---------------------------------------------------------------------
339 
Resize()340 void MediaWindowImpl::Resize()
341 {
342     uno::Reference< media::XPlayerWindow >	xPlayerWindow( getPlayerWindow() );
343     const Size								aCurSize( GetOutputSizePixel() );
344 	const sal_Int32							nOffset( mpMediaWindowControl ? AVMEDIA_CONTROLOFFSET : 0 );
345 	Size 									aPlayerWindowSize( aCurSize.Width() - ( nOffset << 1 ),
346 															   aCurSize.Height() - ( nOffset << 1 ) );
347 
348 	if( mpMediaWindowControl )
349 	{
350 		const sal_Int32	nControlHeight = mpMediaWindowControl->GetSizePixel().Height();
351 		const sal_Int32	nControlY = ::std::max( aCurSize.Height() - nControlHeight - nOffset, 0L );
352 
353 		aPlayerWindowSize.Height() = ( nControlY - ( nOffset << 1 ) );
354 		mpMediaWindowControl->SetPosSizePixel( Point( nOffset, nControlY ), Size( aCurSize.Width() - ( nOffset << 1 ), nControlHeight ) );
355 	}
356 
357 	if( xPlayerWindow.is() )
358 		xPlayerWindow->setPosSize( 0, 0, aPlayerWindowSize.Width(), aPlayerWindowSize.Height(), 0 );
359 
360 	maChildWindow.SetPosSizePixel( Point( nOffset, nOffset ), aPlayerWindowSize );
361 }
362 
363 // ---------------------------------------------------------------------
364 
StateChanged(StateChangedType eType)365 void MediaWindowImpl::StateChanged( StateChangedType eType )
366 {
367     uno::Reference< media::XPlayerWindow > xPlayerWindow( getPlayerWindow() );
368 
369     if( xPlayerWindow.is() )
370     {
371         // stop playing when going disabled or hidden
372         switch( eType )
373         {
374             case STATE_CHANGE_VISIBLE:
375             {
376                 stopPlayingInternal( !IsVisible() );
377                 xPlayerWindow->setVisible( IsVisible() );
378             }
379             break;
380 
381             case STATE_CHANGE_ENABLE:
382             {
383                 stopPlayingInternal( !IsEnabled() );
384                 xPlayerWindow->setEnable( IsEnabled() );
385             }
386             break;
387 
388             default:
389             break;
390         }
391     }
392 }
393 
394 // ---------------------------------------------------------------------
395 
Paint(const Rectangle &)396 void MediaWindowImpl::Paint( const Rectangle& )
397 {
398 	BitmapEx* pLogo = NULL;
399 
400 	if( !getPlayer().is() )
401 	{
402 		if( !mpEmptyBmpEx )
403 			mpEmptyBmpEx = new BitmapEx( AVMEDIA_RESID( AVMEDIA_BMP_EMPTYLOGO ) );
404 
405 		pLogo = mpEmptyBmpEx;
406 	}
407 	else if( !getPlayerWindow().is() )
408 	{
409 		if( !mpAudioBmpEx )
410 			mpAudioBmpEx = new BitmapEx( AVMEDIA_RESID( AVMEDIA_BMP_AUDIOLOGO ) );
411 
412 		pLogo = mpAudioBmpEx;
413 	}
414 
415 	const Point     aBasePos( maChildWindow.GetPosPixel() );
416 	const Rectangle aVideoRect( aBasePos, maChildWindow.GetSizePixel() );
417 
418 	if( pLogo && !pLogo->IsEmpty() && ( aVideoRect.GetWidth() > 0 ) && ( aVideoRect.GetHeight() > 0 ) )
419 	{
420 		Size	    aLogoSize( pLogo->GetSizePixel() );
421 		const Color	aBackgroundColor( 67, 67, 67 );
422 
423 		SetLineColor( aBackgroundColor );
424 		SetFillColor( aBackgroundColor );
425 		DrawRect( aVideoRect );
426 
427 		if( ( aLogoSize.Width() > aVideoRect.GetWidth() || aLogoSize.Height() > aVideoRect.GetHeight() ) &&
428 		    ( aLogoSize.Height() > 0 ) )
429 		{
430 		    const double fLogoWH = (double) aLogoSize.Width() / aLogoSize.Height();
431 
432 		    if( fLogoWH < ( (double) aVideoRect.GetWidth() / aVideoRect.GetHeight() ) )
433 		    {
434 			    aLogoSize.Width() = (long) ( aVideoRect.GetHeight() * fLogoWH );
435 			    aLogoSize.Height()= aVideoRect.GetHeight();
436 		    }
437 		    else
438 		    {
439 			    aLogoSize.Width() = aVideoRect.GetWidth();
440 			    aLogoSize.Height()= (long) ( aVideoRect.GetWidth() / fLogoWH );
441 		    }
442 		}
443 
444 		DrawBitmapEx( Point( aBasePos.X() + ( ( aVideoRect.GetWidth() - aLogoSize.Width() ) >> 1 ),
445 							 aBasePos.Y() + ( ( aVideoRect.GetHeight() - aLogoSize.Height() ) >> 1 ) ),
446 					  aLogoSize, *pLogo );
447 	}
448 }
449 
450 // ---------------------------------------------------------------------
451 
GetFocus()452 void MediaWindowImpl::GetFocus()
453 {
454 }
455 
456 // ---------------------------------------------------------------------
457 
MouseMove(const MouseEvent & rMEvt)458 void MediaWindowImpl::MouseMove( const MouseEvent& rMEvt )
459 {
460     MediaWindow* pMediaWindow = getMediaWindow();
461 
462     if( pMediaWindow )
463         pMediaWindow->MouseMove( rMEvt );
464 }
465 
466 // ---------------------------------------------------------------------
467 
MouseButtonDown(const MouseEvent & rMEvt)468 void MediaWindowImpl::MouseButtonDown( const MouseEvent& rMEvt )
469 {
470     MediaWindow* pMediaWindow = getMediaWindow();
471 
472     if( pMediaWindow )
473         pMediaWindow->MouseButtonDown( rMEvt );
474 }
475 
476 // ---------------------------------------------------------------------
477 
MouseButtonUp(const MouseEvent & rMEvt)478 void MediaWindowImpl::MouseButtonUp( const MouseEvent& rMEvt )
479 {
480     MediaWindow* pMediaWindow = getMediaWindow();
481 
482     if( pMediaWindow )
483         pMediaWindow->MouseButtonUp( rMEvt );
484 }
485 
486 // ---------------------------------------------------------------------
487 
KeyInput(const KeyEvent & rKEvt)488 void MediaWindowImpl::KeyInput( const KeyEvent& rKEvt )
489 {
490     MediaWindow* pMediaWindow = getMediaWindow();
491 
492     if( pMediaWindow )
493         pMediaWindow->KeyInput( rKEvt );
494 }
495 
496 // ---------------------------------------------------------------------
497 
KeyUp(const KeyEvent & rKEvt)498 void MediaWindowImpl::KeyUp( const KeyEvent& rKEvt )
499 {
500     MediaWindow* pMediaWindow = getMediaWindow();
501 
502     if( pMediaWindow )
503         pMediaWindow->KeyUp( rKEvt );
504 }
505 
506 // ---------------------------------------------------------------------
507 
Command(const CommandEvent & rCEvt)508 void MediaWindowImpl::Command( const CommandEvent& rCEvt )
509 {
510     MediaWindow* pMediaWindow = getMediaWindow();
511 
512     if( pMediaWindow )
513         pMediaWindow->Command( rCEvt );
514 }
515 
516 // ---------------------------------------------------------------------
517 
AcceptDrop(const AcceptDropEvent & rEvt)518 sal_Int8 MediaWindowImpl::AcceptDrop( const AcceptDropEvent& rEvt )
519 {
520 	MediaWindow* pMediaWindow = getMediaWindow();
521 	return( pMediaWindow ? pMediaWindow->AcceptDrop( rEvt ) : 0 );
522 }
523 
524 // ---------------------------------------------------------------------
525 
ExecuteDrop(const ExecuteDropEvent & rEvt)526 sal_Int8 MediaWindowImpl::ExecuteDrop( const ExecuteDropEvent& rEvt )
527 {
528     MediaWindow* pMediaWindow = getMediaWindow();
529     return( pMediaWindow ? pMediaWindow->ExecuteDrop( rEvt ) : 0 );
530 }
531 
532 // ---------------------------------------------------------------------
533 
StartDrag(sal_Int8 nAction,const Point & rPosPixel)534 void MediaWindowImpl::StartDrag( sal_Int8 nAction, const Point& rPosPixel )
535 {
536     MediaWindow* pMediaWindow = getMediaWindow();
537 
538     if( pMediaWindow )
539         pMediaWindow->StartDrag( nAction, rPosPixel );
540 }
541 
542 } // namespace priv
543 } // namespace avmedia
544