main_interface.cpp 34.1 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>
zorglub's avatar
zorglub committed
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * 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
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23
 *****************************************************************************/
zorglub's avatar
zorglub committed
24

25
#include "qt4.hpp"
zorglub's avatar
zorglub committed
26
#include "main_interface.hpp"
zorglub's avatar
zorglub committed
27
#include "input_manager.hpp"
zorglub's avatar
zorglub committed
28
#include "util/qvlcframe.hpp"
29
#include "util/customwidgets.hpp"
zorglub's avatar
zorglub committed
30
#include "dialogs_provider.hpp"
31
#include "components/interface_widgets.hpp"
32
33
34
#include "dialogs/playlist.hpp"
#include "menus.hpp"

35

zorglub's avatar
zorglub committed
36
#include <QMenuBar>
zorglub's avatar
zorglub committed
37
#include <QCloseEvent>
zorglub's avatar
zorglub committed
38
#include <QPushButton>
zorglub's avatar
zorglub committed
39
#include <QStatusBar>
40
#include <QKeyEvent>
zorglub's avatar
zorglub committed
41
#include <QUrl>
42
#include <QSystemTrayIcon>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
43
44
#include <QSize>
#include <QMenu>
45
#include <QLabel>
46
47
#include <QSlider>
#include <QWidgetAction>
48
49
#include <QDockWidget>
#include <QToolBar>
50
#include <QGroupBox>
51
52

#include <assert.h>
53
#include <vlc_keys.h>
zorglub's avatar
zorglub committed
54
#include <vlc_vout.h>
zorglub's avatar
zorglub committed
55

zorglub's avatar
zorglub committed
56
#ifdef WIN32
zorglub's avatar
zorglub committed
57
    #define PREF_W 410
58
    #define PREF_H 151
zorglub's avatar
zorglub committed
59
#else
60
61
    #define PREF_W 400
    #define PREF_H 140
zorglub's avatar
zorglub committed
62
#endif
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
    bgWidget = NULL; videoWidget = NULL; playlistWidget = NULL;
zorglub's avatar
zorglub committed
97
    embeddedPlaylistWasActive = videoIsActive = false;
98
    input_name = "";
99
    playlistWidget = new PlaylistWidget( p_intf );
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
    /* Ask for the network policy on first startup */
    if( config_GetInt( p_intf, "privacy-ask") )
    {
        QList<ConfigControl *> controls;
        privacyDialog( controls );

        QList<ConfigControl *>::Iterator i;
        for(  i = controls.begin() ; i != controls.end() ; i++ )
        {
            ConfigControl *c = qobject_cast<ConfigControl *>(*i);
            c->doApply( p_intf );
        }

        config_PutInt( p_intf,  "privacy-ask" , 0 );
        config_SaveConfigFile( p_intf, NULL );
    }

118
    /**
119
     *  Configuration and settings
120
     **/
121
    settings = new QSettings( "vlc", "vlc-qt-interface" );
122
123
    settings->beginGroup( "MainWindow" );

124
125
    /* Main settings */
    setFocusPolicy( Qt::StrongFocus );
126
    setAcceptDrops( true );
127
    setWindowIcon( QApplication::windowIcon() );
128
    setWindowOpacity( config_GetFloat( p_intf, "qt-opacity" ) );
129
130

    /* Set The Video In emebedded Mode or not */
zorglub's avatar
zorglub committed
131
    videoEmbeddedFlag = false;
132
133
    if( config_GetInt( p_intf, "embedded-video" ) )
        videoEmbeddedFlag = true;
zorglub's avatar
zorglub committed
134
135

    alwaysVideoFlag = false;
136
    if( videoEmbeddedFlag && config_GetInt( p_intf, "qt-always-video" ) )
zorglub's avatar
zorglub committed
137
138
        alwaysVideoFlag = true;

139
    /* Set the other interface settings */
