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

zorglub's avatar
zorglub committed
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

zorglub's avatar
zorglub committed
41
42
#include <QLabel>
#include <QSpacerItem>
zorglub's avatar
zorglub committed
43
#include <QCursor>
zorglub's avatar
zorglub committed
44
#include <QPushButton>
45
#include <QToolButton>
46
#include <QHBoxLayout>
zorglub's avatar
zorglub committed
47
#include <QMenu>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
48
49
#include <QPalette>
#include <QResizeEvent>
50
#include <QDate>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
51

52
53
54
55
#ifdef Q_WS_X11
# include <X11/Xlib.h>
# include <qx11info_x11.h>
#endif
56

57
58
#include <math.h>

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

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

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

80
    /* The core can ask through a callback to show the video. */
81
#if HAS_QT43
82
83
84
    connect( this, SIGNAL(askVideoWidgetToShow( unsigned int, unsigned int)),
             this, SLOT(SetSizing(unsigned int, unsigned int )),
             Qt::BlockingQueuedConnection );
85
86
87
88
89
#else
#error This is broken. Fix it with a QEventLoop with a processEvents () 
    connect( this, SIGNAL(askVideoWidgetToShow( unsigned int, unsigned int)),
             this, SLOT(SetSizing(unsigned int, unsigned int )) );
#endif
90
91
}

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

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

105
106
107
108
109
110
111
112
113
114
115
116
    if( p_vout )
    {
        if( !p_intf->psz_switch_intf )
        {
            if( vout_Control( p_vout, VOUT_CLOSE ) != VLC_SUCCESS )
                vout_Control( p_vout, VOUT_REPARENT );
        }
        else
        {
            if( vout_Control( p_vout, VOUT_REPARENT ) != VLC_SUCCESS )
                vout_Control( p_vout, VOUT_CLOSE );
        }
117
        vlc_object_release( p_vout );
118
119
120
    }
}

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

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

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

161
162
163
164
QSize VideoWidget::sizeHint() const
{
    return videoSize;
}
165

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

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

180
    /* A dark background */
zorglub's avatar
zorglub committed
181
    setAutoFillBackground( true );
182
183
184
185
186
    plt =  palette();
    plt.setColor( QPalette::Active, QPalette::Window , Qt::black );
    plt.setColor( QPalette::Inactive, QPalette::Window , Qt::black );
    setPalette( plt );

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

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

204
    CONNECT( THEMIM->getIM(), artChanged( QString ), this, updateArt( QString ) );
205
206
}

zorglub's avatar
zorglub committed
207
BackgroundWidget::~BackgroundWidget()
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
208
{}
Ilkka Ollakka's avatar
   
Ilkka Ollakka committed
209

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

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

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

zorglub's avatar
zorglub committed
239
240
241
242
/**********************************************************************
 * Visualization selector panel
 **********************************************************************/
VisualSelector::VisualSelector( intf_thread_t *_p_i ) :
243
                                QFrame( NULL ), p_intf( _p_i )
zorglub's avatar
zorglub committed
244
245
{
    QHBoxLayout *layout = new QHBoxLayout( this );
246
    layout->setMargin( 0 );
zorglub's avatar
zorglub committed
247
    QPushButton *prevButton = new QPushButton( "Prev" );
248
    QPushButton *nextButton = new QPushButton( "Next" );
zorglub's avatar
zorglub committed
249
250
    layout->addWidget( prevButton );
    layout->addWidget( nextButton );
zorglub's avatar
zorglub committed
251

252
    layout->addStretch( 10 );
253
    layout->addWidget( new QLabel( qtr( "Current visualization" ) ) );
zorglub's avatar
zorglub committed
254
255
256
257
258
259
260

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

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

zorglub's avatar
zorglub committed
261
    setLayout( layout );
262
    setMaximumHeight( 35 );
zorglub's avatar
zorglub committed
263
264
265
}

VisualSelector::~VisualSelector()
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
266
{}
zorglub's avatar
zorglub committed
267

zorglub's avatar
zorglub committed
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
void VisualSelector::prev()
{
    char *psz_new = aout_VisualPrev( p_intf );
    if( psz_new )
    {
        current->setText( qfu( psz_new ) );
        free( psz_new );
    }
}

