]> git.sesse.net Git - vlc/blob - modules/gui/qt4/components/interface_widgets.cpp
Qt4 - FIXME and comments fix. If you want to help, just grep -r FIXME *
[vlc] / modules / gui / qt4 / components / interface_widgets.cpp
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  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * ( at your option ) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 #include "dialogs_provider.hpp"
27 #include "components/interface_widgets.hpp"
28 #include "main_interface.hpp"
29 #include "input_manager.hpp"
30 #include "menus.hpp"
31 #include "util/input_slider.hpp"
32 #include "util/customwidgets.hpp"
33 #include <vlc_vout.h>
34
35 #include <QLabel>
36 #include <QSpacerItem>
37 #include <QCursor>
38 #include <QPushButton>
39 #include <QHBoxLayout>
40 #include <QMenu>
41 #include <QPalette>
42 #include <QResizeEvent>
43
44 /**********************************************************************
45  * Video Widget. A simple frame on which video is drawn
46  * This class handles resize issues
47  **********************************************************************/
48 static void *DoRequest( intf_thread_t *, vout_thread_t *, int*,int*,
49                         unsigned int *, unsigned int * );
50 static void DoRelease( intf_thread_t *, void * );
51 static int DoControl( intf_thread_t *, void *, int, va_list );
52
53 VideoWidget::VideoWidget( intf_thread_t *_p_i ) : QFrame( NULL ), p_intf( _p_i )
54 {
55     vlc_mutex_init( p_intf, &lock );
56     p_vout = NULL;
57
58     CONNECT( this, askResize(), this, SetMinSize() );
59     CONNECT( this, askVideoToShow(), this, show() );
60     setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
61 }
62
63 VideoWidget::~VideoWidget()
64 {
65     vlc_mutex_lock( &lock );
66     if( p_vout )
67     {
68         if( !p_intf->psz_switch_intf )
69         {
70             if( vout_Control( p_vout, VOUT_CLOSE ) != VLC_SUCCESS )
71                 vout_Control( p_vout, VOUT_REPARENT );
72         }
73         else
74         {
75             if( vout_Control( p_vout, VOUT_REPARENT ) != VLC_SUCCESS )
76                 vout_Control( p_vout, VOUT_CLOSE );
77         }
78     }
79     vlc_mutex_unlock( &lock );
80     vlc_mutex_destroy( &lock );
81 }
82
83 QSize VideoWidget::sizeHint() const
84 {
85     return widgetSize;
86 }
87
88 void *VideoWidget::request( vout_thread_t *p_nvout, int *pi_x, int *pi_y,
89                            unsigned int *pi_width, unsigned int *pi_height )
90 {
91     emit askVideoToShow();
92     if( p_vout )
93     {
94         msg_Dbg( p_intf, "embedded video already in use" );
95         return NULL;
96     }
97     p_vout = p_nvout;
98     emit askResize();
99     return ( void* )winId();
100 }
101
102 void VideoWidget::SetMinSize()
103 {
104     setMinimumSize( 16, 16 );
105 }
106
107 void VideoWidget::release( void *p_win )
108 {
109     p_vout = NULL;
110 }
111
112
113 /**********************************************************************
114  * Background Widget. Show a simple image background. Currently,
115  * it's a static cone.
116  **********************************************************************/
117 #define ICON_SIZE 128
118 #define MAX_BG_SIZE 400
119 #define MIN_BG_SIZE 64
120
121 BackgroundWidget::BackgroundWidget( intf_thread_t *_p_i ) :
122                                         QFrame( NULL ), p_intf( _p_i )
123 {
124     /* We should use that one to take the more size it can */
125     setSizePolicy( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding );
126
127     /* A dark background */
128     setAutoFillBackground( true );
129     plt =  palette();
130     plt.setColor( QPalette::Active, QPalette::Window , Qt::black );
131     plt.setColor( QPalette::Inactive, QPalette::Window , Qt::black );
132     setPalette( plt );
133
134     /* A cone in the middle */
135     label = new QLabel;
136 //    label->setScaledContents( true );
137     label->setMargin( 5 );
138     label->setMaximumHeight( MAX_BG_SIZE );
139     label->setMaximumWidth( MAX_BG_SIZE );
140     label->setMinimumHeight( MIN_BG_SIZE );
141     label->setMinimumWidth( MIN_BG_SIZE );
142     label->setPixmap( QPixmap( ":/vlc128.png" ) );
143
144     QHBoxLayout *backgroundLayout = new QHBoxLayout( this );
145     backgroundLayout->addWidget( label );
146
147     resize( 300, 150 );
148     updateGeometry();
149 }
150
151 BackgroundWidget::~BackgroundWidget()
152 {}
153
154 void BackgroundWidget::setArt( QString url )
155 {
156     if( url.isNull() )
157         label->setPixmap( QPixmap( ":/vlc128.png" ) );
158     else
159         label->setPixmap( QPixmap( url ) );
160     updateGeometry();
161 }
162
163 QSize BackgroundWidget::sizeHint() const
164 {
165     return label->size();
166 }
167
168 void BackgroundWidget::resizeEvent( QResizeEvent *e )
169 {
170     msg_Dbg( p_intf, "BG size, %i, %i", e->size().width(), e->size().height() );
171     if( e->size().height() < label->height() )
172     {
173         label->resize( e->size().height(), e->size().height() );
174     }
175 }
176
177 void BackgroundWidget::contextMenuEvent( QContextMenuEvent *event )
178 {
179     QVLCMenu::PopupMenu( p_intf, true );
180 }
181
182 /**********************************************************************
183  * Visualization selector panel
184  **********************************************************************/
185 VisualSelector::VisualSelector( intf_thread_t *_p_i ) :
186                                 QFrame( NULL ), p_intf( _p_i )
187 {
188     QHBoxLayout *layout = new QHBoxLayout( this );
189     layout->setMargin( 0 );
190     QPushButton *prevButton = new QPushButton( "Prev" );
191     QPushButton *nextButton = new QPushButton( "Next" );
192     layout->addWidget( prevButton );
193     layout->addWidget( nextButton );
194
195     layout->addItem( new QSpacerItem( 40,20,
196                               QSizePolicy::Expanding, QSizePolicy::Minimum ) );
197     layout->addWidget( new QLabel( qtr( "Current visualization:" ) ) );
198
199     current = new QLabel( qtr( "None" ) );
200     layout->addWidget( current );
201
202     BUTTONACT( prevButton, prev() );
203     BUTTONACT( nextButton, next() );
204
205     setLayout( layout );
206     setMaximumHeight( 35 );
207 }
208
209 VisualSelector::~VisualSelector()
210 {
211 }
212
213 void VisualSelector::prev()
214 {
215     char *psz_new = aout_VisualPrev( p_intf );
216     if( psz_new )
217     {
218         current->setText( qfu( psz_new ) );
219         free( psz_new );
220     }
221 }
222
223 void VisualSelector::next()
224 {
225     char *psz_new = aout_VisualNext( p_intf );
226     if( psz_new )
227     {
228         current->setText( qfu( psz_new ) );
229         free( psz_new );
230     }
231 }
232
233 /**********************************************************************
234  * TEH controls
235  **********************************************************************/
236
237 #define setupSmallButton( aButton ){  \
238     aButton->setMaximumSize( QSize( 26, 26 ) ); \
239     aButton->setMinimumSize( QSize( 26, 26 ) ); \
240     aButton->setIconSize( QSize( 20, 20 ) ); }
241
242 AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i ) :
243                                            QFrame( NULL ), p_intf( _p_i )
244 {
245     QHBoxLayout *advLayout = new QHBoxLayout( this );
246     advLayout->setMargin( 0 );
247     advLayout->setSpacing( 0 );
248
249     /* A to B Button */
250     ABButton = new QPushButton( "AB" );
251     ABButton->setMaximumSize( QSize( 26, 26 ) );
252     ABButton->setIconSize( QSize( 20, 20 ) );
253     advLayout->addWidget( ABButton );
254     BUTTON_SET_ACT( ABButton, "AB", qtr( "A to B" ), fromAtoB() );
255     timeA = timeB = 0;
256     CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
257              this, AtoBLoop( float, int, int ) );
258
259     frameButton = new QPushButton( "Fr" );
260     frameButton->setMaximumSize( QSize( 26, 26 ) );
261     frameButton->setIconSize( QSize( 20, 20 ) );
262     advLayout->addWidget( frameButton );
263     BUTTON_SET_ACT( frameButton, "Fr", qtr( "Frame by Frame" ), frame() );
264
265     recordButton = new QPushButton( "R" );
266     recordButton->setMaximumSize( QSize( 26, 26 ) );
267     recordButton->setIconSize( QSize( 20, 20 ) );
268     advLayout->addWidget( recordButton );
269     BUTTON_SET_ACT_I( recordButton, "", record_16px.png,
270             qtr( "Record" ), record() );
271
272     /* Snapshot Button */
273     snapshotButton = new QPushButton( "S" );
274     snapshotButton->setMaximumSize( QSize( 26, 26 ) );
275     snapshotButton->setIconSize( QSize( 20, 20 ) );
276     advLayout->addWidget( snapshotButton );
277     BUTTON_SET_ACT( snapshotButton, "S", qtr( "Take a snapshot" ), snapshot() );
278 }
279
280 AdvControlsWidget::~AdvControlsWidget()
281 {}
282
283 void AdvControlsWidget::enableInput( bool enable )
284 {
285     ABButton->setEnabled( enable );
286     recordButton->setEnabled( enable );
287 }
288
289 void AdvControlsWidget::enableVideo( bool enable )
290 {
291     snapshotButton->setEnabled( enable );
292     frameButton->setEnabled( enable );
293 }
294
295 void AdvControlsWidget::snapshot()
296 {
297     vout_thread_t *p_vout =
298         (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
299     if( p_vout ) vout_Control( p_vout, VOUT_SNAPSHOT );
300 }
301
302 /* Function called when the button is clicked() */
303 void AdvControlsWidget::fromAtoB()
304 {
305     if( !timeA )
306     {
307         timeA = var_GetTime( THEMIM->getInput(), "time"  );
308         ABButton->setText( "A->..." );
309         return;
310     }
311     if( !timeB )
312     {
313         timeB = var_GetTime( THEMIM->getInput(), "time"  );
314         var_SetTime( THEMIM->getInput(), "time" , timeA );
315         ABButton->setText( "A<=>B" );
316         return;
317     }
318     timeA = 0;
319     timeB = 0;
320     ABButton->setText( "AB" );
321 }
322
323 /* Function called regularly when in an AtoB loop */
324 void AdvControlsWidget::AtoBLoop( float f_pos, int i_time, int i_length )
325 {
326     if( timeB )
327     {
328         if( i_time >= (int)(timeB/1000000) )
329             var_SetTime( THEMIM->getInput(), "time" , timeA );
330     }
331 }
332
333 /* FIXME Record function */
334 void AdvControlsWidget::record(){}
335
336 //FIXME Frame by frame function
337 void AdvControlsWidget::frame(){}
338
339 /*****************************
340  * DA Control Widget !
341  *****************************/
342 ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
343                                 MainInterface *_p_mi,
344                                 bool b_advControls,
345                                 bool b_shiny ) :
346                                 QFrame( NULL ), p_intf( _p_i )
347 {
348     controlLayout = new QGridLayout( this );
349     controlLayout->setSpacing( 0 );
350     setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Minimum );
351
352     /** The main Slider **/
353     slider = new InputSlider( Qt::Horizontal, NULL );
354     controlLayout->addWidget( slider, 0, 1, 1, 16 );
355     /* Update the position when the IM has changed */
356     CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
357              slider, setPosition( float, int, int ) );
358     /* And update the IM, when the position has changed */
359     CONNECT( slider, sliderDragged( float ),
360              THEMIM->getIM(), sliderUpdate( float ) );
361
362     /** Slower and faster Buttons **/
363     slowerButton = new QPushButton;
364     slowerButton->setFlat( true );
365     slowerButton->setMaximumSize( QSize( 26, 20 ) );
366
367     BUTTON_SET_ACT( slowerButton, "-", qtr( "Slower" ), slower() );
368     controlLayout->addWidget( slowerButton, 0, 0 );
369
370     fasterButton = new QPushButton;
371     fasterButton->setFlat( true );
372     fasterButton->setMaximumSize( QSize( 26, 20 ) );
373
374     BUTTON_SET_ACT( fasterButton, "+", qtr( "Faster" ), faster() );
375     controlLayout->addWidget( fasterButton, 0, 17 );
376
377     /* advanced Controls handling */
378     b_advancedVisible = b_advControls;
379
380     advControls = new AdvControlsWidget( p_intf );
381     controlLayout->addWidget( advControls, 1, 3, 2, 4, Qt::AlignBottom );
382     if( !b_advancedVisible ) advControls->hide();
383
384     /** Disc and Menus handling */
385     discFrame = new QFrame( this );
386
387     QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
388     discLayout->setSpacing( 0 );
389     discLayout->setMargin( 0 );
390
391     prevSectionButton = new QPushButton( discFrame );
392     setupSmallButton( prevSectionButton );
393     discLayout->addWidget( prevSectionButton );
394
395     menuButton = new QPushButton( discFrame );
396     setupSmallButton( menuButton );
397     discLayout->addWidget( menuButton );
398
399     nextSectionButton = new QPushButton( discFrame );
400     setupSmallButton( nextSectionButton );
401     discLayout->addWidget( nextSectionButton );
402
403     controlLayout->addWidget( discFrame, 1, 10, 2, 3, Qt::AlignBottom );
404
405     BUTTON_SET_IMG( prevSectionButton, "", previous.png, "" );
406     BUTTON_SET_IMG( nextSectionButton, "", next.png, "" );
407     BUTTON_SET_IMG( menuButton, "", previous.png, "" );
408
409     discFrame->hide();
410
411     /* Change the navigation button display when the IM navigation changes */
412     CONNECT( THEMIM->getIM(), navigationChanged( int ),
413              this, setNavigation( int ) );
414     /* Changes the IM navigation when triggered on the nav buttons */
415     CONNECT( prevSectionButton, clicked(), THEMIM->getIM(),
416              sectionPrev() );
417     CONNECT( nextSectionButton, clicked(), THEMIM->getIM(),
418              sectionNext() );
419     CONNECT( menuButton, clicked(), THEMIM->getIM(),
420              sectionMenu() );
421
422     /** TODO
423      * Telextext QFrame
424      * Merge with upper menu in a StackLayout
425      **/
426
427     /** Play Buttons **/
428     QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
429     sizePolicy.setHorizontalStretch( 0 );
430     sizePolicy.setVerticalStretch( 0 );
431
432     /* Play */
433     playButton = new QPushButton;
434     playButton->setSizePolicy( sizePolicy );
435     playButton->setMaximumSize( QSize( 38, 38 ) );
436     playButton->setMinimumSize( QSize( 45, 45 ) );
437     playButton->setIconSize( QSize( 30, 30 ) );
438
439     controlLayout->addWidget( playButton, 2, 0, 2, 2 );
440
441     controlLayout->setColumnMinimumWidth( 2, 20 );
442     controlLayout->setColumnStretch( 2, 0 );
443
444     /** Prev + Stop + Next Block **/
445     QHBoxLayout *controlButLayout = new QHBoxLayout;
446     controlButLayout->setSpacing( 0 ); /* Don't remove that, will be useful */
447
448     /* Prev */
449     QPushButton *prevButton = new QPushButton;
450     prevButton->setSizePolicy( sizePolicy );
451     setupSmallButton( prevButton );
452
453     controlButLayout->addWidget( prevButton );
454
455     /* Stop */
456     QPushButton *stopButton = new QPushButton;
457     stopButton->setSizePolicy( sizePolicy );
458     setupSmallButton( stopButton );
459
460     controlButLayout->addWidget( stopButton );
461
462     /* next */
463     QPushButton *nextButton = new QPushButton;
464     nextButton->setSizePolicy( sizePolicy );
465     setupSmallButton( nextButton );
466
467     controlButLayout->addWidget( nextButton );
468
469     /* Add this block to the main layout */
470     controlLayout->addLayout( controlButLayout, 3, 3, 1, 3, Qt::AlignBottom );
471
472     BUTTON_SET_ACT_I( playButton, "", play.png, qtr( "Play" ), play() );
473     BUTTON_SET_ACT_I( prevButton, "" , previous.png,
474                       qtr( "Previous" ), prev() );
475     BUTTON_SET_ACT_I( nextButton, "", next.png, qtr( "Next" ), next() );
476     BUTTON_SET_ACT_I( stopButton, "", stop.png, qtr( "Stop" ), stop() );
477
478     controlLayout->setColumnStretch( 7 , 2 );
479
480     /*
481      * Other first Line buttons
482      */
483     /** Fullscreen/Visualisation **/
484     fullscreenButton = new QPushButton( "F" );
485     BUTTON_SET_ACT( fullscreenButton, "F", qtr( "Fullscreen" ), fullscreen() );
486     setupSmallButton( fullscreenButton );
487     controlLayout->addWidget( fullscreenButton, 3, 10, Qt::AlignBottom );
488
489     /** Playlist Button **/
490     playlistButton = new QPushButton;
491     setupSmallButton( playlistButton );
492     controlLayout->addWidget( playlistButton, 3, 11, Qt::AlignBottom );
493     BUTTON_SET_IMG( playlistButton, "" , playlist.png, qtr( "Show playlist" ) );
494     CONNECT( playlistButton, clicked(), _p_mi, togglePlaylist() );
495
496     /** extended Settings **/
497     QPushButton *extSettingsButton = new QPushButton( "F" );
498     BUTTON_SET_ACT( extSettingsButton, "Ex", qtr( "Extended Settings" ),
499             extSettings() );
500     setupSmallButton( extSettingsButton );
501     controlLayout->addWidget( extSettingsButton, 3, 12, Qt::AlignBottom );
502
503     controlLayout->setColumnStretch( 14, 5 );
504
505     /* Volume */
506     VolumeClickHandler *hVolLabel = new VolumeClickHandler( p_intf, this );
507
508     volMuteLabel = new QLabel;
509     volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-high.png" ) );
510     volMuteLabel->setToolTip( qtr( "Mute" ) );
511     volMuteLabel->installEventFilter( hVolLabel );
512     controlLayout->addWidget( volMuteLabel, 3, 15, Qt::AlignBottom );
513
514     if( b_shiny )
515     {
516         volumeSlider = new SoundSlider( this,
517             config_GetInt( p_intf, "volume-step" ),
518             config_GetInt( p_intf, "qt-volume-complete" ) );
519     }
520     else
521     {
522         volumeSlider = new QSlider( this );
523         volumeSlider->setOrientation( Qt::Horizontal );
524     }
525     volumeSlider->setMaximumSize( QSize( 200, 40 ) );
526     volumeSlider->setMinimumSize( QSize( 106, 30 ) );
527     volumeSlider->setFocusPolicy( Qt::NoFocus );
528     controlLayout->addWidget( volumeSlider, 2, 16, 2 , 2, Qt::AlignBottom );
529
530     /* Set the volume from the config */
531     volumeSlider->setValue( ( config_GetInt( p_intf, "volume" ) ) *
532                               VOLUME_MAX / (AOUT_VOLUME_MAX/2) );
533
534     /* Volume control connection */
535     resize( QSize( 400, 60 ) );
536     CONNECT( volumeSlider, valueChanged( int ), this, updateVolume( int ) );
537     msg_Dbg( p_intf, "controls size: %i - %i", size().width(), size().height() );
538 }
539
540 ControlsWidget::~ControlsWidget()
541 {
542 }
543
544 /*
545 QSize ControlsWidget::sizeHint() const
546 {
547     return QSize( 300, 50 );
548 }
549 */
550
551 void ControlsWidget::stop()
552 {
553     THEMIM->stop();
554 }
555
556 void ControlsWidget::play()
557 {
558     if( THEPL->current.i_size == 0 )
559     {
560         /* The playlist is empty, open a file requester */
561         THEDP->openFileDialog();
562         setStatus( 0 );
563         return;
564     }
565     THEMIM->togglePlayPause();
566 }
567
568 void ControlsWidget::prev()
569 {
570     THEMIM->prev();
571 }
572
573 void ControlsWidget::next()
574 {
575     THEMIM->next();
576 }
577
578 void ControlsWidget::setNavigation( int navigation )
579 {
580 #define HELP_MENU N_( "Menu" )
581 #define HELP_PCH N_( "Previous chapter" )
582 #define HELP_NCH N_( "Next chapter" )
583 #define HELP_PTR N_( "Previous track" )
584 #define HELP_NTR N_( "Next track" )
585
586     // 1 = chapter, 2 = title, 0 = no
587     if( navigation == 0 )
588     {
589         discFrame->hide();
590     } else if( navigation == 1 ) {
591         prevSectionButton->setToolTip( qfu( HELP_PCH ) );
592         nextSectionButton->setToolTip( qfu( HELP_NCH ) );
593         menuButton->show();
594         discFrame->show();
595     } else {
596         prevSectionButton->setToolTip( qfu( HELP_PCH ) );
597         nextSectionButton->setToolTip( qfu( HELP_NCH ) );
598         menuButton->hide();
599         discFrame->show();
600     }
601 }
602
603 static bool b_my_volume;
604 void ControlsWidget::updateVolume( int i_sliderVolume )
605 {
606     if( !b_my_volume )
607     {
608         int i_res = i_sliderVolume  * (AOUT_VOLUME_MAX / 2) / VOLUME_MAX;
609         aout_VolumeSet( p_intf, i_res );
610     }
611     if( i_sliderVolume == 0 )
612         volMuteLabel->setPixmap( QPixmap(":/pixmaps/volume-muted.png" ) );
613     else if( i_sliderVolume < VOLUME_MAX / 2 )
614         volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-low.png" ) );
615     else volMuteLabel->setPixmap( QPixmap( ":/pixmaps/volume-high.png" ) );
616 }
617
618 void ControlsWidget::updateOnTimer()
619 {
620     /* Audio part */
621     audio_volume_t i_volume;
622     aout_VolumeGet( p_intf, &i_volume );
623     i_volume = ( i_volume *  VOLUME_MAX )/ (AOUT_VOLUME_MAX/2);
624     int i_gauge = volumeSlider->value();
625     b_my_volume = false;
626     if( i_volume - i_gauge > 1 || i_gauge - i_volume > 1 )
627     {
628         b_my_volume = true;
629         volumeSlider->setValue( i_volume );
630         b_my_volume = false;
631     }
632
633     /* Activate the interface buttons according to the presence of the input */
634     enableInput( THEMIM->getIM()->hasInput() );
635     //enableVideo( THEMIM->getIM()->hasVideo() );
636     enableVideo( true );
637 }
638
639 void ControlsWidget::setStatus( int status )
640 {
641     if( status == PLAYING_S ) // Playing
642         playButton->setIcon( QIcon( ":/pixmaps/pause.png" ) );
643     else
644         playButton->setIcon( QIcon( ":/pixmaps/play.png" ) );
645 }
646
647 /**
648  * TODO
649  * This functions toggle the fullscreen mode
650  * If there is no video, it should first activate Visualisations...
651  *  This has also to be fixed in enableVideo()
652  */
653 void ControlsWidget::fullscreen()
654 {
655     vout_thread_t *p_vout =
656         (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
657     if( p_vout)
658     {
659         var_SetBool( p_vout, "fullscreen", !var_GetBool( p_vout, "fullscreen" ) );
660         vlc_object_release( p_vout );
661     }
662 }
663
664 void ControlsWidget::extSettings()
665 {
666     THEDP->extendedDialog();
667 }
668
669 void ControlsWidget::slower()
670 {
671     THEMIM->getIM()->slower();
672 }
673
674 void ControlsWidget::faster()
675 {
676     THEMIM->getIM()->faster();
677 }
678
679 void ControlsWidget::enableInput( bool enable )
680 {
681     slowerButton->setEnabled( enable );
682     slider->setEnabled( enable );
683     fasterButton->setEnabled( enable );
684
685     /* Advanced Buttons too */
686     advControls->enableInput( enable );
687 }
688
689 void ControlsWidget::enableVideo( bool enable )
690 {
691     // TODO Later make the fullscreenButton toggle Visualisation and so on.
692     fullscreenButton->setEnabled( enable );
693
694     /* Advanced Buttons too */
695     advControls->enableVideo( enable );
696 }
697
698 void ControlsWidget::toggleAdvanced()
699 {
700     if( !VISIBLE( advControls ) )
701     {
702         advControls->show();
703         b_advancedVisible = true;
704     }
705     else
706     {
707         advControls->hide();
708         b_advancedVisible = false;
709     }
710     emit advancedControlsToggled( b_advancedVisible );
711 }
712
713
714 /**********************************************************************
715  * Speed control widget
716  **********************************************************************/
717 SpeedControlWidget::SpeedControlWidget( intf_thread_t *_p_i ) :
718                              QFrame( NULL ), p_intf( _p_i )
719 {
720     QSizePolicy sizePolicy( QSizePolicy::Maximum, QSizePolicy::Fixed );
721     sizePolicy.setHorizontalStretch( 0 );
722     sizePolicy.setVerticalStretch( 0 );
723
724     speedSlider = new QSlider;
725     speedSlider->setSizePolicy( sizePolicy );
726     speedSlider->setMaximumSize( QSize( 80, 200 ) );
727     speedSlider->setOrientation( Qt::Vertical );
728     speedSlider->setTickPosition( QSlider::TicksRight );
729
730     speedSlider->setRange( -100, 100 );
731     speedSlider->setSingleStep( 10 );
732     speedSlider->setPageStep( 20 );
733     speedSlider->setTickInterval( 20 );
734
735     CONNECT( speedSlider, valueChanged( int ), this, updateRate( int ) );
736
737     normalSpeedButton = new QPushButton( "N" );
738     normalSpeedButton->setMaximumSize( QSize( 26, 20 ) );
739     normalSpeedButton->setFlat( true );
740     normalSpeedButton->setToolTip( qtr( "Revert to normal play speed" ) );
741
742     CONNECT( normalSpeedButton, clicked(), this, resetRate() );
743
744     QVBoxLayout *speedControlLayout = new QVBoxLayout;
745     speedControlLayout->addWidget(speedSlider);
746     speedControlLayout->addWidget(normalSpeedButton);
747     setLayout(speedControlLayout);
748 }
749
750 SpeedControlWidget::~SpeedControlWidget()
751 {}
752
753 #define RATE_SLIDER_MAXIMUM 3.0
754 #define RATE_SLIDER_MINIMUM 0.3
755 #define RATE_SLIDER_LENGTH 100.0
756
757 void SpeedControlWidget::updateControls( int rate )
758 {
759     if( speedSlider->isSliderDown() )
760     {
761         //We don't want to change anything if the user is using the slider
762         return;
763     }
764
765     int sliderValue;
766     double speed = INPUT_RATE_DEFAULT / (double)rate;
767
768     if( rate >= INPUT_RATE_DEFAULT )
769     {
770         if( speed < RATE_SLIDER_MINIMUM )
771         {
772             sliderValue = speedSlider->minimum();
773         }
774         else
775         {
776             sliderValue = (int)( ( speed - 1.0 ) * RATE_SLIDER_LENGTH
777                                         / ( 1.0 - RATE_SLIDER_MAXIMUM ) );
778         }
779     }
780     else
781     {
782         if( speed > RATE_SLIDER_MAXIMUM )
783         {
784             sliderValue = speedSlider->maximum();
785         }
786         else
787         {
788             sliderValue = (int)( ( speed - 1.0 ) * RATE_SLIDER_LENGTH
789                                         / ( RATE_SLIDER_MAXIMUM - 1.0 ) );
790         }
791     }
792
793     //Block signals to avoid feedback loop
794     speedSlider->blockSignals( true );
795     speedSlider->setValue( sliderValue );
796     speedSlider->blockSignals( false );
797 }
798
799 void SpeedControlWidget::updateRate( int sliderValue )
800 {
801     int rate;
802
803     if( sliderValue < 0.0 )
804     {
805         rate = INPUT_RATE_DEFAULT* RATE_SLIDER_LENGTH /
806             ( sliderValue * ( 1.0 - RATE_SLIDER_MINIMUM ) + RATE_SLIDER_LENGTH );
807     }
808     else
809     {
810         rate = INPUT_RATE_DEFAULT* RATE_SLIDER_LENGTH /
811             ( sliderValue * ( RATE_SLIDER_MAXIMUM - 1.0 ) + RATE_SLIDER_LENGTH );
812     }
813
814     THEMIM->getIM()->setRate(rate);
815 }
816
817 void SpeedControlWidget::resetRate()
818 {
819     THEMIM->getIM()->setRate(INPUT_RATE_DEFAULT);
820 }