main_interface.cpp 38.4 KB
Newer Older
zorglub's avatar
zorglub committed
1
/*****************************************************************************
zorglub's avatar
Wtf ?    
zorglub committed
2
 * main_interface.cpp : Main interface
zorglub's avatar
zorglub committed
3
 ****************************************************************************
4
 * Copyright (C) 2006-2007 the VideoLAN team
5
 * $Id$
zorglub's avatar
zorglub committed
6
7
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 *          Jean-Baptiste Kempf <jb@videolan.org>
9
 *          Ilkka Ollakka <ileoo@videolan.org>
zorglub's avatar
zorglub committed
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24
 *****************************************************************************/
25

26
27
28
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
zorglub's avatar
zorglub committed
29

30
#include "qt4.hpp"
zorglub's avatar
zorglub committed
31
#include "main_interface.hpp"
zorglub's avatar
zorglub committed
32
#include "input_manager.hpp"
zorglub's avatar
zorglub committed
33
#include "util/qvlcframe.hpp"
34
#include "util/customwidgets.hpp"
zorglub's avatar
zorglub committed
35
#include "dialogs_provider.hpp"
36
#include "components/interface_widgets.hpp"
37
#include "components/playlist/playlist.hpp"
38
#include "dialogs/extended.hpp"
39
40
41
#include "dialogs/playlist.hpp"
#include "menus.hpp"

zorglub's avatar
zorglub committed
42
#include <QMenuBar>
zorglub's avatar
zorglub committed
43
#include <QCloseEvent>
zorglub's avatar
zorglub committed
44
#include <QPushButton>
zorglub's avatar
zorglub committed
45
#include <QStatusBar>
46
#include <QKeyEvent>
zorglub's avatar
zorglub committed
47
#include <QUrl>
48
#include <QSystemTrayIcon>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
49
50
#include <QSize>
#include <QMenu>
51
#include <QLabel>
52
53
#include <QSlider>
#include <QWidgetAction>
54
55
#include <QDockWidget>
#include <QToolBar>
56
#include <QGroupBox>
57
#include <QDate>
58
#include <QProgressBar>
59
60

#include <assert.h>
61
#include <vlc_keys.h>
zorglub's avatar
zorglub committed
62
#include <vlc_vout.h>
zorglub's avatar
zorglub committed
63

64
65
66
67
68
69
#define SET_WIDTH(i,j) i->widgetSize.setWidth(j)
#define SET_HEIGHT(i,j) i->widgetSize.setHeight(j)
#define SET_WH( i,j,k) i->widgetSize.setWidth(j); i->widgetSize.setHeight(k);

#define DS(i) i.width(),i.height()

70
71
72
73
74
/* Callback prototypes */
static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
                        vlc_value_t old_val, vlc_value_t new_val, void *param );
static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
                       vlc_value_t old_val, vlc_value_t new_val, void *param );
zorglub's avatar
zorglub committed
75
76
static int InteractCallback( vlc_object_t *, const char *, vlc_value_t,
                             vlc_value_t, void *);
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* Video handling */
static void *DoRequest( intf_thread_t *p_intf, vout_thread_t *p_vout,
                        int *pi1, int *pi2, unsigned int*pi3,unsigned int*pi4)
{
    return p_intf->p_sys->p_mi->requestVideo( p_vout, pi1, pi2, pi3, pi4 );
}
static void DoRelease( intf_thread_t *p_intf, void *p_win )
{
    return p_intf->p_sys->p_mi->releaseVideo( p_win );
}
static int DoControl( intf_thread_t *p_intf, void *p_win, int i_q, va_list a )
{
    return p_intf->p_sys->p_mi->controlVideo( p_win, i_q, a );
}
zorglub's avatar
zorglub committed
91

