main_interface.cpp 30.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
    speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );

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

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

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

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

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

    if( b_systrayAvailable && b_createSystray )
192
            createSystray();
193

194 195 196
    if( config_GetInt( p_intf, "qt-minimal-view" ) )
        toggleMenus();

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

202 203 204 205

    /********************
     * Various CONNECTs *
     ********************/
206

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

212
    CONNECT( THEMIM->getIM(), rateChanged( int ), this, setRate( int ) );
213

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

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

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

    /* Register callback for the intf-popupmenu variable */
251 252
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
253 254 255 256 257 258
    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 );
    }
259 260 261

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

262 263
    // DEBUG FIXME
    hide();
264 265 266 267
}

MainInterface::~MainInterface()
{
268
    /* Unregister 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 277
    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 );
    }

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

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

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

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

311

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

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

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

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

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

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

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

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

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

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

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

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

378 379 380 381 382
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() );
}
383
/**********************************************************************
384
 * Handling of sizing of the components
385 386 387 388 389 390
 **********************************************************************/
void MainInterface::calculateInterfaceSize()
{
    int width = 0, height = 0;
    if( VISIBLE( bgWidget ) )
    {
391
        width  = bgWidget->widgetSize.width();
392 393 394 395
        height = bgWidget->widgetSize.height();
    }
    else if( videoIsActive )
    {
396
        width  = videoWidget->widgetSize.width() ;
397 398 399 400
        height = videoWidget->widgetSize.height();
    }
    else
    {
401
        width  = PREF_W - addSize.width();
402 403
        height = PREF_H - addSize.height();
    }
Rafaël Carré's avatar
Rafaël Carré committed
404
    if( !dockPL->isFloating() && dockPL->widget() )
405 406 407 408
    {
        width  += dockPL->widget()->width();
        height += dockPL->widget()->height();
    }
409 410 411 412 413 414 415
    if( VISIBLE( visualSelector ) )
        height += visualSelector->height();
    mainSize = QSize( width + addSize.width(), height + addSize.height() );
}

void MainInterface::resizeEvent( QResizeEvent *e )
{
416 417
    if( videoWidget )
        videoWidget->widgetSize.setWidth( e->size().width() - addSize.width() );
418 419 420 421 422 423 424 425
    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 ) )
    {
426 427 428
        //FIXME
//        SET_WH( playlistWidget , e->size().width() - addSize.width(),
              //                   e->size().height() - addSize.height() );
429 430 431
        playlistWidget->updateGeometry();
    }
}
432

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

442 443 444
/****************************************************************************
 * Video Handling
 ****************************************************************************/
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
class SetVideoOnTopQtEvent : public QEvent
{
public:
    SetVideoOnTopQtEvent( bool _onTop ) :
      QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
    {
    }

    bool OnTop() const
    {
        return onTop;
    }

private:
    bool onTop;
};


463 464 465 466 467
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 );
468 469 470
    if( ret )
    {
        videoIsActive = true;
471

472 473
        bool bgWasVisible = false;
        if( VISIBLE( bgWidget) )
zorglub's avatar
zorglub committed
474
        {
475
            bgWasVisible = true;
476
            emit askBgWidgetToToggle();
zorglub's avatar
zorglub committed
477
        }
478

479 480 481 482 483 484 485 486 487 488 489
        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 );
        }
490
        videoWidget->updateGeometry(); // Needed for deinterlace
491 492
        need_components_update = true;
    }
493 494 495 496
    return ret;
}

void MainInterface::releaseVideo( void *p_win )
497 498 499 500 501
{
    emit askReleaseVideo( p_win );
}

void MainInterface::releaseVideoSlot( void *p_win )
502 503
{
    videoWidget->release( p_win );
504
    videoWidget->hide();
zorglub's avatar
zorglub committed
505

506
    if( bgWidget )
507
        bgWidget->show();
zorglub's avatar
zorglub committed
508

509
    videoIsActive = false;
510
    need_components_update = true;
511 512
}

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

551 552 553 554 555 556 557
/*****************************************************************************
 * Playlist, Visualisation and Menus handling
 *****************************************************************************/
/**
 * Toggle the playlist widget or dialog
 **/
void MainInterface::togglePlaylist()
558
{
559 560 561 562 563 564 565 566
    /* 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) );

567 568 569
        //FIXME
/*        playlistWidget->widgetSize = settings->value( "playlistSize",
                                               QSize( 650, 310 ) ).toSize();*/
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
        /* 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 );
    }
591
    doComponentsUpdate();
592 593
}

zorglub's avatar
zorglub committed
594
void MainInterface::undockPlaylist()
595
{
596
    dockPL->setFloating( true );
597
    doComponentsUpdate();
zorglub's avatar
zorglub committed
598 599
}

600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
#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

622 623
void MainInterface::toggleMenus()
{
624 625
    TOGGLEV( controls );
    TOGGLEV( statusBar() );
626
    updateGeometry();
627 628
}

629 630 631
/* 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
632
{
633 634 635 636 637 638 639 640 641
    calculateInterfaceSize();
    resize( mainSize );
}

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

642
int MainInterface::getControlsVisibilityStatus()
643
{
644 645
    return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
                + CONTROLS_ADVANCED * controls->b_advancedVisible );
646 647 648 649 650
}

/************************************************************************
 * Other stuff
 ************************************************************************/
651
void MainInterface::setDisplayPosition( float pos, int time, int length )
652 653 654
{
    char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
    secstotimestr( psz_length, length );
655
    secstotimestr( psz_time, b_remainingTime ? length - time : time );
656

657
    QString title; title.sprintf( "%s/%s", psz_time, psz_length );
658
    /* Add a minus to remaining time*/
659 660
    if( b_remainingTime ) timeLabel->setText( " -"+title+" " );
    else timeLabel->setText( " "+title+" " );
661 662
}

663
void MainInterface::toggleTimeDisplay()
664 665 666 667
{
    b_remainingTime = ( b_remainingTime ? false : true );
}

668 669
void MainInterface::setName( QString name )
{
670 671 672 673 674
    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 +" " );
675 676 677 678
}

