interface_widgets.cpp 37.7 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 51 52 53
#ifdef Q_WS_X11
# include <X11/Xlib.h>
# include <qx11info_x11.h>
#endif
54

55 56 57 58
/**********************************************************************
 * Video Widget. A simple frame on which video is drawn
 * This class handles resize issues
 **********************************************************************/
59

60
VideoWidget::VideoWidget( intf_thread_t *_p_i ) : QFrame( NULL ), p_intf( _p_i )
61
{
62
    /* Init */
63
    p_vout = NULL;
64
    hide(); setMinimumSize( 16, 16 );
65 66
    videoSize.rwidth() = -1;
    videoSize.rheight() = -1;
67
    setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
68

69 70 71 72 73
    /* 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 );
74
    setAttribute( Qt::WA_PaintOnScreen, true );
75

76
    /* The core can ask through a callback to show the video. */
77
#if HAS_QT43
78 79 80
    connect( this, SIGNAL(askVideoWidgetToShow( unsigned int, unsigned int)),
             this, SLOT(SetSizing(unsigned int, unsigned int )),
             Qt::BlockingQueuedConnection );
81 82 83 84 85 86 87
#else
#error This is broken. Fix it with a QEventLoop with a processEvents () 
    connect( this, SIGNAL(askVideoWidgetToShow( unsigned int, unsigned int)),
             this, SLOT(SetSizing(unsigned int, unsigned int )) );
#endif


88 89
}

90 91 92
void VideoWidget::paintEvent(QPaintEvent *ev)
{
    QFrame::paintEvent(ev);
93 94 95
#ifdef Q_WS_X11
    XFlush( QX11Info::display() );
#endif
96 97
}

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
VideoWidget::~VideoWidget()
{
    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 );
        }
    }
}

115
/**
116
 * Request the video to avoid the conflicts
117
 **/
118
void *VideoWidget::request( vout_thread_t *p_nvout, int *pi_x, int *pi_y,
119 120
                           unsigned int *pi_width, unsigned int *pi_height )
{
121
    msg_Dbg( p_intf, "Video was requested %i, %i", *pi_x, *pi_y );
122
    emit askVideoWidgetToShow( *pi_width, *pi_height );
123 124 125 126 127 128
    if( p_vout )
    {
        msg_Dbg( p_intf, "embedded video already in use" );
        return NULL;
    }
    p_vout = p_nvout;
129
    msg_Dbg( p_intf, "embedded video ready (handle %p)", winId() );
130
    return ( void* )winId();
131 132
}

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

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

155 156 157 158
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
159

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

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

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

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

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

198
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
199 200
}

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

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

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

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

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

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

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

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

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

VisualSelector::~VisualSelector()
{
}

Clément Stenac's avatar
Clément Stenac committed
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
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 );
    }
}

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

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

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

302
    /* A to B Button */
303
    ABButton = new QPushButton( "AB" );
Lukas Durfina's avatar
Lukas Durfina committed
304
    setupSmallButton( ABButton );
305
    advLayout->addWidget( ABButton );
306
    BUTTON_SET_ACT( ABButton, "AB", qtr( "A to B" ), fromAtoB() );
307
    timeA = timeB = 0;
308 309
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
             this, AtoBLoop( float, int, int ) );
310
#if 0
311 312 313 314 315
    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() );
316
#endif
317 318

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

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

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

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

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

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

355
/* Function called when the button is clicked() */
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
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" );
}
375

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

386
/* FIXME Record function */
387
void AdvControlsWidget::record(){}
388

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

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

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

Lukas Durfina's avatar
Lukas Durfina committed
409 410 411
    if( !b_fsCreation )
        setLayout( controlLayout );

412
    setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
413

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

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

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

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

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

439 440 441 442
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

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

446
    /** Disc and Menus handling */
447
    discFrame = new QWidget( this );
448

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

453
    prevSectionButton = new QPushButton( discFrame );
454
    setupSmallButton( prevSectionButton );
455 456
    discLayout->addWidget( prevSectionButton );

457
    menuButton = new QPushButton( discFrame );
458 459 460
    setupSmallButton( menuButton );
    discLayout->addWidget( menuButton );

461
    nextSectionButton = new QPushButton( discFrame );
462
    setupSmallButton( nextSectionButton );
463 464
    discLayout->addWidget( nextSectionButton );

465
    controlLayout->addWidget( discFrame, 1, 10, 2, 3, Qt::AlignBottom );