zorglub's avatar
zorglub committed
92
MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
zorglub's avatar
zorglub committed
93
{
94
    /* Variables initialisation */
95
    // need_components_update = false;
96
97
98
99
    bgWidget = NULL; 
    videoWidget = NULL; 
    playlistWidget = NULL;
    sysTray = NULL;
100
    videoIsActive = false;
101
    playlistVisible = false;
102
    input_name = "";
103

104
    /* Ask for privacy */
105
    askForPrivacy();
106

107
    /**
108
     *  Configuration and settings
109
     *  Pre-building of interface
110
     **/
111
112
    /* Main settings */
    setFocusPolicy( Qt::StrongFocus );
113
    setAcceptDrops( true );
114
    setWindowIcon( QApplication::windowIcon() );
115
    setWindowOpacity( config_GetFloat( p_intf, "qt-opacity" ) );
116
117

    /* Set The Video In emebedded Mode or not */
118
    videoEmbeddedFlag = config_GetInt( p_intf, "embedded-video" );
zorglub's avatar
zorglub committed
119

120
    /* Are we in the enhanced always-video mode or not ? */
121
    i_visualmode = config_GetInt( p_intf, "qt-display-mode" );
zorglub's avatar
zorglub committed
122

123
    /* Set the other interface settings */
124
125
126
    settings = new QSettings( "vlc", "vlc-qt-interface" );
    settings->beginGroup( "MainWindow" );

127
    //TODO: I don't like that code
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
128
    visualSelectorEnabled = settings->value( "visual-selector", false ).toBool();
129
    notificationEnabled = (bool)config_GetInt( p_intf, "qt-notification" );
130

131
132
133
    /**************************
     *  UI and Widgets design
     **************************/
134
    setVLCWindowsTitle();
135
    handleMainUi( settings );
136

137
#if 0
138
    /* Create a Dock to get the playlist */
139
/*    dockPL = new QDockWidget( qtr( "Playlist" ), this );
140
    dockPL->setSizePolicy( QSizePolicy::Preferred,
141
                           QSizePolicy::Expanding );
142
    dockPL->setFeatures( QDockWidget::AllDockWidgetFeatures );
143
144
145
    dockPL->setAllowedAreas( Qt::LeftDockWidgetArea
                           | Qt::RightDockWidgetArea
                           | Qt::BottomDockWidgetArea );
146
147
    dockPL->hide();*/
#endif
148

149
    /************
150
     * Menu Bar
151
     ************/
152
    QVLCMenu::createMenuBar( this, p_intf, visualSelectorEnabled );
153

154
155
    /* StatusBar Creation */
    createStatusBar();
156

157

158
159
160
    /********************
     * Input Manager    *
     ********************/
161
    MainInputManager::getInstance( p_intf );
162

163
164
165
    /**************************
     * Various CONNECTs on IM *
     **************************/
166
    /* Connect the input manager to the GUI elements it manages */
167

168
    /* It is also connected to the control->slider, see the ControlsWidget */
169
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
170
             this, setDisplayPosition( float, int, int ) );
171
    /* Change the SpeedRate in the Status */
172
    CONNECT( THEMIM->getIM(), rateChanged( int ), this, setRate( int ) );
173

174
175
    /**
     * Connects on nameChanged()
176
177
     * Those connects are not merged because different options can trigger
     * them down.
178
     */
179
    /* Naming in the controller statusbar */
180
181
    CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setName( QString ) );
182
    /* and in the systray */
183
    if( sysTray )
184
185
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
186
                 updateSystrayTooltipName( QString ) );
187
    }
188
    /* and in the title of the controller */
189
190
191
192
193
194
    if( config_GetInt( p_intf, "qt-name-in-title" ) )
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setVLCWindowsTitle( QString ) );
    }

195
    /**
196
     * CONNECTS on PLAY_STATUS
197
     **/
198
    /* Status on the main controller */
199
    CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
200
    /* and in the systray */
201
    if( sysTray )
202
203
    {
        CONNECT( THEMIM->getIM(), statusChanged( int ), this,
204
                 updateSystrayTooltipStatus( int ) );
205
    }
206

207
208
209
    /* END CONNECTS ON IM */


210
    /** OnTimeOut **/
211
212
    /* TODO Remove this function, but so far, there is no choice because there
       is no intf-should-die variable */
213
214
215
    ON_TIMEOUT( updateOnTimer() );
    //ON_TIMEOUT( debug() );

216
217
218
    /**
     * Callbacks
     **/
219
220
221
    var_Create( p_intf, "interaction", VLC_VAR_ADDRESS );
    var_AddCallback( p_intf, "interaction", InteractCallback, this );
    p_intf->b_interaction = VLC_TRUE;
222
223

    /* Register callback for the intf-popupmenu variable */
224
225
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
226
227
228
229
230
231
    if( p_playlist != NULL )
    {
        var_AddCallback( p_playlist, "intf-popupmenu", PopupMenuCB, p_intf );
        var_AddCallback( p_playlist, "intf-show", IntfShowCB, p_intf );
        vlc_object_release( p_playlist );
    }
232

233
    /* VideoWidget connect mess to avoid different threads speaking to each other */
234
235
    CONNECT( this, askReleaseVideo( void * ),
             this, releaseVideoSlot( void * ) );
