interface_widgets.cpp 37.5 KB
Newer Older
1
/*****************************************************************************
2
 * interface_widgets.cpp : Custom widgets for the main interface
3
 ****************************************************************************
4
 * Copyright ( C ) 2006 the VideoLAN team
5
 * $Id$
6 7
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 *          Jean-Baptiste Kempf <jb@videolan.org>
9
 *          Rafaël Carré <funman@videolanorg>
10
 *          Ilkka Ollakka <ileoo@videolan.org>
11 12 13 14
 *
 * 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
15
 * ( at your option ) any later version.
16 17 18 19 20 21 22 23 24 25
 *
 * 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
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/
26

27 28 29
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
30

31
#include "dialogs_provider.hpp"
32
#include "components/interface_widgets.hpp"
33
#include "main_interface.hpp"
34
#include "input_manager.hpp"
35
#include "menus.hpp"
36
#include "util/input_slider.hpp"
37
#include "util/customwidgets.hpp"
Clément Stenac's avatar
Clément Stenac committed
38
#include <vlc_vout.h>
39

Clément Stenac's avatar
Clément Stenac committed
40 41
#include <QLabel>
#include <QSpacerItem>
Clément Stenac's avatar
Clément Stenac committed
42
#include <QCursor>
Clément Stenac's avatar
Clément Stenac committed
43
#include <QPushButton>
44
#include <QToolButton>
45
#include <QHBoxLayout>
Clément Stenac's avatar
Clément Stenac committed
46
#include <QMenu>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
47 48
#include <QPalette>
#include <QResizeEvent>
49
#include <QDate>
50
#include <QMutexLocker>
51

52 53 54 55
/**********************************************************************
 * Video Widget. A simple frame on which video is drawn
 * This class handles resize issues
 **********************************************************************/
56

57
VideoWidget::VideoWidget( intf_thread_t *_p_i ) : QFrame( NULL ), p_intf( _p_i )
58
{
59
    /* Init */
60
    vlc_mutex_init( &lock );
61
    p_vout = NULL;
62
    handleReady = false;
63
    hide(); setMinimumSize( 16, 16 );
64 65
    videoSize.rwidth() = -1;
    videoSize.rheight() = -1;
66

67 68 69 70 71 72
    /* Black background is more coherent for a Video Widget IMVHO */
    QPalette plt =  palette();
    plt.setColor( QPalette::Active, QPalette::Window , Qt::black );
    plt.setColor( QPalette::Inactive, QPalette::Window , Qt::black );
    setPalette( plt );

73 74 75 76 77 78 79 80
    /* The core can ask through a callback to show the video.
     * NOTE: We need to block the video output core until the window handle
     * is ready for use (otherwise an X11 invalid handle failure may occur).
     * As a side effect, it is illegal to emit askVideoWidgetToShow from
     * the same thread as the Qt4 thread that owns this. */
    QObject::connect( this, SIGNAL(askVideoWidgetToShow()), this, SLOT(show()),
                      Qt::BlockingQueuedConnection );

81 82
    /* The core can ask through a callback to resize the video */
   // CONNECT( this, askResize( int, int ), this, SetSizing( int, int ) );
83 84
}

85 86 87 88 89 90 91
void VideoWidget::paintEvent(QPaintEvent *ev)
{
    QFrame::paintEvent(ev);
    handleReady = true;
    handleWait.wakeAll();
}

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
VideoWidget::~VideoWidget()
{
    vlc_mutex_lock( &lock );
    if( p_vout )
    {
        if( !p_intf->psz_switch_intf )
        {
            if( vout_Control( p_vout, VOUT_CLOSE ) != VLC_SUCCESS )
                vout_Control( p_vout, VOUT_REPARENT );
        }
        else
        {
            if( vout_Control( p_vout, VOUT_REPARENT ) != VLC_SUCCESS )
                vout_Control( p_vout, VOUT_CLOSE );
        }
    }
    vlc_mutex_unlock( &lock );
    vlc_mutex_destroy( &lock );
}

112
/**
113
 * Request the video to avoid the conflicts
114
 **/
