main_interface.cpp 31.9 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 8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *
 * 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
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22
 *****************************************************************************/
zorglub's avatar
zorglub committed
23

24
#include "qt4.hpp"
zorglub's avatar
zorglub committed
25
#include "main_interface.hpp"
zorglub's avatar
zorglub committed
26
#include "input_manager.hpp"
27
#include "util/input_slider.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 45

#include <assert.h>
46
#include <vlc_keys.h>
zorglub's avatar
zorglub committed
47
#include <vlc_vout.h>
zorglub's avatar
zorglub committed
48

zorglub's avatar
zorglub committed
49
#ifdef WIN32
zorglub's avatar
zorglub committed
50
    #define PREF_W 410
zorglub's avatar
zorglub committed
51 52
    #define PREF_H 121
#else
zorglub's avatar
zorglub committed
53
    #define PREF_W 450
zorglub's avatar
zorglub committed
54 55
    #define PREF_H 125
#endif
zorglub's avatar
zorglub committed
56

57 58 59 60 61 62 63 64
#define VISIBLE(i) (i && i->isVisible())

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

65 66
#define DEBUG_COLOR 0

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

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

96
    bool b_createSystray = false;
97
    input_name = "";
98

99
    /**
100
     *  Configuration and settings
101 102 103 104
     **/
    settings = new QSettings( "VideoLAN", "VLC" );
    settings->beginGroup( "MainWindow" );

105 106 107
    /* Main settings */
    setFocusPolicy( Qt::StrongFocus );
    setAcceptDrops(true);
108 109 110
    setWindowIcon( QApplication::windowIcon() );

    /* 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
    playlistEmbeddedFlag = settings->value("playlist-embedded", true).toBool();
zorglub's avatar
zorglub committed
121
    advControlsEnabled= settings->value( "adv-controls", false ).toBool();
122
    visualSelectorEnabled= settings->value( "visual-selector", false ).toBool();
zorglub's avatar
zorglub committed
123

124 125 126 127 128 129 130 131 132
#if DEBUG_COLOR
    QPalette palette2;
    palette2.setColor(this->backgroundRole(), Qt::magenta);
    setPalette(palette2);
#endif

    /**
     *  UI design
     **/
133
    setVLCWindowsTitle();
134
    handleMainUi( settings );
135 136

    /* Menu Bar */
zorglub's avatar
zorglub committed
137
    QVLCMenu::createMenuBar( this, p_intf, playlistEmbeddedFlag,
138
                             advControlsEnabled, visualSelectorEnabled );
139 140

    /* Status Bar */
141 142 143
    timeLabel = new QLabel;
    nameLabel = new QLabel;
    speedLabel = new QLabel( "1.0x" );
144
    timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
145 146 147 148
    speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
    statusBar()->addWidget( nameLabel, 8 );
    statusBar()->addPermanentWidget( speedLabel, 0 );
    statusBar()->addPermanentWidget( timeLabel, 2 );
149 150 151 152 153 154
    speedLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
    timeLabel->setContextMenuPolicy ( Qt::CustomContextMenu );
    CONNECT( speedLabel, customContextMenuRequested( QPoint ),
             this, showSpeedMenu( QPoint ) );
    CONNECT( timeLabel, customContextMenuRequested( QPoint ),
             this, showTimeMenu( QPoint ) );
155
    /* Systray */
156
    sysTray = NULL;
157
    if( config_GetInt( p_intf, "qt-start-minimized") )
158 159
    {
        hide();
160
        b_createSystray = true;
161
    }
162 163 164
    if( config_GetInt( p_intf, "qt-system-tray") )
        b_createSystray = true;
    if (QSystemTrayIcon::isSystemTrayAvailable() && b_createSystray )
165
            createSystray();
166

167 168 169 170
    /* Init input manager */
    MainInputManager::getInstance( p_intf );
    ON_TIMEOUT( updateOnTimer() );

171 172 173 174
    /**
     * CONNECTs
     **/

175 176
    /* Volume control */
    CONNECT( ui.volumeSlider, valueChanged(int), this, updateVolume(int) );
177

