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

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

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

Clément Stenac's avatar
Clément Stenac committed
40 41
#include <QLabel>
#include <QSpacerItem>
Clément Stenac's avatar
Clément Stenac committed
42
#include <QCursor>
Clément Stenac's avatar
Clément Stenac committed
43
#include <QPushButton>
44
#include <QToolButton>
45
#include <QHBoxLayout>
Clément Stenac's avatar
Clément Stenac committed
46
#include <QMenu>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
47 48
#include <QPalette>
#include <QResizeEvent>
49
#include <QDate>
50
#include <QMutexLocker>
51 52 53 54
#ifdef Q_WS_X11
# include <X11/Xlib.h>
# include <qx11info_x11.h>
#endif
55

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

61
VideoWidget::VideoWidget( intf_thread_t *_p_i ) : QFrame( NULL ), p_intf( _p_i )
62
{
63
    /* Init */
64
    vlc_mutex_init( &lock );
65
    p_vout = NULL;
66
    handleReady = false;
67
    hide(); setMinimumSize( 16, 16 );
68 69
    videoSize.rwidth() = -1;
    videoSize.rheight() = -1;
70

71 72 73 74 75 76
    /* 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 );

77 78 79 80 81 82 83 84
    /* 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 );

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

89 90 91
void VideoWidget::paintEvent(QPaintEvent *ev)
{
    QFrame::paintEvent(ev);
92 93 94 95
#ifdef Q_WS_X11
    XFlush( QX11Info::display() );
#endif
    QMutexLocker locker( &handleLock );
96 97 98 99
    handleReady = true;
    handleWait.wakeAll();
}

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
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 );
}

120
/**
121
 * Request the video to avoid the conflicts
122
 **/
123
void *VideoWidget::request( vout_thread_t *p_nvout, int *pi_x, int *pi_y,
124 125
                           unsigned int *pi_width, unsigned int *pi_height )
{
126
    QMutexLocker locker( &handleLock );
127
    msg_Dbg( p_intf, "Video was requested %i, %i", *pi_x, *pi_y );
128
    emit askVideoWidgetToShow();
129 130 131 132 133 134
    if( p_vout )
    {
        msg_Dbg( p_intf, "embedded video already in use" );
        return NULL;
    }
    p_vout = p_nvout;
135 136 137 138 139 140
    while( !handleReady )
    {
        msg_Dbg( p_intf, "embedded video pending (handle %p)", winId() );
        handleWait.wait( &handleLock );
    }
    msg_Dbg( p_intf, "embedded video ready (handle %p)", winId() );
141
    return ( void* )winId();
142 143
}

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

155
void VideoWidget::release( void *p_win )
156
{
157
    msg_Dbg( p_intf, "Video is non needed anymore" );
158
    p_vout = NULL;
159 160 161 162
    videoSize.rwidth() = 0;
    videoSize.rheight() = 0;
    hide();
    updateGeometry(); // Needed for deinterlace
163
}
164

165 166 167 168
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
169

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

178 179
BackgroundWidget::BackgroundWidget( intf_thread_t *_p_i )
                 :QWidget( NULL ), p_intf( _p_i )
180
{
181
    /* We should use that one to take the more size it can */
182
//    setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
183

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

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

203 204 205 206
    QGridLayout *backgroundLayout = new QGridLayout( this );
    backgroundLayout->addWidget( label, 0, 1 );
    backgroundLayout->setColumnStretch( 0, 1 );
    backgroundLayout->setColumnStretch( 2, 1 );
207

208
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
209 210
}

Clément Stenac's avatar
Clément Stenac committed
211
BackgroundWidget::~BackgroundWidget()
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
212 213 214
{
}

215 216 217 218 219 220 221 222
void BackgroundWidget::resizeEvent( QResizeEvent * event )
{
    if( event->size().height() <= MIN_BG_SIZE )
        label->hide();
    else
        label->show();
}

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

239 240 241 242
void BackgroundWidget::contextMenuEvent( QContextMenuEvent *event )
{
    QVLCMenu::PopupMenu( p_intf, true );
}
243

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

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

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

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

Clément Stenac's avatar
Clément Stenac committed
267
    setLayout( layout );
268
    setMaximumHeight( 35 );
Clément Stenac's avatar
Clément Stenac committed
269 270 271 272 273 274
}

VisualSelector::~VisualSelector()
{
}

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

/**********************************************************************
296
 * TEH controls
Clément Stenac's avatar
Clément Stenac committed
297
 **********************************************************************/
298 299 300 301 302 303

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

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

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

    recordButton = new QPushButton( "R" );
Lukas Durfina's avatar
Lukas Durfina committed
329
    setupSmallButton( recordButton );
330
    advLayout->addWidget( recordButton );
331
    BUTTON_SET_ACT_I( recordButton, "", record_16px.png,
332
            qtr( "Record" ), record() );
333

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

341
AdvControlsWidget::~AdvControlsWidget()
342
{}
Clément Stenac's avatar
Clément Stenac committed
343