void VisualSelector::next()
{
    char *psz_new = aout_VisualNext( p_intf );
    if( psz_new )
    {
        current->setText( qfu( psz_new ) );
        free( psz_new );
    }
}

/**********************************************************************
289
 * TEH controls
zorglub's avatar
zorglub committed
290
 **********************************************************************/
291
292
293
294
295
296

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

297
AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i ) :
zorglub's avatar
zorglub committed
298
299
                                           QFrame( NULL ), p_intf( _p_i )
{
300
301
302
    QHBoxLayout *advLayout = new QHBoxLayout( this );
    advLayout->setMargin( 0 );
    advLayout->setSpacing( 0 );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
303
    advLayout->setAlignment( Qt::AlignBottom );
zorglub's avatar
zorglub committed
304

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

    recordButton = new QPushButton( "R" );
lukas.durfina's avatar
lukas.durfina committed
323
    setupSmallButton( recordButton );
324
    advLayout->addWidget( recordButton );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
325
    BUTTON_SET_ACT_I( recordButton, "", record,
326
            qtr( "Record" ), record() );
327

328
    /* Snapshot Button */
329
    snapshotButton = new QPushButton( "S" );
lukas.durfina's avatar
lukas.durfina committed
330
    setupSmallButton( snapshotButton );
331
    advLayout->addWidget( snapshotButton );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
332
333
    BUTTON_SET_ACT_I( snapshotButton, "", snapshot,
            qtr( "Take a snapshot" ), snapshot() );
zorglub's avatar
zorglub committed
334
335
}

336
AdvControlsWidget::~AdvControlsWidget()
337
{}
zorglub's avatar
zorglub committed
338

339
void AdvControlsWidget::enableInput( bool enable )
zorglub's avatar
zorglub committed
340
{
341
342
    ABButton->setEnabled( enable );
    recordButton->setEnabled( enable );
zorglub's avatar
zorglub committed
343
}
344

345
void AdvControlsWidget::enableVideo( bool enable )
zorglub's avatar
zorglub committed
346
347
{
    snapshotButton->setEnabled( enable );
348
#if 0
349
    frameButton->setEnabled( enable );
350
#endif
zorglub's avatar
zorglub committed
351
352
}

353
void AdvControlsWidget::snapshot()
zorglub's avatar
zorglub committed
354
{
355
356
    vout_thread_t *p_vout =
        (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
357
    if( p_vout ) vout_Control( p_vout, VOUT_SNAPSHOT );
zorglub's avatar
zorglub committed
358
359
}

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

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

394
/* FIXME Record function */
395
void AdvControlsWidget::record(){}
396

397
#if 0
398
//FIXME Frame by frame function
399
void AdvControlsWidget::frame(){}
400
#endif
401

402
403
404
/*****************************
 * DA Control Widget !
 *****************************/
405
ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
406
                                MainInterface *_p_mi,
407
                                bool b_advControls,
lukas.durfina's avatar
lukas.durfina committed
408
409
410
                                bool b_shiny,
                                bool b_fsCreation) :
                                QFrame( _p_mi ), p_intf( _p_i )