178 179 180 181 182
    /* Connect the input manager to the GUI elements it manages */
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
             slider, setPosition( float,int, int ) );
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
             this, setDisplay( float, int, int ) );
183 184

    /* Naming in the controller */
185 186
    CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setName( QString ) );
187
    if( config_GetInt( p_intf, "qt-system-tray" ) && sysTray )
188 189
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
190
                 updateSystrayTooltipName( QString ) );
191
    }
192 193 194 195 196 197 198
    if( config_GetInt( p_intf, "qt-name-in-title" ) )
    {
        CONNECT( THEMIM->getIM(), nameChanged( QString ), this,
             setVLCWindowsTitle( QString ) );
    }

    /* PLAY_STATUS */
199
    CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
200
    CONNECT( THEMIM->getIM(), navigationChanged( int ),
201
             this, setNavigation(int) );
202
    if( config_GetInt( p_intf, "qt-system-tray" ) && sysTray )
203 204
    {
        CONNECT( THEMIM->getIM(), statusChanged( int ), this,
205
                 updateSystrayTooltipStatus( int ) );
206
    }
207 208 209
    CONNECT( slider, sliderDragged( float ),
             THEMIM->getIM(), sliderUpdate( float ) );

210
    /* Buttons */
211 212 213 214 215 216 217
    CONNECT( ui.prevSectionButton, clicked(), THEMIM->getIM(),
             sectionPrev() );
    CONNECT( ui.nextSectionButton, clicked(), THEMIM->getIM(),
             sectionNext() );
    CONNECT( ui.menuButton, clicked(), THEMIM->getIM(),
             sectionMenu() );

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

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

MainInterface::~MainInterface()
{
238
    /* Unregister callback for the intf-popupmenu variable */
239 240
    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
241 242 243 244 245 246 247
    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
248 249 250 251 252
    settings->setValue( "playlist-embedded", playlistEmbeddedFlag );
    settings->setValue( "adv-controls", advControlsEnabled );
    settings->setValue( "pos", pos() );
    settings->endGroup();
    delete settings;
253 254
    p_intf->b_interaction = VLC_FALSE;
    var_DelCallback( p_intf, "interaction", InteractCallback, this );
255 256 257 258

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

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

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

281 282 283
void MainInterface::handleMainUi( QSettings *settings )
{
    QWidget *main = new QWidget( this );
284
    QVBoxLayout *mainLayout = new QVBoxLayout( main );
285 286
    setCentralWidget( main );

287 288 289 290 291
    /* Margins, spacing */
    main->setContentsMargins( 0, 0, 0, 0 );
    mainLayout->setMargin( 0 );

    /* CONTROLS */
292
    QWidget *controls = new QWidget;
293 294 295
    ui.setupUi( controls );

    /* Configure the UI */
zorglub's avatar
zorglub committed
296
    slider = new InputSlider( Qt::Horizontal, NULL );
297
    mainLayout->insertWidget( 0, slider );
298
    ui.discFrame->hide();
299

300 301 302
    BUTTON_SET_IMG( ui.prevSectionButton, "", previous.png, "" );
    BUTTON_SET_IMG( ui.nextSectionButton, "", next.png, "" );
    BUTTON_SET_IMG( ui.menuButton, "", previous.png, "" );
303

zorglub's avatar
zorglub committed
304 305 306 307 308
    BUTTON_SET_ACT_I( ui.prevButton, "" , previous.png,
                      qtr("Previous"), prev() );
    BUTTON_SET_ACT_I( ui.nextButton, "", next.png, qtr("Next"), next() );
    BUTTON_SET_ACT_I( ui.playButton, "", play.png, qtr("Play"), play() );
    BUTTON_SET_ACT_I( ui.stopButton, "", stop.png, qtr("Stop"), stop() );
309 310

    /* Volume */
311
    ui.volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-low.png" ) );
zorglub's avatar
zorglub committed
312
    ui.volumeSlider->setMaximum( 100 );
313 314 315
    ui.volMuteLabel->setToolTip( qtr( "Mute" ) );
    VolumeClickHandler *h = new VolumeClickHandler( p_intf, this );
    ui.volMuteLabel->installEventFilter(h);
zorglub's avatar
zorglub committed
316 317
    ui.volumeSlider->setFocusPolicy( Qt::NoFocus );

318
    BUTTON_SET_IMG( ui.playlistButton, "" , playlist_icon.png,
zorglub's avatar
zorglub committed
319
                        playlistEmbeddedFlag ?  qtr( "Show playlist" ) :
zorglub's avatar
Cleanup  
zorglub committed
320
                                                qtr( "Open playlist" ) );
321
    BUTTONACT( ui.playlistButton, playlist() );
zorglub's avatar
zorglub committed
322

323 324 325 326 327 328 329 330 331
#if DEBUG_COLOR
    QPalette palette;
    palette.setColor(main->backgroundRole(), Qt::green);
    main->setPalette(palette);
#endif

    /* Add the controls Widget */
    mainLayout->addWidget( controls );

zorglub's avatar
zorglub committed
332
    /* Set initial size */
zorglub's avatar
zorglub committed
333
    resize ( PREF_W, PREF_H );
334

335
    addSize = QSize( mainLayout->margin() * 2, PREF_H );
336

337
    /* advanced Controls handling */
zorglub's avatar
zorglub committed
338
    advControls = new ControlsWidget( p_intf );
339
    mainLayout->insertWidget( 0, advControls );
zorglub's avatar
zorglub committed
340 341 342 343
    advControls->updateGeometry();
    if( !advControlsEnabled ) advControls->hide();
    need_components_update = true;

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 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
/**********************************************************************
 * Handling of the components
 **********************************************************************/
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();
    if( VISIBLE( advControls) )
    {
        height += advControls->sizeHint().height();
    }
    mainSize = QSize( width + addSize.width(), height + addSize.height() );
}

void MainInterface::resizeEvent( QResizeEvent *e )
{
    videoWidget->widgetSize.setWidth(  e->size().width() - addSize.width() );
    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();
    }
}
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
/****************************************************************************
 * Small right-click menus
 ****************************************************************************/
