interface_widgets.cpp 37.2 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 54
/**********************************************************************
 * Video Widget. A simple frame on which video is drawn
 * This class handles resize issues
 **********************************************************************/
55

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

65 66 67 68 69 70
    /* 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 );

71 72 73 74 75 76 77 78
    /* The core can ask through a callback to show the video.
     * NOTE: We need to block the video output core until the window handle
     * is ready for use (otherwise an X11 invalid handle failure may occur).
     * As a side effect, it is illegal to emit askVideoWidgetToShow from
     * the same thread as the Qt4 thread that owns this. */
    QObject::connect( this, SIGNAL(askVideoWidgetToShow()), this, SLOT(show()),
                      Qt::BlockingQueuedConnection );

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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
}

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

103
/**
104
 * Request the video to avoid the conflicts
105
 **/
106
void *VideoWidget::request( vout_thread_t *p_nvout, int *pi_x, int *pi_y,
107 108
                           unsigned int *pi_width, unsigned int *pi_height )
{
109
    msg_Dbg( p_intf, "Video was requested %i, %i", *pi_x, *pi_y );
110
    emit askVideoWidgetToShow();
111 112 113 114 115 116
    if( p_vout )
    {
        msg_Dbg( p_intf, "embedded video already in use" );
        return NULL;
    }
    p_vout = p_nvout;
117
    msg_Dbg( p_intf, "embedded video handle %p", winId() );
118
    return ( void* )winId();
119 120
}

121
/* Set the Widget to the correct Size */
122 123
/* Function has to be called by the parent
   Parent has to care about resizing himself*/
124
void VideoWidget::SetSizing( unsigned int w, unsigned int h )
125
{
126 127 128 129
    msg_Dbg( p_intf, "Video is resizing to: %i %i", w, h );
    videoSize.rwidth() = w;
    videoSize.rheight() = h;
    updateGeometry(); // Needed for deinterlace
130 131
}

132
void VideoWidget::release( void *p_win )
133
{
134
    msg_Dbg( p_intf, "Video is non needed anymore" );
135
    p_vout = NULL;
136 137 138 139
    videoSize.rwidth() = 0;
    videoSize.rheight() = 0;
    hide();
    updateGeometry(); // Needed for deinterlace
140
}
141

142 143 144 145
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
146

147 148
/**********************************************************************
 * Background Widget. Show a simple image background. Currently,
149
 * it's album art if present or cone.
150
 **********************************************************************/
151 152 153 154
#define ICON_SIZE 128
#define MAX_BG_SIZE 400
#define MIN_BG_SIZE 64

155 156
BackgroundWidget::BackgroundWidget( intf_thread_t *_p_i )
                 :QWidget( NULL ), p_intf( _p_i )
157
{
158
    /* We should use that one to take the more size it can */
159
//    setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
160

161
    /* A dark background */
Clément Stenac's avatar
Clément Stenac committed
162
    setAutoFillBackground( true );
163 164 165 166 167
    plt =  palette();
    plt.setColor( QPalette::Active, QPalette::Window , Qt::black );
    plt.setColor( QPalette::Inactive, QPalette::Window , Qt::black );
    setPalette( plt );

168
    /* A cone in the middle */
169
    label = new QLabel;
170
    label->setMargin( 5 );
171 172
    label->setMaximumHeight( MAX_BG_SIZE );
    label->setMaximumWidth( MAX_BG_SIZE );
173 174
    label->setMinimumHeight( MIN_BG_SIZE );
    label->setMinimumWidth( MIN_BG_SIZE );
175 176 177 178
    if( QDate::currentDate().dayOfYear() >= 354 )
        label->setPixmap( QPixmap( ":/vlc128-christmas.png" ) );
    else
        label->setPixmap( QPixmap( ":/vlc128.png" ) );
179

180 181 182 183
    QGridLayout *backgroundLayout = new QGridLayout( this );
    backgroundLayout->addWidget( label, 0, 1 );
    backgroundLayout->setColumnStretch( 0, 1 );
    backgroundLayout->setColumnStretch( 2, 1 );
184

185
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
186 187
}

