open.cpp 27.4 KB
Newer Older
Clément Stenac's avatar
Clément Stenac committed
1 2 3
/*****************************************************************************
 * open.cpp : Panels for the open dialogs
 ****************************************************************************
4
 * Copyright (C) 2006-2007 the VideoLAN team
5
 * $Id$
Clément Stenac's avatar
Clément Stenac committed
6 7
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
Clément Stenac's avatar
Clément Stenac committed
8
 *          Jean-Baptiste Kempf <jb@videolan.org>
Clément Stenac's avatar
Clément Stenac committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
25 26

#include "qt4.hpp"
Clément Stenac's avatar
Clément Stenac committed
27
#include "components/open.hpp"
28
#include "dialogs/open.hpp"
29
#include "dialogs_provider.hpp"
30 31 32 33 34
#include "util/customwidgets.hpp"

#include <QFileDialog>
#include <QDialogButtonBox>
#include <QLineEdit>
35
#include <QStackedLayout>
36
#include <QListView>
37

38 39 40 41
#ifdef HAVE_LIMITS_H
#   include <limits.h>
#endif

Clément Stenac's avatar
Clément Stenac committed
42
/**************************************************************************
43
 * Open Files and subtitles                                               *
Clément Stenac's avatar
Clément Stenac committed
44 45 46 47
 **************************************************************************/
FileOpenPanel::FileOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
48
    /* Classic UI Setup */
Clément Stenac's avatar
Clément Stenac committed
49
    ui.setupUi( this );
50

51 52 53 54
    /* Use a QFileDialog and customize it because we don't want to
       rewrite it all. Be careful to your eyes cause there are a few hacks.
       Be very careful and test correctly when you modify this. */

55 56 57 58 59 60 61
    /* Set Filters for file selection */
    QString fileTypes = "";
    ADD_FILTER_MEDIA( fileTypes );
    ADD_FILTER_VIDEO( fileTypes );
    ADD_FILTER_AUDIO( fileTypes );
    ADD_FILTER_PLAYLIST( fileTypes );
    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
    dialogBox->setFileMode( QFileDialog::ExistingFiles );
68
    dialogBox->setAcceptMode( QFileDialog::AcceptOpen );
69

70 71 72 73
    /* retrieve last known path used in file browsing */
    char *psz_filepath = config_GetPsz( p_intf, "qt-filedialog-path" );
    if( psz_filepath )
    {
74
        dialogBox->setDirectory( QString::fromUtf8( psz_filepath ) );
75 76 77
        delete psz_filepath;
    }

78 79
    /* We don't want to see a grip in the middle of the window, do we? */
    dialogBox->setSizeGripEnabled( false );
80 81

    /* Add a tooltip */
82
    dialogBox->setToolTip( qtr( "Select one or multiple files, or a folder" ) );
83 84 85 86 87

    // Add it to the layout
    ui.gridLayout->addWidget( dialogBox, 0, 0, 1, 3 );

    // But hide the two OK/Cancel buttons. Enable them for debug.
88
    QDialogButtonBox *fileDialogAcceptBox =
89
                                        findChildren<QDialogButtonBox*>()[0];
90
    fileDialogAcceptBox->hide();
91 92 93 94 95 96 97 98 99 100 101 102 103

    /* Ugly hacks to get the good Widget */
    //This lineEdit is the normal line in the fileDialog.
    lineFileEdit = findChildren<QLineEdit*>()[3];
    lineFileEdit->hide();

    /* Make a list of QLabel inside the QFileDialog to access the good ones */
    QList<QLabel *> listLabel = findChildren<QLabel*>();

    /* Hide the FileNames one. Enable it for debug */
    listLabel[4]->hide();
    /* Change the text that was uncool in the usual box */
    listLabel[5]->setText( qtr( "Filter:" ) );
Clément Stenac's avatar
Clément Stenac committed
104

105 106 107
#if WIN32
    /* QFileDialog is quite buggy make it brerable on win32 by tweaking 
       the followin */
108
    QListView *fileListView = findChildren<QListView*>().first();
109
    fileListView->setLayoutMode(QListView::Batched);
110 111 112
    fileListView->setViewMode(QListView::ListMode);
    fileListView->setResizeMode(QListView::Adjust);
    fileListView->setUniformItemSizes(false);
113 114 115
    fileListView->setFlow(QListView::TopToBottom);
    fileListView->setWrapping(true);
#endif
116

117 118 119
    // Hide the subtitles control by default.
    ui.subFrame->hide();

120
    /* Build the subs size combo box */
121
    setfillVLCConfigCombo( "freetype-rel-fontsize" , p_intf,
122
                            ui.sizeSubComboBox );
123

124
    /* Build the subs align combo box */
125
    setfillVLCConfigCombo( "subsdec-align", p_intf, ui.alignSubComboBox );
126

127
    /* Connects  */
