main_interface.cpp 31.9 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
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *
 * 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
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22
 *****************************************************************************/
zorglub's avatar
zorglub committed
23

24
#include "qt4.hpp"
zorglub's avatar
zorglub committed
25
#include "main_interface.hpp"
zorglub's avatar
zorglub committed
26
#include "input_manager.hpp"
27
#include "util/input_slider.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"

zorglub's avatar
zorglub committed
35
#include <QMenuBar>
zorglub's avatar
zorglub committed
36
#include <QCloseEvent>
zorglub's avatar
zorglub committed
37
#include <QPushButton>
zorglub's avatar
zorglub committed
38
#include <QStatusBar>
39
#include <QKeyEvent>
zorglub's avatar
zorglub committed
40
#include <QUrl>
41
#include <QSystemTrayIcon>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
42
43
#include <QSize>
#include <QMenu>
44
45

#include <assert.h>
46
#include <vlc_keys.h>
zorglub's avatar
zorglub committed
47
#include <vlc_vout.h>
zorglub's avatar
zorglub committed
48

zorglub's avatar
zorglub committed
49
#ifdef WIN32
zorglub's avatar
zorglub committed
50
    #define PREF_W 410
zorglub's avatar
zorglub committed
51
52
    #define PREF_H 121
#else
zorglub's avatar
zorglub committed
53
    #define PREF_W 450
zorglub's avatar
zorglub committed
54
55
    #define PREF_H 125
#endif
zorglub's avatar
zorglub committed
56

57
58
59
60
61
62
63
64
#define VISIBLE(i) (i && i->isVisible())

#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()

65
66
#define DEBUG_COLOR 0

67
68
69
70
71
/* 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
72
73
static int InteractCallback( vlc_object_t *, const char *, vlc_value_t,
                             vlc_value_t, void *);
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* 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
88

zorglub's avatar
zorglub committed
89
MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
zorglub's avatar
zorglub committed
90
{
91
    /* Variables initialisation */
92
    need_components_update = false;
93
    bgWidget = NULL; videoWidget = NULL; playlistWidget = NULL;
zorglub's avatar
zorglub committed
94
    embeddedPlaylistWasActive = videoIsActive = false;
95

96
    bool b_createSystray = false;
97
    input_name = "";
98

99
    /**
100
     *  Configuration and settings
101
102
103
104
     **/
    settings = new QSettings( "VideoLAN", "VLC" );
    settings->beginGroup( "MainWindow" );

105
106
107
    /* Main settings */
    setFocusPolicy( Qt::StrongFocus );
    setAcceptDrops(true);
108
109
110
    setWindowIcon( QApplication::windowIcon() );

    /* Set The Video In emebedded Mode or not */
zorglub's avatar
zorglub committed
111
    videoEmbeddedFlag = false;
112
113
    if( config_GetInt( p_intf, "embedded-video" ) )
        videoEmbeddedFlag = true;
zorglub's avatar
zorglub committed
114
115

    alwaysVideoFlag = false;
116
    if( videoEmbeddedFlag && config_GetInt( p_intf, "qt-always-video" ) )
zorglub's avatar
zorglub committed
117
118
        alwaysVideoFlag = true;

119
    /* Set the other interface settings */
120
    playlistEmbeddedFlag = settings->value("playlist-embedded", true).toBool();
zorglub's avatar
zorglub committed
121
    advControlsEnabled= settings->value( "adv-controls", false ).toBool();
122
    visualSelectorEnabled= settings->value( "visual-selector", false ).toBool();
zorglub's avatar
zorglub committed
123

124
125
126
127
128
129
130
131
132
#if DEBUG_COLOR
    QPalette palette2;
    palette2.setColor(this->backgroundRole(), Qt::magenta);
    setPalette(palette2);
#endif

    /**
     *  UI design
     **/
133
    setVLCWindowsTitle();
134
    handleMainUi( settings );
135
136

    /* Menu Bar */
zorglub's avatar
zorglub committed
137
    QVLCMenu::createMenuBar( this, p_intf, playlistEmbeddedFlag,
138
                             advControlsEnabled, visualSelectorEnabled );
