main_interface.cpp 32.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"

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
#include <QLabel>
45 46
#include <QSlider>
#include <QWidgetAction>
47 48
#include <QDockWidget>
#include <QToolBar>
49 50

#include <assert.h>
51
#include <vlc_keys.h>
zorglub's avatar
zorglub committed
52
#include <vlc_vout.h>
zorglub's avatar
zorglub committed
53

zorglub's avatar
zorglub committed
54
#ifdef WIN32
zorglub's avatar
zorglub committed
55
    #define PREF_W 410
56
    #define PREF_H 151
zorglub's avatar
zorglub committed
57
#else
58 59
    #define PREF_W 400
    #define PREF_H 140
zorglub's avatar
zorglub committed
60
#endif
zorglub's avatar
zorglub committed
61

62 63 64 65 66 67
#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()

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

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

98
    /**
99
     *  Configuration and settings
100
     **/
101
    settings = new QSettings( "vlc", "vlc-qt-interface" );
102 103
    settings->beginGroup( "MainWindow" );

104 105 106
    /* Main settings */
    setFocusPolicy( Qt::StrongFocus );
    setAcceptDrops(true);
107
    setWindowIcon( QApplication::windowIcon() );
108
    setWindowOpacity( config_GetFloat( p_intf, "qt-opacity" ) );
109 110

    /* 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 121 122
    visualSelectorEnabled = settings->value( "visual-selector", false ).toBool();
    notificationEnabled = config_GetInt( p_intf, "qt-notification" )
                          ? true : false;
123 124 125
    /**************************
     *  UI and Widgets design
     **************************/
126
    setVLCWindowsTitle();
127
    handleMainUi( settings );
128

129 130 131 132 133 134
    /* Create a Dock to get the playlist */
    dockPL = new QDockWidget( qtr("Playlist"), this );
    dockPL->setAllowedAreas( Qt::LeftDockWidgetArea
                           | Qt::RightDockWidgetArea
                           | Qt::BottomDockWidgetArea );
    dockPL->setFeatures( QDockWidget::AllDockWidgetFeatures );
135

136
    /* Menu Bar */
137
    QVLCMenu::createMenuBar( this, p_intf, visualSelectorEnabled );
138

139 140 141 142 143
    /****************
     *  Status Bar  *
     ****************/

    /* Widgets Creation*/
144
    b_remainingTime = false;
145
    timeLabel = new TimeLabel;
146
    nameLabel = new QLabel;
147
    speedLabel = new QLabel( "1.00x" );
148 149 150 151
    speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
    timeLabel->setContextMenuPolicy ( Qt::CustomContextMenu );

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

    /* and adding those */
157 158 159
    statusBar()->addWidget( nameLabel, 8 );
    statusBar()->addPermanentWidget( speedLabel, 0 );
    statusBar()->addPermanentWidget( timeLabel, 2 );
160 161 162 163 164

    /* timeLabel behaviour:
       - double clicking opens the goto time dialog 
       - right-clicking and clicking just toggle between remaining and
         elapsed time.*/
165
    CONNECT( timeLabel, timeLabelClicked(), this, toggleTimeDisplay() );
166 167
    CONNECT( timeLabel, customContextMenuRequested( QPoint ),
             this, toggleTimeDisplay() );
168
    CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
169 170 171

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

175 176 177
    /**********************
     * Systray Management *
     **********************/
178
    sysTray = NULL;
179 180
    bool b_createSystray = false;
    bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
181
    if( config_GetInt( p_intf, "qt-start-minimized") )
182
    {
183 184
        if( b_systrayAvailable ){
            b_createSystray = true;
185
            hide(); //FIXME BUG HERE
186 187 188
        }
        else msg_Warn( p_intf, "You can't minize if you haven't a system "
                "tray bar" );
189
    }
190 191
    if( config_GetInt( p_intf, "qt-system-tray") )
        b_createSystray = true;
