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 b_notificationEnabled = var_InheritBool( 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 b_notificationEnabled = var_InheritBool( 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 *settings )
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] = settings->value( "MainWindow/bgSize", QSize( 600, 0 ) ).toSize();
398 /* Resize even if no-auto-resize, because we are at creation */
399 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
401 /* Create the CONTROLS Widget */
402 controls = new ControlsWidget( p_intf,
403 settings->value( "MainWindow/adv-controls", false ).toBool(), this );
404 inputC = new InputControlsWidget( p_intf, this );
406 mainLayout->insertWidget( 2, inputC );
407 mainLayout->insertWidget( settings->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
410 /* Visualisation, disabled for now, they SUCK */
412 visualSelector = new VisualSelector( p_intf );
413 mainLayout->insertWidget( 0, visualSelector );
414 visualSelector->hide();
418 /* Enable the popup menu in the MI */
419 main->setContextMenuPolicy( Qt::CustomContextMenu );
420 CONNECT( main, customContextMenuRequested( const QPoint& ),
421 this, popupMenu( const QPoint& ) );
423 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
424 /* Create the FULLSCREEN CONTROLS Widget */
425 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
427 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
428 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
429 this, handleKeyPress( QKeyEvent * ) );
433 inline void MainInterface::initSystray()
435 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
436 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
438 if( var_InheritBool( p_intf, "qt-start-minimized") )
440 if( b_systrayAvailable )
442 b_systrayWanted = true;
443 b_hideAfterCreation = true;
446 msg_Err( p_intf, "cannot start minimized without system tray bar" );
449 if( b_systrayAvailable && b_systrayWanted )
453 inline void MainInterface::createStatusBar()
458 /* Widgets Creation*/
459 QStatusBar *statusBarr = statusBar();
461 TimeLabel *timeLabel = new TimeLabel( p_intf );
462 nameLabel = new QLabel( this );
463 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
464 | Qt::TextSelectableByKeyboard );
465 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
467 /* Styling those labels */
468 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
469 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
470 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
471 timeLabel->setStyleSheet(
472 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
473 speedLabel->setStyleSheet(
474 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
475 /* pad both label and its tooltip */
476 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
478 /* and adding those */
479 statusBarr->addWidget( nameLabel, 8 );
480 statusBarr->addPermanentWidget( speedLabel, 0 );
481 statusBarr->addPermanentWidget( timeLabel, 0 );
483 /* timeLabel behaviour:
484 - double clicking opens the goto time dialog
485 - right-clicking and clicking just toggle between remaining and
487 CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
489 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
490 this, showCryptedLabel( bool ) );
492 CONNECT( THEMIM->getIM(), seekRequested( float ),
493 timeLabel, setDisplayPosition( float ) );
495 /* This shouldn't be necessary, but for somehow reason, the statusBarr
496 starts at height of 20px and when a text is shown it needs more space.
497 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
498 geometry, we need to force a height. If you have a better idea, please
501 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
504 /**********************************************************************
505 * Handling of sizing of the components
506 **********************************************************************/
508 void MainInterface::debug()
511 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
512 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
513 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
515 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
516 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
517 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
521 inline void MainInterface::showVideo() { showTab( videoWidget ); }
522 inline void MainInterface::restoreStackOldWidget()
523 { showTab( stackCentralOldWidget ); }
525 inline void MainInterface::showTab( QWidget *widget )
528 msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
531 stackCentralOldWidget = stackCentralW->currentWidget();
532 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
534 /* If we are playing video, embedded */
535 if( videoWidget && THEMIM->getIM()->hasVideo() )
537 /* Video -> Playlist */
538 if( videoWidget == stackCentralOldWidget && widget == playlistWidget )
540 stackCentralW->removeWidget( videoWidget );
541 videoWidget->show(); videoWidget->raise();
544 /* Playlist -> Video */
545 if( playlistWidget == stackCentralOldWidget && widget == videoWidget )
547 playlistWidget->artContainer->removeWidget( videoWidget );
548 videoWidget->show(); videoWidget->raise();
549 stackCentralW->addWidget( videoWidget );
552 /* Embedded playlist -> Non-embedded playlist */
553 if( bgWidget == stackCentralOldWidget && widget == videoWidget )
555 playlistWidget->artContainer->removeWidget( videoWidget );
556 videoWidget->show(); videoWidget->raise();
557 stackCentralW->addWidget( videoWidget );
558 stackCentralW->setCurrentWidget( videoWidget );
562 stackCentralW->setCurrentWidget( widget );
564 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
567 msg_Warn( p_intf, "State change %i", stackCentralW->currentIndex() );
568 msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
571 /* This part is done later, to account for the new pl size */
572 if( videoWidget && THEMIM->getIM()->hasVideo() &&
573 videoWidget == stackCentralOldWidget && widget == playlistWidget )
575 playlistWidget->artContainer->addWidget( videoWidget );
576 playlistWidget->artContainer->setCurrentWidget( videoWidget );
580 void MainInterface::destroyPopupMenu()
582 VLCMenuBar::PopupMenu( p_intf, false );
585 void MainInterface::popupMenu( const QPoint & )
587 VLCMenuBar::PopupMenu( p_intf, true );
590 void MainInterface::toggleFSC()
592 if( !fullscreenControls ) return;
594 IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
595 QApplication::postEvent( fullscreenControls, eShow );
598 /****************************************************************************
600 ****************************************************************************/
604 * You must not change the state of this object or other Qt4 UI objects,
605 * from the video output thread - only from the Qt4 UI main loop thread.
606 * All window provider queries must be handled through signals or events.
607 * That's why we have all those emit statements...
609 WId MainInterface::getVideo( int *pi_x, int *pi_y,
610 unsigned int *pi_width, unsigned int *pi_height )
615 /* This is a blocking call signal. Results are returned through pointers.
616 * Beware of deadlocks! */
618 emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
622 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
623 unsigned *pi_width, unsigned *pi_height )
625 /* Hidden or minimized, activate */
626 if( isHidden() || isMinimized() )
627 toggleUpdateSystrayMenu();
629 /* Request the videoWidget */
630 WId ret = videoWidget->request( pi_x, pi_y,
631 pi_width, pi_height, !b_autoresize );
633 if( ret ) /* The videoWidget is available */
635 /* Consider the video active now */
638 /* Ask videoWidget to resize correctly, if we are in normal mode */
639 if( !isFullScreen() && !isMaximized() && b_autoresize )
640 videoWidget->SetSizing( *pi_width, *pi_height );
644 /* Asynchronous call from the WindowClose function */
645 void MainInterface::releaseVideo( void )
647 emit askReleaseVideo();
650 /* Function that is CONNECTED to the previous emit */
651 void MainInterface::releaseVideoSlot( void )
653 /* This function is called when the embedded video window is destroyed,
654 * or in the rare case that the embedded window is still here but the
655 * Qt4 interface exits. */
656 assert( videoWidget );
657 videoWidget->release();
658 setVideoOnTop( false );
659 setVideoFullScreen( false );
661 if( stackCentralW->currentWidget() == videoWidget )
662 restoreStackOldWidget();
663 else if( playlistWidget &&
664 playlistWidget->artContainer->currentWidget() == videoWidget )
666 playlistWidget->artContainer->setCurrentIndex( 0 );
667 stackCentralW->addWidget( videoWidget );
670 /* We don't want to have a blank video to popup */
671 stackCentralOldWidget = bgWidget;
674 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
676 if( !isFullScreen() && !isMaximized() )
677 videoWidget->SetSizing( w, h );
680 void MainInterface::setVideoFullScreen( bool fs )
682 b_videoFullScreen = fs;
685 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
686 /* if user hasn't defined screennumber, or screennumber that is bigger
687 * than current number of screens, take screennumber where current interface
690 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
691 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
693 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
695 /* To be sure window is on proper-screen in xinerama */
696 if( !screenres.contains( pos() ) )
698 msg_Dbg( p_intf, "Moving video to correct screen");
699 move( QPoint( screenres.x(), screenres.y() ) );
703 if( playlistWidget != NULL && playlistWidget->artContainer->currentWidget() == videoWidget )
705 showTab( videoWidget );
709 setMinimalView( true );
710 setInterfaceFullScreen( true );
714 /* TODO do we want to restore screen and position ? (when
715 * qt-fullscreen-screennumber is forced) */
716 setMinimalView( b_minimalView );
717 setInterfaceFullScreen( b_interfaceFullScreen );
722 /* Slot to change the video always-on-top flag.
723 * Emit askVideoOnTop() to invoke this from other thread. */
724 void MainInterface::setVideoOnTop( bool on_top )
726 Qt::WindowFlags oldflags = windowFlags(), newflags;
729 newflags = oldflags | Qt::WindowStaysOnTopHint;
731 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
732 if( newflags != oldflags && !b_videoFullScreen )
735 setWindowFlags( newflags );
736 show(); /* necessary to apply window flags */
740 /* Asynchronous call from WindowControl function */
741 int MainInterface::controlVideo( int i_query, va_list args )
745 case VOUT_WINDOW_SET_SIZE:
747 unsigned int i_width = va_arg( args, unsigned int );
748 unsigned int i_height = va_arg( args, unsigned int );
750 emit askVideoToResize( i_width, i_height );
753 case VOUT_WINDOW_SET_STATE:
755 unsigned i_arg = va_arg( args, unsigned );
756 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
758 emit askVideoOnTop( on_top != 0 );
761 case VOUT_WINDOW_SET_FULLSCREEN:
763 bool b_fs = va_arg( args, int );
765 emit askVideoSetFullScreen( b_fs );
769 msg_Warn( p_intf, "unsupported control query" );
774 /*****************************************************************************
775 * Playlist, Visualisation and Menus handling
776 *****************************************************************************/
778 * Toggle the playlist widget or dialog
780 void MainInterface::createPlaylist()
782 playlistWidget = new PlaylistWidget( p_intf, this );
786 stackCentralW->addWidget( playlistWidget );
787 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
792 playlistWidget->setParent( NULL );
794 playlistWidget->setWindowFlags( Qt::Window );
796 /* This will restore the geometry but will not work for position,
797 because of parenting */
798 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
799 playlistWidget, QSize( 600, 300 ) );
803 void MainInterface::togglePlaylist()
805 if( !playlistWidget )
812 /* Playlist is not visible, show it */
813 if( stackCentralW->currentWidget() != playlistWidget )
815 if( stackCentralW->indexOf( playlistWidget ) == -1 )
816 stackCentralW->addWidget( playlistWidget );
817 showTab( playlistWidget );
821 restoreStackOldWidget();
823 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
828 playlistWidget->setParent( NULL );
830 playlistWidget->setWindowFlags( Qt::Window );
831 playlistVisible = !playlistVisible;
832 playlistWidget->setVisible( playlistVisible );
837 void MainInterface::dockPlaylist( bool p_docked )
839 if( b_plDocked == p_docked ) return;
840 b_plDocked = p_docked;
842 if( !playlistWidget ) return; /* Playlist wasn't created yet */
843 if( !p_docked ) /* Previously docked */
845 /* If playlist is invisible don't show it */
846 if( stackCentralW->currentWidget() != playlistWidget ) return;
847 stackCentralW->removeWidget( playlistWidget );
849 playlistWidget->setParent( NULL );
851 playlistWidget->setWindowFlags( Qt::Window );
852 QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
853 playlistWidget, QSize( 600, 300 ) );
854 playlistWidget->show();
855 restoreStackOldWidget();
857 else /* Previously undocked */
859 QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
860 playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
861 // It would be logical that QStackWidget::addWidget reset the flags...
862 stackCentralW->addWidget( playlistWidget );
864 /* If playlist is invisible don't show it */
865 if( !playlistWidget->isVisible() ) return;
866 showTab( playlistWidget );
868 playlistVisible = true;
872 * setMinimalView is the private function used by
873 * the SLOT toggleMinimalView and setVideoFullScreen
875 void MainInterface::setMinimalView( bool b_minimal )
877 menuBar()->setVisible( !b_minimal );
878 controls->setVisible( !b_minimal );
879 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
880 inputC->setVisible( !b_minimal );
884 * This public SLOT is used for moving to minimal View Mode
886 * If b_minimal is false, then we are normalView
888 void MainInterface::toggleMinimalView( bool b_minimal )
890 if( !b_minimalView && b_autoresize ) /* Normal mode */
892 if( stackCentralW->currentWidget() == bgWidget )
894 if( stackCentralW->height() < 16 )
896 resizeStack( stackCentralW->width(), 100 );
900 b_minimalView = b_minimal;
901 if( !b_videoFullScreen )
903 setMinimalView( b_minimalView );
904 computeMinimumSize();
907 emit minimalViewToggled( b_minimalView );
910 /* toggling advanced controls buttons */
911 void MainInterface::toggleAdvancedButtons()
913 controls->toggleAdvanced();
914 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
917 /* Get the visibility status of the controls (hidden or not, advanced or not) */
918 int MainInterface::getControlsVisibilityStatus()
920 if( !controls ) return 0;
921 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
922 + CONTROLS_ADVANCED * controls->b_advancedVisible );
925 void MainInterface::setStatusBarVisibility( bool b_visible )
927 statusBar()->setVisible( b_visible );
928 b_statusbarVisible = b_visible;
929 if( controls ) controls->setGripVisible( !b_statusbarVisible );
933 void MainInterface::visual()
935 if( !VISIBLE( visualSelector) )
937 visualSelector->show();
938 if( !THEMIM->getIM()->hasVideo() )
940 /* Show the background widget */
942 visualSelectorEnabled = true;
946 /* Stop any currently running visualization */
947 visualSelector->hide();
948 visualSelectorEnabled = false;
953 /************************************************************************
955 ************************************************************************/
956 void MainInterface::setName( const QString& name )
958 input_name = name; /* store it for the QSystray use */
959 /* Display it in the status bar, but also as a Tooltip in case it doesn't
961 nameLabel->setText( name );
962 nameLabel->setToolTip( name );
966 * Give the decorations of the Main Window a correct Name.
967 * If nothing is given, set it to VLC...
969 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
971 if( aTitle.isEmpty() )
973 setWindowTitle( qtr( "VLC media player" ) );
977 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
981 void MainInterface::showCryptedLabel( bool b_show )
983 if( cryptedLabel == NULL )
985 cryptedLabel = new QLabel;
986 // The lock icon is not the right one for DRM protection/scrambled.
987 //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
988 cryptedLabel->setText( "DRM" );
989 statusBar()->addWidget( cryptedLabel );
992 cryptedLabel->setVisible( b_show );
995 void MainInterface::showBuffering( float f_cache )
997 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
998 statusBar()->showMessage( amount, 1000 );
1001 /*****************************************************************************
1002 * Systray Icon and Systray Menu
1003 *****************************************************************************/
1005 * Create a SystemTray icon and a menu that would go with it.
1006 * Connects to a click handler on the icon.
1008 void MainInterface::createSystray()
1011 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
1012 iconVLC = QIcon( ":/logo/vlc128-xmas.png" );
1014 iconVLC = QIcon( ":/logo/vlc128.png" );
1015 sysTray = new QSystemTrayIcon( iconVLC, this );
1016 sysTray->setToolTip( qtr( "VLC media player" ));
1018 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
1019 systrayMenu->setIcon( iconVLC );
1021 VLCMenuBar::updateSystrayMenu( this, p_intf, true );
1024 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
1025 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
1027 /* Connects on nameChanged() */
1028 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
1029 this, updateSystrayTooltipName( const QString& ) );
1030 /* Connect PLAY_STATUS on the systray */
1031 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
1032 this, updateSystrayTooltipStatus( int ) );
1036 * Updates the Systray Icon's menu and toggle the main interface
1038 void MainInterface::toggleUpdateSystrayMenu()
1040 /* If hidden, show it */
1046 else if( isMinimized() )
1054 /* Visible (possibly under other windows) */
1056 /* check if any visible window is above vlc in the z-order,
1057 * but ignore the ones always on top
1058 * and the ones which can't be activated */
1061 wi.cbSize = sizeof( WINDOWINFO );
1062 for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1063 hwnd && ( !IsWindowVisible( hwnd ) ||
1064 ( GetWindowInfo( hwnd, &wi ) &&
1065 (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1066 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1067 if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1068 (wi.dwExStyle&WS_EX_TOPMOST) )
1081 VLCMenuBar::updateSystrayMenu( this, p_intf );
1084 /* First Item of the systray menu */
1085 void MainInterface::showUpdateSystrayMenu()
1093 VLCMenuBar::updateSystrayMenu( this, p_intf );
1096 /* First Item of the systray menu */
1097 void MainInterface::hideUpdateSystrayMenu()
1100 VLCMenuBar::updateSystrayMenu( this, p_intf );
1103 /* Click on systray Icon */
1104 void MainInterface::handleSystrayClick(
1105 QSystemTrayIcon::ActivationReason reason )
1109 case QSystemTrayIcon::Trigger:
1110 case QSystemTrayIcon::DoubleClick:
1112 VLCMenuBar::updateSystrayMenu( this, p_intf );
1114 toggleUpdateSystrayMenu();
1117 case QSystemTrayIcon::MiddleClick:
1118 sysTray->showMessage( qtr( "VLC media player" ),
1119 qtr( "Control menu for the player" ),
1120 QSystemTrayIcon::Information, 3000 );
1128 * Updates the name of the systray Icon tooltip.
1129 * Doesn't check if the systray exists, check before you call it.
1131 void MainInterface::updateSystrayTooltipName( const QString& name )
1133 if( name.isEmpty() )
1135 sysTray->setToolTip( qtr( "VLC media player" ) );
1139 sysTray->setToolTip( name );
1140 if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1142 sysTray->showMessage( qtr( "VLC media player" ), name,
1143 QSystemTrayIcon::NoIcon, 3000 );
1147 VLCMenuBar::updateSystrayMenu( this, p_intf );
1151 * Updates the status of the systray Icon tooltip.
1152 * Doesn't check if the systray exists, check before you call it.
1154 void MainInterface::updateSystrayTooltipStatus( int i_status )
1159 sysTray->setToolTip( input_name );
1162 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1165 sysTray->setToolTip( qtr( "VLC media player" ) );
1168 VLCMenuBar::updateSystrayMenu( this, p_intf );
1171 void MainInterface::changeEvent(QEvent *event)
1173 if( event->type() == QEvent::WindowStateChange )
1175 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1176 Qt::WindowStates newState = windowState();
1177 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1179 if( newState & Qt::WindowMinimized )
1181 b_hasPausedWhenMinimized = false;
1183 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1184 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1187 b_hasPausedWhenMinimized = true;
1191 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1193 if( b_hasPausedWhenMinimized )
1200 QWidget::changeEvent(event);
1203 /************************************************************************
1205 ************************************************************************/
1206 void MainInterface::dropEvent(QDropEvent *event)
1208 dropEventPlay( event, true );
1214 * Event called if something is dropped onto a VLC window
1215 * \param event the event in question
1216 * \param b_play whether to play the file immediately
1217 * \param b_playlist true to add to playlist, false to add to media library
1220 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play, bool b_playlist )
1222 if( event->possibleActions() & ( Qt::CopyAction | Qt::MoveAction ) )
1223 event->setDropAction( Qt::CopyAction );
1227 const QMimeData *mimeData = event->mimeData();
1229 /* D&D of a subtitles file, add it on the fly */
1230 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1232 if( !input_AddSubtitle( THEMIM->getInput(),
1233 qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1241 bool first = b_play;
1242 foreach( const QUrl &url, mimeData->urls() )
1246 QString mrl = toURI( url.toEncoded().constData() );
1247 playlist_Add( THEPL, qtu(mrl), NULL,
1248 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1249 PLAYLIST_END, b_playlist, pl_Unlocked );
1251 RecentsMRL::getInstance( p_intf )->addRecent( mrl );
1255 /* Browsers give content as text if you dnd the addressbar,
1256 so check if mimedata has valid url in text and use it
1257 if we didn't get any normal Urls()*/
1258 if( !mimeData->hasUrls() && mimeData->hasText() &&
1259 QUrl(mimeData->text()).isValid() )
1261 QString mrl = toURI( mimeData->text() );
1262 playlist_Add( THEPL, qtu(mrl), NULL,
1263 PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1264 PLAYLIST_END, b_playlist, pl_Unlocked );
1268 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1270 event->acceptProposedAction();
1272 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1274 event->acceptProposedAction();
1276 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1281 /************************************************************************
1283 ************************************************************************/
1284 void MainInterface::keyPressEvent( QKeyEvent *e )
1286 handleKeyPress( e );
1289 void MainInterface::handleKeyPress( QKeyEvent *e )
1291 if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1293 toggleMinimalView( !b_minimalView );
1297 int i_vlck = qtEventToVLCKey( e );
1300 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1307 void MainInterface::wheelEvent( QWheelEvent *e )
1309 int i_vlckey = qtWheelEventToVLCKey( e );
1310 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1314 void MainInterface::closeEvent( QCloseEvent *e )
1317 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1318 /* Accept session quit. Otherwise we break the desktop mamager. */
1322 void MainInterface::setInterfaceFullScreen( bool fs )
1325 setWindowState( windowState() | Qt::WindowFullScreen );
1327 setWindowState( windowState() & ~Qt::WindowFullScreen );
1329 void MainInterface::toggleInterfaceFullScreen()
1331 b_interfaceFullScreen = !b_interfaceFullScreen;
1332 if( !b_videoFullScreen )
1333 setInterfaceFullScreen( b_interfaceFullScreen );
1334 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1337 void MainInterface::emitBoss()
1341 void MainInterface::setBoss()
1354 void MainInterface::emitRaise()
1358 void MainInterface::setRaise()
1364 /*****************************************************************************
1365 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1366 * We don't show the menu directly here because we don't want the
1367 * caller to block for a too long time.
1368 *****************************************************************************/
1369 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1370 vlc_value_t old_val, vlc_value_t new_val, void *param )
1372 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1374 intf_thread_t *p_intf = (intf_thread_t *)param;
1376 if( p_intf->pf_show_dialog )
1378 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1379 new_val.b_bool, NULL );
1385 /*****************************************************************************
1386 * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1387 *****************************************************************************/
1388 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1389 vlc_value_t old_val, vlc_value_t new_val, void *param )
1391 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1392 VLC_UNUSED( new_val );
1394 intf_thread_t *p_intf = (intf_thread_t *)param;
1395 p_intf->p_sys->p_mi->toggleFSC();
1401 /*****************************************************************************
1402 * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1403 *****************************************************************************/
1404 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
1405 vlc_value_t old_val, vlc_value_t new_val, void *param )
1407 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1408 VLC_UNUSED( new_val );
1410 intf_thread_t *p_intf = (intf_thread_t *)param;
1411 p_intf->p_sys->p_mi->emitRaise();
1416 /*****************************************************************************
1417 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1418 *****************************************************************************/
1419 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1420 vlc_value_t old_val, vlc_value_t new_val, void *param )
1422 VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1423 VLC_UNUSED( new_val );
1425 intf_thread_t *p_intf = (intf_thread_t *)param;
1426 p_intf->p_sys->p_mi->emitBoss();