236
    CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
237
             videoWidget, SetSizing( unsigned int, unsigned int ) );
238

239
    CONNECT( this, askUpdate(), this, doComponentsUpdate() );
240

241
    CONNECT( controls, advancedControlsToggled( bool ),
242
             this, doComponentsUpdate() );
243

244
    /* Size and placement of interface */
245
246
    move( settings->value( "pos", QPoint( 0, 0 ) ).toPoint() );

247
248
249
250
251
    QSize newSize = settings->value( "size", QSize( 350, 60 ) ).toSize();
    if( newSize.isValid() )
        resize( newSize );
    else
        msg_Warn( p_intf, "Invalid size in constructor" );
252

253
    /* Playlist */
254
    if( settings->value( "playlist-visible", 0 ).toInt() ) togglePlaylist();
255
    settings->endGroup();
256

257
    show();
258

259
260
    if( i_visualmode == QT_MINIMAL_MODE )
        toggleMinimalView();
261

262
    /* Update the geometry TODO: is it useful ?*/
263
    updateGeometry();
264
265
266
267
268

    /*****************************************************
     * End everything by creating the Systray Management *
     *****************************************************/
    initSystray();
269
270
271
272
}

MainInterface::~MainInterface()
{
273
274
    msg_Dbg( p_intf, "Destroying the main interface" );

275
    if( playlistWidget ) playlistWidget->savingSettings( settings );
276
    if( ExtendedDialog::exists() )
277
        ExtendedDialog::getInstance( p_intf )->savingSettings();
278

279
    settings->beginGroup( "MainWindow" );
280
//    settings->setValue( "playlist-floats", (int)(dockPL->isFloating()) );
281
    settings->setValue( "playlist-visible", (int)playlistVisible );
282
    settings->setValue( "adv-controls",
283
                        getControlsVisibilityStatus() & CONTROLS_ADVANCED );
284
    settings->setValue( "pos", pos() );
285
    settings->setValue( "size", size() );
286
287
    if( bgWidget )
        settings->setValue( "backgroundSize", bgWidget->size() );
288
289
290
291

    settings->endGroup();
    delete settings;

292
    /* Unregister callback for the intf-popupmenu variable */
293
294
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
295
296
297
298
299
300
    if( p_playlist != NULL )
    {
        var_DelCallback( p_playlist, "intf-popupmenu", PopupMenuCB, p_intf );
        var_DelCallback( p_playlist, "intf-show", IntfShowCB, p_intf );
        vlc_object_release( p_playlist );
    }
301

302
303
    p_intf->b_interaction = VLC_FALSE;
    var_DelCallback( p_intf, "interaction", InteractCallback, this );
304
305
306
307

    p_intf->pf_request_window = NULL;
    p_intf->pf_release_window = NULL;
    p_intf->pf_control_window = NULL;
308
    p_intf->p_sys->p_mi = NULL;
309
310
}

311
312
313
/*****************************
 *   Main UI handling        *
 *****************************/
314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
inline void MainInterface::createStatusBar()
{
    /****************
     *  Status Bar  *
     ****************/
    /* Widgets Creation*/
    b_remainingTime = false;
    timeLabel = new TimeLabel;
    timeLabel->setText( " --:--/--:-- " );
    timeLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
    nameLabel = new QLabel;
    nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
                                      | Qt::TextSelectableByKeyboard );
    speedLabel = new QLabel( "1.00x" );
    speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );

    /* Styling those labels */
    timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
    speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
    nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);

    pgBar = new QProgressBar;
    pgBar->hide();

    /* and adding those */
    statusBar()->addWidget( nameLabel, 8 );
    statusBar()->addPermanentWidget( speedLabel, 0 );
    statusBar()->addPermanentWidget( pgBar, 0 );
    statusBar()->addPermanentWidget( timeLabel, 0 );

    /* timeLabel behaviour:
       - double clicking opens the goto time dialog
       - right-clicking and clicking just toggle between remaining and
         elapsed time.*/
    CONNECT( timeLabel, timeLabelClicked(), this, toggleTimeDisplay() );
    CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
    CONNECT( timeLabel, timeLabelDoubleClicked(), this, toggleTimeDisplay() );

    /* Speed Label behaviour:
       - right click gives the vertical speed slider */
    CONNECT( speedLabel, customContextMenuRequested( QPoint ),
             this, showSpeedMenu( QPoint ) );
}