128
    BUTTONACT( ui.subBrowseButton, browseFileSub() );
129
    BUTTONACT( ui.subCheckBox, toggleSubtitleFrame());
Clément Stenac's avatar
Clément Stenac committed
130

131 132 133 134 135 136
    CONNECT( ui.fileInput, editTextChanged( QString ), this, updateMRL() );
    CONNECT( ui.subInput, editTextChanged( QString ), this, updateMRL() );
    CONNECT( ui.alignSubComboBox, currentIndexChanged( int ), this,
                                                            updateMRL() );
    CONNECT( ui.sizeSubComboBox, currentIndexChanged( int ), this,
                                                            updateMRL() );
137

138
    CONNECT( lineFileEdit, textChanged( QString ), this, browseFile() );
Clément Stenac's avatar
Clément Stenac committed
139 140 141 142 143
}

FileOpenPanel::~FileOpenPanel()
{}

144
QStringList FileOpenPanel::browse( QString help )
145
{
146
    return THEDP->showSimpleOpen( help );
147 148 149 150
}

void FileOpenPanel::browseFile()
{
Clément Stenac's avatar
Clément Stenac committed
151
    QString fileString = "";
152
    foreach( QString file, dialogBox->selectedFiles() ) {
153
         fileString += "\"" + file + "\" ";
Clément Stenac's avatar
Clément Stenac committed
154 155
    }
    ui.fileInput->setEditText( fileString );
156 157 158 159 160
    updateMRL();
}

void FileOpenPanel::browseFileSub()
{
161
    // FIXME Handle selection of more than one subtitles file
162
    QStringList files = THEDP->showSimpleOpen( qtr("Open subtitles file"),
163 164
                            EXT_FILTER_SUBTITLE,
                            dialogBox->directory().absolutePath() );
165
    if( files.isEmpty() ) return;
166
    ui.subInput->setEditText( files.join(" ") );
Clément Stenac's avatar
Clément Stenac committed
167
    updateMRL();
168 169 170 171
}

void FileOpenPanel::updateMRL()
{
Clément Stenac's avatar
Clément Stenac committed
172 173
    QString mrl = ui.fileInput->currentText();

174
    if( ui.subCheckBox->isChecked() ) {
Clément Stenac's avatar
Clément Stenac committed
175
        mrl.append( " :sub-file=" + ui.subInput->currentText() );
176 177
        int align = ui.alignSubComboBox->itemData(
                    ui.alignSubComboBox->currentIndex() ).toInt();
178
        mrl.append( " :subsdec-align=" + QString().setNum( align ) );
179 180
        int size = ui.sizeSubComboBox->itemData(
                   ui.sizeSubComboBox->currentIndex() ).toInt();
181
        mrl.append( " :freetype-rel-fontsize=" + QString().setNum( size ) );
Clément Stenac's avatar
Clément Stenac committed
182
    }
183 184

    const char *psz_filepath = config_GetPsz( p_intf, "qt-filedialog-path" );
185
    if( ( NULL == psz_filepath )
186
      || strcmp( psz_filepath, qtu( dialogBox->directory().absolutePath() )) )
187 188 189
    {
        /* set dialog box current directory as last known path */
        config_PutPsz( p_intf, "qt-filedialog-path",
190
                       qtu( dialogBox->directory().absolutePath() ) );
191 192 193
    }
    delete psz_filepath;

194
    emit mrlUpdated( mrl );
Clément Stenac's avatar
Clément Stenac committed
195
    emit methodChanged( "file-caching" );
Clément Stenac's avatar
Clément Stenac committed
196 197
}

198 199 200 201

/* Function called by Open Dialog when clicke on Play/Enqueue */
void FileOpenPanel::accept()
{
202 203
    ui.fileInput->addItem( ui.fileInput->currentText());
    if ( ui.fileInput->count() > 8 ) ui.fileInput->removeItem( 0 );
204 205
}

206 207 208 209
void FileOpenBox::accept()
{
    OpenDialog::getInstance( NULL, NULL )->play();
}
210 211

/* Function called by Open Dialog when clicked on cancel */
212 213
void FileOpenPanel::clear()
{
214 215
    ui.fileInput->setEditText( "" );
    ui.subInput->setEditText( "" );
216 217
}

218 219
void FileOpenPanel::toggleSubtitleFrame()
{
220
    if ( ui.subFrame->isVisible() )
221 222
    {
        ui.subFrame->hide();
223 224
        updateGeometry();
    /* FiXME Size */
225 226 227 228 229 230 231 232 233 234
    }
    else
    {
        ui.subFrame->show();
    }

    /* Update the MRL */
    updateMRL();
}

Clément Stenac's avatar
Clément Stenac committed
235
/**************************************************************************
236
 * Open Discs ( DVD, CD, VCD and similar devices )                        *
Clément Stenac's avatar
Clément Stenac committed
237
 **************************************************************************/