466 467 468

    BUTTON_SET_IMG( prevSectionButton, "", previous.png, "" );
    BUTTON_SET_IMG( nextSectionButton, "", next.png, "" );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
469
    BUTTON_SET_IMG( menuButton, "", previous.png, qtr( "Menu" ) );
470

471
    discFrame->hide();
472 473 474

    /* Change the navigation button display when the IM navigation changes */
    CONNECT( THEMIM->getIM(), navigationChanged( int ),
475
             this, setNavigation( int ) );
476 477 478 479 480 481 482
    /* 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() );
483

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

Lukas Durfina's avatar
Lukas Durfina committed
493
    telexOn = new QPushButton;
494 495 496
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

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

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

Lukas Durfina's avatar
Lukas Durfina committed
511 512
    if( !b_fsCreation )
        controlLayout->addWidget( telexFrame, 1, 10, 2, 4, Qt::AlignBottom );
513
    telexFrame->hide(); /* default hidden */
514 515 516

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
Lukas Durfina's avatar
Lukas Durfina committed
517 518 519 520
    CONNECT( THEMIM->getIM(), setNewTelexPage( int ),
              telexPage, setValue( int ) );

    BUTTON_SET_IMG( telexOn, "", tv.png, qtr( "Teletext on" ) );
521

Lukas Durfina's avatar
Lukas Durfina committed
522 523
    CONNECT( telexOn, clicked(), THEMIM->getIM(),
             telexToggleButtons() );
524 525
    CONNECT( telexOn, clicked( bool ), THEMIM->getIM(),
             telexToggle( bool ) );
Lukas Durfina's avatar
Lukas Durfina committed
526 527 528
    CONNECT( THEMIM->getIM(), toggleTelexButtons(),
              this, toggleTeletext() );
    b_telexEnabled = false;
529 530 531
    telexTransparent->setEnabled( false );
    telexPage->setEnabled( false );

Lukas Durfina's avatar
Lukas Durfina committed
532
    BUTTON_SET_IMG( telexTransparent, "", tvtelx.png, qtr( "Teletext" ) );
533
    CONNECT( telexTransparent, clicked( bool ),
534
             THEMIM->getIM(), telexSetTransparency() );
Lukas Durfina's avatar
Lukas Durfina committed
535 536
    CONNECT( THEMIM->getIM(), toggleTelexTransparency(),
              this, toggleTeletextTransparency() );
537 538
    CONNECT( THEMIM->getIM(), teletextEnabled( bool ),
             telexFrame, setVisible( bool ) );
539

540
    /** Play Buttons **/
541
    QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
542 543 544 545
    sizePolicy.setHorizontalStretch( 0 );
    sizePolicy.setVerticalStretch( 0 );

    /* Play */
546
    playButton = new QPushButton;
547
    playButton->setSizePolicy( sizePolicy );
548 549
    playButton->setMaximumSize( QSize( 36, 36 ) );
    playButton->setMinimumSize( QSize( 36, 36 ) );
550
    playButton->setIconSize( QSize( 30, 30 ) );
551

552
    controlLayout->addWidget( playButton, 2, 0, 2, 2 );
553

554 555
    controlLayout->setColumnMinimumWidth( 2, 20 );
    controlLayout->setColumnStretch( 2, 0 );
556 557

    /** Prev + Stop + Next Block **/
Lukas Durfina's avatar
Lukas Durfina committed
558
    controlButLayout = new QHBoxLayout;
559 560 561 562 563
    controlButLayout->setSpacing( 0 ); /* Don't remove that, will be useful */

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

    controlButLayout->addWidget( prevButton );

    /* Stop */
    QPushButton *stopButton = new QPushButton;
    stopButton->setSizePolicy( sizePolicy );
571
    setupSmallButton( stopButton );
572 573 574 575 576 577

    controlButLayout->addWidget( stopButton );

    /* next */
    QPushButton *nextButton = new QPushButton;
    nextButton->setSizePolicy( sizePolicy );
578
    setupSmallButton( nextButton );
579 580 581 582

    controlButLayout->addWidget( nextButton );

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

586
    BUTTON_SET_ACT_I( playButton, "", play.png, qtr( "Play" ), play() );
