]> git.sesse.net Git - vlc/blob - modules/gui/qt4/components/open.cpp
Qt4 - yeah, redefining some existing options *IS* a good idea..
[vlc] / modules / gui / qt4 / components / open.cpp
1 /*****************************************************************************
2  * open.cpp : Panels for the open dialogs
3  ****************************************************************************
4  * Copyright (C) 2006-2007 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
30 #include "qt4.hpp"
31 #include "components/open.hpp"
32 #include "dialogs/open.hpp"
33 #include "dialogs_provider.hpp"
34 #include "util/customwidgets.hpp"
35
36 #include <QFileDialog>
37 #include <QDialogButtonBox>
38 #include <QLineEdit>
39 #include <QStackedLayout>
40 #include <QListView>
41 #include <QCompleter>
42 #include <QDirModel>
43
44 /**************************************************************************
45  * Open Files and subtitles                                               *
46  **************************************************************************/
47 FileOpenPanel::FileOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
48                                 OpenPanel( _parent, _p_intf )
49 {
50     /* Classic UI Setup */
51     ui.setupUi( this );
52
53     /** BEGIN QFileDialog tweaking **/
54     /* Use a QFileDialog and customize it because we don't want to
55        rewrite it all. Be careful to your eyes cause there are a few hacks.
56        Be very careful and test correctly when you modify this. */
57
58     /* Set Filters for file selection */
59     QString fileTypes = "";
60     ADD_FILTER_MEDIA( fileTypes );
61     ADD_FILTER_VIDEO( fileTypes );
62     ADD_FILTER_AUDIO( fileTypes );
63     ADD_FILTER_PLAYLIST( fileTypes );
64     ADD_FILTER_ALL( fileTypes );
65     fileTypes.replace( QString(";*"), QString(" *"));
66
67     /* retrieve last known path used in file browsing */
68     char *psz_filepath = config_GetPsz( p_intf, "qt-filedialog-path" );
69     if( EMPTY_STR( psz_filepath ) )
70     {
71         psz_filepath = p_intf->p_libvlc->psz_homedir;
72     }
73
74     // Make this QFileDialog a child of tempWidget from the ui.
75     dialogBox = new FileOpenBox( ui.tempWidget, NULL,
76             qfu( psz_filepath ), fileTypes );
77     delete psz_filepath;
78
79     dialogBox->setFileMode( QFileDialog::ExistingFiles );
80     dialogBox->setAcceptMode( QFileDialog::AcceptOpen );
81
82     /* We don't want to see a grip in the middle of the window, do we? */
83     dialogBox->setSizeGripEnabled( false );
84
85     /* Add a tooltip */
86     dialogBox->setToolTip( qtr( "Select one or multiple files, or a folder" ) );
87
88     // But hide the two OK/Cancel buttons. Enable them for debug.
89     QDialogButtonBox *fileDialogAcceptBox =
90                       dialogBox->findChildren<QDialogButtonBox*>()[0];
91     fileDialogAcceptBox->hide();
92
93     /* Ugly hacks to get the good Widget */
94     //This lineEdit is the normal line in the fileDialog.
95 #if HAS_QT43
96     lineFileEdit = dialogBox->findChildren<QLineEdit*>()[0];
97 #else
98     // FIXME
99     lineFileEdit = dialogBox->findChildren<QLineEdit*>()[1];
100 #endif
101     /* Make a list of QLabel inside the QFileDialog to access the good ones */
102     QList<QLabel *> listLabel = dialogBox->findChildren<QLabel*>();
103
104     /* Hide the FileNames one. Enable it for debug */
105     listLabel[1]->setText( qtr( "File names:" ) );
106     /* Change the text that was uncool in the usual box */
107     listLabel[2]->setText( qtr( "Filter:" ) );
108
109     dialogBox->layout()->setMargin( 0 );
110     dialogBox->layout()->setSizeConstraint( QLayout::SetMinimumSize );
111
112     /** END of QFileDialog tweaking **/
113
114     // Add the DialogBox to the layout
115     ui.gridLayout->addWidget( dialogBox, 0, 0, 1, 3 );
116
117     //TODO later: fill the fileCompleteList with previous items played.
118     QCompleter *fileCompleter = new QCompleter( fileCompleteList, this );
119     fileCompleter->setModel( new QDirModel( fileCompleter ) );
120     lineFileEdit->setCompleter( fileCompleter );
121
122     // Hide the subtitles control by default.
123     ui.subFrame->hide();
124
125     /* Build the subs size combo box */
126     setfillVLCConfigCombo( "freetype-rel-fontsize" , p_intf,
127                             ui.sizeSubComboBox );
128
129     /* Build the subs align combo box */
130     setfillVLCConfigCombo( "subsdec-align", p_intf, ui.alignSubComboBox );
131
132     /* Connects  */
133     BUTTONACT( ui.subBrowseButton, browseFileSub() );
134     BUTTONACT( ui.subCheckBox, toggleSubtitleFrame());
135
136     CONNECT( lineFileEdit, textChanged( QString ), this, updateMRL() );
137
138     CONNECT( ui.subInput, textChanged( QString ), this, updateMRL() );
139     CONNECT( ui.alignSubComboBox, currentIndexChanged( int ), this,
140                                                             updateMRL() );
141     CONNECT( ui.sizeSubComboBox, currentIndexChanged( int ), this,
142                                                             updateMRL() );
143 }
144
145 FileOpenPanel::~FileOpenPanel()
146 {}
147
148 QStringList FileOpenPanel::browse( QString help )
149 {
150     return THEDP->showSimpleOpen( help );
151 }
152
153
154 void FileOpenPanel::browseFileSub()
155 {
156     // FIXME Handle selection of more than one subtitles file
157     QStringList files = THEDP->showSimpleOpen( qtr("Open subtitles file"),
158                             EXT_FILTER_SUBTITLE,
159                             dialogBox->directory().absolutePath() );
160     if( files.isEmpty() ) return;
161     ui.subInput->setText( files.join(" ") );
162     updateMRL();
163 }
164
165 void FileOpenPanel::updateMRL()
166 {
167     QString mrl = "";
168     foreach( QString file, dialogBox->selectedFiles() ) {
169          mrl += "\"" + file + "\" ";
170     }
171
172     if( ui.subCheckBox->isChecked() ) {
173         mrl.append( " :sub-file=" + ui.subInput->text() );
174         int align = ui.alignSubComboBox->itemData(
175                     ui.alignSubComboBox->currentIndex() ).toInt();
176         mrl.append( " :subsdec-align=" + QString().setNum( align ) );
177         int size = ui.sizeSubComboBox->itemData(
178                    ui.sizeSubComboBox->currentIndex() ).toInt();
179         mrl.append( " :freetype-rel-fontsize=" + QString().setNum( size ) );
180     }
181
182     emit mrlUpdated( mrl );
183     emit methodChanged( "file-caching" );
184 }
185
186
187 /* Function called by Open Dialog when clicke on Play/Enqueue */
188 void FileOpenPanel::accept()
189 {
190     //FIXME set the completer
191     const char *psz_filepath = config_GetPsz( p_intf, "qt-filedialog-path" );
192     if( ( NULL == psz_filepath )
193       || strcmp( psz_filepath, qtu( dialogBox->directory().absolutePath() )) )
194     {
195         /* set dialog box current directory as last known path */
196         config_PutPsz( p_intf, "qt-filedialog-path",
197                        qtu( dialogBox->directory().absolutePath() ) );
198     }
199     delete psz_filepath;
200
201 }
202
203 void FileOpenBox::accept()
204 {
205     OpenDialog::getInstance( NULL, NULL )->play();
206 }
207
208 /* Function called by Open Dialog when clicked on cancel */
209 void FileOpenPanel::clear()
210 {
211     lineFileEdit->clear();
212     ui.subInput->clear();
213 }
214
215 void FileOpenPanel::toggleSubtitleFrame()
216 {
217     TOGGLEV( ui.subFrame );
218
219     /* Update the MRL */
220     updateMRL();
221 }
222
223 /**************************************************************************
224  * Open Discs ( DVD, CD, VCD and similar devices )                        *
225  **************************************************************************/
226 DiscOpenPanel::DiscOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
227                                 OpenPanel( _parent, _p_intf )
228 {
229     ui.setupUi( this );
230
231     /* Get the default configuration path for the devices */
232     psz_dvddiscpath = config_GetPsz( p_intf, "dvd" );
233     psz_vcddiscpath = config_GetPsz( p_intf, "vcd" );
234     psz_cddadiscpath = config_GetPsz( p_intf, "cd-audio" );
235
236     /* State to avoid overwritting the users changes with the configuration */
237     b_firstdvd = true;
238     b_firstvcd = true;
239     b_firstcdda = true;
240
241 #if WIN32 /* Disc drives probing for Windows */
242     char szDrives[512];
243     szDrives[0] = '\0';
244     if( GetLogicalDriveStringsA( sizeof( szDrives ) - 1, szDrives ) )
245     {
246         char *drive = szDrives;
247         UINT oldMode = SetErrorMode( SEM_FAILCRITICALERRORS );
248         while( *drive )
249         {
250             if( GetDriveTypeA(drive) == DRIVE_CDROM )
251                 ui.deviceCombo->addItem( drive );
252
253             /* go to next drive */
254             while( *(drive++) );
255         }
256         SetErrorMode(oldMode);
257     }
258 #endif /* Disc Probing under Windows */
259
260     /* CONNECTs */
261     BUTTONACT( ui.dvdRadioButton, updateButtons() );
262     BUTTONACT( ui.vcdRadioButton, updateButtons() );
263     BUTTONACT( ui.audioCDRadioButton, updateButtons() );
264     BUTTONACT( ui.dvdsimple, updateButtons() );
265     BUTTONACT( ui.browseDiscButton, browseDevice() );
266
267     CONNECT( ui.deviceCombo, editTextChanged( QString ), this, updateMRL());
268     CONNECT( ui.titleSpin, valueChanged( int ), this, updateMRL());
269     CONNECT( ui.chapterSpin, valueChanged( int ), this, updateMRL());
270     CONNECT( ui.audioSpin, valueChanged( int ), this, updateMRL());
271     CONNECT( ui.subtitlesSpin, valueChanged( int ), this, updateMRL());
272     
273     updateButtons();
274 }
275
276 DiscOpenPanel::~DiscOpenPanel()
277 {
278     delete psz_dvddiscpath;
279     delete psz_vcddiscpath;
280     delete psz_cddadiscpath;
281 }
282
283 void DiscOpenPanel::clear()
284 {
285     ui.titleSpin->setValue( 0 );
286     ui.chapterSpin->setValue( 0 );
287     b_firstcdda = true;
288     b_firstdvd = true;
289     b_firstvcd = true;
290 }
291
292 #ifdef WIN32
293     #define setDrive( psz_name ) {\
294     int index = ui.deviceCombo->findText( qfu( psz_name ) ); \
295     if( index != -1 ) ui.deviceCombo->setCurrentIndex( index );}
296 #else
297     #define setDrive( psz_name ) {\
298     ui.deviceCombo->setEditText( qfu( psz_name ) ); }
299 #endif
300
301 void DiscOpenPanel::updateButtons()
302 {
303     if ( ui.dvdRadioButton->isChecked() )
304     {
305         if( b_firstdvd )
306         {
307             setDrive( psz_dvddiscpath );
308             b_firstdvd = false;
309         }
310         ui.titleLabel->setText( qtr("Title") );
311         ui.chapterLabel->show();
312         ui.chapterSpin->show();
313         ui.diskOptionBox_2->show();
314     }
315     else if ( ui.vcdRadioButton->isChecked() )
316     {
317         if( b_firstvcd )
318         {
319             setDrive( psz_vcddiscpath );
320             b_firstvcd = false;
321         }
322         ui.titleLabel->setText( qtr("Entry") );
323         ui.chapterLabel->hide();
324         ui.chapterSpin->hide();
325         ui.diskOptionBox_2->show();
326     }
327     else /* CDDA */
328     {
329         if( b_firstcdda )
330         {
331             setDrive( psz_cddadiscpath );
332             b_firstcdda = false;
333         }
334         ui.titleLabel->setText( qtr("Track") );
335         ui.chapterLabel->hide();
336         ui.chapterSpin->hide();
337         ui.diskOptionBox_2->hide();
338     }
339
340     updateMRL();
341 }
342
343 void DiscOpenPanel::updateMRL()
344 {
345     QString mrl = "";
346
347     /* CDDAX and VCDX not implemented. FIXME ? */
348     /* DVD */
349     if( ui.dvdRadioButton->isChecked() ) {
350         if( !ui.dvdsimple->isChecked() )
351             mrl = "dvd://";
352         else
353             mrl = "dvdsimple://";
354         mrl += ui.deviceCombo->currentText();
355         emit methodChanged( "dvdnav-caching" );
356
357         if ( ui.titleSpin->value() > 0 ) {
358             mrl += QString("@%1").arg( ui.titleSpin->value() );
359             if ( ui.chapterSpin->value() > 0 ) {
360                 mrl+= QString(":%1").arg( ui.chapterSpin->value() );
361             }
362         }
363
364     /* VCD */
365     } else if ( ui.vcdRadioButton->isChecked() ) {
366         mrl = "vcd://" + ui.deviceCombo->currentText();
367         emit methodChanged( "vcd-caching" );
368
369         if( ui.titleSpin->value() > 0 ) {
370             mrl += QString("@E%1").arg( ui.titleSpin->value() );
371         }
372
373     /* CDDA */
374     } else {
375         mrl = "cdda://" + ui.deviceCombo->currentText();
376         if( ui.titleSpin->value() > 0 ) {
377             QString("@%1").arg( ui.titleSpin->value() );
378         }
379     }
380
381     if ( ui.dvdRadioButton->isChecked() || ui.vcdRadioButton->isChecked() )
382     {
383         if ( ui.audioSpin->value() >= 0 ) {
384             mrl += " :audio-track=" +
385                 QString("%1").arg( ui.audioSpin->value() );
386         }
387         if ( ui.subtitlesSpin->value() >= 0 ) {
388             mrl += " :sub-track=" +
389                 QString("%1").arg( ui.subtitlesSpin->value() );
390         }
391     }
392     emit mrlUpdated( mrl );
393 }
394
395 void DiscOpenPanel::browseDevice()
396 {
397     QString dir = QFileDialog::getExistingDirectory( 0, 
398             qtr("Open a device or a VIDEO_TS directory") );
399     if (!dir.isEmpty()) {
400         ui.deviceCombo->setEditText( dir );
401     }
402     updateMRL();
403 }
404
405 void DiscOpenPanel::accept()
406 {}
407
408 /**************************************************************************
409  * Open Network streams and URL pages                                     *
410  **************************************************************************/
411 NetOpenPanel::NetOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
412                                 OpenPanel( _parent, _p_intf )
413 {
414     ui.setupUi( this );
415
416     /* CONNECTs */
417     CONNECT( ui.protocolCombo, currentIndexChanged( int ),
418              this, updateProtocol( int ) );
419     CONNECT( ui.portSpin, valueChanged( int ), this, updateMRL() );
420     CONNECT( ui.addressText, textChanged( QString ), this, updateAddress());
421     CONNECT( ui.timeShift, clicked(), this, updateMRL());
422     CONNECT( ui.ipv6, clicked(), this, updateMRL());
423
424     ui.protocolCombo->addItem("HTTP", QVariant("http"));
425     ui.protocolCombo->addItem("HTTPS", QVariant("https"));
426     ui.protocolCombo->addItem("FTP", QVariant("ftp"));
427     ui.protocolCombo->addItem("MMS", QVariant("mms"));
428     ui.protocolCombo->addItem("RTSP", QVariant("rtsp"));
429     ui.protocolCombo->addItem("UDP/RTP (unicast)", QVariant("udp"));
430     ui.protocolCombo->addItem("UDP/RTP (multicast)", QVariant("udp"));
431 }
432
433 NetOpenPanel::~NetOpenPanel()
434 {}
435
436 void NetOpenPanel::clear()
437 {}
438
439 void NetOpenPanel::updateProtocol( int idx ) {
440     QString addr = ui.addressText->text();
441     QString proto = ui.protocolCombo->itemData( idx ).toString();
442
443     ui.timeShift->setEnabled( idx >= 5 );
444     ui.ipv6->setEnabled( idx == 5 );
445     ui.addressText->setEnabled( idx != 5 );
446     ui.portSpin->setEnabled( idx >= 5 );
447
448     /* If we already have a protocol in the address, replace it */
449     if( addr.contains( "://")) {
450         msg_Err( p_intf, "replace");
451         addr.replace( QRegExp("^.*://"), proto + "://");
452         ui.addressText->setText( addr );
453     }
454     updateMRL();
455 }
456
457 void NetOpenPanel::updateAddress() {
458     updateMRL();
459 }
460
461 void NetOpenPanel::updateMRL() {
462     QString mrl = "";
463     QString addr = ui.addressText->text();
464     int proto = ui.protocolCombo->currentIndex();
465
466     if( addr.contains( "://") && proto != 5 ) {
467         mrl = addr;
468     } else {
469         switch( proto ) {
470         case 0:
471             mrl = "http://" + addr;
472             emit methodChanged("http-caching");
473             break;
474         case 1:
475             mrl = "https://" + addr;
476             emit methodChanged("http-caching");
477             break;
478         case 3:
479             mrl = "mms://" + addr;
480             emit methodChanged("mms-caching");
481             break;
482         case 2:
483             mrl = "ftp://" + addr;
484             emit methodChanged("ftp-caching");
485             break;
486         case 4: /* RTSP */
487             mrl = "rtsp://" + addr;
488             emit methodChanged("rtsp-caching");
489             break;
490         case 5:
491             mrl = "udp://@";
492             if( ui.ipv6->isEnabled() && ui.ipv6->isChecked() ) {
493                 mrl += "[::]";
494             }
495             mrl += QString(":%1").arg( ui.portSpin->value() );
496             emit methodChanged("udp-caching");
497             break;
498         case 6: /* UDP multicast */
499             mrl = "udp://@";
500             /* Add [] to IPv6 */
501             if ( addr.contains(':') && !addr.contains('[') ) {
502                 mrl += "[" + addr + "]";
503             } else mrl += addr;
504             mrl += QString(":%1").arg( ui.portSpin->value() );
505             emit methodChanged("udp-caching");
506         }
507     }
508     if( ui.timeShift->isEnabled() && ui.timeShift->isChecked() ) {
509         mrl += " :access-filter=timeshift";
510     }
511     emit mrlUpdated( mrl );
512 }
513
514 /**************************************************************************
515  * Open Capture device ( DVB, PVR, V4L, and similar )                     *
516  **************************************************************************/
517 CaptureOpenPanel::CaptureOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
518                                 OpenPanel( _parent, _p_intf )
519 {
520     ui.setupUi( this );
521
522     /* Create two stacked layouts in the main comboBoxes */
523     QStackedLayout *stackedDevLayout = new QStackedLayout;
524     ui.cardBox->setLayout( stackedDevLayout );
525
526     QStackedLayout *stackedPropLayout = new QStackedLayout;
527     ui.optionsBox->setLayout( stackedPropLayout );
528
529     /* Creation and connections of the WIdgets in the stacked layout */
530 #define addModuleAndLayouts( number, name, label )                    \
531     QWidget * name ## DevPage = new QWidget( this );                  \
532     QWidget * name ## PropPage = new QWidget( this );                 \
533     stackedDevLayout->addWidget( name ## DevPage );        \
534     stackedPropLayout->addWidget( name ## PropPage );      \
535     QGridLayout * name ## DevLayout = new QGridLayout;                \
536     QGridLayout * name ## PropLayout = new QGridLayout;               \
537     name ## DevPage->setLayout( name ## DevLayout );                  \
538     name ## PropPage->setLayout( name ## PropLayout );                \
539     ui.deviceCombo->addItem( qtr( label ), QVariant( number ) );
540
541 #define CuMRL( widget, slot ) CONNECT( widget , slot , this, updateMRL() );
542
543     /*******
544      * V4L *
545      *******/
546     addModuleAndLayouts( V4L_DEVICE, v4l, "Video for Linux" );
547
548     /* V4l Main panel */
549     QLabel *v4lVideoDeviceLabel = new QLabel( qtr( "Video device name" ) );
550     v4lDevLayout->addWidget( v4lVideoDeviceLabel, 0, 0 );
551
552     v4lVideoDevice = new QLineEdit;
553     v4lDevLayout->addWidget( v4lVideoDevice, 0, 1 );
554
555     QLabel *v4lAudioDeviceLabel = new QLabel( qtr( "Audio device name" ) );
556     v4lDevLayout->addWidget( v4lAudioDeviceLabel, 1, 0 );
557
558     v4lAudioDevice = new QLineEdit;
559     v4lDevLayout->addWidget( v4lAudioDevice, 1, 1 );
560
561     /* V4l Props panel */
562     QLabel *v4lNormLabel = new QLabel( qtr( "Norm" ) );
563     v4lPropLayout->addWidget( v4lNormLabel, 0 , 0 );
564
565     v4lNormBox = new QComboBox;
566     setfillVLCConfigCombo( "v4l-norm", p_intf, v4lNormBox );
567     v4lPropLayout->addWidget( v4lNormBox, 0 , 1 );
568
569     QLabel *v4lFreqLabel = new QLabel( qtr( "Frequency" ) );
570     v4lPropLayout->addWidget( v4lFreqLabel, 1 , 0 );
571
572     v4lFreq = new QSpinBox;
573     v4lFreq->setAlignment( Qt::AlignRight );
574     v4lFreq->setSuffix(" kHz");
575     setSpinBoxFreq( v4lFreq );
576     v4lPropLayout->addWidget( v4lFreq, 1 , 1 );
577     v4lPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
578             2, 0, 2, 1 );
579
580     /* v4l CONNECTs */
581     CuMRL( v4lVideoDevice, textChanged( QString ) );
582     CuMRL( v4lAudioDevice, textChanged( QString ) );
583     CuMRL( v4lFreq, valueChanged ( int ) );
584     CuMRL( v4lNormBox,  currentIndexChanged ( int ) );
585
586     /*******
587      * V4L2*
588      *******/
589     addModuleAndLayouts( V4L2_DEVICE, v4l2, "Video for Linux 2" );
590
591     /* V4l Main panel */
592     QLabel *v4l2VideoDeviceLabel = new QLabel( qtr( "Video device name" ) );
593     v4l2DevLayout->addWidget( v4l2VideoDeviceLabel, 0, 0 );
594
595     v4l2VideoDevice = new QLineEdit;
596     v4l2DevLayout->addWidget( v4l2VideoDevice, 0, 1 );
597
598     QLabel *v4l2AudioDeviceLabel = new QLabel( qtr( "Audio device name" ) );
599     v4l2DevLayout->addWidget( v4l2AudioDeviceLabel, 1, 0 );
600
601     v4l2AudioDevice = new QLineEdit;
602     v4l2DevLayout->addWidget( v4l2AudioDevice, 1, 1 );
603
604     /* v4l2 Props panel */
605     QLabel *v4l2StdLabel = new QLabel( qtr( "Standard" ) );
606     v4l2PropLayout->addWidget( v4l2StdLabel, 0 , 0 );
607
608     v4l2StdBox = new QComboBox;
609     setfillVLCConfigCombo( "v4l2-standard", p_intf, v4l2StdBox );
610     v4l2PropLayout->addWidget( v4l2StdBox, 0 , 1 );
611     v4l2PropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
612             1, 0, 3, 1 );
613
614     /* v4l2 CONNECTs */
615     CuMRL( v4l2VideoDevice, textChanged( QString ) );
616     CuMRL( v4l2AudioDevice, textChanged( QString ) );
617     CuMRL( v4l2StdBox,  currentIndexChanged ( int ) );
618
619     /*******
620      * JACK *
621      *******/
622     addModuleAndLayouts( JACK_DEVICE, jack, "JACK Audio Connection Kit" );
623
624     /* Jack Main panel */
625     /* Channels */
626     QLabel *jackChannelsLabel = new QLabel( qtr( "Channels :" ) );
627     jackDevLayout->addWidget( jackChannelsLabel, 1, 0 );
628
629     jackChannels = new QSpinBox;
630     setSpinBoxFreq( jackChannels );
631     jackChannels->setMaximum(255);
632     jackChannels->setValue(2);
633     jackChannels->setAlignment( Qt::AlignRight );
634     jackDevLayout->addWidget( jackChannels, 1, 1 );
635
636     /* Jack Props panel */
637
638     /* Selected ports */
639     QLabel *jackPortsLabel = new QLabel( qtr( "Selected ports :" ) );
640     jackPropLayout->addWidget( jackPortsLabel, 0 , 0 );
641
642     jackPortsSelected = new QLineEdit( qtr( ".*") );
643     jackPortsSelected->setAlignment( Qt::AlignRight );
644     jackPropLayout->addWidget( jackPortsSelected, 0, 1 );
645
646     /* Caching */
647     QLabel *jackCachingLabel = new QLabel( qtr( "Input caching :" ) );
648     jackPropLayout->addWidget( jackCachingLabel, 1 , 0 );
649     jackCaching = new QSpinBox;
650     setSpinBoxFreq( jackCaching );
651     jackCaching->setSuffix( " ms" );
652     jackCaching->setValue(1000);
653     jackCaching->setAlignment( Qt::AlignRight );
654     jackPropLayout->addWidget( jackCaching, 1 , 1 );
655
656     /* Pace */
657     jackPace = new QCheckBox(qtr( "Use VLC pace" ));
658     jackPropLayout->addWidget( jackPace, 2, 1 );
659
660     /* Auto Connect */
661     jackConnect = new QCheckBox( qtr( "Auto connnection" ));
662     jackPropLayout->addWidget( jackConnect, 3, 1 );
663
664     /* Jack CONNECTs */
665     CuMRL( jackChannels, valueChanged( int ) );
666     CuMRL( jackCaching, valueChanged( int ) );
667     CuMRL( jackPace, stateChanged( int ) );
668     CuMRL( jackConnect, stateChanged( int ) );
669     CuMRL( jackPortsSelected, textChanged( QString ) );
670
671     /************
672      * PVR      *
673      ************/
674     addModuleAndLayouts( PVR_DEVICE, pvr, "PVR" );
675
676     /* PVR Main panel */
677     QLabel *pvrDeviceLabel = new QLabel( qtr( "Device name" ) );
678     pvrDevLayout->addWidget( pvrDeviceLabel, 0, 0 );
679
680     pvrDevice = new QLineEdit;
681     pvrDevLayout->addWidget( pvrDevice, 0, 1 );
682
683     QLabel *pvrRadioDeviceLabel = new QLabel( qtr( "Radio device name" ) );
684     pvrDevLayout->addWidget( pvrRadioDeviceLabel, 1, 0 );
685
686     pvrRadioDevice = new QLineEdit;
687     pvrDevLayout->addWidget( pvrRadioDevice, 1, 1 );
688
689     /* PVR props panel */
690     QLabel *pvrNormLabel = new QLabel( qtr( "Norm" ) );
691     pvrPropLayout->addWidget( pvrNormLabel, 0, 0 );
692
693     pvrNormBox = new QComboBox;
694     setfillVLCConfigCombo( "pvr-norm", p_intf, pvrNormBox );
695     pvrPropLayout->addWidget( pvrNormBox, 0, 1 );
696
697     QLabel *pvrFreqLabel = new QLabel( qtr( "Frequency" ) );
698     pvrPropLayout->addWidget( pvrFreqLabel, 1, 0 );
699
700     pvrFreq = new QSpinBox;
701     pvrFreq->setAlignment( Qt::AlignRight );
702     pvrFreq->setSuffix(" kHz");
703     setSpinBoxFreq( pvrFreq );
704     pvrPropLayout->addWidget( pvrFreq, 1, 1 );
705
706     QLabel *pvrBitrLabel = new QLabel( qtr( "Bitrate" ) );
707     pvrPropLayout->addWidget( pvrBitrLabel, 2, 0 );
708
709     pvrBitr = new QSpinBox;
710     pvrBitr->setAlignment( Qt::AlignRight );
711     pvrBitr->setSuffix(" kHz");
712     setSpinBoxFreq( pvrBitr );
713     pvrPropLayout->addWidget( pvrBitr, 2, 1 );
714     pvrPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
715             3, 0, 1, 1 );
716
717     /* PVR CONNECTs */
718     CuMRL( pvrDevice, textChanged( QString ) );
719     CuMRL( pvrRadioDevice, textChanged( QString ) );
720
721     CuMRL( pvrFreq, valueChanged ( int ) );
722     CuMRL( pvrBitr, valueChanged ( int ) );
723     CuMRL( pvrNormBox,  currentIndexChanged ( int ) );
724
725     /*********************
726      * DirectShow Stuffs *
727      *********************/
728     addModuleAndLayouts( DSHOW_DEVICE, dshow, "DirectShow" );
729
730     /* dshow Main */
731
732     QLabel *dshowVDeviceLabel = new QLabel( qtr( "Video Device Name " ) );
733     dshowDevLayout->addWidget( dshowVDeviceLabel, 0, 0 );
734
735     QLabel *dshowADeviceLabel = new QLabel( qtr( "Audio Device Name " ) );
736     dshowDevLayout->addWidget( dshowADeviceLabel, 1, 0 );
737
738     QComboBox *dshowVDevice = new QComboBox;
739     dshowDevLayout->addWidget( dshowVDevice, 0, 1 );
740
741     QComboBox *dshowADevice = new QComboBox;
742     dshowDevLayout->addWidget( dshowADevice, 1, 1 );
743
744     QPushButton *dshowVRefresh = new QPushButton( qtr( "Update List" ) );
745     dshowDevLayout->addWidget( dshowVRefresh, 0, 2 );
746
747     QPushButton *dshowARefresh = new QPushButton( qtr( "Update List" ) );
748     dshowDevLayout->addWidget( dshowARefresh, 1, 2 );
749
750     QPushButton *dshowVConfig = new QPushButton( qtr( "Configure" ) );
751     dshowDevLayout->addWidget( dshowVConfig, 0, 3 );
752
753     QPushButton *dshowAConfig = new QPushButton( qtr( "Configure" ) );
754     dshowDevLayout->addWidget( dshowAConfig, 1, 3 );
755
756     /* dshow Properties */
757
758     QLabel *dshowVSizeLabel = new QLabel( qtr( "Video size" ) );
759     dshowPropLayout->addWidget( dshowVSizeLabel, 0, 0 );
760
761     QLineEdit *dshowVSizeLine = new QLineEdit;
762     dshowPropLayout->addWidget( dshowVSizeLine, 0, 1);
763     dshowPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
764             1, 0, 3, 1 );
765
766     /* dshow CONNECTs */
767     CuMRL( dshowVDevice, currentIndexChanged ( int ) );
768     CuMRL( dshowADevice, currentIndexChanged ( int ) );
769     CuMRL( dshowVSizeLine, textChanged( QString ) );
770
771     /**************
772      * BDA Stuffs *
773      **************/
774     addModuleAndLayouts( BDA_DEVICE, bda, "DVB DirectShow" );
775
776     /* bda Main */
777     QLabel *bdaTypeLabel = new QLabel( qtr( "DVB Type:" ) );
778
779     bdas = new QRadioButton( "DVB-S" );
780     bdas->setChecked( true );
781     bdac = new QRadioButton( "DVB-C" );
782     bdat = new QRadioButton( "DVB-T" );
783
784     bdaDevLayout->addWidget( bdaTypeLabel, 0, 0 );
785     bdaDevLayout->addWidget( bdas, 0, 1 );
786     bdaDevLayout->addWidget( bdac, 0, 2 );
787     bdaDevLayout->addWidget( bdat, 0, 3 );
788
789     /* bda Props */
790     QLabel *bdaFreqLabel =
791                     new QLabel( qtr( "Transponder/multiplex frequency" ) );
792     bdaPropLayout->addWidget( bdaFreqLabel, 0, 0 );
793
794     bdaFreq = new QSpinBox;
795     bdaFreq->setAlignment( Qt::AlignRight );
796     bdaFreq->setSuffix(" kHz");
797     bdaFreq->setSingleStep( 1000 );
798     setSpinBoxFreq( bdaFreq )
799     bdaPropLayout->addWidget( bdaFreq, 0, 1 );
800
801     bdaSrateLabel = new QLabel( qtr( "Transponder symbol rate" ) );
802     bdaPropLayout->addWidget( bdaSrateLabel, 1, 0 );
803
804     bdaSrate = new QSpinBox;
805     bdaSrate->setAlignment( Qt::AlignRight );
806     bdaSrate->setSuffix(" kHz");
807     setSpinBoxFreq( bdaSrate );
808     bdaPropLayout->addWidget( bdaSrate, 1, 1 );
809
810     bdaBandLabel = new QLabel( qtr( "Bandwidth" ) );
811     bdaPropLayout->addWidget( bdaBandLabel, 2, 0 );
812
813     bdaBandBox = new QComboBox;
814     setfillVLCConfigCombo( "dvb-bandwidth", p_intf, bdaBandBox );
815     bdaPropLayout->addWidget( bdaBandBox, 2, 1 );
816
817     bdaBandLabel->hide();
818     bdaBandBox->hide();
819     bdaPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
820             2, 0, 2, 1 );
821
822     /* bda CONNECTs */
823     CuMRL( bdaFreq, valueChanged ( int ) );
824     CuMRL( bdaSrate, valueChanged ( int ) );
825     CuMRL( bdaBandBox,  currentIndexChanged ( int ) );
826     BUTTONACT( bdas, updateButtons() );
827     BUTTONACT( bdat, updateButtons() );
828     BUTTONACT( bdac, updateButtons() );
829     BUTTONACT( bdas, updateMRL() );
830     BUTTONACT( bdat, updateMRL() );
831     BUTTONACT( bdac, updateMRL() );
832
833     /**************
834      * DVB Stuffs *
835      **************/
836     addModuleAndLayouts( DVB_DEVICE, dvb, "DVB" );
837
838     /* DVB Main */
839     QLabel *dvbDeviceLabel = new QLabel( qtr( "Adapter card to tune" ) );
840     QLabel *dvbTypeLabel = new QLabel( qtr( "DVB Type:" ) );
841
842     dvbCard = new QSpinBox;
843     dvbCard->setAlignment( Qt::AlignRight );
844     dvbCard->setPrefix( "/dev/dvb/adapter" );
845
846     dvbDevLayout->addWidget( dvbDeviceLabel, 0, 0 );
847     dvbDevLayout->addWidget( dvbCard, 0, 2, 1, 2 );
848
849     dvbs = new QRadioButton( "DVB-S" );
850     dvbs->setChecked( true );
851     dvbc = new QRadioButton( "DVB-C" );
852     dvbt = new QRadioButton( "DVB-T" );
853
854     dvbDevLayout->addWidget( dvbTypeLabel, 1, 0 );
855     dvbDevLayout->addWidget( dvbs, 1, 1 );
856     dvbDevLayout->addWidget( dvbc, 1, 2 );
857     dvbDevLayout->addWidget( dvbt, 1, 3 );
858
859     /* DVB Props panel */
860     QLabel *dvbFreqLabel =
861                     new QLabel( qtr( "Transponder/multiplex frequency" ) );
862     dvbPropLayout->addWidget( dvbFreqLabel, 0, 0 );
863
864     dvbFreq = new QSpinBox;
865     dvbFreq->setAlignment( Qt::AlignRight );
866     dvbFreq->setSuffix(" kHz");
867     setSpinBoxFreq( dvbFreq  );
868     dvbPropLayout->addWidget( dvbFreq, 0, 1 );
869
870     QLabel *dvbSrateLabel = new QLabel( qtr( "Transponder symbol rate" ) );
871     dvbPropLayout->addWidget( dvbSrateLabel, 1, 0 );
872
873     dvbSrate = new QSpinBox;
874     dvbSrate->setAlignment( Qt::AlignRight );
875     dvbSrate->setSuffix(" kHz");
876     setSpinBoxFreq( dvbSrate );
877     dvbPropLayout->addWidget( dvbSrate, 1, 1 );
878     dvbPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
879             2, 0, 2, 1 );
880
881     /* DVB CONNECTs */
882     CuMRL( dvbCard, valueChanged ( int ) );
883     CuMRL( dvbFreq, valueChanged ( int ) );
884     CuMRL( dvbSrate, valueChanged ( int ) );
885
886     BUTTONACT( dvbs, updateButtons() );
887     BUTTONACT( dvbt, updateButtons() );
888     BUTTONACT( dvbc, updateButtons() );
889
890     /**********
891      * Screen *
892      **********/
893     addModuleAndLayouts( SCREEN_DEVICE, screen, "Desktop" );
894     QLabel *screenLabel = new QLabel( "This option will open your own "
895             "desktop in order to save or stream it.");
896     screenLabel->setWordWrap( true );
897     screenDevLayout->addWidget( screenLabel, 0, 0 );
898
899     /* General connects */
900     connect( ui.deviceCombo, SIGNAL( activated( int ) ),
901                      stackedDevLayout, SLOT( setCurrentIndex( int ) ) );
902     connect( ui.deviceCombo, SIGNAL( activated( int ) ),
903                      stackedPropLayout, SLOT( setCurrentIndex( int ) ) );
904     CONNECT( ui.deviceCombo, activated( int ), this, updateMRL() );
905     CONNECT( ui.deviceCombo, activated( int ), this, updateButtons() );
906
907 #undef addModule
908 }
909
910 CaptureOpenPanel::~CaptureOpenPanel()
911 {}
912
913 void CaptureOpenPanel::clear()
914 {}
915
916 void CaptureOpenPanel::updateMRL()
917 {
918     QString mrl = "";
919     int i_devicetype = ui.deviceCombo->itemData(
920             ui.deviceCombo->currentIndex() ).toInt();
921     switch( i_devicetype )
922     {
923     case V4L_DEVICE:
924         mrl = "v4l://";
925         mrl += " :v4l-vdev=" + v4lVideoDevice->text();
926         mrl += " :v4l-adev=" + v4lAudioDevice->text();
927         mrl += " :v4l-norm=" + QString("%1").arg( v4lNormBox->currentIndex() );
928         mrl += " :v4l-frequency=" + QString("%1").arg( v4lFreq->value() );
929         break;
930     case V4L2_DEVICE:
931         mrl = "v4l2://";
932         mrl += " :v4l2-dev=" + v4l2VideoDevice->text();
933         mrl += " :v4l2-adev=" + v4l2AudioDevice->text();
934         mrl += " :v4l2-standard=" + QString("%1").arg( v4l2StdBox->currentIndex() );
935         break;
936     case JACK_DEVICE:
937         mrl = "jack://";
938         mrl += "channels=" + QString("%1").arg( jackChannels->value() );
939         mrl += ":ports=" + jackPortsSelected->text();
940         mrl += " --jack-input-caching=" + QString("%1").arg( jackCaching->value() );
941         if ( jackPace->isChecked() )
942         {
943                 mrl += " --jack-input-use-vlc-pace";
944         }
945         if ( jackConnect->isChecked() )
946         {
947                 mrl += " --jack-input-auto-connect";
948         }
949         break;
950     case PVR_DEVICE:
951         mrl = "pvr://";
952         mrl += " :pvr-device=" + pvrDevice->text();
953         mrl += " :pvr-radio-device=" + pvrRadioDevice->text();
954         mrl += " :pvr-norm=" + QString("%1").arg( pvrNormBox->currentIndex() );
955         if( pvrFreq->value() )
956             mrl += " :pvr-frequency=" + QString("%1").arg( pvrFreq->value() );
957         if( pvrBitr->value() )
958             mrl += " :pvr-bitrate=" + QString("%1").arg( pvrBitr->value() );
959         break;
960     case DVB_DEVICE:
961         mrl = "dvb://";
962         mrl += " :dvb-adapter=" + QString("%1").arg( dvbCard->value() );
963         mrl += " :dvb-frequency=" + QString("%1").arg( dvbFreq->value() );
964         mrl += " :dvb-srate=" + QString("%1").arg( dvbSrate->value() );
965         break;
966     case BDA_DEVICE:
967         if( bdas->isChecked() ) mrl = "dvb-s://";
968         else if(  bdat->isChecked() ) mrl = "dvb-t://";
969         else if(  bdac->isChecked() ) mrl = "dvb-c://";
970         else return;
971         mrl += " :dvb-frequency=" + QString("%1").arg( bdaFreq->value() );
972         if( bdas->isChecked() || bdac->isChecked() )
973             mrl += " :dvb-srate=" + QString("%1").arg( bdaSrate->value() );
974         else
975             mrl += " :dvb-bandwidth=" +
976                 QString("%1").arg( bdaBandBox->itemData(
977                     bdaBandBox->currentIndex() ).toInt() );
978         break;
979     case DSHOW_DEVICE:
980         break;
981     case SCREEN_DEVICE:
982         mrl = "screen://";
983         updateButtons();
984         break;
985     }
986     emit mrlUpdated( mrl );
987 }
988
989 /**
990  * Update the Buttons (show/hide) for the GUI as all device type don't
991  * use the same ui. elements.
992  **/
993 void CaptureOpenPanel::updateButtons()
994 {
995     /*  Be sure to display the ui Elements in case they were hidden by
996      *  some Device Type (like Screen://) */
997     ui.optionsBox->show();
998     ui.advancedButton->show();
999     /* Get the current Device Number */
1000     int i_devicetype = ui.deviceCombo->itemData(
1001                                 ui.deviceCombo->currentIndex() ).toInt();
1002     msg_Dbg( p_intf, "Capture Type: %i", i_devicetype );
1003     switch( i_devicetype )
1004     {
1005     case DVB_DEVICE:
1006         if( dvbs->isChecked() ) dvbFreq->setSuffix(" kHz");
1007         if( dvbc->isChecked() || dvbt->isChecked() ) dvbFreq->setSuffix(" Hz");
1008         break;
1009     case BDA_DEVICE:
1010         if( bdas->isChecked() || bdac->isChecked() )
1011         {
1012             bdaSrate->show();
1013             bdaSrateLabel->show();
1014             bdaBandBox->hide();
1015             bdaBandLabel->hide();
1016         }
1017         else
1018         {
1019             bdaSrate->hide();
1020             bdaSrateLabel->hide();
1021             bdaBandBox->show();
1022             bdaBandLabel->show();
1023         }
1024         break;
1025     case SCREEN_DEVICE:
1026         ui.optionsBox->hide();
1027         ui.advancedButton->hide();
1028         break;
1029     }
1030 }