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