main_interface.cpp 30.7 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 <assert.h>
49
#include <vlc_keys.h>
zorglub's avatar
zorglub committed
50
#include <vlc_vout.h>
zorglub's avatar
zorglub committed
51

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

60 61 62 63 64 65
#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()

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

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

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

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

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

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

117
    /* Set the other interface settings */
118 119 120 121
    playlistEmbeddedFlag = settings->value( "playlist-embedded", true).toBool();
    visualSelectorEnabled = settings->value( "visual-selector", false ).toBool();
    notificationEnabled = config_GetInt( p_intf, "qt-notification" )
                          ? true : false;
122 123 124
    /**************************
     *  UI and Widgets design
     **************************/
125
    setVLCWindowsTitle();
126
    handleMainUi( settings );
127 128

    /* Menu Bar */
zorglub's avatar
zorglub committed
129
    QVLCMenu::createMenuBar( this, p_intf, playlistEmbeddedFlag,
130
                             visualSelectorEnabled );
131 132

    /* Status Bar */
133 134 135 136
    /**
     * TODO: clicking on the elapsed time should switch to the remaining time
     **/
    /**
137
     * TODO: do we add a label for the current Volume ?
138
     **/
139
    b_remainingTime = false;
140
    timeLabel = new TimeLabel;
141
    nameLabel = new QLabel;
142
    speedLabel = new QLabel( "1.00x" );
143
    timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
144 145 146 147
    speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
    statusBar()->addWidget( nameLabel, 8 );
    statusBar()->addPermanentWidget( speedLabel, 0 );
    statusBar()->addPermanentWidget( timeLabel, 2 );
148 149
    speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
    timeLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
150
    CONNECT( timeLabel, timeLabelClicked(), this, toggleTimeDisplay() );
151 152 153 154
    CONNECT( speedLabel, customContextMenuRequested( QPoint ),
             this, showSpeedMenu( QPoint ) );
    CONNECT( timeLabel, customContextMenuRequested( QPoint ),
             this, showTimeMenu( QPoint ) );
155

156 157 158
    /**********************
     * Systray Management *
     **********************/
159
    sysTray = NULL;
160 161
    bool b_createSystray = false;
    bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
162
    if( config_GetInt( p_intf, "qt-start-minimized") )
163
    {
164 165 166 167 168 169
        if( b_systrayAvailable ){
            b_createSystray = true;
            hide(); //FIXME
        }
        else msg_Warn( p_intf, "You can't minize if you haven't a system "
                "tray bar" );
170
    }
171 172
    if( config_GetInt( p_intf, "qt-system-tray") )
        b_createSystray = true;
173 174

    if( b_systrayAvailable && b_createSystray )
175
            createSystray();
176

177 178 179 180
    /* Init input manager */
    MainInputManager::getInstance( p_intf );
    ON_TIMEOUT( updateOnTimer() );

181
    /**
182
     * Various CONNECTs
183 184
     **/

185
    /* Connect the input manager to the GUI elements it manages */
186
    /* It is also connected to the control->slider, see the ControlsWidget */
187
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
188
             this, setDisplayPosition( float, int, int ) );
189

190
    CONNECT( THEMIM->getIM(), rateChanged( int ), this, setRate( int ) );
191

192 193
    /** Connects on nameChanged() */
    /* Naming in the controller statusbar */
194 195
    CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setName( QString ) );
196
    /* and in the systray */
197
    if( sysTray )
198 199
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
200
                 updateSystrayTooltipName( QString ) );
201
    }
202
    /* and in the title of the controller */
203 204 205 206 207 208
    if( config_GetInt( p_intf, "qt-name-in-title" ) )
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setVLCWindowsTitle( QString ) );
    }

209 210
    /** CONNECTS on PLAY_STATUS **/
    /* Status on the main controller */
211
    CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
212
    /* and in the systray */
213
    if( sysTray )
214 215
    {
        CONNECT( THEMIM->getIM(), statusChanged( int ), this,
216
                 updateSystrayTooltipStatus( int ) );
217
    }
218

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

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