192 193

    if( b_systrayAvailable && b_createSystray )
194
            createSystray();
195

196 197 198
    if( config_GetInt( p_intf, "qt-minimal-view" ) )
        toggleMenus();

199 200 201
    /* Init input manager */
    MainInputManager::getInstance( p_intf );
    ON_TIMEOUT( updateOnTimer() );
202
    ON_TIMEOUT( debug() );
203

204 205 206 207

    /********************
     * Various CONNECTs *
     ********************/
208

209
    /* Connect the input manager to the GUI elements it manages */
210
    /* It is also connected to the control->slider, see the ControlsWidget */
211
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
212
             this, setDisplayPosition( float, int, int ) );
213

214
    CONNECT( THEMIM->getIM(), rateChanged( int ), this, setRate( int ) );
215

216 217 218
    /**
     * Connects on nameChanged()
     */
219
    /* Naming in the controller statusbar */
220 221
    CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setName( QString ) );
222
    /* and in the systray */
223
    if( sysTray )
224 225
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
226
                 updateSystrayTooltipName( QString ) );
227
    }
228
    /* and in the title of the controller */
229 230 231 232 233 234
    if( config_GetInt( p_intf, "qt-name-in-title" ) )
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setVLCWindowsTitle( QString ) );
    }

235 236
    /** CONNECTS on PLAY_STATUS **/
    /* Status on the main controller */
237
    CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
238
    /* and in the systray */
239
    if( sysTray )
240 241
    {
        CONNECT( THEMIM->getIM(), statusChanged( int ), this,
242
                 updateSystrayTooltipStatus( int ) );
243
    }
244

245 246 247
    /**
     * Callbacks
     **/
248 249 250
    var_Create( p_intf, "interaction", VLC_VAR_ADDRESS );
    var_AddCallback( p_intf, "interaction", InteractCallback, this );
    p_intf->b_interaction = VLC_TRUE;
251 252

    /* Register callback for the intf-popupmenu variable */
253 254
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
255 256 257 258 259 260
    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 );
    }
261 262
    // DEBUG FIXME
    hide();
263 264 265 266
}

MainInterface::~MainInterface()
{
267
    /* Unregister callback for the intf-popupmenu variable */
268 269
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
270 271 272 273 274 275 276
    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 );
    }

277 278
    settings->setValue( "playlist-embedded", !dockPL->isFloating() );
    settings->setValue( "adv-controls", getControlsVisibilityStatus() & CONTROLS_ADVANCED );
zorglub's avatar
zorglub committed
279 280 281
    settings->setValue( "pos", pos() );
    settings->endGroup();
    delete settings;
282 283
    p_intf->b_interaction = VLC_FALSE;
    var_DelCallback( p_intf, "interaction", InteractCallback, this );
284 285 286 287

    p_intf->pf_request_window = NULL;
    p_intf->pf_release_window = NULL;
    p_intf->pf_control_window = NULL;
288 289
}

290 291 292
/*****************************
 *   Main UI handling        *
 *****************************/
293 294 295 296 297

/**
 * Give the decorations of the Main Window a correct Name.
 * If nothing is given, set it to VLC...
 **/
298 299 300 301
void MainInterface::setVLCWindowsTitle( QString aTitle )
{
    if( aTitle.isEmpty() )
    {
302
        setWindowTitle( qtr( "VLC media player" ) );
303 304 305
    }
    else
    {
306
        setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
307 308 309
    }
}

310

