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

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
31 32
#include <vlc_vout.h>

33
#include "dialogs_provider.hpp"
34
#include "components/interface_widgets.hpp"
35
#include "main_interface.hpp"
36
#include "input_manager.hpp"
37
#include "menus.hpp"
38
#include "util/input_slider.hpp"
39
#include "util/customwidgets.hpp"
40

Clément Stenac's avatar
Clément Stenac committed
41 42
#include <QLabel>
#include <QSpacerItem>
Clément Stenac's avatar
Clément Stenac committed
43
#include <QCursor>
Clément Stenac's avatar
Clément Stenac committed
44
#include <QPushButton>
45
#include <QToolButton>
46
#include <QHBoxLayout>
Clément Stenac's avatar
Clément Stenac committed
47
#include <QMenu>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
48 49
#include <QPalette>
#include <QResizeEvent>
50
#include <QDate>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
51

52 53 54 55
#ifdef Q_WS_X11
# include <X11/Xlib.h>
# include <qx11info_x11.h>
#endif
56

57 58
#include <math.h>

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

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

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

80
    /* The core can ask through a callback to show the video. */
81
#if HAS_QT43
82 83 84
    connect( this, SIGNAL(askVideoWidgetToShow( unsigned int, unsigned int)),
             this, SLOT(SetSizing(unsigned int, unsigned int )),
             Qt::BlockingQueuedConnection );
85 86 87 88 89
#else
#error This is broken. Fix it with a QEventLoop with a processEvents () 
    connect( this, SIGNAL(askVideoWidgetToShow( unsigned int, unsigned int)),
             this, SLOT(SetSizing(unsigned int, unsigned int )) );
#endif
90 91
}

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

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

105 106 107 108 109 110 111 112 113 114 115 116
    if( p_vout )
    {
        if( !p_intf->psz_switch_intf )
        {
            if( vout_Control( p_vout, VOUT_CLOSE ) != VLC_SUCCESS )
                vout_Control( p_vout, VOUT_REPARENT );
        }
        else
        {
            if( vout_Control( p_vout, VOUT_REPARENT ) != VLC_SUCCESS )
                vout_Control( p_vout, VOUT_CLOSE );
        }
117
        vlc_object_release( p_vout );
118 119 120
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

252
    layout->addStretch( 10 );
253
    layout->addWidget( new QLabel( qtr( "Current visualization" ) ) );
Clément Stenac's avatar
Clément Stenac committed
254 255 256 257 258 259 260

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

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

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

VisualSelector::~VisualSelector()
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
266
{}
Clément Stenac's avatar
Clément Stenac committed
267

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

/**********************************************************************
289
 * TEH controls
Clément Stenac's avatar
Clément Stenac committed
290
 **********************************************************************/
291 292 293 294 295 296

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

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

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

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

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

334
AdvControlsWidget::~AdvControlsWidget()
335
{}
Clément Stenac's avatar
Clément Stenac committed
336

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

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

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

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

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

389
/* FIXME Record function */
390
void AdvControlsWidget::record(){}
391

392
#if 0
393
//FIXME Frame by frame function
394
void AdvControlsWidget::frame(){}
395
#endif
396

397 398 399
/*****************************
 * DA Control Widget !
 *****************************/
400
ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
401
                                MainInterface *_p_mi,
402
                                bool b_advControls,
Lukas Durfina's avatar
Lukas Durfina committed
403 404 405
                                bool b_shiny,
                                bool b_fsCreation) :
                                QFrame( _p_mi ), p_intf( _p_i )
406
{
407
        setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
408

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

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

423
    BUTTON_SET_ACT( slowerButton, "-", qtr( "Slower" ), slower() );
424

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

429
    BUTTON_SET_ACT( fasterButton, "+", qtr( "Faster" ), faster() );
430

431 432 433 434 435 436
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

    advControls = new AdvControlsWidget( p_intf );
    if( !b_advancedVisible ) advControls->hide();

437
    /** Disc and Menus handling */
438
    discFrame = new QWidget( this );
439

440 441 442
    QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
    discLayout->setSpacing( 0 );
    discLayout->setMargin( 0 );
443

444
    prevSectionButton = new QPushButton( discFrame );
445
    setupSmallButton( prevSectionButton );
446 447
    discLayout->addWidget( prevSectionButton );

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

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

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

460
    discFrame->hide();
461 462 463

    /* Change the navigation button display when the IM navigation changes */
    CONNECT( THEMIM->getIM(), navigationChanged( int ),
464
             this, setNavigation( int ) );
465 466 467 468 469 470 471
    /* 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() );
472

473
    /**
474
     * Telextext QFrame
475
     * TODO: Merge with upper menu in a StackLayout
476
     **/
477 478 479 480 481
    telexFrame = new QWidget( this );
    QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame );
    telexLayout->setSpacing( 0 );
    telexLayout->setMargin( 0 );