115
void *VideoWidget::request( vout_thread_t *p_nvout, int *pi_x, int *pi_y,
116 117
                           unsigned int *pi_width, unsigned int *pi_height )
{
118
    QMutexLocker locker( &handleLock );
119
    msg_Dbg( p_intf, "Video was requested %i, %i", *pi_x, *pi_y );
120
    emit askVideoWidgetToShow();
121 122 123 124 125 126
    if( p_vout )
    {
        msg_Dbg( p_intf, "embedded video already in use" );
        return NULL;
    }
    p_vout = p_nvout;
127 128 129 130 131 132
    while( !handleReady )
    {
        msg_Dbg( p_intf, "embedded video pending (handle %p)", winId() );
        handleWait.wait( &handleLock );
    }
    msg_Dbg( p_intf, "embedded video ready (handle %p)", winId() );
133
    return ( void* )winId();
134 135
}

136
/* Set the Widget to the correct Size */
137 138
/* Function has to be called by the parent
   Parent has to care about resizing himself*/
139
void VideoWidget::SetSizing( unsigned int w, unsigned int h )
140
{
141 142 143 144
    msg_Dbg( p_intf, "Video is resizing to: %i %i", w, h );
    videoSize.rwidth() = w;
    videoSize.rheight() = h;
    updateGeometry(); // Needed for deinterlace
145 146
}

147
void VideoWidget::release( void *p_win )
148
{
149
    msg_Dbg( p_intf, "Video is non needed anymore" );
150
    p_vout = NULL;
151 152 153 154
    videoSize.rwidth() = 0;
    videoSize.rheight() = 0;
    hide();
    updateGeometry(); // Needed for deinterlace
155
}
156

157 158 159 160
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
161

162 163
/**********************************************************************
 * Background Widget. Show a simple image background. Currently,
164
 * it's album art if present or cone.
165
 **********************************************************************/
166 167 168 169
#define ICON_SIZE 128
#define MAX_BG_SIZE 400
#define MIN_BG_SIZE 64

170 171
BackgroundWidget::BackgroundWidget( intf_thread_t *_p_i )
                 :QWidget( NULL ), p_intf( _p_i )
172
{
173
    /* We should use that one to take the more size it can */
174
//    setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
175

176
    /* A dark background */
Clément Stenac's avatar
Clément Stenac committed
177
    setAutoFillBackground( true );
178 179 180 181 182
    plt =  palette();
    plt.setColor( QPalette::Active, QPalette::Window , Qt::black );
    plt.setColor( QPalette::Inactive, QPalette::Window , Qt::black );
    setPalette( plt );

183
    /* A cone in the middle */
184
    label = new QLabel;
185
    label->setMargin( 5 );
186 187
    label->setMaximumHeight( MAX_BG_SIZE );
    label->setMaximumWidth( MAX_BG_SIZE );
188 189
    label->setMinimumHeight( MIN_BG_SIZE );
    label->setMinimumWidth( MIN_BG_SIZE );
190 191 192 193
    if( QDate::currentDate().dayOfYear() >= 354 )
        label->setPixmap( QPixmap( ":/vlc128-christmas.png" ) );
    else
        label->setPixmap( QPixmap( ":/vlc128.png" ) );
194

195 196 197 198
    QGridLayout *backgroundLayout = new QGridLayout( this );
    backgroundLayout->addWidget( label, 0, 1 );
    backgroundLayout->setColumnStretch( 0, 1 );
    backgroundLayout->setColumnStretch( 2, 1 );
199

200
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
201 202
}

Clément Stenac's avatar
Clément Stenac committed
203
BackgroundWidget::~BackgroundWidget()
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
204 205 206
{
}

207 208 209 210 211 212 213 214
void BackgroundWidget::resizeEvent( QResizeEvent * event )
{
    if( event->size().height() <= MIN_BG_SIZE )
        label->hide();
    else
        label->show();
}

215
void BackgroundWidget::updateArt( QString url )
216
{
217
    if( url.isEmpty() )
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
218
    {
219 220 221 222
        if( QDate::currentDate().dayOfYear() >= 354 )
            label->setPixmap( QPixmap( ":/vlc128-christmas.png" ) );
        else
            label->setPixmap( QPixmap( ":/vlc128.png" ) );
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
223 224
        return;
    }
225
    else
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
226
    {
227
        label->setPixmap( QPixmap( url ) );
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
228
    }
229 230
}