311 312
void MainInterface::handleMainUi( QSettings *settings )
{
313
    /* Create the main Widget and the mainLayout */
314
    QWidget *main = new QWidget( this );
315
    mainLayout = new QVBoxLayout( main );
316 317
    setCentralWidget( main );

318 319 320 321
    /* Margins, spacing */
    main->setContentsMargins( 0, 0, 0, 0 );
    mainLayout->setMargin( 0 );

322 323 324
    /* Create the CONTROLS Widget */
    controls = new ControlsWidget( p_intf,
                   settings->value( "adv-controls", false ).toBool() );
325

326 327
    /* Configure the Controls, the playlist button doesn't trigger THEDP
       but the toggle from this MainInterface */
328
    BUTTONACT( controls->playlistButton, togglePlaylist() );
329

330
    /* Add the controls Widget to the main Widget */
331 332
    mainLayout->addWidget( controls );

333 334 335 336 337 338
    /* 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 );
339

340 341
    /* Set initial size */
    resize( PREF_W, PREF_H );
342
    addSize = QSize( mainLayout->margin() * 2, PREF_H );
343

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
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() );
}
381
/**********************************************************************
382
 * Handling of sizing of the components
383 384 385 386 387 388 389 390
 **********************************************************************/
void MainInterface::calculateInterfaceSize()
{
    int width = 0, height = 0;
    if( VISIBLE( bgWidget ) )
    {
        width = bgWidget->widgetSize.width();
        height = bgWidget->widgetSize.height();
391
//        assert( !(playlistWidget));// && playlistWidget->isVisible() ) );
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
    }
    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();
410
/*    if( VISIBLE( advControls) )
411 412
    {
        height += advControls->sizeHint().height();
413
    }*/
414 415 416 417 418
    mainSize = QSize( width + addSize.width(), height + addSize.height() );
}

void MainInterface::resizeEvent( QResizeEvent *e )
{
419 420
    if( videoWidget )
        videoWidget->widgetSize.setWidth( e->size().width() - addSize.width() );
421 422 423 424 425 426 427 428 429 430 431 432 433
    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();
    }
}
434

435 436 437 438 439
/****************************************************************************
 * Small right-click menus
 ****************************************************************************/
void MainInterface::showSpeedMenu( QPoint pos )
{
440
    speedControlMenu->exec( QCursor::pos() - pos + QPoint( 0, speedLabel->height() ) );
441 442
}

443 444 445
/****************************************************************************
 * Video Handling
 ****************************************************************************/
446 447 448 449 450
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 );
451 452 453
    if( ret )
    {
        videoIsActive = true;
454
        if( VISIBLE( playlistWidget ) )
455 456
        {
            embeddedPlaylistWasActive = true;
457
//            playlistWidget->hide();
458
        }
459 460
        bool bgWasVisible = false;
        if( VISIBLE( bgWidget) )
zorglub's avatar
zorglub committed
461
        {
462
            bgWasVisible = true;
463
            bgWidget->hide();
zorglub's avatar
zorglub committed
464
        }
465 466 467 468 469 470 471 472 473 474 475
        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 );
        }
476
        videoWidget->updateGeometry(); // Needed for deinterlace
477 478
        need_components_update = true;
    }
479 480 481 482 483 484
    return ret;
}

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

488
    if( embeddedPlaylistWasActive )
489
        playlistWidget->show();
zorglub's avatar
zorglub committed
490
    else if( bgWidget )
491
        bgWidget->show();
zorglub's avatar
zorglub committed
492

493
    videoIsActive = false;
494
    need_components_update = true;
495 496
}

497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
class SetVideoOnTopQtEvent : public QEvent
{
public:
    SetVideoOnTopQtEvent( bool _onTop ) :
      QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
    {
    }

    bool OnTop() const
    {
        return onTop;
    }

private:
    bool onTop;
};

514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
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 );
533
            // videoWidget->updateGeometry();
534 535 536 537 538
            need_components_update = true;
            i_ret = VLC_SUCCESS;
            break;
        }
        case VOUT_SET_STAY_ON_TOP:
539 540 541 542 543 544
        {
            int i_arg = va_arg( args, int );
            QApplication::postEvent( this, new SetVideoOnTopQtEvent( i_arg ) );
            i_ret = VLC_SUCCESS;
            break;
        }