139
140

    /* Status Bar */
141
142
143
    timeLabel = new QLabel;
    nameLabel = new QLabel;
    speedLabel = new QLabel( "1.0x" );
144
    timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
145
146
147
148
    speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
    statusBar()->addWidget( nameLabel, 8 );
    statusBar()->addPermanentWidget( speedLabel, 0 );
    statusBar()->addPermanentWidget( timeLabel, 2 );
149
150
151
152
153
154
    speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
    timeLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
    CONNECT( speedLabel, customContextMenuRequested( QPoint ),
             this, showSpeedMenu( QPoint ) );
    CONNECT( timeLabel, customContextMenuRequested( QPoint ),
             this, showTimeMenu( QPoint ) );
155
    /* Systray */
156
    sysTray = NULL;
157
    if( config_GetInt( p_intf, "qt-start-minimized") )
158
159
    {
        hide();
160
        b_createSystray = true;
161
    }
162
163
164
    if( config_GetInt( p_intf, "qt-system-tray") )
        b_createSystray = true;
    if (QSystemTrayIcon::isSystemTrayAvailable() && b_createSystray )
165
            createSystray();
166

167
168
169
170
    /* Init input manager */
    MainInputManager::getInstance( p_intf );
    ON_TIMEOUT( updateOnTimer() );

171
172
173
174
    /**
     * CONNECTs
     **/

175
176
    /* Volume control */
    CONNECT( ui.volumeSlider, valueChanged(int), this, updateVolume(int) );
177

178
179
180
181
182
    /* Connect the input manager to the GUI elements it manages */
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
             slider, setPosition( float,int, int ) );
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
             this, setDisplay( float, int, int ) );
183
184

    /* Naming in the controller */
185
186
    CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setName( QString ) );
187
    if( config_GetInt( p_intf, "qt-system-tray" ) && sysTray )
188
189
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
190
                 updateSystrayTooltipName( QString ) );
191
    }
192
193
194
195
196
197
198
    if( config_GetInt( p_intf, "qt-name-in-title" ) )
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setVLCWindowsTitle( QString ) );
    }

    /* PLAY_STATUS */
199
    CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
200
    CONNECT( THEMIM->getIM(), navigationChanged( int ),
201
             this, setNavigation(int) );
202
    if( config_GetInt( p_intf, "qt-system-tray" ) && sysTray )
203
204
    {
        CONNECT( THEMIM->getIM(), statusChanged( int ), this,
205
                 updateSystrayTooltipStatus( int ) );
206
    }
207
208
209
    CONNECT( slider, sliderDragged( float ),
             THEMIM->getIM(), sliderUpdate( float ) );

210
    /* Buttons */
211
212
213
214
215
216
217
    CONNECT( ui.prevSectionButton, clicked(), THEMIM->getIM(),
             sectionPrev() );
    CONNECT( ui.nextSectionButton, clicked(), THEMIM->getIM(),
             sectionNext() );
    CONNECT( ui.menuButton, clicked(), THEMIM->getIM(),
             sectionMenu() );

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

    /* Register callback for the intf-popupmenu variable */
226
227
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
228
229
230
231
232
233
    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 );
    }
234
235
236
237
}

MainInterface::~MainInterface()
{
238
    /* Unregister callback for the intf-popupmenu variable */
239
240
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
241
242
243
244
245
246
247
    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 );
    }

zorglub's avatar
zorglub committed
248
249
250
251
252
    settings->setValue( "playlist-embedded", playlistEmbeddedFlag );
    settings->setValue( "adv-controls", advControlsEnabled );
    settings->setValue( "pos", pos() );
    settings->endGroup();
    delete settings;
253
254
    p_intf->b_interaction = VLC_FALSE;
    var_DelCallback( p_intf, "interaction", InteractCallback, this );
255
256
257
258

    p_intf->pf_request_window = NULL;
    p_intf->pf_release_window = NULL;
    p_intf->pf_control_window = NULL;