411
{
412
    setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
413

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

423
    /** Slower and faster Buttons **/
424
425
    slowerButton = new QToolButton;
    slowerButton->setAutoRaise( true );
426
    slowerButton->setMaximumSize( QSize( 26, 20 ) );
427

428
    BUTTON_SET_ACT( slowerButton, "-", qtr( "Slower" ), slower() );
429

430
431
    fasterButton = new QToolButton;
    fasterButton->setAutoRaise( true );
432
    fasterButton->setMaximumSize( QSize( 26, 20 ) );
433

434
    BUTTON_SET_ACT( fasterButton, "+", qtr( "Faster" ), faster() );
435

436
437
438
439
440
441
    /* advanced Controls handling */
    b_advancedVisible = b_advControls;

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

442
    /** Disc and Menus handling */
443
    discFrame = new QWidget( this );
444

445
446
447
    QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
    discLayout->setSpacing( 0 );
    discLayout->setMargin( 0 );
448

449
    prevSectionButton = new QPushButton( discFrame );
450
    setupSmallButton( prevSectionButton );
451
452
    discLayout->addWidget( prevSectionButton );

453
    menuButton = new QPushButton( discFrame );
454
455
456
    setupSmallButton( menuButton );
    discLayout->addWidget( menuButton );

457
    nextSectionButton = new QPushButton( discFrame );
458
    setupSmallButton( nextSectionButton );
459
460
    discLayout->addWidget( nextSectionButton );

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
461
462
463
    BUTTON_SET_IMG( prevSectionButton, "", dvd_prev, "" );
    BUTTON_SET_IMG( nextSectionButton, "", dvd_next, "" );
    BUTTON_SET_IMG( menuButton, "", dvd_menu, qtr( "Menu" ) );
464

465
    discFrame->hide();
466
467
468

    /* Change the navigation button display when the IM navigation changes */
    CONNECT( THEMIM->getIM(), navigationChanged( int ),
469
             this, setNavigation( int ) );
470
471
472
473
474
475
476
    /* 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() );
477

478
    /**
479
     * Telextext QFrame
480
     * TODO: Merge with upper menu in a StackLayout
481
     **/
482
483
484
485
486
    telexFrame = new QWidget( this );
    QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame );
    telexLayout->setSpacing( 0 );
    telexLayout->setMargin( 0 );

lukas.durfina's avatar
lukas.durfina committed
487
    telexOn = new QPushButton;
488
489
490
    setupSmallButton( telexOn );
    telexLayout->addWidget( telexOn );

491
    telexTransparent = new QPushButton;
492
493
    setupSmallButton( telexTransparent );
    telexLayout->addWidget( telexTransparent );
494
    b_telexTransparent = false;
495

496
    telexPage = new QSpinBox;
497
    telexPage->setRange( 0, 999 );
498
    telexPage->setValue( 100 );
499
500
    telexPage->setAccelerated( true );
    telexPage->setWrapping( true );
501
    telexPage->setAlignment( Qt::AlignRight );
502
    telexPage->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
503
504
    telexLayout->addWidget( telexPage );

505
    telexFrame->hide(); /* default hidden */
506
507
508

    CONNECT( telexPage, valueChanged( int ), THEMIM->getIM(),
             telexGotoPage( int ) );
lukas.durfina's avatar
lukas.durfina committed
509
510
511
    CONNECT( THEMIM->getIM(), setNewTelexPage( int ),
              telexPage, setValue( int ) );

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

lukas.durfina's avatar
lukas.durfina committed
514
515
    CONNECT( telexOn, clicked(), THEMIM->getIM(),
             telexToggleButtons() );
516
517
    CONNECT( telexOn, clicked( bool ), THEMIM->getIM(),
             telexToggle( bool ) );
lukas.durfina's avatar
lukas.durfina committed
518
519
520
    CONNECT( THEMIM->getIM(), toggleTelexButtons(),
              this, toggleTeletext() );
    b_telexEnabled = false;
521
522
523
    telexTransparent->setEnabled( false );
    telexPage->setEnabled( false );

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
524
    BUTTON_SET_IMG( telexTransparent, "", tvtelx, qtr( "Teletext" ) );
525
    CONNECT( telexTransparent, clicked( bool ),
526
             THEMIM->getIM(), telexSetTransparency() );
lukas.durfina's avatar
lukas.durfina committed
527
528
    CONNECT( THEMIM->getIM(), toggleTelexTransparency(),
              this, toggleTeletextTransparency() );
529
    CONNECT( THEMIM->getIM(), teletextEnabled( bool ),
530
             this, enableTeletext( bool ) );
531

532
    /** Play Buttons **/
533
    QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
534
535
536
537
    sizePolicy.setHorizontalStretch( 0 );
    sizePolicy.setVerticalStretch( 0 );

    /* Play */
538
    playButton = new QPushButton;
539
    playButton->setSizePolicy( sizePolicy );
540
541
    playButton->setMaximumSize( QSize( 36, 36 ) );
    playButton->setMinimumSize( QSize( 36, 36 ) );
542
    playButton->setIconSize( QSize( 30, 30 ) );
543

544

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

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

    controlButLayout->addWidget( prevButton );

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

    controlButLayout->addWidget( stopButton );

    /* next */
    QPushButton *nextButton = new QPushButton;
    nextButton->setSizePolicy( sizePolicy );