231 232 233 234
void BackgroundWidget::contextMenuEvent( QContextMenuEvent *event )
{
    QVLCMenu::PopupMenu( p_intf, true );
}
235

Clément Stenac's avatar
Clément Stenac committed
236 237 238 239
/**********************************************************************
 * Visualization selector panel
 **********************************************************************/
VisualSelector::VisualSelector( intf_thread_t *_p_i ) :
240
                                QFrame( NULL ), p_intf( _p_i )
Clément Stenac's avatar
Clément Stenac committed
241 242
{
    QHBoxLayout *layout = new QHBoxLayout( this );
243
    layout->setMargin( 0 );
Clément Stenac's avatar
Clément Stenac committed
244
    QPushButton *prevButton = new QPushButton( "Prev" );
245
    QPushButton *nextButton = new QPushButton( "Next" );
Clément Stenac's avatar
Clément Stenac committed
246 247
    layout->addWidget( prevButton );
    layout->addWidget( nextButton );
Clément Stenac's avatar
Clément Stenac committed
248 249

    layout->addItem( new QSpacerItem( 40,20,
250 251
                              QSizePolicy::Expanding, QSizePolicy::Minimum ) );
    layout->addWidget( new QLabel( qtr( "Current visualization:" ) ) );
Clément Stenac's avatar
Clément Stenac committed
252 253 254 255 256 257 258

    current = new QLabel( qtr( "None" ) );
    layout->addWidget( current );

    BUTTONACT( prevButton, prev() );
    BUTTONACT( nextButton, next() );

Clément Stenac's avatar
Clément Stenac committed
259
    setLayout( layout );
260
    setMaximumHeight( 35 );
Clément Stenac's avatar
Clément Stenac committed
261 262 263 264 265 266
}

VisualSelector::~VisualSelector()
{
}

Clément Stenac's avatar
Clément Stenac committed
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
void VisualSelector::prev()
{
    char *psz_new = aout_VisualPrev( p_intf );
    if( psz_new )
    {
        current->setText( qfu( psz_new ) );
        free( psz_new );
    }
}

void VisualSelector::next()
{
    char *psz_new = aout_VisualNext( p_intf );
    if( psz_new )
    {
        current->setText( qfu( psz_new ) );
        free( psz_new );
    }
}

/**********************************************************************
288
 * TEH controls
Clément Stenac's avatar
Clément Stenac committed
289
 **********************************************************************/
290 291 292 293 294 295

#define setupSmallButton( aButton ){  \
    aButton->setMaximumSize( QSize( 26, 26 ) ); \
    aButton->setMinimumSize( QSize( 26, 26 ) ); \
    aButton->setIconSize( QSize( 20, 20 ) ); }

296
AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i ) :
Clément Stenac's avatar
Clément Stenac committed
297 298
                                           QFrame( NULL ), p_intf( _p_i )
{
299 300 301
    QHBoxLayout *advLayout = new QHBoxLayout( this );
    advLayout->setMargin( 0 );
    advLayout->setSpacing( 0 );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
302
    advLayout->setAlignment( Qt::AlignBottom );
Clément Stenac's avatar
Clément Stenac committed
303

304
    /* A to B Button */
305
    ABButton = new QPushButton( "AB" );
Lukas Durfina's avatar
Lukas Durfina committed
306
    setupSmallButton( ABButton );
307
    advLayout->addWidget( ABButton );
308
    BUTTON_SET_ACT( ABButton, "AB", qtr( "A to B" ), fromAtoB() );
309
    timeA = timeB = 0;
310 311
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
             this, AtoBLoop( float, int, int ) );
312
#if 0
313 314 315 316 317
    frameButton = new QPushButton( "Fr" );
    frameButton->setMaximumSize( QSize( 26, 26 ) );
    frameButton->setIconSize( QSize( 20, 20 ) );
    advLayout->addWidget( frameButton );
    BUTTON_SET_ACT( frameButton, "Fr", qtr( "Frame by Frame" ), frame() );
318
#endif
319 320

    recordButton = new QPushButton( "R" );
Lukas Durfina's avatar
Lukas Durfina committed
321
    setupSmallButton( recordButton );