140
141
142
    visualSelectorEnabled = settings->value( "visual-selector", false ).toBool();
    notificationEnabled = config_GetInt( p_intf, "qt-notification" )
                          ? true : false;
143

144
145
146
    /**************************
     *  UI and Widgets design
     **************************/
147
    setVLCWindowsTitle();
148
    dockPL = new QDockWidget( qtr("Playlist"), this );
149

150
    /* Create a Dock to get the playlist */
151
    handleMainUi( settings );
152
153
154
155
    dockPL->setAllowedAreas( Qt::LeftDockWidgetArea
                           | Qt::RightDockWidgetArea
                           | Qt::BottomDockWidgetArea );
    dockPL->setFeatures( QDockWidget::AllDockWidgetFeatures );
156
157
    dockPL->setWidget( playlistWidget );
    addDockWidget( Qt::BottomDockWidgetArea, dockPL );
158

159
    /* Menu Bar */
160
    QVLCMenu::createMenuBar( this, p_intf, visualSelectorEnabled );
161

162
163
164
165
166
    /****************
     *  Status Bar  *
     ****************/

    /* Widgets Creation*/
167
    b_remainingTime = false;
168
    timeLabel = new TimeLabel;
169
    nameLabel = new QLabel;
170
171
    nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
                                      | Qt::TextSelectableByKeyboard );
172
    speedLabel = new QLabel( "1.00x" );
173
174
175
    speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );

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

    /* and adding those */
181
182
183
    statusBar()->addWidget( nameLabel, 8 );
    statusBar()->addPermanentWidget( speedLabel, 0 );
    statusBar()->addPermanentWidget( timeLabel, 2 );
184
185
186
187
188

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

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

198
199
200
    /**********************
     * Systray Management *
     **********************/
201
    sysTray = NULL;
202
203
    bool b_createSystray = false;
    bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
204
    if( config_GetInt( p_intf, "qt-start-minimized") )
205
    {
206
207
        if( b_systrayAvailable ){
            b_createSystray = true;
208
            hide(); //FIXME BUG HERE
209
210
211
        }
        else msg_Warn( p_intf, "You can't minize if you haven't a system "
                "tray bar" );
212
    }
213
214
    if( config_GetInt( p_intf, "qt-system-tray") )
        b_createSystray = true;
215
216

    if( b_systrayAvailable && b_createSystray )
217
            createSystray();
218

219
    if( config_GetInt( p_intf, "qt-minimal-view" ) )
220
        toggleMinimalView();
221

222
223
224
    /* Init input manager */
    MainInputManager::getInstance( p_intf );
    ON_TIMEOUT( updateOnTimer() );
225
//    ON_TIMEOUT( debug() );
226

227
228
229
230

    /********************
     * Various CONNECTs *
     ********************/
231

232
    /* Connect the input manager to the GUI elements it manages */
233
    /* It is also connected to the control->slider, see the ControlsWidget */
234
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
235
             this, setDisplayPosition( float, int, int ) );
236

237
    CONNECT( THEMIM->getIM(), rateChanged( int ), this, setRate( int ) );
238

239
240
241
    /**
     * Connects on nameChanged()
     */
242
    /* Naming in the controller statusbar */
243
244
    CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setName( QString ) );
245
    /* and in the systray */
246
    if( sysTray )
247
248
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
249
                 updateSystrayTooltipName( QString ) );
250
    }
251
    /* and in the title of the controller */
252
253
254
255
256
257
    if( config_GetInt( p_intf, "qt-name-in-title" ) )
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setVLCWindowsTitle( QString ) );
    }

258
259
    /** CONNECTS on PLAY_STATUS **/
    /* Status on the main controller */
260
    CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
261
    /* and in the systray */
262
    if( sysTray )
263
264
    {
        CONNECT( THEMIM->getIM(), statusChanged( int ), this,
265
                 updateSystrayTooltipStatus( int ) );
266
    }
267

268
269
270
    /**
     * Callbacks
     **/