inline void MainInterface::initSystray()
{
    bool b_createSystray = false;
    bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
    if( config_GetInt( p_intf, "qt-start-minimized") )
    {
        if( b_systrayAvailable )
        {
            b_createSystray = true;
            hide();
        }
        else msg_Err( p_intf, "You can't minimize if you haven't a system "
                "tray bar" );
    }
    if( config_GetInt( p_intf, "qt-system-tray") )
        b_createSystray = true;

    if( b_systrayAvailable && b_createSystray )
            createSystray();
}

380
381
382
383
/**
 * Give the decorations of the Main Window a correct Name.
 * If nothing is given, set it to VLC...
 **/
384
385
386
387
void MainInterface::setVLCWindowsTitle( QString aTitle )
{
    if( aTitle.isEmpty() )
    {
388
        setWindowTitle( qtr( "VLC media player" ) );
389
390
391
    }
    else
    {
392
        setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
393
394
395
    }
}

396
397
void MainInterface::handleMainUi( QSettings *settings )
{
398
    /* Create the main Widget and the mainLayout */
399
    QWidget *main = new QWidget;
400
    setCentralWidget( main );
401
    mainLayout = new QVBoxLayout( main );
402

403
404
    /* Margins, spacing */
    main->setContentsMargins( 0, 0, 0, 0 );
405
    main->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum );
406
407
    mainLayout->setMargin( 0 );

408
    /* Create the CONTROLS Widget */
409
    /* bool b_shiny = config_GetInt( p_intf, "qt-blingbling" ); */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
410
    controls = new ControlsWidget( p_intf, this,
411
                   settings->value( "adv-controls", false ).toBool(),
412
                   config_GetInt( p_intf, "qt-blingbling" ) );
413

414
    /* Add the controls Widget to the main Widget */
415
    mainLayout->insertWidget( 0, controls );
416

417
418
419
    /* Create the Speed Control Widget */
    speedControl = new SpeedControlWidget( p_intf );
    speedControlMenu = new QMenu( this );
420
421

    QWidgetAction *widgetAction = new QWidgetAction( speedControl );
422
423
    widgetAction->setDefaultWidget( speedControl );
    speedControlMenu->addAction( widgetAction );
424

425
    /* Visualisation */
426
427
    /* Disabled for now, they SUCK */
    #if 0
428
    visualSelector = new VisualSelector( p_intf );
429
    mainLayout->insertWidget( 0, visualSelector );
430
    visualSelector->hide();
431
    #endif
432

433
    /* And video Outputs */
434
435
    if( i_visualmode == QT_ALWAYS_VIDEO_MODE ||
        i_visualmode == QT_MINIMAL_MODE )
436
437
    {
        bgWidget = new BackgroundWidget( p_intf );
438
439
        bgWidget->resize(
             settings->value( "backgroundSize", QSize( 300, 150 ) ).toSize() );
440
        bgWidget->updateGeometry();
441
        mainLayout->insertWidget( 0, bgWidget );
442
        CONNECT( this, askBgWidgetToToggle(), bgWidget, toggle() );
443
444
    }

445
    if( videoEmbeddedFlag )
446
    {
447
        videoWidget = new VideoWidget( p_intf );
448
        mainLayout->insertWidget( 0, videoWidget );
449

450
451
452
        p_intf->pf_request_window  = ::DoRequest;
        p_intf->pf_release_window  = ::DoRelease;
        p_intf->pf_control_window  = ::DoControl;
453
    }
454
455

    /* Finish the sizing */
456
    main->updateGeometry();
zorglub's avatar
zorglub committed
457
458
}

459
inline void MainInterface::askForPrivacy()
460
461
462
463
{
    /**
     * Ask for the network policy on FIRST STARTUP
     **/
464
    if( config_GetInt( p_intf, "qt-privacy-ask") )
465
466
467
468
469
470
471
472
473
474
475
    {
        QList<ConfigControl *> controls;
        if( privacyDialog( controls ) == QDialog::Accepted )
        {
            QList<ConfigControl *>::Iterator i;
            for(  i = controls.begin() ; i != controls.end() ; i++ )
            {
                ConfigControl *c = qobject_cast<ConfigControl *>(*i);
                c->doApply( p_intf );
            }

476
            config_PutInt( p_intf,  "qt-privacy-ask" , 0 );
477
            /* We have to save here because the user may not launch Prefs */
478
479
480
481
482
            config_SaveConfigFile( p_intf, NULL );
        }
    }
}

