1 /*****************************************************************************
2 * extended_panels.cpp : Extended controls panels
3 ****************************************************************************
4 * Copyright (C) 2006-2008 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Antoine Cellerier <dionoea .t videolan d@t org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * ( at your option ) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #define __STDC_FORMAT_MACROS 1
35 #include <QGridLayout>
36 #include <QSignalMapper>
39 #include <QFileDialog>
41 #include "components/extended_panels.hpp"
42 #include "dialogs/preferences.hpp"
44 #include "input_manager.hpp"
45 #include "util/qt_dirs.hpp"
47 #include "../../audio_filter/equalizer_presets.h"
49 #include <vlc_intf_strings.h>
52 #include <vlc_modules.h>
54 #include <vlc_charset.h> /* us_strtod */
56 static void ChangeVFiltersString( struct intf_thread_t
*p_intf
, const char *psz_name
, bool b_add
);
59 class ConfClickHandler
: public QObject
62 ConfClickHandler( intf_thread_t
*_p_intf
, ExtVideo
*_e
) : QObject ( _e
) {
63 e
= _e
; p_intf
= _p_intf
;
65 virtual ~ConfClickHandler() {}
66 bool eventFilter( QObject
*obj
, QEvent
*evt
)
68 if( evt
->type() == QEvent::MouseButtonPress
)
77 intf_thread_t
*p_intf
;
81 const QString
ModuleFromWidgetName( QObject
*obj
)
83 return obj
->objectName().replace( "Enable","" );
86 QString
OptionFromWidgetName( QObject
*obj
)
89 QString option
= obj
->objectName().replace( "Slider", "" )
90 .replace( "Combo" , "" )
91 .replace( "Dial" , "" )
92 .replace( "Check" , "" )
93 .replace( "Spin" , "" )
94 .replace( "Text" , "" );
95 for( char a
= 'A'; a
<= 'Z'; a
++ )
97 option
= option
.replace( QString( a
),
98 QString( '-' ) + QString( a
+ 'a' - 'A' ) );
103 ExtVideo::ExtVideo( intf_thread_t
*_p_intf
, QTabWidget
*_parent
) :
104 QObject( _parent
), p_intf( _p_intf
)
106 ui
.setupUi( _parent
);
108 #define SETUP_VFILTER( widget ) \
110 vlc_object_t *p_obj = ( vlc_object_t * ) \
111 vlc_object_find_name( p_intf->p_libvlc, \
114 QCheckBox *checkbox = qobject_cast<QCheckBox*>( ui.widget##Enable ); \
115 QGroupBox *groupbox = qobject_cast<QGroupBox*>( ui.widget##Enable ); \
118 vlc_object_release( p_obj ); \
119 if( checkbox ) checkbox->setChecked( true ); \
120 else groupbox->setChecked( true ); \
124 if( checkbox ) checkbox->setChecked( false ); \
125 else groupbox->setChecked( false ); \
128 CONNECT( ui.widget##Enable, clicked(), this, updateFilters() );
129 #define SETUP_VFILTER_OPTION( widget, signal ) \
130 initComboBoxItems( ui.widget ); \
131 setWidgetValue( ui.widget ); \
132 CONNECT( ui.widget, signal, this, updateFilterOptions() );
134 SETUP_VFILTER( adjust
)
135 SETUP_VFILTER_OPTION( hueSlider
, valueChanged( int ) )
136 SETUP_VFILTER_OPTION( contrastSlider
, valueChanged( int ) )
137 SETUP_VFILTER_OPTION( brightnessSlider
, valueChanged( int ) )
138 SETUP_VFILTER_OPTION( saturationSlider
, valueChanged( int ) )
139 SETUP_VFILTER_OPTION( gammaSlider
, valueChanged( int ) )
140 SETUP_VFILTER_OPTION( brightnessThresholdCheck
, stateChanged( int ) )
142 SETUP_VFILTER( extract
)
143 SETUP_VFILTER_OPTION( extractComponentText
, textChanged( const QString
& ) )
145 SETUP_VFILTER( posterize
)
146 SETUP_VFILTER_OPTION( posterizeLevelSpin
, valueChanged( int ) )
148 SETUP_VFILTER( colorthres
)
149 SETUP_VFILTER_OPTION( colorthresColorText
, textChanged( const QString
& ) )
150 SETUP_VFILTER_OPTION( colorthresSaturationthresSlider
, valueChanged( int ) )
151 SETUP_VFILTER_OPTION( colorthresSimilaritythresSlider
, valueChanged( int ) )
153 SETUP_VFILTER( sepia
)
154 SETUP_VFILTER_OPTION( sepiaIntensitySpin
, valueChanged( int ) )
156 SETUP_VFILTER( invert
)
158 SETUP_VFILTER( gradient
)
159 SETUP_VFILTER_OPTION( gradientModeCombo
, currentIndexChanged( QString
) )
160 SETUP_VFILTER_OPTION( gradientTypeCheck
, stateChanged( int ) )
161 SETUP_VFILTER_OPTION( gradientCartoonCheck
, stateChanged( int ) )
163 SETUP_VFILTER( motionblur
)
164 SETUP_VFILTER_OPTION( blurFactorSlider
, valueChanged( int ) )
166 SETUP_VFILTER( motiondetect
)
168 // SETUP_VFILTER( noise )
170 SETUP_VFILTER( psychedelic
)
172 SETUP_VFILTER( sharpen
)
173 SETUP_VFILTER_OPTION( sharpenSigmaSlider
, valueChanged( int ) )
175 SETUP_VFILTER( ripple
)
177 SETUP_VFILTER( wave
)
179 SETUP_VFILTER( transform
)
180 SETUP_VFILTER_OPTION( transformTypeCombo
, currentIndexChanged( QString
) )
182 SETUP_VFILTER( rotate
)
183 SETUP_VFILTER_OPTION( rotateAngleDial
, valueChanged( int ) )
184 ui
.rotateAngleDial
->setWrapping( true );
185 ui
.rotateAngleDial
->setNotchesVisible( true );
187 SETUP_VFILTER( puzzle
)
188 SETUP_VFILTER_OPTION( puzzleRowsSpin
, valueChanged( int ) )
189 SETUP_VFILTER_OPTION( puzzleColsSpin
, valueChanged( int ) )
190 SETUP_VFILTER_OPTION( puzzleBlackSlotCheck
, stateChanged( int ) )
192 SETUP_VFILTER( magnify
)
194 SETUP_VFILTER( clone
)
195 SETUP_VFILTER_OPTION( cloneCountSpin
, valueChanged( int ) )
197 SETUP_VFILTER( wall
)
198 SETUP_VFILTER_OPTION( wallRowsSpin
, valueChanged( int ) )
199 SETUP_VFILTER_OPTION( wallColsSpin
, valueChanged( int ) )
201 SETUP_VFILTER( panoramix
)
202 SETUP_VFILTER_OPTION( panoramixRowsSpin
, valueChanged( int ) )
203 SETUP_VFILTER_OPTION( panoramixColsSpin
, valueChanged( int ) )
206 SETUP_VFILTER( erase
)
207 SETUP_VFILTER_OPTION( eraseMaskText
, editingFinished() )
208 SETUP_VFILTER_OPTION( eraseYSpin
, valueChanged( int ) )
209 SETUP_VFILTER_OPTION( eraseXSpin
, valueChanged( int ) )
210 BUTTONACT( ui
.eraseBrowseBtn
, browseEraseFile() );
212 SETUP_VFILTER( marq
)
213 SETUP_VFILTER_OPTION( marqMarqueeText
, textChanged( const QString
& ) )
214 SETUP_VFILTER_OPTION( marqPositionCombo
, currentIndexChanged( QString
) )
216 SETUP_VFILTER( logo
)
217 SETUP_VFILTER_OPTION( logoFileText
, editingFinished() )
218 SETUP_VFILTER_OPTION( logoYSpin
, valueChanged( int ) )
219 SETUP_VFILTER_OPTION( logoXSpin
, valueChanged( int ) )
220 SETUP_VFILTER_OPTION( logoOpacitySlider
, valueChanged( int ) )
221 BUTTONACT( ui
.logoBrowseBtn
, browseLogo() );
223 SETUP_VFILTER( gradfun
)
224 SETUP_VFILTER_OPTION( gradfunRadiusSlider
, valueChanged( int ) )
226 SETUP_VFILTER( grain
)
227 SETUP_VFILTER_OPTION( grainVarianceSlider
, valueChanged( int ) )
229 if( module_exists( "atmo" ) )
231 SETUP_VFILTER( atmo
)
232 SETUP_VFILTER_OPTION( atmoEdgeweightningSlider
, valueChanged( int ) )
233 SETUP_VFILTER_OPTION( atmoBrightnessSlider
, valueChanged( int ) )
234 SETUP_VFILTER_OPTION( atmoDarknesslimitSlider
, valueChanged( int ) )
235 SETUP_VFILTER_OPTION( atmoMeanlengthSlider
, valueChanged( int ) )
236 SETUP_VFILTER_OPTION( atmoMeanthresholdSlider
, valueChanged( int ) )
237 SETUP_VFILTER_OPTION( atmoPercentnewSlider
, valueChanged( int ) )
238 SETUP_VFILTER_OPTION( atmoFiltermodeCombo
, currentIndexChanged( int ) )
239 SETUP_VFILTER_OPTION( atmoShowdotsCheck
, stateChanged( int ) )
243 _parent
->removeTab( _parent
->indexOf( ui
.tab_atmo
) );
247 #undef SETUP_VFILTER_OPTION
249 CONNECT( ui
.cropTopPx
, valueChanged( int ), this, cropChange() );
250 CONNECT( ui
.cropBotPx
, valueChanged( int ), this, cropChange() );
251 CONNECT( ui
.cropLeftPx
, valueChanged( int ), this, cropChange() );
252 CONNECT( ui
.cropRightPx
, valueChanged( int ), this, cropChange() );
253 CONNECT( ui
.leftRightCropSync
, toggled ( bool ), this, cropChange() );
254 CONNECT( ui
.topBotCropSync
, toggled ( bool ), this, cropChange() );
255 CONNECT( ui
.topBotCropSync
, toggled( bool ),
256 ui
.cropBotPx
, setDisabled( bool ) );
257 CONNECT( ui
.leftRightCropSync
, toggled( bool ),
258 ui
.cropRightPx
, setDisabled( bool ) );
261 void ExtVideo::cropChange()
263 if( ui
.topBotCropSync
->isChecked() )
264 ui
.cropBotPx
->setValue( ui
.cropTopPx
->value() );
265 if( ui
.leftRightCropSync
->isChecked() )
266 ui
.cropRightPx
->setValue( ui
.cropLeftPx
->value() );
268 vout_thread_t
*p_vout
= THEMIM
->getVout();
271 var_SetInteger( p_vout
, "crop-top", ui
.cropTopPx
->value() );
272 var_SetInteger( p_vout
, "crop-bottom", ui
.cropBotPx
->value() );
273 var_SetInteger( p_vout
, "crop-left", ui
.cropLeftPx
->value() );
274 var_SetInteger( p_vout
, "crop-right", ui
.cropRightPx
->value() );
275 vlc_object_release( p_vout
);
279 void ExtVideo::clean()
281 ui
.cropTopPx
->setValue( 0 );
282 ui
.cropBotPx
->setValue( 0 );
283 ui
.cropLeftPx
->setValue( 0 );
284 ui
.cropRightPx
->setValue( 0 );
287 static void ChangeVFiltersString( struct intf_thread_t
*p_intf
, const char *psz_name
, bool b_add
)
289 char *psz_parser
, *psz_string
;
290 const char *psz_filter_type
;
292 module_t
*p_obj
= module_find( psz_name
);
295 msg_Err( p_intf
, "Unable to find filter module \"%s\".", psz_name
);
299 if( module_provides( p_obj
, "video splitter" ) )
301 psz_filter_type
= "video-splitter";
303 else if( module_provides( p_obj
, "video filter2" ) )
305 psz_filter_type
= "video-filter";
307 else if( module_provides( p_obj
, "sub source" ) )
309 psz_filter_type
= "sub-source";
311 else if( module_provides( p_obj
, "sub filter" ) )
313 psz_filter_type
= "sub-filter";
317 module_release (p_obj
);
318 msg_Err( p_intf
, "Unknown video filter type." );
321 module_release (p_obj
);
323 psz_string
= config_GetPsz( p_intf
, psz_filter_type
);
325 if( !psz_string
) psz_string
= strdup( "" );
327 psz_parser
= strstr( psz_string
, psz_name
);
333 psz_parser
= psz_string
;
334 if( asprintf( &psz_string
, ( *psz_string
) ? "%s:%s" : "%s%s",
335 psz_string
, psz_name
) == -1 )
351 if( *( psz_parser
+ strlen( psz_name
) ) == ':' )
353 memmove( psz_parser
, psz_parser
+ strlen( psz_name
) + 1,
354 strlen( psz_parser
+ strlen( psz_name
) + 1 ) + 1 );
361 /* Remove trailing : : */
362 if( strlen( psz_string
) > 0 &&
363 *( psz_string
+ strlen( psz_string
) -1 ) == ':' )
365 *( psz_string
+ strlen( psz_string
) -1 ) = '\0';
374 /* Vout is not kept, so put that in the config */
375 config_PutPsz( p_intf
, psz_filter_type
, psz_string
);
377 /* Try to set on the fly */
378 if( !strcmp( psz_filter_type
, "video-splitter" ) )
380 playlist_t
*p_playlist
= pl_Get( p_intf
);
381 var_SetString( p_playlist
, psz_filter_type
, psz_string
);
385 vout_thread_t
*p_vout
= THEMIM
->getVout();
388 var_SetString( p_vout
, psz_filter_type
, psz_string
);
389 vlc_object_release( p_vout
);
396 void ExtVideo::updateFilters()
398 QString module
= ModuleFromWidgetName( sender() );
400 QCheckBox
*checkbox
= qobject_cast
<QCheckBox
*>( sender() );
401 QGroupBox
*groupbox
= qobject_cast
<QGroupBox
*>( sender() );
403 ChangeVFiltersString( p_intf
, qtu( module
),
404 checkbox
? checkbox
->isChecked()
405 : groupbox
->isChecked() );
408 void ExtVideo::browseLogo()
410 QString file
= QFileDialog::getOpenFileName( NULL
, qtr( "Logo filenames" ),
411 p_intf
->p_sys
->filepath
, "Images (*.png *.jpg);;All (*)" );
412 ui
.logoFileText
->setText( toNativeSeparators( file
) );
415 void ExtVideo::browseEraseFile()
417 QString file
= QFileDialog::getOpenFileName( NULL
, qtr( "Image mask" ),
418 p_intf
->p_sys
->filepath
, "Images (*.png *.jpg);;All (*)" );
419 ui
.eraseMaskText
->setText( toNativeSeparators( file
) );
422 void ExtVideo::initComboBoxItems( QObject
*widget
)
424 QComboBox
*combobox
= qobject_cast
<QComboBox
*>( widget
);
425 if( !combobox
) return;
427 QString option
= OptionFromWidgetName( widget
);
428 module_config_t
*p_item
= config_FindConfig( VLC_OBJECT( p_intf
),
432 int i_type
= p_item
->i_type
& CONFIG_ITEM
;
433 for( int i_index
= 0; i_index
< p_item
->i_list
; i_index
++ )
435 if( i_type
== CONFIG_ITEM_INTEGER
436 || i_type
== CONFIG_ITEM_BOOL
)
437 combobox
->addItem( qtr( p_item
->ppsz_list_text
[i_index
] ),
438 p_item
->pi_list
[i_index
] );
439 else if( i_type
== CONFIG_ITEM_STRING
)
440 combobox
->addItem( qtr( p_item
->ppsz_list_text
[i_index
] ),
441 p_item
->ppsz_list
[i_index
] );
446 msg_Err( p_intf
, "Couldn't find option \"%s\".",
451 void ExtVideo::setWidgetValue( QObject
*widget
)
453 QString module
= ModuleFromWidgetName( widget
->parent() );
454 //std::cout << "Module name: " << module.toStdString() << std::endl;
455 QString option
= OptionFromWidgetName( widget
);
456 //std::cout << "Option name: " << option.toStdString() << std::endl;
458 vlc_object_t
*p_obj
= ( vlc_object_t
* )
459 vlc_object_find_name( p_intf
->p_libvlc
,
469 "Module instance %s not found, looking in config values.",
472 i_type
= config_GetType( p_intf
, qtu( option
) ) & VLC_VAR_CLASS
;
475 case VLC_VAR_INTEGER
:
477 val
.i_int
= config_GetInt( p_intf
, qtu( option
) );
480 val
.f_float
= config_GetFloat( p_intf
, qtu( option
) );
483 val
.psz_string
= config_GetPsz( p_intf
, qtu( option
) );
489 i_type
= var_Type( p_obj
, qtu( option
) ) & VLC_VAR_CLASS
;
490 var_Get( p_obj
, qtu( option
), &val
);
491 vlc_object_release( p_obj
);
494 /* Try to cast to all the widgets we're likely to encounter. Only
495 * one of the casts is expected to work. */
496 QSlider
*slider
= qobject_cast
<QSlider
*> ( widget
);
497 QCheckBox
*checkbox
= qobject_cast
<QCheckBox
*> ( widget
);
498 QSpinBox
*spinbox
= qobject_cast
<QSpinBox
*> ( widget
);
499 QDoubleSpinBox
*doublespinbox
= qobject_cast
<QDoubleSpinBox
*>( widget
);
500 QDial
*dial
= qobject_cast
<QDial
*> ( widget
);
501 QLineEdit
*lineedit
= qobject_cast
<QLineEdit
*> ( widget
);
502 QComboBox
*combobox
= qobject_cast
<QComboBox
*> ( widget
);
504 if( i_type
== VLC_VAR_INTEGER
|| i_type
== VLC_VAR_BOOL
)
506 if( slider
) slider
->setValue( val
.i_int
);
507 else if( checkbox
) checkbox
->setCheckState( val
.i_int
? Qt::Checked
509 else if( spinbox
) spinbox
->setValue( val
.i_int
);
510 else if( dial
) dial
->setValue( ( 540-val
.i_int
)%360 );
514 snprintf( str
, sizeof(str
), "%06"PRIX64
, val
.i_int
);
515 lineedit
->setText( str
);
517 else if( combobox
) combobox
->setCurrentIndex(
518 combobox
->findData( qlonglong(val
.i_int
) ) );
519 else msg_Warn( p_intf
, "Oops %s %s %d", __FILE__
, __func__
, __LINE__
);
521 else if( i_type
== VLC_VAR_FLOAT
)
523 if( slider
) slider
->setValue( ( int )( val
.f_float
*( double )slider
->tickInterval() ) ); /* hack alert! */
524 else if( doublespinbox
) doublespinbox
->setValue( val
.f_float
);
525 else msg_Warn( p_intf
, "Oops %s %s %d", __FILE__
, __func__
, __LINE__
);
527 else if( i_type
== VLC_VAR_STRING
)
529 if( lineedit
) lineedit
->setText( qfu( val
.psz_string
) );
530 else if( combobox
) combobox
->setCurrentIndex(
531 combobox
->findData( qfu( val
.psz_string
) ) );
532 else msg_Warn( p_intf
, "Oops %s %s %d", __FILE__
, __func__
, __LINE__
);
533 free( val
.psz_string
);
538 "Module %s's %s variable is of an unsupported type ( %d )",
544 void ExtVideo::updateFilterOptions()
546 QString module
= ModuleFromWidgetName( sender()->parent() );
547 //std::cout << "Module name: " << module.toStdString() << std::endl;
548 QString option
= OptionFromWidgetName( sender() );
549 //std::cout << "Option name: " << option.toStdString() << std::endl;
551 vlc_object_t
*p_obj
= ( vlc_object_t
* )
552 vlc_object_find_name( p_intf
->p_libvlc
,
559 msg_Warn( p_intf
, "Module %s not found. You'll need to restart the filter to take the change into account.", qtu( module
) );
560 i_type
= config_GetType( p_intf
, qtu( option
) );
561 b_is_command
= false;
565 i_type
= var_Type( p_obj
, qtu( option
) );
567 i_type
= config_GetType( p_intf
, qtu( option
) );
568 b_is_command
= ( i_type
& VLC_VAR_ISCOMMAND
);
573 msg_Warn( p_intf
, "Module %s's %s variable isn't a command. You'll need to restart the filter to take change into account.",
576 /* FIXME: restart automatically somewhere near the end of this function */
579 /* Try to cast to all the widgets we're likely to encounter. Only
580 * one of the casts is expected to work. */
581 QSlider
*slider
= qobject_cast
<QSlider
*> ( sender() );
582 QCheckBox
*checkbox
= qobject_cast
<QCheckBox
*> ( sender() );
583 QSpinBox
*spinbox
= qobject_cast
<QSpinBox
*> ( sender() );
584 QDoubleSpinBox
*doublespinbox
= qobject_cast
<QDoubleSpinBox
*>( sender() );
585 QDial
*dial
= qobject_cast
<QDial
*> ( sender() );
586 QLineEdit
*lineedit
= qobject_cast
<QLineEdit
*> ( sender() );
587 QComboBox
*combobox
= qobject_cast
<QComboBox
*> ( sender() );
589 i_type
&= VLC_VAR_CLASS
;
590 if( i_type
== VLC_VAR_INTEGER
|| i_type
== VLC_VAR_BOOL
)
593 if( slider
) i_int
= slider
->value();
594 else if( checkbox
) i_int
= checkbox
->checkState() == Qt::Checked
;
595 else if( spinbox
) i_int
= spinbox
->value();
596 else if( dial
) i_int
= ( 540-dial
->value() )%360;
597 else if( lineedit
) i_int
= lineedit
->text().toInt( NULL
,16 );
598 else if( combobox
) i_int
= combobox
->itemData( combobox
->currentIndex() ).toInt();
599 else msg_Warn( p_intf
, "Oops %s %s %d", __FILE__
, __func__
, __LINE__
);
600 config_PutInt( p_intf
, qtu( option
), i_int
);
603 if( i_type
== VLC_VAR_INTEGER
)
604 var_SetInteger( p_obj
, qtu( option
), i_int
);
606 var_SetBool( p_obj
, qtu( option
), i_int
);
609 else if( i_type
== VLC_VAR_FLOAT
)
612 if( slider
) f_float
= ( double )slider
->value()
613 / ( double )slider
->tickInterval(); /* hack alert! */
614 else if( doublespinbox
) f_float
= doublespinbox
->value();
615 else if( lineedit
) f_float
= lineedit
->text().toDouble();
616 else msg_Warn( p_intf
, "Oops %s %s %d", __FILE__
, __func__
, __LINE__
);
617 config_PutFloat( p_intf
, qtu( option
), f_float
);
619 var_SetFloat( p_obj
, qtu( option
), f_float
);
621 else if( i_type
== VLC_VAR_STRING
)
623 char *psz_string
= NULL
;
624 if( lineedit
) psz_string
= strdup( qtu( lineedit
->text() ) );
625 else if( combobox
) psz_string
= strdup( qtu( combobox
->itemData(
626 combobox
->currentIndex() ).toString() ) );
627 else msg_Warn( p_intf
, "Oops %s %s %d", __FILE__
, __func__
, __LINE__
);
628 config_PutPsz( p_intf
, qtu( option
), psz_string
);
630 var_SetString( p_obj
, qtu( option
), psz_string
);
635 "Module %s's %s variable is of an unsupported type ( %d )",
640 if( p_obj
) vlc_object_release( p_obj
);
644 void ExtVideo::gotoConf( QObject
* src
)
646 #define SHOWCONF( module ) \
647 if( src->objectName().contains( module ) ) \
649 PrefsDialog::getInstance( p_intf )->showModulePrefs( module ); \
653 SHOWCONF( "magnify" );
655 SHOWCONF( "ripple" );
656 SHOWCONF( "invert" );
657 SHOWCONF( "puzzle" );
659 SHOWCONF( "gradient" );
660 SHOWCONF( "colorthres" )
664 /**********************************************************************
666 **********************************************************************/
668 ExtV4l2::ExtV4l2( intf_thread_t
*_p_intf
, QWidget
*_parent
)
669 : QWidget( _parent
), p_intf( _p_intf
), box( NULL
)
671 QVBoxLayout
*layout
= new QVBoxLayout( this );
672 help
= new QLabel( qtr("No v4l2 instance found.\n"
673 "Please check that the device has been opened with VLC and is playing.\n\n"
674 "Controls will automatically appear here.")
676 help
->setAlignment( Qt::AlignHCenter
| Qt::AlignVCenter
);
677 layout
->addWidget( help
);
681 void ExtV4l2::showEvent( QShowEvent
*event
)
683 QWidget::showEvent( event
);
687 void ExtV4l2::Refresh( void )
689 vlc_object_t
*p_obj
= (vlc_object_t
*)vlc_object_find_name( p_intf
, "v4l2", FIND_ANYWHERE
);
693 layout()->removeWidget( box
);
699 vlc_value_t val
, text
, name
;
700 int i_ret
= var_Change( p_obj
, "controls", VLC_VAR_GETCHOICES
,
704 msg_Err( p_intf
, "Oops, v4l2 object doesn't have a 'controls' variable." );
706 vlc_object_release( p_obj
);
710 box
= new QGroupBox( this );
711 layout()->addWidget( box
);
712 QVBoxLayout
*layout
= new QVBoxLayout( box
);
713 box
->setLayout( layout
);
715 for( int i
= 0; i
< val
.p_list
->i_count
; i
++ )
717 const char *psz_var
= text
.p_list
->p_values
[i
].psz_string
;
718 var_Change( p_obj
, psz_var
, VLC_VAR_GETTEXT
, &name
, NULL
);
719 const char *psz_label
= name
.psz_string
;
720 msg_Dbg( p_intf
, "v4l2 control \"%"PRIx64
"\": %s (%s)",
721 val
.p_list
->p_values
[i
].i_int
, psz_var
, name
.psz_string
);
723 int i_type
= var_Type( p_obj
, psz_var
);
724 switch( i_type
& VLC_VAR_TYPE
)
726 case VLC_VAR_INTEGER
:
728 QLabel
*label
= new QLabel( qtr( psz_label
), box
);
729 QHBoxLayout
*hlayout
= new QHBoxLayout();
730 hlayout
->addWidget( label
);
731 int i_val
= var_GetInteger( p_obj
, psz_var
);
732 if( i_type
& VLC_VAR_HASCHOICE
)
734 QComboBox
*combobox
= new QComboBox( box
);
735 combobox
->setObjectName( qtr( psz_var
) );
737 vlc_value_t val2
, text2
;
738 var_Change( p_obj
, psz_var
, VLC_VAR_GETCHOICES
,
740 for( int j
= 0; j
< val2
.p_list
->i_count
; j
++ )
743 text2
.p_list
->p_values
[j
].psz_string
,
744 qlonglong( val2
.p_list
->p_values
[j
].i_int
) );
745 if( i_val
== val2
.p_list
->p_values
[j
].i_int
)
746 combobox
->setCurrentIndex( j
);
748 var_FreeList( &val2
, &text2
);
750 CONNECT( combobox
, currentIndexChanged( int ), this,
751 ValueChange( int ) );
752 hlayout
->addWidget( combobox
);
756 QSlider
*slider
= new QSlider( box
);
757 slider
->setObjectName( qtr( psz_var
) );
758 slider
->setOrientation( Qt::Horizontal
);
760 var_Change( p_obj
, psz_var
, VLC_VAR_GETMIN
,
762 slider
->setMinimum( val2
.i_int
);
763 var_Change( p_obj
, psz_var
, VLC_VAR_GETMAX
,
765 slider
->setMaximum( val2
.i_int
);
766 var_Change( p_obj
, psz_var
, VLC_VAR_GETSTEP
,
768 slider
->setSingleStep( val2
.i_int
);
769 slider
->setValue( i_val
);
771 CONNECT( slider
, valueChanged( int ), this,
772 ValueChange( int ) );
773 hlayout
->addWidget( slider
);
775 layout
->addLayout( hlayout
);
780 QCheckBox
*button
= new QCheckBox( qtr( psz_label
), box
);
781 button
->setObjectName( qtr( psz_var
) );
782 button
->setChecked( var_GetBool( p_obj
, psz_var
) );
784 CONNECT( button
, clicked( bool ), this,
785 ValueChange( bool ) );
786 layout
->addWidget( button
);
791 if( i_type
& VLC_VAR_ISCOMMAND
)
793 QPushButton
*button
= new QPushButton( qtr( psz_label
), box
);
794 button
->setObjectName( qtr( psz_var
) );
796 CONNECT( button
, clicked( bool ), this,
797 ValueChange( bool ) );
798 layout
->addWidget( button
);
802 QLabel
*label
= new QLabel( qtr( psz_label
), box
);
803 layout
->addWidget( label
);
808 msg_Warn( p_intf
, "Unhandled var type for %s", psz_var
);
811 free( name
.psz_string
);
813 var_FreeList( &val
, &text
);
814 vlc_object_release( p_obj
);
818 msg_Dbg( p_intf
, "Couldn't find v4l2 instance" );
821 QTimer::singleShot( 2000, this, SLOT(Refresh()) );
825 void ExtV4l2::ValueChange( bool value
)
827 ValueChange( (int)value
);
830 void ExtV4l2::ValueChange( int value
)
832 QObject
*s
= sender();
833 vlc_object_t
*p_obj
= (vlc_object_t
*)vlc_object_find_name( p_intf
, "v4l2", FIND_ANYWHERE
);
836 char *psz_var
= strdup( qtu( s
->objectName() ) );
837 int i_type
= var_Type( p_obj
, psz_var
);
838 switch( i_type
& VLC_VAR_TYPE
)
840 case VLC_VAR_INTEGER
:
841 if( i_type
& VLC_VAR_HASCHOICE
)
843 QComboBox
*combobox
= qobject_cast
<QComboBox
*>( s
);
844 value
= combobox
->itemData( value
).toInt();
846 var_SetInteger( p_obj
, psz_var
, value
);
849 var_SetBool( p_obj
, psz_var
, value
);
852 var_TriggerCallback( p_obj
, psz_var
);
856 vlc_object_release( p_obj
);
860 msg_Warn( p_intf
, "Oops, v4l2 object isn't available anymore" );
865 /**********************************************************************
867 **********************************************************************/
869 static const QString band_frequencies
[] =
871 " 60 Hz ", " 170 Hz ", " 310 Hz ", " 600 Hz ", " 1 kHz ",
872 " 3 kHz ", " 6 kHz ", " 12 kHz ", " 14 kHz ", " 16 kHz "
875 Equalizer::Equalizer( intf_thread_t
*_p_intf
, QWidget
*_parent
) :
876 QWidget( _parent
) , p_intf( _p_intf
)
878 QFont smallFont
= QApplication::font();
879 smallFont
.setPointSize( smallFont
.pointSize() - 3 );
882 ui
.preampLabel
->setFont( smallFont
);
884 /* Setup of presetsComboBox */
885 presetsComboBox
= ui
.presetsCombo
;
886 CONNECT( presetsComboBox
, activated( int ), this, setCorePreset( int ) );
888 /* Add the sliders for the Bands */
889 QGridLayout
*grid
= new QGridLayout( ui
.frame
);
890 grid
->setMargin( 0 );
891 for( int i
= 0 ; i
< BANDS
; i
++ )
893 bands
[i
] = new QSlider( Qt::Vertical
);
894 bands
[i
]->setMaximum( 400 );
895 bands
[i
]->setValue( 200 );
896 CONNECT( bands
[i
], valueChanged( int ), this, setCoreBands() );
898 band_texts
[i
] = new QLabel( band_frequencies
[i
] + "\n0.0dB" );
899 band_texts
[i
]->setFont( smallFont
);
901 grid
->addWidget( bands
[i
], 0, i
);
902 grid
->addWidget( band_texts
[i
], 1, i
);
905 /* Add the listed presets */
906 for( int i
= 0 ; i
< NB_PRESETS
; i
++ )
908 presetsComboBox
->addItem( qtr( preset_list_text
[i
] ),
909 QVariant( preset_list
[i
] ) );
913 BUTTONACT( ui
.enableCheck
, enable() );
914 BUTTONACT( ui
.eq2PassCheck
, set2Pass() );
915 CONNECT( ui
.preampSlider
, valueChanged( int ), this, setPreamp() );
917 /* Do the update from the value of the core */
921 /* Write down initial values */
922 void Equalizer::updateUIFromCore()
924 char *psz_af
, *psz_pres
, *psz_bands
;
928 aout_instance_t
*p_aout
= THEMIM
->getAout();
931 psz_af
= var_GetNonEmptyString( p_aout
, "audio-filter" );
932 psz_pres
= var_GetString( p_aout
, "equalizer-preset" );
933 if( var_GetBool( p_aout
, "equalizer-2pass" ) )
934 ui
.eq2PassCheck
->setChecked( true );
935 f_preamp
= var_GetFloat( p_aout
, "equalizer-preamp" );
936 psz_bands
= var_GetNonEmptyString( p_aout
, "equalizer-bands" );
937 i_preset
= presetsComboBox
->findData( QVariant( psz_pres
) );
938 vlc_object_release( p_aout
);
942 psz_af
= config_GetPsz( p_intf
, "audio-filter" );
943 psz_pres
= config_GetPsz( p_intf
, "equalizer-preset" );
944 if( config_GetInt( p_intf
, "equalizer-2pass" ) )
945 ui
.eq2PassCheck
->setChecked( true );
946 f_preamp
= config_GetFloat( p_intf
, "equalizer-preamp" );
947 psz_bands
= config_GetPsz( p_intf
, "equalizer-bands" );
948 i_preset
= presetsComboBox
->findData( QVariant( psz_pres
) );
950 if( psz_af
&& strstr( psz_af
, "equalizer" ) != NULL
)
951 ui
.enableCheck
->setChecked( true );
952 enable( ui
.enableCheck
->isChecked() );
954 presetsComboBox
->setCurrentIndex( i_preset
);
956 ui
.preampSlider
->setValue( (int)( ( f_preamp
+ 20 ) * 10 ) );
958 if( psz_bands
&& strlen( psz_bands
) > 1 )
960 char *psz_bands_orig
= psz_bands
;
961 for( int i
= 0; i
< BANDS
; i
++ )
963 const float f
= us_strtod(psz_bands
, &psz_bands
);
964 bands
[i
]->setValue( (int)( ( f
+ 20 ) * 10 ) );
965 if( psz_bands
== NULL
|| *psz_bands
== '\0' ) break;
967 if( *psz_bands
== '\0' ) break;
969 free( psz_bands_orig
);
971 else free( psz_bands
);
977 /* Functin called when enableButton is toggled */
978 void Equalizer::enable()
980 bool en
= ui
.enableCheck
->isChecked();
981 aout_EnableFilter( THEPL
, "equalizer", en
);
982 // aout_EnableFilter( THEPL, "upmixer", en );
983 // aout_EnableFilter( THEPL, "vsurround", en );
986 if( presetsComboBox
->currentIndex() < 0 )
987 presetsComboBox
->setCurrentIndex( 0 );
991 void Equalizer::enable( bool en
)
993 ui
.eq2PassCheck
->setEnabled( en
);
994 presetsComboBox
->setEnabled( en
);
995 ui
.presetLabel
->setEnabled( en
);
996 ui
.preampLabel
->setEnabled( en
);
997 ui
.preampSlider
->setEnabled( en
);
998 for( int i
= 0 ; i
< BANDS
; i
++ )
1000 bands
[i
]->setEnabled( en
); band_texts
[i
]->setEnabled( en
);
1004 /* Function called when the set2Pass button is activated */
1005 void Equalizer::set2Pass()
1007 aout_instance_t
*p_aout
= THEMIM
->getAout();
1008 bool b_2p
= ui
.eq2PassCheck
->isChecked();
1012 var_SetBool( p_aout
, "equalizer-2pass", b_2p
);
1013 vlc_object_release( p_aout
);
1015 config_PutInt( p_intf
, "equalizer-2pass", b_2p
);
1018 /* Function called when the preamp slider is moved */
1019 void Equalizer::setPreamp()
1021 const float f
= ( float )( ui
.preampSlider
->value() ) /10 - 20;
1022 aout_instance_t
*p_aout
= THEMIM
->getAout();
1024 ui
.preampLabel
->setText( qtr( "Preamp\n" ) + QString::number( f
, 'f', 1 )
1028 //delCallbacks( p_aout );
1029 var_SetFloat( p_aout
, "equalizer-preamp", f
);
1030 //addCallbacks( p_aout );
1031 vlc_object_release( p_aout
);
1033 config_PutFloat( p_intf
, "equalizer-preamp", f
);
1036 void Equalizer::setCoreBands()
1038 /**\todo smoothing */
1041 for( int i
= 0; i
< BANDS
; i
++ )
1043 const float f_val
= (float)( bands
[i
]->value() ) / 10 - 20;
1044 QString val
= QString("%1").arg( f_val
, 5, 'f', 1 );
1046 band_texts
[i
]->setText( band_frequencies
[i
] + "\n" + val
+ "dB" );
1047 values
+= " " + val
;
1049 const char *psz_values
= values
.toAscii().constData();
1051 aout_instance_t
*p_aout
= THEMIM
->getAout();
1054 //delCallbacks( p_aout );
1055 var_SetString( p_aout
, "equalizer-bands", psz_values
);
1056 //addCallbacks( p_aout );
1057 vlc_object_release( p_aout
);
1061 char * Equalizer::createValuesFromPreset( int i_preset
)
1065 /* Create the QString in Qt */
1066 for( int i
= 0 ; i
< BANDS
;i
++ )
1067 values
+= QString( " %1" ).arg( eqz_preset_10b
[i_preset
]->f_amp
[i
] );
1069 /* Convert it to char * */
1070 return strdup( values
.toAscii().constData() );
1073 void Equalizer::setCorePreset( int i_preset
)
1078 /* Update pre-amplification in the UI */
1079 float f_preamp
= eqz_preset_10b
[i_preset
]->f_preamp
;
1080 ui
.preampSlider
->setValue( (int)( ( f_preamp
+ 20 ) * 10 ) );
1081 ui
.preampLabel
->setText( qtr( "Preamp\n" )
1082 + QString::number( f_preamp
, 'f', 1 ) + qtr( "dB" ) );
1084 char *psz_values
= createValuesFromPreset( i_preset
);
1085 if( !psz_values
) return ;
1087 char *p
= psz_values
;
1088 for( int i
= 0; i
< BANDS
&& *p
; i
++ )
1090 const float f
= us_strtod( p
, &p
);
1092 bands
[i
]->setValue( (int)( ( f
+ 20 ) * 10 ) );
1093 band_texts
[i
]->setText( band_frequencies
[i
] + "\n"
1094 + QString("%1").arg( f
, 5, 'f', 1 ) + "dB" );
1096 p
++; /* skip separator */
1099 /* Apply presets to audio output */
1100 aout_instance_t
*p_aout
= THEMIM
->getAout();
1103 var_SetString( p_aout
, "equalizer-preset" , preset_list
[i_preset
] );
1105 var_SetString( p_aout
, "equalizer-bands", psz_values
);
1106 var_SetFloat( p_aout
, "equalizer-preamp",
1107 eqz_preset_10b
[i_preset
]->f_preamp
);
1108 vlc_object_release( p_aout
);
1110 config_PutPsz( p_intf
, "equalizer-bands", psz_values
);
1111 config_PutPsz( p_intf
, "equalizer-preset", preset_list
[i_preset
] );
1112 config_PutFloat( p_intf
, "equalizer-preamp",
1113 eqz_preset_10b
[i_preset
]->f_preamp
);
1117 static int PresetCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1118 vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
1120 VLC_UNUSED( p_this
); VLC_UNUSED( psz_cmd
); VLC_UNUSED( oldval
);
1122 char *psz_preset
= newval
.psz_string
;
1123 Equalizer
*eq
= ( Equalizer
* )p_data
;
1124 int i_preset
= eq
->presetsComboBox
->findData( QVariant( psz_preset
) );
1125 eq
->presetsComboBox
->setCurrentIndex( i_preset
);
1129 void Equalizer::delCallbacks( aout_instance_t
*p_aout
)
1131 //var_DelCallback( p_aout, "equalizer-bands", EqzCallback, this );
1132 //var_DelCallback( p_aout, "equalizer-preamp", EqzCallback, this );
1133 var_DelCallback( p_aout
, "equalizer-preset", PresetCallback
, this );
1136 void Equalizer::addCallbacks( aout_instance_t
*p_aout
)
1138 //var_AddCallback( p_aout, "equalizer-bands", EqzCallback, this );
1139 //var_AddCallback( p_aout, "equalizer-preamp", EqzCallback, this );
1140 var_AddCallback( p_aout
, "equalizer-preset", PresetCallback
, this );
1143 /**********************************************************************
1145 **********************************************************************/
1147 /**********************************************************************
1148 * Dynamic range compressor
1149 **********************************************************************/
1153 const char *psz_name
;
1154 const char *psz_descs
;
1155 const char *psz_units
;
1156 const float f_min
; // min
1157 const float f_max
; // max
1158 const float f_value
; // value
1159 const float f_resolution
; // resolution
1162 static const comp_controls_t comp_controls
[] =
1164 { "compressor-rms-peak", _("RMS/peak"), "", 0.0f
, 1.0f
, 0.00f
, 0.001f
},
1165 { "compressor-attack", _("Attack"), _(" ms"), 1.5f
, 400.0f
, 25.00f
, 0.100f
},
1166 { "compressor-release", _("Release"), _(" ms"), 2.0f
, 800.0f
, 100.00f
, 0.100f
},
1167 { "compressor-threshold", _("Threshold"), _(" dB"), -30.0f
, 0.0f
, -11.00f
, 0.010f
},
1168 { "compressor-ratio", _("Ratio"), ":1", 1.0f
, 20.0f
, 8.00f
, 0.010f
},
1169 { "compressor-knee", _("Knee\nradius"), _(" dB"), 1.0f
, 10.0f
, 2.50f
, 0.010f
},
1170 { "compressor-makeup-gain", _("Makeup\ngain"), _(" dB"), 0.0f
, 24.0f
, 7.00f
, 0.010f
},
1173 Compressor::Compressor( intf_thread_t
*_p_intf
, QWidget
*_parent
)
1174 : QWidget( _parent
) , p_intf( _p_intf
)
1176 QFont smallFont
= QApplication::font();
1177 smallFont
.setPointSize( smallFont
.pointSize() - 2 );
1179 QGridLayout
*layout
= new QGridLayout( this );
1181 enableCheck
= new QCheckBox( qtr( "Enable dynamic range compressor" ) );
1182 layout
->addWidget( enableCheck
, 0, 0, 1, NUM_CP_CTRL
);
1184 for( int i
= 0 ; i
< NUM_CP_CTRL
; i
++ )
1186 const int i_min
= (int)( comp_controls
[i
].f_min
1187 / comp_controls
[i
].f_resolution
);
1188 const int i_max
= (int)( comp_controls
[i
].f_max
1189 / comp_controls
[i
].f_resolution
);
1190 const int i_val
= (int)( comp_controls
[i
].f_value
1191 / comp_controls
[i
].f_resolution
);
1193 compCtrl
[i
] = new QSlider( Qt::Vertical
);
1194 compCtrl
[i
]->setMinimum( i_min
);
1195 compCtrl
[i
]->setMaximum( i_max
);
1196 compCtrl
[i
]->setValue( i_val
);
1198 oldControlVars
[i
] = comp_controls
[i
].f_value
;
1200 CONNECT( compCtrl
[i
], valueChanged( int ), this, setInitValues() );
1202 ctrl_texts
[i
] = new QLabel( qtr( comp_controls
[i
].psz_descs
) + "\n" );
1203 ctrl_texts
[i
]->setFont( smallFont
);
1204 ctrl_texts
[i
]->setAlignment( Qt::AlignHCenter
);
1206 ctrl_readout
[i
] = new QLabel
;
1207 ctrl_readout
[i
]->setFont( smallFont
);
1208 ctrl_readout
[i
]->setAlignment( Qt::AlignHCenter
);
1210 layout
->addWidget( compCtrl
[i
], 1, i
, Qt::AlignHCenter
);
1211 layout
->addWidget( ctrl_readout
[i
], 2, i
, Qt::AlignHCenter
);
1212 layout
->addWidget( ctrl_texts
[i
], 3, i
, Qt::AlignHCenter
);
1215 BUTTONACT( enableCheck
, enable() );
1217 /* Write down initial values */
1218 aout_instance_t
*p_aout
= THEMIM
->getAout();
1223 psz_af
= var_GetNonEmptyString( p_aout
, "audio-filter" );
1224 for( int i
= 0; i
< NUM_CP_CTRL
; i
++ )
1226 controlVars
[i
] = var_GetFloat( p_aout
,
1227 comp_controls
[i
].psz_name
);
1229 vlc_object_release( p_aout
);
1233 psz_af
= config_GetPsz( p_intf
, "audio-filter" );
1234 for( int i
= 0; i
< NUM_CP_CTRL
; i
++ )
1236 controlVars
[i
] = config_GetFloat( p_intf
,
1237 comp_controls
[i
].psz_name
);
1240 if( psz_af
&& strstr( psz_af
, "compressor" ) != NULL
)
1242 enableCheck
->setChecked( true );
1245 enable( enableCheck
->isChecked() );
1246 updateSliders( controlVars
);
1250 void Compressor::enable()
1252 bool en
= enableCheck
->isChecked();
1253 aout_EnableFilter( THEPL
, "compressor", en
);
1257 void Compressor::enable( bool en
)
1259 for( int i
= 0 ; i
< NUM_CP_CTRL
; i
++ )
1261 compCtrl
[i
]->setEnabled( en
);
1262 ctrl_texts
[i
]->setEnabled( en
);
1263 ctrl_readout
[i
]->setEnabled( en
);
1267 void Compressor::updateSliders( float * controlVars
)
1269 for( int i
= 0 ; i
< NUM_CP_CTRL
; i
++ )
1271 if( oldControlVars
[i
] != controlVars
[i
] )
1273 compCtrl
[i
]->setValue(
1274 (int)( controlVars
[i
] / comp_controls
[i
].f_resolution
) );
1279 void Compressor::setInitValues()
1284 void Compressor::setValues()
1286 aout_instance_t
*p_aout
= THEMIM
->getAout();
1288 for( int i
= 0 ; i
< NUM_CP_CTRL
; i
++ )
1290 float f
= (float)( compCtrl
[i
]->value() ) * ( comp_controls
[i
].f_resolution
);
1291 ctrl_readout
[i
]->setText( QString::number( f
, 'f', 1 )
1292 + qtr( comp_controls
[i
].psz_units
) );
1293 if( oldControlVars
[i
] != f
)
1297 var_SetFloat( p_aout
, comp_controls
[i
].psz_name
, f
);
1299 config_PutFloat( p_intf
, comp_controls
[i
].psz_name
, f
);
1300 oldControlVars
[i
] = f
;
1305 vlc_object_release( p_aout
);
1309 /**********************************************************************
1311 **********************************************************************/
1314 const char *psz_name
;
1315 const char *psz_desc
;
1318 static const spat_controls_t spat_controls
[] =
1320 { "spatializer-roomsize", _("Size") },
1321 { "spatializer-width", _("Width") },
1322 { "spatializer-wet", _("Wet") },
1323 { "spatializer-dry", _("Dry") },
1324 { "spatializer-damp", _("Damp") },
1327 Spatializer::Spatializer( intf_thread_t
*_p_intf
, QWidget
*_parent
)
1328 : QWidget( _parent
) , p_intf( _p_intf
)
1330 QFont smallFont
= QApplication::font();
1331 smallFont
.setPointSize( smallFont
.pointSize() - 2 );
1333 QGridLayout
*layout
= new QGridLayout( this );
1335 enableCheck
= new QCheckBox( qtr( "Enable spatializer" ) );
1336 layout
->addWidget( enableCheck
, 0, 0, 1, NUM_SP_CTRL
);
1338 for( int i
= 0 ; i
< NUM_SP_CTRL
; i
++ )
1340 spatCtrl
[i
] = new QSlider( Qt::Vertical
);
1343 spatCtrl
[i
]->setMaximum( 10 );
1344 spatCtrl
[i
]->setValue( 2 );
1348 spatCtrl
[i
]->setMaximum( 10 );
1349 spatCtrl
[i
]->setValue( 0 );
1350 spatCtrl
[i
]->setMinimum( -10 );
1353 oldControlVars
[i
] = spatCtrl
[i
]->value();
1355 CONNECT( spatCtrl
[i
], valueChanged( int ), this, setInitValues() );
1357 ctrl_texts
[i
] = new QLabel( qtr( spat_controls
[i
].psz_desc
) + "\n" );
1358 ctrl_texts
[i
]->setFont( smallFont
);
1360 ctrl_readout
[i
] = new QLabel
;
1361 ctrl_readout
[i
]->setFont( smallFont
);
1363 layout
->addWidget( spatCtrl
[i
], 1, i
, Qt::AlignHCenter
);
1364 layout
->addWidget( ctrl_readout
[i
], 2, i
, Qt::AlignHCenter
);
1365 layout
->addWidget( ctrl_texts
[i
], 3, i
, Qt::AlignHCenter
);
1368 BUTTONACT( enableCheck
, enable() );
1370 /* Write down initial values */
1371 aout_instance_t
*p_aout
= THEMIM
->getAout();
1376 psz_af
= var_GetNonEmptyString( p_aout
, "audio-filter" );
1377 for( int i
= 0; i
< NUM_SP_CTRL
; i
++ )
1379 controlVars
[i
] = var_GetFloat( p_aout
, spat_controls
[i
].psz_name
);
1381 vlc_object_release( p_aout
);
1385 psz_af
= config_GetPsz( p_intf
, "audio-filter" );
1386 for( int i
= 0; i
< NUM_SP_CTRL
; i
++ )
1388 controlVars
[i
] = config_GetFloat( p_intf
, spat_controls
[i
].psz_name
);
1391 if( psz_af
&& strstr( psz_af
, "spatializer" ) != NULL
)
1392 enableCheck
->setChecked( true );
1394 enable( enableCheck
->isChecked() );
1398 void Spatializer::enable()
1400 bool en
= enableCheck
->isChecked();
1401 aout_EnableFilter( THEPL
, "spatializer", en
);
1405 void Spatializer::enable( bool en
)
1407 for( int i
= 0 ; i
< NUM_SP_CTRL
; i
++ )
1409 spatCtrl
[i
]->setEnabled( en
);
1410 ctrl_texts
[i
]->setEnabled( en
);
1411 ctrl_readout
[i
]->setEnabled( en
);
1414 void Spatializer::setInitValues()
1419 void Spatializer::setValues()
1421 aout_instance_t
*p_aout
= THEMIM
->getAout();
1423 for( int i
= 0 ; i
< NUM_SP_CTRL
; i
++ )
1425 float f
= (float)( spatCtrl
[i
]->value() );
1426 ctrl_readout
[i
]->setText( QString::number( f
, 'f', 1 ) );
1430 for( int i
= 0 ; i
< NUM_SP_CTRL
; i
++ )
1432 if( oldControlVars
[i
] != spatCtrl
[i
]->value() )
1434 var_SetFloat( p_aout
, spat_controls
[i
].psz_name
,
1435 ( float )spatCtrl
[i
]->value() );
1436 config_PutFloat( p_intf
, spat_controls
[i
].psz_name
,
1437 ( float ) spatCtrl
[i
]->value() );
1438 oldControlVars
[i
] = ( float ) spatCtrl
[i
]->value();
1441 vlc_object_release( p_aout
);
1445 void Spatializer::delCallbacks( aout_instance_t
*p_aout
)
1447 VLC_UNUSED( p_aout
);
1448 // var_DelCallback( p_aout, "Spatializer-bands", EqzCallback, this );
1449 // var_DelCallback( p_aout, "Spatializer-preamp", EqzCallback, this );
1452 void Spatializer::addCallbacks( aout_instance_t
*p_aout
)
1454 VLC_UNUSED( p_aout
);
1455 // var_AddCallback( p_aout, "Spatializer-bands", EqzCallback, this );
1456 // var_AddCallback( p_aout, "Spatializer-preamp", EqzCallback, this );
1459 #include <QToolButton>
1460 #include <QGridLayout>
1462 #define SUBSDELAY_CFG_MODE "subsdelay-mode"
1463 #define SUBSDELAY_CFG_FACTOR "subsdelay-factor"
1464 #define SUBSDELAY_MODE_ABSOLUTE 0
1465 #define SUBSDELAY_MODE_RELATIVE_SOURCE_DELAY 1
1466 #define SUBSDELAY_MODE_RELATIVE_SOURCE_CONTENT 2
1468 SyncControls::SyncControls( intf_thread_t
*_p_intf
, QWidget
*_parent
) :
1469 QWidget( _parent
) , p_intf( _p_intf
)
1471 QGroupBox
*AVBox
, *subsBox
;
1473 QToolButton
*moinsAV
, *plusAV
;
1474 QToolButton
*moinssubs
, *plussubs
;
1475 QToolButton
*moinssubSpeed
, *plussubSpeed
;
1476 QToolButton
*moinssubDuration
, *plussubDuration
;
1478 QToolButton
*updateButton
;
1480 b_userAction
= true;
1482 QGridLayout
*mainLayout
= new QGridLayout( this );
1485 AVBox
= new QGroupBox( qtr( "Audio/Video" ) );
1486 QGridLayout
*AVLayout
= new QGridLayout( AVBox
);
1488 moinsAV
= new QToolButton
;
1489 moinsAV
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
1490 moinsAV
->setAutoRaise( true );
1491 moinsAV
->setText( "-" );
1492 AVLayout
->addWidget( moinsAV
, 0, 1, 1, 1 );
1494 plusAV
= new QToolButton
;
1495 plusAV
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
1496 plusAV
->setAutoRaise( true );
1497 plusAV
->setText( "+" );
1498 AVLayout
->addWidget( plusAV
, 0, 3, 1, 1 );
1500 QLabel
*AVLabel
= new QLabel
;
1501 AVLabel
->setText( qtr( "Advance of audio over video:" ) );
1502 AVLayout
->addWidget( AVLabel
, 0, 0, 1, 1 );
1504 AVSpin
= new QDoubleSpinBox
;
1505 AVSpin
->setAlignment( Qt::AlignRight
|Qt::AlignTrailing
|Qt::AlignVCenter
);
1506 AVSpin
->setDecimals( 3 );
1507 AVSpin
->setMinimum( -600.0 );
1508 AVSpin
->setMaximum( 600.0 );
1509 AVSpin
->setSingleStep( 0.1 );
1510 AVSpin
->setToolTip( qtr( "A positive value means that\n"
1511 "the audio is ahead of the video" ) );
1512 AVSpin
->setSuffix( " s" );
1513 AVLayout
->addWidget( AVSpin
, 0, 2, 1, 1 );
1514 mainLayout
->addWidget( AVBox
, 1, 0, 1, 5 );
1518 subsBox
= new QGroupBox( qtr( "Subtitles/Video" ) );
1519 QGridLayout
*subsLayout
= new QGridLayout( subsBox
);
1521 moinssubs
= new QToolButton
;
1522 moinssubs
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
1523 moinssubs
->setAutoRaise( true );
1524 moinssubs
->setText( "-" );
1525 subsLayout
->addWidget( moinssubs
, 0, 1, 1, 1 );
1527 plussubs
= new QToolButton
;
1528 plussubs
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
1529 plussubs
->setAutoRaise( true );
1530 plussubs
->setText( "+" );
1531 subsLayout
->addWidget( plussubs
, 0, 3, 1, 1 );
1533 QLabel
*subsLabel
= new QLabel
;
1534 subsLabel
->setText( qtr( "Advance of subtitles over video:" ) );
1535 subsLayout
->addWidget( subsLabel
, 0, 0, 1, 1 );
1537 subsSpin
= new QDoubleSpinBox
;
1538 subsSpin
->setAlignment( Qt::AlignRight
|Qt::AlignTrailing
|Qt::AlignVCenter
);
1539 subsSpin
->setDecimals( 3 );
1540 subsSpin
->setMinimum( -600.0 );
1541 subsSpin
->setMaximum( 600.0 );
1542 subsSpin
->setSingleStep( 0.1 );
1543 subsSpin
->setToolTip( qtr( "A positive value means that\n"
1544 "the subtitles are ahead of the video" ) );
1545 subsSpin
->setSuffix( " s" );
1546 subsLayout
->addWidget( subsSpin
, 0, 2, 1, 1 );
1549 moinssubSpeed
= new QToolButton
;
1550 moinssubSpeed
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
1551 moinssubSpeed
->setAutoRaise( true );
1552 moinssubSpeed
->setText( "-" );
1553 subsLayout
->addWidget( moinssubSpeed
, 1, 1, 1, 1 );
1555 plussubSpeed
= new QToolButton
;
1556 plussubSpeed
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
1557 plussubSpeed
->setAutoRaise( true );
1558 plussubSpeed
->setText( "+" );
1559 subsLayout
->addWidget( plussubSpeed
, 1, 3, 1, 1 );
1561 QLabel
*subSpeedLabel
= new QLabel
;
1562 subSpeedLabel
->setText( qtr( "Speed of the subtitles:" ) );
1563 subsLayout
->addWidget( subSpeedLabel
, 1, 0, 1, 1 );
1565 subSpeedSpin
= new QDoubleSpinBox
;
1566 subSpeedSpin
->setAlignment( Qt::AlignRight
|Qt::AlignTrailing
|Qt::AlignVCenter
);
1567 subSpeedSpin
->setDecimals( 3 );
1568 subSpeedSpin
->setMinimum( 1 );
1569 subSpeedSpin
->setMaximum( 100 );
1570 subSpeedSpin
->setSingleStep( 0.2 );
1571 subSpeedSpin
->setSuffix( " fps" );
1572 subsLayout
->addWidget( subSpeedSpin
, 1, 2, 1, 1 );
1574 moinssubDuration
= new QToolButton
;
1575 moinssubDuration
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
1576 moinssubDuration
->setAutoRaise( true );
1577 moinssubDuration
->setText( "-" );
1578 subsLayout
->addWidget( moinssubDuration
, 2, 1, 1, 1 );
1580 plussubDuration
= new QToolButton
;
1581 plussubDuration
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
1582 plussubDuration
->setAutoRaise( true );
1583 plussubDuration
->setText( "+" );
1584 subsLayout
->addWidget( plussubDuration
, 2, 3, 1, 1 );
1586 QLabel
*subDurationLabel
= new QLabel
;
1587 subDurationLabel
->setText( qtr( "Subtitles duration factor:" ) );
1588 subsLayout
->addWidget( subDurationLabel
, 2, 0, 1, 1 );
1590 subDurationSpin
= new QDoubleSpinBox
;
1591 subDurationSpin
->setAlignment( Qt::AlignRight
|Qt::AlignTrailing
|Qt::AlignVCenter
);
1592 subDurationSpin
->setDecimals( 3 );
1593 subDurationSpin
->setMinimum( 0 );
1594 subDurationSpin
->setMaximum( 20 );
1595 subDurationSpin
->setSingleStep( 0.2 );
1596 subsLayout
->addWidget( subDurationSpin
, 2, 2, 1, 1 );
1598 mainLayout
->addWidget( subsBox
, 2, 0, 2, 5 );
1600 updateButton
= new QToolButton
;
1601 updateButton
->setAutoRaise( true );
1602 mainLayout
->addWidget( updateButton
, 0, 4, 1, 1 );
1605 /* Various Connects */
1606 CONNECT( moinsAV
, clicked(), AVSpin
, stepDown () );
1607 CONNECT( plusAV
, clicked(), AVSpin
, stepUp () );
1608 CONNECT( moinssubs
, clicked(), subsSpin
, stepDown () );
1609 CONNECT( plussubs
, clicked(), subsSpin
, stepUp () );
1610 CONNECT( moinssubSpeed
, clicked(), subSpeedSpin
, stepDown () );
1611 CONNECT( plussubSpeed
, clicked(), subSpeedSpin
, stepUp () );
1612 CONNECT( moinssubDuration
, clicked(), subDurationSpin
, stepDown () );
1613 CONNECT( plussubDuration
, clicked(), subDurationSpin
, stepUp () );
1614 CONNECT( AVSpin
, valueChanged ( double ), this, advanceAudio( double ) ) ;
1615 CONNECT( subsSpin
, valueChanged ( double ), this, advanceSubs( double ) ) ;
1616 CONNECT( subSpeedSpin
, valueChanged ( double ),
1617 this, adjustSubsSpeed( double ) );
1618 CONNECT( subDurationSpin
, valueChanged ( double ),
1619 this, adjustSubsDuration( double ) );
1621 CONNECT( THEMIM
->getIM(), synchroChanged(), this, update() );
1622 BUTTON_SET_ACT_I( updateButton
, "", update
,
1623 qtr( "Force update of this dialog's values" ), update() );
1627 updateSubsDuration();
1630 SyncControls::~SyncControls()
1635 void SyncControls::clean()
1637 b_userAction
= false;
1638 AVSpin
->setValue( 0.0 );
1639 subsSpin
->setValue( 0.0 );
1640 subSpeedSpin
->setValue( 1.0 );
1642 updateSubsDuration();
1643 b_userAction
= true;
1646 void SyncControls::update()
1648 b_userAction
= false;
1651 if( THEMIM
->getInput() )
1653 i_delay
= var_GetTime( THEMIM
->getInput(), "audio-delay" );
1654 AVSpin
->setValue( ( (double)i_delay
) / 1000000 );
1655 i_delay
= var_GetTime( THEMIM
->getInput(), "spu-delay" );
1656 subsSpin
->setValue( ( (double)i_delay
) / 1000000 );
1657 subSpeedSpin
->setValue( var_GetFloat( THEMIM
->getInput(), "sub-fps" ) );
1659 b_userAction
= true;
1662 void SyncControls::advanceAudio( double f_advance
)
1664 if( THEMIM
->getInput() && b_userAction
)
1666 int64_t i_delay
= f_advance
* 1000000;
1667 var_SetTime( THEMIM
->getInput(), "audio-delay", i_delay
);
1671 void SyncControls::advanceSubs( double f_advance
)
1673 if( THEMIM
->getInput() && b_userAction
)
1675 int64_t i_delay
= f_advance
* 1000000;
1676 var_SetTime( THEMIM
->getInput(), "spu-delay", i_delay
);
1680 void SyncControls::adjustSubsSpeed( double f_fps
)
1682 if( THEMIM
->getInput() && b_userAction
)
1684 var_SetFloat( THEMIM
->getInput(), "sub-fps", f_fps
);
1688 void SyncControls::adjustSubsDuration( double f_factor
)
1690 if( THEMIM
->getInput() && b_userAction
)
1692 subsdelaySetFactor( f_factor
);
1693 ChangeVFiltersString( p_intf
, "subsdelay", f_factor
> 0 );
1697 void SyncControls::updateSubsDuration()
1699 int i_mode
= var_InheritInteger( p_intf
, SUBSDELAY_CFG_MODE
);
1704 case SUBSDELAY_MODE_ABSOLUTE
:
1705 subDurationSpin
->setToolTip( qtr( "Extend subtitles duration by this value.\n"
1706 "Set 0 to disable." ) );
1707 subDurationSpin
->setSuffix( " s" );
1709 case SUBSDELAY_MODE_RELATIVE_SOURCE_DELAY
:
1710 subDurationSpin
->setToolTip( qtr( "Multiply subtitles duration by this value.\n"
1711 "Set 0 to disable." ) );
1712 subDurationSpin
->setSuffix( "" );
1714 case SUBSDELAY_MODE_RELATIVE_SOURCE_CONTENT
:
1715 subDurationSpin
->setToolTip( qtr( "Recalculate subtitles duration according\n"
1716 "to their content and this value.\n"
1717 "Set 0 to disable." ) );
1718 subDurationSpin
->setSuffix( "" );
1722 subDurationSpin
->setValue( var_InheritFloat( p_intf
, SUBSDELAY_CFG_FACTOR
) );
1725 void SyncControls::subsdelayClean()
1727 /* Remove subsdelay filter */
1728 ChangeVFiltersString( p_intf
, "subsdelay", false );
1731 void SyncControls::subsdelaySetFactor( double f_factor
)
1733 /* Set the factor in the preferences */
1734 config_PutFloat( p_intf
, SUBSDELAY_CFG_FACTOR
, f_factor
);
1736 /* Try to find an instance of subsdelay, and set its factor */
1737 vlc_object_t
*p_obj
= ( vlc_object_t
* ) vlc_object_find_name( p_intf
->p_libvlc
, "subsdelay", FIND_CHILD
);
1740 var_SetFloat( p_obj
, SUBSDELAY_CFG_FACTOR
, f_factor
);
1741 vlc_object_release( p_obj
);
1746 /**********************************************************************
1747 * Video filters / Adjust
1748 **********************************************************************/
1750 /**********************************************************************
1751 * Extended playbak controls
1752 **********************************************************************/