1 /*****************************************************************************
2 * Controller.cpp : Controller for the main interface
3 ****************************************************************************
4 * Copyright ( C ) 2006-2008 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Jean-Baptiste Kempf <jb@videolan.org>
9 * Rafaël Carré <funman@videolanorg>
10 * Ilkka Ollakka <ileoo@videolan.org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * ( at your option ) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
33 #include "dialogs_provider.hpp"
34 #include "components/interface_widgets.hpp"
35 #include "main_interface.hpp"
36 #include "input_manager.hpp"
38 #include "util/input_slider.hpp"
39 #include "util/customwidgets.hpp"
42 #include <QSpacerItem>
44 #include <QToolButton>
45 #include <QHBoxLayout>
48 #include <QResizeEvent>
50 #include <QSignalMapper>
53 /**********************************************************************
55 **********************************************************************/
58 * This is an abstract Toolbar/Controller
59 * This has helper to create any toolbar, any buttons and to manage the actions
62 AbstractController::AbstractController( intf_thread_t * _p_i, QWidget *_parent )
68 /* Main action provider */
69 toolbarActionsMapper = new QSignalMapper( this );
70 CONNECT( toolbarActionsMapper, mapped( int ), this, doAction( int ) );
71 CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
74 /* Reemit some signals on status Change to activate some buttons */
75 void AbstractController::setStatus( int status )
77 bool b_hasInput = THEMIM->getIM()->hasInput();
78 /* Activate the interface buttons according to the presence of the input */
79 emit inputExists( b_hasInput );
81 emit inputPlaying( status == PLAYING_S );
83 emit inputIsRecordable( b_hasInput &&
84 var_GetBool( THEMIM->getInput(), "can-record" ) );
87 /* Generic button setup */
88 void AbstractController::setupButton( QAbstractButton *aButton )
90 static QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
91 sizePolicy.setHorizontalStretch( 0 );
92 sizePolicy.setVerticalStretch( 0 );
94 aButton->setSizePolicy( sizePolicy );
95 aButton->setFixedSize( QSize( 26, 26 ) );
96 aButton->setIconSize( QSize( 20, 20 ) );
97 aButton->setFocusPolicy( Qt::NoFocus );
100 /* Open the generic config line for the toolbar, parse it
101 * and create the widgets accordingly */
102 void AbstractController::parseAndCreate( QString config,
103 QBoxLayout *controlLayout )
105 QStringList list = config.split( ";", QString::SkipEmptyParts ) ;
106 for( int i = 0; i < list.size(); i++ )
108 QStringList list2 = list.at( i ).split( "-" );
109 if( list2.size() < 1 )
111 msg_Warn( p_intf, "Parsing error. Report this" );
116 int i_option = WIDGET_NORMAL;
117 buttonType_e i_type = (buttonType_e)list2.at( 0 ).toInt( &ok );
120 msg_Warn( p_intf, "Parsing error 0. Please report this" );
124 if( list2.size() > 1 )
126 i_option = list2.at( 1 ).toInt( &ok );
129 msg_Warn( p_intf, "Parsing error 1. Please report this" );
134 createAndAddWidget( controlLayout, -1, i_type, i_option );
138 void AbstractController::createAndAddWidget( QBoxLayout *controlLayout,
143 /* Special case for SPACERS, who aren't QWidgets */
144 if( i_type == WIDGET_SPACER )
146 controlLayout->insertSpacing( i_index, 16 );
150 if( i_type == WIDGET_SPACER_EXTEND )
152 controlLayout->insertSpacing( i_index, 10 );
156 QWidget *widg = createWidget( i_type, i_option );
159 controlLayout->insertWidget( i_index, widg );
163 #define CONNECT_MAP( a ) CONNECT( a, clicked(), toolbarActionsMapper, map() )
164 #define SET_MAPPING( a, b ) toolbarActionsMapper->setMapping( a , b )
165 #define CONNECT_MAP_SET( a, b ) \
168 #define BUTTON_SET_BAR( a_button ) \
169 a_button->setToolTip( tooltipL[button] ); \
170 a_button->setIcon( QIcon( iconL[button] ) );
171 #define BUTTON_SET_BAR2( button, image, tooltip ) \
172 button->setToolTip( tooltip ); \
173 button->setIcon( QIcon( ":/"#image ) );
176 #define ENABLE_ON_VIDEO( a ) \
177 CONNECT( THEMIM->getIM(), voutChanged( bool ), a, setEnabled( bool ) ); \
178 a->setEnabled( THEMIM->getIM()->hasVideo() ); /* TODO: is this necessary? when input is started before the interface? */
180 #define ENABLE_ON_INPUT( a ) \
181 CONNECT( this, inputExists( bool ), a, setEnabled( bool ) ); \
182 a->setEnabled( THEMIM->getIM()->hasInput() ); /* TODO: is this necessary? when input is started before the interface? */
184 QWidget *AbstractController::createWidget( buttonType_e button, int options )
187 bool b_flat = options & WIDGET_FLAT;
188 bool b_big = options & WIDGET_BIG;
189 bool b_shiny = options & WIDGET_SHINY;
191 QWidget *widget = NULL;
195 PlayButton *playButton = new PlayButton;
196 setupButton( playButton );
197 BUTTON_SET_BAR( playButton );
198 CONNECT_MAP_SET( playButton, PLAY_ACTION );
199 CONNECT( this, inputPlaying( bool ),
200 playButton, updateButton( bool ));
205 QToolButton *stopButton = new QToolButton;
206 setupButton( stopButton );
207 CONNECT_MAP_SET( stopButton, STOP_ACTION );
208 BUTTON_SET_BAR( stopButton );
212 case PREVIOUS_BUTTON:{
213 QToolButton *prevButton = new QToolButton;
214 setupButton( prevButton );
215 CONNECT_MAP_SET( prevButton, PREVIOUS_ACTION );
216 BUTTON_SET_BAR( prevButton );
222 QToolButton *nextButton = new QToolButton;
223 setupButton( nextButton );
224 CONNECT_MAP_SET( nextButton, NEXT_ACTION );
225 BUTTON_SET_BAR( nextButton );
230 QToolButton *slowerButton = new QToolButton;
231 setupButton( slowerButton );
232 CONNECT_MAP_SET( slowerButton, SLOWER_ACTION );
233 BUTTON_SET_BAR( slowerButton );
234 ENABLE_ON_INPUT( slowerButton );
235 widget = slowerButton;
239 QToolButton *fasterButton = new QToolButton;
240 setupButton( fasterButton );
241 CONNECT_MAP_SET( fasterButton, FASTER_ACTION );
242 BUTTON_SET_BAR( fasterButton );
243 ENABLE_ON_INPUT( fasterButton );
244 widget = fasterButton;
248 QToolButton *frameButton = new QToolButton;
249 setupButton( frameButton );
250 CONNECT_MAP_SET( frameButton, FRAME_ACTION );
251 BUTTON_SET_BAR( frameButton );
252 ENABLE_ON_VIDEO( frameButton );
253 widget = frameButton;
256 case FULLSCREEN_BUTTON:{
257 QToolButton *fullscreenButton = new QToolButton;
258 setupButton( fullscreenButton );
259 CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
260 BUTTON_SET_BAR( fullscreenButton );
261 ENABLE_ON_VIDEO( fullscreenButton );
262 widget = fullscreenButton;
265 case DEFULLSCREEN_BUTTON:{
266 QToolButton *fullscreenButton = new QToolButton;
267 setupButton( fullscreenButton );
268 CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
269 BUTTON_SET_BAR( fullscreenButton )
270 ENABLE_ON_VIDEO( fullscreenButton );
271 widget = fullscreenButton;
274 case EXTENDED_BUTTON:{
275 QToolButton *extSettingsButton = new QToolButton;
276 setupButton( extSettingsButton );
277 CONNECT_MAP_SET( extSettingsButton, EXTENDED_ACTION );
278 BUTTON_SET_BAR( extSettingsButton )
279 widget = extSettingsButton;
282 case PLAYLIST_BUTTON:{
283 QToolButton *playlistButton = new QToolButton;
284 setupButton( playlistButton );
285 CONNECT_MAP_SET( playlistButton, PLAYLIST_ACTION );
286 BUTTON_SET_BAR( playlistButton );
287 widget = playlistButton;
290 case SNAPSHOT_BUTTON:{
291 QToolButton *snapshotButton = new QToolButton;
292 setupButton( snapshotButton );
293 CONNECT_MAP_SET( snapshotButton, SNAPSHOT_ACTION );
294 BUTTON_SET_BAR( snapshotButton );
295 ENABLE_ON_VIDEO( snapshotButton );
296 widget = snapshotButton;
300 QToolButton *recordButton = new QToolButton;
301 setupButton( recordButton );
302 CONNECT_MAP_SET( recordButton, RECORD_ACTION );
303 BUTTON_SET_BAR( recordButton );
304 ENABLE_ON_INPUT( recordButton );
305 widget = recordButton;
309 AtoB_Button *ABButton = new AtoB_Button;
310 setupButton( ABButton );
311 BUTTON_SET_BAR( ABButton );
312 ENABLE_ON_INPUT( ABButton );
313 CONNECT_MAP_SET( ABButton, ATOB_ACTION );
314 CONNECT( THEMIM->getIM(), AtoBchanged( bool, bool),
315 ABButton, setIcons( bool, bool ) );
320 InputSlider *slider = new InputSlider( Qt::Horizontal, NULL );
322 /* Update the position when the IM has changed */
323 CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
324 slider, setPosition( float, int, int ) );
325 /* And update the IM, when the position has changed */
326 CONNECT( slider, sliderDragged( float ),
327 THEMIM->getIM(), sliderUpdate( float ) );
332 widget = discFrame();
335 case TELETEXT_BUTTONS:
336 widget = telexFrame();
341 SoundWidget *snd = new SoundWidget( this, p_intf, b_shiny );
347 TimeLabel *timeLabel = new TimeLabel( p_intf );
353 QFrame *line = new QFrame;
354 line->setFrameShape( QFrame::VLine );
355 line->setFrameShadow( QFrame::Raised );
356 line->setLineWidth( 0 );
357 line->setMidLineWidth( 1 );
361 case ADVANCED_CONTROLLER:
363 advControls = new AdvControlsWidget( p_intf, this );
364 widget = advControls;
367 case REVERSE_BUTTON:{
368 QToolButton *reverseButton = new QToolButton;
369 setupButton( reverseButton );
370 CONNECT_MAP_SET( reverseButton, REVERSE_ACTION );
371 BUTTON_SET_BAR( reverseButton );
372 ENABLE_ON_INPUT( reverseButton );
373 widget = reverseButton;
377 msg_Warn( p_intf, "This should not happen %i", button );
381 /* Customize Buttons */
382 if( b_flat || b_big )
384 QToolButton *tmpButton = qobject_cast<QToolButton *>(widget);
388 tmpButton->setAutoRaise( b_flat );
391 tmpButton->setFixedSize( QSize( 32, 32 ) );
392 tmpButton->setIconSize( QSize( 26, 26 ) );
399 QWidget *AbstractController::discFrame()
401 /** Disc and Menus handling */
402 QWidget *discFrame = new QWidget( this );
404 QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
405 discLayout->setSpacing( 0 ); discLayout->setMargin( 0 );
407 QToolButton *prevSectionButton = new QToolButton( discFrame );
408 setupButton( prevSectionButton );
409 BUTTON_SET_BAR2( prevSectionButton, dvd_prev,
410 qtr("Previous Chapter/Title" ) );
411 discLayout->addWidget( prevSectionButton );
413 QToolButton *menuButton = new QToolButton( discFrame );
414 setupButton( menuButton );
415 discLayout->addWidget( menuButton );
416 BUTTON_SET_BAR2( menuButton, dvd_menu, qtr( "Menu" ) );
418 QToolButton *nextSectionButton = new QToolButton( discFrame );
419 setupButton( nextSectionButton );
420 discLayout->addWidget( nextSectionButton );
421 BUTTON_SET_BAR2( nextSectionButton, dvd_next,
422 qtr("Next Chapter/Title" ) );
424 /* Change the navigation button display when the IM
425 navigation changes */
426 CONNECT( THEMIM->getIM(), titleChanged( bool ),
427 discFrame, setVisible( bool ) );
428 CONNECT( THEMIM->getIM(), chapterChanged( bool ),
429 menuButton, setVisible( bool ) );
430 /* Changes the IM navigation when triggered on the nav buttons */
431 CONNECT( prevSectionButton, clicked(), THEMIM->getIM(),
433 CONNECT( nextSectionButton, clicked(), THEMIM->getIM(),
435 CONNECT( menuButton, clicked(), THEMIM->getIM(),
441 QWidget *AbstractController::telexFrame()
446 TeletextController *telexFrame = new TeletextController;
447 QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame );
448 telexLayout->setSpacing( 0 ); telexLayout->setMargin( 0 );
449 CONNECT( THEMIM->getIM(), teletextPossible( bool ),
450 telexFrame, setVisible( bool ) );
453 QToolButton *telexOn = new QToolButton;
454 telexFrame->telexOn = telexOn;
455 setupButton( telexOn );
456 BUTTON_SET_BAR2( telexOn, tv, qtr( "Teletext Activation" ) );
457 telexLayout->addWidget( telexOn );
459 /* Teletext Activation and set */
460 CONNECT( telexOn, clicked( bool ),
461 THEMIM->getIM(), activateTeletext( bool ) );
462 CONNECT( THEMIM->getIM(), teletextActivated( bool ),
463 telexFrame, enableTeletextButtons( bool ) );
466 /* Transparency button */
467 QToolButton *telexTransparent = new QToolButton;
468 telexFrame->telexTransparent = telexTransparent;
469 setupButton( telexTransparent );
470 BUTTON_SET_BAR2( telexTransparent, tvtelx,
471 qtr( "Toggle Transparency " ) );
472 telexTransparent->setEnabled( false );
473 telexLayout->addWidget( telexTransparent );
475 /* Transparency change and set */
476 CONNECT( telexTransparent, clicked( bool ),
477 THEMIM->getIM(), telexSetTransparency( bool ) );
478 CONNECT( THEMIM->getIM(), teletextTransparencyActivated( bool ),
479 telexFrame, toggleTeletextTransparency( bool ) );
483 QSpinBox *telexPage = new QSpinBox;
484 telexFrame->telexPage = telexPage;
485 telexPage->setRange( 0, 999 );
486 telexPage->setValue( 100 );
487 telexPage->setAccelerated( true );
488 telexPage->setWrapping( true );
489 telexPage->setAlignment( Qt::AlignRight );
490 telexPage->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
491 telexPage->setEnabled( false );
492 telexLayout->addWidget( telexPage );
494 /* Page change and set */
495 CONNECT( telexPage, valueChanged( int ),
496 THEMIM->getIM(), telexSetPage( int ) );
497 CONNECT( THEMIM->getIM(), newTelexPageSet( int ),
498 telexPage, setValue( int ) );
504 #undef CONNECT_MAP_SET
505 #undef BUTTON_SET_BAR
506 #undef ENABLE_ON_VIDEO
507 #undef ENABLE_ON_INPUT
509 SoundWidget::SoundWidget( QWidget *_parent, intf_thread_t * _p_intf,
511 : b_my_volume( false ), QWidget( _parent )
514 QHBoxLayout *layout = new QHBoxLayout( this );
515 layout->setSpacing( 0 ); layout->setMargin( 0 );
516 hVolLabel = new VolumeClickHandler( p_intf, this );
518 volMuteLabel = new QLabel;
519 volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) );
520 volMuteLabel->installEventFilter( hVolLabel );
521 layout->addWidget( volMuteLabel );
525 volumeSlider = new SoundSlider( this,
526 config_GetInt( p_intf, "volume-step" ),
527 config_GetInt( p_intf, "qt-volume-complete" ),
528 config_GetPsz( p_intf, "qt-slider-colours" ) );
532 volumeSlider = new QSlider( this );
533 volumeSlider->setOrientation( Qt::Horizontal );
535 volumeSlider->setMaximumSize( QSize( 200, 40 ) );
536 volumeSlider->setMinimumSize( QSize( 85, 30 ) );
537 volumeSlider->setFocusPolicy( Qt::NoFocus );
538 layout->addWidget( volumeSlider );
540 /* Set the volume from the config */
541 volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
542 VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
544 /* Force the update at build time in order to have a muted icon if needed */
545 updateVolume( volumeSlider->value() );
547 /* Volume control connection */
548 CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
549 CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
552 void SoundWidget::updateVolume( int i_sliderVolume )
556 int i_res = i_sliderVolume * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX;
557 aout_VolumeSet( p_intf, i_res );
559 if( i_sliderVolume == 0 )
561 volMuteLabel->setPixmap( QPixmap(":/volume-muted" ) );
562 volMuteLabel->setToolTip( qtr( "Unmute" ) );
566 if( i_sliderVolume < VOLUME_MAX / 3 )
567 volMuteLabel->setPixmap( QPixmap( ":/volume-low" ) );
568 else if( i_sliderVolume > (VOLUME_MAX * 2 / 3 ) )
569 volMuteLabel->setPixmap( QPixmap( ":/volume-high" ) );
570 else volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) );
571 volMuteLabel->setToolTip( qtr( "Mute" ) );
574 void SoundWidget::updateVolume()
577 audio_volume_t i_volume;
578 aout_VolumeGet( p_intf, &i_volume );
579 i_volume = ( i_volume * VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
580 int i_gauge = volumeSlider->value();
582 if( i_volume - i_gauge > 1 || i_gauge - i_volume > 1 )
585 volumeSlider->setValue( i_volume );
590 void TeletextController::toggleTeletextTransparency( bool b_transparent )
592 telexTransparent->setIcon( b_transparent ? QIcon( ":/tvtelx" )
593 : QIcon( ":/tvtelx-trans" ) );
596 void TeletextController::enableTeletextButtons( bool b_enabled )
598 telexOn->setChecked( b_enabled );
599 telexTransparent->setEnabled( b_enabled );
600 telexPage->setEnabled( b_enabled );
603 void PlayButton::updateButton( bool b_playing )
605 setIcon( b_playing ? QIcon( ":/pause_b" ) : QIcon( ":/play_b" ) );
606 setToolTip( b_playing ? qtr( "Pause the playback" )
607 : qtr( I_PLAY_TOOLTIP ) );
610 void AtoB_Button::setIcons( bool timeA, bool timeB )
612 if( !timeA && !timeB)
614 setIcon( QIcon( ":/atob_nob" ) );
615 setToolTip( qtr( "Loop from point A to point B continuously\n"
616 "Click to set point A" ) );
618 else if( timeA && !timeB )
620 setIcon( QIcon( ":/atob_noa" ) );
621 setToolTip( qtr( "Click to set point B" ) );
623 else if( timeA && timeB )
625 setIcon( QIcon( ":/atob" ) );
626 setToolTip( qtr( "Stop the A to B loop" ) );
632 void AbstractController::doAction( int id_action )
638 case PREVIOUS_ACTION:
648 case FULLSCREEN_ACTION:
650 case EXTENDED_ACTION:
651 extSettings(); break;
652 case PLAYLIST_ACTION:
654 case SNAPSHOT_ACTION:
659 THEMIM->getIM()->setAtoB(); break;
665 msg_Dbg( p_intf, "Action: %i", id_action );
670 void AbstractController::stop()
675 void AbstractController::play()
677 if( THEPL->current.i_size == 0 )
679 /* The playlist is empty, open a file requester */
680 THEDP->openFileDialog();
683 THEMIM->togglePlayPause();
686 void AbstractController::prev()
691 void AbstractController::next()
698 * This functions toggle the fullscreen mode
699 * If there is no video, it should first activate Visualisations...
700 * This has also to be fixed in enableVideo()
702 void AbstractController::fullscreen()
704 vout_thread_t *p_vout =
705 (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
708 var_SetBool( p_vout, "fullscreen", !var_GetBool( p_vout, "fullscreen" ) );
709 vlc_object_release( p_vout );
713 void AbstractController::snapshot()
715 vout_thread_t *p_vout =
716 (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
719 vout_Control( p_vout, VOUT_SNAPSHOT );
720 vlc_object_release( p_vout );
724 void AbstractController::extSettings()
726 THEDP->extendedDialog();
729 void AbstractController::reverse()
731 THEMIM->getIM()->reverse();
734 void AbstractController::slower()
736 THEMIM->getIM()->slower();
739 void AbstractController::faster()
741 THEMIM->getIM()->faster();
744 void AbstractController::playlist()
746 if( p_intf->p_sys->p_mi ) p_intf->p_sys->p_mi->togglePlaylist();
749 void AbstractController::record()
751 input_thread_t *p_input = THEMIM->getInput();
754 /* This method won't work fine if the stream can't be cut anywhere */
755 const bool b_recording = var_GetBool( p_input, "record" );
756 var_SetBool( p_input, "record", !b_recording );
760 /* 'record' access-filter is not loaded, we open Save dialog */
761 input_item_t *p_item = input_GetItem( p_input );
765 char *psz = input_item_GetURI( p_item );
767 THEDP->streamingDialog( NULL, psz, true );
773 void AbstractController::frame()
775 input_thread_t *p_input = THEMIM->getInput();
777 var_SetVoid( p_input, "frame-next" );
779 #include <QHBoxLayout>
780 /*****************************
781 * DA Control Widget !
782 *****************************/
783 ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
786 AbstractController( _p_i, _parent )
788 setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
790 /* advanced Controls handling */
791 b_advancedVisible = b_advControls;
793 QVBoxLayout *controlLayout = new QVBoxLayout( this );
794 controlLayout->setLayoutMargins( 6, 4, 6, 2, 5 );
795 controlLayout->setSpacing( 0 );
796 QHBoxLayout *controlLayout1 = new QHBoxLayout;
797 controlLayout1->setSpacing( 0 );
799 QString line1 = getSettings()->value( "MainWindow/Controls1",
800 "64;36;37;38;65").toString();
801 parseAndCreate( line1, controlLayout1 );
803 /* QString line2 = QString( "%1-2;%2;%3;%4;%5;%6;%6;%7;%8;%9;%6;%10;%11-4")
804 .arg( PLAY_BUTTON ) .arg( WIDGET_SPACER )
805 .arg( PREVIOUS_BUTTON ) .arg( STOP_BUTTON )
806 .arg( NEXT_BUTTON ) .arg( WIDGET_SPACER )
807 .arg( FULLSCREEN_BUTTON ) .arg( PLAYLIST_BUTTON )
808 .arg( EXTENDED_BUTTON ) .arg( WIDGET_SPACER_EXTEND )
810 msg_Dbg( p_intf, "%s", qtu( line2 )); */
812 QHBoxLayout *controlLayout2 = new QHBoxLayout;
813 controlLayout2->setSpacing( 0 );
814 QString line2 = getSettings()->value( "MainWindow/Controls2",
815 "0-2;64;3;1;4;64;7;10;9;65;34-4" ).toString();
816 parseAndCreate( line2, controlLayout2 );
818 if( !b_advancedVisible && advControls ) advControls->hide();
820 controlLayout->addLayout( controlLayout1 );
821 controlLayout->addLayout( controlLayout2 );
824 ControlsWidget::~ControlsWidget()
827 void ControlsWidget::toggleAdvanced()
829 if( !advControls ) return;
831 if( !b_advancedVisible )
834 b_advancedVisible = true;
839 b_advancedVisible = false;
841 emit advancedControlsToggled( b_advancedVisible );
844 AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) :
845 AbstractController( _p_i, _parent )
847 controlLayout = new QHBoxLayout( this );
848 controlLayout->setMargin( 0 );
849 controlLayout->setSpacing( 0 );
851 /* QString line = QString( "%1;%2;%3").arg( RECORD_BUTTON )
852 .arg( SNAPSHOT_BUTTON )
854 .arg( FRAME_BUTTON ); */
856 QString line = getSettings()->value( "MainWindow/AdvControl",
857 "12;11;13;14" ).toString();
858 parseAndCreate( line, controlLayout );
861 InputControlsWidget::InputControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) :
862 AbstractController( _p_i, _parent )
864 controlLayout = new QHBoxLayout( this );
865 controlLayout->setMargin( 0 );
866 controlLayout->setSpacing( 0 );
868 /* QString line = QString( "%1-%2;%3;%4-%2")
869 .arg( SLOWER_BUTTON ).arg( WIDGET_FLAT )
871 .arg( FASTER_BUTTON ); */
872 QString line = getSettings()->value( "MainWindow/InputControl",
873 "5-1;33;6-1" ).toString();
874 parseAndCreate( line, controlLayout );
876 /**********************************************************************
877 * Fullscrenn control widget
878 **********************************************************************/
879 FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i )
880 : AbstractController( _p_i )
884 b_mouse_over = false;
885 i_mouse_last_move_x = -1;
886 i_mouse_last_move_y = -1;
887 #if HAVE_TRANSPARENCY
888 b_slow_hide_begin = false;
889 i_slow_hide_timeout = 1;
891 b_fullscreen = false;
896 setWindowFlags( Qt::ToolTip );
897 setMinimumWidth( 600 );
899 setFrameShape( QFrame::StyledPanel );
900 setFrameStyle( QFrame::Sunken );
901 setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
903 controlLayout = new QHBoxLayout( this );
904 controlLayout->setLayoutMargins( 5, 2, 5, 2, 5 );
907 InputControlsWidget *inputC = new InputControlsWidget( p_intf, this );
908 controlLayout->addWidget( inputC );
911 /* QString line = QString( "%1-2;%2;%3;%4;%5;%2;%6;%2;%7;%2;%8;%9;%10-4")
913 .arg( WIDGET_SPACER )
914 .arg( PREVIOUS_BUTTON )
918 .arg( TELETEXT_BUTTONS )
919 .arg( DEFULLSCREEN_BUTTON )
920 .arg( WIDGET_SPACER_EXTEND )
924 QString line = getSettings()->value( "MainWindow/FSCline",
925 "0-2;64;3;1;4;64;36;64;37;64;8;65;35-4;34" ).toString();
926 parseAndCreate( line, controlLayout );
929 p_hideTimer = new QTimer( this );
930 CONNECT( p_hideTimer, timeout(), this, hideFSC() );
931 p_hideTimer->setSingleShot( true );
933 /* slow hiding timer */
934 #if HAVE_TRANSPARENCY
935 p_slowHideTimer = new QTimer( this );
936 CONNECT( p_slowHideTimer, timeout(), this, slowHideFSC() );
939 adjustSize (); /* need to get real width and height for moving */
942 setWindowOpacity( 0.0 );
948 vlc_mutex_init_recursive( &lock );
951 FullscreenControllerWidget::~FullscreenControllerWidget()
953 getSettings()->setValue( "FullScreen/pos", pos() );
955 vlc_mutex_destroy( &lock );
959 * Show fullscreen controller
961 void FullscreenControllerWidget::showFSC()
965 int number = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
966 if( number != i_screennumber )
968 msg_Dbg( p_intf, "Calculation fullscreen controllers center");
969 /* screen has changed, calculate new position */
970 QRect screenRes = QApplication::desktop()->screenGeometry(number);
971 QPoint pos = QPoint( screenRes.x() + (screenRes.width() / 2) - (width() / 2),
972 screenRes.y() + screenRes.height() - height());
974 i_screennumber = number;
977 // after quiting and going to fs, we need to call show()
983 setWindowOpacity( 1.0 );
989 #if HAVE_TRANSPARENCY
990 setWindowOpacity( DEFAULT_OPACITY );
995 * Hide fullscreen controller
996 * FIXME: under windows it have to be done by moving out of screen
997 * because hide() doesnt work
999 void FullscreenControllerWidget::hideFSC()
1003 setWindowOpacity( 0.0 ); // simulate hidding
1010 * Plane to hide fullscreen controller
1012 void FullscreenControllerWidget::planHideFSC()
1014 vlc_mutex_lock( &lock );
1015 int i_timeout = i_hide_timeout;
1016 vlc_mutex_unlock( &lock );
1018 p_hideTimer->start( i_timeout );
1020 #if HAVE_TRANSPARENCY
1021 b_slow_hide_begin = true;
1022 i_slow_hide_timeout = i_timeout;
1023 p_slowHideTimer->start( i_slow_hide_timeout / 2 );
1028 * Hidding fullscreen controller slowly
1029 * Linux: need composite manager
1030 * Windows: it is blinking, so it can be enabled by define TRASPARENCY
1032 void FullscreenControllerWidget::slowHideFSC()
1034 #if HAVE_TRANSPARENCY
1035 if( b_slow_hide_begin )
1037 b_slow_hide_begin = false;
1039 p_slowHideTimer->stop();
1040 /* the last part of time divided to 100 pieces */
1041 p_slowHideTimer->start( (int)( i_slow_hide_timeout / 2 / ( windowOpacity() * 100 ) ) );
1047 if ( windowOpacity() > 0.0 && !b_fscHidden )
1049 if ( windowOpacity() > 0.0 )
1052 /* we should use 0.01 because of 100 pieces ^^^
1053 but than it cannt be done in time */
1054 setWindowOpacity( windowOpacity() - 0.02 );
1057 if ( windowOpacity() <= 0.0 )
1058 p_slowHideTimer->stop();
1065 * events: show, hide, start timer for hidding
1067 void FullscreenControllerWidget::customEvent( QEvent *event )
1071 switch( event->type() )
1073 case FullscreenControlToggle_Type:
1074 vlc_mutex_lock( &lock );
1075 b_fs = b_fullscreen;
1076 vlc_mutex_unlock( &lock );
1084 p_hideTimer->stop();
1090 case FullscreenControlShow_Type:
1091 vlc_mutex_lock( &lock );
1092 b_fs = b_fullscreen;
1093 vlc_mutex_unlock( &lock );
1096 if( b_fs && b_fscHidden )
1098 if( b_fs && !isVisible() )
1102 case FullscreenControlHide_Type:
1105 case FullscreenControlPlanHide_Type:
1106 if( !b_mouse_over ) // Only if the mouse is not over FSC
1116 void FullscreenControllerWidget::mouseMoveEvent( QMouseEvent *event )
1118 if ( event->buttons() == Qt::LeftButton )
1120 int i_moveX = event->globalX() - i_mouse_last_x;
1121 int i_moveY = event->globalY() - i_mouse_last_y;
1123 move( x() + i_moveX, y() + i_moveY );
1125 i_mouse_last_x = event->globalX();
1126 i_mouse_last_y = event->globalY();
1132 * store position of cursor
1134 void FullscreenControllerWidget::mousePressEvent( QMouseEvent *event )
1136 i_mouse_last_x = event->globalX();
1137 i_mouse_last_y = event->globalY();
1141 * On mouse go above FSC
1143 void FullscreenControllerWidget::enterEvent( QEvent *event )
1145 b_mouse_over = true;
1147 p_hideTimer->stop();
1148 #if HAVE_TRANSPARENCY
1149 p_slowHideTimer->stop();
1154 * On mouse go out from FSC
1156 void FullscreenControllerWidget::leaveEvent( QEvent *event )
1160 b_mouse_over = false;
1164 * When you get pressed key, send it to video output
1165 * FIXME: clearing focus by clearFocus() to not getting
1166 * key press events didnt work
1168 void FullscreenControllerWidget::keyPressEvent( QKeyEvent *event )
1170 int i_vlck = qtEventToVLCKey( event );
1173 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1181 static int FullscreenControllerWidgetFullscreenChanged( vlc_object_t *vlc_object,
1182 const char *variable, vlc_value_t old_val,
1183 vlc_value_t new_val, void *data )
1185 vout_thread_t *p_vout = (vout_thread_t *) vlc_object;
1186 msg_Dbg( p_vout, "Qt4: Fullscreen state changed" );
1187 FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
1189 p_fs->fullscreenChanged( p_vout, new_val.b_bool,
1190 var_GetInteger( p_vout, "mouse-hide-timeout" ) );
1195 static int FullscreenControllerWidgetMouseMoved( vlc_object_t *vlc_object, const char *variable,
1196 vlc_value_t old_val, vlc_value_t new_val,
1199 FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
1201 int i_mousex, i_mousey;
1202 bool b_toShow = false;
1204 /* Get the value from the Vout - Trust the vout more than Qt */
1205 i_mousex = var_GetInteger( p_fs->p_vout, "mouse-x" );
1206 i_mousey = var_GetInteger( p_fs->p_vout, "mouse-y" );
1209 if( p_fs->i_mouse_last_move_x == -1 || p_fs->i_mouse_last_move_y == -1 )
1211 p_fs->i_mouse_last_move_x = i_mousex;
1212 p_fs->i_mouse_last_move_y = i_mousey;
1215 /* All other times */
1218 /* Trigger only if move > 3 px dans une direction */
1219 if( abs( p_fs->i_mouse_last_move_x - i_mousex ) > 2 ||
1220 abs( p_fs->i_mouse_last_move_y - i_mousey ) > 2 )
1223 p_fs->i_mouse_last_move_x = i_mousex;
1224 p_fs->i_mouse_last_move_y = i_mousey;
1231 IMEvent *eShow = new IMEvent( FullscreenControlShow_Type, 0 );
1232 QApplication::postEvent( p_fs, static_cast<QEvent *>(eShow) );
1234 /* Plan hide event */
1235 IMEvent *eHide = new IMEvent( FullscreenControlPlanHide_Type, 0 );
1236 QApplication::postEvent( p_fs, static_cast<QEvent *>(eHide) );
1243 * It is called when video start
1245 void FullscreenControllerWidget::attachVout( vout_thread_t *p_nvout )
1247 assert( p_nvout && !p_vout );
1251 msg_Dbg( p_vout, "Qt FS: Attaching Vout" );
1252 vlc_mutex_lock( &lock );
1254 var_AddCallback( p_vout, "fullscreen",
1255 FullscreenControllerWidgetFullscreenChanged, this );
1256 /* I miss a add and fire */
1257 fullscreenChanged( p_vout, var_GetBool( p_vout, "fullscreen" ),
1258 var_GetInteger( p_vout, "mouse-hide-timeout" ) );
1259 vlc_mutex_unlock( &lock );
1263 * It is called after turn off video.
1265 void FullscreenControllerWidget::detachVout()
1269 msg_Dbg( p_vout, "Qt FS: Detaching Vout" );
1270 var_DelCallback( p_vout, "fullscreen",
1271 FullscreenControllerWidgetFullscreenChanged, this );
1272 vlc_mutex_lock( &lock );
1273 fullscreenChanged( p_vout, false, 0 );
1274 vlc_mutex_unlock( &lock );
1280 * Register and unregister callback for mouse moving
1282 void FullscreenControllerWidget::fullscreenChanged( vout_thread_t *p_vout,
1283 bool b_fs, int i_timeout )
1285 msg_Dbg( p_vout, "Qt: Entering Fullscreen" );
1287 vlc_mutex_lock( &lock );
1288 /* Entering fullscreen, register callback */
1289 if( b_fs && !b_fullscreen )
1291 b_fullscreen = true;
1292 i_hide_timeout = i_timeout;
1293 var_AddCallback( p_vout, "mouse-moved",
1294 FullscreenControllerWidgetMouseMoved, this );
1296 /* Quitting fullscreen, unregistering callback */
1297 else if( !b_fs && b_fullscreen )
1299 b_fullscreen = false;
1300 i_hide_timeout = i_timeout;
1301 var_DelCallback( p_vout, "mouse-moved",
1302 FullscreenControllerWidgetMouseMoved, this );
1304 /* Force fs hidding */
1305 IMEvent *eHide = new IMEvent( FullscreenControlHide_Type, 0 );
1306 QApplication::postEvent( this, static_cast<QEvent *>(eHide) );
1308 vlc_mutex_unlock( &lock );