483
int MainInterface::privacyDialog( QList<ConfigControl *> controls )
484
485
486
487
488
489
490
491
492
493
{
    QDialog *privacy = new QDialog( this );

    privacy->setWindowTitle( qtr( "Privacy and Network policies" ) );

    QGridLayout *gLayout = new QGridLayout( privacy );

    QGroupBox *blabla = new QGroupBox( qtr( "Privacy and Network Warning" ) );
    QGridLayout *blablaLayout = new QGridLayout( blabla );
    QLabel *text = new QLabel( qtr(
494
        "<p>The <i>VideoLAN Team</i> doesn't like when an application goes "
495
        "online without authorization.</p>\n "
496
        "<p><i>VLC media player</i> can request limited information on "
Konstantin Pavlov's avatar
Konstantin Pavlov committed
497
        "the Internet, especially to get CD covers and songs metadata or to know "
498
        "if updates are available.</p>\n"
499
        "<p><i>VLC media player</i> <b>DOES NOT</b> send or collect <b>ANY</b> "
Konstantin Pavlov's avatar
Konstantin Pavlov committed
500
        "information, even anonymously, about your usage.</p>\n"
501
502
        "<p>Therefore please check the following options, the default being "
        "almost no access on the web.</p>\n") );
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
    text->setWordWrap( true );
    text->setTextFormat( Qt::RichText );

    blablaLayout->addWidget( text, 0, 0 ) ;

    QGroupBox *options = new QGroupBox;
    QGridLayout *optionsLayout = new QGridLayout( options );

    gLayout->addWidget( blabla, 0, 0, 1, 3 );
    gLayout->addWidget( options, 1, 0, 1, 3 );
    module_config_t *p_config;
    ConfigControl *control;
    int line = 0;

#define CONFIG_GENERIC( option, type )                            \
    p_config =  config_FindConfig( VLC_OBJECT(p_intf), option );  \
    if( p_config )                                                \
    {                                                             \
        control =  new type ## ConfigControl( VLC_OBJECT(p_intf), \
                p_config, options, false, optionsLayout, line );  \
523
        controls.append( control );                               \
524
525
526
527
528
529
530
531
    }

#define CONFIG_GENERIC_NOBOOL( option, type )                     \
    p_config =  config_FindConfig( VLC_OBJECT(p_intf), option );  \
    if( p_config )                                                \
    {                                                             \
        control =  new type ## ConfigControl( VLC_OBJECT(p_intf), \
                p_config, options, optionsLayout, line );  \
532
        controls.append( control );                               \
533
534
535
536
    }

    CONFIG_GENERIC( "album-art", IntegerList ); line++;
    CONFIG_GENERIC_NOBOOL( "fetch-meta", Bool ); line++;
537
#ifdef UPDATE_CHECK
538
539
    CONFIG_GENERIC_NOBOOL( "qt-updates-notif", Bool ); line++;
    CONFIG_GENERIC_NOBOOL( "qt-updates-days", Integer ); line++;
540
#endif
541
542
543
544
545
    QPushButton *ok = new QPushButton( qtr( "Ok" ) );

    gLayout->addWidget( ok, 2, 2 );

    CONNECT( ok, clicked(), privacy, accept() );
546
    return privacy->exec();
547
548
}

549

550
/**********************************************************************
551
 * Handling of sizing of the components
552
 **********************************************************************/
553
554
555
556
557