Clément Stenac's avatar
Clément Stenac committed
188
BackgroundWidget::~BackgroundWidget()
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
189 190 191
{
}

192 193 194 195 196 197 198 199
void BackgroundWidget::resizeEvent( QResizeEvent * event )
{
    if( event->size().height() <= MIN_BG_SIZE )
        label->hide();
    else
        label->show();
}

200
void BackgroundWidget::updateArt( QString url )
201
{
202
    if( url.isEmpty() )
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
203
    {
204 205 206 207
        if( QDate::currentDate().dayOfYear() >= 354 )
            label->setPixmap( QPixmap( ":/vlc128-christmas.png" ) );
        else
            label->setPixmap( QPixmap( ":/vlc128.png" ) );
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
208 209
        return;
    }
210
    else
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
211
    {
212
        label->setPixmap( QPixmap( url ) );
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
213
    }
214 215
}

216 217 218 219
void BackgroundWidget::contextMenuEvent( QContextMenuEvent *event )
{
    QVLCMenu::PopupMenu( p_intf, true );
}
220

Clément Stenac's avatar
Clément Stenac committed
221 222 223 224
/**********************************************************************
 * Visualization selector panel
 **********************************************************************/
VisualSelector::VisualSelector( intf_thread_t *_p_i ) :
225
                                QFrame( NULL ), p_intf( _p_i )
Clément Stenac's avatar
Clément Stenac committed
226 227
{
    QHBoxLayout *layout = new QHBoxLayout( this );
228
    layout->setMargin( 0 );
Clément Stenac's avatar
Clément Stenac committed
229
    QPushButton *prevButton = new QPushButton( "Prev" );
230
    QPushButton *nextButton = new QPushButton( "Next" );
Clément Stenac's avatar
Clément Stenac committed
231 232
    layout->addWidget( prevButton );
    layout->addWidget( nextButton );
Clément Stenac's avatar
Clément Stenac committed
233 234

    layout->addItem( new QSpacerItem( 40,20,
235 236
                              QSizePolicy::Expanding, QSizePolicy::Minimum ) );
    layout->addWidget( new QLabel( qtr( "Current visualization:" ) ) );
Clément Stenac's avatar
Clément Stenac committed
237 238 239 240 241 242 243

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

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

Clément Stenac's avatar
Clément Stenac committed
244
    setLayout( layout );
245
    setMaximumHeight( 35 );
Clément Stenac's avatar
Clément Stenac committed
246 247 248 249 250 251
}

VisualSelector::~VisualSelector()
{
}

Clément Stenac's avatar
Clément Stenac committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
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 );
    }
}

/**********************************************************************
273
 * TEH controls
Clément Stenac's avatar
Clément Stenac committed
274
 **********************************************************************/
275 276 277 278 279 280

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

281
AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i ) :
Clément Stenac's avatar
Clément Stenac committed
282 283
                                           QFrame( NULL ), p_intf( _p_i )
{
284 285 286
    QHBoxLayout *advLayout = new QHBoxLayout( this );
    advLayout->setMargin( 0 );
    advLayout->setSpacing( 0 );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
287
    advLayout->setAlignment( Qt::AlignBottom );
Clément Stenac's avatar
Clément Stenac committed
288

289
    /* A to B Button */
290
    ABButton = new QPushButton( "AB" );
Lukas Durfina's avatar
Lukas Durfina committed
291
    setupSmallButton( ABButton );
292
    advLayout->addWidget( ABButton );
293
    BUTTON_SET_ACT( ABButton, "AB", qtr( "A to B" ), fromAtoB() );
294
    timeA = timeB = 0;
295 296
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
             this, AtoBLoop( float, int, int ) );
297
#if 0
298 299 300 301 302
    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() );
303
#endif
304 305

    recordButton = new QPushButton( "R" );
Lukas Durfina's avatar
Lukas Durfina committed
306
    setupSmallButton( recordButton );