238
DiscOpenPanel::DiscOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
Clément Stenac's avatar
Clément Stenac committed
239 240 241
                                OpenPanel( _parent, _p_intf )
{
    ui.setupUi( this );
Clément Stenac's avatar
Clément Stenac committed
242

243 244
    /*Win 32 Probe  as in WX ? */

245
    /* CONNECTs */
246 247 248 249
    BUTTONACT( ui.dvdRadioButton, updateButtons());
    BUTTONACT( ui.vcdRadioButton, updateButtons());
    BUTTONACT( ui.audioCDRadioButton, updateButtons());
    BUTTONACT( ui.dvdsimple,  updateButtons());
Clément Stenac's avatar
Clément Stenac committed
250

251 252 253 254 255
    CONNECT( ui.deviceCombo, editTextChanged( QString ), this, updateMRL());
    CONNECT( ui.titleSpin, valueChanged( int ), this, updateMRL());
    CONNECT( ui.chapterSpin, valueChanged( int ), this, updateMRL());
    CONNECT( ui.audioSpin, valueChanged( int ), this, updateMRL());
    CONNECT( ui.subtitlesSpin, valueChanged( int ), this, updateMRL());
Clément Stenac's avatar
Clément Stenac committed
256 257
}

258
DiscOpenPanel::~DiscOpenPanel()
259 260
{}

261
void DiscOpenPanel::clear()
Clément Stenac's avatar
Clément Stenac committed
262
{
263 264
    ui.titleSpin->setValue( 0 );
    ui.chapterSpin->setValue( 0 );
Clément Stenac's avatar
Clément Stenac committed
265
}
266

267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
void DiscOpenPanel::updateButtons()
{
    if ( ui.dvdRadioButton->isChecked() )
    {
        ui.titleLabel->setText( qtr("Title") );
        ui.chapterLabel->show();
        ui.chapterSpin->show();
        ui.diskOptionBox_2->show();
    }
    else if ( ui.vcdRadioButton->isChecked() )
    {
        ui.titleLabel->setText( qtr("Entry") );
        ui.chapterLabel->hide();
        ui.chapterSpin->hide();
        ui.diskOptionBox_2->show();
    }
    else
    {
        ui.titleLabel->setText( qtr("Track") );
        ui.chapterLabel->hide();
        ui.chapterSpin->hide();
        ui.diskOptionBox_2->hide();
    }

    updateMRL();
}


295
void DiscOpenPanel::updateMRL()
Clément Stenac's avatar
Clément Stenac committed
296 297
{
    QString mrl = "";
298 299

    /* CDDAX and VCDX not implemented. FIXME ? */
Clément Stenac's avatar
Clément Stenac committed
300 301
    /* DVD */
    if( ui.dvdRadioButton->isChecked() ) {
302 303 304 305 306
        if( !ui.dvdsimple->isChecked() )
            mrl = "dvd://";
        else
            mrl = "dvdsimple://";
        mrl += ui.deviceCombo->currentText();
Clément Stenac's avatar
Clément Stenac committed
307 308 309
        emit methodChanged( "dvdnav-caching" );

        if ( ui.titleSpin->value() > 0 ) {
310
            mrl += QString("@%1").arg( ui.titleSpin->value() );
Clément Stenac's avatar
Clément Stenac committed
311
            if ( ui.chapterSpin->value() > 0 ) {
312
                mrl+= QString(":%1").arg( ui.chapterSpin->value() );
Clément Stenac's avatar
Clément Stenac committed
313 314 315 316
            }
        }

    /* VCD */
317
    } else if ( ui.vcdRadioButton->isChecked() ) {
Clément Stenac's avatar
Clément Stenac committed
318 319 320 321
        mrl = "vcd://" + ui.deviceCombo->currentText();
        emit methodChanged( "vcd-caching" );

        if( ui.titleSpin->value() > 0 ) {
322
            mrl += QString("@E%1").arg( ui.titleSpin->value() );
Clément Stenac's avatar
Clément Stenac committed
323 324 325 326 327
        }

    /* CDDA */
    } else {
        mrl = "cdda://" + ui.deviceCombo->currentText();
328
        if( ui.titleSpin->value() > 0 ) {
329
            QString("@%1").arg( ui.titleSpin->value() );
330 331 332 333 334 335
        }
    }

    if ( ui.dvdRadioButton->isChecked() || ui.vcdRadioButton->isChecked() )
    {
        if ( ui.audioSpin->value() >= 0 ) {
336 337
            mrl += " :audio-track=" +
                QString("%1").arg( ui.audioSpin->value() );
338 339 340
        }
        if ( ui.subtitlesSpin->value() >= 0 ) {
            mrl += " :sub-track=" +
341
                QString("%1").arg( ui.subtitlesSpin->value() );
342
        }
Clément Stenac's avatar
Clément Stenac committed
343
    }
344
    emit mrlUpdated( mrl );
345 346 347
}