Lukas Durfina's avatar
Lukas Durfina committed
482
    telexOn = new QPushButton;
483 484 485
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

486
    telexTransparent = new QPushButton;
487 488
    setupSmallButton( telexTransparent );
    telexLayout->addWidget( telexTransparent );
489
    b_telexTransparent = false;
490

491
    telexPage = new QSpinBox;
492
    telexPage->setRange( 0, 999 );
493
    telexPage->setValue( 100 );
494 495
    telexPage->setAccelerated( true );
    telexPage->setWrapping( true );
496
    telexPage->setAlignment( Qt::AlignRight );
497
    telexPage->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
498 499
    telexLayout->addWidget( telexPage );

500
    telexFrame->hide(); /* default hidden */
501 502 503

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
Lukas Durfina's avatar
Lukas Durfina committed
504 505 506 507
    CONNECT( THEMIM->getIM(), setNewTelexPage( int ),
              telexPage, setValue( int ) );

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

Lukas Durfina's avatar
Lukas Durfina committed
509 510
    CONNECT( telexOn, clicked(), THEMIM->getIM(),
             telexToggleButtons() );
511 512
    CONNECT( telexOn, clicked( bool ), THEMIM->getIM(),
             telexToggle( bool ) );
Lukas Durfina's avatar
Lukas Durfina committed
513 514 515
    CONNECT( THEMIM->getIM(), toggleTelexButtons(),
              this, toggleTeletext() );
    b_telexEnabled = false;
516 517 518
    telexTransparent->setEnabled( false );
    telexPage->setEnabled( false );

Lukas Durfina's avatar
Lukas Durfina committed
519
    BUTTON_SET_IMG( telexTransparent, "", tvtelx.png, qtr( "Teletext" ) );
520
    CONNECT( telexTransparent, clicked( bool ),
521
             THEMIM->getIM(), telexSetTransparency() );
Lukas Durfina's avatar
Lukas Durfina committed
522 523
    CONNECT( THEMIM->getIM(), toggleTelexTransparency(),
              this, toggleTeletextTransparency() );
524
    CONNECT( THEMIM->getIM(), teletextEnabled( bool ),
525
             this, enableTeletext( bool ) );
526

527
    /** Play Buttons **/
528
    QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
529 530 531 532
    sizePolicy.setHorizontalStretch( 0 );
    sizePolicy.setVerticalStretch( 0 );

    /* Play */
533
    playButton = new QPushButton;
534
    playButton->setSizePolicy( sizePolicy );
535 536
    playButton->setMaximumSize( QSize( 36, 36 ) );
    playButton->setMinimumSize( QSize( 36, 36 ) );
537
    playButton->setIconSize( QSize( 30, 30 ) );
538

539

540
        /** Prev + Stop + Next Block **/
Lukas Durfina's avatar
Lukas Durfina committed
541
    controlButLayout = new QHBoxLayout;
542 543 544 545 546
    controlButLayout->setSpacing( 0 ); /* Don't remove that, will be useful */

    /* Prev */
    QPushButton *prevButton = new QPushButton;
    prevButton->setSizePolicy( sizePolicy );
547
    setupSmallButton( prevButton );
548 549 550 551 552 553

    controlButLayout->addWidget( prevButton );

    /* Stop */
    QPushButton *stopButton = new QPushButton;
    stopButton->setSizePolicy( sizePolicy );
554
    setupSmallButton( stopButton );
555 556 557 558 559 560

    controlButLayout->addWidget( stopButton );

    /* next */
    QPushButton *nextButton = new QPushButton;
    nextButton->setSizePolicy( sizePolicy );
561
    setupSmallButton( nextButton );
562 563 564 565 566

    controlButLayout->addWidget( nextButton );

    /* Add this block to the main layout */