/* This function is probably wrong, but we don't have many many choices...
   Since we can't know from the playlist Widget if we are inside a dock or not,
   because the playlist Widget can be called by THEDP, as a separate windows for
   the skins.
558
559
   Maybe the other solution is to redefine the sizeHint() of the playlist and
   ask _parent->isFloating()...
560
   If you think this would be better, please FIXME it...
561
*/
562
#if 0
563
564
QSize MainInterface::sizeHint() const
{
565
    int nwidth  = controls->sizeHint().width();
566
567
568
569
570
    int nheight = controls->isVisible() ?
                  controls->size().height()
                  + menuBar()->size().height()
                  + statusBar()->size().height()
                  : 0 ;
571

572
    msg_Dbg( p_intf, "1 %i %i", nheight, nwidth );
573
    if( VISIBLE( bgWidget ) )
574
575
576
    {
        nheight += bgWidget->size().height();
        nwidth  = bgWidget->size().width();
577
        msg_Dbg( p_intf, "1b %i %i", nheight, nwidth );
578
    }
579
    else if( videoIsActive )
580
581
582
583
584
    {
        nheight += videoWidget->size().height();
        nwidth  = videoWidget->size().width();
        msg_Dbg( p_intf, "2 %i %i", nheight, nwidth );
    }
585
/*    if( !dockPL->isFloating() && dockPL->isVisible() && dockPL->widget()  )
586
587
    {
        nheight += dockPL->size().height();
588
        nwidth = __MAX( nwidth, dockPL->size().width() );
589
        msg_Dbg( p_intf, "3 %i %i", nheight, nwidth );
590
    }*/
591
592
    msg_Dbg( p_intf, "4 %i %i", nheight, nwidth );
    return QSize( nwidth, nheight );
593
}
594
#endif
595
#if 0
596
/* FIXME This is dead code and need to be removed AT THE END */
597
598
void MainInterface::resizeEvent( QResizeEvent *e )
{
599
600
    if( videoWidget )
        videoWidget->widgetSize.setWidth( e->size().width() - addSize.width() );
601
602
603
604
605
606
607
608
    if( videoWidget && videoIsActive && videoWidget->widgetSize.height() > 1 )
    {
        SET_WH( videoWidget, e->size().width() - addSize.width(),
                             e->size().height()  - addSize.height() );
        videoWidget->updateGeometry();
    }
    if( VISIBLE( playlistWidget ) )
    {
609
610
//        SET_WH( playlistWidget , e->size().width() - addSize.width(),
              //                   e->size().height() - addSize.height() );
611
612
613
        playlistWidget->updateGeometry();
    }
}
614
#endif
615

616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
void MainInterface::requestLayoutUpdate()
{
    emit askUpdate();
}

//FIXME remove me at the end...
void MainInterface::debug()
{
    msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
    msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
    if( videoWidget->isVisible() )
    {
//    sleep( 10 );
    msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
    msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
    }
    adjustSize();
}

635
/****************************************************************************
636
 * Small right-click menu for rate control
637
638
639
 ****************************************************************************/
void MainInterface::showSpeedMenu( QPoint pos )
{
640
    speedControlMenu->exec( QCursor::pos() - pos
641
                          + QPoint( 0, speedLabel->height() ) );
642
643
}

644
645
646
/****************************************************************************
 * Video Handling
 ****************************************************************************/
647
648
649
650
651
class SetVideoOnTopQtEvent : public QEvent
{
public:
    SetVideoOnTopQtEvent( bool _onTop ) :
      QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
652
    {}
653
654
655
656
657
658
659
660
661
662

    bool OnTop() const
    {
        return onTop;
    }

private:
    bool onTop;
};

663
664
665
666
667
668
/**
 * README
 * README
 * Thou shall not call/resize/hide widgets from on another thread.
 * This is wrong, and this is TEH reason to emit signals on those Video Functions
 **/
669
670
/* function called from ::DoRequest in order to show a nice VideoWidget
    at the good size */
671
672
673
674
void *MainInterface::requestVideo( vout_thread_t *p_nvout, int *pi_x,
                                   int *pi_y, unsigned int *pi_width,
                                   unsigned int *pi_height )
{
675
676
677
    bool bgWasVisible = false;

    /* Request the videoWidget */
678
    void *ret = videoWidget->request( p_nvout,pi_x, pi_y, pi_width, pi_height );
679
    if( ret ) /* The videoWidget is available */
680
    {
681
        /* Did we have a bg ? Hide it! */
682
        if( VISIBLE( bgWidget) )
zorglub's avatar
zorglub committed
683
        {
684
            bgWasVisible = true;
685
            emit askBgWidgetToToggle();
zorglub's avatar
zorglub committed
686
        }
687

688
        /*if( THEMIM->getIM()->hasVideo() || !bgWasVisible )
689
690
691
692
        {
            videoWidget->widgetSize = QSize( *pi_width, *pi_height );
        }
        else /* Background widget available, use its size */
693
        /*{
694
695
696
            /* Ok, our visualizations are bad, so don't do this for the moment
             * use the requested size anyway */
            // videoWidget->widgetSize = bgWidget->widgeTSize;
697
698
699
700
          /*  videoWidget->widgetSize = QSize( *pi_width, *pi_height );
        }*/

        videoIsActive = true;
701
702

        emit askVideoToResize( *pi_width, *pi_height );
703
        emit askUpdate();
704
    }
705
706
707
708
    return ret;
}

void MainInterface::releaseVideo( void *p_win )
709
710
711
712
713
{
    emit askReleaseVideo( p_win );
}