Clément Stenac's avatar
Clément Stenac committed
348

349
/**************************************************************************
350
 * Open Network streams and URL pages                                     *
351 352 353 354 355
 **************************************************************************/
NetOpenPanel::NetOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    ui.setupUi( this );
Clément Stenac's avatar
Clément Stenac committed
356

357
    /* CONNECTs */
358 359 360 361
    CONNECT( ui.protocolCombo, currentIndexChanged( int ),
             this, updateProtocol( int ) );
    CONNECT( ui.portSpin, valueChanged( int ), this, updateMRL() );
    CONNECT( ui.addressText, textChanged( QString ), this, updateAddress());
Clément Stenac's avatar
Clément Stenac committed
362 363 364 365
    CONNECT( ui.timeShift, clicked(), this, updateMRL());
    CONNECT( ui.ipv6, clicked(), this, updateMRL());

    ui.protocolCombo->addItem("HTTP", QVariant("http"));
366
    ui.protocolCombo->addItem("HTTPS", QVariant("https"));
Clément Stenac's avatar
Clément Stenac committed
367 368 369 370 371
    ui.protocolCombo->addItem("FTP", QVariant("ftp"));
    ui.protocolCombo->addItem("MMS", QVariant("mms"));
    ui.protocolCombo->addItem("RTSP", QVariant("rtsp"));
    ui.protocolCombo->addItem("UDP/RTP (unicast)", QVariant("udp"));
    ui.protocolCombo->addItem("UDP/RTP (multicast)", QVariant("udp"));
Clément Stenac's avatar
Clément Stenac committed
372 373
}

374 375 376
NetOpenPanel::~NetOpenPanel()
{}

Clément Stenac's avatar
Clément Stenac committed
377
void NetOpenPanel::clear()
378 379
{}

380
void NetOpenPanel::updateProtocol( int idx ) {
Clément Stenac's avatar
Clément Stenac committed
381
    QString addr = ui.addressText->text();
382
    QString proto = ui.protocolCombo->itemData( idx ).toString();
Clément Stenac's avatar
Clément Stenac committed
383

384
    ui.timeShift->setEnabled( idx >= 4 );
Clément Stenac's avatar
Clément Stenac committed
385 386 387 388 389 390 391
    ui.ipv6->setEnabled( idx == 4 );
    ui.addressText->setEnabled( idx != 4 );
    ui.portSpin->setEnabled( idx >= 4 );

    /* If we already have a protocol in the address, replace it */
    if( addr.contains( "://")) {
        msg_Err( p_intf, "replace");
392 393
        addr.replace( QRegExp("^.*://"), proto + "://");
        ui.addressText->setText( addr );
Clément Stenac's avatar
Clément Stenac committed
394 395
    }
    updateMRL();
Clément Stenac's avatar
Clément Stenac committed
396
}
397

Clément Stenac's avatar
Clément Stenac committed
398 399 400 401 402 403 404 405 406 407 408 409
void NetOpenPanel::updateAddress() {
    updateMRL();
}

void NetOpenPanel::updateMRL() {
    QString mrl = "";
    QString addr = ui.addressText->text();
    int proto = ui.protocolCombo->currentIndex();

    if( addr.contains( "://") && proto != 4 ) {
        mrl = addr;
    } else {
410
        switch( proto ) {
Clément Stenac's avatar
Clément Stenac committed
411
        case 0:
412
        case 1:
Clément Stenac's avatar
Clément Stenac committed
413 414 415
            mrl = "http://" + addr;
            emit methodChanged("http-caching");
            break;
416
        case 3:
Clément Stenac's avatar
Clément Stenac committed
417 418 419
            mrl = "mms://" + addr;
            emit methodChanged("mms-caching");
            break;
420
        case 2:
Clément Stenac's avatar
Clément Stenac committed
421 422 423
            mrl = "ftp://" + addr;
            emit methodChanged("ftp-caching");
            break;
424
        case 4: /* RTSP */
Clément Stenac's avatar
Clément Stenac committed
425 426 427
            mrl = "rtsp://" + addr;
            emit methodChanged("rtsp-caching");
            break;
428
        case 5:
Clément Stenac's avatar
Clément Stenac committed
429 430 431 432
            mrl = "udp://@";
            if( ui.ipv6->isEnabled() && ui.ipv6->isChecked() ) {
                mrl += "[::]";
            }
433
            mrl += QString(":%1").arg( ui.portSpin->value() );
Clément Stenac's avatar
Clément Stenac committed
434 435
            emit methodChanged("udp-caching");
            break;
436
        case 6: /* UDP multicast */
Clément Stenac's avatar
Clément Stenac committed
437 438 439 440 441
            mrl = "udp://@";
            /* Add [] to IPv6 */
            if ( addr.contains(':') && !addr.contains('[') ) {
                mrl += "[" + addr + "]";
            } else mrl += addr;
442
            mrl += QString(":%1").arg( ui.portSpin->value() );
Clément Stenac's avatar
Clément Stenac committed
443 444 445 446 447 448
            emit methodChanged("udp-caching");
        }
    }
    if( ui.timeShift->isEnabled() && ui.timeShift->isChecked() ) {
        mrl += " :access-filter=timeshift";
    }
449
    emit mrlUpdated( mrl );
Clément Stenac's avatar
Clément Stenac committed
450
}
451 452