void MainInterface::showSpeedMenu( QPoint pos )
{
    QMenu menu( this );
    menu.addAction( "Not Implemented Yet" );
    menu.exec( QCursor::pos() );
}

void MainInterface::showTimeMenu( QPoint pos )
{
    QMenu menu( this );
    menu.addAction( "Not Implemented Yet" );
    menu.exec( QCursor::pos() );
}
444

445 446 447 448
/*****************************************************************************
 * Systray Icon and Systray Menu
 *****************************************************************************/

449 450 451 452 453
/**
 * Create a SystemTray icon and a menu that would go with it.
 * Connects to a click handler on the icon.
 **/
void MainInterface::createSystray()
454
{
455
    QIcon iconVLC =  QIcon( QPixmap( ":/vlc128.png" ) );
456
    sysTray = new QSystemTrayIcon( iconVLC, this );
457 458
    sysTray->setToolTip( qtr( "VLC media player" ));

459
    systrayMenu = new QMenu( qtr( "VLC media player" ), this );
460
    systrayMenu->setIcon( iconVLC );
461

462
    QVLCMenu::updateSystrayMenu( this, p_intf, true );
463
    sysTray->show();
464

465 466
    CONNECT( sysTray, activated(  QSystemTrayIcon::ActivationReason ),
            this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
467 468
}

469 470 471
/**
 * Update the menu of the Systray Icon.
 * May be unneedded, since it just calls QVLCMenu::update
472
 * FIXME !!!
473
 **/
474 475 476 477 478
void MainInterface::updateSystrayMenu( int status )
{
    QVLCMenu::updateSystrayMenu( this, p_intf ) ;
}

479 480 481
/**
 * Updates the Systray Icon's menu and toggle the main interface
 */
482 483
void MainInterface::toggleUpdateSystrayMenu()
{
484 485 486
    if( isHidden() )
    {
        show();
487
        activateWindow();
488 489 490
    }
    else
    {
491 492 493 494 495 496 497 498 499 500 501 502
#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
503
        if( isActiveWindow() )
504
#endif
505 506 507 508 509 510 511 512
        {
            hide();
        }
        else
        {
            activateWindow();
        }
    }
513
    QVLCMenu::updateSystrayMenu( this, p_intf );
514 515
}

516 517
void MainInterface::handleSystrayClick(
                                    QSystemTrayIcon::ActivationReason reason )
518 519 520 521
{
    switch( reason )
    {
        case QSystemTrayIcon::Trigger:
522 523
            toggleUpdateSystrayMenu();
            break;
524 525
        case QSystemTrayIcon::MiddleClick:
            sysTray->showMessage( qtr( "VLC media player" ),
526
                    qtr( "Control menu for the player" ),
527 528 529 530 531
                    QSystemTrayIcon::Information, 4000 );
            break;
    }
}

532 533 534
/**
 * Updates the name of the systray Icon tooltip.
 * Doesn't check if the systray exists, check before you call it.
535
 * FIXME !!! Fusion with next function ?
536
 **/
537 538 539 540 541 542 543 544 545 546 547 548
void MainInterface::updateSystrayTooltipName( QString name )
{
    if( name.isEmpty() )
    {
        sysTray->setToolTip( qtr( "VLC media player" ) );
    }
    else
    {
        sysTray->setToolTip( name );
    }
}

549 550 551 552
/**
 * Updates the status of the systray Icon tooltip.
 * Doesn't check if the systray exists, check before you call it.
 **/
553 554 555
void MainInterface::updateSystrayTooltipStatus( int i_status )
{
    switch( i_status )
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
    {
        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;
            }
    }
575
}
576 577 578 579 580
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 );
581 582 583
    if( ret )
    {
        videoIsActive = true;
584
        if( VISIBLE( playlistWidget ) )
585 586
        {
            embeddedPlaylistWasActive = true;
587
//            playlistWidget->hide();
588
        }
589 590
        bool bgWasVisible = false;
        if( VISIBLE( bgWidget) )
zorglub's avatar
zorglub committed
591
        {
592
            bgWasVisible = true;
593
            bgWidget->hide();
zorglub's avatar
zorglub committed
594
        }
595 596 597 598 599 600 601 602 603 604 605
        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 );
        }