567
    BUTTON_SET_ACT_I( playButton, "", play.png, qtr( "Play" ), play() );
568
    BUTTON_SET_ACT_I( prevButton, "" , previous.png,
569 570 571
                      qtr( "Previous" ), prev() );
    BUTTON_SET_ACT_I( nextButton, "", next.png, qtr( "Next" ), next() );
    BUTTON_SET_ACT_I( stopButton, "", stop.png, qtr( "Stop" ), stop() );
572 573 574 575

    /*
     * Other first Line buttons
     */
576 577 578
    /** Fullscreen/Visualisation **/
    fullscreenButton = new QPushButton( "F" );
    BUTTON_SET_ACT( fullscreenButton, "F", qtr( "Fullscreen" ), fullscreen() );
579
    setupSmallButton( fullscreenButton );
580

581 582
    /** Playlist Button **/
    playlistButton = new QPushButton;
583
    setupSmallButton( playlistButton );
584
    BUTTON_SET_IMG( playlistButton, "" , playlist.png, qtr( "Show playlist" ) );
585
    CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );
586 587

    /** extended Settings **/
Lukas Durfina's avatar
Lukas Durfina committed
588
    extSettingsButton = new QPushButton;
589
    BUTTON_SET_ACT( extSettingsButton, "Ex", qtr( "Extended settings" ),
590
            extSettings() );
591
    setupSmallButton( extSettingsButton );
592

593

594
    /* Volume */
Lukas Durfina's avatar
Lukas Durfina committed
595
    hVolLabel = new VolumeClickHandler( p_intf, this );
596

597
    volMuteLabel = new QLabel;
598
    volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
599
    volMuteLabel->setToolTip( qtr( "Mute" ) );
600
    volMuteLabel->installEventFilter( hVolLabel );
601

602 603 604
    if( b_shiny )
    {
        volumeSlider = new SoundSlider( this,
605
            config_GetInt( p_intf, "volume-step" ),
606 607
            config_GetInt( p_intf, "qt-volume-complete" ),
            config_GetPsz( p_intf, "qt-slider-colours" ) );
608 609 610 611 612 613
    }
    else
    {
        volumeSlider = new QSlider( this );
        volumeSlider->setOrientation( Qt::Horizontal );
    }
614
    volumeSlider->setMaximumSize( QSize( 200, 40 ) );
615
    volumeSlider->setMinimumSize( QSize( 106, 30 ) );
616
    volumeSlider->setFocusPolicy( Qt::NoFocus );
617

618
    /* Set the volume from the config */
619 620
    volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
                              VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
621

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

625 626
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
627
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
628

629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
    if( !b_fsCreation )
    {
        controlLayout = new QGridLayout( this );

        controlLayout->setSpacing( 0 );
        controlLayout->setLayoutMargins( 7, 5, 7, 3, 6 );

        controlLayout->addWidget( slider, 0, 1, 1, 16 );
        controlLayout->addWidget( slowerButton, 0, 0 );
        controlLayout->addWidget( fasterButton, 0, 17 );

        controlLayout->addWidget( advControls, 1, 3, 2, 4, Qt::AlignBottom );
        controlLayout->addWidget( discFrame, 1, 10, 2, 3, Qt::AlignBottom );
        controlLayout->addWidget( telexFrame, 1, 10, 2, 4, Qt::AlignBottom );

        controlLayout->addWidget( playButton, 2, 0, 2, 2 );
        controlLayout->setColumnMinimumWidth( 2, 20 );
        controlLayout->setColumnStretch( 2, 0 );

        controlLayout->addLayout( controlButLayout, 3, 3, 1, 3 );
        controlLayout->setColumnMinimumWidth( 7, 20 );
        controlLayout->setColumnStretch( 7, 0 );
        controlLayout->setColumnStretch( 8, 0 );
        controlLayout->setColumnStretch( 9, 0 );

        controlLayout->addWidget( fullscreenButton, 3, 10, Qt::AlignBottom );
        controlLayout->addWidget( playlistButton, 3, 11, Qt::AlignBottom );
        controlLayout->addWidget( extSettingsButton, 3, 12, Qt::AlignBottom );

        controlLayout->setColumnStretch( 13, 0 );
        controlLayout->setColumnMinimumWidth( 13, 24 );
        controlLayout->setColumnStretch( 14, 5 );

        controlLayout->addWidget( volMuteLabel, 3, 15, Qt::AlignBottom );
        controlLayout->addWidget( volumeSlider, 2, 16, 2 , 2, Qt::AlignBottom );
    }

