]> git.sesse.net Git - vlc/blob - modules/gui/qt4/main_interface.cpp
Qt: correctly delete callbacks
[vlc] / modules / gui / qt4 / main_interface.cpp
1 /*****************************************************************************
2  * main_interface.cpp : Main interface
3  ****************************************************************************
4  * Copyright (C) 2006-2011 VideoLAN and AUTHORS
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *          Jean-Baptiste Kempf <jb@videolan.org>
9  *          Ilkka Ollakka <ileoo@videolan.org>
10  *
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.
15  *
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.
20  *
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  *****************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include "qt4.hpp"
31
32 #include "main_interface.hpp"
33 #include "input_manager.hpp"                    // Creation
34 #include "actions_manager.hpp"                  // killInstance
35 #include "extensions_manager.hpp"               // killInstance
36
37 #include "util/customwidgets.hpp"               // qtEventToVLCKey, QVLCStackedWidget
38 #include "util/qt_dirs.hpp"                     // toNativeSeparators
39
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
44
45 #include "menus.hpp"                            // Menu creation
46 #include "recents.hpp"                          // RecentItems when DnD
47
48 #include <QCloseEvent>
49 #include <QKeyEvent>
50
51 #include <QUrl>
52 #include <QSize>
53 #include <QDate>
54
55 #include <QMenu>
56 #include <QMenuBar>
57 #include <QStatusBar>
58 #include <QLabel>
59 #include <QStackedWidget>
60
61 #include <vlc_keys.h>                       /* Wheel event */
62 #include <vlc_vout_display.h>               /* vout_thread_t and VOUT_ events */
63
64 // #define DEBUG_INTF
65
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,
75                            void *param );
76
77 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
78 {
79     /* Variables initialisation */
80     bgWidget             = NULL;
81     videoWidget          = NULL;
82     playlistWidget       = NULL;
83     stackCentralOldWidget= NULL;
84 #ifndef HAVE_MAEMO
85     sysTray              = NULL;
86 #endif
87     fullscreenControls   = NULL;
88     cryptedLabel         = NULL;
89     controls             = NULL;
90     inputC               = NULL;
91
92     b_hideAfterCreation  = false; // --qt-start-minimized
93     playlistVisible      = false;
94     input_name           = "";
95     b_interfaceFullScreen= false;
96
97
98     /* Ask for Privacy */
99     FirstRun::CheckAndRun( this, p_intf );
100
101     /**
102      *  Configuration and settings
103      *  Pre-building of interface
104      **/
105     /* Main settings */
106     setFocusPolicy( Qt::StrongFocus );
107     setAcceptDrops( true );
108     setWindowRole( "vlc-main" );
109     setWindowIcon( QApplication::windowIcon() );
110     setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
111 #ifdef Q_WS_MAC
112     setAttribute( Qt::WA_MacBrushedMetal );
113 #endif
114
115     /* Is video in embedded in the UI or not */
116     b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
117
118     /* Does the interface resize to video size or the opposite */
119     b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
120
121     /* Are we in the enhanced always-video mode or not ? */
122     b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
123
124     /* Do we want anoying popups or not */
125     b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
126
127     /* */
128     b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
129
130     /* Set the other interface settings */
131     settings = getSettings();
132     settings->beginGroup( "MainWindow" );
133
134 #ifdef WIN32
135     /* Volume keys */
136     p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
137 #endif
138
139     /* */
140     b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
141
142     settings->endGroup( );
143
144     /**************************
145      *  UI and Widgets design
146      **************************/
147     setVLCWindowsTitle();
148
149     /************
150      * Menu Bar *
151      ************/
152     QVLCMenu::createMenuBar( this, p_intf );
153     CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
154              this, destroyPopupMenu() );
155
156     createMainWidget( settings );
157
158     /**************
159      * Status Bar *
160      **************/
161     createStatusBar();
162     setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
163
164     /********************
165      * Input Manager    *
166      ********************/
167     MainInputManager::getInstance( p_intf );
168
169 #ifdef WIN32
170     himl = NULL;
171     p_taskbl = NULL;
172     taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
173 #endif
174
175     /*********************************
176      * Create the Systray Management *
177      *********************************/
178     initSystray();
179
180     /*************************************************************
181      * Connect the input manager to the GUI elements it manages  *
182      * Beware initSystray did some connects on input manager too *
183      *************************************************************/
184     /**
185      * Connects on nameChanged()
186      * Those connects are different because options can impeach them to trigger.
187      **/
188     /* Main Interface statusbar */
189     CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
190              this, setName( const QString& ) );
191     /* and title of the Main Interface*/
192     if( var_InheritBool( p_intf, "qt-name-in-title" ) )
193     {
194         CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
195                  this, setVLCWindowsTitle( const QString& ) );
196     }
197     /* END CONNECTS ON IM */
198
199     /* VideoWidget connects for asynchronous calls */
200     b_videoFullScreen = false;
201     connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
202              this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
203              Qt::BlockingQueuedConnection );
204     connect( this, SIGNAL(askReleaseVideo( void )),
205              this, SLOT(releaseVideoSlot( void )),
206              Qt::BlockingQueuedConnection );
207     CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
208
209     if( videoWidget )
210     {
211         if( b_autoresize )
212         {
213             CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
214                      this, setVideoSize( unsigned int, unsigned int ) );
215             CONNECT( videoWidget, sizeChanged( int, int ),
216                      this, resizeStack( int,  int ) );
217         }
218         CONNECT( this, askVideoSetFullScreen( bool ),
219                  this, setVideoFullScreen( bool ) );
220     }
221
222     CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
223
224     CONNECT( this, askToQuit(), THEDP, quit() );
225
226     CONNECT( this, askBoss(), this, setBoss() );
227     CONNECT( this, askRaise(), this, setRaise() );
228
229     /** END of CONNECTS**/
230
231
232     /************
233      * Callbacks
234      ************/
235     var_AddCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
236     var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
237     var_AddCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
238
239     /* Register callback for the intf-popupmenu variable */
240     var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
241
242     /* Playlist */
243     int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
244
245     if( i_plVis ) togglePlaylist();
246
247     /**** FINAL SIZING and placement of interface */
248     settings->beginGroup( "MainWindow" );
249     QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
250     settings->endGroup();
251
252     b_interfaceFullScreen = isFullScreen();
253
254     /* Final sizing and showing */
255     setVisible( !b_hideAfterCreation );
256
257     computeMinimumSize();
258
259     /* Switch to minimal view if needed, must be called after the show() */
260     if( b_minimalView )
261         toggleMinimalView( true );
262
263     b_hasPausedWhenMinimized = false;
264 }
265
266 MainInterface::~MainInterface()
267 {
268     /* Unsure we hide the videoWidget before destroying it */
269     if( stackCentralOldWidget == videoWidget )
270         showTab( bgWidget );
271
272     if( videoWidget )
273         releaseVideoSlot();
274
275 #ifdef WIN32
276     if( himl )
277         ImageList_Destroy( himl );
278     if(p_taskbl)
279         p_taskbl->vt->Release(p_taskbl);
280     CoUninitialize();
281 #endif
282
283     /* Be sure to kill the actionsManager... Only used in the MI and control */
284     ActionsManager::killInstance();
285
286     /* Idem */
287     ExtensionsManager::killInstance();
288
289     /* Delete the FSC controller */
290     delete fullscreenControls;
291
292     /* Save states */
293     settings->beginGroup( "MainWindow" );
294
295     settings->setValue( "pl-dock-status", b_plDocked );
296     /* Save playlist state */
297     if( playlistWidget )
298         settings->setValue( "playlist-visible", playlistVisible );
299
300     settings->setValue( "adv-controls",
301                         getControlsVisibilityStatus() & CONTROLS_ADVANCED );
302     settings->setValue( "status-bar-visible", b_statusbarVisible );
303
304     /* Save the stackCentralW sizes */
305     settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
306     settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
307
308     /* Save this size */
309     QVLCTools::saveWidgetPosition(settings, this);
310
311     settings->endGroup();
312
313     /* Save undocked playlist size */
314     if( playlistWidget && !isPlDocked() )
315         QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
316
317     delete playlistWidget;
318
319     delete statusBar();
320
321     /* Unregister callbacks */
322     var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
323     var_DelCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
324     var_DelCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
325     var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
326
327     p_intf->p_sys->p_mi = NULL;
328 }
329
330 void MainInterface::computeMinimumSize()
331 {
332     int minWidth = 30;
333     if( menuBar()->isVisible() )
334         minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
335
336     setMinimumWidth( minWidth );
337 }
338
339 /*****************************
340  *   Main UI handling        *
341  *****************************/
342 void MainInterface::recreateToolbars()
343 {
344     bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
345
346     settings->beginGroup( "MainWindow" );
347     delete controls;
348     delete inputC;
349
350     controls = new ControlsWidget( p_intf, b_adv, this );
351     inputC = new InputControlsWidget( p_intf, this );
352
353     if( fullscreenControls )
354     {
355         delete fullscreenControls;
356         fullscreenControls = new FullscreenControllerWidget( p_intf, this );
357         CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
358                  this, handleKeyPress( QKeyEvent * ) );
359     }
360     mainLayout->insertWidget( 2, inputC );
361     mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
362                               controls );
363     settings->endGroup();
364 }
365
366 void MainInterface::reloadPrefs()
367 {
368     b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
369     b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
370 #ifdef WIN32
371     p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
372 #endif
373     if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
374     {
375         delete fullscreenControls;
376         fullscreenControls = NULL;
377     }
378 }
379
380 void MainInterface::createMainWidget( QSettings *settings )
381 {
382     /* Create the main Widget and the mainLayout */
383     QWidget *main = new QWidget;
384     setCentralWidget( main );
385     mainLayout = new QVBoxLayout( main );
386     main->setContentsMargins( 0, 0, 0, 0 );
387     mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
388
389     /* */
390     stackCentralW = new QVLCStackedWidget( main );
391
392     /* Bg Cone */
393     bgWidget = new BackgroundWidget( p_intf );
394     stackCentralW->addWidget( bgWidget );
395     if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
396         bgWidget->setWithArt( false );
397     else
398         if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
399             bgWidget->setExpandstoHeight( true );
400
401     /* And video Outputs */
402     if( b_videoEmbedded )
403     {
404         videoWidget = new VideoWidget( p_intf );
405         stackCentralW->addWidget( videoWidget );
406     }
407     mainLayout->insertWidget( 1, stackCentralW );
408
409     settings->beginGroup( "MainWindow" );
410     stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 600, 0 ) ).toSize();
411     /* Resize even if no-auto-resize, because we are at creation */
412     resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
413
414     /* Create the CONTROLS Widget */
415     controls = new ControlsWidget( p_intf,
416                    settings->value( "adv-controls", false ).toBool(), this );
417     inputC = new InputControlsWidget( p_intf, this );
418
419     mainLayout->insertWidget( 2, inputC );
420     mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
421                               controls );
422
423     /* Visualisation, disabled for now, they SUCK */
424     #if 0
425     visualSelector = new VisualSelector( p_intf );
426     mainLayout->insertWidget( 0, visualSelector );
427     visualSelector->hide();
428     #endif
429
430     settings->endGroup();
431
432     /* Enable the popup menu in the MI */
433     main->setContextMenuPolicy( Qt::CustomContextMenu );
434     CONNECT( main, customContextMenuRequested( const QPoint& ),
435              this, popupMenu( const QPoint& ) );
436
437     if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
438         /* Create the FULLSCREEN CONTROLS Widget */
439         if( var_InheritBool( p_intf, "qt-fs-controller" ) )
440         {
441             fullscreenControls = new FullscreenControllerWidget( p_intf, this );
442             CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
443                      this, handleKeyPress( QKeyEvent * ) );
444         }
445 }
446
447 inline void MainInterface::initSystray()
448 {
449 #ifndef HAVE_MAEMO
450     bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
451     bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
452
453     if( var_InheritBool( p_intf, "qt-start-minimized") )
454     {
455         if( b_systrayAvailable )
456         {
457             b_systrayWanted = true;
458             b_hideAfterCreation = true;
459         }
460         else
461             msg_Err( p_intf, "cannot start minimized without system tray bar" );
462     }
463
464     if( b_systrayAvailable && b_systrayWanted )
465         createSystray();
466 #endif
467 }
468
469 inline void MainInterface::createStatusBar()
470 {
471     /****************
472      *  Status Bar  *
473      ****************/
474     /* Widgets Creation*/
475     QStatusBar *statusBarr = statusBar();
476
477     TimeLabel *timeLabel = new TimeLabel( p_intf );
478     nameLabel = new QLabel( this );
479     nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
480                                       | Qt::TextSelectableByKeyboard );
481     SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
482
483     /* Styling those labels */
484     timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
485     speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
486     nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
487     timeLabel->setStyleSheet(
488             "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
489     speedLabel->setStyleSheet(
490             "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
491     /* pad both label and its tooltip */
492     nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
493
494     /* and adding those */
495     statusBarr->addWidget( nameLabel, 8 );
496     statusBarr->addPermanentWidget( speedLabel, 0 );
497     statusBarr->addPermanentWidget( timeLabel, 0 );
498
499     /* timeLabel behaviour:
500        - double clicking opens the goto time dialog
501        - right-clicking and clicking just toggle between remaining and
502          elapsed time.*/
503     CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
504
505     CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
506              this, showCryptedLabel( bool ) );
507
508     CONNECT( THEMIM->getIM(), seekRequested( float ),
509              timeLabel, setDisplayPosition( float ) );
510
511     /* This shouldn't be necessary, but for somehow reason, the statusBarr
512        starts at height of 20px and when a text is shown it needs more space.
513        But, as the QMainWindow policy doesn't allow statusBar to change QMW's
514        geometry, we need to force a height. If you have a better idea, please
515        tell me -- jb
516      */
517     statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
518 }
519
520 /**********************************************************************
521  * Handling of sizing of the components
522  **********************************************************************/
523
524 void MainInterface::debug()
525 {
526 #ifdef DEBUG_INTF
527     msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
528     msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
529     msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
530
531     msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
532     msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
533     msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
534 #endif
535 }
536
537 inline void MainInterface::showVideo() { showTab( videoWidget ); }
538 inline void MainInterface::restoreStackOldWidget()
539             { showTab( stackCentralOldWidget ); }
540
541 inline void MainInterface::showTab( QWidget *widget )
542 {
543 #ifdef DEBUG_INTF
544     msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
545 #endif
546
547     stackCentralOldWidget = stackCentralW->currentWidget();
548     stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
549
550     stackCentralW->setCurrentWidget( widget );
551     if( b_autoresize )
552         resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
553
554 #ifdef DEBUG_INTF
555     msg_Warn( p_intf, "State change %i",  stackCentralW->currentIndex() );
556     msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
557 #endif
558 }
559
560 void MainInterface::destroyPopupMenu()
561 {
562     QVLCMenu::PopupMenu( p_intf, false );
563 }
564
565 void MainInterface::popupMenu( const QPoint & )
566 {
567     QVLCMenu::PopupMenu( p_intf, true );
568 }
569
570 void MainInterface::toggleFSC()
571 {
572    if( !fullscreenControls ) return;
573
574    IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type );
575    QApplication::postEvent( fullscreenControls, eShow );
576 }
577
578 /****************************************************************************
579  * Video Handling
580  ****************************************************************************/
581
582 /**
583  * NOTE:
584  * You must not change the state of this object or other Qt4 UI objects,
585  * from the video output thread - only from the Qt4 UI main loop thread.
586  * All window provider queries must be handled through signals or events.
587  * That's why we have all those emit statements...
588  */
589 WId MainInterface::getVideo( int *pi_x, int *pi_y,
590                              unsigned int *pi_width, unsigned int *pi_height )
591 {
592     if( !videoWidget )
593         return 0;
594
595     /* This is a blocking call signal. Results are returned through pointers.
596      * Beware of deadlocks! */
597     WId id;
598     emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
599     return id;
600 }
601
602 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
603                                   unsigned *pi_width, unsigned *pi_height )
604 {
605     /* Hidden or minimized, activate */
606     if( isHidden() || isMinimized() )
607         toggleUpdateSystrayMenu();
608
609     /* Request the videoWidget */
610     WId ret = videoWidget->request( pi_x, pi_y,
611                                     pi_width, pi_height, !b_autoresize );
612     *p_id = ret;
613     if( ret ) /* The videoWidget is available */
614     {
615         /* Consider the video active now */
616         showVideo();
617
618         /* Ask videoWidget to resize correctly, if we are in normal mode */
619         if( !isFullScreen() && !isMaximized() && b_autoresize )
620             videoWidget->SetSizing( *pi_width, *pi_height );
621     }
622 }
623
624 /* Asynchronous call from the WindowClose function */
625 void MainInterface::releaseVideo( void )
626 {
627     emit askReleaseVideo();
628 }
629
630 /* Function that is CONNECTED to the previous emit */
631 void MainInterface::releaseVideoSlot( void )
632 {
633     /* This function is called when the embedded video window is destroyed,
634      * or in the rare case that the embedded window is still here but the
635      * Qt4 interface exits. */
636     assert( videoWidget );
637     videoWidget->release();
638     setVideoOnTop( false );
639     setVideoFullScreen( false );
640
641     if( stackCentralW->currentWidget() == videoWidget )
642         restoreStackOldWidget();
643
644     /* We don't want to have a blank video to popup */
645     stackCentralOldWidget = bgWidget;
646 }
647
648 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
649 {
650     if( !isFullScreen() && !isMaximized() )
651         videoWidget->SetSizing( w, h );
652 }
653
654 void MainInterface::setVideoFullScreen( bool fs )
655 {
656     b_videoFullScreen = fs;
657     if( fs )
658     {
659         int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
660         /* if user hasn't defined screennumber, or screennumber that is bigger
661          * than current number of screens, take screennumber where current interface
662          * is
663          */
664         if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
665             numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
666
667         QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
668
669         /* To be sure window is on proper-screen in xinerama */
670         if( !screenres.contains( pos() ) )
671         {
672             msg_Dbg( p_intf, "Moving video to correct screen");
673             move( QPoint( screenres.x(), screenres.y() ) );
674         }
675         setMinimalView( true );
676         setInterfaceFullScreen( true );
677     }
678     else
679     {
680         /* TODO do we want to restore screen and position ? (when
681          * qt-fullscreen-screennumber is forced) */
682         setMinimalView( b_minimalView );
683         setInterfaceFullScreen( b_interfaceFullScreen );
684     }
685     videoWidget->sync();
686 }
687
688 /* Slot to change the video always-on-top flag.
689  * Emit askVideoOnTop() to invoke this from other thread. */
690 void MainInterface::setVideoOnTop( bool on_top )
691 {
692     Qt::WindowFlags oldflags = windowFlags(), newflags;
693
694     if( on_top )
695         newflags = oldflags | Qt::WindowStaysOnTopHint;
696     else
697         newflags = oldflags & ~Qt::WindowStaysOnTopHint;
698     if( newflags != oldflags && !b_videoFullScreen )
699
700     {
701         setWindowFlags( newflags );
702         show(); /* necessary to apply window flags */
703     }
704 }
705
706 /* Asynchronous call from WindowControl function */
707 int MainInterface::controlVideo( int i_query, va_list args )
708 {
709     switch( i_query )
710     {
711     case VOUT_WINDOW_SET_SIZE:
712     {
713         unsigned int i_width  = va_arg( args, unsigned int );
714         unsigned int i_height = va_arg( args, unsigned int );
715
716         emit askVideoToResize( i_width, i_height );
717         return VLC_SUCCESS;
718     }
719     case VOUT_WINDOW_SET_STATE:
720     {
721         unsigned i_arg = va_arg( args, unsigned );
722         unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
723
724         emit askVideoOnTop( on_top != 0 );
725         return VLC_SUCCESS;
726     }
727     case VOUT_WINDOW_SET_FULLSCREEN:
728     {
729         bool b_fs = va_arg( args, int );
730
731         emit askVideoSetFullScreen( b_fs );
732         return VLC_SUCCESS;
733     }
734     default:
735         msg_Warn( p_intf, "unsupported control query" );
736         return VLC_EGENERIC;
737     }
738 }
739
740 /*****************************************************************************
741  * Playlist, Visualisation and Menus handling
742  *****************************************************************************/
743 /**
744  * Toggle the playlist widget or dialog
745  **/
746 void MainInterface::createPlaylist()
747 {
748     playlistWidget = new PlaylistWidget( p_intf, this );
749
750     if( b_plDocked )
751     {
752         stackCentralW->addWidget( playlistWidget );
753         stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
754     }
755     else
756     {
757 #ifdef WIN32
758         playlistWidget->setParent( NULL );
759 #endif
760         playlistWidget->setWindowFlags( Qt::Window );
761
762         /* This will restore the geometry but will not work for position,
763            because of parenting */
764         QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
765                 playlistWidget, QSize( 600, 300 ) );
766     }
767 }
768
769 void MainInterface::togglePlaylist()
770 {
771     if( !playlistWidget )
772     {
773         createPlaylist();
774     }
775
776     if( b_plDocked )
777     {
778         /* Playlist is not visible, show it */
779         if( stackCentralW->currentWidget() != playlistWidget )
780         {
781             showTab( playlistWidget );
782         }
783         else /* Hide it! */
784         {
785             restoreStackOldWidget();
786         }
787         playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
788     }
789     else
790     {
791 #ifdef WIN32
792         playlistWidget->setParent( NULL );
793 #endif
794         playlistWidget->setWindowFlags( Qt::Window );
795         playlistVisible = !playlistVisible;
796         playlistWidget->setVisible( playlistVisible );
797     }
798     debug();
799 }
800
801 void MainInterface::dockPlaylist( bool p_docked )
802 {
803     if( b_plDocked == p_docked ) return;
804     b_plDocked = p_docked;
805
806     if( !playlistWidget ) return; /* Playlist wasn't created yet */
807     if( !p_docked )
808     {
809         stackCentralW->removeWidget( playlistWidget );
810 #ifdef WIN32
811         playlistWidget->setParent( NULL );
812 #endif
813         playlistWidget->setWindowFlags( Qt::Window );
814         QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
815                 playlistWidget, QSize( 600, 300 ) );
816         playlistWidget->show();
817         restoreStackOldWidget();
818     }
819     else
820     {
821         QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
822         playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
823         // It would be logical that QStackWidget::addWidget reset the flags...
824         stackCentralW->addWidget( playlistWidget );
825         showTab( playlistWidget );
826     }
827     playlistVisible = true;
828 }
829
830 /*
831  * setMinimalView is the private function used by
832  * the SLOT toggleMinimalView and setVideoFullScreen
833  */
834 void MainInterface::setMinimalView( bool b_minimal )
835 {
836     menuBar()->setVisible( !b_minimal );
837     controls->setVisible( !b_minimal );
838     statusBar()->setVisible( !b_minimal && b_statusbarVisible );
839     inputC->setVisible( !b_minimal );
840 }
841
842 /*
843  * This public SLOT is used for moving to minimal View Mode
844  *
845  * If b_minimal is false, then we are normalView
846  */
847 void MainInterface::toggleMinimalView( bool b_minimal )
848 {
849     if( !b_minimalView && b_autoresize ) /* Normal mode */
850     {
851         if( stackCentralW->currentWidget() == bgWidget )
852         {
853             if( stackCentralW->height() < 16 )
854             {
855                 resizeStack( stackCentralW->width(), 100 );
856             }
857         }
858     }
859     b_minimalView = b_minimal;
860     if( !b_videoFullScreen )
861     {
862         setMinimalView( b_minimalView );
863         computeMinimumSize();
864     }
865
866     emit minimalViewToggled( b_minimalView );
867 }
868
869 /* toggling advanced controls buttons */
870 void MainInterface::toggleAdvancedButtons()
871 {
872     controls->toggleAdvanced();
873 //    if( fullscreenControls ) fullscreenControls->toggleAdvanced();
874 }
875
876 /* Get the visibility status of the controls (hidden or not, advanced or not) */
877 int MainInterface::getControlsVisibilityStatus()
878 {
879     if( !controls ) return 0;
880     return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
881                 + CONTROLS_ADVANCED * controls->b_advancedVisible );
882 }
883
884 void MainInterface::setStatusBarVisibility( bool b_visible )
885 {
886     statusBar()->setVisible( b_visible );
887     b_statusbarVisible = b_visible;
888     if( controls ) controls->setGripVisible( !b_statusbarVisible );
889 }
890
891 #if 0
892 void MainInterface::visual()
893 {
894     if( !VISIBLE( visualSelector) )
895     {
896         visualSelector->show();
897         if( !THEMIM->getIM()->hasVideo() )
898         {
899             /* Show the background widget */
900         }
901         visualSelectorEnabled = true;
902     }
903     else
904     {
905         /* Stop any currently running visualization */
906         visualSelector->hide();
907         visualSelectorEnabled = false;
908     }
909 }
910 #endif
911
912 /************************************************************************
913  * Other stuff
914  ************************************************************************/
915 void MainInterface::setName( const QString& name )
916 {
917     input_name = name; /* store it for the QSystray use */
918     /* Display it in the status bar, but also as a Tooltip in case it doesn't
919        fit in the label */
920     nameLabel->setText( name );
921     nameLabel->setToolTip( name );
922 }
923
924 /**
925  * Give the decorations of the Main Window a correct Name.
926  * If nothing is given, set it to VLC...
927  **/
928 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
929 {
930     if( aTitle.isEmpty() )
931     {
932         setWindowTitle( qtr( "VLC media player" ) );
933     }
934     else
935     {
936         setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
937     }
938 }
939
940 void MainInterface::showCryptedLabel( bool b_show )
941 {
942     if( cryptedLabel == NULL )
943     {
944         cryptedLabel = new QLabel;
945         // The lock icon is not the right one for DRM protection/scrambled.
946         //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
947         cryptedLabel->setText( "DRM" );
948         statusBar()->addWidget( cryptedLabel );
949     }
950
951     cryptedLabel->setVisible( b_show );
952 }
953
954 void MainInterface::showBuffering( float f_cache )
955 {
956     QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
957     statusBar()->showMessage( amount, 1000 );
958 }
959
960 /*****************************************************************************
961  * Systray Icon and Systray Menu
962  *****************************************************************************/
963 #ifndef HAVE_MAEMO
964 /**
965  * Create a SystemTray icon and a menu that would go with it.
966  * Connects to a click handler on the icon.
967  **/
968 void MainInterface::createSystray()
969 {
970     QIcon iconVLC;
971     if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
972         iconVLC =  QIcon( ":/logo/vlc128-xmas.png" );
973     else
974         iconVLC =  QIcon( ":/logo/vlc128.png" );
975     sysTray = new QSystemTrayIcon( iconVLC, this );
976     sysTray->setToolTip( qtr( "VLC media player" ));
977
978     systrayMenu = new QMenu( qtr( "VLC media player" ), this );
979     systrayMenu->setIcon( iconVLC );
980
981     QVLCMenu::updateSystrayMenu( this, p_intf, true );
982     sysTray->show();
983
984     CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
985              this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
986
987     /* Connects on nameChanged() */
988     CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
989              this, updateSystrayTooltipName( const QString& ) );
990     /* Connect PLAY_STATUS on the systray */
991     CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
992              this, updateSystrayTooltipStatus( int ) );
993 }
994
995 /**
996  * Updates the Systray Icon's menu and toggle the main interface
997  */
998 void MainInterface::toggleUpdateSystrayMenu()
999 {
1000     /* If hidden, show it */
1001     if( isHidden() )
1002     {
1003         show();
1004         activateWindow();
1005     }
1006     else if( isMinimized() )
1007     {
1008         /* Minimized */
1009         showNormal();
1010         activateWindow();
1011     }
1012     else
1013     {
1014         /* Visible (possibly under other windows) */
1015 #ifdef WIN32
1016         /* check if any visible window is above vlc in the z-order,
1017          * but ignore the ones always on top
1018          * and the ones which can't be activated */
1019         WINDOWINFO wi;
1020         HWND hwnd;
1021         wi.cbSize = sizeof( WINDOWINFO );
1022         for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1023                 hwnd && ( !IsWindowVisible( hwnd ) ||
1024                     ( GetWindowInfo( hwnd, &wi ) &&
1025                       (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1026                 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1027             if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1028                 (wi.dwExStyle&WS_EX_TOPMOST) )
1029             {
1030                 hide();
1031             }
1032             else
1033             {
1034                 activateWindow();
1035             }
1036 #else
1037         hide();
1038 #endif
1039     }
1040     if( sysTray )
1041         QVLCMenu::updateSystrayMenu( this, p_intf );
1042 }
1043
1044 /* First Item of the systray menu */
1045 void MainInterface::showUpdateSystrayMenu()
1046 {
1047     if( isHidden() )
1048         show();
1049     if( isMinimized() )
1050         showNormal();
1051     activateWindow();
1052
1053     QVLCMenu::updateSystrayMenu( this, p_intf );
1054 }
1055
1056 /* First Item of the systray menu */
1057 void MainInterface::hideUpdateSystrayMenu()
1058 {
1059     hide();
1060     QVLCMenu::updateSystrayMenu( this, p_intf );
1061 }
1062
1063 /* Click on systray Icon */
1064 void MainInterface::handleSystrayClick(
1065                                     QSystemTrayIcon::ActivationReason reason )
1066 {
1067     switch( reason )
1068     {
1069         case QSystemTrayIcon::Trigger:
1070         case QSystemTrayIcon::DoubleClick:
1071 #ifdef Q_WS_MAC
1072             QVLCMenu::updateSystrayMenu( this, p_intf );
1073 #else
1074             toggleUpdateSystrayMenu();
1075 #endif
1076             break;
1077         case QSystemTrayIcon::MiddleClick:
1078             sysTray->showMessage( qtr( "VLC media player" ),
1079                     qtr( "Control menu for the player" ),
1080                     QSystemTrayIcon::Information, 3000 );
1081             break;
1082         default:
1083             break;
1084     }
1085 }
1086
1087 /**
1088  * Updates the name of the systray Icon tooltip.
1089  * Doesn't check if the systray exists, check before you call it.
1090  **/
1091 void MainInterface::updateSystrayTooltipName( const QString& name )
1092 {
1093     if( name.isEmpty() )
1094     {
1095         sysTray->setToolTip( qtr( "VLC media player" ) );
1096     }
1097     else
1098     {
1099         sysTray->setToolTip( name );
1100         if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1101         {
1102             sysTray->showMessage( qtr( "VLC media player" ), name,
1103                     QSystemTrayIcon::NoIcon, 3000 );
1104         }
1105     }
1106
1107     QVLCMenu::updateSystrayMenu( this, p_intf );
1108 }
1109
1110 /**
1111  * Updates the status of the systray Icon tooltip.
1112  * Doesn't check if the systray exists, check before you call it.
1113  **/
1114 void MainInterface::updateSystrayTooltipStatus( int i_status )
1115 {
1116     switch( i_status )
1117     {
1118     case PLAYING_S:
1119         sysTray->setToolTip( input_name );
1120         break;
1121     case PAUSE_S:
1122         sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1123         break;
1124     default:
1125         sysTray->setToolTip( qtr( "VLC media player" ) );
1126         break;
1127     }
1128     QVLCMenu::updateSystrayMenu( this, p_intf );
1129 }
1130 #endif
1131
1132 void MainInterface::changeEvent(QEvent *event)
1133 {
1134     if( event->type() == QEvent::WindowStateChange )
1135     {
1136         QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1137         Qt::WindowStates newState = windowState();
1138         Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1139
1140         if( newState & Qt::WindowMinimized )
1141         {
1142             b_hasPausedWhenMinimized = false;
1143
1144             if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1145                 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1146                 b_pauseOnMinimize )
1147             {
1148                 b_hasPausedWhenMinimized = true;
1149                 THEMIM->pause();
1150             }
1151         }
1152         else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1153         {
1154             if( b_hasPausedWhenMinimized )
1155             {
1156                 THEMIM->play();
1157             }
1158         }
1159     }
1160
1161     QWidget::changeEvent(event);
1162 }
1163
1164 /************************************************************************
1165  * D&D Events
1166  ************************************************************************/
1167 void MainInterface::dropEvent(QDropEvent *event)
1168 {
1169     dropEventPlay( event, true );
1170 }
1171
1172 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1173 {
1174     if( event->possibleActions() & Qt::CopyAction )
1175        event->setDropAction( Qt::CopyAction );
1176     else
1177         return;
1178
1179     const QMimeData *mimeData = event->mimeData();
1180
1181     /* D&D of a subtitles file, add it on the fly */
1182     if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1183     {
1184         if( !input_AddSubtitle( THEMIM->getInput(),
1185                  qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1186                  true ) )
1187         {
1188             event->accept();
1189             return;
1190         }
1191     }
1192
1193     bool first = b_play;
1194     foreach( const QUrl &url, mimeData->urls() )
1195     {
1196         if( url.isValid() )
1197         {
1198             QString mrl = toURI( url.toEncoded().constData() );
1199             playlist_Add( THEPL, qtu(mrl), NULL,
1200                           PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1201                           PLAYLIST_END, true, pl_Unlocked );
1202             first = false;
1203             RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1204         }
1205     }
1206
1207     /* Browsers give content as text if you dnd the addressbar,
1208        so check if mimedata has valid url in text and use it
1209        if we didn't get any normal Urls()*/
1210     if( !mimeData->hasUrls() && mimeData->hasText() &&
1211         QUrl(mimeData->text()).isValid() )
1212     {
1213         QString mrl = toURI( mimeData->text() );
1214         playlist_Add( THEPL, qtu(mrl), NULL,
1215                       PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1216                       PLAYLIST_END, true, pl_Unlocked );
1217     }
1218     event->accept();
1219 }
1220 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1221 {
1222      event->acceptProposedAction();
1223 }
1224 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1225 {
1226      event->acceptProposedAction();
1227 }
1228 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1229 {
1230      event->accept();
1231 }
1232
1233 /************************************************************************
1234  * Events stuff
1235  ************************************************************************/
1236 void MainInterface::keyPressEvent( QKeyEvent *e )
1237 {
1238     handleKeyPress( e );
1239 }
1240
1241 void MainInterface::handleKeyPress( QKeyEvent *e )
1242 {
1243     if( ( e->modifiers() &  Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1244     {
1245         toggleMinimalView( !b_minimalView );
1246         e->accept();
1247     }
1248
1249     int i_vlck = qtEventToVLCKey( e );
1250     if( i_vlck > 0 )
1251     {
1252         var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1253         e->accept();
1254     }
1255     else
1256         e->ignore();
1257 }
1258
1259 void MainInterface::wheelEvent( QWheelEvent *e )
1260 {
1261     int i_vlckey = qtWheelEventToVLCKey( e );
1262     var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1263     e->accept();
1264 }
1265
1266 void MainInterface::closeEvent( QCloseEvent *e )
1267 {
1268 //  hide();
1269     emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1270     /* Accept session quit. Otherwise we break the desktop mamager. */
1271     e->accept();
1272 }
1273
1274 void MainInterface::setInterfaceFullScreen( bool fs )
1275 {
1276     if( fs )
1277         setWindowState( windowState() | Qt::WindowFullScreen );
1278     else
1279         setWindowState( windowState() & ~Qt::WindowFullScreen );
1280 }
1281 void MainInterface::toggleInterfaceFullScreen()
1282 {
1283     b_interfaceFullScreen = !b_interfaceFullScreen;
1284     if( !b_videoFullScreen )
1285         setInterfaceFullScreen( b_interfaceFullScreen );
1286     emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1287 }
1288
1289 void MainInterface::emitBoss()
1290 {
1291     emit askBoss();
1292 }
1293 void MainInterface::setBoss()
1294 {
1295     THEMIM->pause();
1296 #ifndef HAVE_MAEMO
1297     if( sysTray )
1298     {
1299         hide();
1300     }
1301     else
1302 #endif
1303     {
1304         showMinimized();
1305     }
1306 }
1307
1308 void MainInterface::emitRaise()
1309 {
1310     emit askRaise();
1311 }
1312 void MainInterface::setRaise()
1313 {
1314     activateWindow();
1315     raise();
1316 }
1317
1318 /*****************************************************************************
1319  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1320  *  We don't show the menu directly here because we don't want the
1321  *  caller to block for a too long time.
1322  *****************************************************************************/
1323 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1324                         vlc_value_t old_val, vlc_value_t new_val, void *param )
1325 {
1326     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1327
1328     intf_thread_t *p_intf = (intf_thread_t *)param;
1329
1330     if( p_intf->pf_show_dialog )
1331     {
1332         p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1333                                 new_val.b_bool, NULL );
1334     }
1335
1336     return VLC_SUCCESS;
1337 }
1338
1339 /*****************************************************************************
1340  * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1341  *****************************************************************************/
1342 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1343                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1344 {
1345     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1346     VLC_UNUSED( new_val );
1347
1348     intf_thread_t *p_intf = (intf_thread_t *)param;
1349     p_intf->p_sys->p_mi->toggleFSC();
1350
1351     /* Show event */
1352      return VLC_SUCCESS;
1353 }
1354
1355 /*****************************************************************************
1356  * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1357  *****************************************************************************/
1358 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
1359                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1360 {
1361     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1362     VLC_UNUSED( new_val );
1363
1364     intf_thread_t *p_intf = (intf_thread_t *)param;
1365     p_intf->p_sys->p_mi->emitRaise();
1366
1367     return VLC_SUCCESS;
1368 }
1369
1370 /*****************************************************************************
1371  * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1372  *****************************************************************************/
1373 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1374                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1375 {
1376     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1377     VLC_UNUSED( new_val );
1378
1379     intf_thread_t *p_intf = (intf_thread_t *)param;
1380     p_intf->p_sys->p_mi->emitBoss();
1381
1382     return VLC_SUCCESS;
1383 }