qt: restore compatibility for Qt 5.5
[vlc.git] / modules / gui / qt / components / extended_panels.cpp
blob6136718f785f14f34bc26df35a62daca5368a4e5
1 /*****************************************************************************
2 * extended_panels.cpp : Extended controls panels
3 ****************************************************************************
4 * Copyright (C) 2006-2013 the VideoLAN team
5 * $Id$
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Antoine Cellerier <dionoea .t videolan d@t org>
9 * Jean-Baptiste Kempf <jb@videolan.org>
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.
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.
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 *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include <math.h>
32 #include <algorithm>
34 #include <QLabel>
35 #include <QVariant>
36 #include <QString>
37 #include <QFont>
38 #include <QGridLayout>
39 #include <QComboBox>
40 #include <QTimer>
41 #include <QFileDialog>
42 #include <QGraphicsScene>
43 #include <QPainter>
44 #include <QRegExp>
45 #include <QApplication>
46 #include <QScreen>
48 #include "components/extended_panels.hpp"
49 #include "dialogs/preferences.hpp"
50 #include "qt.hpp"
51 #include "input_manager.hpp"
52 #include "util/qt_dirs.hpp"
53 #include "util/customwidgets.hpp"
55 #include "../../audio_filter/equalizer_presets.h"
56 #include <vlc_vout.h>
57 #include <vlc_modules.h>
58 #include <vlc_plugin.h>
60 static bool filterIsPresent( const QString &filters, const QString &filter )
62 QStringList list = filters.split( ':', QString::SplitBehavior::SkipEmptyParts );
63 foreach( const QString &filterCmp, list )
65 if( filterCmp.compare( filter ) == 0 )
66 return true;
68 return false;
71 static const char* GetVFilterType( struct intf_thread_t *p_intf, const char *psz_name )
73 module_t *p_obj = module_find( psz_name );
74 if( !p_obj )
76 msg_Err( p_intf, "Unable to find filter module \"%s\".", psz_name );
77 return NULL;
80 if( module_provides( p_obj, "video splitter" ) )
81 return "video-splitter";
82 else if( module_provides( p_obj, "video filter" ) )
83 return "video-filter";
84 else if( module_provides( p_obj, "sub source" ) )
85 return "sub-source";
86 else if( module_provides( p_obj, "sub filter" ) )
87 return "sub-filter";
88 else
90 msg_Err( p_intf, "Unknown video filter type." );
91 return NULL;
95 static const QString ModuleFromWidgetName( QObject *obj )
97 return obj->objectName().replace( "Enable","" );
100 static QString OptionFromWidgetName( QObject *obj )
102 /* Gruik ? ... nah */
103 return obj->objectName()
104 .remove( QRegExp( "Slider|Combo|Dial|Check|Spin|Text" ) )
105 .replace( QRegExp( "([A-Z])" ), "-\\1" )
106 .toLower();
109 static inline void setup_vfilter( intf_thread_t *p_intf, const char* psz_name, QWidget *widget )
111 const char *psz_filter_type = GetVFilterType( p_intf, psz_name );
112 if( psz_filter_type == NULL )
113 return;
115 char *psz_filters = var_InheritString( THEPL, psz_filter_type );
116 if( psz_filters == NULL )
117 return;
119 QCheckBox *checkbox = qobject_cast<QCheckBox*>( widget );
120 QGroupBox *groupbox = qobject_cast<QGroupBox*>( widget );
121 if( filterIsPresent( qfu(psz_filters), qfu(psz_name) ) )
123 if( checkbox ) checkbox->setChecked( true ); \
124 else if (groupbox) groupbox->setChecked( true ); \
126 else
128 if( checkbox ) checkbox->setChecked( false );
129 else if (groupbox) groupbox->setChecked( false );
131 free( psz_filters );
134 #define SETUP_VFILTER( widget ) \
135 setup_vfilter( p_intf, #widget, ui.widget##Enable ); \
136 CONNECT( ui.widget##Enable, clicked(), this, updateFilters() );
138 #define SETUP_VFILTER_OPTION( widget, signal ) \
139 initComboBoxItems( ui.widget ); \
140 setWidgetValue( ui.widget ); \
141 CONNECT( ui.widget, signal, this, updateFilterOptions() );
143 ExtVideo::ExtVideo( intf_thread_t *_p_intf, QTabWidget *_parent ) :
144 QObject( _parent ), p_intf( _p_intf )
146 ui.setupUi( _parent );
148 SETUP_VFILTER( adjust )
149 SETUP_VFILTER_OPTION( hueSlider, valueChanged( int ) )
150 SETUP_VFILTER_OPTION( contrastSlider, valueChanged( int ) )
151 SETUP_VFILTER_OPTION( brightnessSlider, valueChanged( int ) )
152 SETUP_VFILTER_OPTION( saturationSlider, valueChanged( int ) )
153 SETUP_VFILTER_OPTION( gammaSlider, valueChanged( int ) )
154 SETUP_VFILTER_OPTION( brightnessThresholdCheck, stateChanged( int ) )
156 SETUP_VFILTER( extract )
157 SETUP_VFILTER_OPTION( extractComponentText, textChanged( const QString& ) )
159 SETUP_VFILTER( posterize )
161 SETUP_VFILTER( colorthres )
162 SETUP_VFILTER_OPTION( colorthresColorText, textChanged( const QString& ) )
163 SETUP_VFILTER_OPTION( colorthresSaturationthresSlider, valueChanged( int ) )
164 SETUP_VFILTER_OPTION( colorthresSimilaritythresSlider, valueChanged( int ) )
166 SETUP_VFILTER( sepia )
167 SETUP_VFILTER_OPTION( sepiaIntensitySpin, valueChanged( int ) )
169 SETUP_VFILTER( invert )
171 SETUP_VFILTER( gradient )
172 SETUP_VFILTER_OPTION( gradientModeCombo, currentIndexChanged( QString ) )
173 SETUP_VFILTER_OPTION( gradientTypeCheck, stateChanged( int ) )
174 SETUP_VFILTER_OPTION( gradientCartoonCheck, stateChanged( int ) )
176 SETUP_VFILTER( motionblur )
177 SETUP_VFILTER_OPTION( blurFactorSlider, valueChanged( int ) )
179 SETUP_VFILTER( motiondetect )
181 SETUP_VFILTER( psychedelic )
183 SETUP_VFILTER( sharpen )
184 SETUP_VFILTER_OPTION( sharpenSigmaSlider, valueChanged( int ) )
186 SETUP_VFILTER( ripple )
188 SETUP_VFILTER( wave )
190 SETUP_VFILTER( transform )
191 SETUP_VFILTER_OPTION( transformTypeCombo, currentIndexChanged( QString ) )
193 SETUP_VFILTER( rotate )
194 SETUP_VFILTER_OPTION( rotateAngleDial, valueChanged( int ) )
195 ui.rotateAngleDial->setWrapping( true );
196 ui.rotateAngleDial->setNotchesVisible( true );
198 SETUP_VFILTER( puzzle )
199 SETUP_VFILTER_OPTION( puzzleRowsSpin, valueChanged( int ) )
200 SETUP_VFILTER_OPTION( puzzleColsSpin, valueChanged( int ) )
202 SETUP_VFILTER( magnify )
204 SETUP_VFILTER( clone )
205 SETUP_VFILTER_OPTION( cloneCountSpin, valueChanged( int ) )
207 SETUP_VFILTER( wall )
208 SETUP_VFILTER_OPTION( wallRowsSpin, valueChanged( int ) )
209 SETUP_VFILTER_OPTION( wallColsSpin, valueChanged( int ) )
212 SETUP_VFILTER( erase )
213 SETUP_VFILTER_OPTION( eraseMaskText, editingFinished() )
214 SETUP_VFILTER_OPTION( eraseYSpin, valueChanged( int ) )
215 SETUP_VFILTER_OPTION( eraseXSpin, valueChanged( int ) )
216 BUTTONACT( ui.eraseBrowseBtn, browseEraseFile() );
218 SETUP_VFILTER( marq )
219 SETUP_VFILTER_OPTION( marqMarqueeText, textChanged( const QString& ) )
220 SETUP_VFILTER_OPTION( marqPositionCombo, currentIndexChanged( QString ) )
222 SETUP_VFILTER( logo )
223 SETUP_VFILTER_OPTION( logoFileText, editingFinished() )
224 SETUP_VFILTER_OPTION( logoYSpin, valueChanged( int ) )
225 SETUP_VFILTER_OPTION( logoXSpin, valueChanged( int ) )
226 SETUP_VFILTER_OPTION( logoOpacitySlider, valueChanged( int ) )
227 BUTTONACT( ui.logoBrowseBtn, browseLogo() );
229 SETUP_VFILTER( gradfun )
230 SETUP_VFILTER_OPTION( gradfunRadiusSlider, valueChanged( int ) )
232 SETUP_VFILTER( grain )
233 SETUP_VFILTER_OPTION( grainVarianceSlider, valueChanged( int ) )
235 SETUP_VFILTER( mirror )
237 SETUP_VFILTER( gaussianblur )
238 SETUP_VFILTER_OPTION( gaussianblurSigmaSlider, valueChanged( int ) )
240 SETUP_VFILTER( antiflicker )
241 SETUP_VFILTER_OPTION( antiflickerSofteningSizeSlider, valueChanged( int ) )
243 SETUP_VFILTER( hqdn3d )
244 SETUP_VFILTER_OPTION( hqdn3dLumaSpatSlider, valueChanged( int ) )
245 SETUP_VFILTER_OPTION( hqdn3dLumaTempSlider, valueChanged( int ) )
246 SETUP_VFILTER_OPTION( hqdn3dChromaSpatSlider, valueChanged( int ) )
247 SETUP_VFILTER_OPTION( hqdn3dChromaTempSlider, valueChanged( int ) )
250 SETUP_VFILTER( anaglyph )
252 #undef SETUP_VFILTER
253 #undef SETUP_VFILTER_OPTION
255 CONNECT( ui.cropTopPx, valueChanged( int ), this, cropChange() );
256 CONNECT( ui.cropBotPx, valueChanged( int ), this, cropChange() );
257 CONNECT( ui.cropLeftPx, valueChanged( int ), this, cropChange() );
258 CONNECT( ui.cropRightPx, valueChanged( int ), this, cropChange() );
259 CONNECT( ui.leftRightCropSync, toggled ( bool ), this, cropChange() );
260 CONNECT( ui.topBotCropSync, toggled ( bool ), this, cropChange() );
261 CONNECT( ui.topBotCropSync, toggled( bool ),
262 ui.cropBotPx, setDisabled( bool ) );
263 CONNECT( ui.leftRightCropSync, toggled( bool ),
264 ui.cropRightPx, setDisabled( bool ) );
267 void ExtVideo::cropChange()
269 if( ui.topBotCropSync->isChecked() )
270 ui.cropBotPx->setValue( ui.cropTopPx->value() );
271 if( ui.leftRightCropSync->isChecked() )
272 ui.cropRightPx->setValue( ui.cropLeftPx->value() );
274 QVector<vout_thread_t*> p_vouts = THEMIM->getVouts();
275 foreach( vout_thread_t *p_vout, p_vouts )
277 var_SetInteger( p_vout, "crop-top", ui.cropTopPx->value() );
278 var_SetInteger( p_vout, "crop-bottom", ui.cropBotPx->value() );
279 var_SetInteger( p_vout, "crop-left", ui.cropLeftPx->value() );
280 var_SetInteger( p_vout, "crop-right", ui.cropRightPx->value() );
281 vlc_object_release( p_vout );
285 void ExtVideo::clean()
287 ui.cropTopPx->setValue( 0 );
288 ui.cropBotPx->setValue( 0 );
289 ui.cropLeftPx->setValue( 0 );
290 ui.cropRightPx->setValue( 0 );
293 static QString ChangeFiltersString( struct intf_thread_t *p_intf, const char *psz_filter_type, const char *psz_name, bool b_add )
295 char* psz_chain = var_GetString( THEPL, psz_filter_type );
297 QString const chain = QString( psz_chain ? psz_chain : "" );
298 QStringList list = chain.split( ':', QString::SplitBehavior::SkipEmptyParts );
300 if( b_add && std::find(list.begin(), list.end(), psz_name) == list.end() )
301 list << psz_name;
302 else if (!b_add)
303 list.removeAll( psz_name );
305 free( psz_chain );
307 return list.join( ":" );
310 static void UpdateVFiltersString( struct intf_thread_t *p_intf,
311 const char *psz_filter_type, const char *value )
313 var_SetString( THEPL, psz_filter_type, value );
315 /* Try to set non splitter filters on the fly */
316 if( strcmp( psz_filter_type, "video-splitter" ) )
318 QVector<vout_thread_t*> p_vouts = THEMIM->getVouts();
319 foreach( vout_thread_t *p_vout, p_vouts )
321 var_SetString( p_vout, psz_filter_type, value );
322 vlc_object_release( p_vout );
327 void ExtVideo::changeVFiltersString( const char *psz_name, bool b_add )
329 const char *psz_filter_type = GetVFilterType( p_intf, psz_name );
330 if( psz_filter_type == NULL )
331 return;
333 QString result = ChangeFiltersString( p_intf, psz_filter_type, psz_name, b_add );
335 emit configChanged( qfu( psz_filter_type ), result );
337 UpdateVFiltersString( p_intf, psz_filter_type, qtu( result ) );
340 void ExtVideo::updateFilters()
342 QString module = ModuleFromWidgetName( sender() );
344 QCheckBox *checkbox = qobject_cast<QCheckBox*>( sender() );
345 QGroupBox *groupbox = qobject_cast<QGroupBox*>( sender() );
347 changeVFiltersString( qtu( module ),
348 checkbox ? checkbox->isChecked()
349 : groupbox->isChecked() );
352 #define UPDATE_AND_APPLY_TEXT( widget, file ) \
353 CONNECT( ui.widget, textChanged( const QString& ), \
354 this, updateFilterOptions() ); \
355 ui.widget->setText( toNativeSeparators( file ) ); \
356 ui.widget->disconnect( SIGNAL( textChanged( const QString& ) ) );
358 void ExtVideo::browseLogo()
360 QString file = QFileDialog::getOpenFileName( NULL, qtr( "Logo filenames" ),
361 p_intf->p_sys->filepath, "Images (*.png *.jpg);;All (*)" );
363 UPDATE_AND_APPLY_TEXT( logoFileText, file );
366 void ExtVideo::browseEraseFile()
368 QString file = QFileDialog::getOpenFileName( NULL, qtr( "Image mask" ),
369 p_intf->p_sys->filepath, "Images (*.png *.jpg);;All (*)" );
371 UPDATE_AND_APPLY_TEXT( eraseMaskText, file );
374 #undef UPDATE_AND_APPLY_TEXT
376 void ExtVideo::initComboBoxItems( QObject *widget )
378 QComboBox *combobox = qobject_cast<QComboBox*>( widget );
379 if( !combobox ) return;
381 QString option = OptionFromWidgetName( widget );
382 module_config_t *p_item = config_FindConfig( qtu( option ) );
383 if( p_item == NULL )
385 msg_Err( p_intf, "Couldn't find option \"%s\".", qtu( option ) );
386 return;
389 if( p_item->i_type == CONFIG_ITEM_INTEGER
390 || p_item->i_type == CONFIG_ITEM_BOOL )
392 int64_t *values;
393 char **texts;
394 ssize_t count = config_GetIntChoices( VLC_OBJECT( p_intf ),
395 qtu( option ), &values, &texts );
396 for( ssize_t i = 0; i < count; i++ )
398 combobox->addItem( qtr( texts[i] ), qlonglong(values[i]) );
399 free( texts[i] );
401 free( texts );
402 free( values );
404 else if( p_item->i_type == CONFIG_ITEM_STRING )
406 char **values;
407 char **texts;
408 ssize_t count = config_GetPszChoices( VLC_OBJECT( p_intf ),
409 qtu( option ), &values, &texts );
410 for( ssize_t i = 0; i < count; i++ )
412 combobox->addItem( qtr( texts[i] ), qfu(values[i]) );
413 free( texts[i] );
414 free( values[i] );
416 free( texts );
417 free( values );
421 void ExtVideo::setWidgetValue( QObject *widget )
423 QString module = ModuleFromWidgetName( widget->parent() );
424 //std::cout << "Module name: " << module.toStdString() << std::endl;
425 QString option = OptionFromWidgetName( widget );
426 //std::cout << "Option name: " << option.toStdString() << std::endl;
428 vlc_value_t val;
429 int i_type = config_GetType( qtu( option ) ) & VLC_VAR_CLASS;
430 switch( i_type )
432 case VLC_VAR_INTEGER:
433 case VLC_VAR_BOOL:
434 case VLC_VAR_FLOAT:
435 case VLC_VAR_STRING:
436 break;
437 default:
438 msg_Err( p_intf,
439 "Module %s's %s variable is of an unsupported type ( %d )",
440 qtu( module ), qtu( option ), i_type );
441 return;
443 if( var_Create( THEPL, qtu( option ), i_type | VLC_VAR_DOINHERIT ) )
444 return;
445 if( var_GetChecked( THEPL, qtu( option ), i_type, &val ) )
446 return;
448 /* Try to cast to all the widgets we're likely to encounter. Only
449 * one of the casts is expected to work. */
450 QSlider *slider = qobject_cast<QSlider*> ( widget );
451 QCheckBox *checkbox = qobject_cast<QCheckBox*> ( widget );
452 QSpinBox *spinbox = qobject_cast<QSpinBox*> ( widget );
453 QDoubleSpinBox *doublespinbox = qobject_cast<QDoubleSpinBox*>( widget );
454 VLCQDial *dial = qobject_cast<VLCQDial*> ( widget );
455 QLineEdit *lineedit = qobject_cast<QLineEdit*> ( widget );
456 QComboBox *combobox = qobject_cast<QComboBox*> ( widget );
458 if( i_type == VLC_VAR_INTEGER || i_type == VLC_VAR_BOOL )
460 if( slider ) slider->setValue( val.i_int );
461 else if( checkbox ) checkbox->setCheckState( val.i_int? Qt::Checked
462 : Qt::Unchecked );
463 else if( spinbox ) spinbox->setValue( val.i_int );
464 else if( dial ) dial->setValue( (360 - val.i_int) % 360 );
465 else if( lineedit )
467 char str[30];
468 snprintf( str, sizeof(str), "%06" PRIX64, val.i_int );
469 lineedit->setText( str );
471 else if( combobox ) combobox->setCurrentIndex(
472 combobox->findData( qlonglong(val.i_int) ) );
473 else msg_Warn( p_intf, "Could not find the correct Integer widget" );
475 else if( i_type == VLC_VAR_FLOAT )
477 if( slider ) slider->setValue( ( int )( val.f_float*( double )slider->tickInterval() ) ); /* hack alert! */
478 else if( doublespinbox ) doublespinbox->setValue( val.f_float );
479 else if( dial ) dial->setValue( (360 - lroundf(val.f_float)) % 360 );
480 else msg_Warn( p_intf, "Could not find the correct Float widget" );
482 else if( i_type == VLC_VAR_STRING )
484 if( lineedit ) lineedit->setText( qfu( val.psz_string ) );
485 else if( combobox ) combobox->setCurrentIndex(
486 combobox->findData( qfu( val.psz_string ) ) );
487 else msg_Warn( p_intf, "Could not find the correct String widget" );
488 free( val.psz_string );
492 void ExtVideo::setFilterOption( const char *psz_module, const char *psz_option,
493 int i_int, double f_float, const char *psz_string )
495 QVector<vout_thread_t*> p_vouts = THEMIM->getVouts();
496 int i_type = 0;
497 bool b_is_command = false;
499 if( !p_vouts.isEmpty() )
501 i_type = var_Type( p_vouts.at(0), psz_option );
502 b_is_command = ( i_type & VLC_VAR_ISCOMMAND );
504 if( i_type == 0 )
505 i_type = config_GetType( psz_option );
507 vlc_value_t val;
508 i_type &= VLC_VAR_CLASS;
509 if( i_type == VLC_VAR_INTEGER || i_type == VLC_VAR_BOOL )
511 emit configChanged( qfu( psz_option ), QVariant( i_int ) );
512 if( i_type == VLC_VAR_INTEGER )
514 val.i_int = i_int;
515 var_SetInteger( THEPL, psz_option, i_int );
517 else
519 var_SetBool( THEPL, psz_option, i_int );
520 val.b_bool = i_int;
523 else if( i_type == VLC_VAR_FLOAT )
525 emit configChanged( qfu( psz_option ), QVariant( f_float ) );
526 var_SetFloat( THEPL, psz_option, f_float );
527 val.f_float = f_float;
529 else if( i_type == VLC_VAR_STRING )
531 if( psz_string == NULL )
532 psz_string = "";
533 emit configChanged( qfu( psz_option ), QVariant( psz_string ) );
534 var_SetString( THEPL, psz_option, psz_string );
535 val.psz_string = (char *) psz_string;
537 else
539 msg_Err( p_intf,
540 "Module %s's %s variable is of an unsupported type ( %d )",
541 psz_module,
542 psz_option,
543 i_type );
544 b_is_command = false;
547 if( b_is_command )
549 foreach( vout_thread_t *p_vout, p_vouts )
551 var_SetChecked( p_vout, psz_option, i_type, val );
552 #ifndef NDEBUG
553 int i_cur_type = var_Type( p_vout, psz_option );
554 assert( ( i_cur_type & VLC_VAR_CLASS ) == i_type );
555 assert( !!( i_cur_type & VLC_VAR_ISCOMMAND ) == b_is_command );
556 #endif
560 foreach( vout_thread_t *p_vout, p_vouts )
561 vlc_object_release( p_vout );
564 void ExtVideo::updateFilterOptions()
566 QString module = ModuleFromWidgetName( sender()->parent() );
567 //msg_Dbg( p_intf, "Module name: %s", qtu( module ) );
568 QString option = OptionFromWidgetName( sender() );
569 //msg_Dbg( p_intf, "Option name: %s", qtu( option ) );
571 /* Try to cast to all the widgets we're likely to encounter. Only
572 * one of the casts is expected to work. */
573 QSlider *slider = qobject_cast<QSlider*> ( sender() );
574 QCheckBox *checkbox = qobject_cast<QCheckBox*> ( sender() );
575 QSpinBox *spinbox = qobject_cast<QSpinBox*> ( sender() );
576 QDoubleSpinBox *doublespinbox = qobject_cast<QDoubleSpinBox*>( sender() );
577 VLCQDial *dial = qobject_cast<VLCQDial*> ( sender() );
578 QLineEdit *lineedit = qobject_cast<QLineEdit*> ( sender() );
579 QComboBox *combobox = qobject_cast<QComboBox*> ( sender() );
581 int i_int = -1;
582 double f_float = -1.;
583 QString val;
585 if( slider ) {
586 i_int = slider->value();
587 f_float = ( double )slider->value() / ( double )slider->tickInterval(); /* hack alert! */
589 else if( checkbox ) i_int = checkbox->checkState() == Qt::Checked;
590 else if( spinbox ) i_int = spinbox->value();
591 else if( doublespinbox ) f_float = doublespinbox->value();
592 else if( dial ) {
593 i_int = (360 - dial->value()) % 360;
594 f_float = i_int;
596 else if( lineedit ) {
597 i_int = lineedit->text().toInt( NULL,16 );
598 f_float = lineedit->text().toDouble();
599 val = lineedit->text();
601 else if( combobox ) {
602 i_int = combobox->itemData( combobox->currentIndex() ).toInt();
603 val = combobox->itemData( combobox->currentIndex() ).toString();
606 setFilterOption( qtu( module ), qtu( option ), i_int, f_float, qtu( val ) );
609 /**********************************************************************
610 * v4l2 controls
611 **********************************************************************/
613 ExtV4l2::ExtV4l2( intf_thread_t *_p_intf, QWidget *_parent )
614 : QWidget( _parent ), p_intf( _p_intf ), box( NULL )
616 QVBoxLayout *layout = new QVBoxLayout( this );
617 help = new QLabel( qtr("No v4l2 instance found.\n"
618 "Please check that the device has been opened with VLC and is playing.\n\n"
619 "Controls will automatically appear here.")
620 , this );
621 help->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
622 help->setWordWrap( true );
623 layout->addWidget( help );
624 setLayout( layout );
627 void ExtV4l2::showEvent( QShowEvent *event )
629 QWidget::showEvent( event );
630 Refresh();
633 void ExtV4l2::Refresh( void )
635 vlc_object_t *p_obj = (vlc_object_t*)vlc_object_find_name( THEPL, "v4l2" );
636 help->hide();
637 if( box )
639 layout()->removeWidget( box );
640 delete box;
641 box = NULL;
643 if( p_obj )
645 vlc_value_t val, text;
646 int i_ret = var_Change( p_obj, "controls", VLC_VAR_GETCHOICES,
647 &val, &text );
648 if( i_ret < 0 )
650 msg_Err( p_intf, "Oops, v4l2 object doesn't have a 'controls' variable." );
651 help->show();
652 vlc_object_release( p_obj );
653 return;
656 box = new QGroupBox( this );
657 layout()->addWidget( box );
658 QVBoxLayout *layout = new QVBoxLayout( box );
659 box->setLayout( layout );
661 for( int i = 0; i < val.p_list->i_count; i++ )
663 vlc_value_t vartext;
664 const char *psz_var = text.p_list->p_values[i].psz_string;
666 if( var_Change( p_obj, psz_var, VLC_VAR_GETTEXT, &vartext, NULL ) )
667 continue;
669 QString name = qtr( vartext.psz_string );
670 free( vartext.psz_string );
671 msg_Dbg( p_intf, "v4l2 control \"%" PRIx64 "\": %s (%s)",
672 val.p_list->p_values[i].i_int, psz_var, qtu( name ) );
674 int i_type = var_Type( p_obj, psz_var );
675 switch( i_type & VLC_VAR_TYPE )
677 case VLC_VAR_INTEGER:
679 QLabel *label = new QLabel( name, box );
680 QHBoxLayout *hlayout = new QHBoxLayout();
681 hlayout->addWidget( label );
682 int i_val = var_GetInteger( p_obj, psz_var );
683 if( i_type & VLC_VAR_HASCHOICE )
685 QComboBox *combobox = new QComboBox( box );
686 combobox->setObjectName( qfu( psz_var ) );
688 vlc_value_t val2, text2;
689 var_Change( p_obj, psz_var, VLC_VAR_GETCHOICES,
690 &val2, &text2 );
691 for( int j = 0; j < val2.p_list->i_count; j++ )
693 combobox->addItem(
694 text2.p_list->p_values[j].psz_string,
695 qlonglong( val2.p_list->p_values[j].i_int) );
696 if( i_val == val2.p_list->p_values[j].i_int )
697 combobox->setCurrentIndex( j );
699 var_FreeList( &val2, &text2 );
701 CONNECT( combobox, currentIndexChanged( int ), this,
702 ValueChange( int ) );
703 hlayout->addWidget( combobox );
705 else
707 QSlider *slider = new QSlider( box );
708 slider->setObjectName( qfu( psz_var ) );
709 slider->setOrientation( Qt::Horizontal );
710 vlc_value_t val2;
711 var_Change( p_obj, psz_var, VLC_VAR_GETMIN,
712 &val2, NULL );
713 if( val2.i_int < INT_MIN )
714 val2.i_int = INT_MIN; /* FIXME */
715 slider->setMinimum( val2.i_int );
716 var_Change( p_obj, psz_var, VLC_VAR_GETMAX,
717 &val2, NULL );
718 if( val2.i_int > INT_MAX )
719 val2.i_int = INT_MAX; /* FIXME */
720 slider->setMaximum( val2.i_int );
721 if( !var_Change( p_obj, psz_var, VLC_VAR_GETSTEP,
722 &val2, NULL ) )
723 slider->setSingleStep( val2.i_int );
724 slider->setValue( i_val );
725 CONNECT( slider, valueChanged( int ), this,
726 ValueChange( int ) );
727 hlayout->addWidget( slider );
729 layout->addLayout( hlayout );
730 break;
732 case VLC_VAR_BOOL:
734 QCheckBox *button = new QCheckBox( name, box );
735 button->setObjectName( qfu( psz_var ) );
736 button->setChecked( var_GetBool( p_obj, psz_var ) );
738 CONNECT( button, clicked( bool ), this,
739 ValueChange( bool ) );
740 layout->addWidget( button );
741 break;
743 case VLC_VAR_VOID:
745 if( i_type & VLC_VAR_ISCOMMAND )
747 QPushButton *button = new QPushButton( name, box );
748 button->setObjectName( qfu( psz_var ) );
750 CONNECT( button, clicked( bool ), this,
751 ValueChange( bool ) );
752 layout->addWidget( button );
754 else
756 QLabel *label = new QLabel( name, box );
757 layout->addWidget( label );
759 break;
761 default:
762 msg_Warn( p_intf, "Unhandled var type for %s", psz_var );
763 break;
766 var_FreeList( &val, &text );
767 vlc_object_release( p_obj );
769 else
771 msg_Dbg( p_intf, "Couldn't find v4l2 instance" );
772 help->show();
773 if ( isVisible() )
774 QTimer::singleShot( 2000, this, SLOT(Refresh()) );
778 void ExtV4l2::ValueChange( bool value )
780 ValueChange( (int)value );
783 void ExtV4l2::ValueChange( int value )
785 QObject *s = sender();
786 vlc_object_t *p_obj = (vlc_object_t*)vlc_object_find_name( THEPL, "v4l2" );
787 if( p_obj )
789 QString var = s->objectName();
790 int i_type = var_Type( p_obj, qtu( var ) );
791 switch( i_type & VLC_VAR_TYPE )
793 case VLC_VAR_INTEGER:
794 if( i_type & VLC_VAR_HASCHOICE )
796 QComboBox *combobox = qobject_cast<QComboBox*>( s );
797 value = combobox->itemData( value ).toInt();
799 var_SetInteger( p_obj, qtu( var ), value );
800 break;
801 case VLC_VAR_BOOL:
802 var_SetBool( p_obj, qtu( var ), value );
803 break;
804 case VLC_VAR_VOID:
805 var_TriggerCallback( p_obj, qtu( var ) );
806 break;
808 vlc_object_release( p_obj );
810 else
812 msg_Warn( p_intf, "Oops, v4l2 object isn't available anymore" );
813 Refresh();
817 /**********************************************************************
818 * Sliders
819 **********************************************************************/
821 FilterSliderData::FilterSliderData( QObject *parent, QSlider *_slider ) :
822 QObject( parent ), slider( _slider )
826 FilterSliderData::FilterSliderData( QObject *parent,
827 intf_thread_t *_p_intf,
828 QSlider *_slider,
829 QLabel *_label, QLabel *_nameLabel,
830 const slider_data_t *_p_data ):
831 QObject( parent ), slider( _slider ), valueLabel( _label ),
832 nameLabel( _nameLabel ), p_data( _p_data ), p_intf( _p_intf )
834 slider->setMinimum( p_data->f_min / p_data->f_resolution );
835 slider->setMaximum( p_data->f_max / p_data->f_resolution );
836 nameLabel->setText( p_data->descs );
837 CONNECT( slider, valueChanged( int ), this, updateText( int ) );
838 setValue( initialValue() );
839 /* In case current == min|max text would not be first updated */
840 if ( slider->value() == slider->maximum() ||
841 slider->value() == slider->minimum() )
842 updateText( slider->value() );
843 CONNECT( slider, valueChanged( int ), this, onValueChanged( int ) );
846 void FilterSliderData::setValue( float f )
848 slider->setValue( f / p_data->f_resolution );
851 void FilterSliderData::updateText( int i )
853 float f = ((float) i) * p_data->f_resolution * p_data->f_visual_multiplier;
854 valueLabel->setText( QString( p_data->units )
855 .prepend( "%1 " )
856 .arg( QString::number( f, 'f', 1 ) ) );
859 float FilterSliderData::initialValue()
861 vlc_object_t *p_aout = (vlc_object_t *) THEMIM->getAout();
862 float f = p_data->f_value;
863 if( p_aout )
865 if ( var_Type( p_aout, qtu(p_data->name) ) == 0 )
867 vlc_object_release( p_aout );
868 /* Not found, will try in config */
870 else
872 f = var_GetFloat( p_aout, qtu(p_data->name) );
873 vlc_object_release( p_aout );
874 return f;
878 if ( ! config_FindConfig( qtu(p_data->name) ) )
879 return f;
881 f = config_GetFloat( p_intf, qtu(p_data->name) );
882 return f;
885 void FilterSliderData::onValueChanged( int i )
887 float f = ((float) i) * p_data->f_resolution;
888 vlc_object_t *p_aout = (vlc_object_t *) THEMIM->getAout();
889 if ( p_aout )
891 var_SetFloat( p_aout, qtu(p_data->name), f );
892 vlc_object_release( p_aout );
894 writeToConfig();
897 void FilterSliderData::writeToConfig()
899 float f = ((float) slider->value()) * p_data->f_resolution;
900 emit configChanged( p_data->name, QVariant( f ) );
903 AudioFilterControlWidget::AudioFilterControlWidget
904 ( intf_thread_t *_p_intf, QWidget *parent, const char *_shortcut,
905 const char *_name = NULL ) :
906 QWidget( parent ), p_intf( _p_intf ), shortcut( _shortcut ),
907 name( _name ? _name : _shortcut ), i_smallfont(0)
911 void AudioFilterControlWidget::connectConfigChanged( FilterSliderData *slider )
913 connect( slider, SIGNAL( configChanged(QString, QVariant) ),
914 this, SIGNAL( configChanged(QString, QVariant) ) );
917 void AudioFilterControlWidget::build()
919 QFont smallFont = QApplication::font();
920 smallFont.setPointSize( smallFont.pointSize() + i_smallfont );
922 QVBoxLayout *layout = new QVBoxLayout( this );
923 slidersBox = new QGroupBox( qtr( "Enable" ) );
924 slidersBox->setCheckable( true );
925 layout->addWidget( slidersBox );
927 QGridLayout *ctrlLayout = new QGridLayout( slidersBox );
929 int i = 0;
930 foreach( const FilterSliderData::slider_data_t &data, controls )
932 QSlider *slider = new QSlider( Qt::Vertical );
933 QLabel *valueLabel = new QLabel();
934 valueLabel->setFont( smallFont );
935 valueLabel->setAlignment( Qt::AlignHCenter );
936 QLabel *nameLabel = new QLabel();
937 nameLabel->setFont( smallFont );
938 nameLabel->setAlignment( Qt::AlignHCenter );
939 FilterSliderData *filter =
940 new FilterSliderData( this, p_intf,
941 slider, valueLabel, nameLabel, & data );
942 ctrlLayout->addWidget( slider, 0, i, Qt::AlignHCenter );
943 ctrlLayout->addWidget( valueLabel, 1, i, Qt::AlignHCenter );
944 ctrlLayout->addWidget( nameLabel, 2, i, Qt::AlignHCenter );
945 i++;
946 sliderDatas << filter;
947 connectConfigChanged( filter );
950 char *psz_af = var_InheritString( THEPL, "audio-filter" );
952 if( psz_af && filterIsPresent( qfu(psz_af), shortcut ) )
953 slidersBox->setChecked( true );
954 else
955 slidersBox->setChecked( false );
956 CONNECT( slidersBox, toggled(bool), this, enable(bool) );
958 free( psz_af );
961 void AudioFilterControlWidget::enable( bool b_enable )
963 module_t *p_obj = module_find( qtu(name) );
964 if( !p_obj )
966 msg_Err( p_intf, "Unable to find filter module \"%s\".", qtu(name) );
967 return;
970 QString result = ChangeFiltersString( p_intf, "audio-filter", qtu(shortcut),
971 b_enable );
972 emit configChanged( qfu("audio-filter"), result );
973 playlist_EnableAudioFilter( THEPL, qtu(shortcut), b_enable );
976 /**********************************************************************
977 * Equalizer
978 **********************************************************************/
980 EqualizerSliderData::EqualizerSliderData( QObject *parent, intf_thread_t *_p_intf,
981 QSlider *slider, QLabel *_label,
982 QLabel *_nameLabel, const slider_data_t *_p_data,
983 int _index )
984 : FilterSliderData( parent, slider ), index( _index )
986 p_intf = _p_intf;
987 valueLabel = _label;
988 nameLabel = _nameLabel;
989 p_data = _p_data;
991 slider->setMinimum( p_data->f_min / p_data->f_resolution );
992 slider->setMaximum( p_data->f_max / p_data->f_resolution );
993 nameLabel->setText( p_data->descs );
994 CONNECT( slider, valueChanged( int ), this, updateText( int ) );
995 setValue( initialValue() );
996 updateText( slider->value() );
997 CONNECT( slider, valueChanged( int ), this, onValueChanged( int ) );
1000 QStringList EqualizerSliderData::getBandsFromAout() const
1002 vlc_object_t *p_aout = (vlc_object_t *) THEMIM->getAout();
1003 QStringList bands;
1004 if( p_aout )
1006 if ( var_Type( p_aout, qtu(p_data->name) ) == VLC_VAR_STRING )
1008 char *psz_bands = var_GetString( p_aout, qtu(p_data->name) );
1009 if ( psz_bands )
1011 bands = QString( psz_bands ).split( " ", QString::SkipEmptyParts );
1012 free( psz_bands );
1015 vlc_object_release( p_aout );
1018 if ( bands.count() ) return bands;
1019 /* Or try config then */
1021 if ( ! config_FindConfig( qtu(p_data->name) ) )
1022 return bands;
1024 char *psz_bands = config_GetPsz( p_intf, qtu(p_data->name) );
1025 if ( psz_bands )
1027 bands = QString( psz_bands ).split( " ", QString::SkipEmptyParts );
1028 free( psz_bands );
1031 return bands;
1034 float EqualizerSliderData::initialValue()
1036 float f = p_data->f_value;
1037 QStringList bands = getBandsFromAout();
1039 if ( bands.count() > index )
1040 f = QLocale( QLocale::C ).toFloat( bands[ index ] );
1042 return f;
1045 void EqualizerSliderData::onValueChanged( int i )
1047 QStringList bands = getBandsFromAout();
1048 if ( bands.count() > index )
1050 float f = ((float) i) * p_data->f_resolution;
1051 bands[ index ] = QLocale( QLocale::C ).toString( f );
1052 vlc_object_t *p_aout = (vlc_object_t *) THEMIM->getAout();
1053 if ( p_aout )
1055 var_SetString( p_aout, qtu(p_data->name), qtu(bands.join( " " )) );
1056 vlc_object_release( p_aout );
1058 writeToConfig();
1062 void EqualizerSliderData::writeToConfig()
1064 QStringList bands = getBandsFromAout();
1065 if ( bands.count() > index )
1067 float f = (float) slider->value() * p_data->f_resolution;
1068 bands[ index ] = QLocale( QLocale::C ).toString( f );
1069 emit configChanged( p_data->name, QVariant( bands.join( " " ) ) );
1073 Equalizer::Equalizer( intf_thread_t *p_intf, QWidget *parent )
1074 : AudioFilterControlWidget( p_intf, parent, "equalizer" )
1076 i_smallfont = -3;
1077 bool b_vlcBands = var_InheritBool( p_intf, "equalizer-vlcfreqs" );
1079 const FilterSliderData::slider_data_t vlc_bands[10] =
1081 { "equalizer-bands", qtr("60 Hz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1082 { "equalizer-bands", qtr("170 Hz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1083 { "equalizer-bands", qtr("310 Hz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1084 { "equalizer-bands", qtr("600 Hz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1085 { "equalizer-bands", qtr("1 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1086 { "equalizer-bands", qtr("3 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1087 { "equalizer-bands", qtr("6 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1088 { "equalizer-bands", qtr("12 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1089 { "equalizer-bands", qtr("14 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1090 { "equalizer-bands", qtr("16 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1092 const FilterSliderData::slider_data_t iso_bands[10] =
1094 { "equalizer-bands", qtr("31 Hz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1095 { "equalizer-bands", qtr("63 Hz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1096 { "equalizer-bands", qtr("125 Hz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1097 { "equalizer-bands", qtr("250 Hz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1098 { "equalizer-bands", qtr("500 Hz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1099 { "equalizer-bands", qtr("1 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1100 { "equalizer-bands", qtr("2 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1101 { "equalizer-bands", qtr("4 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1102 { "equalizer-bands", qtr("8 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1103 { "equalizer-bands", qtr("16 KHz"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 },
1105 const FilterSliderData::slider_data_t preamp_vals =
1106 { "equalizer-preamp", qtr("Preamp"), qtr("dB"), -20.0f, 20.0f, 0.0f, 0.1f, 1.0 };
1108 for( int i=0; i<10 ;i++ ) controls.append( (b_vlcBands) ? vlc_bands[i] : iso_bands[i] );
1109 preamp_values = preamp_vals;
1110 build();
1113 void Equalizer::build()
1115 QFont smallFont = QApplication::font();
1116 smallFont.setPointSize( smallFont.pointSize() + i_smallfont );
1118 Ui::EqualizerWidget ui;
1119 ui.setupUi( this );
1121 QGridLayout *ctrlLayout = new QGridLayout( ui.slidersPlaceholder );
1123 /* set up preamp control */
1124 ui.preampLabel->setFont( smallFont );
1125 ui.preampValue->setFont( smallFont );
1126 preamp = new FilterSliderData( this, p_intf,
1127 ui.preampSlider, ui.preampValue, ui.preampLabel, & preamp_values );
1128 connectConfigChanged( preamp );
1130 /* fix sliders spacing accurately */
1131 int i_width = qMax( QFontMetrics( smallFont ).width( "500 Hz" ),
1132 QFontMetrics( smallFont ).width( "-20.0 dB" ) );
1133 int i = 0;
1134 foreach( const FilterSliderData::slider_data_t &data, controls )
1136 QSlider *slider = new QSlider( Qt::Vertical );
1137 slider->setMinimumWidth( i_width );
1138 QLabel *valueLabel = new QLabel();
1139 valueLabel->setFont( smallFont );
1140 valueLabel->setAlignment( Qt::AlignHCenter );
1141 QLabel *nameLabel = new QLabel();
1142 nameLabel->setFont( smallFont );
1143 nameLabel->setAlignment( Qt::AlignHCenter );
1144 EqualizerSliderData *filter =
1145 new EqualizerSliderData( this, p_intf,
1146 slider, valueLabel, nameLabel, & data, i );
1147 ctrlLayout->addWidget( slider, 0, i, Qt::AlignHCenter );
1148 ctrlLayout->addWidget( valueLabel, 2, i, Qt::AlignHCenter );
1149 ctrlLayout->addWidget( nameLabel, 1, i, Qt::AlignHCenter );
1150 sliderDatas << filter; /* keep track for applying presets */
1151 i++;
1152 connectConfigChanged( filter );
1155 /* Add the listed presets */
1156 ui.presetsCombo->addItem( "", QVariant() ); /* 1st entry = custom/modified */
1157 for( i = 0 ; i < NB_PRESETS ; i ++ )
1159 QGraphicsScene scene;
1160 #if HAS_QT56
1161 qreal f_ratio = QApplication::primaryScreen()->devicePixelRatio();
1162 QPixmap icon( 40 * f_ratio, 40 * f_ratio );
1163 #else
1164 QPixmap icon( 40, 40 );
1165 #endif
1166 icon.fill( Qt::transparent );
1167 QPainter painter( &icon );
1168 for ( int j = 0; j < eqz_preset_10b[i].i_band; j++ )
1170 float f_value = eqz_preset_10b[i].f_amp[j];
1171 if ( f_value > 20.0 ) f_value = 20.0;
1172 if ( f_value < -20.0 ) f_value = -20.0;
1173 QRectF shape( j, 20.0 - f_value, 1, f_value );
1174 scene.addRect( shape, QPen(), palette().brush( QPalette::WindowText ) );
1176 scene.addLine( 0.0, 20.0, eqz_preset_10b[i].i_band, 20.0,
1177 palette().color( QPalette::WindowText ) );
1178 scene.setSceneRect( 0.0, 0.0, eqz_preset_10b[i].i_band , 40.0 );
1179 scene.render( &painter, icon.rect(), scene.sceneRect(), Qt::IgnoreAspectRatio );
1180 ui.presetsCombo->addItem( icon, qtr( preset_list_text[i] ),
1181 QVariant( preset_list[i] ) );
1183 CONNECT( ui.presetsCombo, activated(int), this, setCorePreset(int) );
1185 /* Set enable checkbox */
1186 vlc_object_t *p_aout = (vlc_object_t *)THEMIM->getAout();
1187 char *psz_af;
1188 if( p_aout )
1189 psz_af = var_GetNonEmptyString( p_aout, "audio-filter" );
1190 else
1191 psz_af = var_InheritString( THEPL, "audio-filter" );
1193 /* To enable or disable subwidgets */
1194 /* If that list grows, better iterate over layout's childs */
1195 CONNECT( ui.enableCheck, toggled(bool), ui.presetsCombo, setEnabled(bool) );
1196 CONNECT( ui.enableCheck, toggled(bool), ui.presetLabel, setEnabled(bool) );
1197 CONNECT( ui.enableCheck, toggled(bool), ui.eq2PassCheck, setEnabled(bool) );
1198 CONNECT( ui.enableCheck, toggled(bool), ui.slidersPlaceholder, setEnabled(bool) );
1199 CONNECT( ui.enableCheck, toggled(bool), ui.preampSlider, setEnabled(bool) );
1200 CONNECT( ui.enableCheck, toggled(bool), ui.preampValue, setEnabled(bool) );
1201 CONNECT( ui.enableCheck, toggled(bool), ui.preampLabel, setEnabled(bool) );
1203 if( psz_af && filterIsPresent( qfu(psz_af), name ) )
1204 ui.enableCheck->setChecked( true );
1205 else
1206 ui.enableCheck->setChecked( false );
1208 /* workaround for non emitted toggle() signal */
1209 ui.enableCheck->toggle(); ui.enableCheck->toggle();
1211 free( psz_af );
1212 CONNECT( ui.enableCheck, toggled(bool), this, enable(bool) );
1214 /* Connect and set 2 Pass checkbox */
1215 ui.eq2PassCheck->setChecked( var_InheritBool( p_aout, "equalizer-2pass" ) );
1216 CONNECT( ui.eq2PassCheck, toggled(bool), this, enable2Pass(bool) );
1217 if( p_aout )
1218 vlc_object_release( p_aout );
1221 void Equalizer::setCorePreset( int i_preset )
1223 if( i_preset < 1 )
1224 return;
1226 i_preset--;/* 1st in index was an empty entry */
1228 preamp->setValue( eqz_preset_10b[i_preset].f_preamp );
1229 for ( int i=0; i< qMin( eqz_preset_10b[i_preset].i_band,
1230 sliderDatas.count() ) ; i++ )
1231 sliderDatas[i]->setValue( eqz_preset_10b[i_preset].f_amp[i] );
1233 vlc_object_t *p_aout = (vlc_object_t *)THEMIM->getAout();
1234 if( p_aout )
1236 var_SetString( p_aout , "equalizer-preset" , preset_list[i_preset] );
1237 vlc_object_release( p_aout );
1239 emit configChanged( qfu( "equalizer-preset" ), QVariant( qfu( preset_list[i_preset] ) ) );
1242 /* Function called when the set2Pass button is activated */
1243 void Equalizer::enable2Pass( bool b_enable )
1245 vlc_object_t *p_aout= (vlc_object_t *)THEMIM->getAout();
1247 if( p_aout )
1249 var_SetBool( p_aout, "equalizer-2pass", b_enable );
1250 vlc_object_release( p_aout );
1252 emit configChanged( qfu( "equalizer-2pass" ), QVariant( b_enable ) );
1255 /**********************************************************************
1256 * Audio filters
1257 **********************************************************************/
1259 /**********************************************************************
1260 * Dynamic range compressor
1261 **********************************************************************/
1263 Compressor::Compressor( intf_thread_t *p_intf, QWidget *parent )
1264 : AudioFilterControlWidget( p_intf, parent, "compressor" )
1266 i_smallfont = -2;
1267 const FilterSliderData::slider_data_t a[7] =
1269 { "compressor-rms-peak", qtr("RMS/peak"), "", 0.0f, 1.0f, 0.00f, 0.001f, 1.0 },
1270 { "compressor-attack", qtr("Attack"), qtr("ms"), 1.5f, 400.0f, 25.00f, 0.100f, 1.0 },
1271 { "compressor-release", qtr("Release"), qtr("ms"), 2.0f, 800.0f, 100.00f, 0.100f, 1.0 },
1272 { "compressor-threshold", qtr("Threshold"), qtr("dB"), -30.0f, 0.0f, -11.00f, 0.010f, 1.0 },
1273 { "compressor-ratio", qtr("Ratio"), ":1", 1.0f, 20.0f, 8.00f, 0.010f, 1.0 },
1274 { "compressor-knee", qtr("Knee\nradius"), qtr("dB"), 1.0f, 10.0f, 2.50f, 0.010f, 1.0 },
1275 { "compressor-makeup-gain", qtr("Makeup\ngain"), qtr("dB"), 0.0f, 24.0f, 7.00f, 0.010f, 1.0 },
1277 for( int i=0; i<7 ;i++ ) controls.append( a[i] );
1278 build();
1281 /**********************************************************************
1282 * Spatializer
1283 **********************************************************************/
1285 Spatializer::Spatializer( intf_thread_t *p_intf, QWidget *parent )
1286 : AudioFilterControlWidget( p_intf, parent, "spatializer" )
1288 i_smallfont = -1;
1289 const FilterSliderData::slider_data_t a[5] =
1291 { "spatializer-roomsize", qtr("Size"), "", 0.0f, 1.1f, 0.85f, 0.1f, 10.0 },
1292 { "spatializer-width", qtr("Width"), "", 0.0f, 1.0f, 1.0f, 0.1f, 10.0 },
1293 { "spatializer-wet", qtr("Wet"), "", 0.0f, 1.0f, 0.4f, 0.1f, 10.0 },
1294 { "spatializer-dry", qtr("Dry"), "", 0.0f, 1.0f, 0.5f, 0.1f, 10.0 },
1295 { "spatializer-damp", qtr("Damp"), "", 0.0f, 1.0f, 0.5f, 0.1f, 10.0 },
1297 for( int i=0; i<5 ;i++ ) controls.append( a[i] );
1298 build();
1301 /**********************************************************************
1302 * Spatializer
1303 **********************************************************************/
1305 StereoWidener::StereoWidener( intf_thread_t *p_intf, QWidget *parent )
1306 : AudioFilterControlWidget( p_intf, parent, "stereo_widen" )
1308 i_smallfont = -1;
1309 const FilterSliderData::slider_data_t a[4] =
1311 { "stereowiden-delay", N_("Delay time"), "ms", 1.0, 100, 20, 1.0, 1.0 },
1312 { "stereowiden-feedback", N_("Feedback gain"), "%", 0.0, 0.9, 0.3, 0.1, 1.0 },
1313 { "stereowiden-crossfeed", N_("Crossfeed"), "%", 0.0, 0.8, 0.3, 0.1, 1.0 },
1314 { "stereowiden-dry-mix", N_("Dry mix"), "%", 0.0, 1.0, 0.8, 0.1, 1.0 },
1316 for( int i=0; i<4 ;i++ ) controls.append( a[i] );
1317 build();
1320 /**********************************************************************
1321 * Advanced
1322 **********************************************************************/
1324 PitchShifter::PitchShifter( intf_thread_t *p_intf, QWidget *parent )
1325 : AudioFilterControlWidget( p_intf, parent, "pitch", "scaletempo" )
1327 i_smallfont = -1;
1328 controls.append( { "pitch-shift", N_("Adjust pitch"), "semitones",
1329 -12.0, 12.0, 0.0, 0.25, 1.0 } );
1330 build();
1333 #include <QToolButton>
1334 #include <QGridLayout>
1336 #define SUBSDELAY_CFG_MODE "subsdelay-mode"
1337 #define SUBSDELAY_CFG_FACTOR "subsdelay-factor"
1338 #define SUBSDELAY_MODE_ABSOLUTE 0
1339 #define SUBSDELAY_MODE_RELATIVE_SOURCE_DELAY 1
1340 #define SUBSDELAY_MODE_RELATIVE_SOURCE_CONTENT 2
1342 SyncWidget::SyncWidget( QWidget *_parent ) : QWidget( _parent )
1344 QHBoxLayout *layout = new QHBoxLayout;
1345 spinBox.setAlignment( Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter );
1346 spinBox.setDecimals( 3 );
1347 spinBox.setMinimum( -600.0 );
1348 spinBox.setMaximum( 600.0 );
1349 spinBox.setSingleStep( 0.1 );
1350 spinBox.setSuffix( " s" );
1351 spinBox.setButtonSymbols( QDoubleSpinBox::PlusMinus );
1352 CONNECT( &spinBox, valueChanged( double ), this, valueChangedHandler( double ) );
1353 layout->addWidget( &spinBox );
1354 layout->addWidget( &spinLabel );
1355 layout->setContentsMargins( 0, 0, 0, 0 );
1356 setLayout( layout );
1359 void SyncWidget::valueChangedHandler( double d )
1361 if ( d < 0 )
1362 spinLabel.setText( qtr("(Hastened)") );
1363 else if ( d > 0 )
1364 spinLabel.setText( qtr("(Delayed)") );
1365 else
1366 spinLabel.setText( "" );
1367 emit valueChanged( d );
1370 void SyncWidget::setValue( double d )
1372 spinBox.setValue( d );
1375 SyncControls::SyncControls( intf_thread_t *_p_intf, QWidget *_parent ) :
1376 QWidget( _parent ) , p_intf( _p_intf )
1378 QGroupBox *AVBox, *subsBox;
1379 QToolButton *updateButton;
1381 b_userAction = true;
1383 QGridLayout *mainLayout = new QGridLayout( this );
1385 /* AV sync */
1386 AVBox = new QGroupBox( qtr( "Audio/Video" ) );
1387 QGridLayout *AVLayout = new QGridLayout( AVBox );
1389 QLabel *AVLabel = new QLabel;
1390 AVLabel->setText( qtr( "Audio track synchronization:" ) );
1391 AVLayout->addWidget( AVLabel, 0, 0, 1, 1 );
1393 AVSpin = new SyncWidget( this );
1394 AVLayout->addWidget( AVSpin, 0, 2, 1, 1 );
1395 mainLayout->addWidget( AVBox, 1, 0, 1, 5 );
1397 /* Subs */
1398 subsBox = new QGroupBox( qtr( "Subtitles/Video" ) );
1399 QGridLayout *subsLayout = new QGridLayout( subsBox );
1401 QLabel *subsLabel = new QLabel;
1402 subsLabel->setText( qtr( "Subtitle track synchronization:" ) );
1403 subsLayout->addWidget( subsLabel, 0, 0, 1, 1 );
1405 subsSpin = new SyncWidget( this );
1406 subsLayout->addWidget( subsSpin, 0, 2, 1, 1 );
1408 QLabel *subSpeedLabel = new QLabel;
1409 subSpeedLabel->setText( qtr( "Subtitle speed:" ) );
1410 subsLayout->addWidget( subSpeedLabel, 1, 0, 1, 1 );
1412 subSpeedSpin = new QDoubleSpinBox;
1413 subSpeedSpin->setAlignment( Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter );
1414 subSpeedSpin->setDecimals( 3 );
1415 subSpeedSpin->setMinimum( 1 );
1416 subSpeedSpin->setMaximum( 100 );
1417 subSpeedSpin->setSingleStep( 0.2 );
1418 subSpeedSpin->setSuffix( " fps" );
1419 subSpeedSpin->setButtonSymbols( QDoubleSpinBox::PlusMinus );
1420 subsLayout->addWidget( subSpeedSpin, 1, 2, 1, 1 );
1422 QLabel *subDurationLabel = new QLabel;
1423 subDurationLabel->setText( qtr( "Subtitle duration factor:" ) );
1424 subsLayout->addWidget( subDurationLabel, 2, 0, 1, 1 );
1426 subDurationSpin = new QDoubleSpinBox;
1427 subDurationSpin->setAlignment( Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter );
1428 subDurationSpin->setDecimals( 3 );
1429 subDurationSpin->setMinimum( 0 );
1430 subDurationSpin->setMaximum( 20 );
1431 subDurationSpin->setSingleStep( 0.2 );
1432 subDurationSpin->setButtonSymbols( QDoubleSpinBox::PlusMinus );
1433 subsLayout->addWidget( subDurationSpin, 2, 2, 1, 1 );
1435 mainLayout->addWidget( subsBox, 2, 0, 2, 5 );
1437 updateButton = new QToolButton;
1438 updateButton->setAutoRaise( true );
1439 mainLayout->addWidget( updateButton, 0, 4, 1, 1 );
1441 /* Various Connects */
1442 CONNECT( AVSpin, valueChanged ( double ), this, advanceAudio( double ) ) ;
1443 CONNECT( subsSpin, valueChanged ( double ), this, advanceSubs( double ) ) ;
1444 CONNECT( subSpeedSpin, valueChanged ( double ),
1445 this, adjustSubsSpeed( double ) );
1446 CONNECT( subDurationSpin, valueChanged ( double ),
1447 this, adjustSubsDuration( double ) );
1449 CONNECT( THEMIM->getIM(), synchroChanged(), this, update() );
1450 BUTTON_SET_ACT_I( updateButton, "", update,
1451 qtr( "Force update of this dialog's values" ), update() );
1453 initSubsDuration();
1455 /* Set it */
1456 update();
1459 SyncControls::~SyncControls()
1461 subsdelayClean();
1464 void SyncControls::clean()
1466 b_userAction = false;
1467 AVSpin->setValue( 0.0 );
1468 subsSpin->setValue( 0.0 );
1469 subSpeedSpin->setValue( 1.0 );
1470 subsdelayClean();
1471 b_userAction = true;
1474 void SyncControls::update()
1476 b_userAction = false;
1478 int64_t i_delay;
1479 if( THEMIM->getInput() )
1481 i_delay = var_GetInteger( THEMIM->getInput(), "audio-delay" );
1482 AVSpin->setValue( ( (double)i_delay ) / CLOCK_FREQ );
1483 i_delay = var_GetInteger( THEMIM->getInput(), "spu-delay" );
1484 subsSpin->setValue( ( (double)i_delay ) / CLOCK_FREQ );
1485 subSpeedSpin->setValue( var_GetFloat( THEMIM->getInput(), "sub-fps" ) );
1486 subDurationSpin->setValue( var_InheritFloat( p_intf, SUBSDELAY_CFG_FACTOR ) );
1488 b_userAction = true;
1491 void SyncControls::advanceAudio( double f_advance )
1493 if( THEMIM->getInput() && b_userAction )
1495 int64_t i_delay = f_advance * CLOCK_FREQ;
1496 var_SetInteger( THEMIM->getInput(), "audio-delay", i_delay );
1500 void SyncControls::advanceSubs( double f_advance )
1502 if( THEMIM->getInput() && b_userAction )
1504 int64_t i_delay = f_advance * CLOCK_FREQ;
1505 var_SetInteger( THEMIM->getInput(), "spu-delay", i_delay );
1509 void SyncControls::adjustSubsSpeed( double f_fps )
1511 if( THEMIM->getInput() && b_userAction )
1513 var_SetFloat( THEMIM->getInput(), "sub-fps", f_fps );
1517 void SyncControls::adjustSubsDuration( double f_factor )
1519 if( THEMIM->getInput() && b_userAction )
1521 subsdelaySetFactor( f_factor );
1522 changeVFiltersString( "subsdelay", f_factor > 0 );
1526 void SyncControls::initSubsDuration()
1528 int i_mode = var_InheritInteger( p_intf, SUBSDELAY_CFG_MODE );
1530 switch (i_mode)
1532 default:
1533 case SUBSDELAY_MODE_ABSOLUTE:
1534 subDurationSpin->setToolTip( qtr( "Extend subtitle duration by this value.\n"
1535 "Set 0 to disable." ) );
1536 subDurationSpin->setSuffix( " s" );
1537 break;
1538 case SUBSDELAY_MODE_RELATIVE_SOURCE_DELAY:
1539 subDurationSpin->setToolTip( qtr( "Multiply subtitle duration by this value.\n"
1540 "Set 0 to disable." ) );
1541 subDurationSpin->setSuffix( "" );
1542 break;
1543 case SUBSDELAY_MODE_RELATIVE_SOURCE_CONTENT:
1544 subDurationSpin->setToolTip( qtr( "Recalculate subtitle duration according\n"
1545 "to their content and this value.\n"
1546 "Set 0 to disable." ) );
1547 subDurationSpin->setSuffix( "" );
1548 break;
1552 void SyncControls::subsdelayClean()
1554 /* Remove subsdelay filter */
1555 changeVFiltersString( "subsdelay", false );
1558 void SyncControls::subsdelaySetFactor( double f_factor )
1560 QVector<vout_thread_t*> p_vouts = THEMIM->getVouts();
1561 foreach( vout_thread_t *p_vout, p_vouts )
1563 var_SetFloat( p_vout, SUBSDELAY_CFG_FACTOR, f_factor );
1564 vlc_object_release( p_vout );
1568 void SyncControls::changeVFiltersString( const char *psz_name, bool b_add )
1570 const char *psz_filter_type = GetVFilterType( p_intf, psz_name );
1571 if( psz_filter_type == NULL )
1572 return;
1574 QString result = ChangeFiltersString( p_intf, psz_filter_type, psz_name, b_add );
1576 UpdateVFiltersString( p_intf, psz_filter_type, qtu( result ) );
1580 /**********************************************************************
1581 * Video filters / Adjust
1582 **********************************************************************/
1584 /**********************************************************************
1585 * Extended playbak controls
1586 **********************************************************************/