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

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

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

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

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

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

76 77
    /* The core can ask through a callback to show the video. */
    CONNECT( this, askVideoWidgetToShow(), this, show() );
78

79 80
    /* The core can ask through a callback to resize the video */
   // CONNECT( this, askResize( int, int ), this, SetSizing( int, int ) );
81 82
}

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

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

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

129
/* Set the Widget to the correct Size */
130 131
/* Function has to be called by the parent
   Parent has to care about resizing himself*/
132
void VideoWidget::SetSizing( unsigned int w, unsigned int h )
133
{
134 135 136 137
    msg_Dbg( p_intf, "Video is resizing to: %i %i", w, h );
    videoSize.rwidth() = w;
    videoSize.rheight() = h;
    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 );

488
    QPushButton  *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 );

506
    controlLayout->addWidget( telexFrame, 1, 10, 2, 4, Qt::AlignBottom );
507
    telexFrame->hide(); /* default hidden */
508 509 510

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
511 512 513

    BUTTON_SET_ACT_I( telexOn, "", tv.png, qtr( "Teletext on" ),
                      toggleTeletext() );
514 515
    CONNECT( telexOn, clicked( bool ), THEMIM->getIM(),
             telexToggle( bool ) );
516 517 518 519 520
    telexTransparent->setEnabled( false );
    telexPage->setEnabled( false );

    BUTTON_SET_ACT_I( telexTransparent, "", tvtelx.png, qtr( "Teletext" ),
                      toggleTeletextTransparency() );
521
    CONNECT( telexTransparent, clicked( bool ),
522
             THEMIM->getIM(), telexSetTransparency() );
523 524
    CONNECT( THEMIM->getIM(), teletextEnabled( bool ),
             telexFrame, setVisible( bool ) );
525

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

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

538
    controlLayout->addWidget( playButton, 2, 0, 2, 2 );
539

540 541
    controlLayout->setColumnMinimumWidth( 2, 20 );
    controlLayout->setColumnStretch( 2, 0 );
542 543

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

    /* Prev */
    QPushButton *prevButton = new QPushButton;
    prevButton->setSizePolicy( sizePolicy );
550
    setupSmallButton( prevButton );
551 552 553 554 555 556

    controlButLayout->addWidget( prevButton );

    /* Stop */
    QPushButton *stopButton = new QPushButton;
    stopButton->setSizePolicy( sizePolicy );
557
    setupSmallButton( stopButton );
558 559 560 561 562 563

    controlButLayout->addWidget( stopButton );

    /* next */
    QPushButton *nextButton = new QPushButton;
    nextButton->setSizePolicy( sizePolicy );
564
    setupSmallButton( nextButton );
565 566 567 568

    controlButLayout->addWidget( nextButton );

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

572
    BUTTON_SET_ACT_I( playButton, "", play.png, qtr( "Play" ), play() );
573
    BUTTON_SET_ACT_I( prevButton, "" , previous.png,
574 575 576
                      qtr( "Previous" ), prev() );
    BUTTON_SET_ACT_I( nextButton, "", next.png, qtr( "Next" ), next() );
    BUTTON_SET_ACT_I( stopButton, "", stop.png, qtr( "Stop" ), stop() );
577

578 579 580 581
    controlLayout->setColumnMinimumWidth( 7, 20 );
    controlLayout->setColumnStretch( 7, 0 );
    controlLayout->setColumnStretch( 8, 0 );
    controlLayout->setColumnStretch( 9, 0 );
582

583 584 585
    /*
     * Other first Line buttons
     */
586 587 588
    /** Fullscreen/Visualisation **/
    fullscreenButton = new QPushButton( "F" );
    BUTTON_SET_ACT( fullscreenButton, "F", qtr( "Fullscreen" ), fullscreen() );
589
    setupSmallButton( fullscreenButton );
590
    controlLayout->addWidget( fullscreenButton, 3, 10, Qt::AlignBottom );