271
272
273
    var_Create( p_intf, "interaction", VLC_VAR_ADDRESS );
    var_AddCallback( p_intf, "interaction", InteractCallback, this );
    p_intf->b_interaction = VLC_TRUE;
274
275

    /* Register callback for the intf-popupmenu variable */
276
277
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
278
279
280
281
282
283
    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 );
    }
284
285
286

    CONNECT( this, askReleaseVideo( void * ), this, releaseVideoSlot( void * ) );

287
288
    // DEBUG FIXME
    hide();
289
    updateGeometry();
290
291
292
293
}

MainInterface::~MainInterface()
{
294
    /* Unregister callback for the intf-popupmenu variable */
295
296
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
297
298
299
300
301
302
303
    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 );
    }

304
305
    settings->setValue( "playlist-embedded", !dockPL->isFloating() );
    settings->setValue( "adv-controls", getControlsVisibilityStatus() & CONTROLS_ADVANCED );
zorglub's avatar
zorglub committed
306
307
308
    settings->setValue( "pos", pos() );
    settings->endGroup();
    delete settings;
309
310
    p_intf->b_interaction = VLC_FALSE;
    var_DelCallback( p_intf, "interaction", InteractCallback, this );
311
312
313
314

    p_intf->pf_request_window = NULL;
    p_intf->pf_release_window = NULL;
    p_intf->pf_control_window = NULL;
315
316
}

317
318
319
/*****************************
 *   Main UI handling        *
 *****************************/
320
321
322
323
324

/**
 * Give the decorations of the Main Window a correct Name.
 * If nothing is given, set it to VLC...
 **/
325
326
327
328
void MainInterface::setVLCWindowsTitle( QString aTitle )
{
    if( aTitle.isEmpty() )
    {
329
        setWindowTitle( qtr( "VLC media player" ) );
330
331
332
    }
    else
    {
333
        setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
334
335
336
    }
}

337

338
339
void MainInterface::handleMainUi( QSettings *settings )
{
340
    /* Create the main Widget and the mainLayout */
341
    QWidget *main = new QWidget( this );
342
    mainLayout = new QVBoxLayout( main );
343
344
    setCentralWidget( main );

345
346
347
348
    /* Margins, spacing */
    main->setContentsMargins( 0, 0, 0, 0 );
    mainLayout->setMargin( 0 );

349
    /* Create the CONTROLS Widget */
350
    bool b_shiny = config_GetInt( p_intf, "qt-blingbling" );
351
    controls = new ControlsWidget( p_intf,
352
353
                   settings->value( "adv-controls", false ).toBool(),
                   b_shiny );
354

355
356
    /* Configure the Controls, the playlist button doesn't trigger THEDP
       but the toggle from this MainInterface */
357
    BUTTONACT( controls->playlistButton, togglePlaylist() );
358

359
    /* Add the controls Widget to the main Widget */
360
361
    mainLayout->addWidget( controls );

362
363
364
365
366
367
    /* Create the Speed Control Widget */
    speedControl = new SpeedControlWidget( p_intf );
    speedControlMenu = new QMenu( this );
    QWidgetAction *widgetAction = new QWidgetAction( this );
    widgetAction->setDefaultWidget( speedControl );
    speedControlMenu->addAction( widgetAction );
368

369
    /* Set initial size */
370

371
    /* Visualisation */
372
    visualSelector = new VisualSelector( p_intf );
373
    mainLayout->insertWidget( 0, visualSelector );
374
375
    visualSelector->hide();

376
    /* And video Outputs */
377
    if( alwaysVideoFlag )
378
379
380
    {
        bgWidget = new BackgroundWidget( p_intf );
        bgWidget->widgetSize = settings->value( "backgroundSize",
381
                                           QSize( 300, 300 ) ).toSize();
382
383
        bgWidget->resize( bgWidget->widgetSize );
        bgWidget->updateGeometry();
384
        mainLayout->insertWidget( 0, bgWidget );
385
        CONNECT( this, askBgWidgetToToggle(), bgWidget, toggle() );
386
        CONNECT( playlistWidget, artSet( QString ), bgWidget, setArt(QString) );
387
388
    }

389
    if( videoEmbeddedFlag )
390
    {
391
        videoWidget = new VideoWidget( p_intf );
392
        videoWidget->widgetSize = QSize( 1, 1 );
393
        //videoWidget->resize( videoWidget->widgetSize );
394
        mainLayout->insertWidget( 0, videoWidget );
395

396
397
398
        p_intf->pf_request_window  = ::DoRequest;
        p_intf->pf_release_window  = ::DoRelease;
        p_intf->pf_control_window  = ::DoControl;
399
    }
400
401

    /* Finish the sizing */
402
403
    setMinimumSize( PREF_W, PREF_H );
    updateGeometry();
zorglub's avatar
zorglub committed
404
405
}