322
    advLayout->addWidget( recordButton );
323
    BUTTON_SET_ACT_I( recordButton, "", record_16px.png,
324
            qtr( "Record" ), record() );
325

326
    /* Snapshot Button */
327
    snapshotButton = new QPushButton( "S" );
Lukas Durfina's avatar
Lukas Durfina committed
328
    setupSmallButton( snapshotButton );
329 330
    advLayout->addWidget( snapshotButton );
    BUTTON_SET_ACT( snapshotButton, "S", qtr( "Take a snapshot" ), snapshot() );
Clément Stenac's avatar
Clément Stenac committed
331 332
}

333
AdvControlsWidget::~AdvControlsWidget()
334
{}
Clément Stenac's avatar
Clément Stenac committed
335

336
void AdvControlsWidget::enableInput( bool enable )
Clément Stenac's avatar
Clément Stenac committed
337
{
338 339
    ABButton->setEnabled( enable );
    recordButton->setEnabled( enable );
Clément Stenac's avatar
Clément Stenac committed
340
}
341

342
void AdvControlsWidget::enableVideo( bool enable )
Clément Stenac's avatar
Clément Stenac committed
343 344
{
    snapshotButton->setEnabled( enable );
345
#if 0
346
    frameButton->setEnabled( enable );
347
#endif
Clément Stenac's avatar
Clément Stenac committed
348 349
}

350
void AdvControlsWidget::snapshot()
Clément Stenac's avatar
Clément Stenac committed
351
{
352 353
    vout_thread_t *p_vout =
        (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
354
    if( p_vout ) vout_Control( p_vout, VOUT_SNAPSHOT );
Clément Stenac's avatar
Clément Stenac committed
355 356
}

357
/* Function called when the button is clicked() */
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
void AdvControlsWidget::fromAtoB()
{
    if( !timeA )
    {
        timeA = var_GetTime( THEMIM->getInput(), "time"  );
        ABButton->setText( "A->..." );
        return;
    }
    if( !timeB )
    {
        timeB = var_GetTime( THEMIM->getInput(), "time"  );
        var_SetTime( THEMIM->getInput(), "time" , timeA );
        ABButton->setText( "A<=>B" );
        return;
    }
    timeA = 0;
    timeB = 0;
    ABButton->setText( "AB" );
}
377

378
/* Function called regularly when in an AtoB loop */
379 380 381 382
void AdvControlsWidget::AtoBLoop( float f_pos, int i_time, int i_length )
{
    if( timeB )
    {
383
        if( i_time >= (int)(timeB/1000000) )
384 385 386
            var_SetTime( THEMIM->getInput(), "time" , timeA );
    }
}
387

388
/* FIXME Record function */
389
void AdvControlsWidget::record(){}
390

391
#if 0
392
//FIXME Frame by frame function
393
void AdvControlsWidget::frame(){}
394
#endif
395

396 397 398
/*****************************
 * DA Control Widget !
 *****************************/
399
ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
400
                                MainInterface *_p_mi,
401
                                bool b_advControls,
Lukas Durfina's avatar
Lukas Durfina committed
402 403 404
                                bool b_shiny,
                                bool b_fsCreation) :
                                QFrame( _p_mi ), p_intf( _p_i )
405
{
Lukas Durfina's avatar
Lukas Durfina committed
406 407
    controlLayout = new QGridLayout( );

408
    controlLayout->setSpacing( 0 );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
409
    controlLayout->setLayoutMargins( 7, 5, 7, 3, 6 );
410

Lukas Durfina's avatar
Lukas Durfina committed
411 412 413
    if( !b_fsCreation )
        setLayout( controlLayout );

414
    setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
415

416 417
    /** The main Slider **/
    slider = new InputSlider( Qt::Horizontal, NULL );
418
    controlLayout->addWidget( slider, 0, 1, 1, 16 );
419 420
    /* Update the position when the IM has changed */
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
421
             slider, setPosition( float, int, int ) );
422 423 424 425
    /* And update the IM, when the position has changed */
    CONNECT( slider, sliderDragged( float ),
             THEMIM->getIM(), sliderUpdate( float ) );

426
    /** Slower and faster Buttons **/