void MainInterface::releaseVideoSlot( void *p_win )
714
715
{
    videoWidget->release( p_win );
716
    videoWidget->hide();
zorglub's avatar
zorglub committed
717

718
    if( bgWidget )// WORONG
719
        bgWidget->show();
zorglub's avatar
zorglub committed
720

721
    adjustSize();
722
723
724
    videoIsActive = false;
}

725
726
int MainInterface::controlVideo( void *p_window, int i_query, va_list args )
{
727
    int i_ret = VLC_SUCCESS;
728
729
730
731
732
733
    switch( i_query )
    {
        case VOUT_GET_SIZE:
        {
            unsigned int *pi_width  = va_arg( args, unsigned int * );
            unsigned int *pi_height = va_arg( args, unsigned int * );
734
735
            *pi_width = videoWidget->videoSize.width();
            *pi_height = videoWidget->videoSize.height();
736
737
738
739
740
741
            break;
        }
        case VOUT_SET_SIZE:
        {
            unsigned int i_width  = va_arg( args, unsigned int );
            unsigned int i_height = va_arg( args, unsigned int );
742
743
            emit askVideoToResize( i_width, i_height );
            emit askUpdate();
744
745
746
            break;
        }
        case VOUT_SET_STAY_ON_TOP:
747
748
749
750
751
        {
            int i_arg = va_arg( args, int );
            QApplication::postEvent( this, new SetVideoOnTopQtEvent( i_arg ) );
            break;
        }
752
        default:
753
            i_ret = VLC_EGENERIC;
754
755
756
757
758
759
            msg_Warn( p_intf, "unsupported control query" );
            break;
    }
    return i_ret;
}

760
761
762
763
764
765
766
/*****************************************************************************
 * Playlist, Visualisation and Menus handling
 *****************************************************************************/
/**
 * Toggle the playlist widget or dialog
 **/
void MainInterface::togglePlaylist()
767
{
768
769
    THEDP->playlistDialog();
#if 0
770
    /* CREATION
771
    If no playlist exist, then create one and attach it to the DockPL*/
772
773
    if( !playlistWidget )
    {
774
        playlistWidget = new PlaylistWidget( p_intf, settings, dockPL );
775
776
777
778
779
780
781
782

        /* Add it to the parent DockWidget */
        dockPL->setWidget( playlistWidget );

        /* Add the dock to the main Interface */
        addDockWidget( Qt::BottomDockWidgetArea, dockPL );

        /* Make the playlist floating is requested. Default is not. */
783
784
        settings->beginGroup( "MainWindow" );
        if( settings->value( "playlist-floats", 1 ).toInt() )
785
        {
786
            msg_Dbg( p_intf, "we don't want the playlist inside");
787
            dockPL->setFloating( true );
788
        }
789
        settings->endGroup();
790
791
        settings->beginGroup( "playlist" );
        dockPL->move( settings->value( "pos", QPoint( 0,0 ) ).toPoint() );
792
793
794
        QSize newSize = settings->value( "size", QSize( 400, 300 ) ).toSize();
        if( newSize.isValid() )
            dockPL->resize( newSize );
795
        settings->endGroup();
796

797
        dockPL->show();
798
        playlistVisible = true;
799
800
801
    }
    else
    {
802
    /* toggle the visibility of the playlist */
803
       TOGGLEV( dockPL );
804
       resize( sizeHint() );
805
       playlistVisible = !playlistVisible;
806
    }
807
    #endif
808
809
}

810
/* Function called from the menu to undock the playlist */
zorglub's avatar
zorglub committed
811
void MainInterface::undockPlaylist()
812
{
813
814
//    dockPL->setFloating( true );
    adjustSize();
zorglub's avatar
zorglub committed
815
816
}

817
void MainInterface::toggleMinimalView()
818
{
819
    TOGGLEV( menuBar() );
820
821
    TOGGLEV( controls );
    TOGGLEV( statusBar() );
822
    doComponentsUpdate();
823
824
}

825
826
827
/* Video widget cannot do this synchronously as it runs in another thread */
/* Well, could it, actually ? Probably dangerous ... */
void MainInterface::doComponentsUpdate()
zorglub's avatar
zorglub committed
828
{
829
    msg_Dbg( p_intf, "Updating the geometry" );
830
831
//    resize( sizeHint() );
    debug();
832
}
833

834
/* toggling advanced controls buttons */
835
836
837
838
839
void MainInterface::toggleAdvanced()
{
    controls->toggleAdvanced();
}

840
/* Get the visibility status of the controls (hidden or not, advanced or not) */
841
int MainInterface::getControlsVisibilityStatus()
842
{
843
844
    return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
                + CONTROLS_ADVANCED * controls->b_advancedVisible );