566
    setupSmallButton( nextButton );
567
568
569
570
571

    controlButLayout->addWidget( nextButton );

    /* Add this block to the main layout */

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
572
573
    BUTTON_SET_ACT_I( playButton, "", play_b, qtr( "Play" ), play() );
    BUTTON_SET_ACT_I( prevButton, "" , previous_b,
574
                      qtr( "Previous" ), prev() );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
575
576
    BUTTON_SET_ACT_I( nextButton, "", next_b, qtr( "Next" ), next() );
    BUTTON_SET_ACT_I( stopButton, "", stop_b, qtr( "Stop" ), stop() );
577
578
579
580

    /*
     * Other first Line buttons
     */
581
    /** Fullscreen/Visualisation **/
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
582
583
584
    fullscreenButton = new QPushButton;
    BUTTON_SET_ACT_I( fullscreenButton, "", fullscreen, qtr( "Fullscreen" ),
            fullscreen() );
585
    setupSmallButton( fullscreenButton );
586

587
588
589
590
591
    if( !b_fsCreation )
    {
        /** Playlist Button **/
        playlistButton = new QPushButton;
        setupSmallButton( playlistButton );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
592
        BUTTON_SET_IMG( playlistButton, "" , playlist, qtr( "Show playlist" ) );
593
594
595
596
        CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );

        /** extended Settings **/
        extSettingsButton = new QPushButton;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
597
598
        BUTTON_SET_ACT_I( extSettingsButton, "", extended,
                qtr( "Extended settings" ), extSettings() );
599
600
        setupSmallButton( extSettingsButton );
    }
601

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

605
    volMuteLabel = new QLabel;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
606
    volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) );
607
    volMuteLabel->setToolTip( qtr( "Mute" ) );
608
    volMuteLabel->installEventFilter( hVolLabel );
609

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

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

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

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

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
    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 );
    }

674
    updateInput();
675
}
676

677
ControlsWidget::~ControlsWidget()
678
{}
679

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
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;
    }
}
696

697
698
699
700
701
702
703
704
705
706
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;
}
707
708
709
710
711

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

724
725
726
727
728
729
730
void ControlsWidget::stop()
{
    THEMIM->stop();
}

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

    // 1 = chapter, 2 = title, 0 = no
    if( navigation == 0 )
    {
        discFrame->hide();
    } else if( navigation == 1 ) {
761
762
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
763
764
765
        menuButton->show();
        discFrame->show();
    } else {
766
767
        prevSectionButton->setToolTip( qfu( HELP_PCH ) );
        nextSectionButton->setToolTip( qfu( HELP_NCH ) );
768
769
770
771
772
773
        menuButton->hide();
        discFrame->show();
    }
}

static bool b_my_volume;
774
void ControlsWidget::updateVolume( int i_sliderVolume )
775
776
777
{
    if( !b_my_volume )
    {
778
        int i_res = i_sliderVolume  * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX;
779
780
        aout_VolumeSet( p_intf, i_res );
    }
781
    if( i_sliderVolume == 0 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
782
        volMuteLabel->setPixmap( QPixmap(":/volume-muted" ) );
783
    else if( i_sliderVolume < VOLUME_MAX / 3 )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
784
        volMuteLabel->setPixmap( QPixmap( ":/volume-low" ) );
785
    else if( i_sliderVolume > (VOLUME_MAX * 2 / 3 ) )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
786
787
        volMuteLabel->setPixmap( QPixmap( ":/volume-high" ) );
    else volMuteLabel->setPixmap( QPixmap( ":/volume-medium" ) );
788
789
}

790
void ControlsWidget::updateVolume()
791
{
792
    /* Audio part */
793
794
    audio_volume_t i_volume;
    aout_VolumeGet( p_intf, &i_volume );
795
    i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
796
797
798
799
800
801
802
803
    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;
    }
804
}
805

806
807
void ControlsWidget::updateInput()
{
808
    /* Activate the interface buttons according to the presence of the input */
809
    enableInput( THEMIM->getIM()->hasInput() );
810
    enableVideo( THEMIM->getIM()->hasVideo() && THEMIM->getIM()->hasInput() );
811
}
812