307
    advLayout->addWidget( recordButton );
308
    BUTTON_SET_ACT_I( recordButton, "", record_16px.png,
309
            qtr( "Record" ), record() );
310

311
    /* Snapshot Button */
312
    snapshotButton = new QPushButton( "S" );
Lukas Durfina's avatar
Lukas Durfina committed
313
    setupSmallButton( snapshotButton );
314 315
    advLayout->addWidget( snapshotButton );
    BUTTON_SET_ACT( snapshotButton, "S", qtr( "Take a snapshot" ), snapshot() );
Clément Stenac's avatar
Clément Stenac committed
316 317
}

318
AdvControlsWidget::~AdvControlsWidget()
319
{}
Clément Stenac's avatar
Clément Stenac committed
320

321
void AdvControlsWidget::enableInput( bool enable )
Clément Stenac's avatar
Clément Stenac committed
322
{
323 324
    ABButton->setEnabled( enable );
    recordButton->setEnabled( enable );
Clément Stenac's avatar
Clément Stenac committed
325
}
326

327
void AdvControlsWidget::enableVideo( bool enable )
Clément Stenac's avatar
Clément Stenac committed
328 329
{
    snapshotButton->setEnabled( enable );
330
#if 0
331
    frameButton->setEnabled( enable );
332
#endif
Clément Stenac's avatar
Clément Stenac committed
333 334
}

335
void AdvControlsWidget::snapshot()
Clément Stenac's avatar
Clément Stenac committed
336
{
337 338
    vout_thread_t *p_vout =
        (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
339
    if( p_vout ) vout_Control( p_vout, VOUT_SNAPSHOT );
Clément Stenac's avatar
Clément Stenac committed
340 341
}

342
/* Function called when the button is clicked() */
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
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" );
}
362

363
/* Function called regularly when in an AtoB loop */
364 365 366 367
void AdvControlsWidget::AtoBLoop( float f_pos, int i_time, int i_length )
{
    if( timeB )
    {
368
        if( i_time >= (int)(timeB/1000000) )
369 370 371
            var_SetTime( THEMIM->getInput(), "time" , timeA );
    }
}
372

373
/* FIXME Record function */
374
void AdvControlsWidget::record(){}
375

376
#if 0
377
//FIXME Frame by frame function
378
void AdvControlsWidget::frame(){}
379
#endif
380

381 382 383
/*****************************
 * DA Control Widget !
 *****************************/
384
ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
385
                                MainInterface *_p_mi,
386
                                bool b_advControls,
Lukas Durfina's avatar
Lukas Durfina committed
387 388 389
                                bool b_shiny,
                                bool b_fsCreation) :
                                QFrame( _p_mi ), p_intf( _p_i )
390
{
Lukas Durfina's avatar
Lukas Durfina committed
391 392
    controlLayout = new QGridLayout( );

393
    controlLayout->setSpacing( 0 );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
394
    controlLayout->setLayoutMargins( 7, 5, 7, 3, 6 );
395

Lukas Durfina's avatar
Lukas Durfina committed
396 397 398
    if( !b_fsCreation )
        setLayout( controlLayout );

399
    setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
400

401 402
    /** The main Slider **/
    slider = new InputSlider( Qt::Horizontal, NULL );
403
    controlLayout->addWidget( slider, 0, 1, 1, 16 );
404 405
    /* Update the position when the IM has changed */
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
406
             slider, setPosition( float, int, int ) );
407 408 409 410
    /* And update the IM, when the position has changed */
    CONNECT( slider, sliderDragged( float ),
             THEMIM->getIM(), sliderUpdate( float ) );

411
    /** Slower and faster Buttons **/
412 413
    slowerButton = new QToolButton;
    slowerButton->setAutoRaise( true );
414
    slowerButton->setMaximumSize( QSize( 26, 20 ) );
415

416
    BUTTON_SET_ACT( slowerButton, "-", qtr( "Slower" ), slower() );
