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