MainInterface::~MainInterface()
{
239
    /* Unregister callback for the intf-popupmenu variable */
240 241
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
242 243 244 245 246 247 248
    if( p_playlist != NULL )
    {
        var_DelCallback( p_playlist, "intf-popupmenu", PopupMenuCB, p_intf );
        var_DelCallback( p_playlist, "intf-show", IntfShowCB, p_intf );
        vlc_object_release( p_playlist );
    }

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

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

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

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

282

283 284
void MainInterface::handleMainUi( QSettings *settings )
{
285
    /* Create the main Widget and the mainLayout */
286
    QWidget *main = new QWidget( this );
287
    mainLayout = new QVBoxLayout( main );
288 289
    setCentralWidget( main );

290 291 292 293
    /* Margins, spacing */
    main->setContentsMargins( 0, 0, 0, 0 );
    mainLayout->setMargin( 0 );

294 295 296
    /* Create the CONTROLS Widget */
    controls = new ControlsWidget( p_intf,
                   settings->value( "adv-controls", false ).toBool() );
297

298
    /* Configure the Controls */
299
    BUTTON_SET_IMG( controls->playlistButton, "" , playlist_icon.png,
300 301 302
                    playlistEmbeddedFlag ?  qtr( "Show playlist" ) :
                                            qtr( "Open playlist" ) );
    BUTTONACT( controls->playlistButton, togglePlaylist() );
303

304
    /* Add the controls Widget to the main Widget */
305 306
    mainLayout->addWidget( controls );

307 308 309 310 311 312
    /* 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 );
313

314 315
    /* Set initial size */
    resize( PREF_W, PREF_H );
316
    addSize = QSize( mainLayout->margin() * 2, PREF_H );
317

318
    /* Visualisation */
319
    visualSelector = new VisualSelector( p_intf );
320
    mainLayout->insertWidget( 0, visualSelector );
321 322
    visualSelector->hide();

323
    /* And video Outputs */
324
    if( alwaysVideoFlag )
325 326 327
    {
        bgWidget = new BackgroundWidget( p_intf );
        bgWidget->widgetSize = settings->value( "backgroundSize",
328
                                           QSize( 300, 300 ) ).toSize();
329 330
        bgWidget->resize( bgWidget->widgetSize );
        bgWidget->updateGeometry();
331
        mainLayout->insertWidget( 0, bgWidget );
332 333
    }

334
    if( videoEmbeddedFlag )
335
    {
336
        videoWidget = new VideoWidget( p_intf );
337
        videoWidget->widgetSize = QSize( 1, 1 );
338
        //videoWidget->resize( videoWidget->widgetSize );
339
        mainLayout->insertWidget( 0, videoWidget );
340

341 342 343
        p_intf->pf_request_window  = ::DoRequest;
        p_intf->pf_release_window  = ::DoRelease;
        p_intf->pf_control_window  = ::DoControl;
344
    }
345 346

    /* Finish the sizing */
zorglub's avatar
zorglub committed
347
    setMinimumSize( PREF_W, addSize.height() );
zorglub's avatar
zorglub committed
348 349
}

350
/**********************************************************************
351
 * Handling of sizing of the components
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
 **********************************************************************/
void MainInterface::calculateInterfaceSize()
{
    int width = 0, height = 0;
    if( VISIBLE( bgWidget ) )
    {
        width = bgWidget->widgetSize.width();
        height = bgWidget->widgetSize.height();
        assert( !(playlistWidget && playlistWidget->isVisible() ) );
    }
    else if( VISIBLE( playlistWidget ) )
    {
        width = playlistWidget->widgetSize.width();
        height = playlistWidget->widgetSize.height();
    }
    else if( videoIsActive )
    {
        width =  videoWidget->widgetSize.width() ;
        height = videoWidget->widgetSize.height();
    }
    else
    {
        width = PREF_W - addSize.width();
        height = PREF_H - addSize.height();
    }
    if( VISIBLE( visualSelector ) )
        height += visualSelector->height();
379
/*    if( VISIBLE( advControls) )
380 381
    {
        height += advControls->sizeHint().height();
382
    }*/
383 384 385 386 387
    mainSize = QSize( width + addSize.width(), height + addSize.height() );
}

void MainInterface::resizeEvent( QResizeEvent *e )
{
388 389
    if( videoWidget )
        videoWidget->widgetSize.setWidth( e->size().width() - addSize.width() );
390 391 392 393 394 395 396 397 398 399 400 401 402
    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();
    }
}
403

