]> git.sesse.net Git - vlc/blob - modules/gui/qt4/components/sout/profile_selector.cpp
UI: prefix/namespace resources for better maintainability
[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
35 #include <assert.h>
36
37 VLCProfileSelector::VLCProfileSelector( QWidget *_parent ): QWidget( _parent )
38 {
39     QHBoxLayout *layout = new QHBoxLayout( this );
40
41     QLabel *prLabel = new QLabel( qtr( "Profile"), this );
42     layout->addWidget( prLabel );
43
44     profileBox = new QComboBox( this );
45     layout->addWidget( profileBox );
46
47     QToolButton *editButton = new QToolButton( this );
48     editButton->setIcon( QIcon( ":/menu/preferences" ) );
49     editButton->setToolTip( qtr( "Edit selected profile" ) );
50     layout->addWidget( editButton );
51
52     QToolButton *deleteButton = new QToolButton( this );
53     deleteButton->setIcon( QIcon( ":/toolbar/clear" ) );
54     deleteButton->setToolTip( qtr( "Delete selected profile" ) );
55     layout->addWidget( deleteButton );
56
57     QToolButton *newButton = new QToolButton( this );
58     newButton->setIcon( QIcon( ":/new" ) );
59     newButton->setToolTip( qtr( "Create a new profile" ) );
60     layout->addWidget(newButton);
61
62     BUTTONACT( newButton, newProfile() );
63     BUTTONACT( editButton, editProfile() );
64     BUTTONACT( deleteButton, deleteProfile() );
65     fillProfilesCombo();
66
67     CONNECT( profileBox, activated( int ),
68              this, updateOptions( int ) );
69
70     updateOptions( 0 );
71 }
72
73 inline void VLCProfileSelector::fillProfilesCombo()
74 {
75     QSettings settings(
76 #ifdef WIN32
77             QSettings::IniFormat,
78 #else
79             QSettings::NativeFormat,
80 #endif
81             QSettings::UserScope, "vlc", "vlc-qt-interface" );
82
83     int i_size = settings.beginReadArray( "codecs-profiles" );
84
85     for( int i = 0; i < i_size; i++ )
86     {
87         settings.setArrayIndex( i );
88         if( settings.value( "Profile-Name" ).toString().isEmpty() ) continue;
89         profileBox->addItem( settings.value( "Profile-Name" ).toString(),
90                 settings.value( "Profile-Value" ) );
91     }
92     if( i_size == 0 )
93     {
94         for( int i = 0; i < NB_PROFILE; i++ )
95         {
96             profileBox->addItem( video_profile_name_list[i],
97                                  video_profile_value_list[i] );
98         }
99     }
100     settings.endArray();
101 }
102
103 void VLCProfileSelector::newProfile()
104 {
105     editProfile( "", "" );
106 }
107
108 void VLCProfileSelector::editProfile()
109 {
110     editProfile( profileBox->currentText(),
111                  profileBox->itemData( profileBox->currentIndex() ).toString() );
112 }
113
114 void VLCProfileSelector::editProfile( const QString& qs, const QString& value )
115 {
116     /* Create the Profile Editor */
117     VLCProfileEditor *editor = new VLCProfileEditor( qs, value, this );
118
119     /* Show it */
120     if( QDialog::Accepted == editor->exec() )
121     {
122         /* New Profile */
123         if( qs.isEmpty() )
124             profileBox->addItem( editor->name, QVariant( editor->transcodeValue() ) );
125         /* Update old profile */
126         else
127         {
128             /* Look for the profile */
129             int i_profile = profileBox->findText( qs );
130             assert( i_profile != -1 );
131             profileBox->setItemText( i_profile, editor->name );
132             profileBox->setItemData( i_profile, QVariant( editor->transcodeValue() ) );
133             /* Force mrl recreation */
134             updateOptions( i_profile );
135         }
136     }
137     delete editor;
138
139     saveProfiles();
140     emit optionsChanged();
141 }
142
143 void VLCProfileSelector::deleteProfile()
144 {
145     profileBox->removeItem( profileBox->currentIndex() );
146 }
147
148 void VLCProfileSelector::saveProfiles()
149 {
150     QSettings settings(
151 #ifdef WIN32
152             QSettings::IniFormat,
153 #else
154             QSettings::NativeFormat,
155 #endif
156             QSettings::UserScope, "vlc", "vlc-qt-interface" );
157
158     settings.beginWriteArray( "codecs-profiles" );
159     for( int i = 0; i < profileBox->count(); i++ )
160     {
161         settings.setArrayIndex( i );
162         settings.setValue( "Profile-Name", profileBox->itemText( i ) );
163         settings.setValue( "Profile-Value", profileBox->itemData( i ).toString() );
164     }
165     settings.endArray();
166 }
167
168 void VLCProfileSelector::updateOptions( int i )
169 {
170     QStringList options = profileBox->itemData( i ).toString().split( ";" );
171     if( options.size() < 16 )
172         return;
173
174     mux = options[0];
175
176     SoutMrl smrl;
177     if( options[1].toInt() || options[2].toInt() || options[3].toInt() )
178     {
179         smrl.begin( "transcode" );
180
181         if( options[1].toInt() )
182         {
183             smrl.option( "vcodec", options[4] );
184             if( options[4] != "none" )
185             {
186                 smrl.option( "vb", options[5].toInt() );
187                 if( !options[7].isEmpty() && options[7].toInt() > 0 )
188                     smrl.option( "fps", options[7] );
189                 if( !options[6].isEmpty() )
190                     smrl.option( "scale", options[6] );
191                 if( !options[8].isEmpty() && options[8].toInt() > 0 )
192                     smrl.option( "width", options[8].toInt() );
193                 if( !options[9].isEmpty() && options[9].toInt() > 0 )
194                     smrl.option( "height", options[9].toInt() );
195             }
196         }
197
198         if( options[2].toInt() )
199         {
200             smrl.option( "acodec", options[10] );
201             if( options[10] != "none" )
202             {
203                 smrl.option( "ab", options[11].toInt() );
204                 smrl.option( "channels", options[12].toInt() );
205                 smrl.option( "samplerate", options[13].toInt() );
206             }
207         }
208
209         if( options[3].toInt() )
210         {
211             smrl.option( "scodec", options[14] );
212             if( options[15].toInt() )
213                 smrl.option( "soverlay" );
214         }
215
216         smrl.end();
217
218         transcode = smrl.getMrl();
219     }
220     else
221         transcode = "";
222     emit optionsChanged();
223 }
224
225
226 /**
227  * VLCProfileEditor
228  **/
229 VLCProfileEditor::VLCProfileEditor( const QString& qs_name, const QString& value,
230         QWidget *_parent )
231                  : QVLCDialog( _parent, NULL )
232 {
233     ui.setupUi( this );
234     if( !qs_name.isEmpty() )
235     {
236         ui.profileLine->setText( qs_name );
237         ui.profileLine->setReadOnly( true );
238     }
239     registerCodecs();
240     CONNECT( ui.transcodeVideo, toggled( bool ),
241             this, setVTranscodeOptions( bool ) );
242     CONNECT( ui.transcodeAudio, toggled( bool ),
243             this, setATranscodeOptions( bool ) );
244     CONNECT( ui.transcodeSubs, toggled( bool ),
245             this, setSTranscodeOptions( bool ) );
246     setVTranscodeOptions( false );
247     setATranscodeOptions( false );
248     setSTranscodeOptions( false );
249
250     QPushButton *saveButton = new QPushButton( qtr( "Save" ) );
251     ui.buttonBox->addButton( saveButton, QDialogButtonBox::AcceptRole );
252     BUTTONACT( saveButton, close() );
253     QPushButton *cancelButton = new QPushButton( qtr( "Cancel" ) );
254     ui.buttonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
255     BUTTONACT( cancelButton, reject() );
256
257     fillProfile( value );
258 }
259
260 inline void VLCProfileEditor::registerCodecs()
261 {
262
263 #define ADD_VCODEC( name, fourcc ) ui.vCodecBox->addItem( name, QVariant( fourcc ) );
264     ADD_VCODEC( "MPEG-1", "mp1v" )
265     ADD_VCODEC( "MPEG-2", "mp2v" )
266     ADD_VCODEC( "MPEG-4", "mp4v" )
267     ADD_VCODEC( "DIVX 1" , "DIV1" )
268     ADD_VCODEC( "DIVX 2" , "DIV2" )
269     ADD_VCODEC( "DIVX 3" , "DIV3" )
270     ADD_VCODEC( "H-263", "H263" )
271     ADD_VCODEC( "H-264", "h264" )
272     ADD_VCODEC( "WMV1", "WMV1" )
273     ADD_VCODEC( "WMV2" , "WMV2" )
274     ADD_VCODEC( "M-JPEG", "MJPG" )
275     ADD_VCODEC( "Theora", "theo" )
276     ADD_VCODEC( "Dirac", "drac" )
277 #undef ADD_VCODEC
278
279 #define ADD_ACODEC( name, fourcc ) ui.aCodecBox->addItem( name, QVariant( fourcc ) );
280     ADD_ACODEC( "MPEG Audio", "mpga" )
281     ADD_ACODEC( "MP3", "mp3" )
282     ADD_ACODEC( "MPEG 4 Audio ( AAC )", "mp4a" )
283     ADD_ACODEC( "A52/AC-3", "a52" )
284     ADD_ACODEC( "Vorbis", "vorb" )
285     ADD_ACODEC( "Flac", "flac" )
286     ADD_ACODEC( "Speex", "spx" )
287     ADD_ACODEC( "WAV", "s16l" )
288     ADD_ACODEC( "WMA", "wma" )
289 #undef ADD_ACODEC
290
291 #define ADD_SCALING( factor ) ui.vScaleBox->addItem( factor );
292     ADD_SCALING( "1" )
293     ADD_SCALING( "0.25" )
294     ADD_SCALING( "0.5" )
295     ADD_SCALING( "0.75" )
296     ADD_SCALING( "1.25" )
297     ADD_SCALING( "1.5" )
298     ADD_SCALING( "1.75" )
299     ADD_SCALING( "2" )
300 #undef ADD_SCALING
301
302 #define ADD_SAMPLERATE( sample ) ui.aSampleBox->addItem( sample );
303     ADD_SAMPLERATE( "11250" )
304     ADD_SAMPLERATE( "22500" )
305     ADD_SAMPLERATE( "44100" )
306     ADD_SAMPLERATE( "48000" )
307 #undef ADD_SAMPLERATE
308
309 #define ADD_SCODEC( name, fourcc ) ui.subsCodecBox->addItem( name, QVariant( fourcc ) );
310     ADD_SCODEC( "DVB subtitle", "dvbs" )
311     ADD_SCODEC( "T.140", "t140" )
312 #undef ADD_SCODEC
313 }
314
315 void VLCProfileEditor::fillProfile( const QString& qs )
316 {
317     QStringList options = qs.split( ";" );
318     if( options.size() < 16 )
319         return;
320
321     const QString mux = options[0];
322 #define CHECKMUX( button, text) if( text == mux ) ui.button->setChecked( true ); else
323     CHECKMUX( PSMux, "ps" )
324     CHECKMUX( TSMux, "ts" )
325     CHECKMUX( MPEG1Mux, "mpeg1" )
326     CHECKMUX( OggMux, "ogg" )
327     CHECKMUX( ASFMux, "asf" )
328     CHECKMUX( MOVMux, "mp4" )
329     CHECKMUX( WAVMux, "wav" )
330     CHECKMUX( RAWMux, "raw" )
331     CHECKMUX( FLVMux, "flv" )
332     CHECKMUX( MKVMux, "mkv" )
333     CHECKMUX( AVIMux, "avi" )
334     CHECKMUX( MJPEGMux, "mpjpeg" ){}
335 #undef CHECKMUX
336
337     ui.keepVideo->setChecked( !options[1].toInt() );
338     ui.transcodeVideo->setChecked( ( options[4] != "none" ) );
339     ui.keepAudio->setChecked( !options[2].toInt() );
340     ui.transcodeAudio->setChecked( ( options[10] != "none" ) );
341     ui.transcodeSubs->setChecked( options[3].toInt() );
342
343     ui.vCodecBox->setCurrentIndex( ui.vCodecBox->findData( options[4] ) );
344     ui.vBitrateSpin->setValue( options[5].toInt() );
345     ui.vScaleBox->setEditText( options[6] );
346     ui.vFrameBox->setValue( options[7].toDouble() );
347     ui.widthBox->setText( options[8] );
348     ui.heightBox->setText( options[9] );
349
350     ui.aCodecBox->setCurrentIndex( ui.aCodecBox->findData( options[10] ) );
351     ui.aBitrateSpin->setValue( options[11].toInt() );
352     ui.aChannelsSpin->setValue( options[12].toInt() );
353     ui.aSampleBox->setCurrentIndex( ui.aSampleBox->findText( options[13] ) );
354
355     ui.subsCodecBox->setCurrentIndex( ui.subsCodecBox->findData( options[14] ) );
356     ui.subsOverlay->setChecked( options[15].toInt() );
357 }
358
359 void VLCProfileEditor::setVTranscodeOptions( bool b_trans )
360 {
361     ui.vCodecLabel->setEnabled( b_trans );
362     ui.vCodecBox->setEnabled( b_trans );
363     ui.vBitrateLabel->setEnabled( b_trans );
364     ui.vBitrateSpin->setEnabled( b_trans );
365     ui.vScaleLabel->setEnabled( b_trans );
366     ui.vScaleBox->setEnabled( b_trans );
367     ui.heightBox->setEnabled( b_trans );
368     ui.heightLabel->setEnabled( b_trans );
369     ui.widthBox->setEnabled( b_trans );
370     ui.widthLabel->setEnabled( b_trans );
371     ui.vFrameBox->setEnabled( b_trans );
372     ui.vFrameLabel->setEnabled( b_trans );
373     ui.keepVideo->setEnabled( b_trans );
374 }
375
376 void VLCProfileEditor::setATranscodeOptions( bool b_trans )
377 {
378     ui.aCodecLabel->setEnabled( b_trans );
379     ui.aCodecBox->setEnabled( b_trans );
380     ui.aBitrateLabel->setEnabled( b_trans );
381     ui.aBitrateSpin->setEnabled( b_trans );
382     ui.aChannelsLabel->setEnabled( b_trans );
383     ui.aChannelsSpin->setEnabled( b_trans );
384     ui.aSampleLabel->setEnabled( b_trans );
385     ui.aSampleBox->setEnabled( b_trans );
386     ui.keepAudio->setEnabled( b_trans );
387 }
388
389 void VLCProfileEditor::setSTranscodeOptions( bool b_trans )
390 {
391     ui.subsCodecBox->setEnabled( b_trans );
392     ui.subsOverlay->setEnabled( b_trans );
393 }
394
395 void VLCProfileEditor::close()
396 {
397     if( ui.profileLine->text().isEmpty() )
398     {
399         QMessageBox::warning( this, qtr(" Profile Name Missing" ),
400                 qtr( "You must set a name for the profile." ) );
401         ui.profileLine->setFocus();
402         return;
403     }
404     name = ui.profileLine->text();
405
406     accept();
407 }
408
409 QString VLCProfileEditor::transcodeValue()
410 {
411 #define SMUX( x, txt ) if( ui.x->isChecked() ) muxValue =  txt; else
412     SMUX( PSMux, "ps" )
413     SMUX( TSMux, "ts" )
414     SMUX( MPEG1Mux, "mpeg1" )
415     SMUX( OggMux, "ogg" )
416     SMUX( ASFMux, "asf" )
417     SMUX( MOVMux, "mp4" )
418     SMUX( WAVMux, "wav" )
419     SMUX( RAWMux, "raw" )
420     SMUX( FLVMux, "flv" )
421     SMUX( MKVMux, "mkv" )
422     SMUX( AVIMux, "avi" )
423     SMUX( MJPEGMux, "mpjpeg" ){}
424 #undef SMUX
425
426 #define currentData( box ) box->itemData( box->currentIndex() )
427     QString qs_acodec, qs_vcodec;
428
429     qs_vcodec = ( ui.transcodeVideo->isChecked() ) ? currentData( ui.vCodecBox ).toString()
430                                                    : "none";
431     qs_acodec = ( ui.transcodeAudio->isChecked() ) ? currentData( ui.aCodecBox ).toString()
432                                                    : "none";
433     QStringList transcodeMRL;
434     transcodeMRL
435             << muxValue
436
437             << QString::number( !ui.keepVideo->isChecked() )
438             << QString::number( !ui.keepAudio->isChecked() )
439             << QString::number( ui.transcodeSubs->isChecked() )
440
441             << qs_vcodec
442             << QString::number( ui.vBitrateSpin->value() )
443             << ui.vScaleBox->currentText()
444             << QString::number( ui.vFrameBox->value() )
445             << ui.widthBox->text()
446             << ui.heightBox->text()
447
448             << qs_acodec
449             << QString::number( ui.aBitrateSpin->value() )
450             << QString::number( ui.aChannelsSpin->value() )
451             << ui.aSampleBox->currentText()
452
453             << currentData( ui.subsCodecBox ).toString()
454             << QString::number( ui.subsOverlay->isChecked() );
455 #undef currentData
456
457     return transcodeMRL.join( ";" );
458 }
459