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