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