259
260
}

261
262
263
/*****************************
 *   Main UI handling        *
 *****************************/
264
265
266
267
268

/**
 * Give the decorations of the Main Window a correct Name.
 * If nothing is given, set it to VLC...
 **/
269
270
271
272
void MainInterface::setVLCWindowsTitle( QString aTitle )
{
    if( aTitle.isEmpty() )
    {
273
        setWindowTitle( qtr( "VLC media player" ) );
274
275
276
    }
    else
    {
277
        setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
278
279
280
    }
}

281
282
283
void MainInterface::handleMainUi( QSettings *settings )
{
    QWidget *main = new QWidget( this );
284
    QVBoxLayout *mainLayout = new QVBoxLayout( main );
285
286
    setCentralWidget( main );

287
288
289
290
291
    /* Margins, spacing */
    main->setContentsMargins( 0, 0, 0, 0 );
    mainLayout->setMargin( 0 );

    /* CONTROLS */
292
    QWidget *controls = new QWidget;
293
294
295
    ui.setupUi( controls );

    /* Configure the UI */
zorglub's avatar
zorglub committed
296
    slider = new InputSlider( Qt::Horizontal, NULL );
297
    mainLayout->insertWidget( 0, slider );
298
    ui.discFrame->hide();
299

300
301
302
    BUTTON_SET_IMG( ui.prevSectionButton, "", previous.png, "" );
    BUTTON_SET_IMG( ui.nextSectionButton, "", next.png, "" );
    BUTTON_SET_IMG( ui.menuButton, "", previous.png, "" );
303

zorglub's avatar
zorglub committed
304
305
306
307
308
    BUTTON_SET_ACT_I( ui.prevButton, "" , previous.png,
                      qtr("Previous"), prev() );
    BUTTON_SET_ACT_I( ui.nextButton, "", next.png, qtr("Next"), next() );
    BUTTON_SET_ACT_I( ui.playButton, "", play.png, qtr("Play"), play() );
    BUTTON_SET_ACT_I( ui.stopButton, "", stop.png, qtr("Stop"), stop() );
309
310

    /* Volume */
311
    ui.volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-low.png" ) );
zorglub's avatar
zorglub committed
312
    ui.volumeSlider->setMaximum( 100 );
313
314
315
    ui.volMuteLabel->setToolTip( qtr( "Mute" ) );
    VolumeClickHandler *h = new VolumeClickHandler( p_intf, this );
    ui.volMuteLabel->installEventFilter(h);
zorglub's avatar
zorglub committed
316
317
    ui.volumeSlider->setFocusPolicy( Qt::NoFocus );

318
    BUTTON_SET_IMG( ui.playlistButton, "" , playlist_icon.png,
zorglub's avatar
zorglub committed
319
                        playlistEmbeddedFlag ?  qtr( "Show playlist" ) :
zorglub's avatar
Cleanup    
zorglub committed
320
                                                qtr( "Open playlist" ) );
321
    BUTTONACT( ui.playlistButton, playlist() );
zorglub's avatar
zorglub committed
322

323
324
325
326
327
328
329
330
331
#if DEBUG_COLOR
    QPalette palette;
    palette.setColor(main->backgroundRole(), Qt::green);
    main->setPalette(palette);
#endif

    /* Add the controls Widget */
    mainLayout->addWidget( controls );

zorglub's avatar
zorglub committed
332
    /* Set initial size */
zorglub's avatar
zorglub committed
333
    resize ( PREF_W, PREF_H );
334

335
    addSize = QSize( mainLayout->margin() * 2, PREF_H );
336

337
    /* advanced Controls handling */
zorglub's avatar
zorglub committed
338
    advControls = new ControlsWidget( p_intf );
339
    mainLayout->insertWidget( 0, advControls );
zorglub's avatar
zorglub committed
340
341
342
343
    advControls->updateGeometry();
    if( !advControlsEnabled ) advControls->hide();
    need_components_update = true;

344
    /* Visualisation */
345
    visualSelector = new VisualSelector( p_intf );
346
    mainLayout->insertWidget( 0, visualSelector );
347
348
    visualSelector->hide();

349
    /* And video Outputs */
350
    if( alwaysVideoFlag )
351
352
353
    {
        bgWidget = new BackgroundWidget( p_intf );
        bgWidget->widgetSize = settings->value( "backgroundSize",
354
                                           QSize( 300, 300 ) ).toSize();
355
356
        bgWidget->resize( bgWidget->widgetSize );
        bgWidget->updateGeometry();
357
        mainLayout->insertWidget( 0, bgWidget );
358
359
    }

360
    if( videoEmbeddedFlag )
361
    {
362
        videoWidget = new VideoWidget( p_intf );
363
        videoWidget->widgetSize = QSize( 1, 1 );
364
        //videoWidget->resize( videoWidget->widgetSize );
365
        mainLayout->insertWidget( 0, videoWidget );
366

367
368
369
        p_intf->pf_request_window  = ::DoRequest;
        p_intf->pf_release_window  = ::DoRelease;
        p_intf->pf_control_window  = ::DoControl;
370
    }
371
372

    /* Finish the sizing */
zorglub's avatar
zorglub committed
373
    setMinimumSize( PREF_W, addSize.height() );
zorglub's avatar
zorglub committed
374
375
}

