main_interface.cpp 34.4 KB
Newer Older
zorglub's avatar
zorglub committed
1
/*****************************************************************************
zorglub's avatar
Wtf ?  
zorglub committed
2
 * main_interface.cpp : Main interface
zorglub's avatar
zorglub committed
3
 ****************************************************************************
4
 * Copyright (C) 2006-2007 the VideoLAN team
5
 * $Id$
zorglub's avatar
zorglub committed
6 7
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 *          Jean-Baptiste Kempf <jb@videolan.org>
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
#include "dialogs/extended.hpp"
33 34 35
#include "dialogs/playlist.hpp"
#include "menus.hpp"

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

56 57 58 59 60 61
#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()

62 63 64 65 66
/* 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
67 68
static int InteractCallback( vlc_object_t *, const char *, vlc_value_t,
                             vlc_value_t, void *);
69 70 71 72 73 74 75 76 77 78 79 80 81 82
/* 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
83

zorglub's avatar
zorglub committed
84
MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
zorglub's avatar
zorglub committed
85
{
86
    /* Variables initialisation */
87
    need_components_update = false;
88
    bgWidget = NULL; videoWidget = NULL; playlistWidget = NULL;
zorglub's avatar
zorglub committed
89
    embeddedPlaylistWasActive = videoIsActive = false;
90
    input_name = "";
91

92 93
    /**
     * Ask for the network policy on FIRST STARTUP
94
     **/
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
    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 );
    }

111
    /**
112
     *  Configuration and settings
113
     **/
114
    settings = new QSettings( "vlc", "vlc-qt-interface" );
115 116
    settings->beginGroup( "MainWindow" );

117 118
    /* Main settings */
    setFocusPolicy( Qt::StrongFocus );
119
    setAcceptDrops( true );
120
    setWindowIcon( QApplication::windowIcon() );
121
    setWindowOpacity( config_GetFloat( p_intf, "qt-opacity" ) );
122 123

    /* Set The Video In emebedded Mode or not */
zorglub's avatar
zorglub committed
124
    videoEmbeddedFlag = false;
125 126
    if( config_GetInt( p_intf, "embedded-video" ) )
        videoEmbeddedFlag = true;
zorglub's avatar
zorglub committed
127 128

    alwaysVideoFlag = false;
129
    if( videoEmbeddedFlag && config_GetInt( p_intf, "qt-always-video" ) )
zorglub's avatar
zorglub committed
130 131
        alwaysVideoFlag = true;

132
    /* Set the other interface settings */
133 134 135
    visualSelectorEnabled = settings->value( "visual-selector", false ).toBool();
    notificationEnabled = config_GetInt( p_intf, "qt-notification" )
                          ? true : false;
136

137 138 139
    /**************************
     *  UI and Widgets design
     **************************/
140
    setVLCWindowsTitle();
141
    handleMainUi( settings );
142

143
    /* Create a Dock to get the playlist */
144
    dockPL = new QDockWidget( qtr("Playlist"), this );
145 146
    dockPL->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding );
    dockPL->setFeatures( QDockWidget::AllDockWidgetFeatures );
147 148 149
    dockPL->setAllowedAreas( Qt::LeftDockWidgetArea
                           | Qt::RightDockWidgetArea
                           | Qt::BottomDockWidgetArea );
150

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

156 157 158 159 160
    /****************
     *  Status Bar  *
     ****************/

    /* Widgets Creation*/
161
    b_remainingTime = false;
162
    timeLabel = new TimeLabel;
163
    nameLabel = new QLabel;
164 165
    nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
                                      | Qt::TextSelectableByKeyboard );
166
    speedLabel = new QLabel( "1.00x" );
167 168 169
    speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );

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

    /* and adding those */
175 176 177
    statusBar()->addWidget( nameLabel, 8 );
    statusBar()->addPermanentWidget( speedLabel, 0 );
    statusBar()->addPermanentWidget( timeLabel, 2 );