/**************************************************************************
453
 * Open Capture device ( DVB, PVR, V4L, and similar )                     *
454 455 456 457 458
 **************************************************************************/
CaptureOpenPanel::CaptureOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    ui.setupUi( this );
459

460
    /* Create two stacked layouts in the main comboBoxes */
461 462 463 464 465 466
    QStackedLayout *stackedDevLayout = new QStackedLayout;
    ui.cardBox->setLayout( stackedDevLayout );

    QStackedLayout *stackedPropLayout = new QStackedLayout;
    ui.optionsBox->setLayout( stackedPropLayout );

467
    /* Creation and connections of the WIdgets in the stacked layout */
468
#define addModuleAndLayouts( number, name, label )                    \
469 470
    QWidget * name ## DevPage = new QWidget( this );                  \
    QWidget * name ## PropPage = new QWidget( this );                 \
471 472
    stackedDevLayout->addWidget( name ## DevPage );        \
    stackedPropLayout->addWidget( name ## PropPage );      \
473 474 475 476
    QGridLayout * name ## DevLayout = new QGridLayout;                \
    QGridLayout * name ## PropLayout = new QGridLayout;               \
    name ## DevPage->setLayout( name ## DevLayout );                  \
    name ## PropPage->setLayout( name ## PropLayout );                \
477
    ui.deviceCombo->addItem( qtr( label ), QVariant( number ) );
478 479 480

#define CuMRL( widget, slot ) CONNECT( widget , slot , this, updateMRL() );

481 482
#define setMaxBound( spinbox ) spinbox->setRange ( 0, INT_MAX );

483 484 485
    /*******
     * V4L *
     *******/
486
    addModuleAndLayouts( V4L_DEVICE, v4l, "Video for Linux" );
487 488

    /* V4l Main panel */
489 490
    QLabel *v4lVideoDeviceLabel = new QLabel( qtr( "Video device name" ) );
    v4lDevLayout->addWidget( v4lVideoDeviceLabel, 0, 0 );
491

492
    v4lVideoDevice = new QLineEdit;
493
    v4lDevLayout->addWidget( v4lVideoDevice, 0, 1 );
494

495 496
    QLabel *v4lAudioDeviceLabel = new QLabel( qtr( "Audio device name" ) );
    v4lDevLayout->addWidget( v4lAudioDeviceLabel, 1, 0 );
497

498
    v4lAudioDevice = new QLineEdit;
499 500
    v4lDevLayout->addWidget( v4lAudioDevice, 1, 1 );

501
    /* V4l Props panel */
502 503 504
    QLabel *v4lNormLabel = new QLabel( qtr( "Norm" ) );
    v4lPropLayout->addWidget( v4lNormLabel, 0 , 0 );

505
    v4lNormBox = new QComboBox;
506 507
    setfillVLCConfigCombo( "v4l-norm", p_intf, v4lNormBox );
    v4lPropLayout->addWidget( v4lNormBox, 0 , 1 );
508

509 510 511
    QLabel *v4lFreqLabel = new QLabel( qtr( "Frequency" ) );
    v4lPropLayout->addWidget( v4lFreqLabel, 1 , 0 );

512
    v4lFreq = new QSpinBox;
513 514
    v4lFreq->setAlignment( Qt::AlignRight );
    v4lFreq->setSuffix(" kHz");
515
    v4lPropLayout->addWidget( v4lFreq, 1 , 1 );
516 517 518 519 520 521 522 523 524 525

    /* v4l CONNECTs */
    CuMRL( v4lVideoDevice, textChanged( QString ) );
    CuMRL( v4lAudioDevice, textChanged( QString ) );
    CuMRL( v4lFreq, valueChanged ( int ) );
    CuMRL( v4lNormBox,  currentIndexChanged ( int ) );

    /************
     * PVR      *
     ************/
526
    addModuleAndLayouts( PVR_DEVICE, pvr, "PVR" );
527

528
    /* PVR Main panel */
529 530
    QLabel *pvrDeviceLabel = new QLabel( qtr( "Device name" ) );
    pvrDevLayout->addWidget( pvrDeviceLabel, 0, 0 );
531

532 533
    pvrDevice = new QLineEdit;
    pvrDevLayout->addWidget( pvrDevice, 0, 1 );
534

535 536
    QLabel *pvrRadioDeviceLabel = new QLabel( qtr( "Radio device name" ) );
    pvrDevLayout->addWidget( pvrRadioDeviceLabel, 1, 0 );
537

538 539
    pvrRadioDevice = new QLineEdit;
    pvrDevLayout->addWidget( pvrRadioDevice, 1, 1 );
540

541
    /* PVR props panel */
542 543 544
    QLabel *pvrNormLabel = new QLabel( qtr( "Norm" ) );
    pvrPropLayout->addWidget( pvrNormLabel, 0, 0 );

545
    pvrNormBox = new QComboBox;
546 547 548
    setfillVLCConfigCombo( "pvr-norm", p_intf, pvrNormBox );
    pvrPropLayout->addWidget( pvrNormBox, 0, 1 );

549 550
    QLabel *pvrFreqLabel = new QLabel( qtr( "Frequency" ) );
    pvrPropLayout->addWidget( pvrFreqLabel, 1, 0 );
551

552
    pvrFreq = new QSpinBox;
553 554
    pvrFreq->setAlignment( Qt::AlignRight );
    pvrFreq->setSuffix(" kHz");
555
    setMaxBound( pvrFreq );
556 557
    pvrPropLayout->addWidget( pvrFreq, 1, 1 );

558 559 560
    QLabel *pvrBitrLabel = new QLabel( qtr( "Bitrate" ) );
    pvrPropLayout->addWidget( pvrBitrLabel, 2, 0 );

561 562 563
    pvrBitr = new QSpinBox;
    pvrBitr->setAlignment( Qt::AlignRight );
    pvrBitr->setSuffix(" kHz");
564
    setMaxBound( pvrBitr );
565
    pvrPropLayout->addWidget( pvrBitr, 2, 1 );
566 567

    /* PVR CONNECTs */
568 569
    CuMRL( pvrDevice, textChanged( QString ) );
    CuMRL( pvrRadioDevice, textChanged( QString ) );
570 571

    CuMRL( pvrFreq, valueChanged ( int ) );
572
    CuMRL( pvrBitr, valueChanged ( int ) );
573 574 575 576 577
    CuMRL( pvrNormBox,  currentIndexChanged ( int ) );

    /*********************
     * DirectShow Stuffs *
     *********************/
578
    addModuleAndLayouts( DSHOW_DEVICE, dshow, "DirectShow" );
579

580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
    /* dshow Main */

    QLabel *dshowVDeviceLabel = new QLabel( qtr( "Video Device Name " ) );
    dshowDevLayout->addWidget( dshowVDeviceLabel, 0, 0 );

    QLabel *dshowADeviceLabel = new QLabel( qtr( "Audio Device Name " ) );
    dshowDevLayout->addWidget( dshowADeviceLabel, 1, 0 );

    QComboBox *dshowVDevice = new QComboBox;
    dshowDevLayout->addWidget( dshowVDevice, 0, 1 );

    QComboBox *dshowADevice = new QComboBox;
    dshowDevLayout->addWidget( dshowADevice, 1, 1 );

    QPushButton *dshowVRefresh = new QPushButton( qtr( "Update List" ) );
    dshowDevLayout->addWidget( dshowVRefresh, 0, 2 );

    QPushButton *dshowARefresh = new QPushButton( qtr( "Update List" ) );
    dshowDevLayout->addWidget( dshowARefresh, 1, 2 );

    QPushButton *dshowVConfig = new QPushButton( qtr( "Configure" ) );
    dshowDevLayout->addWidget( dshowVConfig, 0, 3 );

    QPushButton *dshowAConfig = new QPushButton( qtr( "Configure" ) );
    dshowDevLayout->addWidget( dshowAConfig, 1, 3 );

    /* dshow Properties */

    QLabel *dshowVSizeLabel = new QLabel( qtr( "Video size" ) );
    dshowPropLayout->addWidget( dshowVSizeLabel, 0, 0 );

    QLineEdit *dshowVSizeLine = new QLineEdit;
    dshowPropLayout->addWidget( dshowVSizeLine, 0, 1);

    /* dshow CONNECTs */
    CuMRL( dshowVDevice, currentIndexChanged ( int ) );
    CuMRL( dshowADevice, currentIndexChanged ( int ) );
    CuMRL( dshowVSizeLine, textChanged( QString ) );

619 620 621
    /**************
     * BDA Stuffs *
     **************/
622 623 624 625 626 627 628 629 630 631
    addModuleAndLayouts( BDA_DEVICE, bda, "DVB DirectShow" );

    /* bda Main */
    QLabel *bdaTypeLabel = new QLabel( qtr( "DVB Type:" ) );

    bdas = new QRadioButton( "DVB-S" );
    bdas->setChecked( true );
    bdac = new QRadioButton( "DVB-C" );
    bdat = new QRadioButton( "DVB-T" );

632 633 634 635
    bdaDevLayout->addWidget( bdaTypeLabel, 0, 0 );
    bdaDevLayout->addWidget( bdas, 0, 1 );
    bdaDevLayout->addWidget( bdac, 0, 2 );
    bdaDevLayout->addWidget( bdat, 0, 3 );
636 637 638 639

    /* bda Props */
    QLabel *bdaFreqLabel =
                    new QLabel( qtr( "Transponder/multiplex frequency" ) );
640 641
    bdaPropLayout->addWidget( bdaFreqLabel, 0, 0 );

642 643 644
    bdaFreq = new QSpinBox;
    bdaFreq->setAlignment( Qt::AlignRight );
    bdaFreq->setSuffix(" kHz");
645
    bdaFreq->setSingleStep( 1000 );
646
    setMaxBound( bdaFreq )
647 648 649
    bdaPropLayout->addWidget( bdaFreq, 0, 1 );

    bdaSrateLabel = new QLabel( qtr( "Transponder symbol rate" ) );
650 651
    bdaPropLayout->addWidget( bdaSrateLabel, 1, 0 );

652 653 654
    bdaSrate = new QSpinBox;
    bdaSrate->setAlignment( Qt::AlignRight );
    bdaSrate->setSuffix(" kHz");
655
    setMaxBound( bdaSrate );
656 657
    bdaPropLayout->addWidget( bdaSrate, 1, 1 );

658 659
    bdaBandLabel = new QLabel( qtr( "Bandwidth" ) );
    bdaPropLayout->addWidget( bdaBandLabel, 2, 0 );
660 661 662

    bdaBandBox = new QComboBox;
    setfillVLCConfigCombo( "dvb-bandwidth", p_intf, bdaBandBox );
663
    bdaPropLayout->addWidget( bdaBandBox, 2, 1 );
664

665 666 667
    bdaBandLabel->hide();
    bdaBandBox->hide();

668 669 670
    /* bda CONNECTs */
    CuMRL( bdaFreq, valueChanged ( int ) );
    CuMRL( bdaSrate, valueChanged ( int ) );
671
    CuMRL( bdaBandBox,  currentIndexChanged ( int ) );
672 673 674 675 676 677
    BUTTONACT( bdas, updateButtons() );
    BUTTONACT( bdat, updateButtons() );
    BUTTONACT( bdac, updateButtons() );
    BUTTONACT( bdas, updateMRL() );
    BUTTONACT( bdat, updateMRL() );
    BUTTONACT( bdac, updateMRL() );
678 679 680 681

    /**************
     * DVB Stuffs *
     **************/
682
    addModuleAndLayouts( DVB_DEVICE, dvb, "DVB" );
683 684 685

    /* DVB Main */
    QLabel *dvbDeviceLabel = new QLabel( qtr( "Adapter card to tune" ) );
686
    QLabel *dvbTypeLabel = new QLabel( qtr( "DVB Type:" ) );
687

688
    dvbCard = new QSpinBox;
689 690 691 692
    dvbCard->setAlignment( Qt::AlignRight );
    dvbCard->setPrefix( "/dev/dvb/adapter" );

    dvbDevLayout->addWidget( dvbDeviceLabel, 0, 0 );
693
    dvbDevLayout->addWidget( dvbCard, 0, 2, 1, 2 );
694 695 696 697 698 699

    dvbs = new QRadioButton( "DVB-S" );
    dvbs->setChecked( true );
    dvbc = new QRadioButton( "DVB-C" );
    dvbt = new QRadioButton( "DVB-T" );

700
    dvbDevLayout->addWidget( dvbTypeLabel, 1, 0 );
701 702 703
    dvbDevLayout->addWidget( dvbs, 1, 1 );
    dvbDevLayout->addWidget( dvbc, 1, 2 );
    dvbDevLayout->addWidget( dvbt, 1, 3 );
704

705
    /* DVB Props panel */
706 707
    QLabel *dvbFreqLabel =
                    new QLabel( qtr( "Transponder/multiplex frequency" ) );
708 709
    dvbPropLayout->addWidget( dvbFreqLabel, 0, 0 );

710 711 712
    dvbFreq = new QSpinBox;
    dvbFreq->setAlignment( Qt::AlignRight );
    dvbFreq->setSuffix(" kHz");
713
    setMaxBound( dvbFreq  );
714 715 716
    dvbPropLayout->addWidget( dvbFreq, 0, 1 );

    QLabel *dvbSrateLabel = new QLabel( qtr( "Transponder symbol rate" ) );
717 718
    dvbPropLayout->addWidget( dvbSrateLabel, 1, 0 );

719
    dvbSrate = new QSpinBox;
720 721
    dvbSrate->setAlignment( Qt::AlignRight );
    dvbSrate->setSuffix(" kHz");
722
    setMaxBound( dvbSrate );
723 724 725 726 727 728
    dvbPropLayout->addWidget( dvbSrate, 1, 1 );

    /* DVB CONNECTs */
    CuMRL( dvbCard, valueChanged ( int ) );
    CuMRL( dvbFreq, valueChanged ( int ) );
    CuMRL( dvbSrate, valueChanged ( int ) );
729

730 731 732 733 734 735 736 737 738 739 740 741
    BUTTONACT( dvbs, updateButtons() );
    BUTTONACT( dvbt, updateButtons() );
    BUTTONACT( dvbc, updateButtons() );

    /* General connects */
    connect( ui.deviceCombo, SIGNAL( activated( int ) ),
                     stackedDevLayout, SLOT( setCurrentIndex( int ) ) );
    connect( ui.deviceCombo, SIGNAL( activated( int ) ),
                     stackedPropLayout, SLOT( setCurrentIndex( int ) ) );
    CONNECT( ui.deviceCombo, activated( int ), this, updateMRL() );

#undef addModule
742 743 744 745 746
}

CaptureOpenPanel::~CaptureOpenPanel()
{}

747
void CaptureOpenPanel::clear()
748 749
{}

750
void CaptureOpenPanel::updateMRL()
751 752
{
    QString mrl = "";
753 754 755
    int i_devicetype = ui.deviceCombo->itemData(
            ui.deviceCombo->currentIndex() ).toInt();
    msg_Dbg( p_intf, "Capture Type: %i", i_devicetype );
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
    switch( i_devicetype )
    {
    case V4L_DEVICE:
        mrl = "v4l://";
        mrl += " :v4l-vdev=" + v4lVideoDevice->text();
        mrl += " :v4l-adev=" + v4lAudioDevice->text();
        mrl += " :v4l-norm=" + QString("%1").arg( v4lNormBox->currentIndex() );
        mrl += " :v4l-frequency=" + QString("%1").arg( v4lFreq->value() );
        break;
    case PVR_DEVICE:
        mrl = "pvr://";
        mrl += " :pvr-device=" + pvrDevice->text();
        mrl += " :pvr-radio-device=" + pvrRadioDevice->text();
        mrl += " :pvr-norm=" + QString("%1").arg( pvrNormBox->currentIndex() );
        if( pvrFreq->value() )
            mrl += " :pvr-frequency=" + QString("%1").arg( pvrFreq->value() );
        if( pvrBitr->value() )
            mrl += " :pvr-bitrate=" + QString("%1").arg( pvrBitr->value() );
        break;
    case DVB_DEVICE:
        mrl = "dvb://";
        mrl += " :dvb-adapter=" + QString("%1").arg( dvbCard->value() );
        mrl += " :dvb-frequency=" + QString("%1").arg( dvbFreq->value() );
        mrl += " :dvb-srate=" + QString("%1").arg( dvbSrate->value() );
        break;
    case BDA_DEVICE:
782 783 784 785 786
        if( bdas->isChecked() ) mrl = "dvb-s://";
        else if(  bdat->isChecked() ) mrl = "dvb-t://";
        else if(  bdac->isChecked() ) mrl = "dvb-c://";
        else return;
        mrl += " :dvb-frequency=" + QString("%1").arg( bdaFreq->value() );
787 788
        if( bdas->isChecked() || bdac->isChecked() )
            mrl += " :dvb-srate=" + QString("%1").arg( bdaSrate->value() );
789
        else
790 791
            mrl += " :dvb-bandwidth=" +
                QString("%1").arg( bdaBandBox->itemData(
792
                    bdaBandBox->currentIndex() ).toInt() );
793
        break;
794
  case DSHOW_DEVICE:
795 796
        break;
    }
797 798 799 800 801
    emit mrlUpdated( mrl );
}

void CaptureOpenPanel::updateButtons()
{
802 803 804 805 806 807 808 809 810 811 812 813
    int i_devicetype = ui.deviceCombo->itemData(
            ui.deviceCombo->currentIndex() ).toInt();
    msg_Dbg( p_intf, "Capture Type: %i", i_devicetype );
    switch( i_devicetype )
    {
    case DVB_DEVICE:
        if( dvbs->isChecked() ) dvbFreq->setSuffix(" kHz");
        if( dvbc->isChecked() || dvbt->isChecked() ) dvbFreq->setSuffix(" Hz");
        break;
    case BDA_DEVICE:
        if( bdas->isChecked() || bdac->isChecked() )
        {
814 815
            bdaSrate->show();
            bdaSrateLabel->show();
816 817
            bdaBandBox->hide();
            bdaBandLabel->hide();
818 819 820
        }
        else
        {
821
            bdaSrate->hide();
822
            bdaSrateLabel->hide();
823 824
            bdaBandBox->show();
            bdaBandLabel->show();
825 826 827
        }
        break;
    }
828
}