376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
/**********************************************************************
 * Handling of the components
 **********************************************************************/
void MainInterface::calculateInterfaceSize()
{
    int width = 0, height = 0;
    if( VISIBLE( bgWidget ) )
    {
        width = bgWidget->widgetSize.width();
        height = bgWidget->widgetSize.height();
        assert( !(playlistWidget && playlistWidget->isVisible() ) );
    }
    else if( VISIBLE( playlistWidget ) )
    {
        width = playlistWidget->widgetSize.width();
        height = playlistWidget->widgetSize.height();
    }
    else if( videoIsActive )
    {
        width =  videoWidget->widgetSize.width() ;
        height = videoWidget->widgetSize.height();
    }
    else
    {
        width = PREF_W - addSize.width();
        height = PREF_H - addSize.height();
    }
    if( VISIBLE( visualSelector ) )
        height += visualSelector->height();
    if( VISIBLE( advControls) )
    {
        height += advControls->sizeHint().height();
    }
    mainSize = QSize( width + addSize.width(), height + addSize.height() );
}

void MainInterface::resizeEvent( QResizeEvent *e )
{
    videoWidget->widgetSize.setWidth(  e->size().width() - addSize.width() );
    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 ) )
    {
        SET_WH( playlistWidget , e->size().width() - addSize.width(),
                                 e->size().height() - addSize.height() );
        playlistWidget->updateGeometry();
    }
}
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
/****************************************************************************
 * Small right-click menus
 ****************************************************************************/
void MainInterface::showSpeedMenu( QPoint pos )
{
    QMenu menu( this );
    menu.addAction( "Not Implemented Yet" );
    menu.exec( QCursor::pos() );
}

void MainInterface::showTimeMenu( QPoint pos )
{
    QMenu menu( this );
    menu.addAction( "Not Implemented Yet" );
    menu.exec( QCursor::pos() );
}
444

445
446
447
448
/*****************************************************************************
 * Systray Icon and Systray Menu
 *****************************************************************************/

449
450
451
452
453
/**
 * Create a SystemTray icon and a menu that would go with it.
 * Connects to a click handler on the icon.
 **/
