interface_widgets.cpp 36.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
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
29

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

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

50 51 52 53
/**********************************************************************
 * Video Widget. A simple frame on which video is drawn
 * This class handles resize issues
 **********************************************************************/
54 55 56 57 58
static void *DoRequest( intf_thread_t *, vout_thread_t *, int*,int*,
                        unsigned int *, unsigned int * );
static void DoRelease( intf_thread_t *, void * );
static int DoControl( intf_thread_t *, void *, int, va_list );

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

68 69 70 71 72 73 74
    /* 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 );

    /* The core can ask through a callback to show the video */
75
    CONNECT( this, askVideoWidgetToShow(), this, show() );
76 77
    /* The core can ask through a callback to resize the video */
   // CONNECT( this, askResize( int, int ), this, SetSizing( int, int ) );
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
}

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

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

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

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

138 139 140 141
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
142

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

151 152
BackgroundWidget::BackgroundWidget( intf_thread_t *_p_i )
                 :QWidget( NULL ), p_intf( _p_i )
153
{
154
    /* We should use that one to take the more size it can */
155
//    setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
156

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

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

176 177 178 179
    QGridLayout *backgroundLayout = new QGridLayout( this );
    backgroundLayout->addWidget( label, 0, 1 );
    backgroundLayout->setColumnStretch( 0, 1 );
    backgroundLayout->setColumnStretch( 2, 1 );
180

181
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
182 183
}

Clément Stenac's avatar
Clément Stenac committed
184
BackgroundWidget::~BackgroundWidget()
Ilkka Ollakka's avatar
 
Ilkka Ollakka committed
185 186 187
{
}

188 189 190 191 192 193 194 195
void BackgroundWidget::resizeEvent( QResizeEvent * event )
{
    if( event->size().height() <= MIN_BG_SIZE )
        label->hide();
    else
        label->show();
}

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

212 213 214 215
void BackgroundWidget::contextMenuEvent( QContextMenuEvent *event )
{
    QVLCMenu::PopupMenu( p_intf, true );
}
216

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

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

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

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

Clément Stenac's avatar
Clément Stenac committed
240
    setLayout( layout );
241
    setMaximumHeight( 35 );
Clément Stenac's avatar
Clément Stenac committed
242 243 244 245 246 247
}

VisualSelector::~VisualSelector()
{
}

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

/**********************************************************************
269
 * TEH controls
Clément Stenac's avatar
Clément Stenac committed
270
 **********************************************************************/
271 272 273 274 275 276

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

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

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

    recordButton = new QPushButton( "R" );
Lukas Durfina's avatar
Lukas Durfina committed
302
    setupSmallButton( recordButton );
303
    advLayout->addWidget( recordButton );
304
    BUTTON_SET_ACT_I( recordButton, "", record_16px.png,
305
            qtr( "Record" ), record() );
306

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

314
AdvControlsWidget::~AdvControlsWidget()
315
{}
Clément Stenac's avatar
Clément Stenac committed
316

317
void AdvControlsWidget::enableInput( bool enable )
Clément Stenac's avatar
Clément Stenac committed
318
{
319 320
    ABButton->setEnabled( enable );
    recordButton->setEnabled( enable );
Clément Stenac's avatar
Clément Stenac committed
321
}
322

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

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

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

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

369
/* FIXME Record function */
370
void AdvControlsWidget::record(){}
371

372
#if 0
373
//FIXME Frame by frame function
374
void AdvControlsWidget::frame(){}
375
#endif
376

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

389
    controlLayout->setSpacing( 0 );
390 391 392 393 394
#if QT43
    controlLayout->setContentsMargins( 9, 6, 9, 6 );
#else
    controlLayout->setMargin( 6 );
#endif
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
     * Telextext QFrame
472
     * TODO: Merge with upper menu in a StackLayout
473
     **/