587
    BUTTON_SET_ACT_I( prevButton, "" , previous.png,
588 589 590
                      qtr( "Previous" ), prev() );
    BUTTON_SET_ACT_I( nextButton, "", next.png, qtr( "Next" ), next() );
    BUTTON_SET_ACT_I( stopButton, "", stop.png, qtr( "Stop" ), stop() );
591

592 593 594 595
    controlLayout->setColumnMinimumWidth( 7, 20 );
    controlLayout->setColumnStretch( 7, 0 );
    controlLayout->setColumnStretch( 8, 0 );
    controlLayout->setColumnStretch( 9, 0 );
596

597 598 599
    /*
     * Other first Line buttons
     */
600 601 602
    /** Fullscreen/Visualisation **/
    fullscreenButton = new QPushButton( "F" );
    BUTTON_SET_ACT( fullscreenButton, "F", qtr( "Fullscreen" ), fullscreen() );
603
    setupSmallButton( fullscreenButton );
604
    controlLayout->addWidget( fullscreenButton, 3, 10, Qt::AlignBottom );
605

606 607
    /** Playlist Button **/
    playlistButton = new QPushButton;
608
    setupSmallButton( playlistButton );
609
    controlLayout->addWidget( playlistButton, 3, 11, Qt::AlignBottom );
610
    BUTTON_SET_IMG( playlistButton, "" , playlist.png, qtr( "Show playlist" ) );
611
    CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );
612 613

    /** extended Settings **/
Lukas Durfina's avatar
Lukas Durfina committed
614
    extSettingsButton = new QPushButton;
615
    BUTTON_SET_ACT( extSettingsButton, "Ex", qtr( "Extended Settings" ),
616
            extSettings() );
617
    setupSmallButton( extSettingsButton );
618
    controlLayout->addWidget( extSettingsButton, 3, 12, Qt::AlignBottom );
619

620
    controlLayout->setColumnStretch( 13, 0 );
621
    controlLayout->setColumnMinimumWidth( 13, 24 );
622
    controlLayout->setColumnStretch( 14, 5 );
623

624
    /* Volume */
Lukas Durfina's avatar
Lukas Durfina committed
625
    hVolLabel = new VolumeClickHandler( p_intf, this );
626

627
    volMuteLabel = new QLabel;
628
    volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
629
    volMuteLabel->setToolTip( qtr( "Mute" ) );
630
    volMuteLabel->installEventFilter( hVolLabel );
631
    controlLayout->addWidget( volMuteLabel, 3, 15, Qt::AlignBottom );
632

633 634 635
    if( b_shiny )
    {
        volumeSlider = new SoundSlider( this,
636
            config_GetInt( p_intf, "volume-step" ),
637 638
            config_GetInt( p_intf, "qt-volume-complete" ),
            config_GetPsz( p_intf, "qt-slider-colours" ) );
639 640 641 642 643 644
    }
    else
    {
        volumeSlider = new QSlider( this );
        volumeSlider->setOrientation( Qt::Horizontal );
    }
645
    volumeSlider->setMaximumSize( QSize( 200, 40 ) );
646
    volumeSlider->setMinimumSize( QSize( 106, 30 ) );
647
    volumeSlider->setFocusPolicy( Qt::NoFocus );
648
    controlLayout->addWidget( volumeSlider, 2, 16, 2 , 2, Qt::AlignBottom );
649

650
    /* Set the volume from the config */
651 652
    volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
                              VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
653

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

657 658
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
659
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
660 661

    updateInput();
662
}
663

664
ControlsWidget::~ControlsWidget()
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 693 694 695 696 697 698 699
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;
    }
}

700 701 702 703 704 705 706
void ControlsWidget::stop()
{
    THEMIM->stop();
}

void ControlsWidget::play()
{
707
    if( THEPL->current.i_size == 0 )
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
    {
        /* 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 )
{
729 730
#define HELP_PCH N_( "Previous chapter" )
#define HELP_NCH N_( "Next chapter" )
731 732 733 734 735 736

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

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

766
void ControlsWidget::updateVolume()
767
{
768
    /* Audio part */
769 770
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
771
    i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
772 773 774 775 776 777 778 779
    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;
    }
780
}
781

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

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

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

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

825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
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 );
840 841 842

    /* Advanced Buttons too */
    advControls->enableInput( enable );
843 844
}

845
void ControlsWidget::enableVideo( bool enable )
846
{
847 848
    // TODO Later make the fullscreenButton toggle Visualisation and so on.
    fullscreenButton->setEnabled( enable );
849 850 851

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
852 853
}