void MainInterface::createSystray()
454
{
455
    QIcon iconVLC =  QIcon( QPixmap( ":/vlc128.png" ) );
456
    sysTray = new QSystemTrayIcon( iconVLC, this );
457
458
    sysTray->setToolTip( qtr( "VLC media player" ));

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

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

465
466
    CONNECT( sysTray, activated(  QSystemTrayIcon::ActivationReason ),
            this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
467
468
}

469
470
471
/**
 * Update the menu of the Systray Icon.
 * May be unneedded, since it just calls QVLCMenu::update
472
 * FIXME !!!
473
 **/
474
475
476
477
478
void MainInterface::updateSystrayMenu( int status )
{
    QVLCMenu::updateSystrayMenu( this, p_intf ) ;
}

479
480
481
/**
 * Updates the Systray Icon's menu and toggle the main interface
 */
482
483
void MainInterface::toggleUpdateSystrayMenu()
{
484
485
486
    if( isHidden() )
    {
        show();
487
        activateWindow();
488
489
490
    }
    else
    {
491
492
493
494
495
496
497
498
499
500
501
502
#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
503
        if( isActiveWindow() )
504
#endif
505
506
507
508
509
510
511
512
        {
            hide();
        }
        else
        {
            activateWindow();
        }
    }
513
    QVLCMenu::updateSystrayMenu( this, p_intf );
514
515
}

516
517
void MainInterface::handleSystrayClick(
                                    QSystemTrayIcon::ActivationReason reason )
518
519
520
521
{
    switch( reason )
    {
        case QSystemTrayIcon::Trigger:
522
523
            toggleUpdateSystrayMenu();
            break;
524
525
        case QSystemTrayIcon::MiddleClick:
            sysTray->showMessage( qtr( "VLC media player" ),
526
                    qtr( "Control menu for the player" ),
527
528
529
530
531
                    QSystemTrayIcon::Information, 4000 );
            break;
    }
}

532
533
534
/**
 * Updates the name of the systray Icon tooltip.
 * Doesn't check if the systray exists, check before you call it.
535
 * FIXME !!! Fusion with next function ?
536
 **/
537
538
539
540
541
542
543
544
545
546
547
548
void MainInterface::updateSystrayTooltipName( QString name )
{
    if( name.isEmpty() )
    {
        sysTray->setToolTip( qtr( "VLC media player" ) );
    }
    else
    {
        sysTray->setToolTip( name );
    }
}

549
550
551
552
/**
 * Updates the status of the systray Icon tooltip.
 * Doesn't check if the systray exists, check before you call it.
 **/
553
554
555
void MainInterface::updateSystrayTooltipStatus( int i_status )
{
    switch( i_status )
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
    {
        case  0:
            {
                sysTray->setToolTip( qtr( "VLC media player" ) );
                break;
            }
        case PLAYING_S:
            {
                sysTray->setToolTip( input_name );
                //+ " - " + qtr( "Playing" ) );
                break;
            }
        case PAUSE_S:
            {
                sysTray->setToolTip( input_name + " - "
                        + qtr( "Paused") );
                break;
            }
    }
575
}
576
577
578
579
580
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 );
581
582
583
    if( ret )
    {
        videoIsActive = true;
584
        if( VISIBLE( playlistWidget ) )
585
586
        {
            embeddedPlaylistWasActive = true;
587
//            playlistWidget->hide();
588
        }
589
590
        bool bgWasVisible = false;
        if( VISIBLE( bgWidget) )
zorglub's avatar
zorglub committed
591
        {
592
            bgWasVisible = true;
593
            bgWidget->hide();
zorglub's avatar
zorglub committed
594
        }
595
596
597
598
599
600
601
602
603
604
605
        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 );
        }
606
//        videoWidget->updateGeometry(); /// FIXME: Needed ?
607
608
        need_components_update = true;
    }
609
610
611
612
613
614
    return ret;
}

void MainInterface::releaseVideo( void *p_win )
{
    videoWidget->release( p_win );
615
616
    videoWidget->widgetSize = QSize( 0, 0 );
    videoWidget->resize( videoWidget->widgetSize );
zorglub's avatar
zorglub committed
617

618
    if( embeddedPlaylistWasActive )
619
        playlistWidget->show();
zorglub's avatar
zorglub committed
620
    else if( bgWidget )
621
        bgWidget->show();
zorglub's avatar
zorglub committed
622

623
    videoIsActive = false;
624
    need_components_update = true;
625
626
}

627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
class SetVideoOnTopQtEvent : public QEvent
{
public:
    SetVideoOnTopQtEvent( bool _onTop ) :
      QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
    {
    }