404 405 406 407 408
/****************************************************************************
 * Small right-click menus
 ****************************************************************************/
void MainInterface::showSpeedMenu( QPoint pos )
{
409
    speedControlMenu->exec( QCursor::pos() - pos + QPoint( 0, speedLabel->height() ) );
410 411 412 413 414
}

void MainInterface::showTimeMenu( QPoint pos )
{
    QMenu menu( this );
415 416
    menu.addAction(  qtr("Elapsed Time") , this, SLOT( setElapsedTime() ) );
    menu.addAction(  qtr("Remaining Time") , this, SLOT( setRemainTime() ) );
417
    menu.exec( QCursor::pos() - pos +QPoint( 0, timeLabel->height() ) );
418
}
419

420 421 422
/****************************************************************************
 * Video Handling
 ****************************************************************************/
423 424 425 426 427
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 );
428 429 430
    if( ret )
    {
        videoIsActive = true;
431
        if( VISIBLE( playlistWidget ) )
432 433
        {
            embeddedPlaylistWasActive = true;
434
//            playlistWidget->hide();
435
        }
436 437
        bool bgWasVisible = false;
        if( VISIBLE( bgWidget) )
zorglub's avatar
zorglub committed
438
        {
439
            bgWasVisible = true;
440
            bgWidget->hide();
zorglub's avatar
zorglub committed
441
        }
442 443 444 445 446 447 448 449 450 451 452
        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 );
        }
453
        videoWidget->updateGeometry(); // Needed for deinterlace
454 455
        need_components_update = true;
    }
456 457 458 459 460 461
    return ret;
}

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

465
    if( embeddedPlaylistWasActive )
466
        playlistWidget->show();
zorglub's avatar
zorglub committed
467
    else if( bgWidget )
468
        bgWidget->show();
zorglub's avatar
zorglub committed
469

470
    videoIsActive = false;
471
    need_components_update = true;
472 473
}

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
class SetVideoOnTopQtEvent : public QEvent
{
public:
    SetVideoOnTopQtEvent( bool _onTop ) :
      QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
    {
    }

    bool OnTop() const
    {
        return onTop;
    }

private:
    bool onTop;
};

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
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 );
510
            // videoWidget->updateGeometry();
511 512 513 514 515
            need_components_update = true;
            i_ret = VLC_SUCCESS;
            break;
        }
        case VOUT_SET_STAY_ON_TOP:
516 517 518 519 520 521
        {
            int i_arg = va_arg( args, int );
            QApplication::postEvent( this, new SetVideoOnTopQtEvent( i_arg ) );
            i_ret = VLC_SUCCESS;
            break;
        }
522 523 524 525 526 527 528
        default:
            msg_Warn( p_intf, "unsupported control query" );
            break;
    }
    return i_ret;
}

529 530 531 532 533 534 535
/*****************************************************************************
 * Playlist, Visualisation and Menus handling
 *****************************************************************************/
/**
 * Toggle the playlist widget or dialog
 **/
