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

69 70 71 72 73
    /* Black background is more coherent for a Video Widget IMVHO */
    QPalette plt =  palette();
    plt.setColor( QPalette::Active, QPalette::Window , Qt::black );
    plt.setColor( QPalette::Inactive, QPalette::Window , Qt::black );
    setPalette( plt );
74
    setAttribute( Qt::WA_PaintOnScreen, true );
75

76
    /* The core can ask through a callback to show the video. */
77 78 79
    connect( this, SIGNAL(askVideoWidgetToShow( unsigned int, unsigned int)),
             this, SLOT(SetSizing(unsigned int, unsigned int )),
             Qt::BlockingQueuedConnection );
80 81
}

82 83 84
void VideoWidget::paintEvent(QPaintEvent *ev)
{
    QFrame::paintEvent(ev);
85 86 87
#ifdef Q_WS_X11
    XFlush( QX11Info::display() );
#endif
88 89
}

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
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 );
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

VisualSelector::~VisualSelector()
{
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

466
    discFrame->hide();
467 468 469

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    controlButLayout->addWidget( prevButton );

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

    controlButLayout->addWidget( stopButton );

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

    controlButLayout->addWidget( nextButton );

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

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

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

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

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

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

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

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

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

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

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

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

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

    updateInput();
657
}
658

659
ControlsWidget::~ControlsWidget()
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 691 692 693 694
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;
    }
}

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

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

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

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

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

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

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

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

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

823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
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 );
838 839 840

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

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

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
850 851
}

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