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 583 584 585 586 587 588 589 590 591 592 593 594
    if( !b_fsCreation )
    {
        /** Playlist Button **/
        playlistButton = new QPushButton;
        setupSmallButton( playlistButton );
        BUTTON_SET_IMG( playlistButton, "" , playlist.png, qtr( "Show playlist" ) );
        CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );

        /** extended Settings **/
        extSettingsButton = new QPushButton;
        BUTTON_SET_ACT( extSettingsButton, "Ex", qtr( "Extended settings" ),
                extSettings() );
        setupSmallButton( extSettingsButton );
    }
595

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

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

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

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

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

627 628
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
629
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
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 666 667
    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 );
    }

668
    updateInput();
669
}
670

671
ControlsWidget::~ControlsWidget()
672
{}
673

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

691 692 693 694 695 696 697 698 699 700
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;
}
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717

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

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

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

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

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

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

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

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

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

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

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

    /* Advanced Buttons too */
    advControls->enableInput( enable );
861 862
}

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

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
870 871
}

872 873 874 875 876 877 878 879 880 881 882 883
void ControlsWidget::toggleAdvanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        b_advancedVisible = true;
    }
    else
    {
        advControls->hide();
        b_advancedVisible = false;
    }
884
    emit advancedControlsToggled( b_advancedVisible );
885
}
886

887

Lukas Durfina's avatar
Lukas Durfina committed
888 889 890 891 892 893
/**********************************************************************
 * Fullscrenn control widget
 **********************************************************************/
FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i,
        MainInterface *_p_mi, bool b_advControls, bool b_shiny )
        : ControlsWidget( _p_i, _p_mi, b_advControls, b_shiny, true ),
894