427 428
    slowerButton = new QToolButton;
    slowerButton->setAutoRaise( true );
429
    slowerButton->setMaximumSize( QSize( 26, 20 ) );
430

431
    BUTTON_SET_ACT( slowerButton, "-", qtr( "Slower" ), slower() );
432 433
    controlLayout->addWidget( slowerButton, 0, 0 );

434 435
    fasterButton = new QToolButton;
    fasterButton->setAutoRaise( true );
436
    fasterButton->setMaximumSize( QSize( 26, 20 ) );
437

438
    BUTTON_SET_ACT( fasterButton, "+", qtr( "Faster" ), faster() );
439
    controlLayout->addWidget( fasterButton, 0, 17 );
440

441 442 443 444
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

    advControls = new AdvControlsWidget( p_intf );
445
    controlLayout->addWidget( advControls, 1, 3, 2, 4, Qt::AlignBottom );
446 447
    if( !b_advancedVisible ) advControls->hide();

448
    /** Disc and Menus handling */
449
    discFrame = new QWidget( this );
450

451 452 453
    QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
    discLayout->setSpacing( 0 );
    discLayout->setMargin( 0 );
454

455
    prevSectionButton = new QPushButton( discFrame );
456
    setupSmallButton( prevSectionButton );
457 458
    discLayout->addWidget( prevSectionButton );

459
    menuButton = new QPushButton( discFrame );
460 461 462
    setupSmallButton( menuButton );
    discLayout->addWidget( menuButton );

463
    nextSectionButton = new QPushButton( discFrame );
464
    setupSmallButton( nextSectionButton );
465 466
    discLayout->addWidget( nextSectionButton );

467
    controlLayout->addWidget( discFrame, 1, 10, 2, 3, Qt::AlignBottom );
468 469 470 471 472

    BUTTON_SET_IMG( prevSectionButton, "", previous.png, "" );
    BUTTON_SET_IMG( nextSectionButton, "", next.png, "" );
    BUTTON_SET_IMG( menuButton, "", previous.png, "" );

473
    discFrame->hide();
474 475 476

    /* Change the navigation button display when the IM navigation changes */
    CONNECT( THEMIM->getIM(), navigationChanged( int ),
477
             this, setNavigation( int ) );
478 479 480 481 482 483 484
    /* Changes the IM navigation when triggered on the nav buttons */
    CONNECT( prevSectionButton, clicked(), THEMIM->getIM(),
             sectionPrev() );
    CONNECT( nextSectionButton, clicked(), THEMIM->getIM(),
             sectionNext() );
    CONNECT( menuButton, clicked(), THEMIM->getIM(),
             sectionMenu() );
485

486
    /**
487
     * Telextext QFrame
488
     * TODO: Merge with upper menu in a StackLayout
489
     **/
490 491 492 493 494
    telexFrame = new QWidget( this );
    QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame );
    telexLayout->setSpacing( 0 );
    telexLayout->setMargin( 0 );

495
    QPushButton  *telexOn = new QPushButton;
496 497 498
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

499
    telexTransparent = new QPushButton;
500 501
    setupSmallButton( telexTransparent );
    telexLayout->addWidget( telexTransparent );
502
    b_telexTransparent = false;
503

504
    telexPage = new QSpinBox;
505
    telexPage->setRange( 0, 999 );
506
    telexPage->setValue( 100 );
507 508
    telexPage->setAccelerated( true );
    telexPage->setWrapping( true );
509
    telexPage->setAlignment( Qt::AlignRight );
510
    telexPage->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
511 512
    telexLayout->addWidget( telexPage );

513
    controlLayout->addWidget( telexFrame, 1, 10, 2, 4, Qt::AlignBottom );
514
    telexFrame->hide(); /* default hidden */
515 516 517

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
518 519 520

    BUTTON_SET_ACT_I( telexOn, "", tv.png, qtr( "Teletext on" ),
                      toggleTeletext() );
521 522
    CONNECT( telexOn, clicked( bool ), THEMIM->getIM(),
             telexToggle( bool ) );
523 524 525 526 527
    telexTransparent->setEnabled( false );
    telexPage->setEnabled( false );

    BUTTON_SET_ACT_I( telexTransparent, "", tvtelx.png, qtr( "Teletext" ),
                      toggleTeletextTransparency() );