void MainInterface::setStatus( int status )
{
679
    /* Forward the status to the controls to toggle Play/Pause */
680
    controls->setStatus( status );
681
    /* And in the systray for the menu */
682
    if( sysTray )
683
        QVLCMenu::updateSystrayMenu( this, p_intf );
684 685
}

686 687 688
void MainInterface::setRate( int rate )
{
    QString str;
689
    str.setNum( ( 1000 / (double)rate), 'f', 2 );
690 691
    str.append( "x" );
    speedLabel->setText( str );
692
    speedControl->updateControls( rate );
693 694
}

695 696 697 698
void MainInterface::updateOnTimer()
{
    /* \todo Make this event-driven */
    if( intf_ShouldDie( p_intf ) )
699
    {
700 701
        QApplication::closeAllWindows();
        QApplication::quit();
702
    }
703
    if( need_components_update )
704
    {
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
        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();

732
    CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
733 734 735 736 737 738 739 740 741 742 743 744 745
            this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
}

/**
 * Updates the Systray Icon's menu and toggle the main interface
 */
void MainInterface::toggleUpdateSystrayMenu()
{
    if( isHidden() )
    {
        show();
        activateWindow();
    }
746 747 748 749 750
    else if( isMinimized() )
    {
        showNormal();
        activateWindow();
    }
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
    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();
        }
770
        else
771 772 773
        {
            activateWindow();
        }
774
    }
775
    QVLCMenu::updateSystrayMenu( this, p_intf );
776 777
}

778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
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 );
807
        if( notificationEnabled && ( isHidden() || isMinimized() ) )
808 809 810 811
        {
            sysTray->showMessage( qtr( "VLC media player" ), name,
                    QSystemTrayIcon::NoIcon, 4000 );
        }
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
    }
}

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

/************************************************************************
843
 * D&D Events
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
 ************************************************************************/
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 ) {
867 868
            playlist_Add( THEPL, qtu(s), NULL,
                          PLAYLIST_APPEND | (first ? PLAYLIST_GO:0),
869
                          PLAYLIST_END, VLC_TRUE, VLC_FALSE );
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
            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();
}

888
/************************************************************************
889
 * Events stuff
890
 ************************************************************************/
891 892
void MainInterface::customEvent( QEvent *event )
{
893
#if 0
894 895 896 897 898
    if( event->type() == PLDockEvent_Type )
    {
        PlaylistDialog::killInstance();
        playlistEmbeddedFlag = true;
        menuBar()->clear();
899
        QVLCMenu::createMenuBar(this, p_intf, true, visualSelectorEnabled);
900 901
        togglePlaylist();
    }
902 903 904
#endif
    /*else */
    if ( event->type() == SetVideoOnTopEvent_Type )
905 906 907 908 909 910 911 912 913 914
    {
        SetVideoOnTopQtEvent* p_event = (SetVideoOnTopQtEvent*)event;
        if( p_event->OnTop() )
            setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
        else
            setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
        show(); /* necessary to apply window flags?? */
    }
}

915 916
void MainInterface::keyPressEvent( QKeyEvent *e )
{
917
    int i_vlck = qtEventToVLCKey( e );
918 919
    if( i_vlck >= 0 )
    {
920
        var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
921 922 923 924 925 926
        e->accept();
    }
    else
        e->ignore();
}

927 928
void MainInterface::wheelEvent( QWheelEvent *e )
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
929
    int i_vlckey = qtWheelEventToVLCKey( e );
930 931 932 933
    var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
    e->accept();
}

zorglub's avatar
zorglub committed
934 935 936
void MainInterface::closeEvent( QCloseEvent *e )
{
    hide();
937
    vlc_object_kill( p_intf );
zorglub's avatar
zorglub committed
938
}
zorglub's avatar
zorglub committed
939

940 941 942
/*****************************************************************************
 * Callbacks
 *****************************************************************************/
zorglub's avatar
zorglub committed
943 944 945 946 947 948 949
static int InteractCallback( vlc_object_t *p_this,
                             const char *psz_var, vlc_value_t old_val,
                             vlc_value_t new_val, void *param )
{
    intf_dialog_args_t *p_arg = new intf_dialog_args_t;
    p_arg->p_dialog = (interaction_dialog_t *)(new_val.p_address);
    DialogEvent *event = new DialogEvent( INTF_DIALOG_INTERACTION, 0, p_arg );
950
    QApplication::postEvent( THEDP, static_cast<QEvent*>(event) );
zorglub's avatar
zorglub committed
951 952
    return VLC_SUCCESS;
}
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983

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

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

    return VLC_SUCCESS;
}

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