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

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
59 60
#define I_PLAY_TOOLTIP "Play\nIf the playlist is empty, open a media"

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

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

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

82
    /* The core can ask through a callback to show the video. */
83
#if HAS_QT43
84 85 86
    connect( this, SIGNAL(askVideoWidgetToShow( unsigned int, unsigned int)),
             this, SLOT(SetSizing(unsigned int, unsigned int )),
             Qt::BlockingQueuedConnection );
87 88 89 90 91
#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
92 93
}

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

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

107 108 109 110 111 112 113 114 115 116 117 118
    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 );
        }
119
        vlc_object_release( p_vout );
120 121 122
    }
}

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

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

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

163 164 165 166
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
167

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

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

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

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

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

206
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
207 208
}

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

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

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

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

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

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

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

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

Clément Stenac's avatar
Clément Stenac committed
264
    setLayout( layout );
265
    setMaximumHeight( 35 );
Clément Stenac's avatar
Clément Stenac committed
266 267 268
}

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

Clément Stenac's avatar
Clément Stenac committed
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
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 );
    }
}
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
290
#endif
Clément Stenac's avatar
Clément Stenac committed
291 292

/**********************************************************************
293
 * TEH controls
Clément Stenac's avatar
Clément Stenac committed
294
 **********************************************************************/
295 296 297 298 299 300

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

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

309
    /* A to B Button */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
310
    ABButton = new QPushButton;
Lukas Durfina's avatar
Lukas Durfina committed
311
    setupSmallButton( ABButton );
312
    advLayout->addWidget( ABButton );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
313
    BUTTON_SET_ACT_I( ABButton, "", atob_nob,
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
314 315
      qtr( "Loop from point A to point B continuously.\nClick to set point A" ),
      fromAtoB() );
316
    timeA = timeB = 0;
317 318
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
             this, AtoBLoop( float, int, int ) );
319
#if 0
320 321 322 323
    frameButton = new QPushButton( "Fr" );
    frameButton->setMaximumSize( QSize( 26, 26 ) );
    frameButton->setIconSize( QSize( 20, 20 ) );
    advLayout->addWidget( frameButton );
324
    BUTTON_SET_ACT( frameButton, "Fr", qtr( "Frame by frame" ), frame() );
325
#endif
326

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
327
    recordButton = new QPushButton;
Lukas Durfina's avatar
Lukas Durfina committed
328
    setupSmallButton( recordButton );
329
    advLayout->addWidget( recordButton );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
330
    BUTTON_SET_ACT_I( recordButton, "", record,
331
            qtr( "Record" ), record() );
332

333
    /* Snapshot Button */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
334
    snapshotButton = new QPushButton;
Lukas Durfina's avatar
Lukas Durfina committed
335
    setupSmallButton( snapshotButton );
336
    advLayout->addWidget( snapshotButton );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
337 338
    BUTTON_SET_ACT_I( snapshotButton, "", snapshot,
            qtr( "Take a snapshot" ), snapshot() );
Clément Stenac's avatar
Clément Stenac committed
339 340
}

341
AdvControlsWidget::~AdvControlsWidget()
342
{}
Clément Stenac's avatar
Clément Stenac committed
343

344
void AdvControlsWidget::enableInput( bool enable )
Clément Stenac's avatar
Clément Stenac committed
345
{
346 347
    ABButton->setEnabled( enable );
    recordButton->setEnabled( enable );
Clément Stenac's avatar
Clément Stenac committed
348
}
349

350
void AdvControlsWidget::enableVideo( bool enable )
Clément Stenac's avatar
Clément Stenac committed
351 352
{
    snapshotButton->setEnabled( enable );
353
#if 0
354
    frameButton->setEnabled( enable );
355
#endif
Clément Stenac's avatar
Clément Stenac committed
356 357
}

358
void AdvControlsWidget::snapshot()
Clément Stenac's avatar
Clément Stenac committed
359
{
360 361
    vout_thread_t *p_vout =
        (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
362
    if( p_vout ) vout_Control( p_vout, VOUT_SNAPSHOT );
Clément Stenac's avatar
Clément Stenac committed
363 364
}

365
/* Function called when the button is clicked() */
366 367 368 369 370
void AdvControlsWidget::fromAtoB()
{
    if( !timeA )
    {
        timeA = var_GetTime( THEMIM->getInput(), "time"  );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
371 372
        ABButton->setToolTip( "Click to set point B" );
        ABButton->setIcon( QIcon( ":/atob_noa" ) );
373 374 375 376 377 378
        return;
    }
    if( !timeB )
    {
        timeB = var_GetTime( THEMIM->getInput(), "time"  );
        var_SetTime( THEMIM->getInput(), "time" , timeA );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
379 380
        ABButton->setIcon( QIcon( ":/atob" ) );
        ABButton->setToolTip( "Stop the A to B loop" );
381 382 383 384
        return;
    }
    timeA = 0;
    timeB = 0;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
385 386
    ABButton->setToolTip( qtr( "Loop from point A to point B continuously\nClick to set point A" ) );
    ABButton->setIcon( QIcon( ":/atob_nob" ) );
387
}
388

389
/* Function called regularly when in an AtoB loop */
390 391 392 393
void AdvControlsWidget::AtoBLoop( float f_pos, int i_time, int i_length )
{
    if( timeB )
    {
394
        if( i_time >= (int)(timeB/1000000) )
395 396 397
            var_SetTime( THEMIM->getInput(), "time" , timeA );
    }
}
398

399
/* FIXME Record function */
400
void AdvControlsWidget::record(){}
401

402
#if 0
403
//FIXME Frame by frame function
404
void AdvControlsWidget::frame(){}
405
#endif
406

407 408 409
/*****************************
 * DA Control Widget !
 *****************************/
410
ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
411
                                MainInterface *_p_mi,
412
                                bool b_advControls,
Lukas Durfina's avatar
Lukas Durfina committed
413 414 415
                                bool b_shiny,
                                bool b_fsCreation) :
                                QFrame( _p_mi ), p_intf( _p_i )