606
//        videoWidget->updateGeometry(); /// FIXME: Needed ?
607 608
        need_components_update = true;
    }
609 610 611 612 613 614
    return ret;
}

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

618
    if( embeddedPlaylistWasActive )
619
        playlistWidget->show();
zorglub's avatar
zorglub committed
620
    else if( bgWidget )
621
        bgWidget->show();
zorglub's avatar
zorglub committed
622

623
    videoIsActive = false;
624
    need_components_update = true;
625 626
}

627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
class SetVideoOnTopQtEvent : public QEvent
{
public:
    SetVideoOnTopQtEvent( bool _onTop ) :
      QEvent( (QEvent::Type)SetVideoOnTopEvent_Type ), onTop( _onTop)
    {
    }

    bool OnTop() const
    {
        return onTop;
    }

private:
    bool onTop;
};

644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
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 );
663
            // videoWidget->updateGeometry();
664 665 666 667 668
            need_components_update = true;
            i_ret = VLC_SUCCESS;
            break;
        }
        case VOUT_SET_STAY_ON_TOP:
669 670 671 672 673 674
        {
            int i_arg = va_arg( args, int );
            QApplication::postEvent( this, new SetVideoOnTopQtEvent( i_arg ) );
            i_ret = VLC_SUCCESS;
            break;
        }
675 676 677 678 679 680 681
        default:
            msg_Warn( p_intf, "unsupported control query" );
            break;
    }
    return i_ret;
}

zorglub's avatar
zorglub committed
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
void MainInterface::advanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        advControlsEnabled = true;
    }
    else
    {
        advControls->hide();
        advControlsEnabled = false;
    }
    doComponentsUpdate();
}

697 698 699 700 701 702 703 704 705
void MainInterface::visual()
{
    if( !VISIBLE( visualSelector) )
    {
        visualSelector->show();
        if( !THEMIM->getIM()->hasVideo() )
        {
            /* Show the background widget */
        }
706
        visualSelectorEnabled = true;
707 708 709 710 711
    }
    else
    {
        /* Stop any currently running visualization */
        visualSelector->hide();
712
        visualSelectorEnabled = false;
713
    }
714
    doComponentsUpdate();
715 716
}

