interface_widgets.cpp 37.9 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
    i_vout = 0;
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
VideoWidget::~VideoWidget()
{
100 101 102
    vout_thread_t *p_vout = i_vout
        ? (vout_thread_t *)vlc_object_get( i_vout ) : NULL;

103 104 105 106 107 108 109 110 111 112 113 114
    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
        vlc_object_release( p_vout );
116 117 118
    }
}

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

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

149
void VideoWidget::release( void *p_win )
150
{
Rémi Denis-Courmont's avatar
Typo  
Rémi Denis-Courmont committed
151
    msg_Dbg( p_intf, "Video is not needed anymore" );
152
    i_vout = 0;
153 154 155 156
    videoSize.rwidth() = 0;
    videoSize.rheight() = 0;
    hide();
    updateGeometry(); // Needed for deinterlace
157
}
158

159 160 161 162
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
163

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

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

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

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

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

202
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
203 204
}

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

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

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

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

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

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

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

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

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

VisualSelector::~VisualSelector()
{
}

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

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

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

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

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

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

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

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

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

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

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

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

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

390
/* FIXME Record function */
391
void AdvControlsWidget::record(){}
392

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

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

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

Lukas Durfina's avatar
Lukas Durfina committed
413 414 415
    if( !b_fsCreation )
        setLayout( controlLayout );

416
    setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
417

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

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

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

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

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

443 444 445 446
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

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

450
    /** Disc and Menus handling */
451
    discFrame = new QWidget( this );
452

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

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

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

465
    nextSectionButton = new QPushButton( discFrame );
466
    setupSmallButton( nextSectionButton );
467 468
    discLayout->addWidget( nextSectionButton );

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

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

475
    discFrame->hide();
476 477 478

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

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

Lukas Durfina's avatar
Lukas Durfina committed
497
    telexOn = new QPushButton;
498 499 500
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

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

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

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

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
Lukas Durfina's avatar
Lukas Durfina committed
521 522 523 524
    CONNECT( THEMIM->getIM(), setNewTelexPage( int ),
              telexPage, setValue( int ) );

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

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

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

544
    /** Play Buttons **/
545
    QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
546 547 548 549
    sizePolicy.setHorizontalStretch( 0 );
    sizePolicy.setVerticalStretch( 0 );

    /* Play */
550
    playButton = new QPushButton;
551
    playButton->setSizePolicy( sizePolicy );
552 553
    playButton->setMaximumSize( QSize( 36, 36 ) );
    playButton->setMinimumSize( QSize( 36, 36 ) );
554
    playButton->setIconSize( QSize( 30, 30 ) );
555

556
    controlLayout->addWidget( playButton, 2, 0, 2, 2 );
557

558 559
    controlLayout->setColumnMinimumWidth( 2, 20 );
    controlLayout->setColumnStretch( 2, 0 );
560 561

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

    /* Prev */
    QPushButton *prevButton = new QPushButton;
    prevButton->setSizePolicy( sizePolicy );
568
    setupSmallButton( prevButton );
569 570 571 572 573 574

    controlButLayout->addWidget( prevButton );

    /* Stop */
    QPushButton *stopButton = new QPushButton;
    stopButton->setSizePolicy( sizePolicy );
575
    setupSmallButton( stopButton );
576 577 578 579 580 581

    controlButLayout->addWidget( stopButton );

    /* next */
    QPushButton *nextButton = new QPushButton;
    nextButton->setSizePolicy( sizePolicy );
582
    setupSmallButton( nextButton );
583 584 585 586

    controlButLayout->addWidget( nextButton );

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

590
    BUTTON_SET_ACT_I( playButton, "", play.png, qtr( "Play" ), play() );
591
    BUTTON_SET_ACT_I( prevButton, "" , previous.png,
592 593 594
                      qtr( "Previous" ), prev() );
    BUTTON_SET_ACT_I( nextButton, "", next.png, qtr( "Next" ), next() );
    BUTTON_SET_ACT_I( stopButton, "", stop.png, qtr( "Stop" ), stop() );
595

596 597 598 599
    controlLayout->setColumnMinimumWidth( 7, 20 );
    controlLayout->setColumnStretch( 7, 0 );
    controlLayout->setColumnStretch( 8, 0 );
    controlLayout->setColumnStretch( 9, 0 );
600

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

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

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

624
    controlLayout->setColumnStretch( 13, 0 );
625
    controlLayout->setColumnMinimumWidth( 13, 24 );
626
    controlLayout->setColumnStretch( 14, 5 );
627

628
    /* Volume */
Lukas Durfina's avatar
Lukas Durfina committed
629
    hVolLabel = new VolumeClickHandler( p_intf, this );
630

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

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

654
    /* Set the volume from the config */
655 656
    volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
                              VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
657

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

661 662
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
663
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
664 665

    updateInput();
666
}
667

668
ControlsWidget::~ControlsWidget()
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 700 701 702 703
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;
    }
}

704 705 706 707 708 709 710
void ControlsWidget::stop()
{
    THEMIM->stop();
}

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

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

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

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

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

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

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

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

829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
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 );
844 845 846

    /* Advanced Buttons too */
    advControls->enableInput( enable );
847 848
}