474
#ifdef ZVBI_COMPILED
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
    telexFrame = new QWidget( this );
    QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame );
    telexLayout->setSpacing( 0 );
    telexLayout->setMargin( 0 );

    QToolButton *telexOn = new QToolButton;
    telexOn->setText( qtr( "On" ) );
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

    QToolButton *telexTransparent = new QToolButton;
    telexTransparent->setText( qtr( "Transparent" ) );
    setupSmallButton( telexTransparent );
    telexLayout->addWidget( telexTransparent );

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

    controlLayout->addWidget( telexFrame, 1, 10, 2, 3, Qt::AlignBottom );
500
    telexFrame->hide();
501 502 503 504 505 506 507 508 509

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
    CONNECT( telexOn, clicked( bool ), THEMIM->getIM(),
             telexToggle( bool ) );
    CONNECT( telexTransparent, clicked( bool ),
             THEMIM->getIM(), telexSetTransparency( bool ) );
    CONNECT( THEMIM->getIM(), teletextEnabled( bool ),
             telexFrame, setVisible( bool ) );
510
#endif
511

512
    /** Play Buttons **/
513
    QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
514 515 516 517
    sizePolicy.setHorizontalStretch( 0 );
    sizePolicy.setVerticalStretch( 0 );

    /* Play */
518
    playButton = new QPushButton;
519
    playButton->setSizePolicy( sizePolicy );
520 521
    playButton->setMaximumSize( QSize( 36, 36 ) );
    playButton->setMinimumSize( QSize( 36, 36 ) );
522
    playButton->setIconSize( QSize( 30, 30 ) );
523

524
    controlLayout->addWidget( playButton, 2, 0, 2, 2 );
525

526 527
    controlLayout->setColumnMinimumWidth( 2, 20 );
    controlLayout->setColumnStretch( 2, 0 );
528 529

    /** Prev + Stop + Next Block **/
Lukas Durfina's avatar
Lukas Durfina committed
530
    controlButLayout = new QHBoxLayout;
531 532 533 534 535
    controlButLayout->setSpacing( 0 ); /* Don't remove that, will be useful */

    /* Prev */
    QPushButton *prevButton = new QPushButton;
    prevButton->setSizePolicy( sizePolicy );
536
    setupSmallButton( prevButton );
537 538 539 540 541 542

    controlButLayout->addWidget( prevButton );

    /* Stop */
    QPushButton *stopButton = new QPushButton;
    stopButton->setSizePolicy( sizePolicy );
543
    setupSmallButton( stopButton );
544 545 546 547 548 549

    controlButLayout->addWidget( stopButton );

    /* next */
    QPushButton *nextButton = new QPushButton;
    nextButton->setSizePolicy( sizePolicy );
550
    setupSmallButton( nextButton );
551 552 553 554

    controlButLayout->addWidget( nextButton );

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

558
    BUTTON_SET_ACT_I( playButton, "", play.png, qtr( "Play" ), play() );
559
    BUTTON_SET_ACT_I( prevButton, "" , previous.png,
560 561 562
                      qtr( "Previous" ), prev() );
    BUTTON_SET_ACT_I( nextButton, "", next.png, qtr( "Next" ), next() );
    BUTTON_SET_ACT_I( stopButton, "", stop.png, qtr( "Stop" ), stop() );
563

564 565 566 567
    controlLayout->setColumnMinimumWidth( 7, 20 );
    controlLayout->setColumnStretch( 7, 0 );
    controlLayout->setColumnStretch( 8, 0 );
    controlLayout->setColumnStretch( 9, 0 );
568

569 570 571
    /*
     * Other first Line buttons
     */
572 573 574
    /** Fullscreen/Visualisation **/
    fullscreenButton = new QPushButton( "F" );
    BUTTON_SET_ACT( fullscreenButton, "F", qtr( "Fullscreen" ), fullscreen() );
575
    setupSmallButton( fullscreenButton );
576
    controlLayout->addWidget( fullscreenButton, 3, 10, Qt::AlignBottom );
