1 /*****************************************************************************
2 * main_interface.cpp : Main interface
3 ****************************************************************************
4 * Copyright (C) 2006-2011 VideoLAN and AUTHORS
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Jean-Baptiste Kempf <jb@videolan.org>
9 * Ilkka Ollakka <ileoo@videolan.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
32 #include "main_interface.hpp"
33 #include "input_manager.hpp" // Creation
34 #include "actions_manager.hpp" // killInstance
35 #include "extensions_manager.hpp" // killInstance
37 #include "util/customwidgets.hpp" // qtEventToVLCKey, QVLCStackedWidget
38 #include "util/qt_dirs.hpp" // toNativeSeparators
40 #include "components/interface_widgets.hpp" // bgWidget, videoWidget
41 #include "components/controller.hpp" // controllers
42 #include "components/playlist/playlist.hpp" // plWidget
43 #include "dialogs/firstrun.hpp" // First Run
45 #include "menus.hpp" // Menu creation
46 #include "recents.hpp" // RecentItems when DnD
48 #include <QCloseEvent>
59 #include <QStackedWidget>
61 #include <vlc_keys.h> /* Wheel event */
62 #include <vlc_vout_display.h> /* vout_thread_t and VOUT_ events */
66 /* Callback prototypes */
67 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
68 vlc_value_t old_val, vlc_value_t new_val, void *param );
69 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
70 vlc_value_t old_val, vlc_value_t new_val, void *param );
71 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
72 vlc_value_t old_val, vlc_value_t new_val, void *param );
73 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
74 vlc_value_t old_val, vlc_value_t new_val,
77 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
79 /* Variables initialisation */
82 playlistWidget = NULL;
83 stackCentralOldWidget= NULL;
85 fullscreenControls = NULL;
90 b_hideAfterCreation = false; // --qt-start-minimized
91 playlistVisible = false;
93 b_interfaceFullScreen= false;
94 b_hasPausedWhenMinimized = false;
98 FirstRun::CheckAndRun( this, p_intf );
101 * Configuration and settings
102 * Pre-building of interface
105 setFocusPolicy( Qt::StrongFocus );
106 setAcceptDrops( true );
107 setWindowRole( "vlc-main" );
108 setWindowIcon( QApplication::windowIcon() );
109 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
111 setAttribute( Qt::WA_MacBrushedMetal );
114 /* Is video in embedded in the UI or not */
115 b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
117 /* Does the interface resize to video size or the opposite */
118 b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
120 /* Are we in the enhanced always-video mode or not ? */
121 b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
123 /* Do we want anoying popups or not */
124 i_notificationSetting = var_InheritInteger( p_intf, "qt-notification" );
127 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
129 /* Set the other interface settings */
130 settings = getSettings();
134 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
138 b_plDocked = getSettings()->value( "MainWindow/pl-dock-status", true ).toBool();
141 /**************************
142 * UI and Widgets design
143 **************************/
144 setVLCWindowsTitle();
149 VLCMenuBar::createMenuBar( this, p_intf );
150 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
151 this, destroyPopupMenu() );
153 createMainWidget( settings );
159 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
161 /********************
163 ********************/
164 MainInputManager::getInstance( p_intf );
169 taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
172 /*********************************
173 * Create the Systray Management *
174 *********************************/
177 /*************************************************************
178 * Connect the input manager to the GUI elements it manages *
179 * Beware initSystray did some connects on input manager too *
180 *************************************************************/
182 * Connects on nameChanged()
183 * Those connects are different because options can impeach them to trigger.
185 /* Main Interface statusbar */
186 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
187 this, setName( const QString& ) );
188 /* and title of the Main Interface*/
189 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
191 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
192 this, setVLCWindowsTitle( const QString& ) );
194 /* END CONNECTS ON IM */
196 /* VideoWidget connects for asynchronous calls */
197 b_videoFullScreen = false;
198 connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
199 this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
200 Qt::BlockingQueuedConnection );
201 connect( this, SIGNAL(askReleaseVideo( void )),
202 this, SLOT(releaseVideoSlot( void )),
203 Qt::BlockingQueuedConnection );
204 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
210 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
211 this, setVideoSize( unsigned int, unsigned int ) );
212 CONNECT( videoWidget, sizeChanged( int, int ),
213 this, resizeStack( int, int ) );
215 CONNECT( this, askVideoSetFullScreen( bool ),
216 this, setVideoFullScreen( bool ) );
219 CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
221 CONNECT( this, askToQuit(), THEDP, quit() );
223 CONNECT( this, askBoss(), this, setBoss() );
224 CONNECT( this, askRaise(), this, setRaise() );
226 /** END of CONNECTS**/
232 var_AddCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
233 var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
234 var_AddCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
236 /* Register callback for the intf-popupmenu variable */
237 var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
240 /* Final Sizing, restoration and placement of the interface */
241 if( settings->value( "MainWindow/playlist-visible", false ).toBool() )
244 QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
246 b_interfaceFullScreen = isFullScreen();
248 setVisible( !b_hideAfterCreation );
250 computeMinimumSize();
252 /* Switch to minimal view if needed, must be called after the show() */
254 toggleMinimalView( true );
257 MainInterface::~MainInterface()
259 /* Unsure we hide the videoWidget before destroying it */
260 if( stackCentralOldWidget == videoWidget )
268 ImageList_Destroy( himl );
274 /* Be sure to kill the actionsManager... Only used in the MI and control */
275 ActionsManager::killInstance();
278 ExtensionsManager::killInstance();
280 /* Delete the FSC controller */
281 delete fullscreenControls;
285 settings->beginGroup("MainWindow");
286 settings->setValue( "pl-dock-status", b_plDocked );
287 /* Save playlist state */
289 settings->setValue( "playlist-visible", playlistVisible );
291 settings->setValue( "adv-controls",
292 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
293 settings->setValue( "status-bar-visible", b_statusbarVisible );
295 /* Save the stackCentralW sizes */
296 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
297 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
298 settings->endGroup();
301 QVLCTools::saveWidgetPosition(settings, this);
303 /* Save undocked playlist size */
304 if( playlistWidget && !isPlDocked() )
305 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
307 delete playlistWidget;
311 /* Unregister callbacks */
312 var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
313 var_DelCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
314 var_DelCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
315 var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
317 p_intf->p_sys->p_mi = NULL;
320 void MainInterface::computeMinimumSize()
323 if( menuBar()->isVisible() )
324 minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
326 setMinimumWidth( minWidth );
329 /*****************************
331 *****************************/
332 void MainInterface::recreateToolbars()
334 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
339 controls = new ControlsWidget( p_intf, b_adv, this );
340 inputC = new InputControlsWidget( p_intf, this );
341 mainLayout->insertWidget( 2, inputC );
342 mainLayout->insertWidget( settings->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
345 if( fullscreenControls )
347 delete fullscreenControls;
348 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
349 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
350 this, handleKeyPress( QKeyEvent * ) );
354 void MainInterface::reloadPrefs()
356 i_notificationSetting = var_InheritInteger( p_intf, "qt-notification" );
357 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
359 p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
361 if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
363 delete fullscreenControls;
364 fullscreenControls = NULL;
368 void MainInterface::createMainWidget( QSettings *creationSettings )
370 /* Create the main Widget and the mainLayout */
371 QWidget *main = new QWidget;
372 setCentralWidget( main );
373 mainLayout = new QVBoxLayout( main );
374 main->setContentsMargins( 0, 0, 0, 0 );
375 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
378 stackCentralW = new QVLCStackedWidget( main );
381 bgWidget = new BackgroundWidget( p_intf );
382 stackCentralW->addWidget( bgWidget );
383 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
384 bgWidget->setWithArt( false );
386 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
387 bgWidget->setExpandstoHeight( true );
389 /* And video Outputs */
390 if( b_videoEmbedded )
392 videoWidget = new VideoWidget( p_intf );
393 stackCentralW->addWidget( videoWidget );
395 mainLayout->insertWidget( 1, stackCentralW );
397 stackWidgetsSizes[bgWidget] =
398 creationSettings->value( "MainWindow/bgSize", QSize( 600, 0 ) ).toSize();
399 /* Resize even if no-auto-resize, because we are at creation */
400 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
402 /* Create the CONTROLS Widget */
403 controls = new ControlsWidget( p_intf,
404 creationSettings->value( "MainWindow/adv-controls", false ).toBool(), this );
405 inputC = new InputControlsWidget( p_intf, this );
407 mainLayout->insertWidget( 2, inputC );
408 mainLayout->insertWidget(
409 creationSettings->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
412 /* Visualisation, disabled for now, they SUCK */
414 visualSelector = new VisualSelector( p_intf );
415 mainLayout->insertWidget( 0, visualSelector );
416 visualSelector->hide();
420 /* Enable the popup menu in the MI */
421 main->setContextMenuPolicy( Qt::CustomContextMenu );
422 CONNECT( main, customContextMenuRequested( const QPoint& ),
423 this, popupMenu( const QPoint& ) );
425 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
426 /* Create the FULLSCREEN CONTROLS Widget */
427 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
429 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
430 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
431 this, handleKeyPress( QKeyEvent * ) );
435 inline void MainInterface::initSystray()
437 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
438 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
440 if( var_InheritBool( p_intf, "qt-start-minimized") )
442 if( b_systrayAvailable )
444 b_systrayWanted = true;
445 b_hideAfterCreation = true;
448 msg_Err( p_intf, "cannot start minimized without system tray bar" );
451 if( b_systrayAvailable && b_systrayWanted )
455 inline void MainInterface::createStatusBar()
460 /* Widgets Creation*/
461 QStatusBar *statusBarr = statusBar();
463 TimeLabel *timeLabel = new TimeLabel( p_intf );
464 nameLabel = new ClickableQLabel();
465 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
466 | Qt::TextSelectableByKeyboard );
467 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
469 /* Styling those labels */
470 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
471 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
472 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
473 timeLabel->setStyleSheet(
474 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
475 speedLabel->setStyleSheet(
476 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
477 /* pad both label and its tooltip */
478 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
480 /* and adding those */
481 statusBarr->addWidget( nameLabel, 8 );
482 statusBarr->addPermanentWidget( speedLabel, 0 );
483 statusBarr->addPermanentWidget( timeLabel, 0 );
485 CONNECT( nameLabel, doubleClicked(), THEDP, epgDialog() );
486 /* timeLabel behaviour:
487 - double clicking opens the goto time dialog
488 - right-clicking and clicking just toggle between remaining and
490 CONNECT( timeLabel, doubleClicked(), THEDP, gotoTimeDialog() );
492 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
493 this, showCryptedLabel( bool ) );
495 CONNECT( THEMIM->getIM(), seekRequested( float ),
496 timeLabel, setDisplayPosition( float ) );
498 /* This shouldn't be necessary, but for somehow reason, the statusBarr
499 starts at height of 20px and when a text is shown it needs more space.
500 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
501 geometry, we need to force a height. If you have a better idea, please
504 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
507 /**********************************************************************
508 * Handling of sizing of the components
509 **********************************************************************/
511 void MainInterface::debug()
514 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
515 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
516 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
518 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
519 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
520 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
524 inline void MainInterface::showVideo() { showTab( videoWidget ); }
525 inline void MainInterface::restoreStackOldWidget()
526 { showTab( stackCentralOldWidget ); }
528 inline void MainInterface::showTab( QWidget *widget )
531 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
534 stackCentralOldWidget = stackCentralW->currentWidget();
535 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
537 /* If we are playing video, embedded */
538 if( videoWidget && THEMIM->getIM()->hasVideo() )
540 /* Video -> Playlist */
541 if( videoWidget == stackCentralOldWidget && widget == playlistWidget )
543 stackCentralW->removeWidget( videoWidget );
544 videoWidget->show(); videoWidget->raise();
547 /* Playlist -> Video */
548 if( playlistWidget == stackCentralOldWidget && widget == videoWidget )
550 playlistWidget->artContainer->removeWidget( videoWidget );
551 videoWidget->show(); videoWidget->raise();
552 stackCentralW->addWidget( videoWidget );
555 /* Embedded playlist -> Non-embedded playlist */
556 if( bgWidget == stackCentralOldWidget && widget == videoWidget )
558 playlistWidget->artContainer->removeWidget( videoWidget );
559 videoWidget->show(); videoWidget->raise();
560 stackCentralW->addWidget( videoWidget );
561 stackCentralW->setCurrentWidget( videoWidget );
565 stackCentralW->setCurrentWidget( widget );
567 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
570 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
571 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
574 /* This part is done later, to account for the new pl size */
575 if( videoWidget && THEMIM->getIM()->hasVideo() &&
576 videoWidget == stackCentralOldWidget && widget == playlistWidget )
578 playlistWidget->artContainer->addWidget( videoWidget );
579 playlistWidget->artContainer->setCurrentWidget( videoWidget );
583 void MainInterface::destroyPopupMenu()
585 VLCMenuBar::PopupMenu( p_intf, false );
588 void MainInterface::popupMenu( const QPoint & )
590 VLCMenuBar::PopupMenu( p_intf, true );
593 void MainInterface::toggleFSC()
595 if( !fullscreenControls ) return;
597 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
598 QApplication::postEvent( fullscreenControls, eShow );
601 /****************************************************************************
603 ****************************************************************************/
607 * You must not change the state of this object or other Qt4 UI objects,
608 * from the video output thread - only from the Qt4 UI main loop thread.
609 * All window provider queries must be handled through signals or events.
610 * That's why we have all those emit statements...
612 WId MainInterface::getVideo( int *pi_x, int *pi_y,
613 unsigned int *pi_width, unsigned int *pi_height )
618 /* This is a blocking call signal. Results are returned through pointers.
619 * Beware of deadlocks! */
621 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
625 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
626 unsigned *pi_width, unsigned *pi_height )
628 /* Hidden or minimized, activate */
629 if( isHidden() || isMinimized() )
630 toggleUpdateSystrayMenu();
632 /* Request the videoWidget */
633 WId ret = videoWidget->request( pi_x, pi_y,
634 pi_width, pi_height, !b_autoresize );
636 if( ret ) /* The videoWidget is available */
638 /* Consider the video active now */
641 /* Ask videoWidget to resize correctly, if we are in normal mode */
642 if( !isFullScreen() && !isMaximized() && b_autoresize )
643 videoWidget->SetSizing( *pi_width, *pi_height );
647 /* Asynchronous call from the WindowClose function */
648 void MainInterface::releaseVideo( void )
650 emit askReleaseVideo();
653 /* Function that is CONNECTED to the previous emit */
654 void MainInterface::releaseVideoSlot( void )
656 /* This function is called when the embedded video window is destroyed,
657 * or in the rare case that the embedded window is still here but the
658 * Qt4 interface exits. */
659 assert( videoWidget );
660 videoWidget->release();
661 setVideoOnTop( false );
662 setVideoFullScreen( false );
664 if( stackCentralW->currentWidget() == videoWidget )
665 restoreStackOldWidget();
666 else if( playlistWidget &&
667 playlistWidget->artContainer->currentWidget() == videoWidget )
669 playlistWidget->artContainer->setCurrentIndex( 0 );
670 stackCentralW->addWidget( videoWidget );
673 /* We don't want to have a blank video to popup */
674 stackCentralOldWidget = bgWidget;
677 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
679 if( !isFullScreen() && !isMaximized() )
680 videoWidget->SetSizing( w, h );
683 void MainInterface::setVideoFullScreen( bool fs )
685 b_videoFullScreen = fs;
688 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
689 /* if user hasn't defined screennumber, or screennumber that is bigger
690 * than current number of screens, take screennumber where current interface
693 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
694 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
696 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
698 /* To be sure window is on proper-screen in xinerama */
699 if( !screenres.contains( pos() ) )
701 msg_Dbg( p_intf, "Moving video to correct screen");
702 move( QPoint( screenres.x(), screenres.y() ) );
706 if( playlistWidget != NULL && playlistWidget->artContainer->currentWidget() == videoWidget )
708 showTab( videoWidget );
712 setMinimalView( true );
713 setInterfaceFullScreen( true );
717 /* TODO do we want to restore screen and position ? (when
718 * qt-fullscreen-screennumber is forced) */
719 setMinimalView( b_minimalView );
720 setInterfaceFullScreen( b_interfaceFullScreen );
725 /* Slot to change the video always-on-top flag.
726 * Emit askVideoOnTop() to invoke this from other thread. */
727 void MainInterface::setVideoOnTop( bool on_top )
729 Qt::WindowFlags oldflags = windowFlags(), newflags;
732 newflags = oldflags | Qt::WindowStaysOnTopHint;
734 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
735 if( newflags != oldflags && !b_videoFullScreen )
738 setWindowFlags( newflags );
739 show(); /* necessary to apply window flags */
743 /* Asynchronous call from WindowControl function */
744 int MainInterface::controlVideo( int i_query, va_list args )
748 case VOUT_WINDOW_SET_SIZE:
750 unsigned int i_width = va_arg( args, unsigned int );
751 unsigned int i_height = va_arg( args, unsigned int );
753 emit askVideoToResize( i_width, i_height );
756 case VOUT_WINDOW_SET_STATE:
758 unsigned i_arg = va_arg( args, unsigned );
759 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
761 emit askVideoOnTop( on_top != 0 );
764 case VOUT_WINDOW_SET_FULLSCREEN:
766 bool b_fs = va_arg( args, int );
768 emit askVideoSetFullScreen( b_fs );
772 msg_Warn( p_intf, "unsupported control query" );
777 /*****************************************************************************
778 * Playlist, Visualisation and Menus handling
779 *****************************************************************************/
781 * Toggle the playlist widget or dialog
783 void MainInterface::createPlaylist()
785 playlistWidget = new PlaylistWidget( p_intf, this );
789 stackCentralW->addWidget( playlistWidget );
790 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
795 playlistWidget->setParent( NULL );
797 playlistWidget->setWindowFlags( Qt::Window );
799 /* This will restore the geometry but will not work for position,
800 because of parenting */
801 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
802 playlistWidget, QSize( 600, 300 ) );
806 void MainInterface::togglePlaylist()
808 if( !playlistWidget )
815 /* Playlist is not visible, show it */
816 if( stackCentralW->currentWidget() != playlistWidget )
818 if( stackCentralW->indexOf( playlistWidget ) == -1 )
819 stackCentralW->addWidget( playlistWidget );
820 showTab( playlistWidget );
824 restoreStackOldWidget();
826 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
831 playlistWidget->setParent( NULL );
833 playlistWidget->setWindowFlags( Qt::Window );
834 playlistVisible = !playlistVisible;
835 playlistWidget->setVisible( playlistVisible );
840 void MainInterface::dockPlaylist( bool p_docked )
842 if( b_plDocked == p_docked ) return;
843 b_plDocked = p_docked;
845 if( !playlistWidget ) return; /* Playlist wasn't created yet */
846 if( !p_docked ) /* Previously docked */
848 /* If playlist is invisible don't show it */
849 if( stackCentralW->currentWidget() != playlistWidget ) return;
850 stackCentralW->removeWidget( playlistWidget );
852 playlistWidget->setParent( NULL );
854 playlistWidget->setWindowFlags( Qt::Window );
855 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
856 playlistWidget, QSize( 600, 300 ) );
857 playlistWidget->show();
858 restoreStackOldWidget();
860 else /* Previously undocked */
862 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
863 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
864 // It would be logical that QStackWidget::addWidget reset the flags...
865 stackCentralW->addWidget( playlistWidget );
867 /* If playlist is invisible don't show it */
868 if( !playlistWidget->isVisible() ) return;
869 showTab( playlistWidget );
871 playlistVisible = true;
875 * setMinimalView is the private function used by
876 * the SLOT toggleMinimalView and setVideoFullScreen
878 void MainInterface::setMinimalView( bool b_minimal )
880 menuBar()->setVisible( !b_minimal );
881 controls->setVisible( !b_minimal );
882 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
883 inputC->setVisible( !b_minimal );
887 * This public SLOT is used for moving to minimal View Mode
889 * If b_minimal is false, then we are normalView
891 void MainInterface::toggleMinimalView( bool b_minimal )
893 if( !b_minimalView && b_autoresize ) /* Normal mode */
895 if( stackCentralW->currentWidget() == bgWidget )
897 if( stackCentralW->height() < 16 )
899 resizeStack( stackCentralW->width(), 100 );
903 b_minimalView = b_minimal;
904 if( !b_videoFullScreen )
906 setMinimalView( b_minimalView );
907 computeMinimumSize();
910 emit minimalViewToggled( b_minimalView );
913 /* toggling advanced controls buttons */
914 void MainInterface::toggleAdvancedButtons()
916 controls->toggleAdvanced();
917 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
920 /* Get the visibility status of the controls (hidden or not, advanced or not) */
921 int MainInterface::getControlsVisibilityStatus()
923 if( !controls ) return 0;
924 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
925 + CONTROLS_ADVANCED * controls->b_advancedVisible );
928 void MainInterface::setStatusBarVisibility( bool b_visible )
930 statusBar()->setVisible( b_visible );
931 b_statusbarVisible = b_visible;
932 if( controls ) controls->setGripVisible( !b_statusbarVisible );
936 void MainInterface::visual()
938 if( !VISIBLE( visualSelector) )
940 visualSelector->show();
941 if( !THEMIM->getIM()->hasVideo() )
943 /* Show the background widget */
945 visualSelectorEnabled = true;
949 /* Stop any currently running visualization */
950 visualSelector->hide();
951 visualSelectorEnabled = false;
956 /************************************************************************
958 ************************************************************************/
959 void MainInterface::setName( const QString& name )
961 input_name = name; /* store it for the QSystray use */
962 /* Display it in the status bar, but also as a Tooltip in case it doesn't
964 nameLabel->setText( name );
965 nameLabel->setToolTip( name );
969 * Give the decorations of the Main Window a correct Name.
970 * If nothing is given, set it to VLC...
972 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
974 if( aTitle.isEmpty() )
976 setWindowTitle( qtr( "VLC media player" ) );
980 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
984 void MainInterface::showCryptedLabel( bool b_show )
986 if( cryptedLabel == NULL )
988 cryptedLabel = new QLabel;
989 // The lock icon is not the right one for DRM protection/scrambled.
990 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
991 cryptedLabel->setText( "DRM" );
992 statusBar()->addWidget( cryptedLabel );
995 cryptedLabel->setVisible( b_show );
998 void MainInterface::showBuffering( float f_cache )
1000 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
1001 statusBar()->showMessage( amount, 1000 );
1004 /*****************************************************************************
1005 * Systray Icon and Systray Menu
1006 *****************************************************************************/
1008 * Create a SystemTray icon and a menu that would go with it.
1009 * Connects to a click handler on the icon.
1011 void MainInterface::createSystray()
1014 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
1015 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
1017 iconVLC = QIcon( ":/logo/vlc128.png" );
1018 sysTray = new QSystemTrayIcon( iconVLC, this );
1019 sysTray->setToolTip( qtr( "VLC media player" ));
1021 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
1022 systrayMenu->setIcon( iconVLC );
1024 VLCMenuBar::updateSystrayMenu( this, p_intf, true );
1027 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
1028 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
1030 /* Connects on nameChanged() */
1031 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
1032 this, updateSystrayTooltipName( const QString& ) );
1033 /* Connect PLAY_STATUS on the systray */
1034 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
1035 this, updateSystrayTooltipStatus( int ) );
1039 * Updates the Systray Icon's menu and toggle the main interface
1041 void MainInterface::toggleUpdateSystrayMenu()
1043 /* If hidden, show it */
1049 else if( isMinimized() )
1057 /* Visible (possibly under other windows) */
1059 /* check if any visible window is above vlc in the z-order,
1060 * but ignore the ones always on top
1061 * and the ones which can't be activated */
1064 wi.cbSize = sizeof( WINDOWINFO );
1065 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1066 hwnd && ( !IsWindowVisible( hwnd ) ||
1067 ( GetWindowInfo( hwnd, &wi ) &&
1068 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1069 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1070 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1071 (wi.dwExStyle&WS_EX_TOPMOST) )
1084 VLCMenuBar::updateSystrayMenu( this, p_intf );
1087 /* First Item of the systray menu */
1088 void MainInterface::showUpdateSystrayMenu()
1096 VLCMenuBar::updateSystrayMenu( this, p_intf );
1099 /* First Item of the systray menu */
1100 void MainInterface::hideUpdateSystrayMenu()
1103 VLCMenuBar::updateSystrayMenu( this, p_intf );
1106 /* Click on systray Icon */
1107 void MainInterface::handleSystrayClick(
1108 QSystemTrayIcon::ActivationReason reason )
1112 case QSystemTrayIcon::Trigger:
1113 case QSystemTrayIcon::DoubleClick:
1115 VLCMenuBar::updateSystrayMenu( this, p_intf );
1117 toggleUpdateSystrayMenu();
1120 case QSystemTrayIcon::MiddleClick:
1121 sysTray->showMessage( qtr( "VLC media player" ),
1122 qtr( "Control menu for the player" ),
1123 QSystemTrayIcon::Information, 3000 );
1131 * Updates the name of the systray Icon tooltip.
1132 * Doesn't check if the systray exists, check before you call it.
1134 void MainInterface::updateSystrayTooltipName( const QString& name )
1136 if( name.isEmpty() )
1138 sysTray->setToolTip( qtr( "VLC media player" ) );
1142 sysTray->setToolTip( name );
1143 if( ( i_notificationSetting == NOTIFICATION_ALWAYS ) ||
1144 ( i_notificationSetting == NOTIFICATION_MINIMIZED && (isMinimized() || isHidden()) ) )
1146 sysTray->showMessage( qtr( "VLC media player" ), name,
1147 QSystemTrayIcon::NoIcon, 3000 );
1151 VLCMenuBar::updateSystrayMenu( this, p_intf );
1155 * Updates the status of the systray Icon tooltip.
1156 * Doesn't check if the systray exists, check before you call it.
1158 void MainInterface::updateSystrayTooltipStatus( int i_status )
1163 sysTray->setToolTip( input_name );
1166 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1169 sysTray->setToolTip( qtr( "VLC media player" ) );
1172 VLCMenuBar::updateSystrayMenu( this, p_intf );
1175 void MainInterface::changeEvent(QEvent *event)
1177 if( event->type() == QEvent::WindowStateChange )
1179 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1180 Qt::WindowStates newState = windowState();
1181 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1183 if( newState & Qt::WindowMinimized )
1185 b_hasPausedWhenMinimized = false;
1187 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1188 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1191 b_hasPausedWhenMinimized = true;
1195 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1197 if( b_hasPausedWhenMinimized )
1204 QWidget::changeEvent(event);
1207 /************************************************************************
1209 ************************************************************************/
1210 void MainInterface::dropEvent(QDropEvent *event)
1212 dropEventPlay( event, true );
1218 * Event called if something is dropped onto a VLC window
1219 * \param event the event in question
1220 * \param b_play whether to play the file immediately
1221 * \param b_playlist true to add to playlist, false to add to media library
1224 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play, bool b_playlist )
1226 if( event->possibleActions() & ( Qt::CopyAction | Qt::MoveAction ) )
1227 event->setDropAction( Qt::CopyAction );
1231 const QMimeData *mimeData = event->mimeData();
1233 /* D&D of a subtitles file, add it on the fly */
1234 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1236 if( !input_AddSubtitle( THEMIM->getInput(),
1237 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1245 bool first = b_play;
1246 foreach( const QUrl &url, mimeData->urls() )
1250 QString mrl = toURI( url.toEncoded().constData() );
1251 playlist_Add( THEPL, qtu(mrl), NULL,
1252 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1253 PLAYLIST_END, b_playlist, pl_Unlocked );
1255 RecentsMRL::getInstance( p_intf )->addRecent( mrl );
1259 /* Browsers give content as text if you dnd the addressbar,
1260 so check if mimedata has valid url in text and use it
1261 if we didn't get any normal Urls()*/
1262 if( !mimeData->hasUrls() && mimeData->hasText() &&
1263 QUrl(mimeData->text()).isValid() )
1265 QString mrl = toURI( mimeData->text() );
1266 playlist_Add( THEPL, qtu(mrl), NULL,
1267 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1268 PLAYLIST_END, b_playlist, pl_Unlocked );
1272 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1274 event->acceptProposedAction();
1276 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1278 event->acceptProposedAction();
1280 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1285 /************************************************************************
1287 ************************************************************************/
1288 void MainInterface::keyPressEvent( QKeyEvent *e )
1290 handleKeyPress( e );
1293 void MainInterface::handleKeyPress( QKeyEvent *e )
1295 if( ( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) ) ||
1296 ( b_minimalView && !b_videoFullScreen && e->key() == Qt::Key_Escape ) )
1298 toggleMinimalView( !b_minimalView );
1302 int i_vlck = qtEventToVLCKey( e );
1305 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1312 void MainInterface::wheelEvent( QWheelEvent *e )
1314 int i_vlckey = qtWheelEventToVLCKey( e );
1315 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1319 void MainInterface::closeEvent( QCloseEvent *e )
1322 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1323 /* Accept session quit. Otherwise we break the desktop mamager. */
1327 void MainInterface::setInterfaceFullScreen( bool fs )
1330 setWindowState( windowState() | Qt::WindowFullScreen );
1332 setWindowState( windowState() & ~Qt::WindowFullScreen );
1334 void MainInterface::toggleInterfaceFullScreen()
1336 b_interfaceFullScreen = !b_interfaceFullScreen;
1337 if( !b_videoFullScreen )
1338 setInterfaceFullScreen( b_interfaceFullScreen );
1339 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1342 void MainInterface::emitBoss()
1346 void MainInterface::setBoss()
1359 void MainInterface::emitRaise()
1363 void MainInterface::setRaise()
1369 /*****************************************************************************
1370 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1371 * We don't show the menu directly here because we don't want the
1372 * caller to block for a too long time.
1373 *****************************************************************************/
1374 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1375 vlc_value_t old_val, vlc_value_t new_val, void *param )
1377 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1379 intf_thread_t *p_intf = (intf_thread_t *)param;
1381 if( p_intf->pf_show_dialog )
1383 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1384 new_val.b_bool, NULL );
1390 /*****************************************************************************
1391 * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1392 *****************************************************************************/
1393 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1394 vlc_value_t old_val, vlc_value_t new_val, void *param )
1396 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1397 VLC_UNUSED( new_val );
1399 intf_thread_t *p_intf = (intf_thread_t *)param;
1400 p_intf->p_sys->p_mi->toggleFSC();
1406 /*****************************************************************************
1407 * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1408 *****************************************************************************/
1409 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
1410 vlc_value_t old_val, vlc_value_t new_val, void *param )
1412 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1413 VLC_UNUSED( new_val );
1415 intf_thread_t *p_intf = (intf_thread_t *)param;
1416 p_intf->p_sys->p_mi->emitRaise();
1421 /*****************************************************************************
1422 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1423 *****************************************************************************/
1424 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1425 vlc_value_t old_val, vlc_value_t new_val, void *param )
1427 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1428 VLC_UNUSED( new_val );
1430 intf_thread_t *p_intf = (intf_thread_t *)param;
1431 p_intf->p_sys->p_mi->emitBoss();