416
{
417
    setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
418

419 420 421 422
    /** The main Slider **/
    slider = new InputSlider( Qt::Horizontal, NULL );
    /* Update the position when the IM has changed */
    CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
423
             slider, setPosition( float, int, int ) );
424 425 426 427
    /* And update the IM, when the position has changed */
    CONNECT( slider, sliderDragged( float ),
             THEMIM->getIM(), sliderUpdate( float ) );

428
    /** Slower and faster Buttons **/
429 430
    slowerButton = new QToolButton;
    slowerButton->setAutoRaise( true );
431
    slowerButton->setMaximumSize( QSize( 26, 20 ) );
432

433
    BUTTON_SET_ACT( slowerButton, "-", qtr( "Slower" ), slower() );
434

435 436
    fasterButton = new QToolButton;
    fasterButton->setAutoRaise( true );
437
    fasterButton->setMaximumSize( QSize( 26, 20 ) );
438

439
    BUTTON_SET_ACT( fasterButton, "+", qtr( "Faster" ), faster() );
440

441 442 443 444 445 446
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

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

447
    /** Disc and Menus handling */
448
    discFrame = new QWidget( this );
449

450 451 452
    QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
    discLayout->setSpacing( 0 );
    discLayout->setMargin( 0 );
453

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

458
    menuButton = new QPushButton( discFrame );
459 460 461
    setupSmallButton( menuButton );
    discLayout->addWidget( menuButton );

462
    nextSectionButton = new QPushButton( discFrame );
463
    setupSmallButton( nextSectionButton );
464 465
    discLayout->addWidget( nextSectionButton );

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
466 467 468
    BUTTON_SET_IMG( prevSectionButton, "", dvd_prev, "" );
    BUTTON_SET_IMG( nextSectionButton, "", dvd_next, "" );
    BUTTON_SET_IMG( menuButton, "", dvd_menu, qtr( "Menu" ) );
469

470
    discFrame->hide();
471 472 473

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

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

Lukas Durfina's avatar
Lukas Durfina committed
492
    telexOn = new QPushButton;
493 494 495
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

496
    telexTransparent = new QPushButton;
497 498
    setupSmallButton( telexTransparent );
    telexLayout->addWidget( telexTransparent );
499
    b_telexTransparent = false;
500

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

510
    telexFrame->hide(); /* default hidden */
511 512 513

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

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
517
    BUTTON_SET_IMG( telexOn, "", tv, qtr( "Teletext on" ) );
518

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

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
529
    BUTTON_SET_IMG( telexTransparent, "", tvtelx, qtr( "Teletext" ) );
530
    CONNECT( telexTransparent, clicked( bool ),
531
             THEMIM->getIM(), telexSetTransparency() );
Lukas Durfina's avatar
Lukas Durfina committed
532 533
    CONNECT( THEMIM->getIM(), toggleTelexTransparency(),
              this, toggleTeletextTransparency() );
534
    CONNECT( THEMIM->getIM(), teletextEnabled( bool ),
535
             this, enableTeletext( bool ) );
536

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

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

549

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

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

    controlButLayout->addWidget( prevButton );

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

    controlButLayout->addWidget( stopButton );

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

    controlButLayout->addWidget( nextButton );

    /* Add this block to the main layout */

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
577
    BUTTON_SET_ACT_I( playButton, "", play_b, qtr( I_PLAY_TOOLTIP ), play() );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
578
    BUTTON_SET_ACT_I( prevButton, "" , previous_b,
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
579 580 581 582
                      qtr( "Previous media in the playlist" ), prev() );
    BUTTON_SET_ACT_I( nextButton, "", next_b,
                      qtr( "Next media in the playlist" ), next() );
    BUTTON_SET_ACT_I( stopButton, "", stop_b, qtr( "Stop playback" ), stop() );
583 584 585 586

    /*
     * Other first Line buttons
     */
587
    /** Fullscreen/Visualisation **/
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
588
    fullscreenButton = new QPushButton;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
589 590
    BUTTON_SET_ACT_I( fullscreenButton, "", fullscreen,
            qtr( "Toggle the video in fullscreen" ), fullscreen() );
