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