666
    updateInput();
667
}
668

669
ControlsWidget::~ControlsWidget()
670
{}
671

672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687
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;
    }
}
688

689 690 691 692 693 694 695 696 697 698
void ControlsWidget::enableTeletext( bool b_enable )
{
    telexFrame->setVisible( b_enable );
    bool b_on = THEMIM->teletextState();

    telexOn->setChecked( b_on );
    telexTransparent->setEnabled( b_on );
    telexPage->setEnabled( b_on );
    b_telexEnabled = b_on;
}
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715

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;
    }
}

716 717 718 719 720 721 722
void ControlsWidget::stop()
{
    THEMIM->stop();
}

void ControlsWidget::play()
{
723
    if( THEPL->current.i_size == 0 )
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
    {
        /* 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 )
{
745 746
#define HELP_PCH N_( "Previous chapter" )
#define HELP_NCH N_( "Next chapter" )
747 748 749 750 751 752

    // 1 = chapter, 2 = title, 0 = no
    if( navigation == 0 )
    {
        discFrame->hide();
    } else if( navigation == 1 ) {
753 754
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
755 756 757
        menuButton->show();
        discFrame->show();
    } else {
758 759
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
760 761 762 763 764 765
        menuButton->hide();
        discFrame->show();
    }
}

static bool b_my_volume;
766
void ControlsWidget::updateVolume( int i_sliderVolume )
767 768 769
{
    if( !b_my_volume )
    {
770
        int i_res = i_sliderVolume  * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX;
771 772
        aout_VolumeSet( p_intf, i_res );
    }
773 774
    if( i_sliderVolume == 0 )
        volMuteLabel->setPixmap( QPixmap(":/pixmaps/volume-muted.png" ) );
775
    else if( i_sliderVolume < VOLUME_MAX / 3 )
776
        volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-low.png" ) );
777 778 779
    else if( i_sliderVolume > (VOLUME_MAX * 2 / 3 ) )
        volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-high.png" ) );
    else volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
780 781
}

782
void ControlsWidget::updateVolume()
783
{
784
    /* Audio part */
785 786
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
787
    i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
788 789 790 791 792 793 794 795
    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;
    }
796
}
797

798 799
void ControlsWidget::updateInput()
{
800
    /* Activate the interface buttons according to the presence of the input */
801
    enableInput( THEMIM->getIM()->hasInput() );
802
    enableVideo( THEMIM->getIM()->hasVideo() && THEMIM->getIM()->hasInput() );
803
}
804

805 806
void ControlsWidget::setStatus( int status )
{
807 808
    if( status == PLAYING_S ) /* Playing */
    {
809
        playButton->setIcon( QIcon( ":/pixmaps/pause.png" ) );
810 811
        playButton->setToolTip( qtr( "Pause" ) );
    }
812
    else
813
    {
814
        playButton->setIcon( QIcon( ":/pixmaps/play.png" ) );
815 816
        playButton->setToolTip( qtr( "Play" ) );
    }
817
}
818

819 820
/**
 * TODO
821
 * This functions toggle the fullscreen mode
822
 * If there is no video, it should first activate Visualisations...
823
 *  This has also to be fixed in enableVideo()
824
 */
Clément Stenac's avatar
Clément Stenac committed
825 826
void ControlsWidget::fullscreen()
{
827 828
    vout_thread_t *p_vout =
        (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
829
    if( p_vout)
830
    {
831
        var_SetBool( p_vout, "fullscreen", !var_GetBool( p_vout, "fullscreen" ) );
832
        vlc_object_release( p_vout );
833
    }
834 835 836 837 838 839
}

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

841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
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 );
856 857 858

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

861
void ControlsWidget::enableVideo( bool enable )
862
{
863 864
    // TODO Later make the fullscreenButton toggle Visualisation and so on.
    fullscreenButton->setEnabled( enable );
865 866 867

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
868 869
}

870 871 872 873 874 875 876 877 878 879 880 881
void ControlsWidget::toggleAdvanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        b_advancedVisible = true;
    }
    else
    {
        advControls->hide();
        b_advancedVisible = false;
    }