717 718 719 720 721 722 723
void MainInterface::playlist()
{
    // Toggle the playlist dialog
    if( !playlistEmbeddedFlag )
    {
        if( playlistWidget )
        {
724
            /// \todo Destroy it
725 726 727 728 729 730 731 732 733 734 735
        }
        THEDP->playlistDialog();
        return;
    }

    if( !playlistWidget )
    {
        PlaylistDialog::killInstance();
        playlistWidget = new PlaylistWidget( p_intf );
        ui.vboxLayout->insertWidget( 0, playlistWidget );
        playlistWidget->widgetSize = settings->value( "playlistSize",
zorglub's avatar
zorglub committed
736
                                               QSize( 650, 310 ) ).toSize();
737
        playlistWidget->hide();
738 739
        if(bgWidget)
        CONNECT( playlistWidget, artSet( QString ), bgWidget, setArt(QString) );
740
    }
741
    if( VISIBLE( playlistWidget ) )
742 743
    {
        playlistWidget->hide();
744
        if( bgWidget ) bgWidget->show();
745 746
        if( videoIsActive )
        {
747 748 749
            videoWidget->widgetSize = savedVideoSize;
            videoWidget->resize( videoWidget->widgetSize );
            videoWidget->updateGeometry();
750
            if( bgWidget ) bgWidget->hide();
751 752 753 754 755 756
        }
    }
    else
    {
        playlistWidget->show();
        if( videoIsActive )
757 758 759 760 761 762
        {
            savedVideoSize = videoWidget->widgetSize;
            videoWidget->widgetSize.setHeight( 0 );
            videoWidget->resize( videoWidget->widgetSize );
            videoWidget->updateGeometry();
        }
763
        if( VISIBLE( bgWidget ) ) bgWidget->hide();
764
    }
765
    doComponentsUpdate();
766 767
}

zorglub's avatar
zorglub committed
768 769
/* Video widget cannot do this synchronously as it runs in another thread */
/* Well, could it, actually ? Probably dangerous ... */
770 771
void MainInterface::doComponentsUpdate()
{
772 773
    calculateInterfaceSize();
    resize( mainSize );
774 775
}

zorglub's avatar
zorglub committed
776
void MainInterface::undockPlaylist()
777
{
zorglub's avatar
zorglub committed
778
    if( playlistWidget )
779
    {
zorglub's avatar
zorglub committed
780 781
        playlistWidget->hide();
        playlistWidget->deleteLater();
782 783 784
        ui.vboxLayout->removeWidget( playlistWidget );
        playlistWidget = NULL;
        playlistEmbeddedFlag = false;
zorglub's avatar
zorglub committed
785

zorglub's avatar
zorglub committed
786
        menuBar()->clear();
787 788
        QVLCMenu::createMenuBar( this, p_intf, false, advControlsEnabled,
                                 visualSelectorEnabled);
zorglub's avatar
zorglub committed
789 790 791 792 793 794 795 796 797 798

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

        doComponentsUpdate();
        THEDP->playlistDialog();
799
    }
zorglub's avatar
zorglub committed
800 801
}

802 803 804 805 806 807 808
void MainInterface::toggleMenus()
{
    if( menuBar()->isVisible() ) menuBar()->hide();
        else menuBar()->show();
    msg_Dbg( p_intf, "I was there: \\_o<~~ coin coin" );
}

zorglub's avatar
zorglub committed
809 810 811
void MainInterface::customEvent( QEvent *event )
{
    if( event->type() == PLDockEvent_Type )
812 813 814
    {
        PlaylistDialog::killInstance();
        playlistEmbeddedFlag = true;
zorglub's avatar
zorglub committed
815
        menuBar()->clear();
816 817
        QVLCMenu::createMenuBar(this, p_intf, true, advControlsEnabled,
                                visualSelectorEnabled);
818 819
        playlist();
    }
820 821 822 823 824 825
    else if ( event->type() == SetVideoOnTopEvent_Type )
    {
        SetVideoOnTopQtEvent* p_event = (SetVideoOnTopQtEvent*)event;
        if( p_event->OnTop() )
            setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
        else
826
            setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
827 828
        show(); /* necessary to apply window flags?? */
    }
829 830
}

831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856