178 179 180 181 182

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

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

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

    if( b_systrayAvailable && b_createSystray )
211
            createSystray();
212

213
    if( config_GetInt( p_intf, "qt-minimal-view" ) )
214
        toggleMinimalView();
215

216 217 218
    /* Init input manager */
    MainInputManager::getInstance( p_intf );
    ON_TIMEOUT( updateOnTimer() );
219
    //ON_TIMEOUT( debug() );
220 221 222 223

    /********************
     * Various CONNECTs *
     ********************/
224

225
    /* Connect the input manager to the GUI elements it manages */
226
    /* It is also connected to the control->slider, see the ControlsWidget */
227
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
228
             this, setDisplayPosition( float, int, int ) );
229

230
    CONNECT( THEMIM->getIM(), rateChanged( int ), this, setRate( int ) );
231

232 233 234
    /**
     * Connects on nameChanged()
     */
235
    /* Naming in the controller statusbar */
236 237
    CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setName( QString ) );
238
    /* and in the systray */
239
    if( sysTray )
240 241
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
242
                 updateSystrayTooltipName( QString ) );
243
    }
244
    /* and in the title of the controller */
245 246 247 248 249 250
    if( config_GetInt( p_intf, "qt-name-in-title" ) )
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setVLCWindowsTitle( QString ) );
    }

251 252
    /** CONNECTS on PLAY_STATUS **/
    /* Status on the main controller */
253
    CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
254
    /* and in the systray */
255
    if( sysTray )
256 257
    {
        CONNECT( THEMIM->getIM(), statusChanged( int ), this,
258
                 updateSystrayTooltipStatus( int ) );
259
    }
260

261 262 263
    /**
     * Callbacks
     **/
264 265 266
    var_Create( p_intf, "interaction", VLC_VAR_ADDRESS );
    var_AddCallback( p_intf, "interaction", InteractCallback, this );
    p_intf->b_interaction = VLC_TRUE;
267 268

    /* Register callback for the intf-popupmenu variable */
269 270
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
271 272 273 274 275 276
    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 );
    }
277 278 279

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

280
    CONNECT( dockPL, topLevelChanged( bool ), this, doComponentsUpdate() );
281 282
    // DEBUG FIXME
    hide();
283 284


285
    updateGeometry();
286
    settings->endGroup();
287 288 289 290
}

MainInterface::~MainInterface()
{
291 292 293 294
    if( playlistWidget ) playlistWidget->savingSettings( settings );
    if( ExtendedDialog::exists() ) 
        ExtendedDialog::getInstance( p_intf )->savingSettings();
    
295 296 297 298 299 300 301 302
    settings->beginGroup( "MainWindow" );
    settings->setValue( "playlist-floats", dockPL->isFloating() );
    settings->setValue( "adv-controls", getControlsVisibilityStatus() & CONTROLS_ADVANCED );
    settings->setValue( "pos", pos() );

    settings->endGroup();
    delete settings;

303
    /* Unregister callback for the intf-popupmenu variable */
304 305
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
306 307 308 309 310 311
    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 );
    }
312
    
313 314
    p_intf->b_interaction = VLC_FALSE;
    var_DelCallback( p_intf, "interaction", InteractCallback, this );
315 316 317 318

    p_intf->pf_request_window = NULL;
    p_intf->pf_release_window = NULL;
    p_intf->pf_control_window = NULL;
319 320
}

321 322 323
/*****************************
 *   Main UI handling        *
 *****************************/
324 325 326 327 328

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

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

348 349 350 351
    /* Margins, spacing */
    main->setContentsMargins( 0, 0, 0, 0 );
    mainLayout->setMargin( 0 );

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

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

362
    /* Add the controls Widget to the main Widget */
363 364
    mainLayout->addWidget( controls );

365 366 367 368 369 370
    /* 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 );
371

372
    /* Visualisation */
