controller.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:34k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * Controller.cpp : Controller for the main interface
  3.  ****************************************************************************
  4.  * Copyright (C) 2006-2008 the VideoLAN team
  5.  * $Id: 080eb764a78096f8af2278be519d3c4d2c7014f7 $
  6.  *
  7.  * Authors: Jean-Baptiste Kempf <jb@videolan.org>
  8.  *          Ilkka Ollakka <ileoo@videolan.org>
  9.  *
  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.
  14.  *
  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.
  19.  *
  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.  *****************************************************************************/
  24. #ifdef HAVE_CONFIG_H
  25. # include "config.h"
  26. #endif
  27. #include <vlc_vout.h>
  28. #include <vlc_keys.h>
  29. #include "components/controller.hpp"
  30. #include "components/controller_widget.hpp"
  31. #include "components/interface_widgets.hpp"
  32. #include "dialogs_provider.hpp" /* Opening Dialogs */
  33. #include "input_manager.hpp"
  34. #include "actions_manager.hpp"
  35. #include "util/input_slider.hpp" /* InputSlider */
  36. #include "util/customwidgets.hpp" /* qEventToKey */
  37. #include <QSpacerItem>
  38. #include <QToolButton>
  39. #include <QHBoxLayout>
  40. #include <QSignalMapper>
  41. #include <QTimer>
  42. /**********************************************************************
  43.  * TEH controls
  44.  **********************************************************************/
  45. /******
  46.  * This is an abstract Toolbar/Controller
  47.  * This has helper to create any toolbar, any buttons and to manage the actions
  48.  *
  49.  *****/
  50. AbstractController::AbstractController( intf_thread_t * _p_i, QWidget *_parent )
  51.                    : QFrame( _parent )
  52. {
  53.     p_intf = _p_i;
  54.     advControls = NULL;
  55.     /* Main action provider */
  56.     toolbarActionsMapper = new QSignalMapper( this );
  57.     CONNECT( toolbarActionsMapper, mapped( int ),
  58.              ActionsManager::getInstance( p_intf  ), doAction( int ) );
  59.     CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
  60. }
  61. /* Reemit some signals on status Change to activate some buttons */
  62. void AbstractController::setStatus( int status )
  63. {
  64.     bool b_hasInput = THEMIM->getIM()->hasInput();
  65.     /* Activate the interface buttons according to the presence of the input */
  66.     emit inputExists( b_hasInput );
  67.     emit inputPlaying( status == PLAYING_S );
  68.     emit inputIsRecordable( b_hasInput &&
  69.                             var_GetBool( THEMIM->getInput(), "can-record" ) );
  70.     emit inputIsTrickPlayable( b_hasInput &&
  71.                             var_GetBool( THEMIM->getInput(), "can-rewind" ) );
  72. }
  73. /* Generic button setup */
  74. void AbstractController::setupButton( QAbstractButton *aButton )
  75. {
  76.     static QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
  77.     sizePolicy.setHorizontalStretch( 0 );
  78.     sizePolicy.setVerticalStretch( 0 );
  79.     aButton->setSizePolicy( sizePolicy );
  80.     aButton->setFixedSize( QSize( 26, 26 ) );
  81.     aButton->setIconSize( QSize( 20, 20 ) );
  82.     aButton->setFocusPolicy( Qt::NoFocus );
  83. }
  84. /* Open the generic config line for the toolbar, parse it
  85.  * and create the widgets accordingly */
  86. void AbstractController::parseAndCreate( const QString& config,
  87.                                          QBoxLayout *controlLayout )
  88. {
  89.     QStringList list = config.split( ";", QString::SkipEmptyParts ) ;
  90.     for( int i = 0; i < list.size(); i++ )
  91.     {
  92.         QStringList list2 = list.at( i ).split( "-" );
  93.         if( list2.size() < 1 )
  94.         {
  95.             msg_Warn( p_intf, "Parsing error. Report this" );
  96.             continue;
  97.         }
  98.         bool ok;
  99.         int i_option = WIDGET_NORMAL;
  100.         buttonType_e i_type = (buttonType_e)list2.at( 0 ).toInt( &ok );
  101.         if( !ok )
  102.         {
  103.             msg_Warn( p_intf, "Parsing error 0. Please report this" );
  104.             continue;
  105.         }
  106.         if( list2.size() > 1 )
  107.         {
  108.             i_option = list2.at( 1 ).toInt( &ok );
  109.             if( !ok )
  110.             {
  111.                 msg_Warn( p_intf, "Parsing error 1. Please report this" );
  112.                 continue;
  113.             }
  114.         }
  115.         createAndAddWidget( controlLayout, -1, i_type, i_option );
  116.     }
  117. }
  118. void AbstractController::createAndAddWidget( QBoxLayout *controlLayout,
  119.                                              int i_index,
  120.                                              buttonType_e i_type,
  121.                                              int i_option )
  122. {
  123.     /* Special case for SPACERS, who aren't QWidgets */
  124.     if( i_type == WIDGET_SPACER )
  125.     {
  126.         controlLayout->insertSpacing( i_index, 16 );
  127.         return;
  128.     }
  129.     if(  i_type == WIDGET_SPACER_EXTEND )
  130.     {
  131.         controlLayout->insertStretch( i_index, 16 );
  132.         return;
  133.     }
  134.     QWidget *widg = createWidget( i_type, i_option );
  135.     if( !widg ) return;
  136.     controlLayout->insertWidget( i_index, widg );
  137. }
  138. #define CONNECT_MAP( a ) CONNECT( a, clicked(),  toolbarActionsMapper, map() )
  139. #define SET_MAPPING( a, b ) toolbarActionsMapper->setMapping( a , b )
  140. #define CONNECT_MAP_SET( a, b ) 
  141.     CONNECT_MAP( a ); 
  142.     SET_MAPPING( a, b );
  143. #define BUTTON_SET_BAR( a_button ) 
  144.     a_button->setToolTip( qtr( tooltipL[button] ) ); 
  145.     a_button->setIcon( QIcon( iconL[button] ) );
  146. #define BUTTON_SET_BAR2( button, image, tooltip ) 
  147.     button->setToolTip( tooltip );          
  148.     button->setIcon( QIcon( ":/"#image ) );
  149. #define ENABLE_ON_VIDEO( a ) 
  150.     CONNECT( THEMIM->getIM(), voutChanged( bool ), a, setEnabled( bool ) ); 
  151.     a->setEnabled( THEMIM->getIM()->hasVideo() ); /* TODO: is this necessary? when input is started before the interface? */
  152. #define ENABLE_ON_INPUT( a ) 
  153.     CONNECT( this, inputExists( bool ), a, setEnabled( bool ) ); 
  154.     a->setEnabled( THEMIM->getIM()->hasInput() ); /* TODO: is this necessary? when input is started before the interface? */
  155. QWidget *AbstractController::createWidget( buttonType_e button, int options )
  156. {
  157.     bool b_flat = options & WIDGET_FLAT;
  158.     bool b_big = options & WIDGET_BIG;
  159.     bool b_shiny = options & WIDGET_SHINY;
  160.     bool b_special = false;
  161.     QWidget *widget = NULL;
  162.     switch( button )
  163.     {
  164.     case PLAY_BUTTON: {
  165.         PlayButton *playButton = new PlayButton;
  166.         setupButton( playButton );
  167.         BUTTON_SET_BAR(  playButton );
  168.         CONNECT_MAP_SET( playButton, PLAY_ACTION );
  169.         CONNECT( this, inputPlaying( bool ),
  170.                  playButton, updateButton( bool ));
  171.         widget = playButton;
  172.         }
  173.         break;
  174.     case STOP_BUTTON:{
  175.         QToolButton *stopButton = new QToolButton;
  176.         setupButton( stopButton );
  177.         CONNECT_MAP_SET( stopButton, STOP_ACTION );
  178.         BUTTON_SET_BAR(  stopButton );
  179.         widget = stopButton;
  180.         }
  181.         break;
  182.     case OPEN_BUTTON:{
  183.         QToolButton *openButton = new QToolButton;
  184.         setupButton( openButton );
  185.         CONNECT_MAP_SET( openButton, OPEN_ACTION );
  186.         BUTTON_SET_BAR( openButton );
  187.         widget = openButton;
  188.         }
  189.         break;
  190.     case PREVIOUS_BUTTON:{
  191.         QToolButton *prevButton = new QToolButton;
  192.         setupButton( prevButton );
  193.         CONNECT_MAP_SET( prevButton, PREVIOUS_ACTION );
  194.         BUTTON_SET_BAR( prevButton );
  195.         widget = prevButton;
  196.         }
  197.         break;
  198.     case NEXT_BUTTON:
  199.         {
  200.         QToolButton *nextButton = new QToolButton;
  201.         setupButton( nextButton );
  202.         CONNECT_MAP_SET( nextButton, NEXT_ACTION );
  203.         BUTTON_SET_BAR( nextButton );
  204.         widget = nextButton;
  205.         }
  206.         break;
  207.     case SLOWER_BUTTON:{
  208.         QToolButton *slowerButton = new QToolButton;
  209.         setupButton( slowerButton );
  210.         CONNECT_MAP_SET( slowerButton, SLOWER_ACTION );
  211.         BUTTON_SET_BAR(  slowerButton );
  212.         ENABLE_ON_INPUT( slowerButton );
  213.         widget = slowerButton;
  214.         }
  215.         break;
  216.     case FASTER_BUTTON:{
  217.         QToolButton *fasterButton = new QToolButton;
  218.         setupButton( fasterButton );
  219.         CONNECT_MAP_SET( fasterButton, FASTER_ACTION );
  220.         BUTTON_SET_BAR(  fasterButton );
  221.         ENABLE_ON_INPUT( fasterButton );
  222.         widget = fasterButton;
  223.         }
  224.         break;
  225.     case FRAME_BUTTON: {
  226.         QToolButton *frameButton = new QToolButton;
  227.         setupButton( frameButton );
  228.         CONNECT_MAP_SET( frameButton, FRAME_ACTION );
  229.         BUTTON_SET_BAR(  frameButton );
  230.         ENABLE_ON_VIDEO( frameButton );
  231.         widget = frameButton;
  232.         }
  233.         break;
  234.     case FULLSCREEN_BUTTON:{
  235.         QToolButton *fullscreenButton = new QToolButton;
  236.         setupButton( fullscreenButton );
  237.         CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
  238.         BUTTON_SET_BAR( fullscreenButton );
  239.         ENABLE_ON_VIDEO( fullscreenButton );
  240.         widget = fullscreenButton;
  241.         }
  242.         break;
  243.     case DEFULLSCREEN_BUTTON:{
  244.         QToolButton *fullscreenButton = new QToolButton;
  245.         setupButton( fullscreenButton );
  246.         CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
  247.         BUTTON_SET_BAR( fullscreenButton )
  248.         ENABLE_ON_VIDEO( fullscreenButton );
  249.         widget = fullscreenButton;
  250.         }
  251.         break;
  252.     case EXTENDED_BUTTON:{
  253.         QToolButton *extSettingsButton = new QToolButton;
  254.         setupButton( extSettingsButton );
  255.         CONNECT_MAP_SET( extSettingsButton, EXTENDED_ACTION );
  256.         BUTTON_SET_BAR( extSettingsButton )
  257.         widget = extSettingsButton;
  258.         }
  259.         break;
  260.     case PLAYLIST_BUTTON:{
  261.         QToolButton *playlistButton = new QToolButton;
  262.         setupButton( playlistButton );
  263.         CONNECT_MAP_SET( playlistButton, PLAYLIST_ACTION );
  264.         BUTTON_SET_BAR( playlistButton );
  265.         widget = playlistButton;
  266.         }
  267.         break;
  268.     case SNAPSHOT_BUTTON:{
  269.         QToolButton *snapshotButton = new QToolButton;
  270.         setupButton( snapshotButton );
  271.         CONNECT_MAP_SET( snapshotButton, SNAPSHOT_ACTION );
  272.         BUTTON_SET_BAR(  snapshotButton );
  273.         ENABLE_ON_VIDEO( snapshotButton );
  274.         widget = snapshotButton;
  275.         }
  276.         break;
  277.     case RECORD_BUTTON:{
  278.         QToolButton *recordButton = new QToolButton;
  279.         setupButton( recordButton );
  280.         CONNECT_MAP_SET( recordButton, RECORD_ACTION );
  281.         BUTTON_SET_BAR(  recordButton );
  282.         ENABLE_ON_INPUT( recordButton );
  283.         recordButton->setCheckable( true );
  284.         CONNECT( THEMIM->getIM(), recordingStateChanged( bool ),
  285.                  recordButton, setChecked( bool ) );
  286.         widget = recordButton;
  287.         }
  288.         break;
  289.     case ATOB_BUTTON: {
  290.         AtoB_Button *ABButton = new AtoB_Button;
  291.         setupButton( ABButton );
  292.         ABButton->setShortcut( qtr("Shift+L") );
  293.         BUTTON_SET_BAR( ABButton );
  294.         ENABLE_ON_INPUT( ABButton );
  295.         CONNECT_MAP_SET( ABButton, ATOB_ACTION );
  296.         CONNECT( THEMIM->getIM(), AtoBchanged( bool, bool),
  297.                  ABButton, setIcons( bool, bool ) );
  298.         widget = ABButton;
  299.         }
  300.         break;
  301.     case INPUT_SLIDER: {
  302.         InputSlider *slider = new InputSlider( Qt::Horizontal, NULL );
  303.         /* Update the position when the IM has changed */
  304.         CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
  305.                 slider, setPosition( float, int, int ) );
  306.         /* And update the IM, when the position has changed */
  307.         CONNECT( slider, sliderDragged( float ),
  308.                  THEMIM->getIM(), sliderUpdate( float ) );
  309.         widget = slider;
  310.         }
  311.         break;
  312.     case MENU_BUTTONS:
  313.         widget = discFrame();
  314.         widget->hide();
  315.         break;
  316.     case TELETEXT_BUTTONS:
  317.         widget = telexFrame();
  318.         widget->hide();
  319.         break;
  320.     case VOLUME_SPECIAL:
  321.         b_special = true;
  322.     case VOLUME:
  323.         {
  324.             SoundWidget *snd = new SoundWidget( this, p_intf, b_shiny, b_special );
  325.             widget = snd;
  326.         }
  327.         break;
  328.     case TIME_LABEL:
  329.         {
  330.             TimeLabel *timeLabel = new TimeLabel( p_intf );
  331.             widget = timeLabel;
  332.         }
  333.         break;
  334.     case SPLITTER:
  335.         {
  336.             QFrame *line = new QFrame;
  337.             line->setFrameShape( QFrame::VLine );
  338.             line->setFrameShadow( QFrame::Raised );
  339.             line->setLineWidth( 0 );
  340.             line->setMidLineWidth( 1 );
  341.             widget = line;
  342.         }
  343.         break;
  344.     case ADVANCED_CONTROLLER:
  345.         {
  346.             advControls = new AdvControlsWidget( p_intf, this );
  347.             widget = advControls;
  348.         }
  349.         break;
  350.     case REVERSE_BUTTON:{
  351.         QToolButton *reverseButton = new QToolButton;
  352.         setupButton( reverseButton );
  353.         CONNECT_MAP_SET( reverseButton, REVERSE_ACTION );
  354.         BUTTON_SET_BAR(  reverseButton );
  355.         reverseButton->setCheckable( true );
  356.         /* You should, of COURSE change this to the correct event,
  357.            when/if we have one, that tells us if trickplay is possible . */
  358.         CONNECT( this, inputIsTrickPlayable( bool ), reverseButton, setVisible( bool ) );
  359.         reverseButton->setVisible( false );
  360.         widget = reverseButton;
  361.         }
  362.         break;
  363.     case SKIP_BACK_BUTTON: {
  364.         QToolButton *skipBakButton = new QToolButton;
  365.         setupButton( skipBakButton );
  366.         CONNECT_MAP_SET( skipBakButton, SKIP_BACK_ACTION );
  367.         BUTTON_SET_BAR(  skipBakButton );
  368.         ENABLE_ON_INPUT( skipBakButton );
  369.         widget = skipBakButton;
  370.         }
  371.         break;
  372.     case SKIP_FW_BUTTON: {
  373.         QToolButton *skipFwButton = new QToolButton;
  374.         setupButton( skipFwButton );
  375.         CONNECT_MAP_SET( skipFwButton, SKIP_FW_ACTION );
  376.         BUTTON_SET_BAR(  skipFwButton );
  377.         ENABLE_ON_INPUT( skipFwButton );
  378.         widget = skipFwButton;
  379.         }
  380.         break;
  381.     case QUIT_BUTTON: {
  382.         QToolButton *quitButton = new QToolButton;
  383.         setupButton( quitButton );
  384.         CONNECT_MAP_SET( quitButton, QUIT_ACTION );
  385.         BUTTON_SET_BAR(  quitButton );
  386.         widget = quitButton;
  387.         }
  388.         break;
  389.     default:
  390.         msg_Warn( p_intf, "This should not happen %i", button );
  391.         break;
  392.     }
  393.     /* Customize Buttons */
  394.     if( b_flat || b_big )
  395.     {
  396.         QFrame *frame = qobject_cast<QFrame *>(widget);
  397.         if( frame )
  398.         {
  399.             QList<QToolButton *> allTButtons = frame->findChildren<QToolButton *>();
  400.             for( int i = 0; i < allTButtons.size(); i++ )
  401.                 applyAttributes( allTButtons[i], b_flat, b_big );
  402.         }
  403.         else
  404.         {
  405.             QToolButton *tmpButton = qobject_cast<QToolButton *>(widget);
  406.             if( tmpButton )
  407.                 applyAttributes( tmpButton, b_flat, b_big );
  408.         }
  409.     }
  410.     return widget;
  411. }
  412. void AbstractController::applyAttributes( QToolButton *tmpButton, bool b_flat, bool b_big )
  413. {
  414.     if( tmpButton )
  415.     {
  416.         if( b_flat )
  417.             tmpButton->setAutoRaise( b_flat );
  418.         if( b_big )
  419.         {
  420.             tmpButton->setFixedSize( QSize( 32, 32 ) );
  421.             tmpButton->setIconSize( QSize( 26, 26 ) );
  422.         }
  423.     }
  424. }
  425. QFrame *AbstractController::discFrame()
  426. {
  427.     /** Disc and Menus handling */
  428.     QFrame *discFrame = new QFrame( this );
  429.     QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
  430.     discLayout->setSpacing( 0 ); discLayout->setMargin( 0 );
  431.     QToolButton *prevSectionButton = new QToolButton( discFrame );
  432.     setupButton( prevSectionButton );
  433.     BUTTON_SET_BAR2( prevSectionButton, dvd_prev,
  434.             qtr("Previous Chapter/Title" ) );
  435.     discLayout->addWidget( prevSectionButton );
  436.     QToolButton *menuButton = new QToolButton( discFrame );
  437.     setupButton( menuButton );
  438.     discLayout->addWidget( menuButton );
  439.     BUTTON_SET_BAR2( menuButton, dvd_menu, qtr( "Menu" ) );
  440.     QToolButton *nextSectionButton = new QToolButton( discFrame );
  441.     setupButton( nextSectionButton );
  442.     discLayout->addWidget( nextSectionButton );
  443.     BUTTON_SET_BAR2( nextSectionButton, dvd_next,
  444.             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(),
  453.             sectionPrev() );
  454.     CONNECT( nextSectionButton, clicked(), THEMIM->getIM(),
  455.             sectionNext() );
  456.     CONNECT( menuButton, clicked(), THEMIM->getIM(),
  457.             sectionMenu() );
  458.     connect( THEMIM->getIM(), SIGNAL( titleChanged( bool ) ),
  459.              this, SIGNAL( sizeChanged() ) );
  460.     return discFrame;
  461. }
  462. QFrame *AbstractController::telexFrame()
  463. {
  464.     /**
  465.      * Telextext QFrame
  466.      **/
  467.     QFrame *telexFrame = new QFrame;
  468.     QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame );
  469.     telexLayout->setSpacing( 0 ); telexLayout->setMargin( 0 );
  470.     CONNECT( THEMIM->getIM(), teletextPossible( bool ),
  471.              telexFrame, setVisible( bool ) );
  472.     connect( THEMIM->getIM(), SIGNAL( teletextPossible( bool ) ),
  473.              this, SIGNAL( sizeChanged() ) );
  474.     /* On/Off button */
  475.     QToolButton *telexOn = new QToolButton;
  476.     setupButton( telexOn );
  477.     BUTTON_SET_BAR2( telexOn, tv, qtr( "Teletext Activation" ) );
  478.     telexOn->setEnabled( false );
  479.     telexOn->setCheckable( true );
  480.     telexLayout->addWidget( telexOn );
  481.     /* Teletext Activation and set */
  482.     CONNECT( telexOn, clicked( bool ),
  483.              THEMIM->getIM(), activateTeletext( bool ) );
  484.     CONNECT( THEMIM->getIM(), teletextPossible( bool ),
  485.              telexOn, setEnabled( bool ) );
  486.     /* Transparency button */
  487.     QToolButton *telexTransparent = new QToolButton;
  488.     setupButton( telexTransparent );
  489.     BUTTON_SET_BAR2( telexTransparent, tvtelx,
  490.                      qtr( "Toggle Transparency " ) );
  491.     telexTransparent->setEnabled( false );
  492.     telexTransparent->setCheckable( true );
  493.     telexLayout->addWidget( telexTransparent );
  494.     /* Transparency change and set */
  495.     CONNECT( telexTransparent, clicked( bool ),
  496.             THEMIM->getIM(), telexSetTransparency( bool ) );
  497.     CONNECT( THEMIM->getIM(), teletextTransparencyActivated( bool ),
  498.              telexTransparent, setChecked( bool ) );
  499.     /* Page setting */
  500.     QSpinBox *telexPage = new QSpinBox( telexFrame );
  501.     telexPage->setRange( 0, 999 );
  502.     telexPage->setValue( 100 );
  503.     telexPage->setAccelerated( true );
  504.     telexPage->setWrapping( true );
  505.     telexPage->setAlignment( Qt::AlignRight );
  506.     telexPage->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
  507.     telexPage->setEnabled( false );
  508.     telexLayout->addWidget( telexPage );
  509.     /* Page change and set */
  510.     CONNECT( telexPage, valueChanged( int ),
  511.             THEMIM->getIM(), telexSetPage( int ) );
  512.     CONNECT( THEMIM->getIM(), newTelexPageSet( int ),
  513.             telexPage, setValue( int ) );
  514.     CONNECT( THEMIM->getIM(), teletextActivated( bool ), telexPage, setEnabled( bool ) );
  515.     CONNECT( THEMIM->getIM(), teletextActivated( bool ), telexTransparent, setEnabled( bool ) );
  516.     CONNECT( THEMIM->getIM(), teletextActivated( bool ), telexOn, setChecked( bool ) );
  517.     return telexFrame;
  518. }
  519. #undef CONNECT_MAP
  520. #undef SET_MAPPING
  521. #undef CONNECT_MAP_SET
  522. #undef BUTTON_SET_BAR
  523. #undef BUTTON_SET_BAR2
  524. #undef ENABLE_ON_VIDEO
  525. #undef ENABLE_ON_INPUT
  526. #include <QHBoxLayout>
  527. /*****************************
  528.  * DA Control Widget !
  529.  *****************************/
  530. ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
  531.                                 bool b_advControls,
  532.                                 QWidget *_parent ) :
  533.                                 AbstractController( _p_i, _parent )
  534. {
  535.     setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
  536.     /* advanced Controls handling */
  537.     b_advancedVisible = b_advControls;
  538.     QVBoxLayout *controlLayout = new QVBoxLayout( this );
  539.     controlLayout->setLayoutMargins( 6, 4, 6, 2, 5 );
  540.     controlLayout->setSpacing( 0 );
  541.     QHBoxLayout *controlLayout1 = new QHBoxLayout;
  542.     controlLayout1->setSpacing( 0 );
  543.     QString line1 = getSettings()->value( "MainToolbar1", MAIN_TB1_DEFAULT )
  544.                                         .toString();
  545.     parseAndCreate( line1, controlLayout1 );
  546.     QHBoxLayout *controlLayout2 = new QHBoxLayout;
  547.     controlLayout2->setSpacing( 0 );
  548.     QString line2 = getSettings()->value( "MainToolbar2", MAIN_TB2_DEFAULT )
  549.                                         .toString();
  550.     parseAndCreate( line2, controlLayout2 );
  551.     if( !b_advancedVisible && advControls ) advControls->hide();
  552.     controlLayout->addLayout( controlLayout1 );
  553.     controlLayout->addLayout( controlLayout2 );
  554. }
  555. ControlsWidget::~ControlsWidget()
  556. {}
  557. void ControlsWidget::toggleAdvanced()
  558. {
  559.     if( !advControls ) return;
  560.     if( !b_advancedVisible )
  561.     {
  562.         advControls->show();
  563.         b_advancedVisible = true;
  564.     }
  565.     else
  566.     {
  567.         advControls->hide();
  568.         b_advancedVisible = false;
  569.     }
  570.     emit advancedControlsToggled( b_advancedVisible );
  571. }
  572. AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) :
  573.                                      AbstractController( _p_i, _parent )
  574. {
  575.     controlLayout = new QHBoxLayout( this );
  576.     controlLayout->setMargin( 0 );
  577.     controlLayout->setSpacing( 0 );
  578.     QString line = getSettings()->value( "AdvToolbar", ADV_TB_DEFAULT )
  579.         .toString();
  580.     parseAndCreate( line, controlLayout );
  581. }
  582. InputControlsWidget::InputControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) :
  583.                                      AbstractController( _p_i, _parent )
  584. {
  585.     controlLayout = new QHBoxLayout( this );
  586.     controlLayout->setMargin( 0 );
  587.     controlLayout->setSpacing( 0 );
  588.     QString line = getSettings()->value( "InputToolbar", INPT_TB_DEFAULT ).toString();
  589.     parseAndCreate( line, controlLayout );
  590. }
  591. /**********************************************************************
  592.  * Fullscrenn control widget
  593.  **********************************************************************/
  594. FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i, QWidget *_parent )
  595.                            : AbstractController( _p_i, _parent )
  596. {
  597.     i_mouse_last_x      = -1;
  598.     i_mouse_last_y      = -1;
  599.     b_mouse_over        = false;
  600.     i_mouse_last_move_x = -1;
  601.     i_mouse_last_move_y = -1;
  602. #if HAVE_TRANSPARENCY
  603.     b_slow_hide_begin   = false;
  604.     i_slow_hide_timeout = 1;
  605. #endif
  606.     b_fullscreen        = false;
  607.     i_hide_timeout      = 1;
  608.     i_screennumber      = -1;
  609.     vout.clear();
  610.     setWindowFlags( Qt::ToolTip );
  611.     setMinimumWidth( 600 );
  612.     setFrameShape( QFrame::StyledPanel );
  613.     setFrameStyle( QFrame::Sunken );
  614.     setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
  615.     QVBoxLayout *controlLayout2 = new QVBoxLayout( this );
  616.     controlLayout2->setLayoutMargins( 4, 6, 4, 2, 5 );
  617.     /* First line */
  618.     InputControlsWidget *inputC = new InputControlsWidget( p_intf, this );
  619.     controlLayout2->addWidget( inputC );
  620.     controlLayout = new QHBoxLayout;
  621.     QString line = getSettings()->value( "MainWindow/FSCtoolbar", FSC_TB_DEFAULT ).toString();
  622.     parseAndCreate( line, controlLayout );
  623.     controlLayout2->addLayout( controlLayout );
  624.     /* hiding timer */
  625.     p_hideTimer = new QTimer( this );
  626.     CONNECT( p_hideTimer, timeout(), this, hideFSC() );
  627.     p_hideTimer->setSingleShot( true );
  628.     /* slow hiding timer */
  629. #if HAVE_TRANSPARENCY
  630.     p_slowHideTimer = new QTimer( this );
  631.     CONNECT( p_slowHideTimer, timeout(), this, slowHideFSC() );
  632. #endif
  633.     vlc_mutex_init_recursive( &lock );
  634.     CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
  635.              this, setVoutList( vout_thread_t **, int ) );
  636.     /* First Move */
  637.     QPoint pos1 = getSettings()->value( "FullScreen/pos" ).toPoint();
  638.     int number = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
  639.     if( QApplication::desktop()->screenGeometry( number ).contains( pos1, true ) )
  640.     {
  641.         move( pos1 );
  642.         i_screennumber = number;
  643.         screenRes = QApplication::desktop()->screenGeometry(number);
  644.     }
  645.     else
  646.     {
  647.         centerFSC( number );
  648.     }
  649. }
  650. FullscreenControllerWidget::~FullscreenControllerWidget()
  651. {
  652.     getSettings()->setValue( "FullScreen/pos", pos() );
  653.     setVoutList( NULL, 0 );
  654.     vlc_mutex_destroy( &lock );
  655. }
  656. void FullscreenControllerWidget::centerFSC( int number )
  657. {
  658.     screenRes = QApplication::desktop()->screenGeometry(number);
  659.     /* screen has changed, calculate new position */
  660.     QPoint pos = QPoint( screenRes.x() + (screenRes.width() / 2) - (sizeHint().width() / 2),
  661.             screenRes.y() + screenRes.height() - sizeHint().height());
  662.     move( pos );
  663.     i_screennumber = number;
  664. }
  665. /**
  666.  * Show fullscreen controller
  667.  */
  668. void FullscreenControllerWidget::showFSC()
  669. {
  670.     adjustSize();
  671.     int number = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
  672.     if( number != i_screennumber ||
  673.         screenRes != QApplication::desktop()->screenGeometry(number) )
  674.     {
  675.         centerFSC( number );
  676.         msg_Dbg( p_intf, "Recentering the Fullscreen Controller" );
  677.     }
  678. #if HAVE_TRANSPARENCY
  679.     setWindowOpacity( config_GetFloat( p_intf, "qt-fs-opacity" )  );
  680. #endif
  681.     show();
  682. }
  683. /**
  684.  * Plane to hide fullscreen controller
  685.  */
  686. void FullscreenControllerWidget::planHideFSC()
  687. {
  688.     vlc_mutex_lock( &lock );
  689.     int i_timeout = i_hide_timeout;
  690.     vlc_mutex_unlock( &lock );
  691.     p_hideTimer->start( i_timeout );
  692. #if HAVE_TRANSPARENCY
  693.     b_slow_hide_begin = true;
  694.     i_slow_hide_timeout = i_timeout;
  695.     p_slowHideTimer->start( i_slow_hide_timeout / 2 );
  696. #endif
  697. }
  698. /**
  699.  * Hidding fullscreen controller slowly
  700.  * Linux: need composite manager
  701.  * Windows: it is blinking, so it can be enabled by define TRASPARENCY
  702.  */
  703. void FullscreenControllerWidget::slowHideFSC()
  704. {
  705. #if HAVE_TRANSPARENCY
  706.     if( b_slow_hide_begin )
  707.     {
  708.         b_slow_hide_begin = false;
  709.         p_slowHideTimer->stop();
  710.         /* the last part of time divided to 100 pieces */
  711.         p_slowHideTimer->start( (int)( i_slow_hide_timeout / 2 / ( windowOpacity() * 100 ) ) );
  712.     }
  713.     else
  714.     {
  715.          if ( windowOpacity() > 0.0 )
  716.          {
  717.              /* we should use 0.01 because of 100 pieces ^^^
  718.                 but than it cannt be done in time */
  719.              setWindowOpacity( windowOpacity() - 0.02 );
  720.          }
  721.          if ( windowOpacity() <= 0.0 )
  722.              p_slowHideTimer->stop();
  723.     }
  724. #endif
  725. }
  726. /**
  727.  * event handling
  728.  * events: show, hide, start timer for hidding
  729.  */
  730. void FullscreenControllerWidget::customEvent( QEvent *event )
  731. {
  732.     bool b_fs;
  733.     switch( event->type() )
  734.     {
  735.         /* This is used when the 'i' hotkey is used, to force quick toggle */
  736.         case FullscreenControlToggle_Type:
  737.             vlc_mutex_lock( &lock );
  738.             b_fs = b_fullscreen;
  739.             vlc_mutex_unlock( &lock );
  740.             if( b_fs )
  741.             {
  742.                 if( isHidden() )
  743.                 {
  744.                     p_hideTimer->stop();
  745.                     showFSC();
  746.                 }
  747.                 else
  748.                     hideFSC();
  749.             }
  750.             break;
  751.         /* Event called to Show the FSC on mouseChanged() */
  752.         case FullscreenControlShow_Type:
  753.             vlc_mutex_lock( &lock );
  754.             b_fs = b_fullscreen;
  755.             vlc_mutex_unlock( &lock );
  756.             if( b_fs )
  757.                 showFSC();
  758.             break;
  759.         /* Start the timer to hide later, called usually with above case */
  760.         case FullscreenControlPlanHide_Type:
  761.             if( !b_mouse_over ) // Only if the mouse is not over FSC
  762.                 planHideFSC();
  763.             break;
  764.         /* Hide */
  765.         case FullscreenControlHide_Type:
  766.             hideFSC();
  767.             break;
  768.         default:
  769.             break;
  770.     }
  771. }
  772. /**
  773.  * On mouse move
  774.  * moving with FSC
  775.  */
  776. void FullscreenControllerWidget::mouseMoveEvent( QMouseEvent *event )
  777. {
  778.     if( event->buttons() == Qt::LeftButton )
  779.     {
  780.         if( i_mouse_last_x == -1 || i_mouse_last_y == -1 )
  781.             return;
  782.         int i_moveX = event->globalX() - i_mouse_last_x;
  783.         int i_moveY = event->globalY() - i_mouse_last_y;
  784.         move( x() + i_moveX, y() + i_moveY );
  785.         i_mouse_last_x = event->globalX();
  786.         i_mouse_last_y = event->globalY();
  787.     }
  788. }
  789. /**
  790.  * On mouse press
  791.  * store position of cursor
  792.  */
  793. void FullscreenControllerWidget::mousePressEvent( QMouseEvent *event )
  794. {
  795.     i_mouse_last_x = event->globalX();
  796.     i_mouse_last_y = event->globalY();
  797.     event->accept();
  798. }
  799. void FullscreenControllerWidget::mouseReleaseEvent( QMouseEvent *event )
  800. {
  801.     i_mouse_last_x = -1;
  802.     i_mouse_last_y = -1;
  803.     event->accept();
  804. }
  805. /**
  806.  * On mouse go above FSC
  807.  */
  808. void FullscreenControllerWidget::enterEvent( QEvent *event )
  809. {
  810.     b_mouse_over = true;
  811.     p_hideTimer->stop();
  812. #if HAVE_TRANSPARENCY
  813.     p_slowHideTimer->stop();
  814.     setWindowOpacity( DEFAULT_OPACITY );
  815. #endif
  816.     event->accept();
  817. }
  818. /**
  819.  * On mouse go out from FSC
  820.  */
  821. void FullscreenControllerWidget::leaveEvent( QEvent *event )
  822. {
  823.     planHideFSC();
  824.     b_mouse_over = false;
  825.     event->accept();
  826. }
  827. /**
  828.  * When you get pressed key, send it to video output
  829.  * FIXME: clearing focus by clearFocus() to not getting
  830.  * key press events didnt work
  831.  */
  832. void FullscreenControllerWidget::keyPressEvent( QKeyEvent *event )
  833. {
  834.     int i_vlck = qtEventToVLCKey( event );
  835.     if( i_vlck > 0 )
  836.     {
  837.         var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
  838.         event->accept();
  839.     }
  840.     else
  841.         event->ignore();
  842. }
  843. /* */
  844. static int FullscreenControllerWidgetFullscreenChanged( vlc_object_t *vlc_object,
  845.                 const char *variable, vlc_value_t old_val,
  846.                 vlc_value_t new_val,  void *data )
  847. {
  848.     vout_thread_t *p_vout = (vout_thread_t *) vlc_object;
  849.     msg_Dbg( p_vout, "Qt4: Fullscreen state changed" );
  850.     FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
  851.     p_fs->fullscreenChanged( p_vout, new_val.b_bool, var_GetInteger( p_vout, "mouse-hide-timeout" ) );
  852.     return VLC_SUCCESS;
  853. }
  854. /* */
  855. static int FullscreenControllerWidgetMouseMoved( vlc_object_t *vlc_object, const char *variable,
  856.                                                  vlc_value_t old_val, vlc_value_t new_val,
  857.                                                  void *data )
  858. {
  859.     vout_thread_t *p_vout = (vout_thread_t *)vlc_object;
  860.     FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
  861.     /* Get the value from the Vout - Trust the vout more than Qt */
  862.     const int i_mousex = var_GetInteger( p_vout, "mouse-x" );
  863.     const int i_mousey = var_GetInteger( p_vout, "mouse-y" );
  864.     p_fs->mouseChanged( p_vout, i_mousex, i_mousey );
  865.     return VLC_SUCCESS;
  866. }
  867. /**
  868.  * It is call to update the list of vout handled by the fullscreen controller
  869.  */
  870. void FullscreenControllerWidget::setVoutList( vout_thread_t **pp_vout, int i_vout )
  871. {
  872.     QList<vout_thread_t*> del;
  873.     QList<vout_thread_t*> add;
  874.     QList<vout_thread_t*> set;
  875.     /* */
  876.     for( int i = 0; i < i_vout; i++ )
  877.         set += pp_vout[i];
  878.     /* Vout to remove */
  879.     vlc_mutex_lock( &lock );
  880.     foreach( vout_thread_t *p_vout, vout )
  881.     {
  882.         if( !set.contains( p_vout ) )
  883.             del += p_vout;
  884.     }
  885.     vlc_mutex_unlock( &lock );
  886.     foreach( vout_thread_t *p_vout, del )
  887.     {
  888.         var_DelCallback( p_vout, "fullscreen",
  889.                          FullscreenControllerWidgetFullscreenChanged, this );
  890.         vlc_mutex_lock( &lock );
  891.         fullscreenChanged( p_vout, false, 0 );
  892.         vout.removeAll( p_vout );
  893.         vlc_mutex_unlock( &lock );
  894.         vlc_object_release( VLC_OBJECT(p_vout) );
  895.     }
  896.     /* Vout to track */
  897.     vlc_mutex_lock( &lock );
  898.     foreach( vout_thread_t *p_vout, set )
  899.     {
  900.         if( !vout.contains( p_vout ) )
  901.             add += p_vout;
  902.     }
  903.     vlc_mutex_unlock( &lock );
  904.     foreach( vout_thread_t *p_vout, add )
  905.     {
  906.         vlc_object_hold( VLC_OBJECT(p_vout) );
  907.         vlc_mutex_lock( &lock );
  908.         vout.append( p_vout );
  909.         var_AddCallback( p_vout, "fullscreen",
  910.                          FullscreenControllerWidgetFullscreenChanged, this );
  911.         /* I miss a add and fire */
  912.         fullscreenChanged( p_vout, var_GetBool( p_vout, "fullscreen" ),
  913.                            var_GetInteger( p_vout, "mouse-hide-timeout" ) );
  914.         vlc_mutex_unlock( &lock );
  915.     }
  916. }
  917. /**
  918.  * Register and unregister callback for mouse moving
  919.  */
  920. void FullscreenControllerWidget::fullscreenChanged( vout_thread_t *p_vout,
  921.         bool b_fs, int i_timeout )
  922. {
  923.     /* FIXME - multiple vout (ie multiple mouse position ?) and thread safety if multiple vout ? */
  924.     msg_Dbg( p_vout, "Qt: Entering Fullscreen" );
  925.     vlc_mutex_lock( &lock );
  926.     /* Entering fullscreen, register callback */
  927.     if( b_fs && !b_fullscreen )
  928.     {
  929.         b_fullscreen = true;
  930.         i_hide_timeout = i_timeout;
  931.         var_AddCallback( p_vout, "mouse-moved",
  932.                 FullscreenControllerWidgetMouseMoved, this );
  933.     }
  934.     /* Quitting fullscreen, unregistering callback */
  935.     else if( !b_fs && b_fullscreen )
  936.     {
  937.         b_fullscreen = false;
  938.         i_hide_timeout = i_timeout;
  939.         var_DelCallback( p_vout, "mouse-moved",
  940.                 FullscreenControllerWidgetMouseMoved, this );
  941.         /* Force fs hidding */
  942.         IMEvent *eHide = new IMEvent( FullscreenControlHide_Type, 0 );
  943.         QApplication::postEvent( this, eHide );
  944.     }
  945.     vlc_mutex_unlock( &lock );
  946. }
  947. /**
  948.  * Mouse change callback (show/hide the controller on mouse movement)
  949.  */
  950. void FullscreenControllerWidget::mouseChanged( vout_thread_t *p_vout, int i_mousex, int i_mousey )
  951. {
  952.     bool b_toShow;
  953.     /* FIXME - multiple vout (ie multiple mouse position ?) and thread safety if multiple vout ? */
  954.     b_toShow = false;
  955.     if( ( i_mouse_last_move_x == -1 || i_mouse_last_move_y == -1 ) ||
  956.         ( abs( i_mouse_last_move_x - i_mousex ) > 2 ||
  957.           abs( i_mouse_last_move_y - i_mousey ) > 2 ) )
  958.     {
  959.         i_mouse_last_move_x = i_mousex;
  960.         i_mouse_last_move_y = i_mousey;
  961.         b_toShow = true;
  962.     }
  963.     if( b_toShow )
  964.     {
  965.         /* Show event */
  966.         IMEvent *eShow = new IMEvent( FullscreenControlShow_Type, 0 );
  967.         QApplication::postEvent( this, eShow );
  968.         /* Plan hide event */
  969.         IMEvent *eHide = new IMEvent( FullscreenControlPlanHide_Type, 0 );
  970.         QApplication::postEvent( this, eHide );
  971.     }
  972. }