417 418
    controlLayout->addWidget( slowerButton, 0, 0 );

419 420
    fasterButton = new QToolButton;
    fasterButton->setAutoRaise( true );
421
    fasterButton->setMaximumSize( QSize( 26, 20 ) );
422

423
    BUTTON_SET_ACT( fasterButton, "+", qtr( "Faster" ), faster() );
424
    controlLayout->addWidget( fasterButton, 0, 17 );
425

426 427 428 429
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

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

433
    /** Disc and Menus handling */
434
    discFrame = new QWidget( this );
435

436 437 438
    QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
    discLayout->setSpacing( 0 );
    discLayout->setMargin( 0 );
439

440
    prevSectionButton = new QPushButton( discFrame );
441
    setupSmallButton( prevSectionButton );
442 443
    discLayout->addWidget( prevSectionButton );

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

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

452
    controlLayout->addWidget( discFrame, 1, 10, 2, 3, Qt::AlignBottom );
453 454 455 456 457

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

458
    discFrame->hide();
459 460 461

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

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

480
    QPushButton  *telexOn = new QPushButton;
481 482 483
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

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

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

    controlLayout->addWidget( telexFrame, 1, 10, 2, 3, Qt::AlignBottom );
499
    telexFrame->hide(); /* default hidden */
500 501 502

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
503 504 505

    BUTTON_SET_ACT_I( telexOn, "", tv.png, qtr( "Teletext on" ),
                      toggleTeletext() );
506 507
    CONNECT( telexOn, clicked( bool ), THEMIM->getIM(),
             telexToggle( bool ) );
508 509 510 511 512
    telexTransparent->setEnabled( false );
    telexPage->setEnabled( false );

    BUTTON_SET_ACT_I( telexTransparent, "", tvtelx.png, qtr( "Teletext" ),
                      toggleTeletextTransparency() );
513
    CONNECT( telexTransparent, clicked( bool ),
514
             THEMIM->getIM(), telexSetTransparency() );
515 516
    CONNECT( THEMIM->getIM(), teletextEnabled( bool ),
             telexFrame, setVisible( bool ) );
517

518
    /** Play Buttons **/
519
    QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
520 521 522 523
    sizePolicy.setHorizontalStretch( 0 );
    sizePolicy.setVerticalStretch( 0 );

    /* Play */
524
    playButton = new QPushButton;
525
    playButton->setSizePolicy( sizePolicy );
526 527
    playButton->setMaximumSize( QSize( 36, 36 ) );
    playButton->setMinimumSize( QSize( 36, 36 ) );
528
    playButton->setIconSize( QSize( 30, 30 ) );
529

530
    controlLayout->addWidget( playButton, 2, 0, 2, 2 );
531

532 533
    controlLayout->setColumnMinimumWidth( 2, 20 );
    controlLayout->setColumnStretch( 2, 0 );
534 535

    /** Prev + Stop + Next Block **/
Lukas Durfina's avatar
Lukas Durfina committed
536
    controlButLayout = new QHBoxLayout;
537 538 539 540 541
    controlButLayout->setSpacing( 0 ); /* Don't remove that, will be useful */

    /* Prev */
    QPushButton *prevButton = new QPushButton;
    prevButton->setSizePolicy( sizePolicy );
542
    setupSmallButton( prevButton );
543 544 545 546 547 548

    controlButLayout->addWidget( prevButton );

    /* Stop */
    QPushButton *stopButton = new QPushButton;
    stopButton->setSizePolicy( sizePolicy );
549
    setupSmallButton( stopButton );
550 551 552 553 554 555

    controlButLayout->addWidget( stopButton );

    /* next */
    QPushButton *nextButton = new QPushButton;
    nextButton->setSizePolicy( sizePolicy );
556
    setupSmallButton( nextButton );
557 558 559 560

    controlButLayout->addWidget( nextButton );

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

564
    BUTTON_SET_ACT_I( playButton, "", play.png, qtr( "Play" ), play() );