373 374
    /* Disabled for now, they SUCK */
    #if 0
375
    visualSelector = new VisualSelector( p_intf );
376
    mainLayout->insertWidget( 0, visualSelector );
377
    visualSelector->hide();
378
    #endif
379

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

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

399 400 401
        p_intf->pf_request_window  = ::DoRequest;
        p_intf->pf_release_window  = ::DoRelease;
        p_intf->pf_control_window  = ::DoControl;
402
    }
403 404

    /* Finish the sizing */
405
    updateGeometry();
zorglub's avatar
zorglub committed
406 407
}

408 409 410 411 412 413 414 415 416 417 418
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(
419 420
        "<p>The <i>VideoLAN Team</i> doesn't like when an application goes "
        "online without authorisation.</p>\n "
421 422 423
        "<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"
424 425
        "<p><i>VLC media player</i> <b>DOES NOT</b> send or collect <b>ANY</b> "
        "information, even anonymously about your "
426
        "usage.</p>\n"
427 428
        "<p>Therefore please check the following options, the default being "
        "almost no access on the web.</p>\n") );
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
    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 );  \
449
        controls.append( control );                               \
450 451 452 453 454 455 456 457
    }

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

    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();
}

473
//FIXME remove me at the end... 
474 475 476 477 478
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() );
}
479

480
/**********************************************************************
481
 * Handling of sizing of the components
482
 **********************************************************************/
483 484 485 486 487 488 489 490 491

/* This function is probably wrong, but we don't have many many choices...
   Since we can't know from the playlist Widget if we are inside a dock or not,
   because the playlist Widget can be called by THEDP, as a separate windows for
   the skins.
   Maybe the other solution is to redefine the sizeHint() of the playlist and 
   ask _parent->isFloating()... 
   If you think this would be better, please FIX it...
*/
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
QSize MainInterface::sizeHint() const
{
    QSize tempSize = controls->sizeHint() +
        QSize( 100, menuBar()->size().height() + statusBar()->size().height() );

    if( VISIBLE( bgWidget ) )
        tempSize += bgWidget->sizeHint();
    else if( videoIsActive )
        tempSize += videoWidget->size();

    if( !dockPL->isFloating() && dockPL->widget() )
        tempSize += dockPL->widget()->size();

    return tempSize;
}

508
#if 0
509
/* This is dead code and need to be removed AT THE END */
510 511
void MainInterface::resizeEvent( QResizeEvent *e )
{
512 513
    if( videoWidget )
        videoWidget->widgetSize.setWidth( e->size().width() - addSize.width() );
514 515 516 517 518 519 520 521
    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 ) )
    {
522 523 524
        //FIXME
//        SET_WH( playlistWidget , e->size().width() - addSize.width(),
              //                   e->size().height() - addSize.height() );
525 526 527
        playlistWidget->updateGeometry();
    }
}
528
#endif
529

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

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

    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
        bool bgWasVisible = false;
567

568
        /* Did we have a bg ? */
569
        if( VISIBLE( bgWidget) )
zorglub's avatar
zorglub committed
570
        {
571
            bgWasVisible = true;
572
            emit askBgWidgetToToggle();
zorglub's avatar
zorglub committed
573
        }
574

575 576 577 578 579 580 581 582 583 584 585
        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 );
        }
586
        videoWidget->updateGeometry(); // Needed for deinterlace
587
        updateGeometry();
588
    }
589 590 591 592
    return ret;
}

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

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

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

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

609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
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 );
628
            videoWidget->updateGeometry();
629
            updateGeometry();
630 631 632 633
            i_ret = VLC_SUCCESS;
            break;
        }
        case VOUT_SET_STAY_ON_TOP:
634 635 636 637 638 639
        {
            int i_arg = va_arg( args, int );
            QApplication::postEvent( this, new SetVideoOnTopQtEvent( i_arg ) );
            i_ret = VLC_SUCCESS;
            break;
        }