528
    CONNECT( telexTransparent, clicked( bool ),
529
             THEMIM->getIM(), telexSetTransparency() );
530 531
    CONNECT( THEMIM->getIM(), teletextEnabled( bool ),
             telexFrame, setVisible( bool ) );
532

533
    /** Play Buttons **/
534
    QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
535 536 537 538
    sizePolicy.setHorizontalStretch( 0 );
    sizePolicy.setVerticalStretch( 0 );

    /* Play */
539
    playButton = new QPushButton;
540
    playButton->setSizePolicy( sizePolicy );
541 542
    playButton->setMaximumSize( QSize( 36, 36 ) );
    playButton->setMinimumSize( QSize( 36, 36 ) );
543
    playButton->setIconSize( QSize( 30, 30 ) );
544

545
    controlLayout->addWidget( playButton, 2, 0, 2, 2 );
546

547 548
    controlLayout->setColumnMinimumWidth( 2, 20 );
    controlLayout->setColumnStretch( 2, 0 );
549 550

    /** Prev + Stop + Next Block **/
Lukas Durfina's avatar
Lukas Durfina committed
551
    controlButLayout = new QHBoxLayout;
552 553 554 555 556
    controlButLayout->setSpacing( 0 ); /* Don't remove that, will be useful */

    /* Prev */
    QPushButton *prevButton = new QPushButton;
    prevButton->setSizePolicy( sizePolicy );
557
    setupSmallButton( prevButton );
558 559 560 561 562 563

    controlButLayout->addWidget( prevButton );

    /* Stop */
    QPushButton *stopButton = new QPushButton;
    stopButton->setSizePolicy( sizePolicy );
564
    setupSmallButton( stopButton );
565 566 567 568 569 570

    controlButLayout->addWidget( stopButton );

    /* next */
    QPushButton *nextButton = new QPushButton;
    nextButton->setSizePolicy( sizePolicy );
571
    setupSmallButton( nextButton );
572 573 574 575

    controlButLayout->addWidget( nextButton );

    /* Add this block to the main layout */
Lukas Durfina's avatar
Lukas Durfina committed
576 577
    if( !b_fsCreation )
        controlLayout->addLayout( controlButLayout, 3, 3, 1, 3 );
578

579
    BUTTON_SET_ACT_I( playButton, "", play.png, qtr( "Play" ), play() );
580
    BUTTON_SET_ACT_I( prevButton, "" , previous.png,
581 582 583
                      qtr( "Previous" ), prev() );
    BUTTON_SET_ACT_I( nextButton, "", next.png, qtr( "Next" ), next() );
    BUTTON_SET_ACT_I( stopButton, "", stop.png, qtr( "Stop" ), stop() );
584

585 586 587 588
    controlLayout->setColumnMinimumWidth( 7, 20 );
    controlLayout->setColumnStretch( 7, 0 );
    controlLayout->setColumnStretch( 8, 0 );
    controlLayout->setColumnStretch( 9, 0 );
589

590 591 592
    /*
     * Other first Line buttons
     */
593 594 595
    /** Fullscreen/Visualisation **/
    fullscreenButton = new QPushButton( "F" );
    BUTTON_SET_ACT( fullscreenButton, "F", qtr( "Fullscreen" ), fullscreen() );
596
    setupSmallButton( fullscreenButton );
597
    controlLayout->addWidget( fullscreenButton, 3, 10, Qt::AlignBottom );
598

599 600
    /** Playlist Button **/
    playlistButton = new QPushButton;
601
    setupSmallButton( playlistButton );
602
    controlLayout->addWidget( playlistButton, 3, 11, Qt::AlignBottom );
603
    BUTTON_SET_IMG( playlistButton, "" , playlist.png, qtr( "Show playlist" ) );
604
    CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );
605 606

    /** extended Settings **/
Lukas Durfina's avatar
Lukas Durfina committed
607
    extSettingsButton = new QPushButton;
608
    BUTTON_SET_ACT( extSettingsButton, "Ex", qtr( "Extended Settings" ),
609
            extSettings() );
610
    setupSmallButton( extSettingsButton );
