1 /*****************************************************************************
2 * Controller.cpp : Controller for the main interface
3 ****************************************************************************
4 * Copyright (C) 2006-2008 the VideoLAN team
7 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
8 * Ilkka Ollakka <ileoo@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * ( at your option ) any later version.
15 * This program 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 General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
32 #include "components/controller.hpp"
33 #include "components/controller_widget.hpp"
34 #include "components/interface_widgets.hpp"
36 #include "dialogs_provider.hpp" /* Opening Dialogs */
37 #include "input_manager.hpp"
39 #include "util/input_slider.hpp" /* InputSlider */
40 #include "util/customwidgets.hpp" /* qEventToKey */
42 #include <QSpacerItem>
43 #include <QToolButton>
44 #include <QHBoxLayout>
45 #include <QSignalMapper>
48 /**********************************************************************
50 **********************************************************************/
53 * This is an abstract Toolbar/Controller
54 * This has helper to create any toolbar, any buttons and to manage the actions
57 AbstractController::AbstractController( intf_thread_t * _p_i, QWidget *_parent )
63 /* Main action provider */
64 toolbarActionsMapper = new QSignalMapper( this );
65 CONNECT( toolbarActionsMapper, mapped( int ), this, doAction( int ) );
66 CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
69 /* Reemit some signals on status Change to activate some buttons */
70 void AbstractController::setStatus( int status )
72 bool b_hasInput = THEMIM->getIM()->hasInput();
73 /* Activate the interface buttons according to the presence of the input */
74 emit inputExists( b_hasInput );
76 emit inputPlaying( status == PLAYING_S );
78 emit inputIsRecordable( b_hasInput &&
79 var_GetBool( THEMIM->getInput(), "can-record" ) );
82 /* Generic button setup */
83 void AbstractController::setupButton( QAbstractButton *aButton )
85 static QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
86 sizePolicy.setHorizontalStretch( 0 );
87 sizePolicy.setVerticalStretch( 0 );
89 aButton->setSizePolicy( sizePolicy );
90 aButton->setFixedSize( QSize( 26, 26 ) );
91 aButton->setIconSize( QSize( 20, 20 ) );
92 aButton->setFocusPolicy( Qt::NoFocus );
95 /* Open the generic config line for the toolbar, parse it
96 * and create the widgets accordingly */
97 void AbstractController::parseAndCreate( QString config,
98 QBoxLayout *controlLayout )
100 QStringList list = config.split( ";", QString::SkipEmptyParts ) ;
101 for( int i = 0; i < list.size(); i++ )
103 QStringList list2 = list.at( i ).split( "-" );
104 if( list2.size() < 1 )
106 msg_Warn( p_intf, "Parsing error. Report this" );
111 int i_option = WIDGET_NORMAL;
112 buttonType_e i_type = (buttonType_e)list2.at( 0 ).toInt( &ok );
115 msg_Warn( p_intf, "Parsing error 0. Please report this" );
119 if( list2.size() > 1 )
121 i_option = list2.at( 1 ).toInt( &ok );
124 msg_Warn( p_intf, "Parsing error 1. Please report this" );
129 createAndAddWidget( controlLayout, -1, i_type, i_option );
133 void AbstractController::createAndAddWidget( QBoxLayout *controlLayout,
138 /* Special case for SPACERS, who aren't QWidgets */
139 if( i_type == WIDGET_SPACER )
141 controlLayout->insertSpacing( i_index, 16 );
145 if( i_type == WIDGET_SPACER_EXTEND )
147 controlLayout->insertStretch( i_index, 16 );
151 QWidget *widg = createWidget( i_type, i_option );
154 controlLayout->insertWidget( i_index, widg );
158 #define CONNECT_MAP( a ) CONNECT( a, clicked(), toolbarActionsMapper, map() )
159 #define SET_MAPPING( a, b ) toolbarActionsMapper->setMapping( a , b )
160 #define CONNECT_MAP_SET( a, b ) \
163 #define BUTTON_SET_BAR( a_button ) \
164 a_button->setToolTip( tooltipL[button] ); \
165 a_button->setIcon( QIcon( iconL[button] ) );
166 #define BUTTON_SET_BAR2( button, image, tooltip ) \
167 button->setToolTip( tooltip ); \
168 button->setIcon( QIcon( ":/"#image ) );
171 #define ENABLE_ON_VIDEO( a ) \
172 CONNECT( THEMIM->getIM(), voutChanged( bool ), a, setEnabled( bool ) ); \
173 a->setEnabled( THEMIM->getIM()->hasVideo() ); /* TODO: is this necessary? when input is started before the interface? */
175 #define ENABLE_ON_INPUT( a ) \
176 CONNECT( this, inputExists( bool ), a, setEnabled( bool ) ); \
177 a->setEnabled( THEMIM->getIM()->hasInput() ); /* TODO: is this necessary? when input is started before the interface? */
179 QWidget *AbstractController::createWidget( buttonType_e button, int options )
182 bool b_flat = options & WIDGET_FLAT;
183 bool b_big = options & WIDGET_BIG;
184 bool b_shiny = options & WIDGET_SHINY;
186 QWidget *widget = NULL;
190 PlayButton *playButton = new PlayButton;
191 setupButton( playButton );
192 BUTTON_SET_BAR( playButton );
193 CONNECT_MAP_SET( playButton, PLAY_ACTION );
194 CONNECT( this, inputPlaying( bool ),
195 playButton, updateButton( bool ));
200 QToolButton *stopButton = new QToolButton;
201 setupButton( stopButton );
202 CONNECT_MAP_SET( stopButton, STOP_ACTION );
203 BUTTON_SET_BAR( stopButton );
208 QToolButton *openButton = new QToolButton;
209 setupButton( openButton );
210 CONNECT_MAP_SET( openButton, OPEN_ACTION );
211 BUTTON_SET_BAR( openButton );
215 case PREVIOUS_BUTTON:{
216 QToolButton *prevButton = new QToolButton;
217 setupButton( prevButton );
218 CONNECT_MAP_SET( prevButton, PREVIOUS_ACTION );
219 BUTTON_SET_BAR( prevButton );
225 QToolButton *nextButton = new QToolButton;
226 setupButton( nextButton );
227 CONNECT_MAP_SET( nextButton, NEXT_ACTION );
228 BUTTON_SET_BAR( nextButton );
233 QToolButton *slowerButton = new QToolButton;
234 setupButton( slowerButton );
235 CONNECT_MAP_SET( slowerButton, SLOWER_ACTION );
236 BUTTON_SET_BAR( slowerButton );
237 ENABLE_ON_INPUT( slowerButton );
238 widget = slowerButton;
242 QToolButton *fasterButton = new QToolButton;
243 setupButton( fasterButton );
244 CONNECT_MAP_SET( fasterButton, FASTER_ACTION );
245 BUTTON_SET_BAR( fasterButton );
246 ENABLE_ON_INPUT( fasterButton );
247 widget = fasterButton;
251 QToolButton *frameButton = new QToolButton;
252 setupButton( frameButton );
253 CONNECT_MAP_SET( frameButton, FRAME_ACTION );
254 BUTTON_SET_BAR( frameButton );
255 ENABLE_ON_VIDEO( frameButton );
256 widget = frameButton;
259 case FULLSCREEN_BUTTON:{
260 QToolButton *fullscreenButton = new QToolButton;
261 setupButton( fullscreenButton );
262 CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
263 BUTTON_SET_BAR( fullscreenButton );
264 ENABLE_ON_VIDEO( fullscreenButton );
265 widget = fullscreenButton;
268 case DEFULLSCREEN_BUTTON:{
269 QToolButton *fullscreenButton = new QToolButton;
270 setupButton( fullscreenButton );
271 CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
272 BUTTON_SET_BAR( fullscreenButton )
273 ENABLE_ON_VIDEO( fullscreenButton );
274 widget = fullscreenButton;
277 case EXTENDED_BUTTON:{
278 QToolButton *extSettingsButton = new QToolButton;
279 setupButton( extSettingsButton );
280 CONNECT_MAP_SET( extSettingsButton, EXTENDED_ACTION );
281 BUTTON_SET_BAR( extSettingsButton )
282 widget = extSettingsButton;
285 case PLAYLIST_BUTTON:{
286 QToolButton *playlistButton = new QToolButton;
287 setupButton( playlistButton );
288 CONNECT_MAP_SET( playlistButton, PLAYLIST_ACTION );
289 BUTTON_SET_BAR( playlistButton );
290 widget = playlistButton;
293 case SNAPSHOT_BUTTON:{
294 QToolButton *snapshotButton = new QToolButton;
295 setupButton( snapshotButton );
296 CONNECT_MAP_SET( snapshotButton, SNAPSHOT_ACTION );
297 BUTTON_SET_BAR( snapshotButton );
298 ENABLE_ON_VIDEO( snapshotButton );
299 widget = snapshotButton;
303 QToolButton *recordButton = new QToolButton;
304 setupButton( recordButton );
305 CONNECT_MAP_SET( recordButton, RECORD_ACTION );
306 BUTTON_SET_BAR( recordButton );
307 ENABLE_ON_INPUT( recordButton );
308 widget = recordButton;
312 AtoB_Button *ABButton = new AtoB_Button;
313 setupButton( ABButton );
314 BUTTON_SET_BAR( ABButton );
315 ENABLE_ON_INPUT( ABButton );
316 CONNECT_MAP_SET( ABButton, ATOB_ACTION );
317 CONNECT( THEMIM->getIM(), AtoBchanged( bool, bool),
318 ABButton, setIcons( bool, bool ) );
323 InputSlider *slider = new InputSlider( Qt::Horizontal, NULL );
325 /* Update the position when the IM has changed */
326 CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
327 slider, setPosition( float, int, int ) );
328 /* And update the IM, when the position has changed */
329 CONNECT( slider, sliderDragged( float ),
330 THEMIM->getIM(), sliderUpdate( float ) );
335 widget = discFrame();
338 case TELETEXT_BUTTONS:
339 widget = telexFrame();
344 SoundWidget *snd = new SoundWidget( this, p_intf, b_shiny );
350 TimeLabel *timeLabel = new TimeLabel( p_intf );
356 QFrame *line = new QFrame;
357 line->setFrameShape( QFrame::VLine );
358 line->setFrameShadow( QFrame::Raised );
359 line->setLineWidth( 0 );
360 line->setMidLineWidth( 1 );
364 case ADVANCED_CONTROLLER:
366 advControls = new AdvControlsWidget( p_intf, this );
367 widget = advControls;
370 case REVERSE_BUTTON:{
371 QToolButton *reverseButton = new QToolButton;
372 setupButton( reverseButton );
373 CONNECT_MAP_SET( reverseButton, REVERSE_ACTION );
374 BUTTON_SET_BAR( reverseButton );
375 ENABLE_ON_INPUT( reverseButton );
376 widget = reverseButton;
379 case SKIP_BACK_BUTTON: {
380 QToolButton *skipBakButton = new QToolButton;
381 setupButton( skipBakButton );
382 CONNECT_MAP_SET( skipBakButton, SKIP_BACK_ACTION );
383 BUTTON_SET_BAR( skipBakButton );
384 ENABLE_ON_INPUT( skipBakButton );
385 widget = skipBakButton;
388 case SKIP_FW_BUTTON: {
389 QToolButton *skipFwButton = new QToolButton;
390 setupButton( skipFwButton );
391 CONNECT_MAP_SET( skipFwButton, SKIP_FW_ACTION );
392 BUTTON_SET_BAR( skipFwButton );
393 ENABLE_ON_INPUT( skipFwButton );
394 widget = skipFwButton;
398 msg_Warn( p_intf, "This should not happen %i", button );
402 /* Customize Buttons */
403 if( b_flat || b_big )
405 QToolButton *tmpButton = qobject_cast<QToolButton *>(widget);
409 tmpButton->setAutoRaise( b_flat );
412 tmpButton->setFixedSize( QSize( 32, 32 ) );
413 tmpButton->setIconSize( QSize( 26, 26 ) );
420 QWidget *AbstractController::discFrame()
422 /** Disc and Menus handling */
423 QWidget *discFrame = new QWidget( this );
425 QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
426 discLayout->setSpacing( 0 ); discLayout->setMargin( 0 );
428 QToolButton *prevSectionButton = new QToolButton( discFrame );
429 setupButton( prevSectionButton );
430 BUTTON_SET_BAR2( prevSectionButton, dvd_prev,
431 qtr("Previous Chapter/Title" ) );
432 discLayout->addWidget( prevSectionButton );
434 QToolButton *menuButton = new QToolButton( discFrame );
435 setupButton( menuButton );
436 discLayout->addWidget( menuButton );
437 BUTTON_SET_BAR2( menuButton, dvd_menu, qtr( "Menu" ) );
439 QToolButton *nextSectionButton = new QToolButton( discFrame );
440 setupButton( nextSectionButton );
441 discLayout->addWidget( nextSectionButton );
442 BUTTON_SET_BAR2( nextSectionButton, dvd_next,
443 qtr("Next Chapter/Title" ) );
445 /* Change the navigation button display when the IM
446 navigation changes */
447 CONNECT( THEMIM->getIM(), titleChanged( bool ),
448 discFrame, setVisible( bool ) );
449 CONNECT( THEMIM->getIM(), chapterChanged( bool ),
450 menuButton, setVisible( bool ) );
451 /* Changes the IM navigation when triggered on the nav buttons */
452 CONNECT( prevSectionButton, clicked(), THEMIM->getIM(),
454 CONNECT( nextSectionButton, clicked(), THEMIM->getIM(),
456 CONNECT( menuButton, clicked(), THEMIM->getIM(),
462 QWidget *AbstractController::telexFrame()
467 TeletextController *telexFrame = new TeletextController;
468 QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame );
469 telexLayout->setSpacing( 0 ); telexLayout->setMargin( 0 );
470 CONNECT( THEMIM->getIM(), teletextPossible( bool ),
471 telexFrame, setVisible( bool ) );
474 QToolButton *telexOn = new QToolButton;
475 telexFrame->telexOn = telexOn;
476 setupButton( telexOn );
477 BUTTON_SET_BAR2( telexOn, tv, qtr( "Teletext Activation" ) );
478 telexLayout->addWidget( telexOn );
480 /* Teletext Activation and set */
481 CONNECT( telexOn, clicked( bool ),
482 THEMIM->getIM(), activateTeletext( bool ) );
483 CONNECT( THEMIM->getIM(), teletextActivated( bool ),
484 telexFrame, enableTeletextButtons( bool ) );
487 /* Transparency button */
488 QToolButton *telexTransparent = new QToolButton;
489 telexFrame->telexTransparent = telexTransparent;
490 setupButton( telexTransparent );
491 BUTTON_SET_BAR2( telexTransparent, tvtelx,
492 qtr( "Toggle Transparency " ) );
493 telexTransparent->setEnabled( false );
494 telexLayout->addWidget( telexTransparent );
496 /* Transparency change and set */
497 CONNECT( telexTransparent, clicked( bool ),
498 THEMIM->getIM(), telexSetTransparency( bool ) );
499 CONNECT( THEMIM->getIM(), teletextTransparencyActivated( bool ),
500 telexFrame, toggleTeletextTransparency( bool ) );
504 QSpinBox *telexPage = new QSpinBox;
505 telexFrame->telexPage = telexPage;
506 telexPage->setRange( 0, 999 );
507 telexPage->setValue( 100 );
508 telexPage->setAccelerated( true );
509 telexPage->setWrapping( true );
510 telexPage->setAlignment( Qt::AlignRight );
511 telexPage->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
512 telexPage->setEnabled( false );
513 telexLayout->addWidget( telexPage );
515 /* Page change and set */
516 CONNECT( telexPage, valueChanged( int ),
517 THEMIM->getIM(), telexSetPage( int ) );
518 CONNECT( THEMIM->getIM(), newTelexPageSet( int ),
519 telexPage, setValue( int ) );
525 #undef CONNECT_MAP_SET
526 #undef BUTTON_SET_BAR
527 #undef ENABLE_ON_VIDEO
528 #undef ENABLE_ON_INPUT
531 void AbstractController::doAction( int id_action )
537 case PREVIOUS_ACTION:
547 case FULLSCREEN_ACTION:
549 case EXTENDED_ACTION:
550 extSettings(); break;
551 case PLAYLIST_ACTION:
553 case SNAPSHOT_ACTION:
558 THEMIM->getIM()->setAtoB(); break;
563 case SKIP_BACK_ACTION:
564 var_SetInteger( p_intf->p_libvlc, "key-pressed",
565 ACTIONID_JUMP_BACKWARD_SHORT );
568 var_SetInteger( p_intf->p_libvlc, "key-pressed",
569 ACTIONID_JUMP_FORWARD_SHORT );
572 msg_Dbg( p_intf, "Action: %i", id_action );
577 void AbstractController::stop()
582 void AbstractController::play()
584 if( THEPL->current.i_size == 0 )
586 /* The playlist is empty, open a file requester */
587 THEDP->openFileDialog();
590 THEMIM->togglePlayPause();
593 void AbstractController::prev()
598 void AbstractController::next()
605 * This functions toggle the fullscreen mode
606 * If there is no video, it should first activate Visualisations...
607 * This has also to be fixed in enableVideo()
609 void AbstractController::fullscreen()
611 vout_thread_t *p_vout =
612 (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
615 var_SetBool( p_vout, "fullscreen", !var_GetBool( p_vout, "fullscreen" ) );
616 vlc_object_release( p_vout );
620 void AbstractController::snapshot()
622 vout_thread_t *p_vout =
623 (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
626 vout_Control( p_vout, VOUT_SNAPSHOT );
627 vlc_object_release( p_vout );
631 void AbstractController::extSettings()
633 THEDP->extendedDialog();
636 void AbstractController::reverse()
638 THEMIM->getIM()->reverse();
641 void AbstractController::slower()
643 THEMIM->getIM()->slower();
646 void AbstractController::faster()
648 THEMIM->getIM()->faster();
651 void AbstractController::playlist()
653 if( p_intf->p_sys->p_mi ) p_intf->p_sys->p_mi->togglePlaylist();
656 void AbstractController::record()
658 input_thread_t *p_input = THEMIM->getInput();
661 /* This method won't work fine if the stream can't be cut anywhere */
662 const bool b_recording = var_GetBool( p_input, "record" );
663 var_SetBool( p_input, "record", !b_recording );
667 /* 'record' access-filter is not loaded, we open Save dialog */
668 input_item_t *p_item = input_GetItem( p_input );
672 char *psz = input_item_GetURI( p_item );
674 THEDP->streamingDialog( NULL, psz, true );
680 void AbstractController::frame()
682 input_thread_t *p_input = THEMIM->getInput();
684 var_SetVoid( p_input, "frame-next" );
687 #include <QHBoxLayout>
688 /*****************************
689 * DA Control Widget !
690 *****************************/
691 ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
694 AbstractController( _p_i, _parent )
696 setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
698 /* advanced Controls handling */
699 b_advancedVisible = b_advControls;
701 QVBoxLayout *controlLayout = new QVBoxLayout( this );
702 controlLayout->setLayoutMargins( 6, 4, 6, 2, 5 );
703 controlLayout->setSpacing( 0 );
704 QHBoxLayout *controlLayout1 = new QHBoxLayout;
705 controlLayout1->setSpacing( 0 );
707 QString line1 = getSettings()->value( "MainWindow/MainToolbar1",
708 "64;36;37;38;65").toString();
709 parseAndCreate( line1, controlLayout1 );
711 /* QString line2 = QString( "%1-2;%2;%3;%4;%5;%6;%6;%7;%8;%9;%6;%10;%11-4")
712 .arg( PLAY_BUTTON ) .arg( WIDGET_SPACER )
713 .arg( PREVIOUS_BUTTON ) .arg( STOP_BUTTON )
714 .arg( NEXT_BUTTON ) .arg( WIDGET_SPACER )
715 .arg( FULLSCREEN_BUTTON ) .arg( PLAYLIST_BUTTON )
716 .arg( EXTENDED_BUTTON ) .arg( WIDGET_SPACER_EXTEND )
718 msg_Dbg( p_intf, "%s", qtu( line2 )); */
720 QHBoxLayout *controlLayout2 = new QHBoxLayout;
721 controlLayout2->setSpacing( 0 );
722 QString line2 = getSettings()->value( "MainWindow/MainToolbar2",
723 "0-2;64;3;1;4;64;7;10;9;65;34-4" ).toString();
724 parseAndCreate( line2, controlLayout2 );
726 if( !b_advancedVisible && advControls ) advControls->hide();
728 controlLayout->addLayout( controlLayout1 );
729 controlLayout->addLayout( controlLayout2 );
732 ControlsWidget::~ControlsWidget()
735 void ControlsWidget::toggleAdvanced()
737 if( !advControls ) return;
739 if( !b_advancedVisible )
742 b_advancedVisible = true;
747 b_advancedVisible = false;
749 emit advancedControlsToggled( b_advancedVisible );
752 AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) :
753 AbstractController( _p_i, _parent )
755 controlLayout = new QHBoxLayout( this );
756 controlLayout->setMargin( 0 );
757 controlLayout->setSpacing( 0 );
759 /* QString line = QString( "%1;%2;%3").arg( RECORD_BUTTON )
760 .arg( SNAPSHOT_BUTTON )
762 .arg( FRAME_BUTTON ); */
764 QString line = getSettings()->value( "MainWindow/AdvToolbar",
765 "12;11;13;14" ).toString();
766 parseAndCreate( line, controlLayout );
769 InputControlsWidget::InputControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) :
770 AbstractController( _p_i, _parent )
772 controlLayout = new QHBoxLayout( this );
773 controlLayout->setMargin( 0 );
774 controlLayout->setSpacing( 0 );
776 /* QString line = QString( "%1-%2;%3;%4-%2")
777 .arg( SLOWER_BUTTON ).arg( WIDGET_FLAT )
779 .arg( FASTER_BUTTON ); */
780 QString line = getSettings()->value( "MainWindow/InputToolbar",
781 "5-1;33;6-1" ).toString();
782 parseAndCreate( line, controlLayout );
784 /**********************************************************************
785 * Fullscrenn control widget
786 **********************************************************************/
787 FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i )
788 : AbstractController( _p_i )
792 b_mouse_over = false;
793 i_mouse_last_move_x = -1;
794 i_mouse_last_move_y = -1;
795 #if HAVE_TRANSPARENCY
796 b_slow_hide_begin = false;
797 i_slow_hide_timeout = 1;
799 b_fullscreen = false;
805 setWindowFlags( Qt::ToolTip );
806 setMinimumWidth( 600 );
808 setFrameShape( QFrame::StyledPanel );
809 setFrameStyle( QFrame::Sunken );
810 setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
812 QVBoxLayout *controlLayout2 = new QVBoxLayout( this );
813 controlLayout2->setLayoutMargins( 5, 2, 5, 2, 5 );
816 InputControlsWidget *inputC = new InputControlsWidget( p_intf, this );
817 controlLayout2->addWidget( inputC );
820 /* QString line = QString( "%1-2;%2;%3;%4;%5;%2;%6;%2;%7;%2;%8;%9;%10-4")
822 .arg( WIDGET_SPACER )
823 .arg( PREVIOUS_BUTTON )
827 .arg( TELETEXT_BUTTONS )
828 .arg( DEFULLSCREEN_BUTTON )
829 .arg( WIDGET_SPACER_EXTEND )
833 controlLayout = new QHBoxLayout;
834 QString line = getSettings()->value( "MainWindow/FSCtoolbar",
835 "0-2;64;3;1;4;64;36;64;37;64;8;65;35-4;34" ).toString();
836 parseAndCreate( line, controlLayout );
837 controlLayout2->addLayout( controlLayout );
840 p_hideTimer = new QTimer( this );
841 CONNECT( p_hideTimer, timeout(), this, hideFSC() );
842 p_hideTimer->setSingleShot( true );
844 /* slow hiding timer */
845 #if HAVE_TRANSPARENCY
846 p_slowHideTimer = new QTimer( this );
847 CONNECT( p_slowHideTimer, timeout(), this, slowHideFSC() );
850 adjustSize (); /* need to get real width and height for moving */
853 setWindowOpacity( 0.0 );
859 vlc_mutex_init_recursive( &lock );
861 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ), this, setVoutList( vout_thread_t **, int ) );
864 FullscreenControllerWidget::~FullscreenControllerWidget()
866 getSettings()->setValue( "FullScreen/pos", pos() );
867 setVoutList( NULL, 0 );
868 vlc_mutex_destroy( &lock );
872 * Show fullscreen controller
874 void FullscreenControllerWidget::showFSC()
878 int number = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
879 if( number != i_screennumber )
881 msg_Dbg( p_intf, "Calculation fullscreen controllers center");
882 /* screen has changed, calculate new position */
883 QRect screenRes = QApplication::desktop()->screenGeometry(number);
884 QPoint pos = QPoint( screenRes.x() + (screenRes.width() / 2) - (width() / 2),
885 screenRes.y() + screenRes.height() - height());
887 i_screennumber = number;
890 // after quiting and going to fs, we need to call show()
896 setWindowOpacity( 1.0 );
902 #if HAVE_TRANSPARENCY
903 setWindowOpacity( DEFAULT_OPACITY );
908 * Hide fullscreen controller
909 * FIXME: under windows it have to be done by moving out of screen
910 * because hide() doesnt work
912 void FullscreenControllerWidget::hideFSC()
916 setWindowOpacity( 0.0 ); // simulate hidding
923 * Plane to hide fullscreen controller
925 void FullscreenControllerWidget::planHideFSC()
927 vlc_mutex_lock( &lock );
928 int i_timeout = i_hide_timeout;
929 vlc_mutex_unlock( &lock );
931 p_hideTimer->start( i_timeout );
933 #if HAVE_TRANSPARENCY
934 b_slow_hide_begin = true;
935 i_slow_hide_timeout = i_timeout;
936 p_slowHideTimer->start( i_slow_hide_timeout / 2 );
941 * Hidding fullscreen controller slowly
942 * Linux: need composite manager
943 * Windows: it is blinking, so it can be enabled by define TRASPARENCY
945 void FullscreenControllerWidget::slowHideFSC()
947 #if HAVE_TRANSPARENCY
948 if( b_slow_hide_begin )
950 b_slow_hide_begin = false;
952 p_slowHideTimer->stop();
953 /* the last part of time divided to 100 pieces */
954 p_slowHideTimer->start( (int)( i_slow_hide_timeout / 2 / ( windowOpacity() * 100 ) ) );
960 if ( windowOpacity() > 0.0 && !b_fscHidden )
962 if ( windowOpacity() > 0.0 )
965 /* we should use 0.01 because of 100 pieces ^^^
966 but than it cannt be done in time */
967 setWindowOpacity( windowOpacity() - 0.02 );
970 if ( windowOpacity() <= 0.0 )
971 p_slowHideTimer->stop();
978 * events: show, hide, start timer for hidding
980 void FullscreenControllerWidget::customEvent( QEvent *event )
984 switch( event->type() )
986 case FullscreenControlToggle_Type:
987 vlc_mutex_lock( &lock );
989 vlc_mutex_unlock( &lock );
1005 case FullscreenControlShow_Type:
1006 vlc_mutex_lock( &lock );
1007 b_fs = b_fullscreen;
1008 vlc_mutex_unlock( &lock );
1011 if( b_fs && b_fscHidden )
1013 if( b_fs && !isVisible() )
1017 case FullscreenControlHide_Type:
1020 case FullscreenControlPlanHide_Type:
1021 if( !b_mouse_over ) // Only if the mouse is not over FSC
1033 void FullscreenControllerWidget::mouseMoveEvent( QMouseEvent *event )
1035 if ( event->buttons() == Qt::LeftButton )
1037 int i_moveX = event->globalX() - i_mouse_last_x;
1038 int i_moveY = event->globalY() - i_mouse_last_y;
1040 move( x() + i_moveX, y() + i_moveY );
1042 i_mouse_last_x = event->globalX();
1043 i_mouse_last_y = event->globalY();
1049 * store position of cursor
1051 void FullscreenControllerWidget::mousePressEvent( QMouseEvent *event )
1053 i_mouse_last_x = event->globalX();
1054 i_mouse_last_y = event->globalY();
1058 * On mouse go above FSC
1060 void FullscreenControllerWidget::enterEvent( QEvent *event )
1062 b_mouse_over = true;
1064 p_hideTimer->stop();
1065 #if HAVE_TRANSPARENCY
1066 p_slowHideTimer->stop();
1072 * On mouse go out from FSC
1074 void FullscreenControllerWidget::leaveEvent( QEvent *event )
1078 b_mouse_over = false;
1083 * When you get pressed key, send it to video output
1084 * FIXME: clearing focus by clearFocus() to not getting
1085 * key press events didnt work
1087 void FullscreenControllerWidget::keyPressEvent( QKeyEvent *event )
1089 int i_vlck = qtEventToVLCKey( event );
1092 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1100 static int FullscreenControllerWidgetFullscreenChanged( vlc_object_t *vlc_object,
1101 const char *variable, vlc_value_t old_val,
1102 vlc_value_t new_val, void *data )
1104 vout_thread_t *p_vout = (vout_thread_t *) vlc_object;
1106 msg_Dbg( p_vout, "Qt4: Fullscreen state changed" );
1107 FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
1109 p_fs->fullscreenChanged( p_vout, new_val.b_bool, var_GetInteger( p_vout, "mouse-hide-timeout" ) );
1114 static int FullscreenControllerWidgetMouseMoved( vlc_object_t *vlc_object, const char *variable,
1115 vlc_value_t old_val, vlc_value_t new_val,
1118 vout_thread_t *p_vout = (vout_thread_t *)vlc_object;
1119 FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
1121 /* Get the value from the Vout - Trust the vout more than Qt */
1122 const int i_mousex = var_GetInteger( p_vout, "mouse-x" );
1123 const int i_mousey = var_GetInteger( p_vout, "mouse-y" );
1125 p_fs->mouseChanged( p_vout, i_mousex, i_mousey );
1131 * It is call to update the list of vout handled by the fullscreen controller
1133 void FullscreenControllerWidget::setVoutList( vout_thread_t **pp_vout, int i_vout )
1135 QList<vout_thread_t*> del;
1136 QList<vout_thread_t*> add;
1138 QList<vout_thread_t*> set;
1141 for( int i = 0; i < i_vout; i++ )
1144 /* Vout to remove */
1145 vlc_mutex_lock( &lock );
1146 foreach( vout_thread_t *p_vout, vout )
1148 if( !set.contains( p_vout ) )
1151 vlc_mutex_unlock( &lock );
1153 foreach( vout_thread_t *p_vout, del )
1155 var_DelCallback( p_vout, "fullscreen",
1156 FullscreenControllerWidgetFullscreenChanged, this );
1157 vlc_mutex_lock( &lock );
1158 fullscreenChanged( p_vout, false, 0 );
1159 vout.removeAll( p_vout );
1160 vlc_mutex_unlock( &lock );
1164 vlc_mutex_lock( &lock );
1165 foreach( vout_thread_t *p_vout, set )
1167 if( !vout.contains( p_vout ) )
1170 vlc_mutex_unlock( &lock );
1172 foreach( vout_thread_t *p_vout, add )
1174 vlc_object_hold( (vlc_object_t*)p_vout );
1176 vlc_mutex_lock( &lock );
1177 vout.append( p_vout );
1178 var_AddCallback( p_vout, "fullscreen",
1179 FullscreenControllerWidgetFullscreenChanged, this );
1180 /* I miss a add and fire */
1181 fullscreenChanged( p_vout, var_GetBool( p_vout, "fullscreen" ),
1182 var_GetInteger( p_vout, "mouse-hide-timeout" ) );
1183 vlc_mutex_unlock( &lock );
1187 * Register and unregister callback for mouse moving
1189 void FullscreenControllerWidget::fullscreenChanged( vout_thread_t *p_vout,
1190 bool b_fs, int i_timeout )
1192 /* FIXME - multiple vout (ie multiple mouse position ?) and thread safety if multiple vout ? */
1193 msg_Dbg( p_vout, "Qt: Entering Fullscreen" );
1195 vlc_mutex_lock( &lock );
1196 /* Entering fullscreen, register callback */
1197 if( b_fs && !b_fullscreen )
1199 b_fullscreen = true;
1200 i_hide_timeout = i_timeout;
1201 var_AddCallback( p_vout, "mouse-moved",
1202 FullscreenControllerWidgetMouseMoved, this );
1204 /* Quitting fullscreen, unregistering callback */
1205 else if( !b_fs && b_fullscreen )
1207 b_fullscreen = false;
1208 i_hide_timeout = i_timeout;
1209 var_DelCallback( p_vout, "mouse-moved",
1210 FullscreenControllerWidgetMouseMoved, this );
1212 /* Force fs hidding */
1213 IMEvent *eHide = new IMEvent( FullscreenControlHide_Type, 0 );
1214 QApplication::postEvent( this, static_cast<QEvent *>(eHide) );
1216 vlc_mutex_unlock( &lock );
1219 * Mouse change callback (show/hide the controller on mouse movement)
1221 void FullscreenControllerWidget::mouseChanged( vout_thread_t *p_vout, int i_mousex, int i_mousey )
1225 /* FIXME - multiple vout (ie multiple mouse position ?) and thread safety if multiple vout ? */
1228 if( ( i_mouse_last_move_x == -1 || i_mouse_last_move_y == -1 ) ||
1229 ( abs( i_mouse_last_move_x - i_mousex ) > 2 ||
1230 abs( i_mouse_last_move_y - i_mousey ) > 2 ) )
1232 i_mouse_last_move_x = i_mousex;
1233 i_mouse_last_move_y = i_mousey;
1240 IMEvent *eShow = new IMEvent( FullscreenControlShow_Type, 0 );
1241 QApplication::postEvent( this, static_cast<QEvent *>(eShow) );
1243 /* Plan hide event */
1244 IMEvent *eHide = new IMEvent( FullscreenControlPlanHide_Type, 0 );
1245 QApplication::postEvent( this, static_cast<QEvent *>(eHide) );