406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446

void MainInterface::privacyDialog( QList<ConfigControl *> controls )
{
    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(
        "<p>The <i>VideoLAN Team</i> doesn't like when an application goes online without "
        "authorisation.</p>\n "
        "<p><i>VLC media player</i> can request limited information on "
        "Internet, espically to get CD Covers and songs metadata or to know "
        "if updates are available.</p>\n"
        "<p><i>VLC media player</i> <b>DOES NOT</b> send or collect <b>ANY</b> information, even anonymously about your "
        "usage.</p>\n"
        "<p>Therefore please check the following options, the default being almost no "
        "access on the web.</p>\n") );
    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 );  \
447
        controls.append( control );                               \
448
449
450
451
452
453
454
455
    }

#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 );  \
456
        controls.append( control );                               \
457
458
459
460
461
462
463
464
465
466
467
468
469
470
    }

    CONFIG_GENERIC( "album-art", IntegerList ); line++;
    CONFIG_GENERIC_NOBOOL( "fetch-meta", Bool ); line++;
    CONFIG_GENERIC_NOBOOL( "qt-updates-notif", Bool );

    QPushButton *ok = new QPushButton( qtr( "Ok" ) );

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

    CONNECT( ok, clicked(), privacy, accept() );
    privacy->exec();
}

471
472
473
474
475
void MainInterface::debug()
{
    msg_Dbg( p_intf, "size: %i - %i", controls->size().height(), controls->size().width() );
    msg_Dbg( p_intf, "sizeHint: %i - %i", controls->sizeHint().height(), controls->sizeHint().width() );
}
476
/**********************************************************************
477
 * Handling of sizing of the components
478
 **********************************************************************/
479
#if 0
480
481
482
483
484
void MainInterface::calculateInterfaceSize()
{
    int width = 0, height = 0;
    if( VISIBLE( bgWidget ) )
    {
485
        width  = bgWidget->widgetSize.width();
486
487
488
489
        height = bgWidget->widgetSize.height();
    }
    else if( videoIsActive )
    {
490
        width  = videoWidget->widgetSize.width() ;
491
492
493
494
        height = videoWidget->widgetSize.height();
    }
    else
    {
495
        width  = PREF_W - addSize.width();
496
497
        height = PREF_H - addSize.height();
    }
Rafaël Carré's avatar
Rafaël Carré committed
498
    if( !dockPL->isFloating() && dockPL->widget() )
499
500
501
502
    {
        width  += dockPL->widget()->width();
        height += dockPL->widget()->height();
    }
503
504
505
506
507
508
509
    if( VISIBLE( visualSelector ) )
        height += visualSelector->height();
    mainSize = QSize( width + addSize.width(), height + addSize.height() );
}

void MainInterface::resizeEvent( QResizeEvent *e )
{
510
511
    if( videoWidget )
        videoWidget->widgetSize.setWidth( e->size().width() - addSize.width() );
512
513
514
515
516
517
518
519
    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 ) )
    {
520
521
522
        //FIXME
//        SET_WH( playlistWidget , e->size().width() - addSize.width(),
              //                   e->size().height() - addSize.height() );
523
524
525
        playlistWidget->updateGeometry();
    }
}
526
#endif
527

