interface_widgets.cpp 37.5 KB
Newer Older
1
/*****************************************************************************
2
 * interface_widgets.cpp : Custom widgets for the main interface
3
 ****************************************************************************
4
 * Copyright ( C ) 2006 the VideoLAN team
5
 * $Id$
6 7
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 *          Jean-Baptiste Kempf <jb@videolan.org>
9
 *          Rafaël Carré <funman@videolanorg>
10
 *          Ilkka Ollakka <ileoo@videolan.org>
11 12 13 14
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
15
 * ( at your option ) any later version.
16 17 18 19 20 21 22 23 24 25
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/
26

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

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

Clément Stenac's avatar
Clément Stenac committed
40 41
#include <QLabel>
#include <QSpacerItem>
Clément Stenac's avatar
Clément Stenac committed
42
#include <QCursor>
Clément Stenac's avatar
Clément Stenac committed
43
#include <QPushButton>
44
#include <QToolButton>
45
#include <QHBoxLayout>
Clément Stenac's avatar
Clément Stenac committed
46
#include <QMenu>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
47 48
#include <QPalette>
#include <QResizeEvent>
49
#include <QDate>
50 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
    vlc_mutex_init( &lock );
64
    p_vout = NULL;
65
    hide(); setMinimumSize( 16, 16 );
66 67
    videoSize.rwidth() = -1;
    videoSize.rheight() = -1;
68
    setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
69

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

77
    /* The core can ask through a callback to show the video. */
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
void VideoWidget::paintEvent(QPaintEvent *ev)
{
    QFrame::paintEvent(ev);
86 87 88
#ifdef Q_WS_X11
    XFlush( QX11Info::display() );
#endif
89 90
}

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

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

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

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

151 152 153 154
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
155

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

164 165
BackgroundWidget::BackgroundWidget( intf_thread_t *_p_i )
                 :QWidget( NULL ), p_intf( _p_i )
166
{
167
    /* We should use that one to take the more size it can */
168
//    setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
169

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

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

189 190 191 192
    QGridLayout *backgroundLayout = new QGridLayout( this );
    backgroundLayout->addWidget( label, 0, 1 );
    backgroundLayout->setColumnStretch( 0, 1 );
    backgroundLayout->setColumnStretch( 2, 1 );
193

194
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
195 196
}

Clément Stenac's avatar
Clément Stenac committed
197
BackgroundWidget::~BackgroundWidget()
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
198 199 200
{
}

201 202 203 204 205 206 207 208
void BackgroundWidget::resizeEvent( QResizeEvent * event )
{
    if( event->size().height() <= MIN_BG_SIZE )
        label->hide();
    else
        label->show();
}

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

225 226 227 228
void BackgroundWidget::contextMenuEvent( QContextMenuEvent *event )
{
    QVLCMenu::PopupMenu( p_intf, true );
}
229

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

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

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

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

Clément Stenac's avatar
Clément Stenac committed
253
    setLayout( layout );
254
    setMaximumHeight( 35 );
Clément Stenac's avatar
Clément Stenac committed
255 256 257 258 259 260
}

VisualSelector::~VisualSelector()
{
}

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

/**********************************************************************
282
 * TEH controls
Clément Stenac's avatar
Clément Stenac committed
283
 **********************************************************************/
284 285 286 287 288 289

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

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

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

    recordButton = new QPushButton( "R" );
Lukas Durfina's avatar
Lukas Durfina committed
315
    setupSmallButton( recordButton );
316
    advLayout->addWidget( recordButton );
317
    BUTTON_SET_ACT_I( recordButton, "", record_16px.png,
318
            qtr( "Record" ), record() );
319

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

327
AdvControlsWidget::~AdvControlsWidget()
328
{}
Clément Stenac's avatar
Clément Stenac committed
329

330
void AdvControlsWidget::enableInput( bool enable )
Clément Stenac's avatar
Clément Stenac committed
331
{
332 333
    ABButton->setEnabled( enable );
    recordButton->setEnabled( enable );
Clément Stenac's avatar
Clément Stenac committed
334
}
335

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

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

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

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

382
/* FIXME Record function */
383
void AdvControlsWidget::record(){}
384

385
#if 0
386
//FIXME Frame by frame function
387
void AdvControlsWidget::frame(){}
388
#endif
389

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

402
    controlLayout->setSpacing( 0 );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