611
    controlLayout->addWidget( extSettingsButton, 3, 12, Qt::AlignBottom );
612

613
    controlLayout->setColumnStretch( 13, 0 );
614
    controlLayout->setColumnMinimumWidth( 13, 24 );
615
    controlLayout->setColumnStretch( 14, 5 );
616

617
    /* Volume */
Lukas Durfina's avatar
Lukas Durfina committed
618
    hVolLabel = new VolumeClickHandler( p_intf, this );
619

620
    volMuteLabel = new QLabel;
621
    volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
622
    volMuteLabel->setToolTip( qtr( "Mute" ) );
623
    volMuteLabel->installEventFilter( hVolLabel );
624
    controlLayout->addWidget( volMuteLabel, 3, 15, Qt::AlignBottom );
625

626 627 628
    if( b_shiny )
    {
        volumeSlider = new SoundSlider( this,
629
            config_GetInt( p_intf, "volume-step" ),
630 631
            config_GetInt( p_intf, "qt-volume-complete" ),
            config_GetPsz( p_intf, "qt-slider-colours" ) );
632 633 634 635 636 637
    }
    else
    {
        volumeSlider = new QSlider( this );
        volumeSlider->setOrientation( Qt::Horizontal );
    }
638
    volumeSlider->setMaximumSize( QSize( 200, 40 ) );
639
    volumeSlider->setMinimumSize( QSize( 106, 30 ) );
640
    volumeSlider->setFocusPolicy( Qt::NoFocus );
641
    controlLayout->addWidget( volumeSlider, 2, 16, 2 , 2, Qt::AlignBottom );
642

643
    /* Set the volume from the config */
644 645
    volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
                              VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
646

647 648 649
    /* Force the update at build time in order to have a muted icon if needed */
    updateVolume( volumeSlider->value() );

650 651
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
652
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
653 654

    updateInput();
655
}
656

657
ControlsWidget::~ControlsWidget()
658
{}
659

660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
void ControlsWidget::toggleTeletext()
{
    bool b_enabled = THEMIM->teletextState();
    if( b_telexEnabled )
    {
        telexTransparent->setEnabled( false );
        telexPage->setEnabled( false );
        b_telexEnabled = false;
    }
    else if( b_enabled )
    {
        telexTransparent->setEnabled( true );
        telexPage->setEnabled( true );
        b_telexEnabled = true;
    }
}

void ControlsWidget::toggleTeletextTransparency()
{
    if( b_telexTransparent )
    {
        telexTransparent->setIcon( QIcon( ":/pixmaps/tvtelx.png" ) );
        telexTransparent->setToolTip( qtr( "Teletext" ) );
        b_telexTransparent = false;
    }
    else
    {
        telexTransparent->setIcon( QIcon( ":/pixmaps/tvtelx-transparent.png" ) );
        telexTransparent->setToolTip( qtr( "Transparent" ) );
        b_telexTransparent = true;
    }
}

693 694 695 696 697 698 699
void ControlsWidget::stop()
{
    THEMIM->stop();
}

void ControlsWidget::play()
{
700
    if( THEPL->current.i_size == 0 )
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
    {
        /* The playlist is empty, open a file requester */
        THEDP->openFileDialog();
        setStatus( 0 );
        return;
    }
    THEMIM->togglePlayPause();
}

void ControlsWidget::prev()
{
    THEMIM->prev();
}

void ControlsWidget::next()
{
    THEMIM->next();
}

void ControlsWidget::setNavigation( int navigation )
{
722 723 724 725 726
#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" )
727 728 729 730 731 732

    // 1 = chapter, 2 = title, 0 = no
    if( navigation == 0 )
    {
        discFrame->hide();
    } else if( navigation == 1 ) {
733 734
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
735 736 737
        menuButton->show();
        discFrame->show();
    } else {
738 739
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
740 741 742 743 744 745
        menuButton->hide();
        discFrame->show();
    }
}