528
/****************************************************************************
529
 * Small right-click menu for rate control
530
531
532
 ****************************************************************************/
void MainInterface::showSpeedMenu( QPoint pos )
{
533
534
    speedControlMenu->exec( QCursor::pos() - pos
            + QPoint( 0, speedLabel->height() ) );
535
536
}

537
538
539
/****************************************************************************
 * Video Handling
 ****************************************************************************/
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
class SetVideoOnTopQtEvent : public QEvent
{
public:
    SetVideoOnTopQtEvent( bool _onTop ) :
      QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
    {
    }

    bool OnTop() const
    {
        return onTop;
    }

private:
    bool onTop;
};


558
559
560
561
562
void *MainInterface::requestVideo( vout_thread_t *p_nvout, int *pi_x,
                                   int *pi_y, unsigned int *pi_width,
                                   unsigned int *pi_height )
{
    void *ret = videoWidget->request( p_nvout,pi_x, pi_y, pi_width, pi_height );
563
564
565
    if( ret )
    {
        videoIsActive = true;
566

567
568
        bool bgWasVisible = false;
        if( VISIBLE( bgWidget) )
zorglub's avatar
zorglub committed
569
        {
570
            bgWasVisible = true;
571
            emit askBgWidgetToToggle();
zorglub's avatar
zorglub committed
572
        }
573

574
575
576
577
578
579
580
581
582
583
584
        if( THEMIM->getIM()->hasVideo() || !bgWasVisible )
        {
            videoWidget->widgetSize = QSize( *pi_width, *pi_height );
        }
        else /* Background widget available, use its size */
        {
            /* Ok, our visualizations are bad, so don't do this for the moment
             * use the requested size anyway */
            // videoWidget->widgetSize = bgWidget->widgeTSize;
            videoWidget->widgetSize = QSize( *pi_width, *pi_height );
        }
585
        videoWidget->updateGeometry(); // Needed for deinterlace
586
        updateGeometry();
587
    }
588
589
590
591
    return ret;
}

void MainInterface::releaseVideo( void *p_win )
592
593
594
595
596
{
    emit askReleaseVideo( p_win );
}

void MainInterface::releaseVideoSlot( void *p_win )
597
598
{
    videoWidget->release( p_win );
599
    videoWidget->hide();
zorglub's avatar
zorglub committed
600

601
    if( bgWidget )
602
        bgWidget->show();
zorglub's avatar
zorglub committed
603

604
    videoIsActive = false;
605
    updateGeometry();
606
607
}

608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
int MainInterface::controlVideo( void *p_window, int i_query, va_list args )
{
    int i_ret = VLC_EGENERIC;
    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 * );
            *pi_width = videoWidget->widgetSize.width();
            *pi_height = videoWidget->widgetSize.height();
            i_ret = VLC_SUCCESS;
            break;
        }
        case VOUT_SET_SIZE:
        {
            unsigned int i_width  = va_arg( args, unsigned int );
            unsigned int i_height = va_arg( args, unsigned int );
            videoWidget->widgetSize = QSize( i_width, i_height );
627
            videoWidget->updateGeometry();
628
            updateGeometry();
629
630
631
632
            i_ret = VLC_SUCCESS;
            break;
        }
        case VOUT_SET_STAY_ON_TOP:
633
634
635
636
637
638
        {
            int i_arg = va_arg( args, int );
            QApplication::postEvent( this, new SetVideoOnTopQtEvent( i_arg ) );
            i_ret = VLC_SUCCESS;
            break;
        }
639
640
641
642
643
644
645
        default:
            msg_Warn( p_intf, "unsupported control query" );
            break;
    }
    return i_ret;
}

646
647
648
649
650
651
652
/*****************************************************************************
 * Playlist, Visualisation and Menus handling
 *****************************************************************************/
/**
 * Toggle the playlist widget or dialog
 **/