403
    controlLayout->setLayoutMargins( 7, 5, 7, 3, 6 );
404

Lukas Durfina's avatar
Lukas Durfina committed
405 406 407
    if( !b_fsCreation )
        setLayout( controlLayout );

408
    setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
409

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

420
    /** Slower and faster Buttons **/
421 422
    slowerButton = new QToolButton;
    slowerButton->setAutoRaise( true );
423
    slowerButton->setMaximumSize( QSize( 26, 20 ) );
424

425
    BUTTON_SET_ACT( slowerButton, "-", qtr( "Slower" ), slower() );
426 427
    controlLayout->addWidget( slowerButton, 0, 0 );

428 429
    fasterButton = new QToolButton;
    fasterButton->setAutoRaise( true );
430
    fasterButton->setMaximumSize( QSize( 26, 20 ) );
431

432
    BUTTON_SET_ACT( fasterButton, "+", qtr( "Faster" ), faster() );
433
    controlLayout->addWidget( fasterButton, 0, 17 );
434

435 436 437 438
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

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

442
    /** Disc and Menus handling */
443
    discFrame = new QWidget( this );
444

445 446 447
    QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
    discLayout->setSpacing( 0 );
    discLayout->setMargin( 0 );
448

449
    prevSectionButton = new QPushButton( discFrame );
450
    setupSmallButton( prevSectionButton );
451 452
    discLayout->addWidget( prevSectionButton );

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

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

461
    controlLayout->addWidget( discFrame, 1, 10, 2, 3, Qt::AlignBottom );
462 463 464

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

467
    discFrame->hide();
468 469 470

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

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

Lukas Durfina's avatar
Lukas Durfina committed
489
    telexOn = new QPushButton;
490 491 492
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

493
    telexTransparent = new QPushButton;
494 495
    setupSmallButton( telexTransparent );
    telexLayout->addWidget( telexTransparent );
496
    b_telexTransparent = false;
497

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

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

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
Lukas Durfina's avatar
Lukas Durfina committed
513 514 515 516
    CONNECT( THEMIM->getIM(), setNewTelexPage( int ),
              telexPage, setValue( int ) );

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

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

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

536
    /** Play Buttons **/
537
    QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
538 539 540 541
    sizePolicy.setHorizontalStretch( 0 );
    sizePolicy.setVerticalStretch( 0 );

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

548
    controlLayout->addWidget( playButton, 2, 0, 2, 2 );
549

550 551
    controlLayout->setColumnMinimumWidth( 2, 20 );
    controlLayout->setColumnStretch( 2, 0 );
552 553

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

    /* Prev */
    QPushButton *prevButton = new QPushButton;
    prevButton->setSizePolicy( sizePolicy );
560
    setupSmallButton( prevButton );
561 562 563 564 565 566

    controlButLayout->addWidget( prevButton );

    /* Stop */
    QPushButton *stopButton = new QPushButton;
    stopButton->setSizePolicy( sizePolicy );
567
    setupSmallButton( stopButton );
568 569 570 571 572 573

    controlButLayout->addWidget( stopButton );

    /* next */
    QPushButton *nextButton = new QPushButton;
    nextButton->setSizePolicy( sizePolicy );
574
    setupSmallButton( nextButton );
575 576 577 578

    controlButLayout->addWidget( nextButton );

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

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

588 589 590 591
    controlLayout->setColumnMinimumWidth( 7, 20 );
    controlLayout->setColumnStretch( 7, 0 );
    controlLayout->setColumnStretch( 8, 0 );
    controlLayout->setColumnStretch( 9, 0 );
592

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

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

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

616
    controlLayout->setColumnStretch( 13, 0 );
617
    controlLayout->setColumnMinimumWidth( 13, 24 );
618
    controlLayout->setColumnStretch( 14, 5 );
619

620
    /* Volume */
Lukas Durfina's avatar
Lukas Durfina committed
621
    hVolLabel = new VolumeClickHandler( p_intf, this );
622

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

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

646
    /* Set the volume from the config */
647 648
    volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
                              VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
649

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

653 654
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
655
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
656 657

    updateInput();
658
}
659

660
ControlsWidget::~ControlsWidget()
661
{}
662

663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
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;
    }
}

696 697 698 699 700 701 702
void ControlsWidget::stop()
{
    THEMIM->stop();
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

850 851 852 853 854 855 856 857 858 859