640 641 642 643 644 645 646
        default:
            msg_Warn( p_intf, "unsupported control query" );
            break;
    }
    return i_ret;
}

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

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

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

        /* Make the playlist floating is requested. Default is not. */
672
        if( settings->value( "playlist-floats", false ).toBool() );
673 674
        {
            msg_Dbg( p_intf, "we don't want it inside");
675
            dockPL->setFloating( true );
676 677 678 679
        }
    }
    else
    {
680
    /* toggle the visibility of the playlist */
681
       TOGGLEV( dockPL );
682
     //resize(sizeHint());
683
    }
684
#if 0
685
    doComponentsUpdate();
686 687
#endif
    updateGeometry();
688 689
}

690
/* Function called from the menu to undock the playlist */
zorglub's avatar
zorglub committed
691
void MainInterface::undockPlaylist()
692
{
693
    dockPL->setFloating( true );
694
    updateGeometry();
zorglub's avatar
zorglub committed
695 696
}

697
void MainInterface::toggleMinimalView()
698
{
699
    TOGGLEV( menuBar() );
700 701
    TOGGLEV( controls );
    TOGGLEV( statusBar() );
702
    updateGeometry();
703 704
}

705 706 707
/* Video widget cannot do this synchronously as it runs in another thread */
/* Well, could it, actually ? Probably dangerous ... */
void MainInterface::doComponentsUpdate()
zorglub's avatar
zorglub committed
708
{
709
    updateGeometry();
710
}
711

712
/* toggling advanced controls buttons */
713 714 715 716 717
void MainInterface::toggleAdvanced()
{
    controls->toggleAdvanced();
}

718
/* Get the visibility status of the controls (hidden or not, advanced or not) */
719
int MainInterface::getControlsVisibilityStatus()
720
{
721 722
    return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
                + CONTROLS_ADVANCED * controls->b_advancedVisible );
723 724
}

725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
#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

747 748 749
/************************************************************************
 * Other stuff
 ************************************************************************/
750
void MainInterface::setDisplayPosition( float pos, int time, int length )
751 752 753
{
    char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
    secstotimestr( psz_length, length );
754 755
    secstotimestr( psz_time, ( b_remainingTime && length ) ? length - time
                                                           : time );
756

757 758 759 760
    QString title;
    title.sprintf( "%s/%s", psz_time,
                            ( !length && time ) ? "--:--" : psz_length );

761
    /* Add a minus to remaining time*/
762
    if( b_remainingTime && length ) timeLabel->setText( " -"+title+" " );
763
    else timeLabel->setText( " "+title+" " );
764 765
}

766
void MainInterface::toggleTimeDisplay()
767 768 769 770
{
    b_remainingTime = ( b_remainingTime ? false : true );
}

771 772
void MainInterface::setName( QString name )
{
773 774 775 776 777
    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 +" " );
778 779 780 781
}

void MainInterface::setStatus( int status )
{
782
    /* Forward the status to the controls to toggle Play/Pause */
783
    controls->setStatus( status );
784
    /* And in the systray for the menu */
785
    if( sysTray )
786
        QVLCMenu::updateSystrayMenu( this, p_intf );
787 788
}

789 790 791
void MainInterface::setRate( int rate )
{
    QString str;
792
    str.setNum( ( 1000 / (double)rate), 'f', 2 );
793 794
    str.append( "x" );
    speedLabel->setText( str );
795
    speedControl->updateControls( rate );
796 797
}

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

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

837
    CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
838 839 840 841 842 843 844 845 846 847 848 849 850
            this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
}

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

883 884 885 886 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
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 );
912
        if( notificationEnabled && ( isHidden() || isMinimized() ) )
913 914 915 916
        {
            sysTray->showMessage( qtr( "VLC media player" ), name,
                    QSystemTrayIcon::NoIcon, 4000 );
        }