void MainInterface::togglePlaylist()
653
{
654
655
656
657
658
    /* If no playlist exist, then create one and attach it to the DockPL*/
    if( !playlistWidget )
    {
        msg_Dbg( p_intf, "Creating a new playlist" );
        playlistWidget = new PlaylistWidget( p_intf );
659
        if( bgWidget )
660
661
            CONNECT( playlistWidget, artSet( QString ), bgWidget, setArt(QString) );

662
663
664
        //FIXME
/*        playlistWidget->widgetSize = settings->value( "playlistSize",
                                               QSize( 650, 310 ) ).toSize();*/
665
666
667
668
669
670
671
672
673
        /* Add it to the parent DockWidget */
        dockPL->setWidget( playlistWidget );

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

        msg_Dbg( p_intf, "Creating a new playlist" );

        /* Make the playlist floating is requested. Default is not. */
674
        if( !(settings->value( "playlist-embedded", true )).toBool() );
675
676
        {
            msg_Dbg( p_intf, "we don't want it inside");
677
            //dockPL->setFloating( true );
678
679
680
681
682
683
684
        }

    }
    else
    {
    /* toggle the display */
       TOGGLEV( dockPL );
685
       resize(sizeHint());
686
    }
687
#if 0
688
    doComponentsUpdate();
689
690
#endif
    updateGeometry();
691
692
}

zorglub's avatar
zorglub committed
693
void MainInterface::undockPlaylist()
694
{
695
    dockPL->setFloating( true );
696
697
    updateGeometry();
#if 0
698
    doComponentsUpdate();
699
#endif
zorglub's avatar
zorglub committed
700
701
}

702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
#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

724
void MainInterface::toggleMinimalView()
725
{
726
    TOGGLEV( menuBar() );
727
728
    TOGGLEV( controls );
    TOGGLEV( statusBar() );
729
    updateGeometry();
730
731
}

732
733
/* Video widget cannot do this synchronously as it runs in another thread */
/* Well, could it, actually ? Probably dangerous ... */
734
#if 0
735
void MainInterface::doComponentsUpdate()
zorglub's avatar
zorglub committed
736
{
737
738
739
    calculateInterfaceSize();
    resize( mainSize );
}
740
#endif
741
742
743
744
745
746

void MainInterface::toggleAdvanced()
{
    controls->toggleAdvanced();
}

747
int MainInterface::getControlsVisibilityStatus()
748
{
749
750
    return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
                + CONTROLS_ADVANCED * controls->b_advancedVisible );
751
752
753
754
755
}

/************************************************************************
 * Other stuff
 ************************************************************************/
756
void MainInterface::setDisplayPosition( float pos, int time, int length )
757
758
759
{
    char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
    secstotimestr( psz_length, length );
760
761
    secstotimestr( psz_time, ( b_remainingTime && length ) ? length - time
                                                           : time );
762

763
764
765
766
    QString title;
    title.sprintf( "%s/%s", psz_time,
                            ( !length && time ) ? "--:--" : psz_length );

767
    /* Add a minus to remaining time*/
768
    if( b_remainingTime && length ) timeLabel->setText( " -"+title+" " );
769
    else timeLabel->setText( " "+title+" " );
770
771
}

772
void MainInterface::toggleTimeDisplay()
773
774
775
776
{
    b_remainingTime = ( b_remainingTime ? false : true );
}

777
778
void MainInterface::setName( QString name )
{
779
780
781
782
783
    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 +" " );
784
785
786
787
}

void MainInterface::setStatus( int status )
{
788
    /* Forward the status to the controls to toggle Play/Pause */
789
    controls->setStatus( status );
790
    /* And in the systray for the menu */
791
    if( sysTray )
792
        QVLCMenu::updateSystrayMenu( this, p_intf );
793
794
}

795
796
797
void MainInterface::setRate( int rate )
{
    QString str;
798
    str.setNum( ( 1000 / (double)rate), 'f', 2 );
799
800
    str.append( "x" );
    speedLabel->setText( str );
801
    speedControl->updateControls( rate );
802
803
}