565
    BUTTON_SET_ACT_I( prevButton, "" , previous.png,
566 567 568
                      qtr( "Previous" ), prev() );
    BUTTON_SET_ACT_I( nextButton, "", next.png, qtr( "Next" ), next() );
    BUTTON_SET_ACT_I( stopButton, "", stop.png, qtr( "Stop" ), stop() );
569

570 571 572 573
    controlLayout->setColumnMinimumWidth( 7, 20 );
    controlLayout->setColumnStretch( 7, 0 );
    controlLayout->setColumnStretch( 8, 0 );
    controlLayout->setColumnStretch( 9, 0 );
574

575 576 577
    /*
     * Other first Line buttons
     */
578 579 580
    /** Fullscreen/Visualisation **/
    fullscreenButton = new QPushButton( "F" );
    BUTTON_SET_ACT( fullscreenButton, "F", qtr( "Fullscreen" ), fullscreen() );
581
    setupSmallButton( fullscreenButton );
582
    controlLayout->addWidget( fullscreenButton, 3, 10, Qt::AlignBottom );
583

584 585
    /** Playlist Button **/
    playlistButton = new QPushButton;
586
    setupSmallButton( playlistButton );
587
    controlLayout->addWidget( playlistButton, 3, 11, Qt::AlignBottom );
588
    BUTTON_SET_IMG( playlistButton, "" , playlist.png, qtr( "Show playlist" ) );
589
    CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );
590 591

    /** extended Settings **/
Lukas Durfina's avatar
Lukas Durfina committed
592
    extSettingsButton = new QPushButton;
593
    BUTTON_SET_ACT( extSettingsButton, "Ex", qtr( "Extended Settings" ),
594
            extSettings() );
595
    setupSmallButton( extSettingsButton );
596
    controlLayout->addWidget( extSettingsButton, 3, 12, Qt::AlignBottom );
597

598
    controlLayout->setColumnStretch( 13, 0 );
599
    controlLayout->setColumnMinimumWidth( 13, 24 );
600
    controlLayout->setColumnStretch( 14, 5 );
601

602
    /* Volume */
Lukas Durfina's avatar
Lukas Durfina committed
603
    hVolLabel = new VolumeClickHandler( p_intf, this );
604

605
    volMuteLabel = new QLabel;
606
    volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
607
    volMuteLabel->setToolTip( qtr( "Mute" ) );
608
    volMuteLabel->installEventFilter( hVolLabel );
609
    controlLayout->addWidget( volMuteLabel, 3, 15, Qt::AlignBottom );
610

611 612 613
    if( b_shiny )
    {
        volumeSlider = new SoundSlider( this,
614
            config_GetInt( p_intf, "volume-step" ),
615 616
            config_GetInt( p_intf, "qt-volume-complete" ),
            config_GetPsz( p_intf, "qt-slider-colours" ) );
617 618 619 620 621 622
    }
    else
    {
        volumeSlider = new QSlider( this );
        volumeSlider->setOrientation( Qt::Horizontal );
    }
623
    volumeSlider->setMaximumSize( QSize( 200, 40 ) );
624
    volumeSlider->setMinimumSize( QSize( 106, 30 ) );
625
    volumeSlider->setFocusPolicy( Qt::NoFocus );
626
    controlLayout->addWidget( volumeSlider, 2, 16, 2 , 2, Qt::AlignBottom );
627

628
    /* Set the volume from the config */
629 630
    volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
                              VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
631

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

635 636
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
637
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
638 639

    updateInput();
640
}
641

642
ControlsWidget::~ControlsWidget()
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 668 669 670 671 672 673 674 675 676 677
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;
    }
}

678 679 680 681 682 683 684
void ControlsWidget::stop()
{
    THEMIM->stop();
}

