interface_widgets.cpp 37.4 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

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

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

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

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
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 );
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

VisualSelector::~VisualSelector()
{
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

471
    discFrame->hide();
472 473 474

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

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

493
    QPushButton  *telexOn = new QPushButton;
494 495 496
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

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

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

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

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
516 517 518

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

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

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

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

543
    controlLayout->addWidget( playButton, 2, 0, 2, 2 );
544

545 546
    controlLayout->setColumnMinimumWidth( 2, 20 );
    controlLayout->setColumnStretch( 2, 0 );
547 548

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

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

    controlButLayout->addWidget( prevButton );

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

    controlButLayout->addWidget( stopButton );

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

    controlButLayout->addWidget( nextButton );

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

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

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

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

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

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

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

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

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

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

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

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

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

    updateInput();
653
}
654

655
ControlsWidget::~ControlsWidget()
656
{}
657

658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
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;
    }
}

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

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

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

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

760
void ControlsWidget::updateVolume()
761
{
762
    /* Audio part */
763 764
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
765
    i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
766 767 768 769 770 771 772 773
    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;
    }
774
}
775

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

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

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

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

819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
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 );
834 835 836

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

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

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
846 847
}

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

863

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