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 ) : QFrame( NULL )
67 /* Main action provider */
68 toolbarActionsMapper = new QSignalMapper( this );
69 CONNECT( toolbarActionsMapper, mapped( int ), this, doAction( int ) );
70 CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
73 /* Reemit some signals on status Change to activate some buttons */
74 void AbstractController::setStatus( int status )
76 bool b_hasInput = THEMIM->getIM()->hasInput();
77 /* Activate the interface buttons according to the presence of the input */
78 emit inputExists( b_hasInput );
80 emit inputPlaying( status == PLAYING_S );
82 emit inputIsRecordable( b_hasInput &&
83 var_GetBool( THEMIM->getInput(), "can-record" ) );
86 /* Generic button setup */
87 void AbstractController::setupButton( QAbstractButton *aButton )
89 static QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
90 sizePolicy.setHorizontalStretch( 0 );
91 sizePolicy.setVerticalStretch( 0 );
93 aButton->setSizePolicy( sizePolicy );
94 aButton->setFixedSize( QSize( 26, 26 ) );
95 aButton->setIconSize( QSize( 20, 20 ) );
96 aButton->setFocusPolicy( Qt::NoFocus );
99 /* Open the generic config line for the toolbar, parse it
100 * and create the widgets accordingly */
101 void AbstractController::parseAndCreate( QString config,
102 QBoxLayout *controlLayout )
104 QStringList list = config.split( ";" ) ;
105 for( int i = 0; i < list.size(); i++ )
107 QStringList list2 = list.at( i ).split( "-" );
108 if( list2.size() < 1 )
110 msg_Warn( p_intf, "Parsing error. Report this" );
115 int i_option = WIDGET_NORMAL;
116 buttonType_e i_type = (buttonType_e)list2.at( 0 ).toInt( &ok );
119 msg_Warn( p_intf, "Parsing error 0. Please report this" );
123 if( list2.size() > 1 )
125 i_option = list2.at( 1 ).toInt( &ok );
128 msg_Warn( p_intf, "Parsing error 1. Please report this" );
133 createAndAddWidget( controlLayout, -1, i_type, i_option );
137 void AbstractController::createAndAddWidget( QBoxLayout *controlLayout,
142 /* Special case for SPACERS, who aren't QWidgets */
143 if( i_type == WIDGET_SPACER )
145 controlLayout->insertSpacing( i_index, 16 );
149 if( i_type == WIDGET_SPACER_EXTEND )
151 controlLayout->insertSpacing( i_index, 10 );
155 QWidget *widg = createWidget( i_type, i_option );
158 controlLayout->insertWidget( i_index, widg );
162 #define CONNECT_MAP( a ) CONNECT( a, clicked(), toolbarActionsMapper, map() )
163 #define SET_MAPPING( a, b ) toolbarActionsMapper->setMapping( a , b )
164 #define CONNECT_MAP_SET( a, b ) \
167 #define BUTTON_SET_BAR( a_button ) \
168 a_button->setToolTip( tooltipL[button] ); \
169 a_button->setIcon( QIcon( iconL[button] ) );
170 #define BUTTON_SET_BAR2( button, image, tooltip ) \
171 button->setToolTip( tooltip ); \
172 button->setIcon( QIcon( ":/"#image ) );
175 #define ENABLE_ON_VIDEO( a ) \
176 CONNECT( THEMIM->getIM(), voutChanged( bool ), a, setEnabled( bool ) ); \
177 a->setEnabled( THEMIM->getIM()->hasVideo() ); /* TODO: is this necessary? when input is started before the interface? */
179 #define ENABLE_ON_INPUT( a ) \
180 CONNECT( this, inputExists( bool ), a, setEnabled( bool ) ); \
181 a->setEnabled( THEMIM->getIM()->hasInput() ); /* TODO: is this necessary? when input is started before the interface? */
183 QWidget *AbstractController::createWidget( buttonType_e button, int options )
186 bool b_flat = options & WIDGET_FLAT;
187 bool b_big = options & WIDGET_BIG;
188 bool b_shiny = options & WIDGET_SHINY;
190 QWidget *widget = NULL;
194 PlayButton *playButton = new PlayButton;
195 setupButton( playButton );
196 BUTTON_SET_BAR( playButton );
197 CONNECT_MAP_SET( playButton, PLAY_ACTION );
198 CONNECT( this, inputPlaying( bool ),
199 playButton, updateButton( bool ));
204 QToolButton *stopButton = new QToolButton;
205 setupButton( stopButton );
206 CONNECT_MAP_SET( stopButton, STOP_ACTION );
207 BUTTON_SET_BAR( stopButton );
211 case PREVIOUS_BUTTON:{
212 QToolButton *prevButton = new QToolButton;
213 setupButton( prevButton );
214 CONNECT_MAP_SET( prevButton, PREVIOUS_ACTION );
215 BUTTON_SET_BAR( prevButton );
221 QToolButton *nextButton = new QToolButton;
222 setupButton( nextButton );
223 CONNECT_MAP_SET( nextButton, NEXT_ACTION );
224 BUTTON_SET_BAR( nextButton );
229 QToolButton *slowerButton = new QToolButton;
230 setupButton( slowerButton );
231 CONNECT_MAP_SET( slowerButton, SLOWER_ACTION );
232 BUTTON_SET_BAR( slowerButton );
233 ENABLE_ON_INPUT( slowerButton );
234 widget = slowerButton;
238 QToolButton *fasterButton = new QToolButton;
239 setupButton( fasterButton );
240 CONNECT_MAP_SET( fasterButton, FASTER_ACTION );
241 BUTTON_SET_BAR( fasterButton );
242 ENABLE_ON_INPUT( fasterButton );
243 widget = fasterButton;
247 QToolButton *frameButton = new QToolButton;
248 setupButton( frameButton );
249 CONNECT_MAP_SET( frameButton, FRAME_ACTION );
250 BUTTON_SET_BAR( frameButton );
251 ENABLE_ON_VIDEO( frameButton );
252 widget = frameButton;
255 case FULLSCREEN_BUTTON:{
256 QToolButton *fullscreenButton = new QToolButton;
257 setupButton( fullscreenButton );
258 CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
259 BUTTON_SET_BAR( fullscreenButton );
260 ENABLE_ON_VIDEO( fullscreenButton );
261 widget = fullscreenButton;
264 case DEFULLSCREEN_BUTTON:{
265 QToolButton *fullscreenButton = new QToolButton;
266 setupButton( fullscreenButton );
267 CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
268 BUTTON_SET_BAR( fullscreenButton )
269 ENABLE_ON_VIDEO( fullscreenButton );
270 widget = fullscreenButton;
273 case EXTENDED_BUTTON:{
274 QToolButton *extSettingsButton = new QToolButton;
275 setupButton( extSettingsButton );
276 CONNECT_MAP_SET( extSettingsButton, EXTENDED_ACTION );
277 BUTTON_SET_BAR( extSettingsButton )
278 widget = extSettingsButton;
281 case PLAYLIST_BUTTON:{
282 QToolButton *playlistButton = new QToolButton;
283 setupButton( playlistButton );
284 CONNECT_MAP_SET( playlistButton, PLAYLIST_ACTION );
285 BUTTON_SET_BAR( playlistButton );
286 widget = playlistButton;
289 case SNAPSHOT_BUTTON:{
290 QToolButton *snapshotButton = new QToolButton;
291 setupButton( snapshotButton );
292 CONNECT_MAP_SET( snapshotButton, SNAPSHOT_ACTION );
293 BUTTON_SET_BAR( snapshotButton );
294 ENABLE_ON_VIDEO( snapshotButton );
295 widget = snapshotButton;
299 QToolButton *recordButton = new QToolButton;
300 setupButton( recordButton );
301 CONNECT_MAP_SET( recordButton, RECORD_ACTION );
302 BUTTON_SET_BAR( recordButton );
303 ENABLE_ON_INPUT( recordButton );
304 widget = recordButton;
308 AtoB_Button *ABButton = new AtoB_Button;
309 setupButton( ABButton );
310 BUTTON_SET_BAR( ABButton );
311 ENABLE_ON_INPUT( ABButton );
312 CONNECT_MAP_SET( ABButton, ATOB_ACTION );
313 CONNECT( THEMIM->getIM(), AtoBchanged( bool, bool),
314 ABButton, setIcons( bool, bool ) );
319 InputSlider *slider = new InputSlider( Qt::Horizontal, NULL );
321 /* Update the position when the IM has changed */
322 CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
323 slider, setPosition( float, int, int ) );
324 /* And update the IM, when the position has changed */
325 CONNECT( slider, sliderDragged( float ),
326 THEMIM->getIM(), sliderUpdate( float ) );
331 widget = discFrame();
334 case TELETEXT_BUTTONS:
335 widget = telexFrame();
340 SoundWidget *snd = new SoundWidget( this, p_intf, b_shiny );
346 TimeLabel *timeLabel = new TimeLabel( p_intf );
352 QFrame *line = new QFrame;
353 line->setFrameShape( QFrame::VLine );
354 line->setFrameShadow( QFrame::Raised );
355 line->setLineWidth( 0 );
356 line->setMidLineWidth( 1 );
360 case ADVANCED_CONTROLLER:
362 advControls = new AdvControlsWidget( p_intf );
363 widget = advControls;
366 case REVERSE_BUTTON:{
367 QToolButton *reverseButton = new QToolButton;
368 setupButton( reverseButton );
369 CONNECT_MAP_SET( reverseButton, REVERSE_ACTION );
370 BUTTON_SET_BAR( reverseButton );
371 ENABLE_ON_INPUT( reverseButton );
372 widget = reverseButton;
376 msg_Warn( p_intf, "This should not happen" );
380 /* Customize Buttons */
381 if( b_flat || b_big )
383 QToolButton *tmpButton = qobject_cast<QToolButton *>(widget);
387 tmpButton->setAutoRaise( b_flat );
390 tmpButton->setFixedSize( QSize( 32, 32 ) );
391 tmpButton->setIconSize( QSize( 26, 26 ) );
398 QWidget *AbstractController::discFrame()
400 /** Disc and Menus handling */
401 QWidget *discFrame = new QWidget( this );
403 QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
404 discLayout->setSpacing( 0 ); discLayout->setMargin( 0 );
406 QToolButton *prevSectionButton = new QToolButton( discFrame );
407 setupButton( prevSectionButton );
408 BUTTON_SET_BAR2( prevSectionButton, dvd_prev,
409 qtr("Previous Chapter/Title" ) );
410 discLayout->addWidget( prevSectionButton );
412 QToolButton *menuButton = new QToolButton( discFrame );
413 setupButton( menuButton );
414 discLayout->addWidget( menuButton );
415 BUTTON_SET_BAR2( menuButton, dvd_menu, qtr( "Menu" ) );
417 QToolButton *nextSectionButton = new QToolButton( discFrame );
418 setupButton( nextSectionButton );
419 discLayout->addWidget( nextSectionButton );
420 BUTTON_SET_BAR2( nextSectionButton, dvd_next,
421 qtr("Next Chapter/Title" ) );
423 /* Change the navigation button display when the IM
424 navigation changes */
425 CONNECT( THEMIM->getIM(), titleChanged( bool ),
426 discFrame, setVisible( bool ) );
427 CONNECT( THEMIM->getIM(), chapterChanged( bool ),
428 menuButton, setVisible( bool ) );
429 /* Changes the IM navigation when triggered on the nav buttons */
430 CONNECT( prevSectionButton, clicked(), THEMIM->getIM(),
432 CONNECT( nextSectionButton, clicked(), THEMIM->getIM(),
434 CONNECT( menuButton, clicked(), THEMIM->getIM(),
440 QWidget *AbstractController::telexFrame()
445 TeletextController *telexFrame = new TeletextController;
446 QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame );
447 telexLayout->setSpacing( 0 ); telexLayout->setMargin( 0 );
448 CONNECT( THEMIM->getIM(), teletextPossible( bool ),
449 telexFrame, setVisible( bool ) );
452 QToolButton *telexOn = new QToolButton;
453 telexFrame->telexOn = telexOn;
454 setupButton( telexOn );
455 BUTTON_SET_BAR2( telexOn, tv, qtr( "Teletext Activation" ) );
456 telexLayout->addWidget( telexOn );
458 /* Teletext Activation and set */
459 CONNECT( telexOn, clicked( bool ),
460 THEMIM->getIM(), activateTeletext( bool ) );
461 CONNECT( THEMIM->getIM(), teletextActivated( bool ),
462 telexFrame, enableTeletextButtons( bool ) );
465 /* Transparency button */
466 QToolButton *telexTransparent = new QToolButton;
467 telexFrame->telexTransparent = telexTransparent;
468 setupButton( telexTransparent );
469 BUTTON_SET_BAR2( telexTransparent, tvtelx,
470 qtr( "Toggle Transparency " ) );
471 telexTransparent->setEnabled( false );
472 telexLayout->addWidget( telexTransparent );
474 /* Transparency change and set */
475 CONNECT( telexTransparent, clicked( bool ),
476 THEMIM->getIM(), telexSetTransparency( bool ) );
477 CONNECT( THEMIM->getIM(), teletextTransparencyActivated( bool ),
478 telexFrame, toggleTeletextTransparency( bool ) );
482 QSpinBox *telexPage = new QSpinBox;
483 telexFrame->telexPage = telexPage;
484 telexPage->setRange( 0, 999 );
485 telexPage->setValue( 100 );
486 telexPage->setAccelerated( true );
487 telexPage->setWrapping( true );
488 telexPage->setAlignment( Qt::AlignRight );
489 telexPage->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
490 telexPage->setEnabled( false );
491 telexLayout->addWidget( telexPage );
493 /* Page change and set */
494 CONNECT( telexPage, valueChanged( int ),
495 THEMIM->getIM(), telexSetPage( int ) );
496 CONNECT( THEMIM->getIM(), newTelexPageSet( int ),
497 telexPage, setValue( int ) );
503 #undef CONNECT_MAP_SET
504 #undef BUTTON_SET_BAR
505 #undef ENABLE_ON_VIDEO
506 #undef ENABLE_ON_INPUT
508 SoundWidget::SoundWidget( QWidget *_parent, intf_thread_t * _p_intf,
510 : b_my_volume( false ), QWidget( _parent )
513 QHBoxLayout *layout = new QHBoxLayout( this );
514 layout->setSpacing( 0 ); layout->setMargin( 0 );
515 hVolLabel = new VolumeClickHandler( p_intf, this );
517 volMuteLabel = new QLabel;
518 volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) );
519 volMuteLabel->installEventFilter( hVolLabel );
520 layout->addWidget( volMuteLabel );
524 volumeSlider = new SoundSlider( this,
525 config_GetInt( p_intf, "volume-step" ),
526 config_GetInt( p_intf, "qt-volume-complete" ),
527 config_GetPsz( p_intf, "qt-slider-colours" ) );
531 volumeSlider = new QSlider( this );
532 volumeSlider->setOrientation( Qt::Horizontal );
534 volumeSlider->setMaximumSize( QSize( 200, 40 ) );
535 volumeSlider->setMinimumSize( QSize( 85, 30 ) );
536 volumeSlider->setFocusPolicy( Qt::NoFocus );
537 layout->addWidget( volumeSlider );
539 /* Set the volume from the config */
540 volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
541 VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
543 /* Force the update at build time in order to have a muted icon if needed */
544 updateVolume( volumeSlider->value() );
546 /* Volume control connection */
547 CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
548 CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
551 void SoundWidget::updateVolume( int i_sliderVolume )
555 int i_res = i_sliderVolume * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX;
556 aout_VolumeSet( p_intf, i_res );
558 if( i_sliderVolume == 0 )
560 volMuteLabel->setPixmap( QPixmap(":/volume-muted" ) );
561 volMuteLabel->setToolTip( qtr( "Unmute" ) );
565 if( i_sliderVolume < VOLUME_MAX / 3 )
566 volMuteLabel->setPixmap( QPixmap( ":/volume-low" ) );
567 else if( i_sliderVolume > (VOLUME_MAX * 2 / 3 ) )
568 volMuteLabel->setPixmap( QPixmap( ":/volume-high" ) );
569 else volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) );
570 volMuteLabel->setToolTip( qtr( "Mute" ) );
573 void SoundWidget::updateVolume()
576 audio_volume_t i_volume;
577 aout_VolumeGet( p_intf, &i_volume );
578 i_volume = ( i_volume * VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
579 int i_gauge = volumeSlider->value();
581 if( i_volume - i_gauge > 1 || i_gauge - i_volume > 1 )
584 volumeSlider->setValue( i_volume );
589 void TeletextController::toggleTeletextTransparency( bool b_transparent )
591 telexTransparent->setIcon( b_transparent ? QIcon( ":/tvtelx" )
592 : QIcon( ":/tvtelx-trans" ) );
595 void TeletextController::enableTeletextButtons( bool b_enabled )
597 telexOn->setChecked( b_enabled );
598 telexTransparent->setEnabled( b_enabled );
599 telexPage->setEnabled( b_enabled );
602 void PlayButton::updateButton( bool b_playing )
604 setIcon( b_playing ? QIcon( ":/pause_b" ) : QIcon( ":/play_b" ) );
605 setToolTip( b_playing ? qtr( "Pause the playback" )
606 : qtr( I_PLAY_TOOLTIP ) );
609 void AtoB_Button::setIcons( bool timeA, bool timeB )
611 if( !timeA && !timeB)
613 setIcon( QIcon( ":/atob_nob" ) );
614 setToolTip( qtr( "Loop from point A to point B continuously\n"
615 "Click to set point A" ) );
617 else if( timeA && !timeB )
619 setIcon( QIcon( ":/atob_noa" ) );
620 setToolTip( qtr( "Click to set point B" ) );
622 else if( timeA && timeB )
624 setIcon( QIcon( ":/atob" ) );
625 setToolTip( qtr( "Stop the A to B loop" ) );
631 void AbstractController::doAction( int id_action )
637 case PREVIOUS_ACTION:
647 case FULLSCREEN_ACTION:
649 case EXTENDED_ACTION:
650 extSettings(); break;
651 case PLAYLIST_ACTION:
653 case SNAPSHOT_ACTION:
658 THEMIM->getIM()->setAtoB(); break;
664 msg_Dbg( p_intf, "Action: %i", id_action );
669 void AbstractController::stop()
674 void AbstractController::play()
676 if( THEPL->current.i_size == 0 )
678 /* The playlist is empty, open a file requester */
679 THEDP->openFileDialog();
682 THEMIM->togglePlayPause();
685 void AbstractController::prev()
690 void AbstractController::next()
697 * This functions toggle the fullscreen mode
698 * If there is no video, it should first activate Visualisations...
699 * This has also to be fixed in enableVideo()
701 void AbstractController::fullscreen()
703 vout_thread_t *p_vout =
704 (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
707 var_SetBool( p_vout, "fullscreen", !var_GetBool( p_vout, "fullscreen" ) );
708 vlc_object_release( p_vout );
712 void AbstractController::snapshot()
714 vout_thread_t *p_vout =
715 (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
718 vout_Control( p_vout, VOUT_SNAPSHOT );
719 vlc_object_release( p_vout );
723 void AbstractController::extSettings()
725 THEDP->extendedDialog();
728 void AbstractController::reverse()
730 THEMIM->getIM()->reverse();
733 void AbstractController::slower()
735 THEMIM->getIM()->slower();
738 void AbstractController::faster()
740 THEMIM->getIM()->faster();
743 void AbstractController::playlist()
745 if( p_intf->p_sys->p_mi ) p_intf->p_sys->p_mi->togglePlaylist();
748 void AbstractController::record()
750 input_thread_t *p_input = THEMIM->getInput();
753 /* This method won't work fine if the stream can't be cut anywhere */
754 const bool b_recording = var_GetBool( p_input, "record" );
755 var_SetBool( p_input, "record", !b_recording );
759 /* 'record' access-filter is not loaded, we open Save dialog */
760 input_item_t *p_item = input_GetItem( p_input );
764 char *psz = input_item_GetURI( p_item );
766 THEDP->streamingDialog( NULL, psz, true );
772 void AbstractController::frame()
774 input_thread_t *p_input = THEMIM->getInput();
776 var_SetVoid( p_input, "frame-next" );
778 #include <QHBoxLayout>
779 /*****************************
780 * DA Control Widget !
781 *****************************/
782 ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
783 bool b_advControls ) :
784 AbstractController( _p_i )
786 setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
788 /* advanced Controls handling */
789 b_advancedVisible = b_advControls;
791 QVBoxLayout *controlLayout = new QVBoxLayout( this );
792 controlLayout->setLayoutMargins( 6, 4, 6, 2, 5 );
793 controlLayout->setSpacing( 0 );
794 QHBoxLayout *controlLayout1 = new QHBoxLayout;
795 controlLayout1->setSpacing( 0 );
797 QString line1 = getSettings()->value( "MainWindow/Controls1",
798 "18;19;25" ).toString();
799 parseAndCreate( line1, controlLayout1 );
801 /* QString line2 = QString( "%1-2;%2;%3;%4;%5;%6;%6;%7;%8;%9;%6;%10;%11-4")
802 .arg( PLAY_BUTTON ) .arg( WIDGET_SPACER )
803 .arg( PREVIOUS_BUTTON ) .arg( STOP_BUTTON )
804 .arg( NEXT_BUTTON ) .arg( WIDGET_SPACER )
805 .arg( FULLSCREEN_BUTTON ) .arg( PLAYLIST_BUTTON )
806 .arg( EXTENDED_BUTTON ) .arg( WIDGET_SPACER_EXTEND )
809 QHBoxLayout *controlLayout2 = new QHBoxLayout;
810 controlLayout2->setSpacing( 0 );
811 QString line2 = getSettings()->value( "MainWindow/Controls2",
812 "0-2;21;4;2;5;21;8;11;10;21;22;20-4" ).toString();
813 parseAndCreate( line2, controlLayout2 );
815 if( !b_advancedVisible && advControls ) advControls->hide();
817 controlLayout->addLayout( controlLayout1 );
818 controlLayout->addLayout( controlLayout2 );
821 ControlsWidget::~ControlsWidget()
824 void ControlsWidget::toggleAdvanced()
826 if( !advControls ) return;
828 if( !b_advancedVisible )
831 b_advancedVisible = true;
836 b_advancedVisible = false;
838 emit advancedControlsToggled( b_advancedVisible );
841 AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i ) :
842 AbstractController( _p_i )
844 controlLayout = new QHBoxLayout( this );
845 controlLayout->setMargin( 0 );
846 controlLayout->setSpacing( 0 );
848 /* QString line = QString( "%1;%2;%3").arg( RECORD_BUTTON )
849 .arg( SNAPSHOT_BUTTON )
851 .arg( FRAME_BUTTON ); */
853 QString line = getSettings()->value( "MainWindow/AdvControl",
854 "12;13;14;15" ).toString();
855 parseAndCreate( line, controlLayout );
858 InputControlsWidget::InputControlsWidget( intf_thread_t *_p_i ) :
859 AbstractController( _p_i )
861 controlLayout = new QHBoxLayout( this );
862 controlLayout->setMargin( 0 );
863 controlLayout->setSpacing( 0 );
865 /* QString line = QString( "%1-%2;%3;%4-%2")
866 .arg( SLOWER_BUTTON ).arg( WIDGET_FLAT )
868 .arg( FASTER_BUTTON ); */
869 QString line = getSettings()->value( "MainWindow/InputControl",
870 "6-1;16;7-1" ).toString();
871 parseAndCreate( line, controlLayout );
873 /**********************************************************************
874 * Fullscrenn control widget
875 **********************************************************************/
876 FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i )
877 : AbstractController( _p_i )
881 b_mouse_over = false;
882 i_mouse_last_move_x = -1;
883 i_mouse_last_move_y = -1;
884 #if HAVE_TRANSPARENCY
885 b_slow_hide_begin = false;
886 i_slow_hide_timeout = 1;
888 b_fullscreen = false;
893 setWindowFlags( Qt::ToolTip );
894 setMinimumWidth( 600 );
896 setFrameShape( QFrame::StyledPanel );
897 setFrameStyle( QFrame::Sunken );
898 setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
900 controlLayout = new QHBoxLayout( this );
901 controlLayout->setLayoutMargins( 5, 2, 5, 2, 5 );
904 InputControlsWidget *inputC = new InputControlsWidget( p_intf );
905 // controlLayout->addWidget( inputC, 0, 0, 1, -1 );
908 /* QString line2 = QString( "%1-2;%2;%3;%4;%5;%2;%6;%2;%7;%2;%8;%9;%10-4")
910 .arg( WIDGET_SPACER )
911 .arg( PREVIOUS_BUTTON )
915 .arg( TELETEXT_BUTTONS )
916 .arg( DEFULLSCREEN_BUTTON )
917 .arg( WIDGET_SPACER_EXTEND )
921 QString line = getSettings()->value( "MainWindow/FSCline",
922 "0-2;21;4;2;5;21;18;21;19;21;9;22;23-4" ).toString();
923 parseAndCreate( line, controlLayout );
926 p_hideTimer = new QTimer( this );
927 CONNECT( p_hideTimer, timeout(), this, hideFSC() );
928 p_hideTimer->setSingleShot( true );
930 /* slow hiding timer */
931 #if HAVE_TRANSPARENCY
932 p_slowHideTimer = new QTimer( this );
933 CONNECT( p_slowHideTimer, timeout(), this, slowHideFSC() );
936 adjustSize (); /* need to get real width and height for moving */
939 setWindowOpacity( 0.0 );
945 vlc_mutex_init_recursive( &lock );
948 FullscreenControllerWidget::~FullscreenControllerWidget()
950 getSettings()->setValue( "FullScreen/pos", pos() );
952 vlc_mutex_destroy( &lock );
956 * Show fullscreen controller
958 void FullscreenControllerWidget::showFSC()
962 int number = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
963 if( number != i_screennumber )
965 msg_Dbg( p_intf, "Calculation fullscreen controllers center");
966 /* screen has changed, calculate new position */
967 QRect screenRes = QApplication::desktop()->screenGeometry(number);
968 QPoint pos = QPoint( screenRes.x() + (screenRes.width() / 2) - (width() / 2),
969 screenRes.y() + screenRes.height() - height());
971 i_screennumber = number;
974 // after quiting and going to fs, we need to call show()
980 setWindowOpacity( 1.0 );
986 #if HAVE_TRANSPARENCY
987 setWindowOpacity( DEFAULT_OPACITY );
992 * Hide fullscreen controller
993 * FIXME: under windows it have to be done by moving out of screen
994 * because hide() doesnt work
996 void FullscreenControllerWidget::hideFSC()
1000 setWindowOpacity( 0.0 ); // simulate hidding
1007 * Plane to hide fullscreen controller
1009 void FullscreenControllerWidget::planHideFSC()
1011 vlc_mutex_lock( &lock );
1012 int i_timeout = i_hide_timeout;
1013 vlc_mutex_unlock( &lock );
1015 p_hideTimer->start( i_timeout );
1017 #if HAVE_TRANSPARENCY
1018 b_slow_hide_begin = true;
1019 i_slow_hide_timeout = i_timeout;
1020 p_slowHideTimer->start( i_slow_hide_timeout / 2 );
1025 * Hidding fullscreen controller slowly
1026 * Linux: need composite manager
1027 * Windows: it is blinking, so it can be enabled by define TRASPARENCY
1029 void FullscreenControllerWidget::slowHideFSC()
1031 #if HAVE_TRANSPARENCY
1032 if( b_slow_hide_begin )
1034 b_slow_hide_begin = false;
1036 p_slowHideTimer->stop();
1037 /* the last part of time divided to 100 pieces */
1038 p_slowHideTimer->start( (int)( i_slow_hide_timeout / 2 / ( windowOpacity() * 100 ) ) );
1044 if ( windowOpacity() > 0.0 && !b_fscHidden )
1046 if ( windowOpacity() > 0.0 )
1049 /* we should use 0.01 because of 100 pieces ^^^
1050 but than it cannt be done in time */
1051 setWindowOpacity( windowOpacity() - 0.02 );
1054 if ( windowOpacity() <= 0.0 )
1055 p_slowHideTimer->stop();
1062 * events: show, hide, start timer for hidding
1064 void FullscreenControllerWidget::customEvent( QEvent *event )
1068 switch( event->type() )
1070 case FullscreenControlToggle_Type:
1071 vlc_mutex_lock( &lock );
1072 b_fs = b_fullscreen;
1073 vlc_mutex_unlock( &lock );
1081 p_hideTimer->stop();
1087 case FullscreenControlShow_Type:
1088 vlc_mutex_lock( &lock );
1089 b_fs = b_fullscreen;
1090 vlc_mutex_unlock( &lock );
1093 if( b_fs && b_fscHidden )
1095 if( b_fs && !isVisible() )
1099 case FullscreenControlHide_Type:
1102 case FullscreenControlPlanHide_Type:
1103 if( !b_mouse_over ) // Only if the mouse is not over FSC
1113 void FullscreenControllerWidget::mouseMoveEvent( QMouseEvent *event )
1115 if ( event->buttons() == Qt::LeftButton )
1117 int i_moveX = event->globalX() - i_mouse_last_x;
1118 int i_moveY = event->globalY() - i_mouse_last_y;
1120 move( x() + i_moveX, y() + i_moveY );
1122 i_mouse_last_x = event->globalX();
1123 i_mouse_last_y = event->globalY();
1129 * store position of cursor
1131 void FullscreenControllerWidget::mousePressEvent( QMouseEvent *event )
1133 i_mouse_last_x = event->globalX();
1134 i_mouse_last_y = event->globalY();
1138 * On mouse go above FSC
1140 void FullscreenControllerWidget::enterEvent( QEvent *event )
1142 b_mouse_over = true;
1144 p_hideTimer->stop();
1145 #if HAVE_TRANSPARENCY
1146 p_slowHideTimer->stop();
1151 * On mouse go out from FSC
1153 void FullscreenControllerWidget::leaveEvent( QEvent *event )
1157 b_mouse_over = false;
1161 * When you get pressed key, send it to video output
1162 * FIXME: clearing focus by clearFocus() to not getting
1163 * key press events didnt work
1165 void FullscreenControllerWidget::keyPressEvent( QKeyEvent *event )
1167 int i_vlck = qtEventToVLCKey( event );
1170 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1178 static int FullscreenControllerWidgetFullscreenChanged( vlc_object_t *vlc_object,
1179 const char *variable, vlc_value_t old_val,
1180 vlc_value_t new_val, void *data )
1182 vout_thread_t *p_vout = (vout_thread_t *) vlc_object;
1183 msg_Dbg( p_vout, "Qt4: Fullscreen state changed" );
1184 FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
1186 p_fs->fullscreenChanged( p_vout, new_val.b_bool,
1187 var_GetInteger( p_vout, "mouse-hide-timeout" ) );
1192 static int FullscreenControllerWidgetMouseMoved( vlc_object_t *vlc_object, const char *variable,
1193 vlc_value_t old_val, vlc_value_t new_val,
1196 FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
1198 int i_mousex, i_mousey;
1199 bool b_toShow = false;
1201 /* Get the value from the Vout - Trust the vout more than Qt */
1202 i_mousex = var_GetInteger( p_fs->p_vout, "mouse-x" );
1203 i_mousey = var_GetInteger( p_fs->p_vout, "mouse-y" );
1206 if( p_fs->i_mouse_last_move_x == -1 || p_fs->i_mouse_last_move_y == -1 )
1208 p_fs->i_mouse_last_move_x = i_mousex;
1209 p_fs->i_mouse_last_move_y = i_mousey;
1212 /* All other times */
1215 /* Trigger only if move > 3 px dans une direction */
1216 if( abs( p_fs->i_mouse_last_move_x - i_mousex ) > 2 ||
1217 abs( p_fs->i_mouse_last_move_y - i_mousey ) > 2 )
1220 p_fs->i_mouse_last_move_x = i_mousex;
1221 p_fs->i_mouse_last_move_y = i_mousey;
1228 IMEvent *eShow = new IMEvent( FullscreenControlShow_Type, 0 );
1229 QApplication::postEvent( p_fs, static_cast<QEvent *>(eShow) );
1231 /* Plan hide event */
1232 IMEvent *eHide = new IMEvent( FullscreenControlPlanHide_Type, 0 );
1233 QApplication::postEvent( p_fs, static_cast<QEvent *>(eHide) );
1240 * It is called when video start
1242 void FullscreenControllerWidget::attachVout( vout_thread_t *p_nvout )
1244 assert( p_nvout && !p_vout );
1248 msg_Dbg( p_vout, "Qt FS: Attaching Vout" );
1249 vlc_mutex_lock( &lock );
1251 var_AddCallback( p_vout, "fullscreen",
1252 FullscreenControllerWidgetFullscreenChanged, this );
1253 /* I miss a add and fire */
1254 fullscreenChanged( p_vout, var_GetBool( p_vout, "fullscreen" ),
1255 var_GetInteger( p_vout, "mouse-hide-timeout" ) );
1256 vlc_mutex_unlock( &lock );
1260 * It is called after turn off video.
1262 void FullscreenControllerWidget::detachVout()
1266 msg_Dbg( p_vout, "Qt FS: Detaching Vout" );
1267 var_DelCallback( p_vout, "fullscreen",
1268 FullscreenControllerWidgetFullscreenChanged, this );
1269 vlc_mutex_lock( &lock );
1270 fullscreenChanged( p_vout, false, 0 );
1271 vlc_mutex_unlock( &lock );
1277 * Register and unregister callback for mouse moving
1279 void FullscreenControllerWidget::fullscreenChanged( vout_thread_t *p_vout,
1280 bool b_fs, int i_timeout )
1282 msg_Dbg( p_vout, "Qt: Entering Fullscreen" );
1284 vlc_mutex_lock( &lock );
1285 /* Entering fullscreen, register callback */
1286 if( b_fs && !b_fullscreen )
1288 b_fullscreen = true;
1289 i_hide_timeout = i_timeout;
1290 var_AddCallback( p_vout, "mouse-moved",
1291 FullscreenControllerWidgetMouseMoved, this );
1293 /* Quitting fullscreen, unregistering callback */
1294 else if( !b_fs && b_fullscreen )
1296 b_fullscreen = false;
1297 i_hide_timeout = i_timeout;
1298 var_DelCallback( p_vout, "mouse-moved",
1299 FullscreenControllerWidgetMouseMoved, this );
1301 /* Force fs hidding */
1302 IMEvent *eHide = new IMEvent( FullscreenControlHide_Type, 0 );
1303 QApplication::postEvent( this, static_cast<QEvent *>(eHide) );
1305 vlc_mutex_unlock( &lock );