577

578 579
    /** Playlist Button **/
    playlistButton = new QPushButton;
580
    setupSmallButton( playlistButton );
581
    controlLayout->addWidget( playlistButton, 3, 11, Qt::AlignBottom );
582
    BUTTON_SET_IMG( playlistButton, "" , playlist.png, qtr( "Show playlist" ) );
583
    CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );
584 585

    /** extended Settings **/
Lukas Durfina's avatar
Lukas Durfina committed
586
    extSettingsButton = new QPushButton;
587
    BUTTON_SET_ACT( extSettingsButton, "Ex", qtr( "Extended Settings" ),
588
            extSettings() );
589
    setupSmallButton( extSettingsButton );
590
    controlLayout->addWidget( extSettingsButton, 3, 12, Qt::AlignBottom );
591

592
    controlLayout->setColumnStretch( 13, 0 );
593
    controlLayout->setColumnMinimumWidth( 13, 24 );
594
    controlLayout->setColumnStretch( 14, 5 );
595

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

599
    volMuteLabel = new QLabel;
600
    volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
601
    volMuteLabel->setToolTip( qtr( "Mute" ) );
602
    volMuteLabel->installEventFilter( hVolLabel );
603
    controlLayout->addWidget( volMuteLabel, 3, 15, Qt::AlignBottom );
604

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

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

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

629 630
    /* Volume control connection */
    CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
631
    CONNECT( THEMIM, volumeChanged( void ), this, updateVolume( void ) );
632 633

    updateInput();
634
}
635

636
ControlsWidget::~ControlsWidget()
637
{}
638

639 640 641 642 643 644 645
void ControlsWidget::stop()
{
    THEMIM->stop();
}

void ControlsWidget::play()
{
646
    if( THEPL->current.i_size == 0 )
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
    {
        /* 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 )
{
668 669 670 671 672
#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" )
673 674 675 676 677 678

    // 1 = chapter, 2 = title, 0 = no
    if( navigation == 0 )
    {
        discFrame->hide();
    } else if( navigation == 1 ) {
679 680
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
681 682 683
        menuButton->show();
        discFrame->show();
    } else {
684 685
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
686 687 688 689 690 691
        menuButton->hide();
        discFrame->show();
    }
}

static bool b_my_volume;
692
void ControlsWidget::updateVolume( int i_sliderVolume )
693 694 695
{
    if( !b_my_volume )
    {
696
        int i_res = i_sliderVolume  * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX;
697 698
        aout_VolumeSet( p_intf, i_res );
    }
699 700
    if( i_sliderVolume == 0 )
        volMuteLabel->setPixmap( QPixmap(":/pixmaps/volume-muted.png" ) );
701
    else if( i_sliderVolume < VOLUME_MAX / 3 )
702
        volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-low.png" ) );
703 704 705
    else if( i_sliderVolume > (VOLUME_MAX * 2 / 3 ) )
        volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-high.png" ) );
    else volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-medium.png" ) );
706 707
}

708
void ControlsWidget::updateVolume()
709
{
710
    /* Audio part */
711 712
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
713
    i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
714 715 716 717 718 719 720 721
    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;
    }
722
}
723

724 725
void ControlsWidget::updateInput()
{
726
    /* Activate the interface buttons according to the presence of the input */
727
    enableInput( THEMIM->getIM()->hasInput() );
728
    enableVideo( THEMIM->getIM()->hasVideo() && THEMIM->getIM()->hasInput() );
729
}
730

731 732
void ControlsWidget::setStatus( int status )
{
733 734
    if( status == PLAYING_S ) /* Playing */
    {
735
        playButton->setIcon( QIcon( ":/pixmaps/pause.png" ) );
736 737
        playButton->setToolTip( qtr( "Pause" ) );
    }
738
    else
739
    {
740
        playButton->setIcon( QIcon( ":/pixmaps/play.png" ) );
741 742
        playButton->setToolTip( qtr( "Play" ) );
    }
743
}
744