845
846
}

847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
#if 0
void MainInterface::visual()
{
    if( !VISIBLE( visualSelector) )
    {
        visualSelector->show();
        if( !THEMIM->getIM()->hasVideo() )
        {
            /* Show the background widget */
        }
        visualSelectorEnabled = true;
    }
    else
    {
        /* Stop any currently running visualization */
        visualSelector->hide();
        visualSelectorEnabled = false;
    }
    doComponentsUpdate();
}
#endif

869
870
871
/************************************************************************
 * Other stuff
 ************************************************************************/
872
void MainInterface::setDisplayPosition( float pos, int time, int length )
873
874
875
{
    char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
    secstotimestr( psz_length, length );
876
877
    secstotimestr( psz_time, ( b_remainingTime && length ) ? length - time
                                                           : time );
878

879
880
    QString timestr;
    timestr.sprintf( "%s/%s", psz_time,
881
882
                            ( !length && time ) ? "--:--" : psz_length );

883
    /* Add a minus to remaining time*/
884
885
    if( b_remainingTime && length ) timeLabel->setText( " -"+timestr+" " );
    else timeLabel->setText( " "+timestr+" " );
886
887
}

888
void MainInterface::toggleTimeDisplay()
889
{
890
    b_remainingTime = !b_remainingTime;
891
892
}

893
894
void MainInterface::setName( QString name )
{
895
896
897
898
899
    input_name = name; /* store it for the QSystray use */
    /* Display it in the status bar, but also as a Tooltip in case it doesn't
       fit in the label */
    nameLabel->setText( " " + name + " " );
    nameLabel->setToolTip( " " + name +" " );
900
901
902
903
}

void MainInterface::setStatus( int status )
{
904
    /* Forward the status to the controls to toggle Play/Pause */
905
    controls->setStatus( status );
906
    /* And in the systray for the menu */
907
    if( sysTray )
908
        QVLCMenu::updateSystrayMenu( this, p_intf );
909
910
}

911
912
913
void MainInterface::setRate( int rate )
{
    QString str;
914
    str.setNum( ( 1000 / (double)rate ), 'f', 2 );
915
916
    str.append( "x" );
    speedLabel->setText( str );
917
    speedControl->updateControls( rate );
918
919
}

920
921
void MainInterface::updateOnTimer()
{
922
    /* No event for dying */
923
    if( intf_ShouldDie( p_intf ) )
924
    {
925
926
        QApplication::closeAllWindows();
        QApplication::quit();
927
    }
928
929
930
931
932
933
934
935
936
937
938
939
}

/*****************************************************************************
 * Systray Icon and Systray Menu
 *****************************************************************************/

/**
 * Create a SystemTray icon and a menu that would go with it.
 * Connects to a click handler on the icon.
 **/
void MainInterface::createSystray()
{
940
941
942
943
944
    QIcon iconVLC;
    if( QDate::currentDate().dayOfYear() >= 354 )
        iconVLC =  QIcon( QPixmap( ":/vlc128-christmas.png" ) );
    else
        iconVLC =  QIcon( QPixmap( ":/vlc128.png" ) );
945
946
947
948
949
950
951
952
953
    sysTray = new QSystemTrayIcon( iconVLC, this );
    sysTray->setToolTip( qtr( "VLC media player" ));

    systrayMenu = new QMenu( qtr( "VLC media player" ), this );
    systrayMenu->setIcon( iconVLC );

    QVLCMenu::updateSystrayMenu( this, p_intf, true );
    sysTray->show();

954
    CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
955
956
957
958
959
960
961
962
            this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
}

/**
 * Updates the Systray Icon's menu and toggle the main interface
 */
void MainInterface::toggleUpdateSystrayMenu()
{
963
    /* If hidden, show it */
964
965
966
967
968
    if( isHidden() )
    {
        show();
        activateWindow();
    }
969
970
    else if( isMinimized() )
    {
971
        /* Minimized */
972
973
974
        showNormal();
        activateWindow();
    }
975
976
    else
    {
977
        /* Visible */
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
#ifdef WIN32
        /* check if any visible window is above vlc in the z-order,
         * but ignore the ones always on top */
        WINDOWINFO wi;
        HWND hwnd;
        wi.cbSize = sizeof( WINDOWINFO );
        for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
                hwnd && !IsWindowVisible( hwnd );
                hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
        if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
                (wi.dwExStyle&WS_EX_TOPMOST) )
#else
        if( isActiveWindow() )
#endif<