]> git.sesse.net Git - vlc/blob - modules/gui/qt4/components/sout/profile_selector.cpp
Use _WIN32 rather than WIN32 (same for WIN64)
[vlc] / modules / gui / qt4 / components / sout / profile_selector.cpp
1 /*****************************************************************************
2  * profile_selector.cpp : A small profile selector and editor
3  ****************************************************************************
4  * Copyright (C) 2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jean-Baptiste Kempf <jb@videolan.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24
25 #include "components/sout/profile_selector.hpp"
26 #include "components/sout/profiles.hpp"
27 #include "dialogs/sout.hpp"
28
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
41 #include <assert.h>
42 #include <vlc_modules.h>
43
44 #define CATPROP2NAME( val ) QString("valueholder_%1").arg( val )
45 #define CATANDPROP( cat, prop ) QString("%1_%2").arg( cat ).arg( prop )
46 #define OLDFORMAT "^\\w+;\\d+;\\d+;\\d+;"
47
48 VLCProfileSelector::VLCProfileSelector( QWidget *_parent ): QWidget( _parent )
49 {
50     QHBoxLayout *layout = new QHBoxLayout( this );
51
52     QLabel *prLabel = new QLabel( qtr( "Profile"), this );
53     layout->addWidget( prLabel );
54
55     profileBox = new QComboBox( this );
56     layout->addWidget( profileBox );
57
58     QToolButton *editButton = new QToolButton( this );
59     editButton->setIcon( QIcon( ":/menu/preferences" ) );
60     editButton->setToolTip( qtr( "Edit selected profile" ) );
61     layout->addWidget( editButton );
62
63     QToolButton *deleteButton = new QToolButton( this );
64     deleteButton->setIcon( QIcon( ":/toolbar/clear" ) );
65     deleteButton->setToolTip( qtr( "Delete selected profile" ) );
66     layout->addWidget( deleteButton );
67
68     QToolButton *newButton = new QToolButton( this );
69     newButton->setIcon( QIcon( ":/new" ) );
70     newButton->setToolTip( qtr( "Create a new profile" ) );
71     layout->addWidget(newButton);
72
73     BUTTONACT( newButton, newProfile() );
74     BUTTONACT( editButton, editProfile() );
75     BUTTONACT( deleteButton, deleteProfile() );
76     fillProfilesCombo();
77
78     CONNECT( profileBox, activated( int ),
79              this, updateOptions( int ) );
80     updateOptions( 0 );
81 }
82
83 inline void VLCProfileSelector::fillProfilesCombo()
84 {
85     QSettings settings(
86 #ifdef _WIN32
87             QSettings::IniFormat,
88 #else
89             QSettings::NativeFormat,
90 #endif
91             QSettings::UserScope, "vlc", "vlc-qt-interface" );
92
93     int i_size = settings.beginReadArray( "codecs-profiles" );
94
95     for( int i = 0; i < i_size; i++ )
96     {
97         settings.setArrayIndex( i );
98         if( settings.value( "Profile-Name" ).toString().isEmpty() ) continue;
99         profileBox->addItem( settings.value( "Profile-Name" ).toString(),
100                 settings.value( "Profile-Value" ) );
101     }
102     if( i_size == 0 )
103     {
104         for( size_t i = 0; i < NB_PROFILE; i++ )
105         {
106             profileBox->addItem( video_profile_name_list[i],
107                                  video_profile_value_list[i] );
108         }
109     }
110     settings.endArray();
111 }
112
113 void VLCProfileSelector::newProfile()
114 {
115     editProfile( "", "" );
116 }
117
118 void VLCProfileSelector::editProfile()
119 {
120     editProfile( profileBox->currentText(),
121                  profileBox->itemData( profileBox->currentIndex() ).toString() );
122 }
123
124 void VLCProfileSelector::editProfile( const QString& qs, const QString& value )
125 {
126     /* Create the Profile Editor */
127     VLCProfileEditor *editor = new VLCProfileEditor( qs, value, this );
128
129     /* Show it */
130     if( QDialog::Accepted == editor->exec() )
131     {
132         /* New Profile */
133         if( qs.isEmpty() )
134             profileBox->addItem( editor->name, QVariant( editor->transcodeValue() ) );
135         /* Update old profile */
136         else
137         {
138             /* Look for the profile */
139             int i_profile = profileBox->findText( qs );
140             assert( i_profile != -1 );
141             profileBox->setItemText( i_profile, editor->name );
142             profileBox->setItemData( i_profile, editor->transcodeValue() );
143             /* Force mrl recreation */
144             updateOptions( i_profile );
145         }
146     }
147     delete editor;
148
149     saveProfiles();
150     emit optionsChanged();
151 }
152
153 void VLCProfileSelector::deleteProfile()
154 {
155     profileBox->removeItem( profileBox->currentIndex() );
156     saveProfiles();
157 }
158
159 void VLCProfileSelector::saveProfiles()
160 {
161     QSettings settings(
162 #ifdef _WIN32
163             QSettings::IniFormat,
164 #else
165             QSettings::NativeFormat,
166 #endif
167             QSettings::UserScope, "vlc", "vlc-qt-interface" );
168
169     settings.remove( "codecs-profiles" ); /* Erase old profiles to be rewritten */
170     settings.beginWriteArray( "codecs-profiles" );
171     for( int i = 0; i < profileBox->count(); i++ )
172     {
173         settings.setArrayIndex( i );
174         settings.setValue( "Profile-Name", profileBox->itemText( i ) );
175         settings.setValue( "Profile-Value", profileBox->itemData( i ).toString() );
176     }
177     settings.endArray();
178 }
179
180 void VLCProfileSelector::updateOptions( int i )
181 {
182     QString options = profileBox->itemData( i ).toString();
183     QRegExp rx(OLDFORMAT);
184     if ( !options.contains( ";" ) ) return;
185     if ( rx.indexIn( options ) != -1 )
186         return updateOptionsOldFormat( i );
187
188     transcode = "";
189
190     QStringList tuples = options.split( ";" );
191     typedef QHash<QString, QString> proptovalueHashType;
192     QHash<QString, proptovalueHashType *> categtopropHash;
193     proptovalueHashType *proptovalueHash;
194     QString value;
195
196     /* Build a double hash structure because we need to make ordered lookups */
197     foreach ( const QString &tuple, tuples )
198     {
199         QStringList keyvalue = tuple.split( "=" );
200         if ( keyvalue.count() != 2 ) continue;
201         QString key = keyvalue[0];
202         value = keyvalue[1];
203         keyvalue = key.split( "_" );
204         if ( keyvalue.count() != 2 ) continue;
205         QString categ = keyvalue[0];
206         QString prop = keyvalue[1];
207
208         if ( ! categtopropHash.contains( categ ) )
209         {
210             proptovalueHash = new proptovalueHashType();
211             categtopropHash.insert( categ, proptovalueHash );
212         } else {
213             proptovalueHash = categtopropHash.value( categ );
214         }
215         proptovalueHash->insert( prop, value );
216     }
217
218     /* Now we can build the/translate into MRL */
219 #define HASHPICK( categ, prop ) \
220     if ( categtopropHash.contains( categ ) ) \
221     {\
222         proptovalueHash = categtopropHash.value( categ );\
223         value = proptovalueHash->take( prop );\
224     }\
225     else value = QString()
226
227     SoutMrl smrl;
228     smrl.begin( "transcode" );
229
230     /* First muxer options */
231     HASHPICK( "muxer", "mux" );
232     if ( value.isEmpty() ) goto cleanup;
233     mux = value;
234
235     HASHPICK( "video", "enable" );
236     if ( !value.isEmpty() )
237     {
238         HASHPICK( "video", "codec" );
239
240         if ( !value.isEmpty() )
241         {
242             smrl.option( "vcodec", value );
243
244             HASHPICK( "vcodec", "bitrate" );
245             if ( value.toInt() > 0 )
246             {
247                 smrl.option( "vb", value.toInt() );
248             }
249
250             HASHPICK( "video", "filters" );
251             if ( !value.isEmpty() )
252             {
253                 QStringList valuesList = QUrl::fromPercentEncoding( value.toAscii() ).split( ";" );
254                 smrl.option( "vfilter", valuesList.join( ":" ) );
255             }
256
257             /*if ( codec is h264 )*/
258             {
259                 /* special handling */
260                 QStringList codecoptions;
261
262                 HASHPICK( "vcodec", "qp" );
263                 if( value.toInt() > 0 )
264                     codecoptions << QString( "qp=%1" ).arg( value );
265
266                 HASHPICK( "vcodec", "custom" );
267                 if( !value.isEmpty() )
268                     codecoptions << QUrl::fromPercentEncoding( value.toAscii() );
269
270                 if ( codecoptions.count() )
271                     smrl.option( "venc",
272                         QString("x264{%1}").arg( codecoptions.join(",") ) );
273             }
274
275             HASHPICK( "vcodec", "framerate" );
276             if ( !value.isEmpty() && value.toInt() > 0 )
277                 smrl.option( "fps", value );
278
279             HASHPICK( "vcodec", "scale" );
280             if ( !value.isEmpty() )
281                 smrl.option( "scale", value );
282
283             HASHPICK( "vcodec", "width" );
284             if ( !value.isEmpty() && value.toInt() > 0 )
285                 smrl.option( "width", value );
286
287             HASHPICK( "vcodec", "height" );
288             if ( !value.isEmpty() && value.toInt() > 0 )
289                 smrl.option( "height", value );
290         } else {
291             HASHPICK( "video", "copy" );
292             if ( ! value.isEmpty() )
293                 smrl.option( "vcodec", "copy" );
294         }
295     } else {
296         smrl.option( "vcodec", "none" );
297     }
298
299     HASHPICK( "audio", "enable" );
300     if ( !value.isEmpty() )
301     {
302         HASHPICK( "audio", "codec" );
303         if ( !value.isEmpty() )
304         {
305             smrl.option( "acodec", value );
306
307             HASHPICK( "acodec", "bitrate" );
308             smrl.option( "ab", value.toInt() );
309
310             HASHPICK( "acodec", "channels" );
311             smrl.option( "channels", value.toInt() );
312
313             HASHPICK( "acodec", "samplerate" );
314             smrl.option( "samplerate", value.toInt() );
315
316             HASHPICK( "audio", "filters" );
317             if ( !value.isEmpty() )
318             {
319                 QStringList valuesList = QUrl::fromPercentEncoding( value.toAscii() ).split( ";" );
320                 smrl.option( "afilter", valuesList.join( ":" ) );
321             }
322
323         } else {
324             HASHPICK( "audio", "copy" );
325             if ( ! value.isEmpty() )
326                 smrl.option( "acodec", "copy" );
327         }
328     } else {
329         smrl.option( "acodec", "none" );
330     }
331
332     HASHPICK( "subtitles", "enable" );
333     if( !value.isEmpty() )
334     {
335         HASHPICK( "subtitles", "codec" );
336         smrl.option( "scodec", value );
337
338         HASHPICK( "subtitles", "overlay" );
339         if ( !value.isEmpty() )
340             smrl.option( "soverlay" );
341     }
342     smrl.end();
343 #undef HASHPICK
344
345     transcode = smrl.getMrl();
346
347     cleanup:
348     /* Temp hash tables cleanup */
349     foreach( proptovalueHashType *hash, categtopropHash )
350         delete hash;
351
352     emit optionsChanged();
353 }
354
355 void VLCProfileSelector::updateOptionsOldFormat( int i )
356 {
357     QStringList options = profileBox->itemData( i ).toString().split( ";" );
358     if( options.count() < 16 )
359         return;
360
361     mux = options[0];
362
363     SoutMrl smrl;
364     if( options[1].toInt() || options[2].toInt() || options[3].toInt() )
365     {
366         smrl.begin( "transcode" );
367
368         if( options[1].toInt() )
369         {
370             smrl.option( "vcodec", options[4] );
371             if( options[4] != "none" )
372             {
373                 smrl.option( "vb", options[5].toInt() );
374                 if( !options[7].isEmpty() && options[7].toInt() > 0 )
375                     smrl.option( "fps", options[7] );
376                 if( !options[6].isEmpty() )
377                     smrl.option( "scale", options[6] );
378                 if( !options[8].isEmpty() && options[8].toInt() > 0 )
379                     smrl.option( "width", options[8].toInt() );
380                 if( !options[9].isEmpty() && options[9].toInt() > 0 )
381                     smrl.option( "height", options[9].toInt() );
382             }
383         }
384
385         if( options[2].toInt() )
386         {
387             smrl.option( "acodec", options[10] );
388             if( options[10] != "none" )
389             {
390                 smrl.option( "ab", options[11].toInt() );
391                 smrl.option( "channels", options[12].toInt() );
392                 smrl.option( "samplerate", options[13].toInt() );
393             }
394         }
395
396         if( options[3].toInt() )
397         {
398             smrl.option( "scodec", options[14] );
399             if( options[15].toInt() )
400                 smrl.option( "soverlay" );
401         }
402
403         smrl.end();
404
405         transcode = smrl.getMrl();
406     }
407     else
408         transcode = "";
409     emit optionsChanged();
410 }
411
412
413 /**
414  * VLCProfileEditor
415  **/
416 VLCProfileEditor::VLCProfileEditor( const QString& qs_name, const QString& value,
417         QWidget *_parent )
418                  : QVLCDialog( _parent, NULL )
419 {
420     ui.setupUi( this );
421     ui.buttonGroup->setObjectName( CATPROP2NAME( CATANDPROP( "muxer", "mux" ) ) );
422     if( !qs_name.isEmpty() )
423     {
424         ui.profileLine->setText( qs_name );
425         ui.profileLine->setReadOnly( true );
426     }
427     loadCapabilities();
428     registerCodecs();
429     registerFilters();
430
431     QPushButton *saveButton = new QPushButton(
432                 ( qs_name.isEmpty() ) ? qtr( "Create" ) : qtr( "Save" ) );
433     ui.buttonBox->addButton( saveButton, QDialogButtonBox::AcceptRole );
434     BUTTONACT( saveButton, close() );
435     QPushButton *cancelButton = new QPushButton( qtr( "Cancel" ) );
436     ui.buttonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
437     BUTTONACT( cancelButton, reject() );
438
439     CONNECT( ui.valueholder_video_copy, stateChanged( int ),
440              this, activatePanels() );
441     CONNECT( ui.valueholder_audio_copy, stateChanged( int ),
442              this, activatePanels() );
443     CONNECT( ui.valueholder_vcodec_bitrate, editingFinished( ),
444              this, fixBirateState() );
445     CONNECT( ui.valueholder_vcodec_qp, editingFinished( ),
446              this, fixQPState() );
447     CONNECT( ui.valueholder_video_codec, currentIndexChanged( int ),
448              this, codecSelected() );
449     reset();
450
451     fillProfile( value );
452     muxSelected();
453     codecSelected();
454 }
455
456 void VLCProfileEditor::loadCapabilities()
457 {
458     size_t count;
459     module_t **p_all = module_list_get (&count);
460
461     /* Parse the module list for capabilities and probe each of them */
462     for (size_t i = 0; i < count; i++)
463     {
464          module_t *p_module = p_all[i];
465
466          if( module_provides( p_module, "sout mux" ) )
467              caps["muxers"].insert( module_get_object( p_module ) );
468 //        else if ( module_provides( p_module, "encoder" ) )
469 //            caps["encoders"].insert( module_get_object( p_module ) );
470     }
471     module_list_free (p_all);
472 }
473
474 inline void VLCProfileEditor::registerFilters()
475 {
476     size_t count;
477     module_t **p_all = module_list_get (&count);
478
479     for (size_t i = 0; i < count; i++)
480     {
481         module_t *p_module = p_all[i];
482         if ( module_get_score( p_module ) > 0 ) continue;
483
484         QString capability = module_get_capability( p_module );
485         QListWidget *listWidget = NULL;
486         QListWidgetItem *item;
487
488         if ( capability == "video filter2" )
489             listWidget = ui.valueholder_video_filters;
490         else if ( capability == "audio filter" )
491             listWidget = ui.valueholder_audio_filters;
492
493         if ( !listWidget ) continue;
494
495         item = new QListWidgetItem( module_get_name( p_module, true ) );
496         item->setCheckState( Qt::Unchecked );
497         item->setToolTip( QString( module_get_help( p_module ) ) );
498         item->setData( Qt::UserRole, QString( module_get_object( p_module ) ) );
499         listWidget->addItem( item );
500     }
501     module_list_free (p_all);
502
503     ui.valueholder_video_filters->sortItems();
504     ui.valueholder_audio_filters->sortItems();
505 }
506
507 inline void VLCProfileEditor::registerCodecs()
508 {
509 #define SETMUX( button, val,    vid, aud, men, sub, stream, chaps ) \
510     ui.button->setProperty( "sout", val );\
511     ui.button->setProperty( "capvideo", vid );\
512     ui.button->setProperty( "capaudio", aud );\
513     ui.button->setProperty( "capmenu", men );\
514     ui.button->setProperty( "capsubs", sub );\
515     ui.button->setProperty( "capstream", stream );\
516     ui.button->setProperty( "capchaps", chaps );\
517     CONNECT( ui.button, clicked(bool), this, muxSelected() );
518     SETMUX( PSMux, "ps",        true, true, false, true, false, true )
519     SETMUX( TSMux, "ts",        true, true, false, true, true, false )
520     SETMUX( WEBMux, "webm",     true, true, false, false, true, false )
521     SETMUX( MPEG1Mux, "mpeg1",  true, true, false, false, false, false )
522     SETMUX( OggMux, "ogg",      true, true, false, false, true, true )
523     SETMUX( ASFMux, "asf",      true, true, false, true, true, true )
524     SETMUX( MOVMux, "mp4",      true, true, true, true, true, false )
525     SETMUX( WAVMux, "wav",      false, true, false, false, false, false )
526     SETMUX( RAWMux, "raw",      true, true, false, false, false, false )
527     SETMUX( FLVMux, "flv",      true, true, false, false, true, false )
528     SETMUX( MKVMux, "mkv",      true, true, true, true, true, true )
529     SETMUX( AVIMux, "avi",      true, true, false, false, false, false )
530     SETMUX( MJPEGMux, "mpjpeg", true, false, false, false, false, false )
531 #undef SETMUX
532
533 #define ADD_VCODEC( name, fourcc ) \
534             ui.valueholder_video_codec->addItem( name, QVariant( fourcc ) );
535     ADD_VCODEC( "MPEG-1", "mp1v" )
536     ADD_VCODEC( "MPEG-2", "mp2v" )
537     ADD_VCODEC( "MPEG-4", "mp4v" )
538     ADD_VCODEC( "DIVX 1" , "DIV1" )
539     ADD_VCODEC( "DIVX 2" , "DIV2" )
540     ADD_VCODEC( "DIVX 3" , "DIV3" )
541     ADD_VCODEC( "H-263", "H263" )
542     ADD_VCODEC( "H-264", "h264" )
543     ADD_VCODEC( "VP8", "VP80" )
544     ADD_VCODEC( "WMV1", "WMV1" )
545     ADD_VCODEC( "WMV2" , "WMV2" )
546     ADD_VCODEC( "M-JPEG", "MJPG" )
547     ADD_VCODEC( "Theora", "theo" )
548     ADD_VCODEC( "Dirac", "drac" )
549 #undef ADD_VCODEC
550     /* can do quality */
551     qpcodecsList << "h264";
552
553 #define ADD_ACODEC( name, fourcc ) ui.valueholder_audio_codec->addItem( name, QVariant( fourcc ) );
554     ADD_ACODEC( "MPEG Audio", "mpga" )
555     ADD_ACODEC( "MP3", "mp3" )
556     ADD_ACODEC( "MPEG 4 Audio ( AAC )", "mp4a" )
557     ADD_ACODEC( "A52/AC-3", "a52" )
558     ADD_ACODEC( "Vorbis", "vorb" )
559     ADD_ACODEC( "Flac", "flac" )
560     ADD_ACODEC( "Speex", "spx" )
561     ADD_ACODEC( "WAV", "s16l" )
562     ADD_ACODEC( "WMA2", "wma2" )
563 #undef ADD_ACODEC
564
565 #define ADD_SCALING( factor ) ui.valueholder_vcodec_scale->addItem( factor );
566     ADD_SCALING( qtr("Auto") );
567     ADD_SCALING( "1" )
568     ADD_SCALING( "0.25" )
569     ADD_SCALING( "0.5" )
570     ADD_SCALING( "0.75" )
571     ADD_SCALING( "1.25" )
572     ADD_SCALING( "1.5" )
573     ADD_SCALING( "1.75" )
574     ADD_SCALING( "2" )
575 #undef ADD_SCALING
576
577 #define ADD_SAMPLERATE( sample, val ) ui.valueholder_acodec_samplerate->addItem( sample, val );
578     ADD_SAMPLERATE( "8000 Hz", 8000 )
579     ADD_SAMPLERATE( "11025 Hz", 11025 )
580     ADD_SAMPLERATE( "22050 Hz", 22050 )
581     ADD_SAMPLERATE( "44100 Hz", 44100 )
582     ADD_SAMPLERATE( "48000 Hz", 48000 )
583 #undef ADD_SAMPLERATE
584
585 #define ADD_SCODEC( name, fourcc ) ui.valueholder_subtitles_codec->addItem( name, QVariant( fourcc ) );
586     ADD_SCODEC( "DVB subtitle", "dvbs" )
587     ADD_SCODEC( "T.140", "t140" )
588 #undef ADD_SCODEC
589 }
590
591 void VLCProfileEditor::muxSelected()
592 {
593     QRadioButton *current =
594             qobject_cast<QRadioButton *>( ui.buttonGroup->checkedButton() );
595
596 #define SETYESNOSTATE( name, prop ) \
597     ui.name->setChecked( current->property( prop ).toBool() )
598
599     /* dumb :/ */
600     SETYESNOSTATE( capvideo, "capvideo" );
601     SETYESNOSTATE( capaudio, "capaudio" );
602     SETYESNOSTATE( capmenu, "capmenu" );
603     SETYESNOSTATE( capsubs, "capsubs" );
604     SETYESNOSTATE( capstream, "capstream" );
605     SETYESNOSTATE( capchaps, "capchaps" );
606     bool b = caps["muxers"].contains( "mux_" + current->property("sout").toString() );
607     if ( !b )
608         ui.muxerwarning->setText(
609                     QString( "<img src=\":/menu/info\"/> %1" )
610                     .arg( qtr( "This muxer is not provided directly by VLC: It could be missing." ) )
611                     );
612     else
613         ui.muxerwarning->setText("");
614     return;
615
616 #undef SETYESNOSTATE
617 }
618
619 void VLCProfileEditor::codecSelected()
620 {
621     /* Enable quality preset */
622     QString currentcodec = ui.valueholder_video_codec->
623             itemData(ui.valueholder_video_codec->currentIndex() ).toString();
624     ui.valueholder_vcodec_qp->setEnabled( qpcodecsList.contains( currentcodec ) );
625 }
626
627 void VLCProfileEditor::fillProfile( const QString& qs )
628 {
629     QRegExp rx(OLDFORMAT);
630     if ( rx.indexIn( qs ) != -1 ) return fillProfileOldFormat( qs );
631
632     QStringList tuples = qs.split( ";" );
633     foreach ( const QString &tuple, tuples )
634     {
635         QStringList keyvalue = tuple.split( "=" );
636         if ( keyvalue.count() != 2 ) continue;
637         QString key = keyvalue[0];
638         QString value = keyvalue[1];
639         QObject *object = findChild<QObject *>( CATPROP2NAME( key ) );
640         if ( object )
641         {
642             if( object->inherits( "QButtonGroup" ) )
643             { /* Buttongroup for Radios */
644                 const QButtonGroup *group = qobject_cast<const QButtonGroup *>( object );
645                 foreach( QAbstractButton *button, group->buttons() )
646                 {
647                     if ( button->property("sout").toString() == value )
648                     {
649                         button->setChecked( true );
650                         break;/* radios are exclusive */
651                     }
652                 }
653             }
654             else if( object->inherits( "QCheckBox" ) )
655             {
656                 QCheckBox *box = qobject_cast<QCheckBox *>( object );
657                 box->setChecked( ! value.isEmpty() );
658             }
659             else if( object->inherits( "QGroupBox" ) )
660             {
661                 QGroupBox *box = qobject_cast<QGroupBox *>( object );
662                 box->setChecked( ! value.isEmpty() );
663             }
664             else if( object->inherits( "QSpinBox" ) )
665             {
666                 QSpinBox *box = qobject_cast<QSpinBox *>( object );
667                 box->setValue( value.toInt() );
668             }
669             else if( object->inherits( "QDoubleSpinBox" ) )
670             {
671                 QDoubleSpinBox *box = qobject_cast<QDoubleSpinBox *>( object );
672                 box->setValue( value.toDouble() );
673             }
674             else if( object->inherits( "QComboBox" ) )
675             {
676                 QComboBox *box = qobject_cast<QComboBox *>( object );
677                 box->setCurrentIndex( box->findData( value ) );
678             }
679             else if( object->inherits( "QLineEdit" ) )
680             {
681                 QLineEdit *box = qobject_cast<QLineEdit *>( object );
682                 box->setText( QUrl::fromPercentEncoding( value.toAscii() ) );
683             }
684             else if ( object->inherits( "QListWidget" ) )
685             {
686                 QStringList valuesList = QUrl::fromPercentEncoding( value.toAscii() ).split( ";" );
687                 const QListWidget *list = qobject_cast<const QListWidget *>( object );
688                 for( int i=0; i < list->count(); i++ )
689                 {
690                     QListWidgetItem *item = list->item( i );
691                     if ( valuesList.contains( item->data( Qt::UserRole ).toString() ) )
692                         item->setCheckState( Qt::Checked );
693                     else
694                         item->setCheckState( Qt::Unchecked );
695                 }
696             }
697         }
698     }
699 }
700
701 void VLCProfileEditor::fillProfileOldFormat( const QString& qs )
702 {
703     QStringList options = qs.split( ";" );
704     if( options.count() < 16 )
705         return;
706
707     const QString mux = options[0];
708     for ( int i=0; i< ui.muxer->layout()->count(); i++ )
709     {
710         QRadioButton *current =
711                 qobject_cast<QRadioButton *>(ui.muxer->layout()->itemAt(i)->widget());
712         if ( unlikely( !current ) ) continue;/* someone is messing up with ui */
713         if ( current->property("sout").toString() == mux )
714         {
715             current->setChecked( true );
716             break;/* radios are exclusive */
717         }
718     }
719
720     ui.valueholder_video_copy->setChecked( !options[1].toInt() );
721     ui.valueholder_video_enable->setChecked( ( options[4] != "none" ) );
722     ui.valueholder_audio_copy->setChecked( !options[2].toInt() );
723     ui.valueholder_audio_enable->setChecked( ( options[10] != "none" ) );
724     ui.valueholder_subtitles_enable->setChecked( options[3].toInt() );
725
726     ui.valueholder_video_codec->setCurrentIndex( ui.valueholder_video_codec->findData( options[4] ) );
727     ui.valueholder_vcodec_bitrate->setValue( options[5].toInt() );
728     if ( options[6].toInt() > 0 )
729         ui.valueholder_vcodec_scale->setEditText( options[6] );
730     else
731         ui.valueholder_vcodec_scale->setCurrentIndex( 0 );
732     ui.valueholder_vcodec_framerate->setValue( options[7].toDouble() );
733     ui.valueholder_vcodec_width->setValue( options[8].toInt() );
734     ui.valueholder_vcodec_height->setValue( options[9].toInt() );
735
736     ui.valueholder_audio_codec->setCurrentIndex( ui.valueholder_audio_codec->findData( options[10] ) );
737     ui.valueholder_acodec_bitrate->setValue( options[11].toInt() );
738     ui.valueholder_acodec_channels->setValue( options[12].toInt() );
739
740     int index = ui.valueholder_acodec_samplerate->findData( options[13] );
741     if ( index == -1 ) index = ui.valueholder_acodec_samplerate->findData( 44100 );
742     ui.valueholder_acodec_samplerate->setCurrentIndex( index );
743
744     ui.valueholder_subtitles_codec->setCurrentIndex( ui.valueholder_subtitles_codec->findData( options[14] ) );
745     ui.valueholder_subtitles_overlay->setChecked( options[15].toInt() );
746 }
747
748 void VLCProfileEditor::close()
749 {
750     if( ui.profileLine->text().isEmpty() )
751     {
752         QMessageBox::warning( this, qtr(" Profile Name Missing" ),
753                 qtr( "You must set a name for the profile." ) );
754         ui.profileLine->setFocus();
755         return;
756     }
757     name = ui.profileLine->text();
758
759     accept();
760 }
761
762 #define currentData( box ) box->itemData( box->currentIndex() )
763
764 QString VLCProfileEditor::transcodeValue()
765 {
766     QList<QObject *> allwidgets = findChildren<QObject *>();
767     QStringList configuration;
768
769     foreach( const QObject *object, allwidgets )
770     {
771         if ( ! object->objectName().startsWith( CATPROP2NAME( "" ) ) )
772             continue;
773         if ( object->inherits( "QWidget" ) &&
774              ! qobject_cast<const QWidget *>(object)->isEnabled() ) continue;
775
776         QString name = object->objectName();
777         QStringList vals = object->objectName().split( "_" );
778         if ( vals.count() != 3 ) continue;
779         QString &categ = vals[1];
780         QString &prop = vals[2];
781         QString value;
782
783         if( object->inherits( "QButtonGroup" ) )
784         {
785             const QButtonGroup *group = qobject_cast<const QButtonGroup *>( object );
786             value = group->checkedButton()->property( "sout" ).toString();
787         }
788         else if( object->inherits( "QCheckBox" ) )
789         {
790             const QCheckBox *box = qobject_cast<const QCheckBox *>( object );
791             value = box->isChecked() ? "yes" : "";
792         }
793         else if( object->inherits( "QGroupBox" ) )
794         {
795             const QGroupBox *box = qobject_cast<const QGroupBox *>( object );
796             value = box->isChecked() ? "yes" : "";
797         }
798         else if( object->inherits( "QSpinBox" ) )
799         {
800             const QSpinBox *box = qobject_cast<const QSpinBox *>( object );
801             value = QString::number( box->value() );
802         }
803         else if( object->inherits( "QDoubleSpinBox" ) )
804         {
805             const QDoubleSpinBox *box = qobject_cast<const QDoubleSpinBox *>( object );
806             value =  QString::number( box->value() );
807         }
808         else if( object->inherits( "QComboBox" ) )
809         {
810             const QComboBox *box = qobject_cast<const QComboBox *>( object );
811             value = currentData( box ).toString();
812         }
813         else if( object->inherits( "QLineEdit" ) )
814         {
815             const QLineEdit *box = qobject_cast<const QLineEdit *>( object );
816             value = QUrl::toPercentEncoding( box->text(), "", "_;" );
817         }
818         else if ( object->inherits( "QListWidget" ) )
819         {
820             const QListWidget *list = qobject_cast<const QListWidget *>( object );
821             QStringList valuesList;
822             for( int i=0; i < list->count(); i++ )
823             {
824                 const QListWidgetItem *item = list->item( i );
825                 if ( item->checkState() == Qt::Checked )
826                     valuesList.append( item->data( Qt::UserRole ).toString() );
827             }
828             value = QUrl::toPercentEncoding( valuesList.join( ";" ), "", "_;" );
829         }
830
831         if ( !value.isEmpty() )
832             configuration << QString( "%1_%2=%3" )
833                              .arg( categ ).arg( prop ).arg( value );
834     }
835
836     return configuration.join( ";" );
837 }
838
839 void VLCProfileEditor::reset()
840 {
841     /* reset to default state as we can only check/enable existing values */
842     ui.valueholder_video_copy->setChecked( false );
843     ui.valueholder_audio_copy->setChecked( false );
844     activatePanels();
845     fixBirateState(); /* defaults to bitrate, not qp */
846     /* end with top level ones for cascaded setEnabled() */
847     ui.valueholder_video_enable->setChecked( false );
848     ui.valueholder_audio_enable->setChecked( false );
849     ui.valueholder_subtitles_enable->setChecked( false );
850 }
851
852 void VLCProfileEditor::activatePanels()
853 {
854     ui.transcodevideo->setEnabled( ! ui.valueholder_video_copy->isChecked() );
855     ui.transcodeaudio->setEnabled( ! ui.valueholder_audio_copy->isChecked() );
856 }
857
858 void VLCProfileEditor::fixBirateState()
859 {
860     /* exclusive bitrate choice */
861     ui.valueholder_vcodec_qp->setValue( 0 );
862 }
863
864 void VLCProfileEditor::fixQPState()
865 {
866     /* exclusive bitrate choice */
867     ui.valueholder_vcodec_bitrate->setValue( 0 );
868 }
869
870 #undef CATPROP2NAME
871 #undef CATANDPROP
872 #undef OLDFORMAT