void ControlsWidget::play()
{
685
    if( THEPL->current.i_size == 0 )
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
    {
        /* 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 )
{
707 708 709 710 711
#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" )
712 713 714 715 716 717

    // 1 = chapter, 2 = title, 0 = no
    if( navigation == 0 )
    {
        discFrame->hide();
    } else if( navigation == 1 ) {
718 719
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
720 721 722
        menuButton->show();
        discFrame->show();
    } else {
723 724
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
725 726 727 728 729 730
        menuButton->hide();
        discFrame->show();
    }
}

static bool b_my_volume;
731
void ControlsWidget::updateVolume( int i_sliderVolume )
732 733 734
{
    if( !b_my_volume )
    {
735
        int i_res = i_sliderVolume  * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX;
736 737
        aout_VolumeSet( p_intf, i_res );
    }
738 739
    if( i_sliderVolume == 0 )
        volMuteLabel->setPixmap( QPixmap(":/pixmaps/volume-muted.png" ) );
740
    else if( i_sliderVolume < VOLUME_MAX / 3 )
741
        volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-low.png" ) );
742 743 744
    else if( i_sliderVolume > (VOLUME_MAX * 2 / 3 ) )
        volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-high.png" ) );
    else volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
745 746
}

747
void ControlsWidget::updateVolume()
748
{
749
    /* Audio part */
750 751
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
752
    i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
753 754 755 756 757 758 759 760
    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;
    }
761
}
762

763 764
void ControlsWidget::updateInput()
{
765
    /* Activate the interface buttons according to the presence of the input */
766
    enableInput( THEMIM->getIM()->hasInput() );
767
    enableVideo( THEMIM->getIM()->hasVideo() && THEMIM->getIM()->hasInput() );
768
}
769

770 771
void ControlsWidget::setStatus( int status )
{
772 773
    if( status == PLAYING_S ) /* Playing */
    {
774
        playButton->setIcon( QIcon( ":/pixmaps/pause.png" ) );
775 776
        playButton->setToolTip( qtr( "Pause" ) );
    }
777
    else
778
    {
779
        playButton->setIcon( QIcon( ":/pixmaps/play.png" ) );
780 781
        playButton->setToolTip( qtr( "Play" ) );
    }
782
}
783

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

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

806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
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 );
821 822 823

    /* Advanced Buttons too */
    advControls->enableInput( enable );
824 825
}

826
void ControlsWidget::enableVideo( bool enable )
827
{
828 829
    // TODO Later make the fullscreenButton toggle Visualisation and so on.
    fullscreenButton->setEnabled( enable );
830 831 832

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
833 834
}

835 836 837 838 839 840 841 842 843 844 845 846
void ControlsWidget::toggleAdvanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        b_advancedVisible = true;
    }
    else
    {
        advControls->hide();
        b_advancedVisible = false;
    }
847
    emit advancedControlsToggled( b_advancedVisible );
848
}
849

850

Lukas Durfina's avatar
Lukas Durfina committed
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
/**********************************************************************
 * 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::StyledPanel );
    setFrameStyle( QFrame::Sunken );
    setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );

    QGridLayout *fsLayout = new QGridLayout( this );
    controlLayout->setSpacing( 0 );
868
    controlLayout->setLayoutMargins( 5, 1, 5, 1, 5 );
Lukas Durfina's avatar
Lukas Durfina committed
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895

    fsLayout->addWidget( slowerButton, 0, 0 );
    slider->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum);
    fsLayout->addWidget( slider, 0, 1, 1, 6 );
    fsLayout->addWidget( fasterButton, 0, 7 );

    fsLayout->addWidget( volMuteLabel, 1, 0);
    fsLayout->addWidget( volumeSlider, 1, 1 );

    fsLayout->addLayout( controlButLayout, 1, 2 );

    fsLayout->addWidget( playButton, 1, 3 );

    fsLayout->addWidget( discFrame, 1, 4 );

    fsLayout->addWidget( telexFrame, 1, 5 );

    fsLayout->addWidget( advControls, 1, 6, Qt::AlignVCenter );

    fsLayout->addWidget( fullscreenButton, 1, 7 );

    /* hiding timer */
    p_hideTimer = new QTimer( this );