1 /*****************************************************************************
2 * profile_selector.cpp : A small profile selector and editor
3 ****************************************************************************
4 * Copyright (C) 2009 the VideoLAN team
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>
33 #include <QMessageBox>
34 #include <QRadioButton>
38 VLCProfileSelector::VLCProfileSelector( QWidget *_parent ): QWidget( _parent )
40 QHBoxLayout *layout = new QHBoxLayout( this );
42 QLabel *prLabel = new QLabel( qtr( "Profile"), this );
43 layout->addWidget( prLabel );
45 profileBox = new QComboBox( this );
46 layout->addWidget( profileBox );
48 QToolButton *editButton = new QToolButton( this );
49 editButton->setIcon( QIcon( ":/menu/preferences" ) );
50 editButton->setToolTip( qtr( "Edit selected profile" ) );
51 layout->addWidget( editButton );
53 QToolButton *deleteButton = new QToolButton( this );
54 deleteButton->setIcon( QIcon( ":/toolbar/clear" ) );
55 deleteButton->setToolTip( qtr( "Delete selected profile" ) );
56 layout->addWidget( deleteButton );
58 QToolButton *newButton = new QToolButton( this );
59 newButton->setIcon( QIcon( ":/new" ) );
60 newButton->setToolTip( qtr( "Create a new profile" ) );
61 layout->addWidget(newButton);
63 BUTTONACT( newButton, newProfile() );
64 BUTTONACT( editButton, editProfile() );
65 BUTTONACT( deleteButton, deleteProfile() );
68 CONNECT( profileBox, activated( int ),
69 this, updateOptions( int ) );
74 inline void VLCProfileSelector::fillProfilesCombo()
80 QSettings::NativeFormat,
82 QSettings::UserScope, "vlc", "vlc-qt-interface" );
84 int i_size = settings.beginReadArray( "codecs-profiles" );
86 for( int i = 0; i < i_size; i++ )
88 settings.setArrayIndex( i );
89 if( settings.value( "Profile-Name" ).toString().isEmpty() ) continue;
90 profileBox->addItem( settings.value( "Profile-Name" ).toString(),
91 settings.value( "Profile-Value" ) );
95 for( size_t i = 0; i < NB_PROFILE; i++ )
97 profileBox->addItem( video_profile_name_list[i],
98 video_profile_value_list[i] );
104 void VLCProfileSelector::newProfile()
106 editProfile( "", "" );
109 void VLCProfileSelector::editProfile()
111 editProfile( profileBox->currentText(),
112 profileBox->itemData( profileBox->currentIndex() ).toString() );
115 void VLCProfileSelector::editProfile( const QString& qs, const QString& value )
117 /* Create the Profile Editor */
118 VLCProfileEditor *editor = new VLCProfileEditor( qs, value, this );
121 if( QDialog::Accepted == editor->exec() )
125 profileBox->addItem( editor->name, QVariant( editor->transcodeValue() ) );
126 /* Update old profile */
129 /* Look for the profile */
130 int i_profile = profileBox->findText( qs );
131 assert( i_profile != -1 );
132 profileBox->setItemText( i_profile, editor->name );
133 profileBox->setItemData( i_profile, QVariant( editor->transcodeValue() ) );
134 /* Force mrl recreation */
135 updateOptions( i_profile );
141 emit optionsChanged();
144 void VLCProfileSelector::deleteProfile()
146 profileBox->removeItem( profileBox->currentIndex() );
150 void VLCProfileSelector::saveProfiles()
154 QSettings::IniFormat,
156 QSettings::NativeFormat,
158 QSettings::UserScope, "vlc", "vlc-qt-interface" );
160 settings.remove( "codecs-profiles" ); /* Erase old profiles to be rewritten */
161 settings.beginWriteArray( "codecs-profiles" );
162 for( int i = 0; i < profileBox->count(); i++ )
164 settings.setArrayIndex( i );
165 settings.setValue( "Profile-Name", profileBox->itemText( i ) );
166 settings.setValue( "Profile-Value", profileBox->itemData( i ).toString() );
171 void VLCProfileSelector::updateOptions( int i )
173 QStringList options = profileBox->itemData( i ).toString().split( ";" );
174 if( options.count() < 16 )
180 if( options[1].toInt() || options[2].toInt() || options[3].toInt() )
182 smrl.begin( "transcode" );
184 if( options[1].toInt() )
186 smrl.option( "vcodec", options[4] );
187 if( options[4] != "none" )
189 smrl.option( "vb", options[5].toInt() );
190 if( !options[7].isEmpty() && options[7].toInt() > 0 )
191 smrl.option( "fps", options[7] );
192 if( !options[6].isEmpty() )
193 smrl.option( "scale", options[6] );
194 if( !options[8].isEmpty() && options[8].toInt() > 0 )
195 smrl.option( "width", options[8].toInt() );
196 if( !options[9].isEmpty() && options[9].toInt() > 0 )
197 smrl.option( "height", options[9].toInt() );
201 if( options[2].toInt() )
203 smrl.option( "acodec", options[10] );
204 if( options[10] != "none" )
206 smrl.option( "ab", options[11].toInt() );
207 smrl.option( "channels", options[12].toInt() );
208 smrl.option( "samplerate", options[13].toInt() );
212 if( options[3].toInt() )
214 smrl.option( "scodec", options[14] );
215 if( options[15].toInt() )
216 smrl.option( "soverlay" );
221 transcode = smrl.getMrl();
225 emit optionsChanged();
232 VLCProfileEditor::VLCProfileEditor( const QString& qs_name, const QString& value,
234 : QVLCDialog( _parent, NULL )
237 if( !qs_name.isEmpty() )
239 ui.profileLine->setText( qs_name );
240 ui.profileLine->setReadOnly( true );
243 CONNECT( ui.transcodeVideo, toggled( bool ),
244 this, setVTranscodeOptions( bool ) );
245 CONNECT( ui.transcodeAudio, toggled( bool ),
246 this, setATranscodeOptions( bool ) );
247 CONNECT( ui.transcodeSubs, toggled( bool ),
248 this, setSTranscodeOptions( bool ) );
249 setVTranscodeOptions( false );
250 setATranscodeOptions( false );
251 setSTranscodeOptions( false );
253 QPushButton *saveButton = new QPushButton(
254 ( qs_name.isEmpty() ) ? qtr( "Create" ) : qtr( "Save" ) );
255 ui.buttonBox->addButton( saveButton, QDialogButtonBox::AcceptRole );
256 BUTTONACT( saveButton, close() );
257 QPushButton *cancelButton = new QPushButton( qtr( "Cancel" ) );
258 ui.buttonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
259 BUTTONACT( cancelButton, reject() );
261 fillProfile( value );
264 inline void VLCProfileEditor::registerCodecs()
266 #define SETMUX( button, val ) ui.button->setProperty( "sout", val );
267 SETMUX( PSMux, "ps" )
268 SETMUX( TSMux, "ts" )
269 SETMUX( WEBMux, "webm" )
270 SETMUX( MPEG1Mux, "mpeg1" )
271 SETMUX( OggMux, "ogg" )
272 SETMUX( ASFMux, "asf" )
273 SETMUX( MOVMux, "mp4" )
274 SETMUX( WAVMux, "wav" )
275 SETMUX( RAWMux, "raw" )
276 SETMUX( FLVMux, "flv" )
277 SETMUX( MKVMux, "mkv" )
278 SETMUX( AVIMux, "avi" )
279 SETMUX( MJPEGMux, "mpjpeg" )
282 #define ADD_VCODEC( name, fourcc ) ui.vCodecBox->addItem( name, QVariant( fourcc ) );
283 ADD_VCODEC( "MPEG-1", "mp1v" )
284 ADD_VCODEC( "MPEG-2", "mp2v" )
285 ADD_VCODEC( "MPEG-4", "mp4v" )
286 ADD_VCODEC( "DIVX 1" , "DIV1" )
287 ADD_VCODEC( "DIVX 2" , "DIV2" )
288 ADD_VCODEC( "DIVX 3" , "DIV3" )
289 ADD_VCODEC( "H-263", "H263" )
290 ADD_VCODEC( "H-264", "h264" )
291 ADD_VCODEC( "VP8", "VP80" )
292 ADD_VCODEC( "WMV1", "WMV1" )
293 ADD_VCODEC( "WMV2" , "WMV2" )
294 ADD_VCODEC( "M-JPEG", "MJPG" )
295 ADD_VCODEC( "Theora", "theo" )
296 ADD_VCODEC( "Dirac", "drac" )
299 #define ADD_ACODEC( name, fourcc ) ui.aCodecBox->addItem( name, QVariant( fourcc ) );
300 ADD_ACODEC( "MPEG Audio", "mpga" )
301 ADD_ACODEC( "MP3", "mp3" )
302 ADD_ACODEC( "MPEG 4 Audio ( AAC )", "mp4a" )
303 ADD_ACODEC( "A52/AC-3", "a52" )
304 ADD_ACODEC( "Vorbis", "vorb" )
305 ADD_ACODEC( "Flac", "flac" )
306 ADD_ACODEC( "Speex", "spx" )
307 ADD_ACODEC( "WAV", "s16l" )
308 ADD_ACODEC( "WMA2", "wma2" )
311 #define ADD_SCALING( factor ) ui.vScaleBox->addItem( factor );
312 ADD_SCALING( qtr("Auto") );
314 ADD_SCALING( "0.25" )
316 ADD_SCALING( "0.75" )
317 ADD_SCALING( "1.25" )
319 ADD_SCALING( "1.75" )
323 #define ADD_SAMPLERATE( sample, val ) ui.aSampleBox->addItem( sample, val );
324 ADD_SAMPLERATE( "8000 Hz", 8000 )
325 ADD_SAMPLERATE( "11025 Hz", 11025 )
326 ADD_SAMPLERATE( "22050 Hz", 22050 )
327 ADD_SAMPLERATE( "44100 Hz", 44100 )
328 ADD_SAMPLERATE( "48000 Hz", 48000 )
329 #undef ADD_SAMPLERATE
331 #define ADD_SCODEC( name, fourcc ) ui.subsCodecBox->addItem( name, QVariant( fourcc ) );
332 ADD_SCODEC( "DVB subtitle", "dvbs" )
333 ADD_SCODEC( "T.140", "t140" )
337 void VLCProfileEditor::fillProfile( const QString& qs )
339 QStringList options = qs.split( ";" );
340 if( options.count() < 16 )
343 const QString mux = options[0];
344 for ( int i=0; i< ui.muxer->layout()->count(); i++ )
346 QRadioButton *current =
347 qobject_cast<QRadioButton *>(ui.muxer->layout()->itemAt(i)->widget());
348 if ( unlikely( !current ) ) continue;/* someone is messing up with ui */
349 if ( current->property("sout").toString() == mux )
351 current->setChecked( true );
352 break;/* radios are exclusive */
356 ui.keepVideo->setChecked( !options[1].toInt() );
357 ui.transcodeVideo->setChecked( ( options[4] != "none" ) );
358 ui.keepAudio->setChecked( !options[2].toInt() );
359 ui.transcodeAudio->setChecked( ( options[10] != "none" ) );
360 ui.transcodeSubs->setChecked( options[3].toInt() );
362 ui.vCodecBox->setCurrentIndex( ui.vCodecBox->findData( options[4] ) );
363 ui.vBitrateSpin->setValue( options[5].toInt() );
364 if ( options[6].toInt() > 0 )
365 ui.vScaleBox->setEditText( options[6] );
367 ui.vScaleBox->setCurrentIndex( 0 );
368 ui.vFrameBox->setValue( options[7].toDouble() );
369 ui.widthBox->setValue( options[8].toInt() );
370 ui.heightBox->setValue( options[9].toInt() );
372 ui.aCodecBox->setCurrentIndex( ui.aCodecBox->findData( options[10] ) );
373 ui.aBitrateSpin->setValue( options[11].toInt() );
374 ui.aChannelsSpin->setValue( options[12].toInt() );
376 int index = ui.aSampleBox->findData( options[13] );
377 if ( index == -1 ) index = ui.aSampleBox->findData( 44100 );
378 ui.aSampleBox->setCurrentIndex( index );
380 ui.subsCodecBox->setCurrentIndex( ui.subsCodecBox->findData( options[14] ) );
381 ui.subsOverlay->setChecked( options[15].toInt() );
384 void VLCProfileEditor::setVTranscodeOptions( bool b_trans )
386 ui.vCodecLabel->setEnabled( b_trans );
387 ui.vCodecBox->setEnabled( b_trans );
388 ui.vBitrateLabel->setEnabled( b_trans );
389 ui.vBitrateSpin->setEnabled( b_trans );
390 ui.vScaleLabel->setEnabled( b_trans );
391 ui.vScaleBox->setEnabled( b_trans );
392 ui.heightBox->setEnabled( b_trans );
393 ui.heightLabel->setEnabled( b_trans );
394 ui.widthBox->setEnabled( b_trans );
395 ui.widthLabel->setEnabled( b_trans );
396 ui.vFrameBox->setEnabled( b_trans );
397 ui.vFrameLabel->setEnabled( b_trans );
398 ui.keepVideo->setEnabled( b_trans );
401 void VLCProfileEditor::setATranscodeOptions( bool b_trans )
403 ui.aCodecLabel->setEnabled( b_trans );
404 ui.aCodecBox->setEnabled( b_trans );
405 ui.aBitrateLabel->setEnabled( b_trans );
406 ui.aBitrateSpin->setEnabled( b_trans );
407 ui.aChannelsLabel->setEnabled( b_trans );
408 ui.aChannelsSpin->setEnabled( b_trans );
409 ui.aSampleLabel->setEnabled( b_trans );
410 ui.aSampleBox->setEnabled( b_trans );
411 ui.keepAudio->setEnabled( b_trans );
414 void VLCProfileEditor::setSTranscodeOptions( bool b_trans )
416 ui.subsCodecBox->setEnabled( b_trans );
417 ui.subsOverlay->setEnabled( b_trans );
420 void VLCProfileEditor::close()
422 if( ui.profileLine->text().isEmpty() )
424 QMessageBox::warning( this, qtr(" Profile Name Missing" ),
425 qtr( "You must set a name for the profile." ) );
426 ui.profileLine->setFocus();
429 name = ui.profileLine->text();
434 QString VLCProfileEditor::transcodeValue()
436 for ( int i=0; i< ui.muxer->layout()->count(); i++ )
438 QRadioButton *current =
439 qobject_cast<QRadioButton *>(ui.muxer->layout()->itemAt(i)->widget());
440 if ( unlikely( !current ) ) continue;/* someone is messing up with ui */
441 if ( current->isChecked() )
443 muxValue = current->property("sout").toString();
444 break;/* radios are exclusive */
448 #define currentData( box ) box->itemData( box->currentIndex() )
449 QString qs_acodec, qs_vcodec;
451 qs_vcodec = ( ui.transcodeVideo->isChecked() ) ? currentData( ui.vCodecBox ).toString()
453 qs_acodec = ( ui.transcodeAudio->isChecked() ) ? currentData( ui.aCodecBox ).toString()
455 QStringList transcodeMRL;
459 << QString::number( !ui.keepVideo->isChecked() )
460 << QString::number( !ui.keepAudio->isChecked() )
461 << QString::number( ui.transcodeSubs->isChecked() )
464 << QString::number( ui.vBitrateSpin->value() )
465 << ( ( ui.vScaleBox->currentIndex() != 0 ) ? ui.vScaleBox->currentText() : QString("0") )
466 << QString::number( ui.vFrameBox->value() )
467 << QString::number( ui.widthBox->value() )
468 << QString::number( ui.heightBox->value() )
471 << QString::number( ui.aBitrateSpin->value() )
472 << QString::number( ui.aChannelsSpin->value() )
473 << currentData( ui.aSampleBox ).toString()
475 << currentData( ui.subsCodecBox ).toString()
476 << QString::number( ui.subsOverlay->isChecked() );
479 return transcodeMRL.join( ";" );