344
void AdvControlsWidget::enableInput( bool enable )
Clément Stenac's avatar
Clément Stenac committed
345
{
346 347
    ABButton->setEnabled( enable );
    recordButton->setEnabled( enable );
Clément Stenac's avatar
Clément Stenac committed
348
}
349

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

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

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

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

396
/* FIXME Record function */
397
void AdvControlsWidget::record(){}
398

399
#if 0
400
//FIXME Frame by frame function
401
void AdvControlsWidget::frame(){}
402
#endif
403

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

416
    controlLayout->setSpacing( 0 );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
417
    controlLayout->setLayoutMargins( 7, 5, 7, 3, 6 );
418

Lukas Durfina's avatar
Lukas Durfina committed
419 420 421
    if( !b_fsCreation )
        setLayout( controlLayout );

422
    setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
423

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

434
    /** Slower and faster Buttons **/
435 436
    slowerButton = new QToolButton;
    slowerButton->setAutoRaise( true );
437
    slowerButton->setMaximumSize( QSize( 26, 20 ) );
438

439
    BUTTON_SET_ACT( slowerButton, "-", qtr( "Slower" ), slower() );
440 441
    controlLayout->addWidget( slowerButton, 0, 0 );

442 443
    fasterButton = new QToolButton;
    fasterButton->setAutoRaise( true );
444
    fasterButton->setMaximumSize( QSize( 26, 20 ) );
445

446
    BUTTON_SET_ACT( fasterButton, "+", qtr( "Faster" ), faster() );
447
    controlLayout->addWidget( fasterButton, 0, 17 );
448

449 450 451 452
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

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

456
    /** Disc and Menus handling */
457
    discFrame = new QWidget( this );
458

459 460 461
    QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
    discLayout->setSpacing( 0 );
    discLayout->setMargin( 0 );
462

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

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

471
    nextSectionButton = new QPushButton( discFrame );
472
    setupSmallButton( nextSectionButton );
473 474
    discLayout->addWidget( nextSectionButton );

475
    controlLayout->addWidget( discFrame, 1, 10, 2, 3, Qt::AlignBottom );
476 477 478 479 480

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

481
    discFrame->hide();
482 483 484

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

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

503
    QPushButton  *telexOn = new QPushButton;
504 505 506
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

507
    telexTransparent = new QPushButton;
508 509
    setupSmallButton( telexTransparent );
    telexLayout->addWidget( telexTransparent );
510
    b_telexTransparent = false;
511

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

521
    controlLayout->addWidget( telexFrame, 1, 10, 2, 4, Qt::AlignBottom );
522
    telexFrame->hide(); /* default hidden */
523 524 525

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
526 527 528

    BUTTON_SET_ACT_I( telexOn, "", tv.png, qtr( "Teletext on" ),
                      toggleTeletext() );
529 530
    CONNECT( telexOn, clicked( bool ), THEMIM->getIM(),
             telexToggle( bool ) );
531 532 533 534 535
    telexTransparent->setEnabled( false );
    telexPage->setEnabled( false );

    BUTTON_SET_ACT_I( telexTransparent, "", tvtelx.png, qtr( "Teletext" ),
                      toggleTeletextTransparency() );
536
    CONNECT( telexTransparent, clicked( bool ),
537
             THEMIM->getIM(), telexSetTransparency() );
538 539
    CONNECT( THEMIM->getIM(), teletextEnabled( bool ),
             telexFrame, setVisible( bool ) );
540

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

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

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

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

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

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

    controlButLayout->addWidget( prevButton );

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

    controlButLayout->addWidget( stopButton );

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

    controlButLayout->addWidget( nextButton );

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

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

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

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

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

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

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

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

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

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

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

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

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

    updateInput();
663
}
664

665
ControlsWidget::~ControlsWidget()
666
{}
667

668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
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;
    }
}

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

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

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

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

770
void ControlsWidget::updateVolume()
771
{
772
    /* Audio part */
773 774
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
775
    i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
776 777 778 779 780 781 782 783
    int i_gauge = volumeSlider->value();
    b_my_volume = false;
    if( i_volume - i_gauge > 1 || i_gauge - i_volume > 1 )
    {
        b_my_volume = true;
        volumeSlider->setValue( i_volume );
        b_my_volume = false;
    }
784
}
785

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

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

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

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

829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
void ControlsWidget::slower()
{
    THEMIM->getIM()->slower();
}

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

void ControlsWidget::enableInput( bool enable )
{
    slowerButton->setEnabled( enable );
    slider->setEnabled( enable );
    fasterButton->setEnabled( enable );
844 845 846

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

849
void ControlsWidget::enableVideo( bool enable )
850
{
851 852
    // TODO Later make the fullscreenButton toggle Visualisation and so on.
    fullscreenButton->setEnabled( enable );
853 854 855

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
856 857
}

858 859 860 861 862 863 864 865 866 867 868 869
void ControlsWidget::toggleAdvanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        b_advancedVisible = true;
    }
    else
    {
        advControls->hide();
        b_advancedVisible = false;
    }
870
    emit advancedControlsToggled( b_advancedVisible );
871
}
872

873

Lukas Durfina's avatar
Lukas Durfina committed
874