/************************************************************************
 * D&D
 ************************************************************************/
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 ) {
857 858
            playlist_Add( THEPL, qtu(s), NULL,
                          PLAYLIST_APPEND | (first ? PLAYLIST_GO:0),
859
                          PLAYLIST_END, VLC_TRUE, VLC_FALSE );
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
            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();
}

878 879 880
/************************************************************************
 * Other stuff
 ************************************************************************/
881 882
void MainInterface::keyPressEvent( QKeyEvent *e )
{
883
    int i_vlck = qtEventToVLCKey( e );
884 885
    if( i_vlck >= 0 )
    {
886
        var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
887 888 889 890 891 892
        e->accept();
    }
    else
        e->ignore();
}

893 894
void MainInterface::wheelEvent( QWheelEvent *e )
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
895
    int i_vlckey = qtWheelEventToVLCKey( e );
896 897 898 899
    var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
    e->accept();
}

zorglub's avatar
zorglub committed
900 901
void MainInterface::stop()
{
902
    THEMIM->stop();
zorglub's avatar
zorglub committed
903
}
904

zorglub's avatar
zorglub committed
905 906
void MainInterface::play()
{
zorglub's avatar
zorglub committed
907
    if( playlist_IsEmpty(THEPL) )
908 909
    {
        /* The playlist is empty, open a file requester */
zorglub's avatar
Wtf ?  
zorglub committed
910
        THEDP->openFileDialog();
911 912 913 914
        setStatus( 0 );
        return;
    }
    THEMIM->togglePlayPause();
zorglub's avatar
zorglub committed
915
}
916

zorglub's avatar
zorglub committed
917 918
void MainInterface::prev()
{
919
    THEMIM->prev();
zorglub's avatar
zorglub committed
920
}
921

zorglub's avatar
zorglub committed
922 923
void MainInterface::next()
{
924
    THEMIM->next();
zorglub's avatar
zorglub committed
925 926 927 928 929 930 931 932 933
}

void MainInterface::setDisplay( float pos, int time, int length )
{
    char psz_length[MSTRTIME_MAX_SIZE], psz_time[MSTRTIME_MAX_SIZE];
    secstotimestr( psz_length, length );
    secstotimestr( psz_time, time );
    QString title;
    title.sprintf( "%s/%s", psz_time, psz_length );
934
    timeLabel->setText( " "+title+" " );
zorglub's avatar
zorglub committed
935 936 937 938
}

void MainInterface::setName( QString name )
{
939
    input_name = name;
940
    nameLabel->setText( " " + name+" " );
zorglub's avatar
zorglub committed
941 942
}

943 944
void MainInterface::setStatus( int status )
{
zorglub's avatar
zorglub committed
945
    if( status == 1 ) // Playing
946 947 948
        ui.playButton->setIcon( QIcon( ":/pixmaps/pause.png" ) );
    else
        ui.playButton->setIcon( QIcon( ":/pixmaps/play.png" ) );
949 950
    if( systrayMenu )
        updateSystrayMenu( status );
951 952
}

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
#define HELP_MENU N_("Menu")
#define HELP_PCH N_("Previous chapter")
#define HELP_NCH N_("Next chapter")
#define HELP_PTR N_("Previous track")
#define HELP_NTR N_("Next track")

void MainInterface::setNavigation( int navigation )
{
    // 1 = chapter, 2 = title, 0 = no
    if( navigation == 0 )
    {
        ui.discFrame->hide();
    } else if( navigation == 1 ) {
        ui.prevSectionButton->show();
        ui.prevSectionButton->setToolTip( qfu(HELP_PCH) );
        ui.nextSectionButton->show();
        ui.nextSectionButton->setToolTip( qfu(HELP_NCH) );
        ui.menuButton->show();
        ui.discFrame->show();
    } else {
        ui.prevSectionButton->show();
        ui.prevSectionButton->setToolTip( qfu(HELP_PCH) );
        ui.nextSectionButton->show();
        ui.nextSectionButton->setToolTip( qfu(HELP_NCH) );
        ui.menuButton->hide();
        ui.discFrame->show();
    }
}

zorglub's avatar
zorglub committed
982 983
static bool b_my_volume;