804
805
806
807
void MainInterface::updateOnTimer()
{
    /* \todo Make this event-driven */
    if( intf_ShouldDie( p_intf ) )
808
    {
809
810
        QApplication::closeAllWindows();
        QApplication::quit();
811
    }
812
#if 0
813
    if( need_components_update )
814
    {
815
816
817
        doComponentsUpdate();
        need_components_update = false;
    }
818
#endif
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842

    controls->updateOnTimer();
}

/*****************************************************************************
 * 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()
{
    QIcon iconVLC =  QIcon( QPixmap( ":/vlc128.png" ) );
    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();

843
    CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
844
845
846
847
848
849
850
851
852
853
854
855
856
            this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
}

/**
 * Updates the Systray Icon's menu and toggle the main interface
 */
void MainInterface::toggleUpdateSystrayMenu()
{
    if( isHidden() )
    {
        show();
        activateWindow();
    }
857
858
859
860
861
    else if( isMinimized() )
    {
        showNormal();
        activateWindow();
    }
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
    else
    {
#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
        {
            hide();
        }
881
        else
882
883
884
        {
            activateWindow();
        }
885
    }
886
    QVLCMenu::updateSystrayMenu( this, p_intf );
887
888
}

889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
void MainInterface::handleSystrayClick(
                                    QSystemTrayIcon::ActivationReason reason )
{
    switch( reason )
    {
        case QSystemTrayIcon::Trigger:
            toggleUpdateSystrayMenu();
            break;
        case QSystemTrayIcon::MiddleClick:
            sysTray->showMessage( qtr( "VLC media player" ),
                    qtr( "Control menu for the player" ),
                    QSystemTrayIcon::Information, 4000 );
            break;
    }
}

/**
 * Updates the name of the systray Icon tooltip.
 * Doesn't check if the systray exists, check before you call it.
 **/
void MainInterface::updateSystrayTooltipName( QString name )
{
    if( name.isEmpty() )
    {
        sysTray->setToolTip( qtr( "VLC media player" ) );
    }
    else
    {
        sysTray->setToolTip( name );
918
        if( notificationEnabled && ( isHidden() || isMinimized() ) )
919
920
921
922
        {
            sysTray->showMessage( qtr( "VLC media player" ), name,
                    QSystemTrayIcon::NoIcon, 4000 );
        }
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
    }
}

/**
 * Updates the status of the systray Icon tooltip.
 * Doesn't check if the systray exists, check before you call it.
 **/
void MainInterface::updateSystrayTooltipStatus( int i_status )
{
    switch( i_status )
    {
        case  0:
            {
                sysTray->setToolTip( qtr( "VLC media player" ) );
                break;
            }
        case PLAYING_S:
            {
                sysTray->setToolTip( input_name );
                break;
            }
        case PAUSE_S:
            {
                sysTray->setToolTip( input_name + " - "
                        + qtr( "Paused") );
                break;
            }
    }
}
952
953

/************************************************************************
954
 * D&D Events
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
 ************************************************************************/
void MainInterface::dropEvent(QDropEvent *event)
{
     const QMimeData *mimeData = event->mimeData();

     /* D&D of a subtitles file, add it on the fly */
     if( mimeData->urls().size() == 1 )
     {
        if( THEMIM->getIM()->hasInput() )
        {
            if( input_AddSubtitles( THEMIM->getInput(),
                                    qtu( mimeData->urls()[0].toString() ),
                                    VLC_TRUE ) )
            {
                event->acceptProposedAction();
                return;
            }
        }
     }
     bool first = true;
     foreach( QUrl url, mimeData->urls() ) {
        QString s = url.toString();
        if( s.length() > 0 ) {
978
979
            playlist_Add( THEPL, qtu(s), NULL,
                          PLAYLIST_APPEND | (first ? PLAYLIST_GO:0),
980
                          PLAYLIST_END, VLC_TRUE, VLC_FALSE );
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
            first = false;
        }
     }
     event->acceptProposedAction();
}
void MainInterface::dragEnterEvent(QDragEnterEvent *event)
{
     event->acceptProposedAction();
}
void MainInterface::dragMoveEvent(QDragMoveEvent *event)
{
     event->acceptProposedAction();
}
void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
{
     event->accept();
}

