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