745 746
/**
 * TODO
747
 * This functions toggle the fullscreen mode
748
 * If there is no video, it should first activate Visualisations...
749
 *  This has also to be fixed in enableVideo()
750
 */
Clément Stenac's avatar
Clément Stenac committed
751 752
void ControlsWidget::fullscreen()
{
753 754
    vout_thread_t *p_vout =
        (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
755
    if( p_vout)
756
    {
757
        var_SetBool( p_vout, "fullscreen", !var_GetBool( p_vout, "fullscreen" ) );
758
        vlc_object_release( p_vout );
759
    }
760 761 762 763 764 765
}

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

767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
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 );
782 783 784

    /* Advanced Buttons too */
    advControls->enableInput( enable );
785 786
}

787
void ControlsWidget::enableVideo( bool enable )
788
{
789 790
    // TODO Later make the fullscreenButton toggle Visualisation and so on.
    fullscreenButton->setEnabled( enable );
791 792 793

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
794 795
}

796 797 798 799 800 801 802 803 804 805 806 807
void ControlsWidget::toggleAdvanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        b_advancedVisible = true;
    }
    else
    {
        advControls->hide();
        b_advancedVisible = false;
    }
808
    emit advancedControlsToggled( b_advancedVisible );
809
}
810

811

Lukas Durfina's avatar
Lukas Durfina committed
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
/**********************************************************************
 * 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 );
829
    #if QT43
Lukas Durfina's avatar
Lukas Durfina committed
830
    controlLayout->setContentsMargins( 5, 1, 5, 1 );
831 832 833
    #else
    controlLayout->setMargin( 5 );
    #endif
Lukas Durfina's avatar
Lukas Durfina committed
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848

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

849
    #ifdef ZVBI_COMPILED
Lukas Durfina's avatar
Lukas Durfina committed
850
    fsLayout->addWidget( telexFrame, 1, 5 );
851
    #endif
Lukas Durfina's avatar
Lukas Durfina committed
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 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 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917

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

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

    /* hiding timer */
    p_hideTimer = new QTimer( this );
    CONNECT( p_hideTimer, timeout(), this, hideFSControllerWidget() );
    p_hideTimer->setSingleShot( true );

    /* slow hiding timer */
    #ifdef TRANSPARENCY
    p_slowHideTimer = new QTimer( this );
    CONNECT( p_slowHideTimer, timeout(), this, slowHideFSC() );
    #endif

    adjustSize ();  /* need to get real width and height for moving */

    /* center down */
    QDesktopWidget * p_desktop = QApplication::desktop();

    move( p_desktop->width() / 2 - width() / 2,
          p_desktop->height() - height() );

    #ifdef WIN32TRICK
    setWindowOpacity( 0.0 );
    fscHidden = true;
    show();
    #endif
}

FullscreenControllerWidget::~FullscreenControllerWidget()
{
}

/**
 * Hide fullscreen controller
 * FIXME: under windows it have to be done by moving out of screen
 *        because hide() doesnt work
 */
void FullscreenControllerWidget::hideFSControllerWidget()
{
    #ifdef WIN32TRICK
    fscHidden = true;
    setWindowOpacity( 0.0 );    // simulate hidding
    #else
    hide();
    #endif
}

#ifdef TRANSPARENCY
/**
 * Hidding fullscreen controller slowly
 * Linux: need composite manager
 * Windows: it is blinking, so it can be enabled by define TRASPARENCY
 */
void FullscreenControllerWidget::slowHideFSC()
{
    static bool first_call = true;

    if ( first_call )
    {
        first_call = false;

        p_slowHideTimer->stop();
        /* the last part of time divided to 100 pieces */
918 919
        p_slowHideTimer->start(
            (int) ( i_hideTimeout / 2 / ( windowOpacity() * 100 ) ) );
Lukas Durfina's avatar
Lukas Durfina committed
920 921