    bool OnTop() const
    {
        return onTop;
    }

private:
    bool onTop;
};

644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
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 );
663
            // videoWidget->updateGeometry();
664
665
666
667
668
            need_components_update = true;
            i_ret = VLC_SUCCESS;
            break;
        }
        case VOUT_SET_STAY_ON_TOP:
669
670
671
672
673
674
        {
            int i_arg = va_arg( args, int );
            QApplication::postEvent( this, new SetVideoOnTopQtEvent( i_arg ) );
            i_ret = VLC_SUCCESS;
            break;
        }
675
676
677
678
679
680
681
        default:
            msg_Warn( p_intf, "unsupported control query" );
            break;
    }
    return i_ret;
}

zorglub's avatar
zorglub committed
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
void MainInterface::advanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        advControlsEnabled = true;
    }
    else
    {
        advControls->hide();
        advControlsEnabled = false;
    }
    doComponentsUpdate();
}

697
698
699
700
701
702
703
704
705
void MainInterface::visual()
{
    if( !VISIBLE( visualSelector) )
    {
        visualSelector->show();
        if( !THEMIM->getIM()->hasVideo() )
        {
            /* Show the background widget */
        }
706
        visualSelectorEnabled = true;
707
708
709
710
711
    }
    else
    {
        /* Stop any currently running visualization */
        visualSelector->hide();
712
        visualSelectorEnabled = false;
713
    }
714
    doComponentsUpdate();
715
716
}

717
718
719
720
721
722
723
void MainInterface::playlist()
{
    // Toggle the playlist dialog
    if( !playlistEmbeddedFlag )
    {
        if( playlistWidget )
        {
724
            /// \todo Destroy it
725
726
727
728
729
730
731
732
733
734
735
        }
        THEDP->playlistDialog();
        return;
    }

    if( !playlistWidget )
    {
        PlaylistDialog::killInstance();
        playlistWidget = new PlaylistWidget( p_intf );
        ui.vboxLayout->insertWidget( 0, playlistWidget );
        playlistWidget->widgetSize = settings->value( "playlistSize",
zorglub's avatar
zorglub committed
736
                                               QSize( 650, 310 ) ).toSize();
737
        playlistWidget->hide();
738
739
        if(bgWidget)
        CONNECT( playlistWidget, artSet( QString ), bgWidget, setArt(QString) );
740
    }
741
    if( VISIBLE( playlistWidget ) )
742
743
    {
        playlistWidget->hide();
744
        if( bgWidget ) bgWidget->show();
745
746
        if( videoIsActive )
        {
747
748
749
            videoWidget->widgetSize = savedVideoSize;
            videoWidget->resize( videoWidget->widgetSize );
            videoWidget->updateGeometry();
750
            if( bgWidget ) bgWidget->hide();
751
752
753
754
755
756
        }
    }
    else
    {
        playlistWidget->show();
        if( videoIsActive )
757
758
759
760
761
762
        {
            savedVideoSize = videoWidget->widgetSize;
            videoWidget->widgetSize.setHeight( 0 );
            videoWidget->resize( videoWidget->widgetSize );
            videoWidget->updateGeometry();
        }
763
        if( VISIBLE( bgWidget ) ) bgWidget->hide();
764
    }
765
    doComponentsUpdate();
766
767
}

zorglub's avatar
zorglub committed
768
769
/* Video widget cannot do this synchronously as it runs in another thread */
/* Well, could it, actually ? Probably dangerous ... */
770
771
void MainInterface::doComponentsUpdate()
{
772
773
    calculateInterfaceSize();
    resize( mainSize );
774
775
}

