]> git.sesse.net Git - vlc/blob - modules/gui/qt4/components/open_panels.cpp
5866a05b79c18f125cc6f8061c57c2e00a1f6958
[vlc] / modules / gui / qt4 / components / open_panels.cpp
1 /*****************************************************************************
2  * open.cpp : Panels for the open dialogs
3  ****************************************************************************
4  * Copyright (C) 2006-2009 the VideoLAN team
5  * Copyright (C) 2007 Société des arts technologiques
6  * Copyright (C) 2007 Savoir-faire Linux
7  *
8  * $Id$
9  *
10  * Authors: Clément Stenac <zorglub@videolan.org>
11  *          Jean-Baptiste Kempf <jb@videolan.org>
12  *          Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include "qt4.hpp"
34 #include "components/open_panels.hpp"
35 #include "dialogs/open.hpp"
36 #include "dialogs_provider.hpp" /* Open Subtitle file */
37 #include "util/qt_dirs.hpp"
38 #include <vlc_intf_strings.h>
39 #include <vlc_modules.h>
40 #ifdef WIN32
41   #include <vlc_charset.h> /* FromWide for Win32 */
42 #endif
43
44 #include <QFileDialog>
45 #include <QDialogButtonBox>
46 #include <QLineEdit>
47 #include <QStackedLayout>
48 #include <QListView>
49 #include <QCompleter>
50 #include <QDirModel>
51 #include <QScrollArea>
52 #include <QUrl>
53 #include <QStringListModel>
54 #include <QDropEvent>
55
56 #define I_DEVICE_TOOLTIP \
57     I_DIR_OR_FOLDER( N_("Select a device or a VIDEO_TS directory"), \
58                      N_("Select a device or a VIDEO_TS folder") )
59
60 /* Populate a combobox with the devices matching a pattern.
61    Combobox will automatically do autocompletion on the edit zone */
62 #define POPULATE_WITH_DEVS(ppsz_devlist, targetCombo) \
63     QStringList targetCombo ## StringList = QStringList(); \
64     for ( size_t i = 0; i< sizeof(ppsz_devlist) / sizeof(*ppsz_devlist); i++ ) \
65         targetCombo ## StringList << QString( ppsz_devlist[ i ] ); \
66     targetCombo->addItems( QDir( "/dev/" )\
67         .entryList( targetCombo ## StringList, QDir::System )\
68         .replaceInStrings( QRegExp("^"), "/dev/" ) \
69     );
70
71 static const char psz_devModule[][8] = { "v4l2", "pvr", "dtv",
72                                        "dshow", "screen", "jack" };
73
74 /**************************************************************************
75  * Open Files and subtitles                                               *
76  **************************************************************************/
77 FileOpenPanel::FileOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
78                                 OpenPanel( _parent, _p_intf ), dialogBox( NULL )
79 {
80     /* Classic UI Setup */
81     ui.setupUi( this );
82
83     setAcceptDrops( true );
84
85     /* Set Filters for file selection */
86 /*    QString fileTypes = "";
87     ADD_FILTER_MEDIA( fileTypes );
88     ADD_FILTER_VIDEO( fileTypes );
89     ADD_FILTER_AUDIO( fileTypes );
90     ADD_FILTER_PLAYLIST( fileTypes );
91     ADD_FILTER_ALL( fileTypes );
92     fileTypes.replace( QString(";*"), QString(" *")); */
93
94
95 /*    lineFileEdit = ui.fileEdit;
96     //TODO later: fill the fileCompleteList with previous items played.
97     QCompleter *fileCompleter = new QCompleter( fileCompleteList, this );
98     fileCompleter->setModel( new QDirModel( fileCompleter ) );
99     lineFileEdit->setCompleter( fileCompleter );*/
100     if( var_InheritBool( p_intf, "qt-embedded-open" ) )
101     {
102         ui.tempWidget->hide();
103         BuildOldPanel();
104     }
105
106     /* Subtitles */
107     /* Deactivate the subtitles control by default. */
108     ui.subFrame->setEnabled( false );
109
110     /* Connects  */
111     BUTTONACT( ui.fileBrowseButton, browseFile() );
112     BUTTONACT( ui.removeFileButton, removeFile() );
113
114     BUTTONACT( ui.subBrowseButton, browseFileSub() );
115     CONNECT( ui.subCheckBox, toggled( bool ), this, toggleSubtitleFrame( bool ) );
116
117     CONNECT( ui.fileListWidg, itemChanged( QListWidgetItem * ), this, updateMRL() );
118     CONNECT( ui.subInput, textChanged( const QString& ), this, updateMRL() );
119     updateButtons();
120 }
121
122 inline void FileOpenPanel::BuildOldPanel()
123 {
124     /** BEGIN QFileDialog tweaking **/
125     /* Use a QFileDialog and customize it because we don't want to
126        rewrite it all. Be careful to your eyes cause there are a few hacks.
127        Be very careful and test correctly when you modify this. */
128
129     /* Make this QFileDialog a child of tempWidget from the ui. */
130     dialogBox = new FileOpenBox( ui.tempWidget, NULL,
131                                  p_intf->p_sys->filepath, "" );
132
133     dialogBox->setFileMode( QFileDialog::ExistingFiles );
134     dialogBox->setAcceptMode( QFileDialog::AcceptOpen );
135     dialogBox->restoreState(
136             getSettings()->value( "file-dialog-state" ).toByteArray() );
137
138     /* We don't want to see a grip in the middle of the window, do we? */
139     dialogBox->setSizeGripEnabled( false );
140
141     /* Add a tooltip */
142     dialogBox->setToolTip( qtr( "Select one or multiple files" ) );
143     dialogBox->setMinimumHeight( 250 );
144
145     // But hide the two OK/Cancel buttons. Enable them for debug.
146     QDialogButtonBox *fileDialogAcceptBox =
147                       dialogBox->findChildren<QDialogButtonBox*>()[0];
148     fileDialogAcceptBox->hide();
149
150     /* Ugly hacks to get the good Widget */
151     //This lineEdit is the normal line in the fileDialog.
152     QLineEdit *lineFileEdit = dialogBox->findChildren<QLineEdit*>()[0];
153     /* Make a list of QLabel inside the QFileDialog to access the good ones */
154     QList<QLabel *> listLabel = dialogBox->findChildren<QLabel*>();
155
156     /* Hide the FileNames one. Enable it for debug */
157     listLabel[1]->setText( qtr( "File names:" ) );
158     /* Change the text that was uncool in the usual box */
159     listLabel[2]->setText( qtr( "Filter:" ) );
160
161     dialogBox->layout()->setMargin( 0 );
162     dialogBox->layout()->setSizeConstraint( QLayout::SetNoConstraint );
163
164     /** END of QFileDialog tweaking **/
165
166     // Add the DialogBox to the layout
167     ui.gridLayout->addWidget( dialogBox, 0, 0, 1, 3 );
168
169     CONNECT( lineFileEdit, textChanged( const QString& ), this, updateMRL() );
170     dialogBox->installEventFilter( this );
171 }
172
173 FileOpenPanel::~FileOpenPanel()
174 {
175     if( dialogBox )
176         getSettings()->setValue( "file-dialog-state", dialogBox->saveState() );
177 }
178
179 void FileOpenPanel::dragEnterEvent( QDragEnterEvent *event )
180 {
181     event->acceptProposedAction();
182 }
183
184 void FileOpenPanel::dragMoveEvent( QDragMoveEvent *event )
185 {
186     event->acceptProposedAction();
187 }
188
189 void FileOpenPanel::dragLeaveEvent( QDragLeaveEvent *event )
190 {
191     event->accept();
192 }
193
194 void FileOpenPanel::dropEvent( QDropEvent *event )
195 {
196     if( event->possibleActions() & Qt::CopyAction )
197        event->setDropAction( Qt::CopyAction );
198     else
199         return;
200
201     const QMimeData *mimeData = event->mimeData();
202     foreach( const QUrl &url, mimeData->urls() )
203     {
204         if( url.isValid() )
205         {
206             QListWidgetItem *item = new QListWidgetItem(
207                                          toNativeSeparators( url.toLocalFile() ),
208                                          ui.fileListWidg );
209             item->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled );
210             ui.fileListWidg->addItem( item );
211         }
212     }
213     updateMRL();
214     updateButtons();
215     event->accept();
216 }
217
218 void FileOpenPanel::browseFile()
219 {
220     QStringList files = QFileDialog::getOpenFileNames( this, qtr( "Select one or multiple files" ), p_intf->p_sys->filepath) ;
221     foreach( const QString &file, files )
222     {
223         QListWidgetItem *item =
224             new QListWidgetItem( toNativeSeparators( file ), ui.fileListWidg );
225         item->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled );
226         ui.fileListWidg->addItem( item );
227         savedirpathFromFile( file );
228     }
229     updateButtons();
230     updateMRL();
231 }
232
233 void FileOpenPanel::removeFile()
234 {
235     int i = ui.fileListWidg->currentRow();
236     if( i != -1 )
237     {
238         QListWidgetItem *temp = ui.fileListWidg->takeItem( i );
239         delete temp;
240     }
241
242     updateMRL();
243     updateButtons();
244 }
245
246 /* Show a fileBrowser to select a subtitle */
247 void FileOpenPanel::browseFileSub()
248 {
249     // TODO Handle selection of more than one subtitles file
250     QStringList files = THEDP->showSimpleOpen( qtr("Open subtitles file"),
251                            EXT_FILTER_SUBTITLE, p_intf->p_sys->filepath );
252
253     if( files.isEmpty() ) return;
254     ui.subInput->setText( toNativeSeparators( files.join(" ") ) );
255     updateMRL();
256 }
257
258 void FileOpenPanel::toggleSubtitleFrame( bool b )
259 {
260     ui.subFrame->setEnabled( b );
261
262     /* Update the MRL */
263     updateMRL();
264 }
265
266
267 /* Update the current MRL */
268 void FileOpenPanel::updateMRL()
269 {
270     QStringList fileList;
271     QString mrl;
272
273     /* File Listing */
274     if( dialogBox == NULL )
275         for( int i = 0; i < ui.fileListWidg->count(); i++ )
276         {
277             if( !ui.fileListWidg->item( i )->text().isEmpty() )
278                 fileList << toURI(ui.fileListWidg->item( i )->text());
279         }
280     else
281     {
282         fileList = dialogBox->selectedFiles();
283         for( int i = 0; i < fileList.count(); i++ )
284             fileList[i] = toURI( fileList[i] );
285     }
286
287     /* Options */
288     if( ui.subCheckBox->isChecked() &&  !ui.subInput->text().isEmpty() ) {
289         mrl.append( " :sub-file=" + colon_escape( ui.subInput->text() ) );
290     }
291
292     emit methodChanged( "file-caching" );
293     emit mrlUpdated( fileList, mrl );
294 }
295
296 /* Function called by Open Dialog when clicke on Play/Enqueue */
297 void FileOpenPanel::accept()
298 {
299     if( dialogBox )
300         p_intf->p_sys->filepath = dialogBox->directory().absolutePath();
301     ui.fileListWidg->clear();
302 }
303
304 /* Function called by Open Dialog when clicked on cancel */
305 void FileOpenPanel::clear()
306 {
307     ui.fileListWidg->clear();
308     ui.subInput->clear();
309 }
310
311 /* Update buttons depending on current selection */
312 void FileOpenPanel::updateButtons()
313 {
314     bool b_has_files = ( ui.fileListWidg->count() > 0 );
315     ui.removeFileButton->setEnabled( b_has_files );
316     ui.subCheckBox->setEnabled( b_has_files );
317 }
318
319 /**************************************************************************
320  * Open Discs ( DVD, CD, VCD and similar devices )                        *
321  **************************************************************************/
322 DiscOpenPanel::DiscOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
323                                 OpenPanel( _parent, _p_intf )
324 {
325     ui.setupUi( this );
326
327     /* Get the default configuration path for the devices */
328     psz_dvddiscpath = var_InheritString( p_intf, "dvd" );
329     psz_vcddiscpath = var_InheritString( p_intf, "vcd" );
330     psz_cddadiscpath = var_InheritString( p_intf, "cd-audio" );
331
332     /* State to avoid overwritting the users changes with the configuration */
333     m_discType = None;
334
335     ui.browseDiscButton->setToolTip( qtr( I_DEVICE_TOOLTIP ));
336     ui.deviceCombo->setToolTip( qtr(I_DEVICE_TOOLTIP) );
337     ui.deviceCombo->setInsertPolicy( QComboBox::InsertAtTop );
338
339     /* CONNECTs */
340     BUTTONACT( ui.dvdRadioButton,     updateButtons() );
341     BUTTONACT( ui.bdRadioButton,      updateButtons() );
342     BUTTONACT( ui.vcdRadioButton,     updateButtons() );
343     BUTTONACT( ui.audioCDRadioButton, updateButtons() );
344     BUTTONACT( ui.dvdsimple,          updateButtons() );
345     BUTTONACT( ui.browseDiscButton, browseDevice() );
346     BUTTON_SET_ACT_I( ui.ejectButton, "", toolbar/eject, qtr( "Eject the disc" ),
347             eject() );
348
349     CONNECT( ui.deviceCombo, editTextChanged( QString ), this, updateMRL());
350     CONNECT( ui.deviceCombo, currentIndexChanged( QString ), this, updateMRL());
351     CONNECT( ui.titleSpin, valueChanged( int ), this, updateMRL());
352     CONNECT( ui.chapterSpin, valueChanged( int ), this, updateMRL());
353     CONNECT( ui.audioSpin, valueChanged( int ), this, updateMRL());
354     CONNECT( ui.subtitlesSpin, valueChanged( int ), this, updateMRL());
355
356     /* Run once the updateButtons function in order to fill correctly the comboBoxes */
357     updateButtons();
358 }
359
360 void DiscOpenPanel::onFocus()
361 {
362 #ifdef WIN32 /* Disc drives probing for Windows */
363     wchar_t szDrives[512];
364     szDrives[0] = '\0';
365     if( GetLogicalDriveStringsW( sizeof( szDrives ) - 1, szDrives ) )
366     {
367         wchar_t *drive = szDrives;
368         UINT oldMode = SetErrorMode( SEM_FAILCRITICALERRORS );
369         while( *drive )
370         {
371             if( GetDriveTypeW(drive) == DRIVE_CDROM )
372             {
373                 wchar_t psz_name[512] = L"";
374                 GetVolumeInformationW( drive, psz_name, 511, NULL, NULL, NULL, NULL, 0 );
375
376                 QString displayName = FromWide( drive );
377                 if( !*psz_name ) {
378                     displayName = displayName + " - "  + FromWide( psz_name );
379                 }
380
381                 ui.deviceCombo->addItem( displayName, FromWide( drive ) );
382             }
383
384             /* go to next drive */
385             while( *(drive++) );
386         }
387         SetErrorMode(oldMode);
388     }
389 #else /* Linux */
390     char const * const ppsz_discdevices[] = {
391         "sr*",
392         "sg*",
393         "scd*",
394         "dvd*",
395         "cd*"
396     };
397     QComboBox *discCombo = ui.deviceCombo; /* avoid namespacing in macro */
398     POPULATE_WITH_DEVS( ppsz_discdevices, discCombo );
399 #endif
400
401
402 }
403
404 DiscOpenPanel::~DiscOpenPanel()
405 {
406     free( psz_dvddiscpath );
407     free( psz_vcddiscpath );
408     free( psz_cddadiscpath );
409 }
410
411 void DiscOpenPanel::clear()
412 {
413     ui.titleSpin->setValue( 0 );
414     ui.chapterSpin->setValue( 0 );
415     ui.subtitlesSpin->setValue( -1 );
416     ui.audioSpin->setValue( -1 );
417     m_discType = None;
418 }
419
420 #ifdef WIN32
421     #define setDrive( psz_name ) {\
422     int index = ui.deviceCombo->findText( qfu( psz_name ) ); \
423     if( index != -1 ) ui.deviceCombo->setCurrentIndex( index );}
424 #else
425     #define setDrive( psz_name ) {\
426     ui.deviceCombo->setEditText( qfu( psz_name ) ); }
427 #endif
428
429 /* update the buttons according the type of device */
430 void DiscOpenPanel::updateButtons()
431 {
432     if ( ui.dvdRadioButton->isChecked() )
433     {
434         if( m_discType != Dvd )
435         {
436             setDrive( psz_dvddiscpath );
437             m_discType = Dvd;
438         }
439         ui.titleLabel->setText( qtr("Title") );
440         ui.chapterLabel->show();
441         ui.chapterSpin->show();
442         ui.diskOptionBox_2->show();
443         ui.dvdsimple->setEnabled( true );
444     }
445     else if ( ui.bdRadioButton->isChecked() )
446     {
447         if( m_discType != BRD )
448         {
449             setDrive( psz_dvddiscpath );
450             m_discType = BRD;
451         }
452         ui.titleLabel->setText( qtr("Title") );
453         ui.chapterLabel->hide();
454         ui.chapterSpin->hide();
455         ui.diskOptionBox_2->hide();
456         ui.dvdsimple->setEnabled( true );
457     }
458     else if ( ui.vcdRadioButton->isChecked() )
459     {
460         if( m_discType != Vcd )
461         {
462             setDrive( psz_vcddiscpath );
463             m_discType = Vcd;
464         }
465         ui.titleLabel->setText( qtr("Entry") );
466         ui.chapterLabel->hide();
467         ui.chapterSpin->hide();
468         ui.diskOptionBox_2->show();
469         ui.dvdsimple->setEnabled( false );
470     }
471     else /* CDDA */
472     {
473         if( m_discType != Cdda )
474         {
475             setDrive( psz_cddadiscpath );
476             m_discType = Cdda;
477         }
478         ui.titleLabel->setText( qtr("Track") );
479         ui.chapterLabel->hide();
480         ui.chapterSpin->hide();
481         ui.diskOptionBox_2->hide();
482         ui.dvdsimple->setEnabled( false );
483     }
484
485     updateMRL();
486 }
487
488 #undef setDrive
489
490 #ifndef WIN32
491 # define LOCALHOST ""
492 #else
493 # define LOCALHOST "/"
494 #endif
495
496 /* Update the current MRL */
497 void DiscOpenPanel::updateMRL()
498 {
499     QString mrl;
500     QString discPath;
501     QStringList fileList;
502
503     if( ui.deviceCombo->itemData( ui.deviceCombo->currentIndex() ) != QVariant::Invalid )
504         discPath = ui.deviceCombo->itemData( ui.deviceCombo->currentIndex() ).toString();
505     else
506         discPath = ui.deviceCombo->currentText();
507
508     /* MRL scheme */
509     /* DVD */
510     if( ui.dvdRadioButton->isChecked() ) {
511         if( !ui.dvdsimple->isChecked() )
512             mrl = "dvd://" LOCALHOST;
513         else
514             mrl = "dvdsimple://" LOCALHOST + discPath;
515     } else if ( ui.bdRadioButton->isChecked() )
516         mrl = "bluray://" LOCALHOST;
517     /* VCD */
518     else if ( ui.vcdRadioButton->isChecked() )
519         mrl = "vcd://" LOCALHOST;
520     /* CDDA */
521     else
522         mrl = "cdda://" LOCALHOST;
523
524     mrl += discPath;
525
526     /* Title/chapter encoded in MRL */
527     if( ui.titleSpin->value() > 0 ) {
528         if( ui.dvdRadioButton->isChecked() || ui.bdRadioButton->isChecked() ) {
529             mrl += QString("#%1").arg( ui.titleSpin->value() );
530             if ( ui.chapterSpin->value() > 0 )
531                 mrl+= QString(":%1").arg( ui.chapterSpin->value() );
532         }
533         else if ( ui.vcdRadioButton->isChecked() )
534             mrl += QString("@%1").arg( ui.titleSpin->value() );
535     }
536
537     emit methodChanged( "disc-caching" );
538
539     fileList << mrl; mrl = "";
540
541     /* Input item options */
542     if ( ui.dvdRadioButton->isChecked() || ui.vcdRadioButton->isChecked() )
543     {
544         if ( ui.audioSpin->value() >= 0 ) {
545             mrl += " :audio-track=" +
546                 QString("%1").arg( ui.audioSpin->value() );
547         }
548         if ( ui.subtitlesSpin->value() >= 0 ) {
549             mrl += " :sub-track=" +
550                 QString("%1").arg( ui.subtitlesSpin->value() );
551         }
552     }
553     if( ui.audioCDRadioButton->isChecked() )
554     {
555         if( ui.titleSpin->value() > 0 )
556             mrl += QString(" :cdda-track=%1").arg( ui.titleSpin->value() );
557     }
558     emit mrlUpdated( fileList, mrl );
559 }
560
561 void DiscOpenPanel::browseDevice()
562 {
563     QString dir = QFileDialog::getExistingDirectory( this,
564             qtr( I_DEVICE_TOOLTIP ) );
565     if( !dir.isEmpty() )
566     {
567         ui.deviceCombo->addItem( toNativeSepNoSlash( dir ) );
568         ui.deviceCombo->setCurrentIndex( ui.deviceCombo->findText( toNativeSepNoSlash( dir ) ) );
569         updateMRL();
570     }
571
572     updateMRL();
573 }
574
575 void DiscOpenPanel::eject()
576 {
577     intf_Eject( p_intf, qtu( ui.deviceCombo->currentText() ) );
578 }
579
580 void DiscOpenPanel::accept()
581 {}
582
583 /**************************************************************************
584  * Open Network streams and URL pages                                     *
585  **************************************************************************/
586 NetOpenPanel::NetOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
587                                 OpenPanel( _parent, _p_intf )
588 {
589     ui.setupUi( this );
590     CONNECT( ui.urlComboBox, editTextChanged( const QString& ), this, updateMRL());
591
592     /* */
593     if( var_InheritBool( p_intf, "qt-recentplay" ) )
594     {
595         b_recentList = true;
596         ui.urlComboBox->addItems( getSettings()->value( "OpenDialog/netMRL" ).toStringList() );
597         ui.urlComboBox->setMaxCount( 10 );
598     }
599     else
600         b_recentList = false;
601
602     /* Use a simple validator for URLs */
603     ui.urlComboBox->setValidator( new UrlValidator( this ) );
604     ui.urlComboBox->setFocus();
605 }
606
607 NetOpenPanel::~NetOpenPanel()
608 {
609     if( !b_recentList ) return;
610
611     /* Create the list with the current items */
612     QStringList mrlList;
613     for( int i = 0; i < ui.urlComboBox->count(); i++ )
614         mrlList << ui.urlComboBox->itemText( i );
615
616     /* Clean the list... */
617     mrlList.removeDuplicates();
618     /* ...and save the 8 last entries */
619     getSettings()->setValue( "OpenDialog/netMRL", mrlList );
620 }
621
622 void NetOpenPanel::clear()
623 {
624     ui.urlComboBox->clear();
625 }
626
627 void NetOpenPanel::onAccept()
628 {
629     if( ui.urlComboBox->findText( ui.urlComboBox->currentText() ) == -1 )
630         ui.urlComboBox->insertItem( 0, ui.urlComboBox->currentText());
631 }
632
633 void NetOpenPanel::onFocus()
634 {
635     ui.urlComboBox->setFocus();
636     ui.urlComboBox->lineEdit()->selectAll();
637 }
638
639 void NetOpenPanel::updateMRL()
640 {
641     QString url = ui.urlComboBox->lineEdit()->text();
642
643     if( url.isEmpty() )
644         return;
645
646     emit methodChanged( qfu( "network-caching" ) );
647
648     QStringList qsl;
649     qsl << url;
650     emit mrlUpdated( qsl, "" );
651 }
652
653 QValidator::State UrlValidator::validate( QString& str, int& ) const
654 {
655     if( str.contains( ' ' ) )
656         return QValidator::Invalid;
657     if( !str.contains( "://" ) )
658         return QValidator::Intermediate;
659     return QValidator::Acceptable;
660 }
661
662 void UrlValidator::fixup( QString& str ) const
663 {
664     str = str.trimmed();
665 }
666
667 /**************************************************************************
668  * Open Capture device ( DVB, PVR, V4L, and similar )                     *
669  **************************************************************************/
670 CaptureOpenPanel::CaptureOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
671                                 OpenPanel( _parent, _p_intf )
672 {
673     isInitialized = false;
674 }
675
676 void CaptureOpenPanel::initialize()
677 {
678     if( isInitialized ) return;
679
680     isInitialized = true;
681
682     ui.setupUi( this );
683
684     BUTTONACT( ui.advancedButton, advancedDialog() );
685
686     /* Create two stacked layouts in the main comboBoxes */
687     QStackedLayout *stackedDevLayout = new QStackedLayout;
688     ui.cardBox->setLayout( stackedDevLayout );
689
690     QStackedLayout *stackedPropLayout = new QStackedLayout;
691     ui.optionsBox->setLayout( stackedPropLayout );
692
693     /* Creation and connections of the WIdgets in the stacked layout */
694 #define addModuleAndLayouts( number, name, label, layout )            \
695     QWidget * name ## DevPage = new QWidget( this );                  \
696     QWidget * name ## PropPage = new QWidget( this );                 \
697     stackedDevLayout->addWidget( name ## DevPage );        \
698     stackedPropLayout->addWidget( name ## PropPage );      \
699     layout * name ## DevLayout = new layout;                \
700     layout * name ## PropLayout = new layout;               \
701     name ## DevPage->setLayout( name ## DevLayout );                  \
702     name ## PropPage->setLayout( name ## PropLayout );                \
703     ui.deviceCombo->addItem( qtr( label ), QVariant( number ) );
704
705 #define CuMRL( widget, slot ) CONNECT( widget , slot , this, updateMRL() );
706
707 #ifdef WIN32
708     /*********************
709      * DirectShow Stuffs *
710      *********************/
711     if( module_exists( "dshow" ) ){
712     addModuleAndLayouts( DSHOW_DEVICE, dshow, "DirectShow", QGridLayout );
713
714     /* dshow Main */
715     int line = 0;
716     module_config_t *p_config =
717         config_FindConfig( VLC_OBJECT(p_intf), "dshow-vdev" );
718     vdevDshowW = new StringListConfigControl(
719         VLC_OBJECT(p_intf), p_config, this, dshowDevLayout, line );
720     line++;
721
722     p_config = config_FindConfig( VLC_OBJECT(p_intf), "dshow-adev" );
723     adevDshowW = new StringListConfigControl(
724         VLC_OBJECT(p_intf), p_config, this, dshowDevLayout, line );
725     line++;
726
727     /* dshow Properties */
728     QLabel *dshowVSizeLabel = new QLabel( qtr( "Video size" ) );
729     dshowPropLayout->addWidget( dshowVSizeLabel, 0, 0 );
730
731     dshowVSizeLine = new QLineEdit;
732     dshowPropLayout->addWidget( dshowVSizeLine, 0, 1);
733     dshowPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
734             1, 0, 3, 1 );
735
736     /* dshow CONNECTs */
737     CuMRL( vdevDshowW->combo, currentIndexChanged ( int ) );
738     CuMRL( adevDshowW->combo, currentIndexChanged ( int ) );
739     CuMRL( dshowVSizeLine, textChanged( const QString& ) );
740     configList << "dshow-vdev" << "dshow-adev" << "dshow-size";
741     }
742 #else /* WIN32 */
743     /*******
744      * V4L2*
745      *******/
746     if( module_exists( "v4l2" ) ){
747     addModuleAndLayouts( V4L2_DEVICE, v4l2, "Video for Linux 2", QGridLayout );
748
749     char const * const ppsz_v4lvdevices[] = {
750         "video*"
751     };
752
753     /* V4L2 main panel */
754     QLabel *v4l2VideoDeviceLabel = new QLabel( qtr( "Video device name" ) );
755     v4l2DevLayout->addWidget( v4l2VideoDeviceLabel, 0, 0 );
756
757     v4l2VideoDevice = new QComboBox( this );
758     v4l2VideoDevice->setEditable( true );
759     POPULATE_WITH_DEVS( ppsz_v4lvdevices, v4l2VideoDevice );
760     v4l2VideoDevice->clearEditText();
761     v4l2DevLayout->addWidget( v4l2VideoDevice, 0, 1 );
762
763     QLabel *v4l2AudioDeviceLabel = new QLabel( qtr( "Audio device name" ) );
764     v4l2DevLayout->addWidget( v4l2AudioDeviceLabel, 1, 0 );
765
766     v4l2AudioDevice = new QComboBox( this );
767     v4l2AudioDevice->setEditable( true );
768     {
769         QStringList patterns = QStringList();
770         patterns << QString( "pcmC*D*c" );
771
772         QStringList nodes = QDir( "/dev/snd" ).entryList( patterns,
773                                                           QDir::System );
774         QStringList names = nodes.replaceInStrings( QRegExp("^pcmC"), "hw:" )
775                                  .replaceInStrings( QRegExp("c$"), "" )
776                                  .replaceInStrings( QRegExp("D"), "," );
777         v4l2AudioDevice->addItems( names );
778     }
779     v4l2AudioDevice->clearEditText();
780     v4l2DevLayout->addWidget( v4l2AudioDevice, 1, 1 );
781
782     /* v4l2 Props panel */
783     QLabel *v4l2StdLabel = new QLabel( qtr( "Video standard" ) );
784     v4l2PropLayout->addWidget( v4l2StdLabel, 0 , 0 );
785
786     v4l2StdBox = new QComboBox;
787     setfillVLCConfigCombo( "v4l2-standard", p_intf, v4l2StdBox );
788     v4l2PropLayout->addWidget( v4l2StdBox, 0 , 1 );
789     v4l2PropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
790             1, 0, 3, 2 );
791
792     /* v4l2 CONNECTs */
793     CuMRL( v4l2VideoDevice->lineEdit(), textChanged( const QString& ) );
794     CuMRL( v4l2VideoDevice,  currentIndexChanged ( int ) );
795     CuMRL( v4l2AudioDevice->lineEdit(), textChanged( const QString& ) );
796     CuMRL( v4l2AudioDevice,  currentIndexChanged ( int ) );
797     CuMRL( v4l2StdBox,  currentIndexChanged ( int ) );
798     configList << "v4l2-standard" << "v4l2-dev";
799     }
800
801     /*******
802      * JACK *
803      *******/
804     if( module_exists( "jack" ) ){
805     addModuleAndLayouts( JACK_DEVICE, jack, "JACK Audio Connection Kit",
806                          QGridLayout);
807
808     /* Jack Main panel */
809     /* Channels */
810     QLabel *jackChannelsLabel = new QLabel( qtr( "Channels:" ) );
811     jackDevLayout->addWidget( jackChannelsLabel, 1, 0 );
812
813     jackChannels = new QSpinBox;
814     setSpinBoxFreq( jackChannels );
815     jackChannels->setMaximum(255);
816     jackChannels->setValue(2);
817     jackChannels->setAlignment( Qt::AlignRight );
818     jackDevLayout->addWidget( jackChannels, 1, 1 );
819
820     /* Selected ports */
821     QLabel *jackPortsLabel = new QLabel( qtr( "Selected ports:" ) );
822     jackDevLayout->addWidget( jackPortsLabel, 0 , 0 );
823
824     jackPortsSelected = new QLineEdit( qtr( ".*") );
825     jackPortsSelected->setAlignment( Qt::AlignRight );
826     jackDevLayout->addWidget( jackPortsSelected, 0, 1 );
827
828     /* Jack Props panel */
829
830     /* Pace */
831     jackPace = new QCheckBox(qtr( "Use VLC pace" ));
832     jackPropLayout->addWidget( jackPace, 1, 1 );
833
834     /* Auto Connect */
835     jackConnect = new QCheckBox( qtr( "Auto connection" ));
836     jackPropLayout->addWidget( jackConnect, 1, 2 );
837
838     /* Jack CONNECTs */
839     CuMRL( jackChannels, valueChanged( int ) );
840     CuMRL( jackPace, stateChanged( int ) );
841     CuMRL( jackConnect, stateChanged( int ) );
842     CuMRL( jackPortsSelected, textChanged( const QString& ) );
843     configList << "jack-input-use-vlc-pace" << "jack-input-auto-connect";
844     }
845
846     /************
847      * PVR      *
848      ************/
849     if( module_exists( "pvr" ) ){
850     addModuleAndLayouts( PVR_DEVICE, pvr, "PVR", QGridLayout );
851
852     /* PVR Main panel */
853     QLabel *pvrDeviceLabel = new QLabel( qtr( "Device name" ) );
854     pvrDevLayout->addWidget( pvrDeviceLabel, 0, 0 );
855
856     pvrDevice = new QLineEdit;
857     pvrDevLayout->addWidget( pvrDevice, 0, 1 );
858
859     QLabel *pvrRadioDeviceLabel = new QLabel( qtr( "Radio device name" ) );
860     pvrDevLayout->addWidget( pvrRadioDeviceLabel, 1, 0 );
861
862     pvrRadioDevice = new QLineEdit;
863     pvrDevLayout->addWidget( pvrRadioDevice, 1, 1 );
864
865     /* PVR props panel */
866     QLabel *pvrNormLabel = new QLabel( qtr( "Norm" ) );
867     pvrPropLayout->addWidget( pvrNormLabel, 0, 0 );
868
869     pvrNormBox = new QComboBox;
870     setfillVLCConfigCombo( "pvr-norm", p_intf, pvrNormBox );
871     pvrPropLayout->addWidget( pvrNormBox, 0, 1 );
872
873     QLabel *pvrFreqLabel = new QLabel( qtr( "Frequency" ) );
874     pvrPropLayout->addWidget( pvrFreqLabel, 1, 0 );
875
876     pvrFreq = new QSpinBox;
877     pvrFreq->setAlignment( Qt::AlignRight );
878     pvrFreq->setSuffix(" kHz");
879     setSpinBoxFreq( pvrFreq );
880     pvrPropLayout->addWidget( pvrFreq, 1, 1 );
881
882     QLabel *pvrBitrLabel = new QLabel( qtr( "Bitrate" ) );
883     pvrPropLayout->addWidget( pvrBitrLabel, 2, 0 );
884
885     pvrBitr = new QSpinBox;
886     pvrBitr->setAlignment( Qt::AlignRight );
887     pvrBitr->setSuffix(" kHz");
888     setSpinBoxFreq( pvrBitr );
889     pvrPropLayout->addWidget( pvrBitr, 2, 1 );
890     pvrPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
891             3, 0, 1, 1 );
892
893     /* PVR CONNECTs */
894     CuMRL( pvrDevice, textChanged( const QString& ) );
895     CuMRL( pvrRadioDevice, textChanged( const QString& ) );
896
897     CuMRL( pvrFreq, valueChanged ( int ) );
898     CuMRL( pvrBitr, valueChanged ( int ) );
899     CuMRL( pvrNormBox, currentIndexChanged ( int ) );
900     configList << "pvr-device" << "pvr-radio-device" << "pvr-norm"
901                << "pvr-frequency" << "pvr-bitrate";
902     }
903 #endif
904     /*************
905      * DVB Stuff *
906      *************/
907     if( module_exists( "dtv" ) ){
908     addModuleAndLayouts( DTV_DEVICE, dvb, N_("TV (digital)"), QGridLayout );
909
910     /* DVB Main */
911     QLabel *dvbDeviceLabel = new QLabel( qtr( "Tuner card" ) );
912     QLabel *dvbTypeLabel = new QLabel( qtr( "Delivery system" ) );
913
914     dvbCard = new QSpinBox;
915     dvbCard->setAlignment( Qt::AlignRight );
916 #ifdef __linux__
917     dvbCard->setPrefix( "/dev/dvb/adapter" );
918 #endif
919     dvbDevLayout->addWidget( dvbDeviceLabel, 0, 0 );
920     dvbDevLayout->addWidget( dvbCard, 0, 1, 1, 2 );
921
922     dvbc = new QRadioButton( "DVB-C" );
923     dvbs = new QRadioButton( "DVB-S" );
924     dvbs2 = new QRadioButton( "DVB-S2" );
925     dvbt = new QRadioButton( "DVB-T" );
926     dvbt2 = new QRadioButton( "DVB-T2" );
927     atsc = new QRadioButton( "ATSC" );
928     cqam = new QRadioButton( "Clear QAM" );
929     dvbt->setChecked( true );
930
931     dvbDevLayout->addWidget( dvbTypeLabel, 1, 0, 2, 1 );
932     dvbDevLayout->addWidget( dvbc,  1, 1 );
933     dvbDevLayout->addWidget( dvbs,  1, 2 );
934     dvbDevLayout->addWidget( dvbs2, 2, 2 );
935     dvbDevLayout->addWidget( dvbt,  1, 3 );
936     dvbDevLayout->addWidget( dvbt2, 2, 3 );
937     dvbDevLayout->addWidget( atsc,  1, 4 );
938     dvbDevLayout->addWidget( cqam,  2, 4 );
939
940     /* DVB Props panel */
941     QLabel *dvbFreqLabel =
942                     new QLabel( qtr( "Transponder/multiplex frequency" ) );
943     dvbPropLayout->addWidget( dvbFreqLabel, 0, 0 );
944
945     dvbFreq = new QSpinBox;
946     dvbFreq->setAlignment( Qt::AlignRight );
947     dvbFreq->setSuffix(" kHz");
948     dvbFreq->setSingleStep( 1000 );
949     setSpinBoxFreq( dvbFreq  );
950     dvbPropLayout->addWidget( dvbFreq, 0, 1 );
951
952     dvbSrateLabel = new QLabel( qtr( "Transponder symbol rate" ) );
953     dvbPropLayout->addWidget( dvbSrateLabel, 1, 0 );
954
955     dvbSrate = new QSpinBox;
956     dvbSrate->setAlignment( Qt::AlignRight );
957     dvbSrate->setSuffix(" bauds");
958     setSpinBoxFreq( dvbSrate );
959     dvbPropLayout->addWidget( dvbSrate, 1, 1 );
960
961     dvbModLabel = new QLabel( qtr( "Modulation / Constellation" ) );
962     dvbPropLayout->addWidget( dvbModLabel, 2, 0 );
963
964     dvbQamBox = new QComboBox;
965     dvbQamBox->addItem( qtr( "Automatic" ), qfu("QAM") );
966     dvbQamBox->addItem( "256-QAM", qfu("256QAM") );
967     dvbQamBox->addItem( "128-QAM", qfu("128QAM") );
968     dvbQamBox->addItem( "64-QAM", qfu("64QAM") );
969     dvbQamBox->addItem( "32-QAM", qfu("32QAM") );
970     dvbQamBox->addItem( "16-QAM", qfu("16QAM") );
971     dvbPropLayout->addWidget( dvbQamBox, 2, 1 );
972
973     dvbPskBox = new QComboBox;
974     dvbPskBox->addItem( "QPSK", qfu("QPSK") );
975     dvbPskBox->addItem( "DQPSK", qfu("DQPSK") );
976     dvbPskBox->addItem( "8-PSK", qfu("8PSK") );
977     dvbPskBox->addItem( "16-APSK", qfu("16APSK") );
978     dvbPskBox->addItem( "32-APSK", qfu("32APSK") );
979     dvbPropLayout->addWidget( dvbPskBox, 2, 1 );
980
981     dvbModLabel->hide();
982     dvbQamBox->hide();
983     dvbPskBox->hide();
984
985     dvbBandLabel = new QLabel( qtr( "Bandwidth" ) );
986     dvbPropLayout->addWidget( dvbBandLabel, 2, 0 );
987
988     dvbBandBox = new QComboBox;
989     setfillVLCConfigCombo( "dvb-bandwidth", p_intf, dvbBandBox );
990     dvbPropLayout->addWidget( dvbBandBox, 2, 1 );
991
992     dvbBandLabel->hide();
993     dvbBandBox->hide();
994
995     dvbPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
996             2, 0, 2, 1 );
997
998     /* DVB CONNECTs */
999     CuMRL( dvbCard, valueChanged ( int ) );
1000     CuMRL( dvbFreq, valueChanged ( int ) );
1001     CuMRL( dvbSrate, valueChanged ( int ) );
1002     CuMRL( dvbQamBox, currentIndexChanged ( int ) );
1003     CuMRL( dvbPskBox, currentIndexChanged ( int ) );
1004     CuMRL( dvbBandBox, currentIndexChanged ( int ) );
1005
1006     BUTTONACT( dvbc, updateButtons() );
1007     BUTTONACT( dvbs, updateButtons() );
1008     BUTTONACT( dvbs2, updateButtons() );
1009     BUTTONACT( dvbt, updateButtons() );
1010     BUTTONACT( dvbt2, updateButtons() );
1011     BUTTONACT( atsc, updateButtons() );
1012     BUTTONACT( cqam, updateButtons() );
1013     BUTTONACT( dvbc, updateMRL() );
1014     BUTTONACT( dvbt, updateMRL() );
1015     BUTTONACT( dvbt2, updateMRL() );
1016     BUTTONACT( dvbs, updateMRL() );
1017     BUTTONACT( dvbs2, updateMRL() );
1018     BUTTONACT( atsc, updateMRL() );
1019     BUTTONACT( cqam, updateMRL() );
1020     configList << "dvb-adapter" << "dvb-frequency" << "dvb-modulation"
1021                << "dvb-bandwidth";
1022     }
1023
1024     /**********
1025      * Screen *
1026      **********/
1027     addModuleAndLayouts( SCREEN_DEVICE, screen, "Desktop", QGridLayout );
1028     QLabel *screenLabel = new QLabel( qtr( "Your display will be "
1029             "opened and played in order to stream or save it." ) );
1030     screenLabel->setWordWrap( true );
1031     screenDevLayout->addWidget( screenLabel, 0, 0 );
1032
1033     QLabel *screenFPSLabel = new QLabel(
1034             qtr( "Desired frame rate for the capture." ) );
1035     screenPropLayout->addWidget( screenFPSLabel, 0, 0 );
1036
1037     screenFPS = new QDoubleSpinBox;
1038     screenFPS->setValue( 1. );
1039     screenFPS->setRange( .01, 100. );
1040     screenFPS->setAlignment( Qt::AlignRight );
1041     /* xgettext: frames per second */
1042     screenFPS->setSuffix( qtr( " f/s" ) );
1043     screenPropLayout->addWidget( screenFPS, 0, 1 );
1044
1045     /* Screen connect */
1046     CuMRL( screenFPS, valueChanged( double ) );
1047
1048     /* General connects */
1049     CONNECT( ui.deviceCombo, activated( int ) ,
1050              stackedDevLayout, setCurrentIndex( int ) );
1051     CONNECT( ui.deviceCombo, activated( int ),
1052              stackedPropLayout, setCurrentIndex( int ) );
1053     CONNECT( ui.deviceCombo, activated( int ), this, updateMRL() );
1054     CONNECT( ui.deviceCombo, activated( int ), this, updateButtons() );
1055
1056 #undef CuMRL
1057 #undef addModuleAndLayouts
1058 }
1059
1060 CaptureOpenPanel::~CaptureOpenPanel()
1061 {
1062 }
1063
1064 void CaptureOpenPanel::clear()
1065 {
1066     advMRL.clear();
1067 }
1068
1069 void CaptureOpenPanel::updateMRL()
1070 {
1071     QString mrl = "";
1072     QStringList fileList;
1073     int i_devicetype = ui.deviceCombo->itemData(
1074             ui.deviceCombo->currentIndex() ).toInt();
1075     switch( i_devicetype )
1076     {
1077 #ifdef WIN32
1078     case DSHOW_DEVICE:
1079         fileList << "dshow://";
1080         mrl+= " :dshow-vdev=" +
1081             colon_escape( QString("%1").arg( vdevDshowW->getValue() ) );
1082         mrl+= " :dshow-adev=" +
1083             colon_escape( QString("%1").arg( adevDshowW->getValue() ) )+" ";
1084         if( dshowVSizeLine->isModified() )
1085             mrl += ":dshow-size=" + dshowVSizeLine->text();
1086         break;
1087 #else
1088     case V4L2_DEVICE:
1089         fileList << "v4l2://" + v4l2VideoDevice->currentText();
1090         mrl += ":v4l2-standard="
1091             + v4l2StdBox->itemData( v4l2StdBox->currentIndex() ).toString();
1092         mrl += " :input-slave=alsa://" + v4l2AudioDevice->currentText();
1093         break;
1094     case JACK_DEVICE:
1095         mrl = "jack://";
1096         mrl += "channels=" + QString::number( jackChannels->value() );
1097         mrl += ":ports=" + jackPortsSelected->text();
1098         fileList << mrl; mrl = "";
1099
1100         if ( jackPace->isChecked() )
1101         {
1102                 mrl += " :jack-input-use-vlc-pace";
1103         }
1104         if ( jackConnect->isChecked() )
1105         {
1106                 mrl += " :jack-input-auto-connect";
1107         }
1108         break;
1109     case PVR_DEVICE:
1110         fileList << "pvr://";
1111         mrl += " :pvr-device=" + pvrDevice->text();
1112         mrl += " :pvr-radio-device=" + pvrRadioDevice->text();
1113         mrl += " :pvr-norm=" + QString::number( pvrNormBox->currentIndex() );
1114         if( pvrFreq->value() )
1115             mrl += " :pvr-frequency=" + QString::number( pvrFreq->value() );
1116         if( pvrBitr->value() )
1117             mrl += " :pvr-bitrate=" + QString::number( pvrBitr->value() );
1118         break;
1119 #endif
1120     case DTV_DEVICE:
1121         if( dvbc->isChecked() ) mrl = "dvb-c://";
1122         else
1123         if( dvbs->isChecked() ) mrl = "dvb-s://";
1124         else
1125         if( dvbs2->isChecked() ) mrl = "dvb-s2://";
1126         else
1127         if( dvbt->isChecked() ) mrl = "dvb-t://";
1128         else
1129         if( dvbt2->isChecked() ) mrl = "dvb-t2://";
1130         else
1131         if( atsc->isChecked() ) mrl = "atsc://";
1132         else
1133         if( cqam->isChecked() ) mrl = "cqam://";
1134
1135         mrl += "frequency=" + QString::number( dvbFreq->value() ) + "000";
1136
1137         if( dvbc->isChecked() || cqam->isChecked() )
1138             mrl += ":modulation="
1139                 + dvbQamBox->itemData( dvbQamBox->currentIndex() ).toString();
1140         if( dvbs2->isChecked() )
1141             mrl += ":modulation="
1142                 + dvbPskBox->itemData( dvbPskBox->currentIndex() ).toString();
1143         if( dvbc->isChecked() || dvbs->isChecked() || dvbs2->isChecked() )
1144             mrl += ":srate=" + QString::number( dvbSrate->value() );
1145         if( dvbt->isChecked() || dvbt2->isChecked() )
1146             mrl += ":bandwidth=" +
1147                 QString::number( dvbBandBox->itemData(
1148                     dvbBandBox->currentIndex() ).toInt() );
1149
1150         fileList << mrl; mrl= "";
1151         mrl += " :dvb-adapter=" + QString::number( dvbCard->value() );
1152         break;
1153     case SCREEN_DEVICE:
1154         fileList << "screen://";
1155         mrl = " :screen-fps=" + QString::number( screenFPS->value(), 'f' );
1156         updateButtons();
1157         break;
1158     }
1159     emit methodChanged( "live-caching" );
1160
1161     if( !advMRL.isEmpty() ) mrl += advMRL;
1162
1163     emit mrlUpdated( fileList, mrl );
1164 }
1165
1166 /**
1167  * Update the Buttons (show/hide) for the GUI as all device type don't
1168  * use the same ui. elements.
1169  **/
1170 void CaptureOpenPanel::updateButtons()
1171 {
1172     /*  Be sure to display the ui Elements in case they were hidden by
1173      *  some Device Type (like Screen://) */
1174     ui.optionsBox->show();
1175     ui.advancedButton->show();
1176     /* Get the current Device Number */
1177     int i_devicetype = ui.deviceCombo->itemData(
1178                                 ui.deviceCombo->currentIndex() ).toInt();
1179     switch( i_devicetype )
1180     {
1181     case DTV_DEVICE:
1182         dvbSrate->hide();
1183         dvbSrateLabel->hide();
1184         dvbQamBox->hide();
1185         dvbPskBox->hide();
1186         dvbModLabel->hide();
1187         dvbBandBox->hide();
1188         dvbBandLabel->hide();
1189
1190         if( dvbc->isChecked() )
1191         {
1192             dvbSrate->show();
1193             dvbSrateLabel->show();
1194             dvbQamBox->show();
1195             dvbModLabel->show();
1196         }
1197         else if( dvbs->isChecked() )
1198         {
1199             dvbSrate->show();
1200             dvbSrateLabel->show();
1201         }
1202         else if( dvbs2->isChecked() )
1203         {
1204             dvbSrate->show();
1205             dvbSrateLabel->show();
1206             dvbPskBox->show();
1207             dvbModLabel->show();
1208         }
1209         else if( dvbt->isChecked() || dvbt2->isChecked() )
1210         {
1211             dvbBandBox->show();
1212             dvbBandLabel->show();
1213         }
1214         break;
1215     case SCREEN_DEVICE:
1216         //ui.optionsBox->hide();
1217         ui.advancedButton->hide();
1218         break;
1219     }
1220
1221     advMRL.clear();
1222 }
1223
1224 void CaptureOpenPanel::advancedDialog()
1225 {
1226     /* Get selected device type */
1227     int i_devicetype = ui.deviceCombo->itemData(
1228                                 ui.deviceCombo->currentIndex() ).toInt();
1229
1230     /* Get the corresponding module */
1231     module_t *p_module =
1232         module_find( psz_devModule[i_devicetype] );
1233     if( NULL == p_module ) return;
1234
1235     /* Init */
1236     QList<ConfigControl *> controls;
1237
1238     /* Get the confsize  */
1239     unsigned int i_confsize;
1240     module_config_t *p_config;
1241     p_config = module_config_get( p_module, &i_confsize );
1242
1243     /* New Adv Prop dialog */
1244     adv = new QDialog( this );
1245     adv->setWindowTitle( qtr( "Advanced Options" ) );
1246     adv->setWindowRole( "vlc-advanced-options" );
1247
1248     /* A main Layout with a Frame */
1249     QVBoxLayout *mainLayout = new QVBoxLayout( adv );
1250     QScrollArea *scroll = new QScrollArea;
1251     mainLayout->addWidget( scroll );
1252
1253     QFrame *advFrame = new QFrame;
1254     /* GridLayout inside the Frame */
1255     QGridLayout *gLayout = new QGridLayout( advFrame );
1256
1257     scroll->setWidgetResizable( true );
1258     scroll->setWidget( advFrame );
1259
1260     /* Create the options inside the FrameLayout */
1261     for( int n = 0; n < (int)i_confsize; n++ )
1262     {
1263         module_config_t *p_item = p_config + n;
1264         QString name = p_item->psz_name;
1265
1266         if( name.isEmpty() || configList.contains( name ) )
1267             continue;
1268
1269         msg_Err( p_intf, "%s", p_item->psz_name);
1270         ConfigControl *config = ConfigControl::createControl(
1271                         VLC_OBJECT( p_intf ), p_item, advFrame, gLayout, n );
1272         if( config )
1273             controls.append( config );
1274     }
1275
1276     /* Button stuffs */
1277     QDialogButtonBox *advButtonBox = new QDialogButtonBox( adv );
1278     QPushButton *closeButton = new QPushButton( qtr( "OK" ) );
1279     QPushButton *cancelButton = new QPushButton( qtr( "Cancel" ) );
1280
1281     CONNECT( closeButton, clicked(), adv, accept() );
1282     CONNECT( cancelButton, clicked(), adv, reject() );
1283
1284     advButtonBox->addButton( closeButton, QDialogButtonBox::AcceptRole );
1285     advButtonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
1286
1287     mainLayout->addWidget( advButtonBox );
1288
1289     /* Creation of the MRL */
1290     if( adv->exec() )
1291     {
1292         QString tempMRL = "";
1293         for( int i = 0; i < controls.count(); i++ )
1294         {
1295             ConfigControl *control = controls[i];
1296
1297             tempMRL += (i ? " :" : ":");
1298
1299             if( control->getType() == CONFIG_ITEM_BOOL )
1300                 if( !(qobject_cast<VIntConfigControl *>(control)->getValue() ) )
1301                     tempMRL += "no-";
1302
1303             tempMRL += control->getName();
1304
1305             switch( control->getType() )
1306             {
1307                 case CONFIG_ITEM_STRING:
1308                 case CONFIG_ITEM_LOADFILE:
1309                 case CONFIG_ITEM_SAVEFILE:
1310                 case CONFIG_ITEM_DIRECTORY:
1311                 case CONFIG_ITEM_MODULE:
1312                     tempMRL += colon_escape( QString("=%1").arg( qobject_cast<VStringConfigControl *>(control)->getValue() ) );
1313                     break;
1314                 case CONFIG_ITEM_INTEGER:
1315                     tempMRL += QString("=%1").arg( qobject_cast<VIntConfigControl *>(control)->getValue() );
1316                     break;
1317                 case CONFIG_ITEM_FLOAT:
1318                     tempMRL += QString("=%1").arg( qobject_cast<VFloatConfigControl *>(control)->getValue() );
1319                     break;
1320             }
1321         }
1322         advMRL = tempMRL;
1323         updateMRL();
1324     }
1325     qDeleteAll( controls );
1326     delete adv;
1327     module_config_free( p_config );
1328 }
1329