545 546 547 548 549 550 551
        default:
            msg_Warn( p_intf, "unsupported control query" );
            break;
    }
    return i_ret;
}

552 553 554 555 556 557 558
/*****************************************************************************
 * Playlist, Visualisation and Menus handling
 *****************************************************************************/
/**
 * Toggle the playlist widget or dialog
 **/
void MainInterface::togglePlaylist()
559
{
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
    /* 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 );
        if(bgWidget)
            CONNECT( playlistWidget, artSet( QString ), bgWidget, setArt(QString) );

        playlistWidget->widgetSize = settings->value( "playlistSize",
                                               QSize( 650, 310 ) ).toSize();
        /* 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. */
        if( !settings->value( "playlist-embedded", true ).toBool() );
        {
            msg_Dbg( p_intf, "we don't want it inside");
            dockPL->setFloating( true );
        }

    }
    else
    {
    /* toggle the display */
       TOGGLEV( dockPL );
    }

#if 0  // Toggle the playlist dialog if not embedded and return
593 594 595 596
    if( !playlistEmbeddedFlag )
    {
        if( playlistWidget )
        {
597
            /// \todo Destroy it
598 599 600 601
        }
        return;
    }

602
    // Create the playlist Widget and destroy the existing dialog
603 604 605
    if( !playlistWidget )
    {
        PlaylistDialog::killInstance();
606
        mainLayout->insertWidget( 0, playlistWidget );
607
        playlistWidget->hide();
608
    }
609 610

    // And toggle visibility
611
    if( VISIBLE( playlistWidget ) )
612 613
    {
        playlistWidget->hide();
614
        if( bgWidget ) bgWidget->show();
615 616
        if( videoIsActive )
        {
617 618 619
            videoWidget->widgetSize = savedVideoSize;
            videoWidget->resize( videoWidget->widgetSize );
            videoWidget->updateGeometry();
620
            if( bgWidget ) bgWidget->hide();
621 622 623 624 625 626
        }
    }
    else
    {
        playlistWidget->show();
        if( videoIsActive )
627 628 629 630 631 632
        {
            savedVideoSize = videoWidget->widgetSize;
            videoWidget->widgetSize.setHeight( 0 );
            videoWidget->resize( videoWidget->widgetSize );
            videoWidget->updateGeometry();
        }
633
        if( VISIBLE( bgWidget ) ) bgWidget->hide();
634
    }
635
#endif
636
    doComponentsUpdate();
637 638
}

zorglub's avatar
zorglub committed
639
void MainInterface::undockPlaylist()
640
{
641 642
    dockPL->setFloating( true );
#if 0
zorglub's avatar
zorglub committed
643
    if( playlistWidget )
644
    {
zorglub's avatar
zorglub committed
645 646
        playlistWidget->hide();
        playlistWidget->deleteLater();
647
        mainLayout->removeWidget( playlistWidget );
648 649
        playlistWidget = NULL;
        playlistEmbeddedFlag = false;
zorglub's avatar
zorglub committed
650

zorglub's avatar
zorglub committed
651
        menuBar()->clear();
652
        QVLCMenu::createMenuBar( this, p_intf, false, visualSelectorEnabled);
zorglub's avatar
zorglub committed
653 654 655 656 657 658 659 660 661 662

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

        doComponentsUpdate();
        THEDP->playlistDialog();
663
    }
664
#endif
zorglub's avatar
zorglub committed
665 666
}

667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
#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

689 690
void MainInterface::toggleMenus()
{
691 692
    TOGGLEV( controls );
    TOGGLEV( statusBar() );
693
    updateGeometry();
694 695
}

696 697 698
/* 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
699
{
700 701 702 703 704 705 706 707 708
    calculateInterfaceSize();
    resize( mainSize );
}

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

709
int MainInterface::getControlsVisibilityStatus()
710
{
711 712
    return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
                + CONTROLS_ADVANCED * controls->b_advancedVisible );
713 714 715 716 717
}

/************************************************************************
 * Other stuff
 ************************************************************************/