void MainInterface::togglePlaylist()
536
{
537
    // Toggle the playlist dialog if not embedded and return
538 539 540 541
    if( !playlistEmbeddedFlag )
    {
        if( playlistWidget )
        {
542
            /// \todo Destroy it
543 544 545 546 547
        }
        THEDP->playlistDialog();
        return;
    }

548
    // Create the playlist Widget and destroy the existing dialog
549 550 551 552
    if( !playlistWidget )
    {
        PlaylistDialog::killInstance();
        playlistWidget = new PlaylistWidget( p_intf );
553
        mainLayout->insertWidget( 0, playlistWidget );
554
        playlistWidget->widgetSize = settings->value( "playlistSize",
zorglub's avatar
zorglub committed
555
                                               QSize( 650, 310 ) ).toSize();
556
        playlistWidget->hide();
557 558
        if(bgWidget)
        CONNECT( playlistWidget, artSet( QString ), bgWidget, setArt(QString) );
559
    }
560 561

    // And toggle visibility
562
    if( VISIBLE( playlistWidget ) )
563 564
    {
        playlistWidget->hide();
565
        if( bgWidget ) bgWidget->show();
566 567
        if( videoIsActive )
        {
568 569 570
            videoWidget->widgetSize = savedVideoSize;
            videoWidget->resize( videoWidget->widgetSize );
            videoWidget->updateGeometry();
571
            if( bgWidget ) bgWidget->hide();
572 573 574 575 576 577
        }
    }
    else
    {
        playlistWidget->show();
        if( videoIsActive )
578 579 580 581 582 583
        {
            savedVideoSize = videoWidget->widgetSize;
            videoWidget->widgetSize.setHeight( 0 );
            videoWidget->resize( videoWidget->widgetSize );
            videoWidget->updateGeometry();
        }
584
        if( VISIBLE( bgWidget ) ) bgWidget->hide();
585
    }
586

587
    doComponentsUpdate();
588 589
}

zorglub's avatar
zorglub committed
590
void MainInterface::undockPlaylist()
591
{
zorglub's avatar
zorglub committed
592
    if( playlistWidget )
593
    {
zorglub's avatar
zorglub committed
594 595
        playlistWidget->hide();
        playlistWidget->deleteLater();
596
        mainLayout->removeWidget( playlistWidget );
597 598
        playlistWidget = NULL;
        playlistEmbeddedFlag = false;
zorglub's avatar
zorglub committed
599

zorglub's avatar
zorglub committed
600
        menuBar()->clear();
601
        QVLCMenu::createMenuBar( this, p_intf, false, visualSelectorEnabled);
zorglub's avatar
zorglub committed
602 603 604 605 606 607 608 609 610 611

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

        doComponentsUpdate();
        THEDP->playlistDialog();
612
    }
zorglub's avatar
zorglub committed
613 614
}

615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
#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

637 638
void MainInterface::toggleMenus()
{
639 640
    TOGGLEV( controls );
    TOGGLEV( statusBar() );
641
    updateGeometry();
642 643
}

644 645 646
/* 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
647
{
648 649 650 651 652 653 654 655 656
    calculateInterfaceSize();
    resize( mainSize );
}

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

657
int MainInterface::getControlsVisibilityStatus()
658
{
659
    return( (controls->isVisible() ? 0x2 : 0x0 )
660
                + controls->b_advancedVisible );
661 662 663 664 665
}

/************************************************************************
 * Other stuff
 ************************************************************************/
666
void MainInterface::setDisplayPosition( float pos, int time, int length )
667 668 669
{
    char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
    secstotimestr( psz_length, length );
670 671 672 673
    secstotimestr( psz_time, b_remainingTime ? length - time : time );
    QString title; title.sprintf( "%s/%s", psz_time, psz_length );
    if( b_remainingTime ) timeLabel->setText( " -"+title+" " );
    else timeLabel->setText( " "+title+" " );
674 675
}

676
void MainInterface::toggleTimeDisplay()
677 678 679 680 681 682 683
{
    b_remainingTime = ( b_remainingTime ? false : true );
}

void MainInterface::setElapsedTime(){ b_remainingTime = false; }
void MainInterface::setRemainTime(){ b_remainingTime = true; }

684 685 686 687 688 689 690 691 692 693 694 695 696
void MainInterface::setName( QString name )
{
    input_name = name;
    nameLabel->setText( " " + name+" " );
}

void MainInterface::setStatus( int status )
{
    controls->setStatus( status );
    if( sysTray )
        updateSystrayMenu( status );
}

697 698 699
void MainInterface::setRate( int rate )
{
    QString str;
700
    str.setNum( ( 1000 / (double)rate), 'f', 2 );
701 702
    str.append( "x" );
    speedLabel->setText( str );
703
    speedControl->updateControls( rate );
704 705
}