813
814
void ControlsWidget::setStatus( int status )
{
815
816
    if( status == PLAYING_S ) /* Playing */
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
817
        playButton->setIcon( QIcon( ":/pause_b" ) );
818
819
        playButton->setToolTip( qtr( "Pause" ) );
    }
820
    else
821
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
822
        playButton->setIcon( QIcon( ":/play_b" ) );
823
824
        playButton->setToolTip( qtr( "Play" ) );
    }
825
}
826

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

void ControlsWidget::extSettings()
{
    THEDP->extendedDialog();
}
zorglub's avatar
zorglub committed
848

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
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 );
864
865
866

    /* Advanced Buttons too */
    advControls->enableInput( enable );
867
868
}

869
void ControlsWidget::enableVideo( bool enable )
870
{
871
872
    // TODO Later make the fullscreenButton toggle Visualisation and so on.
    fullscreenButton->setEnabled( enable );
873
874
875

    /* Advanced Buttons too */
    advControls->enableVideo( enable );
876
877
}

878
879
880
881
882
883
884
885
886
887
888
889
void ControlsWidget::toggleAdvanced()
{
    if( !VISIBLE( advControls ) )
    {
        advControls->show();
        b_advancedVisible = true;
    }
    else
    {
        advControls->hide();
        b_advancedVisible = false;
    }
890
    emit advancedControlsToggled( b_advancedVisible );
891
}
892

893

lukas.durfina's avatar
lukas.durfina committed
894
895
896
897
898
899
/**********************************************************************
 * 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 ),
900
901
902
          i_mouse_last_x( -1 ), i_mouse_last_y( -1 ), b_mouse_over(false),
          b_slow_hide_begin(false), i_slow_hide_timeout(1),
          b_fullscreen( false ), i_hide_timeout( 1 )
lukas.durfina's avatar
lukas.durfina committed
903
904
905
906
907
908
909
910
{
    setWindowFlags( Qt::ToolTip );

    setFrameShape( QFrame::StyledPanel );
    setFrameStyle( QFrame::Sunken );
    setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );

    QGridLayout *fsLayout = new QGridLayout( this );
911
    fsLayout->setLayoutMargins( 5, 1, 5, 1, 5 );
lukas.durfina's avatar
lukas.durfina committed
912

913
    /* First line */
lukas.durfina's avatar
lukas.durfina committed
914
    slider->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum);
915
    fsLayout->addWidget( slowerButton, 0, 0 );
lukas.durfina's avatar
lukas.durfina committed
916
917
918
    fsLayout->addWidget( slider, 0, 1, 1, 6 );
    fsLayout->addWidget( fasterButton, 0, 7 );

919
920
    fsLayout->addWidget( playButton, 1, 0 );
    fsLayout->addLayout( controlButLayout, 1, 1 );
lukas.durfina's avatar
lukas.durfina committed
921

922
923
924
925
    fsLayout->addWidget( discFrame, 1, 2 );
    fsLayout->addWidget( telexFrame, 1, 3 );
    fsLayout->addWidget( advControls, 1, 4, Qt::AlignVCenter );
    fsLayout->addWidget( fullscreenButton, 1, 5 );
lukas.durfina's avatar
lukas.durfina committed
926

927
928
    fsLayout->addWidget( volMuteLabel, 1, 6);
    fsLayout->addWidget( volumeSlider, 1, 7 );
lukas.durfina's avatar
lukas.durfina committed
929
930
931

    /* hiding timer */
    p_hideTimer = new QTimer( this );
932
    CONNECT( p_hideTimer, timeout(), this, hideFSC() );
lukas.durfina's avatar
lukas.durfina committed
933
934
935
    p_hideTimer->setSingleShot( true );

    /* slow hiding timer */
936
#if HAVE_TRANSPARENCY
lukas.durfina's avatar
lukas.durfina committed
937
938
    p_slowHideTimer = new QTimer( this );
    CONNECT( p_slowHideTimer, timeout(), this, slowHideFSC() );
939
#endif
lukas.durfina's avatar
lukas.durfina committed
940
941
942
943
944
945
946
947
948

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

949
#ifdef WIN32TRICK
lukas.durfina's avatar
lukas.durfina committed
950
951
952
    setWindowOpacity( 0.0 );
    fscHidden = true;
    show();