static bool b_my_volume;
746
void ControlsWidget::updateVolume( int i_sliderVolume )
747 748 749
{
    if( !b_my_volume )
    {
750
        int i_res = i_sliderVolume  * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX;
751 752
        aout_VolumeSet( p_intf, i_res );
    }
753 754
    if( i_sliderVolume == 0 )
        volMuteLabel->setPixmap( QPixmap(":/pixmaps/volume-muted.png" ) );
755
    else if( i_sliderVolume < VOLUME_MAX / 3 )
756
        volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-low.png" ) );
757 758 759
    else if( i_sliderVolume > (VOLUME_MAX * 2 / 3 ) )
        volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-high.png" ) );
    else volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
760 761
}

762
void ControlsWidget::updateVolume()
763
{
764
    /* Audio part */
765 766
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
767
    i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
768 769 770 771 772 773 774 775
    int i_gauge = volumeSlider->value();
    b_my_volume = false;
    if( i_volume - i_gauge > 1 || i_gauge - i_volume > 1 )
    {
        b_my_volume = true;
        volumeSlider->setValue( i_volume );
        b_my_volume = false;
    }
776
}
777

778 779
void ControlsWidget::updateInput()
{
780
    /* Activate the interface buttons according to the presence of the input */
781
    enableInput( THEMIM->getIM()->hasInput() );
782
    enableVideo( THEMIM->getIM()->hasVideo() && THEMIM->getIM()->hasInput() );
783
}
784

785 786
void ControlsWidget::setStatus( int status )
{
787 788
    if( status == PLAYING_S ) /* Playing */
    {
789
        playButton->setIcon( QIcon( ":/pixmaps/pause.png" ) );
790 791
        playButton->setToolTip( qtr( "Pause" ) );
    }
792
    else
793
    {
794
        playButton->setIcon( QIcon( ":/pixmaps/play.png" ) );
795 796
        playButton->setToolTip( qtr( "Play" ) );
    }
797
}
798

799 800
/**
 * TODO
801
 * This functions toggle the fullscreen mode
802
 * If there is no video, it should first activate Visualisations...
803
 *  This has also to be fixed in enableVideo()
804
 */
Clément Stenac's avatar
Clément Stenac committed
805 806
void ControlsWidget::fullscreen()
{
807 808
    vout_thread_t *p_vout =
        (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
809
    if( p_vout)
810
    {
811
        var_SetBool( p_vout, "fullscreen", !var_GetBool( p_vout, "fullscreen" ) );
812
        vlc_object_release( p_vout );
813
    }
814 815 816 817 818 819
}

void ControlsWidget::extSettings()
{
    THEDP->extendedDialog();
}
Clément Stenac's avatar
Clément Stenac committed
820

821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
void ControlsWidget::slower()
{
    THEMIM->getIM()->slower();
}

void ControlsWidget::faster()
{
    THEMIM->getIM()->faster();
}

void ControlsWidget::enableInput( bool enable )
{
    slowerButton->setEnabled( enable );
    slider->setEnabled( enable );
    fasterButton->setEnabled( enable );
836 837 838

    /* Advanced Buttons too */
    advControls->enableInput( enable );
839 840
}

841
void ControlsWidget::enableVideo( bool enable )
842
{
843 844
    // TODO Later make the fullscreenButton toggle Visualisation and so on.
    fullscreenButton->setEnabled( enable );
845 846 847

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
848 849
}

850 851 852 853 854 855 856 857 858 859 860 861
void ControlsWidget::toggleAdvanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        b_advancedVisible = true;
    }
    else
    {
        advControls->hide();
        b_advancedVisible = false;
    }
862
    emit advancedControlsToggled( b_advancedVisible );
863
}
864

865

Lukas Durfina's avatar
Lukas Durfina committed
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
/**********************************************************************
 * Fullscrenn control widget
 **********************************************************************/
FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i,
        MainInterface *_p_mi, bool b_advControls, bool b_shiny )
        : ControlsWidget( _p_i, _p_mi, b_advControls, b_shiny, true ),
        i_lastPosX( -1 ), i_lastPosY( -1 ), i_hideTimeout( 1 ),
        b_mouseIsOver( false )
{
    setWindowFlags( Qt::ToolTip );

    setFrameShape( QFrame::StyledPanel );
    setFrameStyle( QFrame::Sunken );
    setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );

    QGridLayout *fsLayout = new QGridLayout( this );
    controlLayout->setSpacing( 0 );