706 707 708 709
void MainInterface::updateOnTimer()
{
    /* \todo Make this event-driven */
    if( intf_ShouldDie( p_intf ) )
710
    {
711 712
        QApplication::closeAllWindows();
        QApplication::quit();
713
    }
714
    if( need_components_update )
715
    {
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
        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();

743
    CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
            this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
}

/**
 * Update the menu of the Systray Icon.
 * May be unneedded, since it just calls QVLCMenu::update
 * FIXME !!!
 **/
void MainInterface::updateSystrayMenu( int status )
{
    QVLCMenu::updateSystrayMenu( this, p_intf ) ;
}

/**
 * Updates the Systray Icon's menu and toggle the main interface
 */
void MainInterface::toggleUpdateSystrayMenu()
{
    if( isHidden() )
    {
        show();
        activateWindow();
    }
767 768 769 770 771
    else if( isMinimized() )
    {
        showNormal();
        activateWindow();
    }
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
    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();
        }
791
        else
792 793 794
        {
            activateWindow();
        }
795
    }
796
    QVLCMenu::updateSystrayMenu( this, p_intf );
797 798
}

799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
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.
 * FIXME !!! Fusion with next function ?
 **/
void MainInterface::updateSystrayTooltipName( QString name )
{
    if( name.isEmpty() )
    {
        sysTray->setToolTip( qtr( "VLC media player" ) );
    }
    else
    {
        sysTray->setToolTip( name );
829
        if( notificationEnabled && ( isHidden() || isMinimized() ) )
830 831 832 833
        {
            sysTray->showMessage( qtr( "VLC media player" ), name,
                    QSystemTrayIcon::NoIcon, 4000 );
        }
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
    }
}

/**
 * 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 );
                //+ " - " + qtr( "Playing" ) );
                break;
            }
        case PAUSE_S:
            {
                sysTray->setToolTip( input_name + " - "
                        + qtr( "Paused") );
                break;
            }
    }
}
864 865

/************************************************************************
866
 * D&D Events
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
 ************************************************************************/
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 ) {
890 891
            playlist_Add( THEPL, qtu(s), NULL,
                          PLAYLIST_APPEND | (first ? PLAYLIST_GO:0),
892
                          PLAYLIST_END, VLC_TRUE, VLC_FALSE );
893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
            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();
}

911
/************************************************************************
912
 * Events stuff
913
 ************************************************************************/
914 915 916 917 918 919 920
void MainInterface::customEvent( QEvent *event )
{
    if( event->type() == PLDockEvent_Type )
    {
        PlaylistDialog::killInstance();
        playlistEmbeddedFlag = true;
        menuBar()->clear();
921
        QVLCMenu::createMenuBar(this, p_intf, true, visualSelectorEnabled);
922 923 924 925 926 927 928 929 930 931 932 933 934
        togglePlaylist();
    }
    else if ( event->type() == SetVideoOnTopEvent_Type )
    {
        SetVideoOnTopQtEvent* p_event = (SetVideoOnTopQtEvent*)event;
        if( p_event->OnTop() )
            setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
        else
            setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
        show(); /* necessary to apply window flags?? */
    }
}

935 936
void MainInterface::keyPressEvent( QKeyEvent *e )
{
937
    int i_vlck = qtEventToVLCKey( e );
938 939
    if( i_vlck >= 0 )
    {
940
        var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
941 942 943 944 945 946
        e->accept();
    }
    else
        e->ignore();
}

947 948
void MainInterface::wheelEvent( QWheelEvent *e )
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
949
    int i_vlckey = qtWheelEventToVLCKey( e );
950 951 952 953
    var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
    e->accept();
}

zorglub's avatar
zorglub committed
954 955 956
void MainInterface::closeEvent( QCloseEvent *e )
{
    hide();
957
    vlc_object_kill( p_intf );
zorglub's avatar
zorglub committed
958
}
zorglub's avatar
zorglub committed
959

960 961 962
/*****************************************************************************
 * Callbacks
 *****************************************************************************/
zorglub's avatar
zorglub committed
963 964 965 966 967 968 969
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 );
970
    QApplication::postEvent( THEDP, static_cast<QEvent*>(event) );
zorglub's avatar
zorglub committed
971 972
    return VLC_SUCCESS;
}
973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000