Shows qt4 notification only if the player isn't visible
[vlc.git] / modules / gui / qt4 / main_interface.cpp
1 /*****************************************************************************
2  * main_interface.cpp : Main interface
3  ****************************************************************************
4  * Copyright (C) 2006-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *          Jean-Baptiste Kempf <jb@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include "qt4.hpp"
26 #include "main_interface.hpp"
27 #include "input_manager.hpp"
28 #include "util/qvlcframe.hpp"
29 #include "util/customwidgets.hpp"
30 #include "dialogs_provider.hpp"
31 #include "components/interface_widgets.hpp"
32 #include "dialogs/playlist.hpp"
33 #include "menus.hpp"
34
35 #include <QMenuBar>
36 #include <QCloseEvent>
37 #include <QPushButton>
38 #include <QStatusBar>
39 #include <QKeyEvent>
40 #include <QUrl>
41 #include <QSystemTrayIcon>
42 #include <QSize>
43 #include <QMenu>
44 #include <QLabel>
45
46 #include <assert.h>
47 #include <vlc_keys.h>
48 #include <vlc_vout.h>
49
50 #ifdef WIN32
51     #define PREF_W 410
52     #define PREF_H 121
53 #else
54     #define PREF_W 450
55     #define PREF_H 160
56 #endif
57
58 #define SET_WIDTH(i,j) i->widgetSize.setWidth(j)
59 #define SET_HEIGHT(i,j) i->widgetSize.setHeight(j)
60 #define SET_WH( i,j,k) i->widgetSize.setWidth(j); i->widgetSize.setHeight(k);
61
62 #define DS(i) i.width(),i.height()
63
64 /* Callback prototypes */
65 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
66                         vlc_value_t old_val, vlc_value_t new_val, void *param );
67 static int IntfShowCB( 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 InteractCallback( vlc_object_t *, const char *, vlc_value_t,
70                              vlc_value_t, void *);
71 /* Video handling */
72 static void *DoRequest( intf_thread_t *p_intf, vout_thread_t *p_vout,
73                         int *pi1, int *pi2, unsigned int*pi3,unsigned int*pi4)
74 {
75     return p_intf->p_sys->p_mi->requestVideo( p_vout, pi1, pi2, pi3, pi4 );
76 }
77 static void DoRelease( intf_thread_t *p_intf, void *p_win )
78 {
79     return p_intf->p_sys->p_mi->releaseVideo( p_win );
80 }
81 static int DoControl( intf_thread_t *p_intf, void *p_win, int i_q, va_list a )
82 {
83     return p_intf->p_sys->p_mi->controlVideo( p_win, i_q, a );
84 }
85
86 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
87 {
88     /* Variables initialisation */
89     need_components_update = false;
90     bgWidget = NULL; videoWidget = NULL; playlistWidget = NULL;
91     embeddedPlaylistWasActive = videoIsActive = false;
92     input_name = "";
93
94     /**
95      *  Configuration and settings
96      **/
97     settings = new QSettings( "VideoLAN", "VLC" );
98     settings->beginGroup( "MainWindow" );
99
100     /* Main settings */
101     setFocusPolicy( Qt::StrongFocus );
102     setAcceptDrops(true);
103     setWindowIcon( QApplication::windowIcon() );
104     setWindowOpacity( config_GetFloat( p_intf, "qt-opacity" ) );
105
106     /* Set The Video In emebedded Mode or not */
107     videoEmbeddedFlag = false;
108     if( config_GetInt( p_intf, "embedded-video" ) )
109         videoEmbeddedFlag = true;
110
111     alwaysVideoFlag = false;
112     if( videoEmbeddedFlag && config_GetInt( p_intf, "qt-always-video" ) )
113         alwaysVideoFlag = true;
114
115     /* Set the other interface settings */
116     playlistEmbeddedFlag = settings->value( "playlist-embedded", true).toBool();
117     visualSelectorEnabled = settings->value( "visual-selector", false ).toBool();
118     notificationEnabled = config_GetInt( p_intf, "qt-notification" )
119                           ? true : false;
120     /**************************
121      *  UI and Widgets design
122      **************************/
123     setVLCWindowsTitle();
124     handleMainUi( settings );
125
126     /* Menu Bar */
127     QVLCMenu::createMenuBar( this, p_intf, playlistEmbeddedFlag,
128                              isAdvancedVisible(), visualSelectorEnabled );
129
130     /* Status Bar */
131     /**
132      * TODO: clicking on the elapsed time should switch to the remaining time
133      **/
134     /**
135      * TODO: do we add a label for the current Volume ?
136      **/
137     timeLabel = new QLabel;
138     nameLabel = new QLabel;
139     speedLabel = new QLabel( "1.0x" );
140     timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
141     speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
142     statusBar()->addWidget( nameLabel, 8 );
143     statusBar()->addPermanentWidget( speedLabel, 0 );
144     statusBar()->addPermanentWidget( timeLabel, 2 );
145     speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
146     timeLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
147     CONNECT( speedLabel, customContextMenuRequested( QPoint ),
148              this, showSpeedMenu( QPoint ) );
149     CONNECT( timeLabel, customContextMenuRequested( QPoint ),
150              this, showTimeMenu( QPoint ) );
151
152     /**********************
153      * Systray Management *
154      **********************/
155     sysTray = NULL;
156     bool b_createSystray = false;
157     bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
158     if( config_GetInt( p_intf, "qt-start-minimized") )
159     {
160         if( b_systrayAvailable ){
161             b_createSystray = true;
162             hide(); //FIXME
163         }
164         else msg_Warn( p_intf, "You can't minize if you haven't a system "
165                 "tray bar" );
166     }
167     if( config_GetInt( p_intf, "qt-system-tray") )
168         b_createSystray = true;
169
170     if( b_systrayAvailable && b_createSystray )
171             createSystray();
172
173     /* Init input manager */
174     MainInputManager::getInstance( p_intf );
175     ON_TIMEOUT( updateOnTimer() );
176
177     /**
178      * Various CONNECTs
179      **/
180
181     /* Connect the input manager to the GUI elements it manages */
182     /* It is also connected to the control->slider, see the ControlsWidget */
183     CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
184              this, setDisplay( float, int, int ) );
185
186     /** Connects on nameChanged() */
187     /* Naming in the controller statusbar */
188     CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
189              setName( QString ) );
190     /* and in the systray */
191     if( sysTray )
192     {
193         CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
194                  updateSystrayTooltipName( QString ) );
195     }
196     /* and in the title of the controller */
197     if( config_GetInt( p_intf, "qt-name-in-title" ) )
198     {
199         CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
200              setVLCWindowsTitle( QString ) );
201     }
202
203     /** CONNECTS on PLAY_STATUS **/
204     /* Status on the main controller */
205     CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
206     /* and in the systray */
207     if( sysTray )
208     {
209         CONNECT( THEMIM->getIM(), statusChanged( int ), this,
210                  updateSystrayTooltipStatus( int ) );
211     }
212
213     /**
214      * Callbacks
215      **/
216     var_Create( p_intf, "interaction", VLC_VAR_ADDRESS );
217     var_AddCallback( p_intf, "interaction", InteractCallback, this );
218     p_intf->b_interaction = VLC_TRUE;
219
220     /* Register callback for the intf-popupmenu variable */
221     playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
222                                         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
223     if( p_playlist != NULL )
224     {
225         var_AddCallback( p_playlist, "intf-popupmenu", PopupMenuCB, p_intf );
226         var_AddCallback( p_playlist, "intf-show", IntfShowCB, p_intf );
227         vlc_object_release( p_playlist );
228     }
229 }
230
231 MainInterface::~MainInterface()
232 {
233     /* Unregister callback for the intf-popupmenu variable */
234     playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
235                                         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
236     if( p_playlist != NULL )
237     {
238         var_DelCallback( p_playlist, "intf-popupmenu", PopupMenuCB, p_intf );
239         var_DelCallback( p_playlist, "intf-show", IntfShowCB, p_intf );
240         vlc_object_release( p_playlist );
241     }
242
243     settings->setValue( "playlist-embedded", playlistEmbeddedFlag );
244     settings->setValue( "adv-controls", isAdvancedVisible() );
245     settings->setValue( "pos", pos() );
246     settings->endGroup();
247     delete settings;
248     p_intf->b_interaction = VLC_FALSE;
249     var_DelCallback( p_intf, "interaction", InteractCallback, this );
250
251     p_intf->pf_request_window = NULL;
252     p_intf->pf_release_window = NULL;
253     p_intf->pf_control_window = NULL;
254 }
255
256 /*****************************
257  *   Main UI handling        *
258  *****************************/
259
260 /**
261  * Give the decorations of the Main Window a correct Name.
262  * If nothing is given, set it to VLC...
263  **/
264 void MainInterface::setVLCWindowsTitle( QString aTitle )
265 {
266     if( aTitle.isEmpty() )
267     {
268         setWindowTitle( qtr( "VLC media player" ) );
269     }
270     else
271     {
272         setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
273     }
274 }
275
276 void MainInterface::handleMainUi( QSettings *settings )
277 {
278     /* Create the main Widget and the mainLayout */
279     QWidget *main = new QWidget( this );
280     mainLayout = new QVBoxLayout( main );
281     setCentralWidget( main );
282
283     /* Margins, spacing */
284     main->setContentsMargins( 0, 0, 0, 0 );
285     mainLayout->setMargin( 0 );
286
287     /* Create the CONTROLS Widget */
288     controls = new ControlsWidget( p_intf,
289                    settings->value( "adv-controls", false ).toBool() );
290
291     /* Configure the Controls */
292     BUTTON_SET_IMG( controls->playlistButton, "" , playlist_icon.png,
293                     playlistEmbeddedFlag ?  qtr( "Show playlist" ) :
294                                             qtr( "Open playlist" ) );
295     BUTTONACT( controls->playlistButton, togglePlaylist() );
296
297     /* Add the controls Widget to the main Widget */
298     mainLayout->addWidget( controls );
299
300
301     /* Set initial size */
302     resize( PREF_W, PREF_H );
303     addSize = QSize( mainLayout->margin() * 2, PREF_H );
304
305     /* Visualisation */
306     visualSelector = new VisualSelector( p_intf );
307     mainLayout->insertWidget( 0, visualSelector );
308     visualSelector->hide();
309
310     /* And video Outputs */
311     if( alwaysVideoFlag )
312     {
313         bgWidget = new BackgroundWidget( p_intf );
314         bgWidget->widgetSize = settings->value( "backgroundSize",
315                                            QSize( 300, 300 ) ).toSize();
316         bgWidget->resize( bgWidget->widgetSize );
317         bgWidget->updateGeometry();
318         mainLayout->insertWidget( 0, bgWidget );
319     }
320
321     if( videoEmbeddedFlag )
322     {
323         videoWidget = new VideoWidget( p_intf );
324         videoWidget->widgetSize = QSize( 1, 1 );
325         //videoWidget->resize( videoWidget->widgetSize );
326         mainLayout->insertWidget( 0, videoWidget );
327
328         p_intf->pf_request_window  = ::DoRequest;
329         p_intf->pf_release_window  = ::DoRelease;
330         p_intf->pf_control_window  = ::DoControl;
331     }
332
333     /* Finish the sizing */
334     setMinimumSize( PREF_W, addSize.height() );
335 }
336
337 /**********************************************************************
338  * Handling of sizing of the components
339  **********************************************************************/
340 void MainInterface::calculateInterfaceSize()
341 {
342     int width = 0, height = 0;
343     if( VISIBLE( bgWidget ) )
344     {
345         width = bgWidget->widgetSize.width();
346         height = bgWidget->widgetSize.height();
347         assert( !(playlistWidget && playlistWidget->isVisible() ) );
348     }
349     else if( VISIBLE( playlistWidget ) )
350     {
351         width = playlistWidget->widgetSize.width();
352         height = playlistWidget->widgetSize.height();
353     }
354     else if( videoIsActive )
355     {
356         width =  videoWidget->widgetSize.width() ;
357         height = videoWidget->widgetSize.height();
358     }
359     else
360     {
361         width = PREF_W - addSize.width();
362         height = PREF_H - addSize.height();
363     }
364     if( VISIBLE( visualSelector ) )
365         height += visualSelector->height();
366 /*    if( VISIBLE( advControls) )
367     {
368         height += advControls->sizeHint().height();
369     }*/
370     mainSize = QSize( width + addSize.width(), height + addSize.height() );
371 }
372
373 void MainInterface::resizeEvent( QResizeEvent *e )
374 {
375     videoWidget->widgetSize.setWidth(  e->size().width() - addSize.width() );
376     if( videoWidget && videoIsActive && videoWidget->widgetSize.height() > 1 )
377     {
378         SET_WH( videoWidget, e->size().width() - addSize.width(),
379                              e->size().height()  - addSize.height() );
380         videoWidget->updateGeometry();
381     }
382     if( VISIBLE( playlistWidget ) )
383     {
384         SET_WH( playlistWidget , e->size().width() - addSize.width(),
385                                  e->size().height() - addSize.height() );
386         playlistWidget->updateGeometry();
387     }
388 }
389
390 /****************************************************************************
391  * Small right-click menus
392  ****************************************************************************/
393 void MainInterface::showSpeedMenu( QPoint pos )
394 {
395     QMenu menu( this );
396     menu.addAction( "Not Implemented Yet" );
397     menu.exec( QCursor::pos() );
398 }
399
400 void MainInterface::showTimeMenu( QPoint pos )
401 {
402     QMenu menu( this );
403     menu.addAction( "Not Implemented Yet" );
404     menu.exec( QCursor::pos() );
405 }
406
407 /****************************************************************************
408  * Video Handling
409  ****************************************************************************/
410 void *MainInterface::requestVideo( vout_thread_t *p_nvout, int *pi_x,
411                                    int *pi_y, unsigned int *pi_width,
412                                    unsigned int *pi_height )
413 {
414     void *ret = videoWidget->request( p_nvout,pi_x, pi_y, pi_width, pi_height );
415     if( ret )
416     {
417         videoIsActive = true;
418         if( VISIBLE( playlistWidget ) )
419         {
420             embeddedPlaylistWasActive = true;
421 //            playlistWidget->hide();
422         }
423         bool bgWasVisible = false;
424         if( VISIBLE( bgWidget) )
425         {
426             bgWasVisible = true;
427             bgWidget->hide();
428         }
429         if( THEMIM->getIM()->hasVideo() || !bgWasVisible )
430         {
431             videoWidget->widgetSize = QSize( *pi_width, *pi_height );
432         }
433         else /* Background widget available, use its size */
434         {
435             /* Ok, our visualizations are bad, so don't do this for the moment
436              * use the requested size anyway */
437             // videoWidget->widgetSize = bgWidget->widgeTSize;
438             videoWidget->widgetSize = QSize( *pi_width, *pi_height );
439         }
440 //        videoWidget->updateGeometry(); /// FIXME: Needed ?
441         need_components_update = true;
442     }
443     return ret;
444 }
445
446 void MainInterface::releaseVideo( void *p_win )
447 {
448     videoWidget->release( p_win );
449     videoWidget->widgetSize = QSize( 0, 0 );
450     videoWidget->resize( videoWidget->widgetSize );
451
452     if( embeddedPlaylistWasActive )
453         playlistWidget->show();
454     else if( bgWidget )
455         bgWidget->show();
456
457     videoIsActive = false;
458     need_components_update = true;
459 }
460
461 class SetVideoOnTopQtEvent : public QEvent
462 {
463 public:
464     SetVideoOnTopQtEvent( bool _onTop ) :
465       QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
466     {
467     }
468
469     bool OnTop() const
470     {
471         return onTop;
472     }
473
474 private:
475     bool onTop;
476 };
477
478 int MainInterface::controlVideo( void *p_window, int i_query, va_list args )
479 {
480     int i_ret = VLC_EGENERIC;
481     switch( i_query )
482     {
483         case VOUT_GET_SIZE:
484         {
485             unsigned int *pi_width  = va_arg( args, unsigned int * );
486             unsigned int *pi_height = va_arg( args, unsigned int * );
487             *pi_width = videoWidget->widgetSize.width();
488             *pi_height = videoWidget->widgetSize.height();
489             i_ret = VLC_SUCCESS;
490             break;
491         }
492         case VOUT_SET_SIZE:
493         {
494             unsigned int i_width  = va_arg( args, unsigned int );
495             unsigned int i_height = va_arg( args, unsigned int );
496             videoWidget->widgetSize = QSize( i_width, i_height );
497             // videoWidget->updateGeometry();
498             need_components_update = true;
499             i_ret = VLC_SUCCESS;
500             break;
501         }
502         case VOUT_SET_STAY_ON_TOP:
503         {
504             int i_arg = va_arg( args, int );
505             QApplication::postEvent( this, new SetVideoOnTopQtEvent( i_arg ) );
506             i_ret = VLC_SUCCESS;
507             break;
508         }
509         default:
510             msg_Warn( p_intf, "unsupported control query" );
511             break;
512     }
513     return i_ret;
514 }
515
516 /*****************************************************************************
517  * Playlist, Visualisation and Menus handling
518  *****************************************************************************/
519 /**
520  * Toggle the playlist widget or dialog
521  **/
522 void MainInterface::togglePlaylist()
523 {
524     // Toggle the playlist dialog if not embedded and return
525     if( !playlistEmbeddedFlag )
526     {
527         if( playlistWidget )
528         {
529             /// \todo Destroy it
530         }
531         THEDP->playlistDialog();
532         return;
533     }
534
535     // Create the playlist Widget and destroy the existing dialog
536     if( !playlistWidget )
537     {
538         PlaylistDialog::killInstance();
539         playlistWidget = new PlaylistWidget( p_intf );
540         mainLayout->insertWidget( 0, playlistWidget );
541         playlistWidget->widgetSize = settings->value( "playlistSize",
542                                                QSize( 650, 310 ) ).toSize();
543         playlistWidget->hide();
544         if(bgWidget)
545         CONNECT( playlistWidget, artSet( QString ), bgWidget, setArt(QString) );
546     }
547
548     // And toggle visibility
549     if( VISIBLE( playlistWidget ) )
550     {
551         playlistWidget->hide();
552         if( bgWidget ) bgWidget->show();
553         if( videoIsActive )
554         {
555             videoWidget->widgetSize = savedVideoSize;
556             videoWidget->resize( videoWidget->widgetSize );
557             videoWidget->updateGeometry();
558             if( bgWidget ) bgWidget->hide();
559         }
560     }
561     else
562     {
563         playlistWidget->show();
564         if( videoIsActive )
565         {
566             savedVideoSize = videoWidget->widgetSize;
567             videoWidget->widgetSize.setHeight( 0 );
568             videoWidget->resize( videoWidget->widgetSize );
569             videoWidget->updateGeometry();
570         }
571         if( VISIBLE( bgWidget ) ) bgWidget->hide();
572     }
573
574     doComponentsUpdate();
575 }
576
577 void MainInterface::undockPlaylist()
578 {
579     if( playlistWidget )
580     {
581         playlistWidget->hide();
582         playlistWidget->deleteLater();
583         mainLayout->removeWidget( playlistWidget );
584         playlistWidget = NULL;
585         playlistEmbeddedFlag = false;
586
587         menuBar()->clear();
588         QVLCMenu::createMenuBar( this, p_intf, false, isAdvancedVisible(),
589                                  visualSelectorEnabled);
590
591         if( videoIsActive )
592         {
593             videoWidget->widgetSize = savedVideoSize;
594             videoWidget->resize( videoWidget->widgetSize );
595             videoWidget->updateGeometry();
596         }
597
598         doComponentsUpdate();
599         THEDP->playlistDialog();
600     }
601 }
602
603 #if 0
604 void MainInterface::visual()
605 {
606     if( !VISIBLE( visualSelector) )
607     {
608         visualSelector->show();
609         if( !THEMIM->getIM()->hasVideo() )
610         {
611             /* Show the background widget */
612         }
613         visualSelectorEnabled = true;
614     }
615     else
616     {
617         /* Stop any currently running visualization */
618         visualSelector->hide();
619         visualSelectorEnabled = false;
620     }
621     doComponentsUpdate();
622 }
623 #endif
624
625 void MainInterface::toggleMenus()
626 {
627     msg_Dbg( p_intf, "I HAS HERE, HIDING YOUR MENUZ: \\_o<~~ coin coin" );
628     TOGGLEV( controls );
629     TOGGLEV( statusBar() );
630     updateGeometry();
631 }
632
633 /* Video widget cannot do this synchronously as it runs in another thread */
634 /* Well, could it, actually ? Probably dangerous ... */
635 void MainInterface::doComponentsUpdate()
636 {
637     calculateInterfaceSize();
638     resize( mainSize );
639 }
640
641 void MainInterface::toggleAdvanced()
642 {
643     controls->toggleAdvanced();
644 }
645
646 bool MainInterface::isAdvancedVisible()
647 {
648     return controls->b_advancedVisible;
649 }
650
651 /************************************************************************
652  * Other stuff
653  ************************************************************************/
654 void MainInterface::setDisplay( float pos, int time, int length )
655 {
656     char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
657     secstotimestr( psz_length, length );
658     secstotimestr( psz_time, time );
659     QString title;
660     title.sprintf( "%s/%s", psz_time, psz_length );
661     timeLabel->setText( " "+title+" " );
662 }
663
664 void MainInterface::setName( QString name )
665 {
666     input_name = name;
667     nameLabel->setText( " " + name+" " );
668 }
669
670 void MainInterface::setStatus( int status )
671 {
672     controls->setStatus( status );
673     if( sysTray )
674         updateSystrayMenu( status );
675 }
676
677 void MainInterface::updateOnTimer()
678 {
679     /* \todo Make this event-driven */
680     if( intf_ShouldDie( p_intf ) )
681     {
682         QApplication::closeAllWindows();
683         QApplication::quit();
684     }
685     if( need_components_update )
686     {
687         doComponentsUpdate();
688         need_components_update = false;
689     }
690
691     controls->updateOnTimer();
692 }
693
694 /*****************************************************************************
695  * Systray Icon and Systray Menu
696  *****************************************************************************/
697
698 /**
699  * Create a SystemTray icon and a menu that would go with it.
700  * Connects to a click handler on the icon.
701  **/
702 void MainInterface::createSystray()
703 {
704     QIcon iconVLC =  QIcon( QPixmap( ":/vlc128.png" ) );
705     sysTray = new QSystemTrayIcon( iconVLC, this );
706     sysTray->setToolTip( qtr( "VLC media player" ));
707
708     systrayMenu = new QMenu( qtr( "VLC media player" ), this );
709     systrayMenu->setIcon( iconVLC );
710
711     QVLCMenu::updateSystrayMenu( this, p_intf, true );
712     sysTray->show();
713
714     CONNECT( sysTray, activated(  QSystemTrayIcon::ActivationReason ),
715             this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
716 }
717
718 /**
719  * Update the menu of the Systray Icon.
720  * May be unneedded, since it just calls QVLCMenu::update
721  * FIXME !!!
722  **/
723 void MainInterface::updateSystrayMenu( int status )
724 {
725     QVLCMenu::updateSystrayMenu( this, p_intf ) ;
726 }
727
728 /**
729  * Updates the Systray Icon's menu and toggle the main interface
730  */
731 void MainInterface::toggleUpdateSystrayMenu()
732 {
733     if( isHidden() )
734     {
735         show();
736         activateWindow();
737     }
738     else
739     {
740 #ifdef WIN32
741         /* check if any visible window is above vlc in the z-order,
742          * but ignore the ones always on top */
743         WINDOWINFO wi;
744         HWND hwnd;
745         wi.cbSize = sizeof( WINDOWINFO );
746         for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
747                 hwnd && !IsWindowVisible( hwnd );
748                 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
749         if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
750                 (wi.dwExStyle&WS_EX_TOPMOST) )
751 #else
752         if( isActiveWindow() )
753 #endif
754         {
755             hide();
756         }
757         else
758         {
759             activateWindow();
760         }
761     }
762     QVLCMenu::updateSystrayMenu( this, p_intf );
763 }
764
765 void MainInterface::handleSystrayClick(
766                                     QSystemTrayIcon::ActivationReason reason )
767 {
768     switch( reason )
769     {
770         case QSystemTrayIcon::Trigger:
771             toggleUpdateSystrayMenu();
772             break;
773         case QSystemTrayIcon::MiddleClick:
774             sysTray->showMessage( qtr( "VLC media player" ),
775                     qtr( "Control menu for the player" ),
776                     QSystemTrayIcon::Information, 4000 );
777             break;
778     }
779 }
780
781 /**
782  * Updates the name of the systray Icon tooltip.
783  * Doesn't check if the systray exists, check before you call it.
784  * FIXME !!! Fusion with next function ?
785  **/
786 void MainInterface::updateSystrayTooltipName( QString name )
787 {
788     if( name.isEmpty() )
789     {
790         sysTray->setToolTip( qtr( "VLC media player" ) );
791     }
792     else
793     {
794         sysTray->setToolTip( name );
795         if( notificationEnabled && ( isHidden() || isMinimized() ) )
796         {
797             sysTray->showMessage( qtr( "VLC media player" ), name,
798                     QSystemTrayIcon::NoIcon, 4000 );
799         }
800     }
801 }
802
803 /**
804  * Updates the status of the systray Icon tooltip.
805  * Doesn't check if the systray exists, check before you call it.
806  **/
807 void MainInterface::updateSystrayTooltipStatus( int i_status )
808 {
809     switch( i_status )
810     {
811         case  0:
812             {
813                 sysTray->setToolTip( qtr( "VLC media player" ) );
814                 break;
815             }
816         case PLAYING_S:
817             {
818                 sysTray->setToolTip( input_name );
819                 //+ " - " + qtr( "Playing" ) );
820                 break;
821             }
822         case PAUSE_S:
823             {
824                 sysTray->setToolTip( input_name + " - "
825                         + qtr( "Paused") );
826                 break;
827             }
828     }
829 }
830
831 /************************************************************************
832  * D&D Events
833  ************************************************************************/
834 void MainInterface::dropEvent(QDropEvent *event)
835 {
836      const QMimeData *mimeData = event->mimeData();
837
838      /* D&D of a subtitles file, add it on the fly */
839      if( mimeData->urls().size() == 1 )
840      {
841         if( THEMIM->getIM()->hasInput() )
842         {
843             if( input_AddSubtitles( THEMIM->getInput(),
844                                     qtu( mimeData->urls()[0].toString() ),
845                                     VLC_TRUE ) )
846             {
847                 event->acceptProposedAction();
848                 return;
849             }
850         }
851      }
852      bool first = true;
853      foreach( QUrl url, mimeData->urls() ) {
854         QString s = url.toString();
855         if( s.length() > 0 ) {
856             playlist_Add( THEPL, qtu(s), NULL,
857                           PLAYLIST_APPEND | (first ? PLAYLIST_GO:0),
858                           PLAYLIST_END, VLC_TRUE, VLC_FALSE );
859             first = false;
860         }
861      }
862      event->acceptProposedAction();
863 }
864 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
865 {
866      event->acceptProposedAction();
867 }
868 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
869 {
870      event->acceptProposedAction();
871 }
872 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
873 {
874      event->accept();
875 }
876
877 /************************************************************************
878  * Events stuff
879  ************************************************************************/
880 void MainInterface::customEvent( QEvent *event )
881 {
882     if( event->type() == PLDockEvent_Type )
883     {
884         PlaylistDialog::killInstance();
885         playlistEmbeddedFlag = true;
886         menuBar()->clear();
887         QVLCMenu::createMenuBar(this, p_intf, true, isAdvancedVisible(),
888                                 visualSelectorEnabled);
889         togglePlaylist();
890     }
891     else if ( event->type() == SetVideoOnTopEvent_Type )
892     {
893         SetVideoOnTopQtEvent* p_event = (SetVideoOnTopQtEvent*)event;
894         if( p_event->OnTop() )
895             setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
896         else
897             setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
898         show(); /* necessary to apply window flags?? */
899     }
900 }
901
902 void MainInterface::keyPressEvent( QKeyEvent *e )
903 {
904     int i_vlck = qtEventToVLCKey( e );
905     if( i_vlck >= 0 )
906     {
907         var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
908         e->accept();
909     }
910     else
911         e->ignore();
912 }
913
914 void MainInterface::wheelEvent( QWheelEvent *e )
915 {
916     int i_vlckey = qtWheelEventToVLCKey( e );
917     var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
918     e->accept();
919 }
920
921 void MainInterface::closeEvent( QCloseEvent *e )
922 {
923     hide();
924     vlc_object_kill( p_intf );
925 }
926
927 /*****************************************************************************
928  * Callbacks
929  *****************************************************************************/
930 static int InteractCallback( vlc_object_t *p_this,
931                              const char *psz_var, vlc_value_t old_val,
932                              vlc_value_t new_val, void *param )
933 {
934     intf_dialog_args_t *p_arg = new intf_dialog_args_t;
935     p_arg->p_dialog = (interaction_dialog_t *)(new_val.p_address);
936     DialogEvent *event = new DialogEvent( INTF_DIALOG_INTERACTION, 0, p_arg );
937     QApplication::postEvent( THEDP, static_cast<QEvent*>(event) );
938     return VLC_SUCCESS;
939 }
940
941 /*****************************************************************************
942  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
943  *  We don't show the menu directly here because we don't want the
944  *  caller to block for a too long time.
945  *****************************************************************************/
946 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
947                         vlc_value_t old_val, vlc_value_t new_val, void *param )
948 {
949     intf_thread_t *p_intf = (intf_thread_t *)param;
950
951     if( p_intf->pf_show_dialog )
952     {
953         p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
954                                 new_val.b_bool, 0 );
955     }
956
957     return VLC_SUCCESS;
958 }
959
960 /*****************************************************************************
961  * IntfShowCB: callback triggered by the intf-show playlist variable.
962  *****************************************************************************/
963 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
964                        vlc_value_t old_val, vlc_value_t new_val, void *param )
965 {
966     intf_thread_t *p_intf = (intf_thread_t *)param;
967     //p_intf->p_sys->b_intf_show = VLC_TRUE;
968
969     return VLC_SUCCESS;
970 }