718
void MainInterface::setDisplayPosition( float pos, int time, int length )
719 720 721
{
    char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
    secstotimestr( psz_length, length );
722
    secstotimestr( psz_time, b_remainingTime ? length - time : time );
723

724
    QString title; title.sprintf( "%s/%s", psz_time, psz_length );
725
    /* Add a minus to remaining time*/
726 727
    if( b_remainingTime ) timeLabel->setText( " -"+title+" " );
    else timeLabel->setText( " "+title+" " );
728 729
}

730
void MainInterface::toggleTimeDisplay()
731 732 733 734
{
    b_remainingTime = ( b_remainingTime ? false : true );
}

735 736
void MainInterface::setName( QString name )
{
737 738 739 740 741
    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 +" " );
742 743 744 745
}

void MainInterface::setStatus( int status )
{
746
    /* Forward the status to the controls to toggle Play/Pause */
747
    controls->setStatus( status );
748
    /* And in the systray for the menu */
749
    if( sysTray )
750
        QVLCMenu::updateSystrayMenu( this, p_intf );
751 752
}

753 754 755
void MainInterface::setRate( int rate )
{
    QString str;
756
    str.setNum( ( 1000 / (double)rate), 'f', 2 );
757 758
    str.append( "x" );
    speedLabel->setText( str );
759
    speedControl->updateControls( rate );
760 761
}

762 763 764 765
void MainInterface::updateOnTimer()
{
    /* \todo Make this event-driven */
    if( intf_ShouldDie( p_intf ) )
766
    {
767 768
        QApplication::closeAllWindows();
        QApplication::quit();
769
    }
770
    if( need_components_update )
771
    {
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798
        doComponentsUpdate();
        need_components_update = false;
    }

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

799
    CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
800 801 802 803 804 805 806 807 808 809 810 811 812
            this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
}

/**
 * Updates the Systray Icon's menu and toggle the main interface
 */
void MainInterface::toggleUpdateSystrayMenu()
{
    if( isHidden() )
    {
        show();
        activateWindow();
    }
813 814 815 816 817
    else if( isMinimized() )
    {
        showNormal();
        activateWindow();
    }
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
    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();
        }
837
        else
838 839 840
        {
            activateWindow();
        }
841
    }
842
    QVLCMenu::updateSystrayMenu( this, p_intf );
843 844
}

845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
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 );
874
        if( notificationEnabled && ( isHidden() || isMinimized() ) )
875 876 877 878
        {
            sysTray->showMessage( qtr( "VLC media player" ), name,
                    QSystemTrayIcon::NoIcon, 4000 );
        }
879 880 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
    }
}

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

/************************************************************************
910
 * D&D Events
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
 ************************************************************************/
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 ) {
934 935
            playlist_Add( THEPL, qtu(s), NULL,
                          PLAYLIST_APPEND | (first ? PLAYLIST_GO:0),
936
                          PLAYLIST_END, VLC_TRUE, VLC_FALSE );
937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
            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();
}

955
/************************************************************************
956
 * Events stuff
957
 ************************************************************************/
958 959
void MainInterface::customEvent( QEvent *event )
{
960
#if 0
961 962 963 964 965
    if( event->type() == PLDockEvent_Type )
    {
        PlaylistDialog::killInstance();
        playlistEmbeddedFlag = true;
        menuBar()->clear();
966
        QVLCMenu::createMenuBar(this, p_intf, true, visualSelectorEnabled);
967 968
        togglePlaylist();
    }
969 970 971
#endif
    /*else */
    if ( event->type() == SetVideoOnTopEvent_Type )
972 973 974 975 976 977 978 979 980 981
    {
        SetVideoOnTopQtEvent* p_event = (SetVideoOnTopQtEvent*)event;
        if( p_event->OnTop() )
            setWindowFlags(windowFlags