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