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>
38 #include <QFileDialog>
40 #include "components/extended_panels.hpp"
41 #include "dialogs/preferences.hpp"
43 #include "input_manager.hpp"
44 #include "util/qt_dirs.hpp"
46 #include "../../audio_filter/equalizer_presets.h"
47 #include <vlc_aout_intf.h>
48 #include <vlc_intf_strings.h>
51 #include <vlc_modules.h>
52 #include <vlc_plugin.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, \
113 QCheckBox *checkbox = qobject_cast<QCheckBox*>( ui.widget##Enable ); \
114 QGroupBox *groupbox = qobject_cast<QGroupBox*>( ui.widget##Enable ); \
117 vlc_object_release( p_obj ); \
118 if( checkbox ) checkbox->setChecked( true ); \
119 else if (groupbox) groupbox->setChecked( true ); \
123 if( checkbox ) checkbox->setChecked( false ); \
124 else if (groupbox) groupbox->setChecked( false ); \
127 CONNECT( ui.widget##Enable, clicked(), this, updateFilters() );
130 #define SETUP_VFILTER_OPTION( widget, signal ) \
131 initComboBoxItems( ui.widget ); \
132 setWidgetValue( ui.widget ); \
133 CONNECT( ui.widget, signal, this, updateFilterOptions() );
135 SETUP_VFILTER( adjust
)
136 SETUP_VFILTER_OPTION( hueSlider
, valueChanged( int ) )
137 SETUP_VFILTER_OPTION( contrastSlider
, valueChanged( int ) )
138 SETUP_VFILTER_OPTION( brightnessSlider
, valueChanged( int ) )
139 SETUP_VFILTER_OPTION( saturationSlider
, valueChanged( int ) )
140 SETUP_VFILTER_OPTION( gammaSlider
, valueChanged( int ) )
141 SETUP_VFILTER_OPTION( brightnessThresholdCheck
, stateChanged( int ) )
143 SETUP_VFILTER( extract
)
144 SETUP_VFILTER_OPTION( extractComponentText
, textChanged( const QString
& ) )
146 SETUP_VFILTER( posterize
)
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( psychedelic
)
170 SETUP_VFILTER( sharpen
)
171 SETUP_VFILTER_OPTION( sharpenSigmaSlider
, valueChanged( int ) )
173 SETUP_VFILTER( ripple
)
175 SETUP_VFILTER( wave
)
177 SETUP_VFILTER( transform
)
178 SETUP_VFILTER_OPTION( transformTypeCombo
, currentIndexChanged( QString
) )
180 SETUP_VFILTER( rotate
)
181 SETUP_VFILTER_OPTION( rotateAngleDial
, valueChanged( int ) )
182 ui
.rotateAngleDial
->setWrapping( true );
183 ui
.rotateAngleDial
->setNotchesVisible( true );
185 SETUP_VFILTER( puzzle
)
186 SETUP_VFILTER_OPTION( puzzleRowsSpin
, valueChanged( int ) )
187 SETUP_VFILTER_OPTION( puzzleColsSpin
, valueChanged( int ) )
188 SETUP_VFILTER_OPTION( puzzleBlackSlotCheck
, stateChanged( int ) )
190 SETUP_VFILTER( magnify
)
192 SETUP_VFILTER( clone
)
193 SETUP_VFILTER_OPTION( cloneCountSpin
, valueChanged( int ) )
195 SETUP_VFILTER( wall
)
196 SETUP_VFILTER_OPTION( wallRowsSpin
, valueChanged( int ) )
197 SETUP_VFILTER_OPTION( wallColsSpin
, valueChanged( int ) )
200 SETUP_VFILTER( erase
)
201 SETUP_VFILTER_OPTION( eraseMaskText
, editingFinished() )
202 SETUP_VFILTER_OPTION( eraseYSpin
, valueChanged( int ) )
203 SETUP_VFILTER_OPTION( eraseXSpin
, valueChanged( int ) )
204 BUTTONACT( ui
.eraseBrowseBtn
, browseEraseFile() );
206 SETUP_VFILTER( marq
)
207 SETUP_VFILTER_OPTION( marqMarqueeText
, textChanged( const QString
& ) )
208 SETUP_VFILTER_OPTION( marqPositionCombo
, currentIndexChanged( QString
) )
210 SETUP_VFILTER( logo
)
211 SETUP_VFILTER_OPTION( logoFileText
, editingFinished() )
212 SETUP_VFILTER_OPTION( logoYSpin
, valueChanged( int ) )
213 SETUP_VFILTER_OPTION( logoXSpin
, valueChanged( int ) )
214 SETUP_VFILTER_OPTION( logoOpacitySlider
, valueChanged( int ) )
215 BUTTONACT( ui
.logoBrowseBtn
, browseLogo() );
217 SETUP_VFILTER( gradfun
)
218 SETUP_VFILTER_OPTION( gradfunRadiusSlider
, valueChanged( int ) )
220 SETUP_VFILTER( grain
)
221 SETUP_VFILTER_OPTION( grainVarianceSlider
, valueChanged( int ) )
223 SETUP_VFILTER( mirror
)
225 SETUP_VFILTER( gaussianblur
)
226 SETUP_VFILTER_OPTION( gaussianbluSigmaSlider
, valueChanged( int ) )
228 SETUP_VFILTER( antiflicker
)
229 SETUP_VFILTER_OPTION( antiflickerSofteningSizeSlider
, valueChanged( int ) )
232 if( module_exists( "atmo" ) )
234 SETUP_VFILTER( atmo
)
235 SETUP_VFILTER_OPTION( atmoEdgeweightningSlider
, valueChanged( int ) )
236 SETUP_VFILTER_OPTION( atmoBrightnessSlider
, valueChanged( int ) )
237 SETUP_VFILTER_OPTION( atmoDarknesslimitSlider
, valueChanged( int ) )
238 SETUP_VFILTER_OPTION( atmoMeanlengthSlider
, valueChanged( int ) )
239 SETUP_VFILTER_OPTION( atmoMeanthresholdSlider
, valueChanged( int ) )
240 SETUP_VFILTER_OPTION( atmoPercentnewSlider
, valueChanged( int ) )
241 SETUP_VFILTER_OPTION( atmoFiltermodeCombo
, currentIndexChanged( int ) )
242 SETUP_VFILTER_OPTION( atmoShowdotsCheck
, stateChanged( int ) )
246 _parent
->removeTab( _parent
->indexOf( ui
.tab_atmo
) );
250 #undef SETUP_VFILTER_OPTION
252 CONNECT( ui
.cropTopPx
, valueChanged( int ), this, cropChange() );
253 CONNECT( ui
.cropBotPx
, valueChanged( int ), this, cropChange() );
254 CONNECT( ui
.cropLeftPx
, valueChanged( int ), this, cropChange() );
255 CONNECT( ui
.cropRightPx
, valueChanged( int ), this, cropChange() );
256 CONNECT( ui
.leftRightCropSync
, toggled ( bool ), this, cropChange() );
257 CONNECT( ui
.topBotCropSync
, toggled ( bool ), this, cropChange() );
258 CONNECT( ui
.topBotCropSync
, toggled( bool ),
259 ui
.cropBotPx
, setDisabled( bool ) );
260 CONNECT( ui
.leftRightCropSync
, toggled( bool ),
261 ui
.cropRightPx
, setDisabled( bool ) );
264 void ExtVideo::cropChange()
266 if( ui
.topBotCropSync
->isChecked() )
267 ui
.cropBotPx
->setValue( ui
.cropTopPx
->value() );
268 if( ui
.leftRightCropSync
->isChecked() )
269 ui
.cropRightPx
->setValue( ui
.cropLeftPx
->value() );
271 vout_thread_t
*p_vout
= THEMIM
->getVout();
274 var_SetInteger( p_vout
, "crop-top", ui
.cropTopPx
->value() );
275 var_SetInteger( p_vout
, "crop-bottom", ui
.cropBotPx
->value() );
276 var_SetInteger( p_vout
, "crop-left", ui
.cropLeftPx
->value() );
277 var_SetInteger( p_vout
, "crop-right", ui
.cropRightPx
->value() );
278 vlc_object_release( p_vout
);
282 void ExtVideo::clean()
284 ui
.cropTopPx
->setValue( 0 );
285 ui
.cropBotPx
->setValue( 0 );
286 ui
.cropLeftPx
->setValue( 0 );
287 ui
.cropRightPx
->setValue( 0 );
290 static void ChangeVFiltersString( struct intf_thread_t
*p_intf
, const char *psz_name
, bool b_add
)
292 char *psz_parser
, *psz_string
;
293 const char *psz_filter_type
;
295 module_t
*p_obj
= module_find( psz_name
);
298 msg_Err( p_intf
, "Unable to find filter module \"%s\".", psz_name
);
302 if( module_provides( p_obj
, "video splitter" ) )
304 psz_filter_type
= "video-splitter";
306 else if( module_provides( p_obj
, "video filter2" ) )
308 psz_filter_type
= "video-filter";
310 else if( module_provides( p_obj
, "sub source" ) )
312 psz_filter_type
= "sub-source";
314 else if( module_provides( p_obj
, "sub filter" ) )
316 psz_filter_type
= "sub-filter";
320 msg_Err( p_intf
, "Unknown video filter type." );
324 psz_string
= config_GetPsz( p_intf
, psz_filter_type
);
326 if( !psz_string
) psz_string
= strdup( "" );
328 psz_parser
= strstr( psz_string
, psz_name
);
334 psz_parser
= psz_string
;
335 if( asprintf( &psz_string
, ( *psz_string
) ? "%s:%s" : "%s%s",
336 psz_string
, psz_name
) == -1 )
353 if( *( psz_parser
+ strlen( psz_name
) ) == ':' )
355 memmove( psz_parser
, psz_parser
+ strlen( psz_name
) + 1,
356 strlen( psz_parser
+ strlen( psz_name
) + 1 ) + 1 );
363 /* Remove trailing : : */
364 if( strlen( psz_string
) > 0 &&
365 *( psz_string
+ strlen( psz_string
) -1 ) == ':' )
367 *( psz_string
+ strlen( psz_string
) -1 ) = '\0';
376 /* Vout is not kept, so put that in the config */
377 config_PutPsz( p_intf
, psz_filter_type
, psz_string
);
379 /* Try to set on the fly */
380 if( !strcmp( psz_filter_type
, "video-splitter" ) )
382 playlist_t
*p_playlist
= pl_Get( p_intf
);
383 var_SetString( p_playlist
, psz_filter_type
, psz_string
);
387 vout_thread_t
*p_vout
= THEMIM
->getVout();
390 var_SetString( p_vout
, psz_filter_type
, psz_string
);
391 vlc_object_release( p_vout
);
398 void ExtVideo::updateFilters()
400 QString module
= ModuleFromWidgetName( sender() );
402 QCheckBox
*checkbox
= qobject_cast
<QCheckBox
*>( sender() );
403 QGroupBox
*groupbox
= qobject_cast
<QGroupBox
*>( sender() );
405 ChangeVFiltersString( p_intf
, qtu( module
),
406 checkbox
? checkbox
->isChecked()
407 : groupbox
->isChecked() );
410 #define UPDATE_AND_APPLY_TEXT( widget, file ) \
411 CONNECT( ui.widget, textChanged( const QString& ), \
412 this, updateFilterOptions() ); \
413 ui.widget->setText( toNativeSeparators( file ) ); \
414 ui.widget->disconnect( SIGNAL( textChanged( const QString& ) ) );
416 void ExtVideo::browseLogo()
418 QString file
= QFileDialog::getOpenFileName( NULL
, qtr( "Logo filenames" ),
419 p_intf
->p_sys
->filepath
, "Images (*.png *.jpg);;All (*)" );
421 UPDATE_AND_APPLY_TEXT( logoFileText
, file
);
424 void ExtVideo::browseEraseFile()
426 QString file
= QFileDialog::getOpenFileName( NULL
, qtr( "Image mask" ),
427 p_intf
->p_sys
->filepath
, "Images (*.png *.jpg);;All (*)" );
429 UPDATE_AND_APPLY_TEXT( eraseMaskText
, file
);
432 #undef UPDATE_AND_APPLY_TEXT
434 void ExtVideo::initComboBoxItems( QObject
*widget
)
436 QComboBox
*combobox
= qobject_cast
<QComboBox
*>( widget
);
437 if( !combobox
) return;
439 QString option
= OptionFromWidgetName( widget
);
440 module_config_t
*p_item
= config_FindConfig( VLC_OBJECT( p_intf
),
444 int i_type
= p_item
->i_type
;
445 for( int i_index
= 0; i_index
< p_item
->i_list
; i_index
++ )
447 if( i_type
== CONFIG_ITEM_INTEGER
448 || i_type
== CONFIG_ITEM_BOOL
)
449 combobox
->addItem( qtr( p_item
->ppsz_list_text
[i_index
] ),
450 p_item
->pi_list
[i_index
] );
451 else if( i_type
== CONFIG_ITEM_STRING
)
452 combobox
->addItem( qtr( p_item
->ppsz_list_text
[i_index
] ),
453 p_item
->ppsz_list
[i_index
] );
458 msg_Err( p_intf
, "Couldn't find option \"%s\".", qtu( option
) );
462 void ExtVideo::setWidgetValue( QObject
*widget
)
464 QString module
= ModuleFromWidgetName( widget
->parent() );
465 //std::cout << "Module name: " << module.toStdString() << std::endl;
466 QString option
= OptionFromWidgetName( widget
);
467 //std::cout << "Option name: " << option.toStdString() << std::endl;
469 vlc_object_t
*p_obj
= ( vlc_object_t
* )
470 vlc_object_find_name( p_intf
->p_libvlc
, qtu( module
) );
478 "Module instance %s not found, looking in config values.",
481 i_type
= config_GetType( p_intf
, qtu( option
) ) & VLC_VAR_CLASS
;
484 case VLC_VAR_INTEGER
:
486 val
.i_int
= config_GetInt( p_intf
, qtu( option
) );
489 val
.f_float
= config_GetFloat( p_intf
, qtu( option
) );
492 val
.psz_string
= config_GetPsz( p_intf
, qtu( option
) );
498 i_type
= var_Type( p_obj
, qtu( option
) ) & VLC_VAR_CLASS
;
499 var_Get( p_obj
, qtu( option
), &val
);
500 vlc_object_release( p_obj
);
503 /* Try to cast to all the widgets we're likely to encounter. Only
504 * one of the casts is expected to work. */
505 QSlider
*slider
= qobject_cast
<QSlider
*> ( widget
);
506 QCheckBox
*checkbox
= qobject_cast
<QCheckBox
*> ( widget
);
507 QSpinBox
*spinbox
= qobject_cast
<QSpinBox
*> ( widget
);
508 QDoubleSpinBox
*doublespinbox
= qobject_cast
<QDoubleSpinBox
*>( widget
);
509 QDial
*dial
= qobject_cast
<QDial
*> ( widget
);
510 QLineEdit
*lineedit
= qobject_cast
<QLineEdit
*> ( widget
);
511 QComboBox
*combobox
= qobject_cast
<QComboBox
*> ( widget
);
513 if( i_type
== VLC_VAR_INTEGER
|| i_type
== VLC_VAR_BOOL
)
515 if( slider
) slider
->setValue( val
.i_int
);
516 else if( checkbox
) checkbox
->setCheckState( val
.i_int
? Qt::Checked
518 else if( spinbox
) spinbox
->setValue( val
.i_int
);
519 else if( dial
) dial
->setValue( ( 540-val
.i_int
)%360 );
523 snprintf( str
, sizeof(str
), "%06"PRIX64
, val
.i_int
);
524 lineedit
->setText( str
);
526 else if( combobox
) combobox
->setCurrentIndex(
527 combobox
->findData( qlonglong(val
.i_int
) ) );
528 else msg_Warn( p_intf
, "Could not find the correct Integer widget" );
530 else if( i_type
== VLC_VAR_FLOAT
)
532 if( slider
) slider
->setValue( ( int )( val
.f_float
*( double )slider
->tickInterval() ) ); /* hack alert! */
533 else if( doublespinbox
) doublespinbox
->setValue( val
.f_float
);
534 else msg_Warn( p_intf
, "Could not find the correct Float widget" );
536 else if( i_type
== VLC_VAR_STRING
)
538 if( lineedit
) lineedit
->setText( qfu( val
.psz_string
) );
539 else if( combobox
) combobox
->setCurrentIndex(
540 combobox
->findData( qfu( val
.psz_string
) ) );
541 else msg_Warn( p_intf
, "Could not find the correct String widget" );
542 free( val
.psz_string
);
547 "Module %s's %s variable is of an unsupported type ( %d )",
553 void ExtVideo::updateFilterOptions()
555 QString module
= ModuleFromWidgetName( sender()->parent() );
556 //std::cout << "Module name: " << module.toStdString() << std::endl;
557 QString option
= OptionFromWidgetName( sender() );
558 //std::cout << "Option name: " << option.toStdString() << std::endl;
560 vlc_object_t
*p_obj
= ( vlc_object_t
* )
561 vlc_object_find_name( p_intf
->p_libvlc
, qtu( module
) );
566 msg_Warn( p_intf
, "Module %s not found. You'll need to restart the filter to take the change into account.", qtu( module
) );
567 i_type
= config_GetType( p_intf
, qtu( option
) );
568 b_is_command
= false;
572 i_type
= var_Type( p_obj
, qtu( option
) );
574 i_type
= config_GetType( p_intf
, qtu( option
) );
575 b_is_command
= ( i_type
& VLC_VAR_ISCOMMAND
);
578 /* Try to cast to all the widgets we're likely to encounter. Only
579 * one of the casts is expected to work. */
580 QSlider
*slider
= qobject_cast
<QSlider
*> ( sender() );
581 QCheckBox
*checkbox
= qobject_cast
<QCheckBox
*> ( sender() );
582 QSpinBox
*spinbox
= qobject_cast
<QSpinBox
*> ( sender() );
583 QDoubleSpinBox
*doublespinbox
= qobject_cast
<QDoubleSpinBox
*>( sender() );
584 QDial
*dial
= qobject_cast
<QDial
*> ( sender() );
585 QLineEdit
*lineedit
= qobject_cast
<QLineEdit
*> ( sender() );
586 QComboBox
*combobox
= qobject_cast
<QComboBox
*> ( sender() );
588 i_type
&= VLC_VAR_CLASS
;
589 if( i_type
== VLC_VAR_INTEGER
|| i_type
== VLC_VAR_BOOL
)
592 if( slider
) i_int
= slider
->value();
593 else if( checkbox
) i_int
= checkbox
->checkState() == Qt::Checked
;
594 else if( spinbox
) i_int
= spinbox
->value();
595 else if( dial
) i_int
= ( 540-dial
->value() )%360;
596 else if( lineedit
) i_int
= lineedit
->text().toInt( NULL
,16 );
597 else if( combobox
) i_int
= combobox
->itemData( combobox
->currentIndex() ).toInt();
598 else msg_Warn( p_intf
, "Could not find the correct Integer widget" );
599 config_PutInt( p_intf
, qtu( option
), i_int
);
602 if( i_type
== VLC_VAR_INTEGER
)
603 var_SetInteger( p_obj
, qtu( option
), i_int
);
605 var_SetBool( p_obj
, qtu( option
), i_int
);
608 else if( i_type
== VLC_VAR_FLOAT
)
611 if( slider
) f_float
= ( double )slider
->value()
612 / ( double )slider
->tickInterval(); /* hack alert! */
613 else if( doublespinbox
) f_float
= doublespinbox
->value();
614 else if( lineedit
) f_float
= lineedit
->text().toDouble();
615 else msg_Warn( p_intf
, "Could not find the correct Float widget" );
616 config_PutFloat( p_intf
, qtu( option
), f_float
);
618 var_SetFloat( p_obj
, qtu( option
), f_float
);
620 else if( i_type
== VLC_VAR_STRING
)
624 val
= lineedit
->text();
626 val
= combobox
->itemData( combobox
->currentIndex() ).toString();
628 msg_Warn( p_intf
, "Could not find the correct String widget" );
629 config_PutPsz( p_intf
, qtu( option
), qtu( val
) );
631 var_SetString( p_obj
, qtu( option
), qtu( val
) );
635 "Module %s's %s variable is of an unsupported type ( %d )",
642 msg_Warn( p_intf
, "Module %s's %s variable isn't a command. Brute-restarting the filter.",
645 ChangeVFiltersString( p_intf
, qtu( module
), false );
646 ChangeVFiltersString( p_intf
, qtu( module
), true );
649 if( p_obj
) vlc_object_release( p_obj
);
653 void ExtVideo::gotoConf( QObject
* src
)
655 #define SHOWCONF( module ) \
656 if( src->objectName().contains( module ) ) \
658 PrefsDialog::getInstance( p_intf )->showModulePrefs( module ); \
662 SHOWCONF( "magnify" );
664 SHOWCONF( "ripple" );
665 SHOWCONF( "invert" );
666 SHOWCONF( "puzzle" );
668 SHOWCONF( "gradient" );
669 SHOWCONF( "colorthres" )
673 /**********************************************************************
675 **********************************************************************/
677 ExtV4l2::ExtV4l2( intf_thread_t
*_p_intf
, QWidget
*_parent
)
678 : QWidget( _parent
), p_intf( _p_intf
), box( NULL
)
680 QVBoxLayout
*layout
= new QVBoxLayout( this );
681 help
= new QLabel( qtr("No v4l2 instance found.\n"
682 "Please check that the device has been opened with VLC and is playing.\n\n"
683 "Controls will automatically appear here.")
685 help
->setAlignment( Qt::AlignHCenter
| Qt::AlignVCenter
);
686 layout
->addWidget( help
);
690 void ExtV4l2::showEvent( QShowEvent
*event
)
692 QWidget::showEvent( event
);
696 void ExtV4l2::Refresh( void )
698 vlc_object_t
*p_obj
= (vlc_object_t
*)vlc_object_find_name( pl_Get(p_intf
), "v4l2" );
702 layout()->removeWidget( box
);
708 vlc_value_t val
, text
;
709 int i_ret
= var_Change( p_obj
, "controls", VLC_VAR_GETCHOICES
,
713 msg_Err( p_intf
, "Oops, v4l2 object doesn't have a 'controls' variable." );
715 vlc_object_release( p_obj
);
719 box
= new QGroupBox( this );
720 layout()->addWidget( box
);
721 QVBoxLayout
*layout
= new QVBoxLayout( box
);
722 box
->setLayout( layout
);
724 for( int i
= 0; i
< val
.p_list
->i_count
; i
++ )
727 const char *psz_var
= text
.p_list
->p_values
[i
].psz_string
;
729 if( var_Change( p_obj
, psz_var
, VLC_VAR_GETTEXT
, &vartext
, NULL
) )
732 QString name
= qtr( vartext
.psz_string
);
733 free( vartext
.psz_string
);
734 msg_Dbg( p_intf
, "v4l2 control \"%"PRIx64
"\": %s (%s)",
735 val
.p_list
->p_values
[i
].i_int
, psz_var
, qtu( name
) );
737 int i_type
= var_Type( p_obj
, psz_var
);
738 switch( i_type
& VLC_VAR_TYPE
)
740 case VLC_VAR_INTEGER
:
742 QLabel
*label
= new QLabel( name
, box
);
743 QHBoxLayout
*hlayout
= new QHBoxLayout();
744 hlayout
->addWidget( label
);
745 int i_val
= var_GetInteger( p_obj
, psz_var
);
746 if( i_type
& VLC_VAR_HASCHOICE
)
748 QComboBox
*combobox
= new QComboBox( box
);
749 combobox
->setObjectName( qfu( psz_var
) );
751 vlc_value_t val2
, text2
;
752 var_Change( p_obj
, psz_var
, VLC_VAR_GETCHOICES
,
754 for( int j
= 0; j
< val2
.p_list
->i_count
; j
++ )
757 text2
.p_list
->p_values
[j
].psz_string
,
758 qlonglong( val2
.p_list
->p_values
[j
].i_int
) );
759 if( i_val
== val2
.p_list
->p_values
[j
].i_int
)
760 combobox
->setCurrentIndex( j
);
762 var_FreeList( &val2
, &text2
);
764 CONNECT( combobox
, currentIndexChanged( int ), this,
765 ValueChange( int ) );
766 hlayout
->addWidget( combobox
);
769 if( (i_type
& VLC_VAR_HASMIN
) && (i_type
& VLC_VAR_HASMAX
) )
771 QSlider
*slider
= new QSlider( box
);
772 slider
->setObjectName( qfu( psz_var
) );
773 slider
->setOrientation( Qt::Horizontal
);
775 var_Change( p_obj
, psz_var
, VLC_VAR_GETMIN
,
777 if( val2
.i_int
< INT_MIN
)
778 val2
.i_int
= INT_MIN
; /* FIXME */
779 slider
->setMinimum( val2
.i_int
);
780 var_Change( p_obj
, psz_var
, VLC_VAR_GETMAX
,
782 if( val2
.i_int
> INT_MAX
)
783 val2
.i_int
= INT_MAX
; /* FIXME */
784 slider
->setMaximum( val2
.i_int
);
785 if( !var_Change( p_obj
, psz_var
, VLC_VAR_GETSTEP
,
787 slider
->setSingleStep( val2
.i_int
);
788 slider
->setValue( i_val
);
789 CONNECT( slider
, valueChanged( int ), this,
790 ValueChange( int ) );
791 hlayout
->addWidget( slider
);
795 QSpinBox
*spinBox
= new QSpinBox( box
);
796 spinBox
->setObjectName( qfu( psz_var
) );
797 spinBox
->setMinimum( INT_MIN
);
798 spinBox
->setMaximum( INT_MAX
);
799 spinBox
->setValue( i_val
);
800 CONNECT( spinBox
, valueChanged( int ), this,
801 ValueChange( int ) );
802 hlayout
->addWidget( spinBox
);
804 layout
->addLayout( hlayout
);
809 QCheckBox
*button
= new QCheckBox( name
, box
);
810 button
->setObjectName( qfu( psz_var
) );
811 button
->setChecked( var_GetBool( p_obj
, psz_var
) );
813 CONNECT( button
, clicked( bool ), this,
814 ValueChange( bool ) );
815 layout
->addWidget( button
);
820 if( i_type
& VLC_VAR_ISCOMMAND
)
822 QPushButton
*button
= new QPushButton( name
, box
);
823 button
->setObjectName( qfu( psz_var
) );
825 CONNECT( button
, clicked( bool ), this,
826 ValueChange( bool ) );
827 layout
->addWidget( button
);
831 QLabel
*label
= new QLabel( name
, box
);
832 layout
->addWidget( label
);
837 msg_Warn( p_intf
, "Unhandled var type for %s", psz_var
);
841 var_FreeList( &val
, &text
);
842 vlc_object_release( p_obj
);
846 msg_Dbg( p_intf
, "Couldn't find v4l2 instance" );
849 QTimer::singleShot( 2000, this, SLOT(Refresh()) );
853 void ExtV4l2::ValueChange( bool value
)
855 ValueChange( (int)value
);
858 void ExtV4l2::ValueChange( int value
)
860 QObject
*s
= sender();
861 vlc_object_t
*p_obj
= (vlc_object_t
*)vlc_object_find_name( pl_Get(p_intf
), "v4l2" );
864 QString var
= s
->objectName();
865 int i_type
= var_Type( p_obj
, qtu( var
) );
866 switch( i_type
& VLC_VAR_TYPE
)
868 case VLC_VAR_INTEGER
:
869 if( i_type
& VLC_VAR_HASCHOICE
)
871 QComboBox
*combobox
= qobject_cast
<QComboBox
*>( s
);
872 value
= combobox
->itemData( value
).toInt();
874 var_SetInteger( p_obj
, qtu( var
), value
);
877 var_SetBool( p_obj
, qtu( var
), value
);
880 var_TriggerCallback( p_obj
, qtu( var
) );
883 vlc_object_release( p_obj
);
887 msg_Warn( p_intf
, "Oops, v4l2 object isn't available anymore" );
892 /**********************************************************************
894 **********************************************************************/
896 static const QString band_frequencies
[] =
898 " 60 Hz ", " 170 Hz ", " 310 Hz ", " 600 Hz ", " 1 kHz ",
899 " 3 kHz ", " 6 kHz ", " 12 kHz ", " 14 kHz ", " 16 kHz "
902 Equalizer::Equalizer( intf_thread_t
*_p_intf
, QWidget
*_parent
) :
903 QWidget( _parent
) , p_intf( _p_intf
)
905 QFont smallFont
= QApplication::font();
906 smallFont
.setPointSize( smallFont
.pointSize() - 3 );
909 ui
.preampLabel
->setFont( smallFont
);
911 /* Setup of presetsComboBox */
912 presetsComboBox
= ui
.presetsCombo
;
913 CONNECT( presetsComboBox
, activated( int ), this, setCorePreset( int ) );
915 /* Add the sliders for the Bands */
916 QGridLayout
*grid
= new QGridLayout( ui
.frame
);
917 grid
->setMargin( 0 );
918 for( int i
= 0 ; i
< BANDS
; i
++ )
920 bands
[i
] = new QSlider( Qt::Vertical
);
921 bands
[i
]->setMaximum( 400 );
922 bands
[i
]->setValue( 200 );
923 bands
[i
]->setMinimumWidth(34);
924 CONNECT( bands
[i
], valueChanged( int ), this, setCoreBands() );
926 band_texts
[i
] = new QLabel( band_frequencies
[i
] + "\n00.0dB" );
927 band_texts
[i
]->setFont( smallFont
);
929 grid
->addWidget( bands
[i
], 0, i
);
930 grid
->addWidget( band_texts
[i
], 1, i
);
933 /* Add the listed presets */
934 for( int i
= 0 ; i
< NB_PRESETS
; i
++ )
936 presetsComboBox
->addItem( qtr( preset_list_text
[i
] ),
937 QVariant( preset_list
[i
] ) );
941 BUTTONACT( ui
.enableCheck
, enable() );
942 BUTTONACT( ui
.eq2PassCheck
, set2Pass() );
943 CONNECT( ui
.preampSlider
, valueChanged( int ), this, setPreamp() );
945 /* Do the update from the value of the core */
949 /* Write down initial values */
950 void Equalizer::updateUIFromCore()
952 char *psz_af
, *psz_pres
, *psz_bands
;
956 vlc_object_t
*p_aout
= (vlc_object_t
*)THEMIM
->getAout();
959 psz_af
= var_GetNonEmptyString( p_aout
, "audio-filter" );
960 psz_pres
= var_GetString( p_aout
, "equalizer-preset" );
961 if( var_GetBool( p_aout
, "equalizer-2pass" ) )
962 ui
.eq2PassCheck
->setChecked( true );
963 f_preamp
= var_GetFloat( p_aout
, "equalizer-preamp" );
964 psz_bands
= var_GetNonEmptyString( p_aout
, "equalizer-bands" );
965 i_preset
= presetsComboBox
->findData( QVariant( psz_pres
) );
966 vlc_object_release( p_aout
);
970 psz_af
= config_GetPsz( p_intf
, "audio-filter" );
971 psz_pres
= config_GetPsz( p_intf
, "equalizer-preset" );
972 if( config_GetInt( p_intf
, "equalizer-2pass" ) )
973 ui
.eq2PassCheck
->setChecked( true );
974 f_preamp
= config_GetFloat( p_intf
, "equalizer-preamp" );
975 psz_bands
= config_GetPsz( p_intf
, "equalizer-bands" );
976 i_preset
= presetsComboBox
->findData( QVariant( psz_pres
) );
978 if( psz_af
&& strstr( psz_af
, "equalizer" ) != NULL
)
979 ui
.enableCheck
->setChecked( true );
980 enable( ui
.enableCheck
->isChecked() );
982 presetsComboBox
->setCurrentIndex( i_preset
);
984 ui
.preampSlider
->setValue( (int)( ( f_preamp
+ 20 ) * 10 ) );
986 if( psz_bands
&& strlen( psz_bands
) > 1 )
988 char *psz_bands_orig
= psz_bands
;
989 for( int i
= 0; i
< BANDS
; i
++ )
991 const float f
= us_strtod(psz_bands
, &psz_bands
);
992 bands
[i
]->setValue( (int)( ( f
+ 20 ) * 10 ) );
993 if( psz_bands
== NULL
|| *psz_bands
== '\0' ) break;
995 if( *psz_bands
== '\0' ) break;
997 free( psz_bands_orig
);
999 else free( psz_bands
);
1005 /* Functin called when enableButton is toggled */
1006 void Equalizer::enable()
1008 bool en
= ui
.enableCheck
->isChecked();
1009 aout_EnableFilter( THEPL
, "equalizer", en
);
1010 // aout_EnableFilter( THEPL, "upmixer", en );
1011 // aout_EnableFilter( THEPL, "vsurround", en );
1014 if( presetsComboBox
->currentIndex() < 0 )
1015 presetsComboBox
->setCurrentIndex( 0 );
1019 void Equalizer::enable( bool en
)
1021 ui
.eq2PassCheck
->setEnabled( en
);
1022 presetsComboBox
->setEnabled( en
);
1023 ui
.presetLabel
->setEnabled( en
);
1024 ui
.preampLabel
->setEnabled( en
);
1025 ui
.preampSlider
->setEnabled( en
);
1026 for( int i
= 0 ; i
< BANDS
; i
++ )
1028 bands
[i
]->setEnabled( en
); band_texts
[i
]->setEnabled( en
);
1032 /* Function called when the set2Pass button is activated */
1033 void Equalizer::set2Pass()
1035 vlc_object_t
*p_aout
= (vlc_object_t
*)THEMIM
->getAout();
1036 bool b_2p
= ui
.eq2PassCheck
->isChecked();
1040 var_SetBool( p_aout
, "equalizer-2pass", b_2p
);
1041 vlc_object_release( p_aout
);
1043 config_PutInt( p_intf
, "equalizer-2pass", b_2p
);
1046 /* Function called when the preamp slider is moved */
1047 void Equalizer::setPreamp()
1049 const float f
= ( float )( ui
.preampSlider
->value() ) /10 - 20;
1050 vlc_object_t
*p_aout
= (vlc_object_t
*)THEMIM
->getAout();
1052 ui
.preampLabel
->setText( qtr( "Preamp\n" ) + QString::number( f
, 'f', 1 )
1056 //delCallbacks( p_aout );
1057 var_SetFloat( p_aout
, "equalizer-preamp", f
);
1058 //addCallbacks( p_aout );
1059 vlc_object_release( p_aout
);
1061 config_PutFloat( p_intf
, "equalizer-preamp", f
);
1064 void Equalizer::setCoreBands()
1066 /**\todo smoothing */
1069 for( int i
= 0; i
< BANDS
; i
++ )
1071 const float f_val
= (float)( bands
[i
]->value() ) / 10 - 20;
1072 QString val
= QString("%1").arg( f_val
, 5, 'f', 1 );
1074 band_texts
[i
]->setText( band_frequencies
[i
] + "\n" + val
+ "dB" );
1075 values
+= " " + val
;
1078 vlc_object_t
*p_aout
= (vlc_object_t
*)THEMIM
->getAout();
1081 //delCallbacks( p_aout );
1082 var_SetString( p_aout
, "equalizer-bands", qtu( values
) );
1083 //addCallbacks( p_aout );
1084 vlc_object_release( p_aout
);
1088 char * Equalizer::createValuesFromPreset( int i_preset
)
1092 /* Create the QString in Qt */
1093 for( int i
= 0 ; i
< BANDS
;i
++ )
1094 values
+= QString( " %1" ).arg( eqz_preset_10b
[i_preset
].f_amp
[i
], 5, 'f', 1 );
1096 /* Convert it to char * */
1097 return strdup( values
.toAscii().constData() );
1100 void Equalizer::setCorePreset( int i_preset
)
1105 /* Update pre-amplification in the UI */
1106 float f_preamp
= eqz_preset_10b
[i_preset
].f_preamp
;
1107 ui
.preampSlider
->setValue( (int)( ( f_preamp
+ 20 ) * 10 ) );
1108 ui
.preampLabel
->setText( qtr( "Preamp\n" )
1109 + QString::number( f_preamp
, 'f', 1 ) + qtr( "dB" ) );
1111 char *psz_values
= createValuesFromPreset( i_preset
);
1112 if( !psz_values
) return ;
1114 char *p
= psz_values
;
1115 for( int i
= 0; i
< BANDS
&& *p
; i
++ )
1117 const float f
= us_strtod( p
, &p
);
1119 bands
[i
]->setValue( (int)( ( f
+ 20 ) * 10 ) );
1120 band_texts
[i
]->setText( band_frequencies
[i
] + "\n"
1121 + QString("%1").arg( f
, 5, 'f', 1 ) + "dB" );
1123 p
++; /* skip separator */
1126 /* Apply presets to audio output */
1127 vlc_object_t
*p_aout
= (vlc_object_t
*)THEMIM
->getAout();
1130 var_SetString( p_aout
, "equalizer-preset" , preset_list
[i_preset
] );
1132 var_SetString( p_aout
, "equalizer-bands", psz_values
);
1133 var_SetFloat( p_aout
, "equalizer-preamp",
1134 eqz_preset_10b
[i_preset
].f_preamp
);
1135 vlc_object_release( p_aout
);
1137 config_PutPsz( p_intf
, "equalizer-bands", psz_values
);
1138 config_PutPsz( p_intf
, "equalizer-preset", preset_list
[i_preset
] );
1139 config_PutFloat( p_intf
, "equalizer-preamp",
1140 eqz_preset_10b
[i_preset
].f_preamp
);
1144 static int PresetCallback( vlc_object_t
*p_this
, char const *psz_cmd
,
1145 vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
1147 VLC_UNUSED( p_this
); VLC_UNUSED( psz_cmd
); VLC_UNUSED( oldval
);
1149 char *psz_preset
= newval
.psz_string
;
1150 Equalizer
*eq
= ( Equalizer
* )p_data
;
1151 int i_preset
= eq
->presetsComboBox
->findData( QVariant( psz_preset
) );
1152 eq
->presetsComboBox
->setCurrentIndex( i_preset
);
1156 void Equalizer::delCallbacks( vlc_object_t
*p_aout
)
1158 //var_DelCallback( p_aout, "equalizer-bands", EqzCallback, this );
1159 //var_DelCallback( p_aout, "equalizer-preamp", EqzCallback, this );
1160 var_DelCallback( p_aout
, "equalizer-preset", PresetCallback
, this );
1163 void Equalizer::addCallbacks( vlc_object_t
*p_aout
)
1165 //var_AddCallback( p_aout, "equalizer-bands", EqzCallback, this );
1166 //var_AddCallback( p_aout, "equalizer-preamp", EqzCallback, this );
1167 var_AddCallback( p_aout
, "equalizer-preset", PresetCallback
, this );
1170 /**********************************************************************
1172 **********************************************************************/
1174 /**********************************************************************
1175 * Dynamic range compressor
1176 **********************************************************************/
1180 const char *psz_name
;
1181 const char *psz_descs
;
1182 const char *psz_units
;
1183 const float f_min
; // min
1184 const float f_max
; // max
1185 const float f_value
; // value
1186 const float f_resolution
; // resolution
1189 static const comp_controls_t comp_controls
[] =
1191 { "compressor-rms-peak", _("RMS/peak"), "", 0.0f
, 1.0f
, 0.00f
, 0.001f
},
1192 { "compressor-attack", _("Attack"), _(" ms"), 1.5f
, 400.0f
, 25.00f
, 0.100f
},
1193 { "compressor-release", _("Release"), _(" ms"), 2.0f
, 800.0f
, 100.00f
, 0.100f
},
1194 { "compressor-threshold", _("Threshold"), _(" dB"), -30.0f
, 0.0f
, -11.00f
, 0.010f
},
1195 { "compressor-ratio", _("Ratio"), ":1", 1.0f
, 20.0f
, 8.00f
, 0.010f
},
1196 { "compressor-knee", _("Knee\nradius"), _(" dB"), 1.0f
, 10.0f
, 2.50f
, 0.010f
},
1197 { "compressor-makeup-gain", _("Makeup\ngain"), _(" dB"), 0.0f
, 24.0f
, 7.00f
, 0.010f
},
1200 Compressor::Compressor( intf_thread_t
*_p_intf
, QWidget
*_parent
)
1201 : QWidget( _parent
) , p_intf( _p_intf
)
1203 QFont smallFont
= QApplication::font();
1204 smallFont
.setPointSize( smallFont
.pointSize() - 2 );
1206 QGridLayout
*layout
= new QGridLayout( this );
1208 enableCheck
= new QCheckBox( qtr( "Enable dynamic range compressor" ) );
1209 layout
->addWidget( enableCheck
, 0, 0, 1, NUM_CP_CTRL
);
1211 for( int i
= 0 ; i
< NUM_CP_CTRL
; i
++ )
1213 const int i_min
= (int)( comp_controls
[i
].f_min
1214 / comp_controls
[i
].f_resolution
);
1215 const int i_max
= (int)( comp_controls
[i
].f_max
1216 / comp_controls
[i
].f_resolution
);
1217 const int i_val
= (int)( comp_controls
[i
].f_value
1218 / comp_controls
[i
].f_resolution
);
1220 compCtrl
[i
] = new QSlider( Qt::Vertical
);
1221 compCtrl
[i
]->setMinimum( i_min
);
1222 compCtrl
[i
]->setMaximum( i_max
);
1223 compCtrl
[i
]->setValue( i_val
);
1225 oldControlVars
[i
] = comp_controls
[i
].f_value
;
1227 CONNECT( compCtrl
[i
], valueChanged( int ), this, setInitValues() );
1229 ctrl_texts
[i
] = new QLabel( qtr( comp_controls
[i
].psz_descs
) + "\n" );
1230 ctrl_texts
[i
]->setFont( smallFont
);
1231 ctrl_texts
[i
]->setAlignment( Qt::AlignHCenter
);
1233 ctrl_readout
[i
] = new QLabel
;
1234 ctrl_readout
[i
]->setFont( smallFont
);
1235 ctrl_readout
[i
]->setAlignment( Qt::AlignHCenter
);
1237 layout
->addWidget( compCtrl
[i
], 1, i
, Qt::AlignHCenter
);
1238 layout
->addWidget( ctrl_readout
[i
], 2, i
, Qt::AlignHCenter
);
1239 layout
->addWidget( ctrl_texts
[i
], 3, i
, Qt::AlignHCenter
);
1242 BUTTONACT( enableCheck
, enable() );
1244 /* Write down initial values */
1245 vlc_object_t
*p_aout
= (vlc_object_t
*)THEMIM
->getAout();
1250 psz_af
= var_GetNonEmptyString( p_aout
, "audio-filter" );
1251 for( int i
= 0; i
< NUM_CP_CTRL
; i
++ )
1253 controlVars
[i
] = var_GetFloat( p_aout
,
1254 comp_controls
[i
].psz_name
);
1256 vlc_object_release( p_aout
);
1260 psz_af
= config_GetPsz( p_intf
, "audio-filter" );
1261 for( int i
= 0; i
< NUM_CP_CTRL
; i
++ )
1263 controlVars
[i
] = config_GetFloat( p_intf
,
1264 comp_controls
[i
].psz_name
);
1267 if( psz_af
&& strstr( psz_af
, "compressor" ) != NULL
)
1269 enableCheck
->setChecked( true );
1272 enable( enableCheck
->isChecked() );
1273 updateSliders( controlVars
);
1277 void Compressor::enable()
1279 bool en
= enableCheck
->isChecked();
1280 aout_EnableFilter( THEPL
, "compressor", en
);
1284 void Compressor::enable( bool en
)
1286 for( int i
= 0 ; i
< NUM_CP_CTRL
; i
++ )
1288 compCtrl
[i
]->setEnabled( en
);
1289 ctrl_texts
[i
]->setEnabled( en
);
1290 ctrl_readout
[i
]->setEnabled( en
);
1294 void Compressor::updateSliders( float * p_controlVars
)
1296 for( int i
= 0 ; i
< NUM_CP_CTRL
; i
++ )
1298 if( oldControlVars
[i
] != p_controlVars
[i
] )
1300 compCtrl
[i
]->setValue(
1301 (int)( p_controlVars
[i
] / comp_controls
[i
].f_resolution
) );
1306 void Compressor::setInitValues()
1311 void Compressor::setValues()
1313 vlc_object_t
*p_aout
= (vlc_object_t
*)THEMIM
->getAout();
1315 for( int i
= 0 ; i
< NUM_CP_CTRL
; i
++ )
1317 float f
= (float)( compCtrl
[i
]->value() ) * ( comp_controls
[i
].f_resolution
);
1318 ctrl_readout
[i
]->setText( QString::number( f
, 'f', 1 )
1319 + qtr( comp_controls
[i
].psz_units
) );
1320 if( oldControlVars
[i
] != f
)
1324 var_SetFloat( p_aout
, comp_controls
[i
].psz_name
, f
);
1326 config_PutFloat( p_intf
, comp_controls
[i
].psz_name
, f
);
1327 oldControlVars
[i
] = f
;
1332 vlc_object_release( p_aout
);
1336 /**********************************************************************
1338 **********************************************************************/
1341 const char *psz_name
;
1342 const char *psz_desc
;
1345 static const spat_controls_t spat_controls
[] =
1347 { "spatializer-roomsize", _("Size") },
1348 { "spatializer-width", _("Width") },
1349 { "spatializer-wet", _("Wet") },
1350 { "spatializer-dry", _("Dry") },
1351 { "spatializer-damp", _("Damp") },
1354 Spatializer::Spatializer( intf_thread_t
*_p_intf
, QWidget
*_parent
)
1355 : QWidget( _parent
) , p_intf( _p_intf
)
1357 QFont smallFont
= QApplication::font();
1358 smallFont
.setPointSize( smallFont
.pointSize() - 1 );
1360 QGridLayout
*layout
= new QGridLayout( this );
1362 enableCheck
= new QCheckBox( qtr( "Enable spatializer" ) );
1363 layout
->addWidget( enableCheck
, 0, 0, 1, NUM_SP_CTRL
);
1365 for( int i
= 0 ; i
< NUM_SP_CTRL
; i
++ )
1367 spatCtrl
[i
] = new QSlider( Qt::Vertical
);
1368 spatCtrl
[i
]->setValue( (int)var_InheritFloat( p_intf
, spat_controls
[i
].psz_name
) * 10. );
1369 oldControlVars
[i
] = spatCtrl
[i
]->value();
1371 CONNECT( spatCtrl
[i
], valueChanged( int ), this, setInitValues() );
1373 ctrl_texts
[i
] = new QLabel( qtr( spat_controls
[i
].psz_desc
) + "\n" );
1374 ctrl_texts
[i
]->setFont( smallFont
);
1376 ctrl_readout
[i
] = new QLabel
;
1377 ctrl_readout
[i
]->setFont( smallFont
);
1379 layout
->addWidget( spatCtrl
[i
], 1, i
, Qt::AlignHCenter
);
1380 layout
->addWidget( ctrl_readout
[i
], 2, i
, Qt::AlignHCenter
);
1381 layout
->addWidget( ctrl_texts
[i
], 3, i
, Qt::AlignHCenter
);
1382 spatCtrl
[i
]->setRange( 0, 10 );
1384 spatCtrl
[0]->setRange( 0, 11 );
1386 BUTTONACT( enableCheck
, enable() );
1388 /* Write down initial values */
1389 vlc_object_t
*p_aout
= (vlc_object_t
*)THEMIM
->getAout();
1394 psz_af
= var_GetNonEmptyString( p_aout
, "audio-filter" );
1395 for( int i
= 0; i
< NUM_SP_CTRL
; i
++ )
1397 controlVars
[i
] = var_GetFloat( p_aout
, spat_controls
[i
].psz_name
);
1399 vlc_object_release( p_aout
);
1403 psz_af
= config_GetPsz( p_intf
, "audio-filter" );
1404 for( int i
= 0; i
< NUM_SP_CTRL
; i
++ )
1406 controlVars
[i
] = config_GetFloat( p_intf
, spat_controls
[i
].psz_name
);
1409 if( psz_af
&& strstr( psz_af
, "spatializer" ) != NULL
)
1410 enableCheck
->setChecked( true );
1412 enable( enableCheck
->isChecked() );
1416 void Spatializer::enable()
1418 bool en
= enableCheck
->isChecked();
1419 aout_EnableFilter( THEPL
, "spatializer", en
);
1423 void Spatializer::enable( bool en
)
1425 for( int i
= 0 ; i
< NUM_SP_CTRL
; i
++ )
1427 spatCtrl
[i
]->setEnabled( en
);
1428 ctrl_texts
[i
]->setEnabled( en
);
1429 ctrl_readout
[i
]->setEnabled( en
);
1432 void Spatializer::setInitValues()
1437 void Spatializer::setValues()
1439 vlc_object_t
*p_aout
= (vlc_object_t
*)THEMIM
->getAout();
1441 for( int i
= 0 ; i
< NUM_SP_CTRL
; i
++ )
1443 float f
= (float)( spatCtrl
[i
]->value() ) / 10;
1444 ctrl_readout
[i
]->setText( QString::number( f
, 'f', 1 ) );
1449 for( int i
= 0 ; i
< NUM_SP_CTRL
; i
++ )
1451 float f
= (float)( spatCtrl
[i
]->value() ) / 10 ;
1452 if( oldControlVars
[i
] != spatCtrl
[i
]->value() )
1454 var_SetFloat( p_aout
, spat_controls
[i
].psz_name
, f
);
1455 config_PutFloat( p_intf
, spat_controls
[i
].psz_name
, f
);
1456 oldControlVars
[i
] = spatCtrl
[i
]->value();
1459 vlc_object_release( p_aout
);
1463 void Spatializer::delCallbacks( vlc_object_t
*p_aout
)
1465 VLC_UNUSED( p_aout
);
1466 // var_DelCallback( p_aout, "Spatializer-bands", EqzCallback, this );
1467 // var_DelCallback( p_aout, "Spatializer-preamp", EqzCallback, this );
1470 void Spatializer::addCallbacks( vlc_object_t
*p_aout
)
1472 VLC_UNUSED( p_aout
);
1473 // var_AddCallback( p_aout, "Spatializer-bands", EqzCallback, this );
1474 // var_AddCallback( p_aout, "Spatializer-preamp", EqzCallback, this );
1477 #include <QToolButton>
1478 #include <QGridLayout>
1480 #define SUBSDELAY_CFG_MODE "subsdelay-mode"
1481 #define SUBSDELAY_CFG_FACTOR "subsdelay-factor"
1482 #define SUBSDELAY_MODE_ABSOLUTE 0
1483 #define SUBSDELAY_MODE_RELATIVE_SOURCE_DELAY 1
1484 #define SUBSDELAY_MODE_RELATIVE_SOURCE_CONTENT 2
1486 SyncWidget::SyncWidget( QWidget
*_parent
) : QWidget( _parent
)
1488 QHBoxLayout
*layout
= new QHBoxLayout
;
1489 spinBox
.setAlignment( Qt::AlignRight
|Qt::AlignTrailing
|Qt::AlignVCenter
);
1490 spinBox
.setDecimals( 3 );
1491 spinBox
.setMinimum( -600.0 );
1492 spinBox
.setMaximum( 600.0 );
1493 spinBox
.setSingleStep( 0.1 );
1494 spinBox
.setSuffix( " s" );
1495 spinBox
.setButtonSymbols( QDoubleSpinBox::PlusMinus
);
1496 CONNECT( &spinBox
, valueChanged( double ), this, valueChangedHandler( double ) );
1497 layout
->addWidget( &spinBox
);
1498 layout
->addWidget( &spinLabel
);
1499 layout
->setContentsMargins( 0, 0, 0, 0 );
1500 setLayout( layout
);
1503 void SyncWidget::valueChangedHandler( double d
)
1506 spinLabel
.setText( qtr("(Hastened)") );
1508 spinLabel
.setText( qtr("(Delayed)") );
1510 spinLabel
.setText( "" );
1511 emit
valueChanged( d
);
1514 void SyncWidget::setValue( double d
)
1516 spinBox
.setValue( d
);
1519 SyncControls::SyncControls( intf_thread_t
*_p_intf
, QWidget
*_parent
) :
1520 QWidget( _parent
) , p_intf( _p_intf
)
1522 QGroupBox
*AVBox
, *subsBox
;
1523 QToolButton
*updateButton
;
1525 b_userAction
= true;
1527 QGridLayout
*mainLayout
= new QGridLayout( this );
1530 AVBox
= new QGroupBox( qtr( "Audio/Video" ) );
1531 QGridLayout
*AVLayout
= new QGridLayout( AVBox
);
1533 QLabel
*AVLabel
= new QLabel
;
1534 AVLabel
->setText( qtr( "Audio track synchronization:" ) );
1535 AVLayout
->addWidget( AVLabel
, 0, 0, 1, 1 );
1537 AVSpin
= new SyncWidget( this );
1538 AVLayout
->addWidget( AVSpin
, 0, 2, 1, 1 );
1539 mainLayout
->addWidget( AVBox
, 1, 0, 1, 5 );
1542 subsBox
= new QGroupBox( qtr( "Subtitles/Video" ) );
1543 QGridLayout
*subsLayout
= new QGridLayout( subsBox
);
1545 QLabel
*subsLabel
= new QLabel
;
1546 subsLabel
->setText( qtr( "Subtitle track syncronization:" ) );
1547 subsLayout
->addWidget( subsLabel
, 0, 0, 1, 1 );
1549 subsSpin
= new SyncWidget( this );
1550 subsLayout
->addWidget( subsSpin
, 0, 2, 1, 1 );
1552 QLabel
*subSpeedLabel
= new QLabel
;
1553 subSpeedLabel
->setText( qtr( "Subtitles speed:" ) );
1554 subsLayout
->addWidget( subSpeedLabel
, 1, 0, 1, 1 );
1556 subSpeedSpin
= new QDoubleSpinBox
;
1557 subSpeedSpin
->setAlignment( Qt::AlignRight
|Qt::AlignTrailing
|Qt::AlignVCenter
);
1558 subSpeedSpin
->setDecimals( 3 );
1559 subSpeedSpin
->setMinimum( 1 );
1560 subSpeedSpin
->setMaximum( 100 );
1561 subSpeedSpin
->setSingleStep( 0.2 );
1562 subSpeedSpin
->setSuffix( " fps" );
1563 subSpeedSpin
->setButtonSymbols( QDoubleSpinBox::PlusMinus
);
1564 subsLayout
->addWidget( subSpeedSpin
, 1, 2, 1, 1 );
1566 QLabel
*subDurationLabel
= new QLabel
;
1567 subDurationLabel
->setText( qtr( "Subtitles duration factor:" ) );
1568 subsLayout
->addWidget( subDurationLabel
, 2, 0, 1, 1 );
1570 subDurationSpin
= new QDoubleSpinBox
;
1571 subDurationSpin
->setAlignment( Qt::AlignRight
|Qt::AlignTrailing
|Qt::AlignVCenter
);
1572 subDurationSpin
->setDecimals( 3 );
1573 subDurationSpin
->setMinimum( 0 );
1574 subDurationSpin
->setMaximum( 20 );
1575 subDurationSpin
->setSingleStep( 0.2 );
1576 subDurationSpin
->setButtonSymbols( QDoubleSpinBox::PlusMinus
);
1577 subsLayout
->addWidget( subDurationSpin
, 2, 2, 1, 1 );
1579 mainLayout
->addWidget( subsBox
, 2, 0, 2, 5 );
1581 updateButton
= new QToolButton
;
1582 updateButton
->setAutoRaise( true );
1583 mainLayout
->addWidget( updateButton
, 0, 4, 1, 1 );
1585 /* Various Connects */
1586 CONNECT( AVSpin
, valueChanged ( double ), this, advanceAudio( double ) ) ;
1587 CONNECT( subsSpin
, valueChanged ( double ), this, advanceSubs( double ) ) ;
1588 CONNECT( subSpeedSpin
, valueChanged ( double ),
1589 this, adjustSubsSpeed( double ) );
1590 CONNECT( subDurationSpin
, valueChanged ( double ),
1591 this, adjustSubsDuration( double ) );
1593 CONNECT( THEMIM
->getIM(), synchroChanged(), this, update() );
1594 BUTTON_SET_ACT_I( updateButton
, "", update
,
1595 qtr( "Force update of this dialog's values" ), update() );
1603 SyncControls::~SyncControls()
1608 void SyncControls::clean()
1610 b_userAction
= false;
1611 AVSpin
->setValue( 0.0 );
1612 subsSpin
->setValue( 0.0 );
1613 subSpeedSpin
->setValue( 1.0 );
1615 b_userAction
= true;
1618 void SyncControls::update()
1620 b_userAction
= false;
1623 if( THEMIM
->getInput() )
1625 i_delay
= var_GetTime( THEMIM
->getInput(), "audio-delay" );
1626 AVSpin
->setValue( ( (double)i_delay
) / 1000000 );
1627 i_delay
= var_GetTime( THEMIM
->getInput(), "spu-delay" );
1628 subsSpin
->setValue( ( (double)i_delay
) / 1000000 );
1629 subSpeedSpin
->setValue( var_GetFloat( THEMIM
->getInput(), "sub-fps" ) );
1630 subDurationSpin
->setValue( var_InheritFloat( p_intf
, SUBSDELAY_CFG_FACTOR
) );
1632 b_userAction
= true;
1635 void SyncControls::advanceAudio( double f_advance
)
1637 if( THEMIM
->getInput() && b_userAction
)
1639 int64_t i_delay
= f_advance
* 1000000;
1640 var_SetTime( THEMIM
->getInput(), "audio-delay", i_delay
);
1644 void SyncControls::advanceSubs( double f_advance
)
1646 if( THEMIM
->getInput() && b_userAction
)
1648 int64_t i_delay
= f_advance
* 1000000;
1649 var_SetTime( THEMIM
->getInput(), "spu-delay", i_delay
);
1653 void SyncControls::adjustSubsSpeed( double f_fps
)
1655 if( THEMIM
->getInput() && b_userAction
)
1657 var_SetFloat( THEMIM
->getInput(), "sub-fps", f_fps
);
1661 void SyncControls::adjustSubsDuration( double f_factor
)
1663 if( THEMIM
->getInput() && b_userAction
)
1665 subsdelaySetFactor( f_factor
);
1666 ChangeVFiltersString( p_intf
, "subsdelay", f_factor
> 0 );
1670 void SyncControls::initSubsDuration()
1672 int i_mode
= var_InheritInteger( p_intf
, SUBSDELAY_CFG_MODE
);
1677 case SUBSDELAY_MODE_ABSOLUTE
:
1678 subDurationSpin
->setToolTip( qtr( "Extend subtitles duration by this value.\n"
1679 "Set 0 to disable." ) );
1680 subDurationSpin
->setSuffix( " s" );
1682 case SUBSDELAY_MODE_RELATIVE_SOURCE_DELAY
:
1683 subDurationSpin
->setToolTip( qtr( "Multiply subtitles duration by this value.\n"
1684 "Set 0 to disable." ) );
1685 subDurationSpin
->setSuffix( "" );
1687 case SUBSDELAY_MODE_RELATIVE_SOURCE_CONTENT
:
1688 subDurationSpin
->setToolTip( qtr( "Recalculate subtitles duration according\n"
1689 "to their content and this value.\n"
1690 "Set 0 to disable." ) );
1691 subDurationSpin
->setSuffix( "" );
1696 void SyncControls::subsdelayClean()
1698 /* Remove subsdelay filter */
1699 ChangeVFiltersString( p_intf
, "subsdelay", false );
1702 void SyncControls::subsdelaySetFactor( double f_factor
)
1704 /* Set the factor in the preferences */
1705 config_PutFloat( p_intf
, SUBSDELAY_CFG_FACTOR
, f_factor
);
1707 /* Try to find an instance of subsdelay, and set its factor */
1708 vlc_object_t
*p_obj
= ( vlc_object_t
* ) vlc_object_find_name( p_intf
->p_libvlc
, "subsdelay" );
1711 var_SetFloat( p_obj
, SUBSDELAY_CFG_FACTOR
, f_factor
);
1712 vlc_object_release( p_obj
);
1717 /**********************************************************************
1718 * Video filters / Adjust
1719 **********************************************************************/
1721 /**********************************************************************
1722 * Extended playbak controls
1723 **********************************************************************/