591
    setupSmallButton( fullscreenButton );
592

593 594 595 596 597
    if( !b_fsCreation )
    {
        /** Playlist Button **/
        playlistButton = new QPushButton;
        setupSmallButton( playlistButton );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
598
        BUTTON_SET_IMG( playlistButton, "" , playlist, qtr( "Show playlist" ) );
599 600 601 602
        CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );

        /** extended Settings **/
        extSettingsButton = new QPushButton;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
603
        BUTTON_SET_ACT_I( extSettingsButton, "", extended,
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
604
                qtr( "Show extended settings" ), extSettings() );
605 606
        setupSmallButton( extSettingsButton );
    }
607

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

611
    volMuteLabel = new QLabel;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
612
    volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) );
613
    volMuteLabel->installEventFilter( hVolLabel );
614

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

631
    /* Set the volume from the config */
632 633
    volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
                              VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
634

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

638 639
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
640
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
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 668 669 670 671 672 673 674 675 676 677 678
    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 );
    }

679
    updateInput();
680
}
681

682
ControlsWidget::~ControlsWidget()
683
{}
684

685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
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;
    }
}
701

702 703 704 705 706 707 708 709 710 711
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;
}
712 713 714 715 716

void ControlsWidget::toggleTeletextTransparency()
{
    if( b_telexTransparent )
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
717
        telexTransparent->setIcon( QIcon( ":/tvtelx" ) );
718 719 720 721 722
        telexTransparent->setToolTip( qtr( "Teletext" ) );
        b_telexTransparent = false;
    }
    else
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
723
        telexTransparent->setIcon( QIcon( ":/tvtelx-transparent" ) );
724 725 726 727 728
        telexTransparent->setToolTip( qtr( "Transparent" ) );
        b_telexTransparent = true;
    }
}

729 730 731 732 733 734 735
void ControlsWidget::stop()
{
    THEMIM->stop();
}

void ControlsWidget::play()
{
736
    if( THEPL->current.i_size == 0 )
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
    {
        /* 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 )
{
758 759
#define HELP_PCH N_( "Previous chapter" )
#define HELP_NCH N_( "Next chapter" )
760 761 762 763 764 765

    // 1 = chapter, 2 = title, 0 = no
    if( navigation == 0 )
    {
        discFrame->hide();
    } else if( navigation == 1 ) {
766 767
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
768 769 770
        menuButton->show();
        discFrame->show();
    } else {
771 772
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
773 774 775 776 777 778
        menuButton->hide();
        discFrame->show();
    }
}

static bool b_my_volume;
779
void ControlsWidget::updateVolume( int i_sliderVolume )
780 781 782
{
    if( !b_my_volume )
    {
783
        int i_res = i_sliderVolume  * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX;
784 785
        aout_VolumeSet( p_intf, i_res );
    }
786
    if( i_sliderVolume == 0 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
787
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
788
        volMuteLabel->setPixmap( QPixmap(":/volume-muted" ) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
789 790 791 792 793
        volMuteLabel->setToolTip( qtr( "Unmute" ) );
        return;
    }

    if( i_sliderVolume < VOLUME_MAX / 3 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
794
        volMuteLabel->setPixmap( QPixmap( ":/volume-low" ) );
795
    else if( i_sliderVolume > (VOLUME_MAX * 2 / 3 ) )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
796 797
        volMuteLabel->setPixmap( QPixmap( ":/volume-high" ) );
    else volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
798
    volMuteLabel->setToolTip( qtr( "Mute" ) );
799 800
}

801
void ControlsWidget::updateVolume()
802
{
803
    /* Audio part */
804 805
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
806
    i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
807 808 809 810 811 812 813 814
    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;
    }
815
}
816

817 818
void ControlsWidget::updateInput()
{
819
    /* Activate the interface buttons according to the presence of the input */
820
    enableInput( THEMIM->getIM()->hasInput() );
821
    enableVideo( THEMIM->getIM()->hasVideo() && THEMIM->getIM()->hasInput() );
822
}
823

824 825
void ControlsWidget::setStatus( int status )
{
826 827
    if( status == PLAYING_S ) /* Playing */
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
828
        playButton->setIcon( QIcon( ":/pause_b" ) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
829
        playButton->setToolTip( qtr( "Pause the playback" ) );
830
    }
831
    else
832
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
833
        playButton->setIcon( QIcon( ":/play_b" ) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
834
        playButton->setToolTip( qtr( I_PLAY_TOOLTIP ) );
835
    }
836
}
837

838 839
/**
 * TODO
840
 * This functions toggle the fullscreen mode
841
 * If there is no video, it should first activate Visualisations...
842
 *  This has also to be fixed in enableVideo()
843
 */
Clément Stenac's avatar
Clément Stenac committed
844 845
void ControlsWidget::fullscreen()
{
846 847
    vout_thread_t *p_vout =
        (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
848
    if( p_vout)
849
    {
850
        var_SetBool( p_vout, "fullscreen", !var_GetBool( p_vout, "fullscreen" ) );
851
        vlc_object_release( p_vout );
852
    }
853 854 855 856 857 858
}