interface_widgets.cpp 37.3 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
#include <math.h>

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

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

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

78
    /* The core can ask through a callback to show the video. */
79
#if HAS_QT43
80 81 82
    connect( this, SIGNAL(askVideoWidgetToShow( unsigned int, unsigned int)),
             this, SLOT(SetSizing(unsigned int, unsigned int )),
             Qt::BlockingQueuedConnection );
83 84 85 86 87 88 89
#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


90 91
}

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

100 101
VideoWidget::~VideoWidget()
{
102 103 104
    vout_thread_t *p_vout = i_vout
        ? (vout_thread_t *)vlc_object_get( i_vout ) : NULL;

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

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

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

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

161 162 163 164
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
165

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

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

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

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

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

204
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
205 206
}

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

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

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

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

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

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

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

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

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

VisualSelector::~VisualSelector()
{
}

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

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

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

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

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

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

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

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

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

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

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

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

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

392
/* FIXME Record function */
393
void AdvControlsWidget::record(){}
394

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

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

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

Lukas Durfina's avatar
Lukas Durfina committed
415 416 417
    if( !b_fsCreation )
        setLayout( controlLayout );

418
    setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
419

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

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

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

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

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

445 446 447 448
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

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

452
    /** Disc and Menus handling */
453
    discFrame = new QWidget( this );
454

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

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

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

467
    nextSectionButton = new QPushButton( discFrame );
468
    setupSmallButton( nextSectionButton );
469 470
    discLayout->addWidget( nextSectionButton );

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

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

477
    discFrame->hide();
478 479 480

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

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

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

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

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

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

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

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

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

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

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

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

558
    controlLayout->addWidget( playButton, 2, 0, 2, 2 );
559

560 561
    controlLayout->setColumnMinimumWidth( 2, 20 );
    controlLayout->setColumnStretch( 2, 0 );
562 563

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

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

    controlButLayout->addWidget( prevButton );

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

    controlButLayout->addWidget( stopButton );

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

    controlButLayout->addWidget( nextButton );

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

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

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

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

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

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

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

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

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

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

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

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

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

    updateInput();
668
}
669

670
ControlsWidget::~ControlsWidget()
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 704 705
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;
    }
}

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

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

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

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

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

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

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

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

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

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

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