591

592 593
    /** Playlist Button **/
    playlistButton = new QPushButton;
594
    setupSmallButton( playlistButton );
595
    controlLayout->addWidget( playlistButton, 3, 11, Qt::AlignBottom );
596
    BUTTON_SET_IMG( playlistButton, "" , playlist.png, qtr( "Show playlist" ) );
597
    CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );
598 599

    /** extended Settings **/
Lukas Durfina's avatar
Lukas Durfina committed
600
    extSettingsButton = new QPushButton;
601
    BUTTON_SET_ACT( extSettingsButton, "Ex", qtr( "Extended Settings" ),
602
            extSettings() );
603
    setupSmallButton( extSettingsButton );
604
    controlLayout->addWidget( extSettingsButton, 3, 12, Qt::AlignBottom );
605

606
    controlLayout->setColumnStretch( 13, 0 );
607
    controlLayout->setColumnMinimumWidth( 13, 24 );
608
    controlLayout->setColumnStretch( 14, 5 );
609

610
    /* Volume */
Lukas Durfina's avatar
Lukas Durfina committed
611
    hVolLabel = new VolumeClickHandler( p_intf, this );
612

613
    volMuteLabel = new QLabel;
614
    volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
615
    volMuteLabel->setToolTip( qtr( "Mute" ) );
616
    volMuteLabel->installEventFilter( hVolLabel );
617
    controlLayout->addWidget( volMuteLabel, 3, 15, Qt::AlignBottom );
618

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

636
    /* Set the volume from the config */
637 638
    volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
                              VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
639

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

643 644
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
645
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
646 647

    updateInput();
648
}
649

650
ControlsWidget::~ControlsWidget()
651
{}
652

653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
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;
    }
}

686 687 688 689 690 691 692
void ControlsWidget::stop()
{
    THEMIM->stop();
}

void ControlsWidget::play()
{
693
    if( THEPL->current.i_size == 0 )
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
    {
        /* 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 )
{
715 716 717 718 719
#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" )
720 721 722 723 724 725

    // 1 = chapter, 2 = title, 0 = no
    if( navigation == 0 )
    {
        discFrame->hide();
    } else if( navigation == 1 ) {
726 727
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
728 729 730
        menuButton->show();
        discFrame->show();
    } else {
731 732
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
733 734 735 736 737 738
        menuButton->hide();
        discFrame->show();
    }
}

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

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

771 772
void ControlsWidget::updateInput()
{
773
    /* Activate the interface buttons according to the presence of the input */
774
    enableInput( THEMIM->getIM()->hasInput() );
775
    enableVideo( THEMIM->getIM()->hasVideo() && THEMIM->getIM()->hasInput() );
776
}
777

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

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

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

814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
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 );
829 830 831

    /* Advanced Buttons too */
    advControls->enableInput( enable );
832 833
}

834
void ControlsWidget::enableVideo( bool enable )
835
{
836 837
    // TODO Later make the fullscreenButton toggle Visualisation and so on.
    fullscreenButton->setEnabled( enable );
838 839 840

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

843 844 845 846 847 848 849 850 851 852 853 854
void ControlsWidget::toggleAdvanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        b_advancedVisible = true;
    }
    else
    {
        advControls->hide();
        b_advancedVisible = false;
    }
855
    emit advancedControlsToggled( b_advancedVisible );
856
}
857

858

Lukas Durfina's avatar
Lukas Durfina committed
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
/**********************************************************************
 * Fullscrenn control widget
 **********************************************************************/
FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i,
        MainInterface *_p_mi, bool b_advControls, bool b_shiny )
        : ControlsWidget( _p_i, _p_mi, b_advControls, b_shiny, true ),
        i_lastPosX( -1 ), i_lastPosY( -1 ), i_hideTimeout( 1 ),
        b_mouseIsOver( false )
{
    setWindowFlags( Qt::ToolTip );

    setFrameShape( QFrame