Qt: add AV1 in profiles codecs
[vlc.git] / modules / gui / qt / components / sout / profile_selector.cpp
blobe7e5590521bf02240c97c923b3f9e899dfed41e8
1 /*****************************************************************************
2 * profile_selector.cpp : A small profile selector and editor
3 ****************************************************************************
4 * Copyright (C) 2009 the VideoLAN team
5 * $Id$
7 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
25 #include "components/sout/profile_selector.hpp"
26 #include "components/sout/profiles.hpp"
27 #include "dialogs/sout.hpp"
29 #include <QHBoxLayout>
30 #include <QToolButton>
31 #include <QComboBox>
32 #include <QLabel>
33 #include <QMessageBox>
34 #include <QRadioButton>
35 #include <QRegExp>
36 #include <QButtonGroup>
37 #include <QSpinBox>
38 #include <QUrl>
39 #include <QListWidgetItem>
40 #include <QFontMetrics>
42 #include <assert.h>
43 #include <vlc_modules.h>
45 #define CATPROP2NAME( val ) QString("valueholder_%1").arg( val )
46 #define CATANDPROP( cat, prop ) QString("%1_%2").arg( cat ).arg( prop )
47 #define OLDFORMAT "^\\w+;\\d+;\\d+;\\d+;"
49 VLCProfileSelector::VLCProfileSelector( QWidget *_parent ): QWidget( _parent )
51 QHBoxLayout *layout = new QHBoxLayout( this );
53 QLabel *prLabel = new QLabel( qtr( "Profile"), this );
54 layout->addWidget( prLabel );
56 profileBox = new QComboBox( this );
57 layout->addWidget( profileBox );
59 QToolButton *editButton = new QToolButton( this );
60 editButton->setIcon( QIcon( ":/menu/preferences.svg" ) );
61 editButton->setToolTip( qtr( "Edit selected profile" ) );
62 layout->addWidget( editButton );
64 QToolButton *deleteButton = new QToolButton( this );
65 deleteButton->setIcon( QIcon( ":/toolbar/clear.svg" ) );
66 deleteButton->setToolTip( qtr( "Delete selected profile" ) );
67 layout->addWidget( deleteButton );
69 QToolButton *newButton = new QToolButton( this );
70 newButton->setIcon( QIcon( ":/new.svg" ) );
71 newButton->setToolTip( qtr( "Create a new profile" ) );
72 layout->addWidget(newButton);
74 BUTTONACT( newButton, newProfile() );
75 BUTTONACT( editButton, editProfile() );
76 BUTTONACT( deleteButton, deleteProfile() );
77 fillProfilesCombo();
79 CONNECT( profileBox, activated( int ),
80 this, updateOptions( int ) );
81 updateOptions( qMax(profileBox->currentIndex(), 0) );
84 VLCProfileSelector::~VLCProfileSelector()
86 QSettings settings(
87 #ifdef _WIN32
88 QSettings::IniFormat,
89 #else
90 QSettings::NativeFormat,
91 #endif
92 QSettings::UserScope, "vlc", "vlc-qt-interface" );
94 settings.setValue( "codecs-profiles-selected", profileBox->currentText() );
97 inline void VLCProfileSelector::fillProfilesCombo()
99 QSettings settings(
100 #ifdef _WIN32
101 QSettings::IniFormat,
102 #else
103 QSettings::NativeFormat,
104 #endif
105 QSettings::UserScope, "vlc", "vlc-qt-interface" );
107 int i_size = settings.beginReadArray( "codecs-profiles" );
109 for( int i = 0; i < i_size; i++ )
111 settings.setArrayIndex( i );
112 if( settings.value( "Profile-Name" ).toString().isEmpty() ) continue;
113 profileBox->addItem( settings.value( "Profile-Name" ).toString(),
114 settings.value( "Profile-Value" ) );
116 if( i_size == 0 )
118 for( size_t i = 0; i < NB_PROFILE; i++ )
120 profileBox->addItem( video_profile_name_list[i],
121 video_profile_value_list[i] );
124 settings.endArray();
126 profileBox->setCurrentIndex(
127 profileBox->findText(
128 settings.value( "codecs-profiles-selected" ).toString() ));
132 void VLCProfileSelector::newProfile()
134 editProfile( "", "" );
137 void VLCProfileSelector::editProfile()
139 editProfile( profileBox->currentText(),
140 profileBox->itemData( profileBox->currentIndex() ).toString() );
143 void VLCProfileSelector::editProfile( const QString& qs, const QString& value )
145 /* Create the Profile Editor */
146 VLCProfileEditor *editor = new VLCProfileEditor( qs, value, this );
148 /* Show it */
149 if( QDialog::Accepted == editor->exec() )
151 /* New Profile */
152 if( qs.isEmpty() )
153 profileBox->addItem( editor->name, QVariant( editor->transcodeValue() ) );
154 /* Update old profile */
155 else
157 /* Look for the profile */
158 int i_profile = profileBox->findText( qs );
159 assert( i_profile != -1 );
160 profileBox->setItemText( i_profile, editor->name );
161 profileBox->setItemData( i_profile, editor->transcodeValue() );
162 /* Force mrl recreation */
163 updateOptions( i_profile );
166 delete editor;
168 saveProfiles();
169 emit optionsChanged();
172 void VLCProfileSelector::deleteProfile()
174 profileBox->removeItem( profileBox->currentIndex() );
175 saveProfiles();
178 void VLCProfileSelector::saveProfiles()
180 QSettings settings(
181 #ifdef _WIN32
182 QSettings::IniFormat,
183 #else
184 QSettings::NativeFormat,
185 #endif
186 QSettings::UserScope, "vlc", "vlc-qt-interface" );
188 settings.remove( "codecs-profiles" ); /* Erase old profiles to be rewritten */
189 settings.beginWriteArray( "codecs-profiles" );
190 for( int i = 0; i < profileBox->count(); i++ )
192 settings.setArrayIndex( i );
193 settings.setValue( "Profile-Name", profileBox->itemText( i ) );
194 settings.setValue( "Profile-Value", profileBox->itemData( i ).toString() );
196 settings.endArray();
199 void VLCProfileSelector::updateOptions( int i )
201 QString options = profileBox->itemData( i ).toString();
202 QRegExp rx(OLDFORMAT);
203 if ( !options.contains( ";" ) ) return;
204 if ( rx.indexIn( options ) != -1 )
205 return updateOptionsOldFormat( i );
207 transcode = "";
209 QStringList tuples = options.split( ";" );
210 typedef QHash<QString, QString> proptovalueHashType;
211 QHash<QString, proptovalueHashType *> categtopropHash;
212 proptovalueHashType *proptovalueHash;
213 QString value;
215 /* Build a double hash structure because we need to make ordered lookups */
216 foreach ( const QString &tuple, tuples )
218 QStringList keyvalue = tuple.split( "=" );
219 if ( keyvalue.count() != 2 ) continue;
220 QString key = keyvalue[0];
221 value = keyvalue[1];
222 keyvalue = key.split( "_" );
223 if ( keyvalue.count() != 2 ) continue;
224 QString categ = keyvalue[0];
225 QString prop = keyvalue[1];
227 if ( ! categtopropHash.contains( categ ) )
229 proptovalueHash = new proptovalueHashType();
230 categtopropHash.insert( categ, proptovalueHash );
231 } else {
232 proptovalueHash = categtopropHash.value( categ );
234 proptovalueHash->insert( prop, value );
237 /* Now we can build the/translate into MRL */
238 #define HASHPICK( categ, prop ) \
239 if ( categtopropHash.contains( categ ) ) \
241 proptovalueHash = categtopropHash.value( categ );\
242 value = proptovalueHash->take( prop );\
244 else value = QString()
246 SoutMrl smrl;
247 smrl.begin( "transcode" );
249 /* First muxer options */
250 HASHPICK( "muxer", "mux" );
251 if ( value.isEmpty() ) goto cleanup;
252 mux = value;
254 HASHPICK( "video", "enable" );
255 if ( !value.isEmpty() )
257 HASHPICK( "video", "codec" );
259 if ( !value.isEmpty() )
261 smrl.option( "vcodec", value );
263 HASHPICK( "vcodec", "bitrate" );
264 if ( value.toInt() > 0 )
266 smrl.option( "vb", value.toInt() );
269 HASHPICK( "video", "filters" );
270 if ( !value.isEmpty() )
272 QStringList valuesList = QUrl::fromPercentEncoding( value.toLatin1() ).split( ";" );
273 smrl.option( "vfilter", valuesList.join( ":" ) );
276 /*if ( codec is h264 )*/
278 /* special handling */
279 QStringList codecoptions;
281 HASHPICK( "vcodec", "qp" );
282 if( value.toInt() > 0 )
283 codecoptions << QString( "qp=%1" ).arg( value );
285 HASHPICK( "vcodec", "custom" );
286 if( !value.isEmpty() )
287 codecoptions << QUrl::fromPercentEncoding( value.toLatin1() );
289 if ( codecoptions.count() )
290 smrl.option( "venc",
291 QString("x264{%1}").arg( codecoptions.join(",") ) );
294 HASHPICK( "vcodec", "framerate" );
295 if ( !value.isEmpty() && value.toInt() > 0 )
296 smrl.option( "fps", value );
298 HASHPICK( "vcodec", "scale" );
299 if ( !value.isEmpty() )
300 smrl.option( "scale", value );
302 HASHPICK( "vcodec", "width" );
303 if ( !value.isEmpty() && value.toInt() > 0 )
304 smrl.option( "width", value );
306 HASHPICK( "vcodec", "height" );
307 if ( !value.isEmpty() && value.toInt() > 0 )
308 smrl.option( "height", value );
310 } else {
311 smrl.option( "vcodec", "none" );
314 HASHPICK( "audio", "enable" );
315 if ( !value.isEmpty() )
317 HASHPICK( "audio", "codec" );
318 if ( !value.isEmpty() )
320 smrl.option( "acodec", value );
322 HASHPICK( "acodec", "bitrate" );
323 smrl.option( "ab", value.toInt() );
325 HASHPICK( "acodec", "channels" );
326 smrl.option( "channels", value.toInt() );
328 HASHPICK( "acodec", "samplerate" );
329 smrl.option( "samplerate", value.toInt() );
331 HASHPICK( "audio", "filters" );
332 if ( !value.isEmpty() )
334 QStringList valuesList = QUrl::fromPercentEncoding( value.toLatin1() ).split( ";" );
335 smrl.option( "afilter", valuesList.join( ":" ) );
339 } else {
340 smrl.option( "acodec", "none" );
343 HASHPICK( "subtitles", "enable" );
344 if( !value.isEmpty() )
346 HASHPICK( "subtitles", "overlay" );
347 if ( value.isEmpty() )
349 HASHPICK( "subtitles", "codec" );
350 smrl.option( "scodec", value );
352 else
354 smrl.option( "soverlay" );
356 } else {
357 smrl.option( "scodec", "none" );
359 smrl.end();
360 #undef HASHPICK
362 transcode = smrl.getMrl();
364 cleanup:
365 /* Temp hash tables cleanup */
366 foreach( proptovalueHashType *hash, categtopropHash )
367 delete hash;
369 emit optionsChanged();
372 void VLCProfileSelector::updateOptionsOldFormat( int i )
374 QStringList options = profileBox->itemData( i ).toString().split( ";" );
375 if( options.count() < 16 )
376 return;
378 mux = options[0];
380 SoutMrl smrl;
381 if( options[1].toInt() || options[2].toInt() || options[3].toInt() )
383 smrl.begin( "transcode" );
385 if( options[1].toInt() )
387 smrl.option( "vcodec", options[4] );
388 if( options[4] != "none" )
390 smrl.option( "vb", options[5].toInt() );
391 if( !options[7].isEmpty() && options[7].toInt() > 0 )
392 smrl.option( "fps", options[7] );
393 if( !options[6].isEmpty() )
394 smrl.option( "scale", options[6] );
395 if( !options[8].isEmpty() && options[8].toInt() > 0 )
396 smrl.option( "width", options[8].toInt() );
397 if( !options[9].isEmpty() && options[9].toInt() > 0 )
398 smrl.option( "height", options[9].toInt() );
402 if( options[2].toInt() )
404 smrl.option( "acodec", options[10] );
405 if( options[10] != "none" )
407 smrl.option( "ab", options[11].toInt() );
408 smrl.option( "channels", options[12].toInt() );
409 smrl.option( "samplerate", options[13].toInt() );
413 if( options[3].toInt() )
415 smrl.option( "scodec", options[14] );
416 if( options[15].toInt() )
417 smrl.option( "soverlay" );
420 smrl.end();
422 transcode = smrl.getMrl();
424 else
425 transcode = "";
426 emit optionsChanged();
431 * VLCProfileEditor
433 VLCProfileEditor::VLCProfileEditor( const QString& qs_name, const QString& value,
434 QWidget *_parent )
435 : QVLCDialog( _parent, NULL )
437 ui.setupUi( this );
438 ui.buttonGroup->setObjectName( CATPROP2NAME( CATANDPROP( "muxer", "mux" ) ) );
439 if( !qs_name.isEmpty() )
441 ui.profileLine->setText( qs_name );
442 ui.profileLine->setReadOnly( true );
444 loadCapabilities();
445 registerCodecs();
446 registerFilters();
448 QPushButton *saveButton = new QPushButton(
449 ( qs_name.isEmpty() ) ? qtr( "Create" ) : qtr( "Save" ) );
450 ui.buttonBox->addButton( saveButton, QDialogButtonBox::AcceptRole );
451 BUTTONACT( saveButton, close() );
452 QPushButton *cancelButton = new QPushButton( qtr( "Cancel" ) );
453 ui.buttonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
454 BUTTONACT( cancelButton, reject() );
456 CONNECT( ui.valueholder_video_copy, stateChanged( int ),
457 this, activatePanels() );
458 CONNECT( ui.valueholder_audio_copy, stateChanged( int ),
459 this, activatePanels() );
460 CONNECT( ui.valueholder_subtitles_overlay, stateChanged( int ),
461 this, activatePanels() );
462 CONNECT( ui.valueholder_vcodec_bitrate, editingFinished( ),
463 this, fixBirateState() );
464 CONNECT( ui.valueholder_vcodec_qp, editingFinished( ),
465 this, fixQPState() );
466 CONNECT( ui.valueholder_video_codec, currentIndexChanged( int ),
467 this, codecSelected() );
468 reset();
470 fillProfile( value );
471 muxSelected();
472 codecSelected();
475 void VLCProfileEditor::loadCapabilities()
477 size_t count;
478 module_t **p_all = module_list_get (&count);
480 /* Parse the module list for capabilities and probe each of them */
481 for (size_t i = 0; i < count; i++)
483 module_t *p_module = p_all[i];
485 if( module_provides( p_module, "sout mux" ) )
486 caps["muxers"].insert( module_get_object( p_module ) );
487 // else if ( module_provides( p_module, "encoder" ) )
488 // caps["encoders"].insert( module_get_object( p_module ) );
490 module_list_free (p_all);
493 inline void VLCProfileEditor::registerFilters()
495 size_t count;
496 module_t **p_all = module_list_get (&count);
498 for (size_t i = 0; i < count; i++)
500 module_t *p_module = p_all[i];
501 if ( module_get_score( p_module ) > 0 ) continue;
503 QString capability = module_get_capability( p_module );
504 QListWidget *listWidget = NULL;
505 QListWidgetItem *item;
507 if ( capability == "video filter" )
508 listWidget = ui.valueholder_video_filters;
509 else if ( capability == "audio filter" )
510 listWidget = ui.valueholder_audio_filters;
512 if ( !listWidget ) continue;
514 item = new QListWidgetItem( module_get_name( p_module, true ) );
515 item->setCheckState( Qt::Unchecked );
516 item->setToolTip( QString( module_get_help( p_module ) ) );
517 item->setData( Qt::UserRole, QString( module_get_object( p_module ) ) );
518 listWidget->addItem( item );
520 module_list_free (p_all);
522 ui.valueholder_video_filters->sortItems();
523 ui.valueholder_audio_filters->sortItems();
526 inline void VLCProfileEditor::registerCodecs()
528 #define SETMUX( button, val, mod, vid, aud, men, sub, stream, chaps ) \
529 ui.button->setProperty( "sout", val );\
530 ui.button->setProperty( "module", mod );\
531 ui.button->setProperty( "capvideo", vid );\
532 ui.button->setProperty( "capaudio", aud );\
533 ui.button->setProperty( "capmenu", men );\
534 ui.button->setProperty( "capsubs", sub );\
535 ui.button->setProperty( "capstream", stream );\
536 ui.button->setProperty( "capchaps", chaps );\
537 CONNECT( ui.button, clicked(bool), this, muxSelected() );
538 SETMUX( PSMux, "ps", "ps", true, true, false, true, false, true )
539 SETMUX( TSMux, "ts", "ts", true, true, false, true, true, false )
540 SETMUX( WEBMux, "webm", "avformat", true, true, false, false, true, false )
541 SETMUX( MPEG1Mux, "mpeg1", "ps", true, true, false, false, false, false )
542 SETMUX( OggMux, "ogg", "ogg", true, true, false, false, true, true )
543 SETMUX( ASFMux, "asf", "asf", true, true, false, true, true, true )
544 SETMUX( MOVMux, "mp4", "mp4", true, true, true, true, true, false )
545 SETMUX( WAVMux, "wav", "wav", false, true, false, false, false, false )
546 SETMUX( FLACMux, "flac", "dummy", false, true, false, false, false, false )
547 SETMUX( MP3Mux, "mp3", "dummy", false, true, false, false, false, false )
548 SETMUX( RAWMux, "raw", "dummy", true, true, false, false, false, false )
549 SETMUX( FLVMux, "flv", "avformat", true, true, false, false, true, false )
550 SETMUX( MKVMux, "mkv", "avformat", true, true, true, true, true, true )
551 SETMUX( AVIMux, "avi", "avi", true, true, false, false, false, false )
552 SETMUX( MJPEGMux, "mpjpeg", "mpjpeg", true, false, false, false, false, false )
553 #undef SETMUX
555 #define ADD_VCODEC( name, fourcc ) \
556 ui.valueholder_video_codec->addItem( name, QVariant( fourcc ) );
557 ADD_VCODEC( "MPEG-1", "mp1v" )
558 ADD_VCODEC( "MPEG-2", "mp2v" )
559 ADD_VCODEC( "MPEG-4", "mp4v" )
560 ADD_VCODEC( "DIVX 1" , "DIV1" )
561 ADD_VCODEC( "DIVX 2" , "DIV2" )
562 ADD_VCODEC( "DIVX 3" , "DIV3" )
563 ADD_VCODEC( "H-263", "H263" )
564 ADD_VCODEC( "H-264 (AVC)", "h264" )
565 ADD_VCODEC( "H-265 (HEVC)", "hevc" )
566 ADD_VCODEC( "AV1", "av01" )
567 ADD_VCODEC( "VP8", "VP80" )
568 ADD_VCODEC( "WMV1", "WMV1" )
569 ADD_VCODEC( "WMV2" , "WMV2" )
570 ADD_VCODEC( "M-JPEG", "MJPG" )
571 ADD_VCODEC( "Theora", "theo" )
572 #undef ADD_VCODEC
573 /* can do quality */
574 qpcodecsList << "h264";
576 #define ADD_ACODEC( name, fourcc ) ui.valueholder_audio_codec->addItem( name, QVariant( fourcc ) );
577 ADD_ACODEC( "MPEG Audio", "mpga" )
578 ADD_ACODEC( "MP3", "mp3" )
579 ADD_ACODEC( "MPEG 4 Audio ( AAC )", "mp4a" )
580 ADD_ACODEC( "A52/AC-3", "a52" )
581 ADD_ACODEC( "Vorbis", "vorb" )
582 ADD_ACODEC( "Flac", "flac" )
583 ADD_ACODEC( "Opus", "opus" )
584 ADD_ACODEC( "Speex", "spx" )
585 ADD_ACODEC( "WAV", "s16l" )
586 ADD_ACODEC( "WMA2", "wma2" )
587 #undef ADD_ACODEC
589 #define ADD_SCALING( factor ) ui.valueholder_vcodec_scale->addItem( factor );
590 ADD_SCALING( qtr("Auto") );
591 ADD_SCALING( "1" )
592 ADD_SCALING( "0.25" )
593 ADD_SCALING( "0.5" )
594 ADD_SCALING( "0.75" )
595 ADD_SCALING( "1.25" )
596 ADD_SCALING( "1.5" )
597 ADD_SCALING( "1.75" )
598 ADD_SCALING( "2" )
599 #undef ADD_SCALING
601 #define ADD_SAMPLERATE( sample, val ) ui.valueholder_acodec_samplerate->addItem( sample, val );
602 ADD_SAMPLERATE( "8000 Hz", 8000 )
603 ADD_SAMPLERATE( "11025 Hz", 11025 )
604 ADD_SAMPLERATE( "22050 Hz", 22050 )
605 ADD_SAMPLERATE( "44100 Hz", 44100 )
606 ADD_SAMPLERATE( "48000 Hz", 48000 )
607 #undef ADD_SAMPLERATE
609 #define ADD_SCODEC( name, fourcc ) ui.valueholder_subtitles_codec->addItem( name, QVariant( fourcc ) );
610 ADD_SCODEC( "DVBS (DVB subtitles)", "dvbs" )
611 ADD_SCODEC( "tx3g (MPEG-4 timed text)", "tx3g" )
612 ADD_SCODEC( "T-REC 140 (for rtp)", "t140" )
613 #undef ADD_SCODEC
616 void VLCProfileEditor::muxSelected()
618 QRadioButton *current =
619 qobject_cast<QRadioButton *>( ui.buttonGroup->checkedButton() );
621 #define SETYESNOSTATE( name, prop ) \
622 ui.name->setChecked( current->property( prop ).toBool() )
624 /* dumb :/ */
625 SETYESNOSTATE( capvideo, "capvideo" );
626 SETYESNOSTATE( capaudio, "capaudio" );
627 SETYESNOSTATE( capmenu, "capmenu" );
628 SETYESNOSTATE( capsubs, "capsubs" );
629 SETYESNOSTATE( capstream, "capstream" );
630 SETYESNOSTATE( capchaps, "capchaps" );
632 int textsize = QFontMetrics(ui.muxerwarning->font()).ascent();
633 if( current->property("module").toString() == "avformat" )
634 ui.muxerwarning->setText(
635 QString( "<img src=\":/menu/info.svg\" width=%2 height=%2/> %1" )
636 .arg( qtr( "This muxer is not provided directly by VLC: It could be missing." ) )
637 .arg(textsize)
639 else if ( !caps["muxers"].contains( current->property("module").toString() ) &&
640 !caps["muxers"].contains( "mux_" + current->property("module").toString() ) )
641 ui.muxerwarning->setText(
642 QString( "<img src=\":/toobar/clear.svg\" width=%2 height=%2/> %1" )
643 .arg( qtr( "This muxer is missing. Using this profile will fail" ) )
644 .arg(textsize)
646 else
647 ui.muxerwarning->setText("");
648 return;
650 #undef SETYESNOSTATE
653 void VLCProfileEditor::codecSelected()
655 /* Enable quality preset */
656 QString currentcodec = ui.valueholder_video_codec->
657 itemData(ui.valueholder_video_codec->currentIndex() ).toString();
658 ui.valueholder_vcodec_qp->setEnabled( qpcodecsList.contains( currentcodec ) );
661 void VLCProfileEditor::fillProfile( const QString& qs )
663 QRegExp rx(OLDFORMAT);
664 if ( rx.indexIn( qs ) != -1 ) return fillProfileOldFormat( qs );
666 QStringList tuples = qs.split( ";" );
667 foreach ( const QString &tuple, tuples )
669 QStringList keyvalue = tuple.split( "=" );
670 if ( keyvalue.count() != 2 ) continue;
671 QString key = keyvalue[0];
672 QString value = keyvalue[1];
673 QObject *object = findChild<QObject *>( CATPROP2NAME( key ) );
674 if ( object )
676 if( object->inherits( "QButtonGroup" ) )
677 { /* Buttongroup for Radios */
678 const QButtonGroup *group = qobject_cast<const QButtonGroup *>( object );
679 foreach( QAbstractButton *button, group->buttons() )
681 if ( button->property("sout").toString() == value )
683 button->setChecked( true );
684 break;/* radios are exclusive */
688 else if( object->inherits( "QCheckBox" ) )
690 QCheckBox *box = qobject_cast<QCheckBox *>( object );
691 box->setChecked( ! value.isEmpty() );
693 else if( object->inherits( "QGroupBox" ) )
695 QGroupBox *box = qobject_cast<QGroupBox *>( object );
696 box->setChecked( ! value.isEmpty() );
698 else if( object->inherits( "QSpinBox" ) )
700 QSpinBox *box = qobject_cast<QSpinBox *>( object );
701 box->setValue( value.toInt() );
703 else if( object->inherits( "QDoubleSpinBox" ) )
705 QDoubleSpinBox *box = qobject_cast<QDoubleSpinBox *>( object );
706 box->setValue( value.toDouble() );
708 else if( object->inherits( "QComboBox" ) )
710 QComboBox *box = qobject_cast<QComboBox *>( object );
711 box->setCurrentIndex( box->findData( value ) );
712 if ( box->lineEdit() && box->currentIndex() == -1 )
713 box->lineEdit()->setText( value );
715 else if( object->inherits( "QLineEdit" ) )
717 QLineEdit *box = qobject_cast<QLineEdit *>( object );
718 box->setText( QUrl::fromPercentEncoding( value.toLatin1() ) );
720 else if ( object->inherits( "QListWidget" ) )
722 QStringList valuesList = QUrl::fromPercentEncoding( value.toLatin1() ).split( ";" );
723 const QListWidget *list = qobject_cast<const QListWidget *>( object );
724 for( int i=0; i < list->count(); i++ )
726 QListWidgetItem *item = list->item( i );
727 if ( valuesList.contains( item->data( Qt::UserRole ).toString() ) )
728 item->setCheckState( Qt::Checked );
729 else
730 item->setCheckState( Qt::Unchecked );
737 void VLCProfileEditor::fillProfileOldFormat( const QString& qs )
739 QStringList options = qs.split( ";" );
740 if( options.count() < 16 )
741 return;
743 const QString mux = options[0];
744 for ( int i=0; i< ui.muxer->layout()->count(); i++ )
746 QRadioButton *current =
747 qobject_cast<QRadioButton *>(ui.muxer->layout()->itemAt(i)->widget());
748 if ( unlikely( !current ) ) continue;/* someone is messing up with ui */
749 if ( current->property("sout").toString() == mux )
751 current->setChecked( true );
752 break;/* radios are exclusive */
756 ui.valueholder_video_copy->setChecked( !options[1].toInt() );
757 ui.valueholder_video_enable->setChecked( ( options[4] != "none" ) );
758 ui.valueholder_audio_copy->setChecked( !options[2].toInt() );
759 ui.valueholder_audio_enable->setChecked( ( options[10] != "none" ) );
760 ui.valueholder_subtitles_enable->setChecked( options[3].toInt() );
762 ui.valueholder_video_codec->setCurrentIndex( ui.valueholder_video_codec->findData( options[4] ) );
763 ui.valueholder_vcodec_bitrate->setValue( options[5].toInt() );
764 if ( options[6].toInt() > 0 )
765 ui.valueholder_vcodec_scale->setEditText( options[6] );
766 else
767 ui.valueholder_vcodec_scale->setCurrentIndex( 0 );
768 ui.valueholder_vcodec_framerate->setValue( options[7].toDouble() );
769 ui.valueholder_vcodec_width->setValue( options[8].toInt() );
770 ui.valueholder_vcodec_height->setValue( options[9].toInt() );
772 ui.valueholder_audio_codec->setCurrentIndex( ui.valueholder_audio_codec->findData( options[10] ) );
773 ui.valueholder_acodec_bitrate->setValue( options[11].toInt() );
774 ui.valueholder_acodec_channels->setValue( options[12].toInt() );
776 int index = ui.valueholder_acodec_samplerate->findData( options[13] );
777 if ( index == -1 ) index = ui.valueholder_acodec_samplerate->findData( 44100 );
778 ui.valueholder_acodec_samplerate->setCurrentIndex( index );
780 ui.valueholder_subtitles_codec->setCurrentIndex( ui.valueholder_subtitles_codec->findData( options[14] ) );
781 ui.valueholder_subtitles_overlay->setChecked( options[15].toInt() );
784 void VLCProfileEditor::close()
786 if( ui.profileLine->text().isEmpty() )
788 QMessageBox::warning( this, qtr(" Profile Name Missing" ),
789 qtr( "You must set a name for the profile." ) );
790 ui.profileLine->setFocus();
791 return;
793 name = ui.profileLine->text();
795 accept();
798 #define currentData( box ) box->itemData( box->currentIndex() )
800 QString VLCProfileEditor::transcodeValue()
802 QList<QObject *> allwidgets = findChildren<QObject *>();
803 QStringList configuration;
805 foreach( const QObject *object, allwidgets )
807 if ( ! object->objectName().startsWith( CATPROP2NAME( "" ) ) )
808 continue;
809 if ( object->inherits( "QWidget" ) &&
810 ! qobject_cast<const QWidget *>(object)->isEnabled() ) continue;
812 QString name = object->objectName();
813 QStringList vals = object->objectName().split( "_" );
814 if ( vals.count() != 3 ) continue;
815 QString &categ = vals[1];
816 QString &prop = vals[2];
817 QString value;
819 if( object->inherits( "QButtonGroup" ) )
821 const QButtonGroup *group = qobject_cast<const QButtonGroup *>( object );
822 value = group->checkedButton()->property( "sout" ).toString();
824 else if( object->inherits( "QCheckBox" ) )
826 const QCheckBox *box = qobject_cast<const QCheckBox *>( object );
827 value = box->isChecked() ? "yes" : "";
829 else if( object->inherits( "QGroupBox" ) )
831 const QGroupBox *box = qobject_cast<const QGroupBox *>( object );
832 value = box->isChecked() ? "yes" : "";
834 else if( object->inherits( "QSpinBox" ) )
836 const QSpinBox *box = qobject_cast<const QSpinBox *>( object );
837 value = QString::number( box->value() );
839 else if( object->inherits( "QDoubleSpinBox" ) )
841 const QDoubleSpinBox *box = qobject_cast<const QDoubleSpinBox *>( object );
842 value = QString::number( box->value() );
844 else if( object->inherits( "QComboBox" ) )
846 const QComboBox *box = qobject_cast<const QComboBox *>( object );
847 value = currentData( box ).toString();
848 if ( value.isEmpty() && box->lineEdit() ) value = box->lineEdit()->text();
850 else if( object->inherits( "QLineEdit" ) )
852 const QLineEdit *box = qobject_cast<const QLineEdit *>( object );
853 value = QUrl::toPercentEncoding( box->text(), "", "_;" );
855 else if ( object->inherits( "QListWidget" ) )
857 const QListWidget *list = qobject_cast<const QListWidget *>( object );
858 QStringList valuesList;
859 for( int i=0; i < list->count(); i++ )
861 const QListWidgetItem *item = list->item( i );
862 if ( item->checkState() == Qt::Checked )
863 valuesList.append( item->data( Qt::UserRole ).toString() );
865 value = QUrl::toPercentEncoding( valuesList.join( ";" ), "", "_;" );
868 if ( !value.isEmpty() )
869 configuration << QString( "%1_%2=%3" )
870 .arg( categ ).arg( prop ).arg( value );
873 return configuration.join( ";" );
876 void VLCProfileEditor::reset()
878 /* reset to default state as we can only check/enable existing values */
879 ui.valueholder_video_copy->setChecked( false );
880 ui.valueholder_audio_copy->setChecked( false );
881 activatePanels();
882 fixBirateState(); /* defaults to bitrate, not qp */
883 /* end with top level ones for cascaded setEnabled() */
884 ui.valueholder_video_enable->setChecked( false );
885 ui.valueholder_audio_enable->setChecked( false );
886 ui.valueholder_subtitles_enable->setChecked( false );
889 void VLCProfileEditor::activatePanels()
891 ui.transcodevideo->setEnabled( ! ui.valueholder_video_copy->isChecked() );
892 ui.transcodeaudio->setEnabled( ! ui.valueholder_audio_copy->isChecked() );
893 ui.valueholder_subtitles_codec->setEnabled( ! ui.valueholder_subtitles_overlay->isChecked() );
896 void VLCProfileEditor::fixBirateState()
898 /* exclusive bitrate choice */
899 ui.valueholder_vcodec_qp->setValue( 0 );
902 void VLCProfileEditor::fixQPState()
904 /* exclusive bitrate choice */
905 ui.valueholder_vcodec_bitrate->setValue( 0 );
908 #undef CATPROP2NAME
909 #undef CATANDPROP
910 #undef OLDFORMAT