zorglub's avatar
zorglub committed
776
void MainInterface::undockPlaylist()
777
{
zorglub's avatar
zorglub committed
778
    if( playlistWidget )
779
    {
zorglub's avatar
zorglub committed
780
781
        playlistWidget->hide();
        playlistWidget->deleteLater();
782
783
784
        ui.vboxLayout->removeWidget( playlistWidget );
        playlistWidget = NULL;
        playlistEmbeddedFlag = false;
zorglub's avatar
zorglub committed
785

zorglub's avatar
zorglub committed
786
        menuBar()->clear();
787
788
        QVLCMenu::createMenuBar( this, p_intf, false, advControlsEnabled,
                                 visualSelectorEnabled);
zorglub's avatar
zorglub committed
789
790
791
792
793
794
795
796
797
798

        if( videoIsActive )
        {
            videoWidget->widgetSize = savedVideoSize;
            videoWidget->resize( videoWidget->widgetSize );
            videoWidget->updateGeometry();
        }

        doComponentsUpdate();
        THEDP->playlistDialog();
799
    }
zorglub's avatar
zorglub committed
800
801
}

802
803
804
805
806
807
808
void MainInterface::toggleMenus()
{
    if( menuBar()->isVisible() ) menuBar()->hide();
        else menuBar()->show();
    msg_Dbg( p_intf, "I was there: \\_o<~~ coin coin" );
}

zorglub's avatar
zorglub committed
809
810
811
void MainInterface::customEvent( QEvent *event )
{
    if( event->type() == PLDockEvent_Type )
812
813
814
    {
        PlaylistDialog::killInstance();
        playlistEmbeddedFlag = true;
zorglub's avatar
zorglub committed
815
        menuBar()->clear();
816
817
        QVLCMenu::createMenuBar(this, p_intf, true, advControlsEnabled,
                                visualSelectorEnabled);
818
819
        playlist();
    }
820
821
822
823
824
825
    else if ( event->type() == SetVideoOnTopEvent_Type )
    {
        SetVideoOnTopQtEvent* p_event = (SetVideoOnTopQtEvent*)event;
        if( p_event->OnTop() )
            setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
        else
826
            setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
827
828
        show(); /* necessary to apply window flags?? */
    }
829
830
}

831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856

/************************************************************************
 * D&D
 ************************************************************************/
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 ) {
857
858
            playlist_Add( THEPL, qtu(s), NULL,
                          PLAYLIST_APPEND | (first ? PLAYLIST_GO:0),
859
                          PLAYLIST_END, VLC_TRUE, VLC_FALSE );
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
            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();
}

878
879
880
/************************************************************************
 * Other stuff
 ************************************************************************/
881
882
void MainInterface::keyPressEvent( QKeyEvent *e )
{
883
    int i_vlck = qtEventToVLCKey( e );
884
885
    if( i_vlck >= 0 )
    {
886
        var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
887
888
889
890
891
892
        e->accept();
    }
    else
        e->ignore();
}

893
894
void MainInterface::wheelEvent( QWheelEvent *e )
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
895
    int i_vlckey = qtWheelEventToVLCKey( e );
896
897
898
899
    var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
    e->accept();
}

zorglub's avatar
zorglub committed
900
901
void MainInterface::stop()
{
902
    THEMIM->stop();
zorglub's avatar
zorglub committed
903
}
904

zorglub's avatar
zorglub committed
905
906
void MainInterface::play()
{
zorglub's avatar
zorglub committed
907
    if( playlist_IsEmpty(THEPL) )
908
909
    {
        /* The playlist is empty, open a file requester */
zorglub's avatar
Wtf ?    
zorglub committed
910
        THEDP->openFileDialog();
911
912
913
914
        setStatus( 0 );
        return;
    }
    THEMIM->togglePlayPause();
zorglub's avatar
zorglub committed
915
}
916

zorglub's avatar
zorglub committed
917
918
void MainInterface::prev()
{
919
    THEMIM->prev();
zorglub's avatar
zorglub committed
920
}
921

zorglub's avatar
zorglub committed
922
923
void MainInterface::next()
{
924
    THEMIM->next();
zorglub's avatar
zorglub committed
925
926
927
928
929
930
931
932
933
}

void MainInterface::setDisplay( float pos, int time, int length )
{
    char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
    secstotimestr( psz_length, length );
    secstotimestr( psz_time, time );
    QString title;
    title.sprintf( "%s/%s", psz_time, psz_length );
934
    timeLabel->setText( " "+title+" " );
zorglub's avatar
zorglub committed
935
936
937
938
}