999
/************************************************************************
1000
 * Events stuff
1001
 ************************************************************************/
1002
1003
void MainInterface::customEvent( QEvent *event )
{
1004
#if 0
1005
1006
1007
1008
1009
    if( event->type() == PLDockEvent_Type )
    {
        PlaylistDialog::killInstance();
        playlistEmbeddedFlag = true;
        menuBar()->clear();
1010
        QVLCMenu::createMenuBar(this, p_intf, true, visualSelectorEnabled);
1011
1012
        togglePlaylist();
    }
1013
1014
1015
#endif
    /*else */
    if ( event->type() == SetVideoOnTopEvent_Type )
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
    {
        SetVideoOnTopQtEvent* p_event = (SetVideoOnTopQtEvent*)event;
        if( p_event->OnTop() )
            setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
        else
            setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
        show(); /* necessary to apply window flags?? */
    }
}

1026
1027
void MainInterface::keyPressEvent( QKeyEvent *e )
{
1028
1029
1030
1031
1032
1033
1034
    if( ( e->modifiers() &  Qt::ControlModifier ) && ( e->key() & Qt::Key_H )
          && menuBar()->isHidden() )
    {
        toggleMinimalView();
        e->accept();
    }

1035
    int i_vlck = qtEventToVLCKey( e );
1036
    if( i_vlck > 0 )
1037
    {
1038
        var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1039
1040
1041
1042
1043
1044
        e->accept();
    }
    else
        e->ignore();
}

1045
1046
void MainInterface::wheelEvent( QWheelEvent *e )
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
1047
    int i_vlckey = qtWheelEventToVLCKey( e );
1048
1049
1050
1051
    var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
    e->accept();
}

zorglub's avatar
zorglub committed
1052
1053
1054
void MainInterface::closeEvent( QCloseEvent *e )
{
    hide();
1055
    vlc_object_kill( p_intf );
zorglub's avatar
zorglub committed
1056
}
zorglub's avatar
zorglub committed
1057

1058
1059
1060
/*****************************************************************************
 * Callbacks
 *****************************************************************************/
zorglub's avatar
zorglub committed
1061
1062
1063
1064
1065
1066
1067
static int InteractCallback( vlc_object_t *p_this,
                             const char *psz_var, vlc_value_t old_val,
                             vlc_value_t new_val, void *param )
{
    intf_dialog_args_t *p_arg = new intf_dialog_args_t;
    p_arg->p_dialog = (interaction_dialog_t *)(new_val.p_address);
    DialogEvent *event = new DialogEvent( INTF_DIALOG_INTERACTION, 0, p_arg );
1068
    QApplication::postEvent( THEDP, static_cast<QEvent*>(event) );
zorglub's avatar
zorglub committed
1069
1070
    return VLC_SUCCESS;
}
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101

/*****************************************************************************
 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
 *  We don't show the menu directly here because we don't want the
 *  caller to block for a too long time.
 *****************************************************************************/
static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
                        vlc_value_t old_val, vlc_value_t new_val, void *param )
{
    intf_thread_t *p_intf = (intf_thread_t *)param;

    if( p_intf->pf_show_dialog )
    {
        p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
                                new_val.b_bool, 0 );
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
 * IntfShowCB: callback triggered by the intf-show playlist variable.
 *****************************************************************************/
static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
                       vlc_value_t old_val, vlc_value_t new_val, void *param )
{
    intf_thread_t *p_intf = (intf_thread_t *)param;
    //p_intf->p_sys->b_intf_show = VLC_TRUE;

    return VLC_SUCCESS;
}