void MainInterface::setName( QString name )
{
939
    input_name = name;
940
    nameLabel->setText( " " + name+" " );
zorglub's avatar
zorglub committed
941
942
}

943
944
void MainInterface::setStatus( int status )
{
zorglub's avatar
zorglub committed
945
    if( status == 1 ) // Playing
946
947
948
        ui.playButton->setIcon( QIcon( ":/pixmaps/pause.png" ) );
    else
        ui.playButton->setIcon( QIcon( ":/pixmaps/play.png" ) );
949
950
    if( systrayMenu )
        updateSystrayMenu( status );
951
952
}

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
#define HELP_MENU N_("Menu")
#define HELP_PCH N_("Previous chapter")
#define HELP_NCH N_("Next chapter")
#define HELP_PTR N_("Previous track")
#define HELP_NTR N_("Next track")

void MainInterface::setNavigation( int navigation )
{
    // 1 = chapter, 2 = title, 0 = no
    if( navigation == 0 )
    {
        ui.discFrame->hide();
    } else if( navigation == 1 ) {
        ui.prevSectionButton->show();
        ui.prevSectionButton->setToolTip( qfu(HELP_PCH) );
        ui.nextSectionButton->show();
        ui.nextSectionButton->setToolTip( qfu(HELP_NCH) );
        ui.menuButton->show();
        ui.discFrame->show();
    } else {
        ui.prevSectionButton->show();
        ui.prevSectionButton->setToolTip( qfu(HELP_PCH) );
        ui.nextSectionButton->show();
        ui.nextSectionButton->setToolTip( qfu(HELP_NCH) );
        ui.menuButton->hide();
        ui.discFrame->show();
    }
}

zorglub's avatar
zorglub committed
982
983
static bool b_my_volume;

zorglub's avatar
zorglub committed
984
985
void MainInterface::updateOnTimer()
{
986
    /* \todo Make this event-driven */
zorglub's avatar
zorglub committed
987
988
989
    advControls->enableInput( THEMIM->getIM()->hasInput() );
    advControls->enableVideo( THEMIM->getIM()->hasVideo() );

990
    if( intf_ShouldDie( p_intf ) )
zorglub's avatar
zorglub committed
991
    {
zorglub's avatar
zorglub committed
992
        QApplication::closeAllWindows();
zorglub's avatar
zorglub committed
993
994
        QApplication::quit();
    }
995
996
997
998
999
1000
    if( need_components_update )
    {
        doComponentsUpdate();
        need_components_update = false;
    }

zorglub's avatar
zorglub committed
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
    i_volume = (i_volume *  200 )/ AOUT_VOLUME_MAX ;
    int i_gauge = ui.volumeSlider->value();
    b_my_volume = false;
    if( i_volume - i_gauge > 1 || i_gauge - i_volume > 1 )
    {
        b_my_volume = true;
        ui.volumeSlider->setValue( i_volume );
        b_my_volume = false;
    }
zorglub's avatar
zorglub committed
1012
1013
1014
1015
1016
}

void MainInterface::closeEvent( QCloseEvent *e )
{
    hide();
1017
    vlc_object_kill( p_intf );
zorglub's avatar
zorglub committed
1018
}
zorglub's avatar
zorglub committed
1019

zorglub's avatar
zorglub committed
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
void MainInterface::updateVolume( int sliderVolume )
{
    if( !b_my_volume )
    {
        int i_res = sliderVolume * AOUT_VOLUME_MAX /
                            (2*ui.volumeSlider->maximum() );
        aout_VolumeSet( p_intf, i_res );
    }
}

zorglub's avatar
zorglub committed
1030
1031
1032
1033
1034
1035
1036
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 );
1037
    QApplication::postEvent( THEDP, static_cast<QEvent*>(event) );
zorglub's avatar
zorglub committed
1038
1039
    return VLC_SUCCESS;
}
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070

/*****************************************************************************
 * 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;
}