Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  profile_selector.cpp   Sprache: C

 

/*****************************************************************************
 * profile_selector.cpp : A small profile selector and editor
 ****************************************************************************
 * Copyright (C) 2009 the VideoLAN team
 *
 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
 *
 * 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.
 *****************************************************************************/


#include "dialogs/sout/profile_selector.hpp"
#include "dialogs/sout/profiles.hpp"
#include "dialogs/sout/sout.hpp"
#include "util/soutchain.hpp"

#include <QHBoxLayout>
#include <QToolButton>
#include <QComboBox>
#include <QLabel>
#include <QMessageBox>
#include <QRadioButton>
#include <QRegularExpression>
#include <QButtonGroup>
#include <QSpinBox>
#include <QUrl>
#include <QListWidgetItem>
#include <QFontMetrics>

#include <cassert>
#include <vlc_modules.h>

#define CATPROP2NAME( val ) QString("valueholder_%1").arg( val )
#define CATANDPROP( cat, prop ) QString("%1_%2").arg( cat ).arg( prop )
#define OLDFORMAT "^\\w+;\\d+;\\d+;\\d+;"

VLCProfileSelector::VLCProfileSelector( QWidget *_parent ): QWidget( _parent )
{
    QHBoxLayout *layout = new QHBoxLayout( this );

    QLabel *prLabel = new QLabel( qtr( "Profile"), this );
    layout->addWidget( prLabel );

    profileBox = new QComboBox( this );
    layout->addWidget( profileBox );

    QToolButton *editButton = new QToolButton( this );
    editButton->setIcon( QIcon( ":/menu/preferences.svg" ) );
    editButton->setToolTip( qtr( "Edit selected profile" ) );
    layout->addWidget( editButton );

    QToolButton *deleteButton = new QToolButton( this );
    deleteButton->setIcon( QIcon( ":/menu/clear.svg" ) );
    deleteButton->setToolTip( qtr( "Delete selected profile" ) );
    layout->addWidget( deleteButton );

    QToolButton *newButton = new QToolButton( this );
    newButton->setIcon( QIcon( ":/menu/profile_new.svg" ) );
    newButton->setToolTip( qtr( "Create a new profile" ) );
    layout->addWidget(newButton);

    BUTTONACT( newButton, &VLCProfileSelector::newProfile );
    BUTTONACT( editButton, &VLCProfileSelector::editProfile );
    BUTTONACT( deleteButton, &VLCProfileSelector::deleteProfile );
    fillProfilesCombo();

    connect( profileBox, QOverload<int>::of(&QComboBox::activated),
             this, &VLCProfileSelector::updateOptions );
    updateOptions( qMax(profileBox->currentIndex(), 0) );
}

VLCProfileSelector::~VLCProfileSelector()
{
    QSettings settings(
#ifdef _WIN32
            QSettings::IniFormat,
#else
            QSettings::NativeFormat,
#endif
            QSettings::UserScope, "vlc", "vlc-qt-interface" );
    ;
    settings.setValue( "codecs-profiles-selected", profileBox->currentText() );
}

inline void VLCProfileSelector::fillProfilesCombo()
{
    QSettings settings(
#ifdef _WIN32
            QSettings::IniFormat,
#else
            QSettings::NativeFormat,
#endif
            QSettings::UserScope, "vlc", "vlc-qt-interface" );

    int i_size = settings.beginReadArray( "codecs-profiles" );

    for( int i = 0; i < i_size; i++ )
    {
        settings.setArrayIndex( i );
        if( settings.value( "Profile-Name" ).toString().isEmpty() ) continue;
        profileBox->addItem( settings.value( "Profile-Name" ).toString(),
                settings.value( "Profile-Value" ) );
    }
    if( i_size == 0 )
    {
        for( size_t i = 0; i < NB_PROFILE; i++ )
        {
            profileBox->addItem( video_profile_name_list[i],
                                 video_profile_value_list[i] );
        }
    }
    settings.endArray();

    profileBox->setCurrentIndex(
        profileBox->findText(
            settings.value( "codecs-profiles-selected" ).toString() ));

}

void VLCProfileSelector::newProfile()
{
    editProfilePrivate( "", "" );
}

void VLCProfileSelector::editProfile()
{
    editProfilePrivate( profileBox->currentText(),
                 profileBox->itemData( profileBox->currentIndex() ).toString() );
}

void VLCProfileSelector::editProfilePrivate( const QString& qs, const QString& value )
{
    /* Create the Profile Editor */
    QWidget* windowWidget = window();
    QWindow* parentWindow = windowWidget ? windowWidget->windowHandle() : nullptr;
    VLCProfileEditor *editor = new VLCProfileEditor( qs, value,  parentWindow );

    /* Show it */
    if( QDialog::Accepted == editor->exec() )
    {
        /* New Profile */
        if( qs.isEmpty() )
            profileBox->addItem( editor->name, QVariant( editor->transcodeValue() ) );
        /* Update old profile */
        else
        {
            /* Look for the profile */
            int i_profile = profileBox->findText( qs );
            assert( i_profile != -1 );
            profileBox->setItemText( i_profile, editor->name );
            profileBox->setItemData( i_profile, editor->transcodeValue() );
            /* Force mrl recreation */
            updateOptions( i_profile );
        }
    }
    delete editor;

    saveProfiles();
    emit optionsChanged();
}

void VLCProfileSelector::deleteProfile()
{
    profileBox->removeItem( profileBox->currentIndex() );
    saveProfiles();
}

void VLCProfileSelector::saveProfiles()
{
    QSettings settings(
#ifdef _WIN32
            QSettings::IniFormat,
#else
            QSettings::NativeFormat,
#endif
            QSettings::UserScope, "vlc", "vlc-qt-interface" );

    settings.remove( "codecs-profiles" ); /* Erase old profiles to be rewritten */
    settings.beginWriteArray( "codecs-profiles" );
    for( int i = 0; i < profileBox->count(); i++ )
    {
        settings.setArrayIndex( i );
        settings.setValue( "Profile-Name", profileBox->itemText( i ) );
        settings.setValue( "Profile-Value", profileBox->itemData( i ).toString() );
    }
    settings.endArray();
}

void VLCProfileSelector::updateOptions( int i )
{
    QString options = profileBox->itemData( i ).toString();
    QRegularExpression rx(QStringLiteral(OLDFORMAT));
    if ( !options.contains( ";" ) ) return;
    if ( rx.match( options ).hasMatch() )
        return updateOptionsOldFormat( i );

    transcode.clear();

    QStringList tuples = options.split( ";" );
    typedef QHash<QString, QString> proptovalueHashType;
    QHash<QString, proptovalueHashType *> categtopropHash;
    proptovalueHashType *proptovalueHash;
    QString value;

    /* Build a double hash structure because we need to make ordered lookups */
    foreach ( const QString &tuple, tuples )
    {
        QStringList keyvalue = tuple.split( "=" );
        if ( keyvalue.count() != 2 ) continue;
        QString key = keyvalue[0];
        value = keyvalue[1];
        keyvalue = key.split( "_" );
        if ( keyvalue.count() != 2 ) continue;
        QString categ = keyvalue[0];
        QString prop = keyvalue[1];

        if ( ! categtopropHash.contains( categ ) )
        {
            proptovalueHash = new proptovalueHashType();
            categtopropHash.insert( categ, proptovalueHash );
        } else {
            proptovalueHash = categtopropHash.value( categ );
        }
        proptovalueHash->insert( prop, value );
    }

    /* Now we can build the/translate into MRL */
#define HASHPICK( categ, prop ) \
    if ( categtopropHash.contains( categ ) ) \
    {\
        proptovalueHash = categtopropHash.value( categ );\
        value = proptovalueHash->take( prop );\
    }\
    else value = QString()

    transcode.begin( "transcode" );

    /* First muxer options */
    HASHPICK( "muxer", "mux" );
    if ( value.isEmpty() ) goto cleanup;
    mux = value;

    HASHPICK( "video", "enable" );
    if ( !value.isEmpty() )
    {
        HASHPICK( "video", "codec" );

        if ( !value.isEmpty() )
        {
            transcode.option( "vcodec", value );

            HASHPICK( "vcodec", "bitrate" );
            if ( value.toInt() > 0 )
            {
                transcode.option( "vb", value.toInt() );
            }

            HASHPICK( "video", "filters" );
            if ( !value.isEmpty() )
            {
                QStringList valuesList = QUrl::fromPercentEncoding( value.toLatin1() ).split( ";" );
                transcode.option( "vfilter", valuesList.join( ":" ) );
            }

            /*if ( codec is h264 )*/
            {
                /* special handling */
                QStringList codecoptions;

                HASHPICK( "vcodec", "qp" );
                if( value.toInt() > 0 )
                    codecoptions << QString( "qp=%1" ).arg( value );

                HASHPICK( "vcodec", "custom" );
                if( !value.isEmpty() )
                    codecoptions << QUrl::fromPercentEncoding( value.toLatin1() );

                if ( codecoptions.count() )
                    transcode.option( "venc",
                        QString("x264{%1}").arg( codecoptions.join(",") ) );
            }

            HASHPICK( "vcodec", "framerate" );
            if ( !value.isEmpty() && value.toInt() > 0 )
                transcode.option( "fps", value );

            HASHPICK( "vcodec", "scale" );
            if ( !value.isEmpty() )
                transcode.option( "scale", value );

            HASHPICK( "vcodec", "width" );
            if ( !value.isEmpty() && value.toInt() > 0 )
                transcode.option( "width", value );

            HASHPICK( "vcodec", "height" );
            if ( !value.isEmpty() && value.toInt() > 0 )
                transcode.option( "height", value );
        }
    } else {
        transcode.option( "vcodec", "none" );
    }

    HASHPICK( "audio", "enable" );
    if ( !value.isEmpty() )
    {
        HASHPICK( "audio", "codec" );
        if ( !value.isEmpty() )
        {
            transcode.option( "acodec", value );

            HASHPICK( "acodec", "bitrate" );
            transcode.option( "ab", value.toInt() );

            HASHPICK( "acodec", "channels" );
            transcode.option( "channels", value.toInt() );

            HASHPICK( "acodec", "samplerate" );
            transcode.option( "samplerate", value.toInt() );

            /* Build audio filter chain: user-selected filters + optional gain boost */
            {
                QStringList audioFilters;

                HASHPICK( "audio", "filters" );
                if ( !value.isEmpty() )
                    audioFilters << QUrl::fromPercentEncoding( value.toLatin1() ).split( ";" );

                HASHPICK( "acodec", "gain" );
                if ( !value.isEmpty() )
                {
                    double gainPct = value.toDouble();
                    if ( gainPct > 0.0 )
                    {
                        /* normvol peak-level multiplier: 100% = 1.0 (no change),
                         * 200% = 2.0 (double volume), 50% = 0.5 (half volume). */

                        double gainMult = gainPct / 100.0;
                        audioFilters.prepend(
                            QString("normvol{max-level=%1}").arg( gainMult, 0, 'f', 2 ) );
                    }
                }

                if ( !audioFilters.isEmpty() )
                    transcode.option( "afilter", audioFilters.join( ":" ) );
            }

        }
    } else {
        transcode.option( "acodec", "none" );
    }

    HASHPICK( "subtitles", "enable" );
    if( !value.isEmpty() )
    {
        HASHPICK( "subtitles", "overlay" );
        if ( value.isEmpty() )
        {
            HASHPICK( "subtitles", "codec" );
            transcode.option( "scodec", value );
        }
        else
        {
            transcode.option( "soverlay" );
        }
    } else {
        transcode.option( "scodec", "none" );
    }
    transcode.end();
#undef HASHPICK

    cleanup:
    /* Temp hash tables cleanup */
    foreach( proptovalueHashType *hash, categtopropHash )
        delete hash;

    emit optionsChanged();
}

void VLCProfileSelector::updateOptionsOldFormat( int i )
{
    QStringList options = profileBox->itemData( i ).toString().split( ";" );
    if( options.count() < 16 )
        return;

    mux = options[0];

    if( options[1].toInt() || options[2].toInt() || options[3].toInt() )
    {
        transcode.begin( "transcode" );

        if( options[1].toInt() )
        {
            transcode.option( "vcodec", options[4] );
            if( options[4] != "none" )
            {
                transcode.option( "vb", options[5].toInt() );
                if( !options[7].isEmpty() && options[7].toInt() > 0 )
                    transcode.option( "fps", options[7] );
                if( !options[6].isEmpty() )
                    transcode.option( "scale", options[6] );
                if( !options[8].isEmpty() && options[8].toInt() > 0 )
                    transcode.option( "width", options[8].toInt() );
                if( !options[9].isEmpty() && options[9].toInt() > 0 )
                    transcode.option( "height", options[9].toInt() );
            }
        }

        if( options[2].toInt() )
        {
            transcode.option( "acodec", options[10] );
            if( options[10] != "none" )
            {
                transcode.option( "ab", options[11].toInt() );
                transcode.option( "channels", options[12].toInt() );
                transcode.option( "samplerate", options[13].toInt() );
            }
        }

        if( options[3].toInt() )
        {
            transcode.option( "scodec", options[14] );
            if( options[15].toInt() )
                transcode.option( "soverlay" );
        }

        transcode.end();
    }
    else
        transcode.clear();
    emit optionsChanged();
}


/**
 * VLCProfileEditor
 **/

VLCProfileEditor::VLCProfileEditor( const QString& qs_name, const QString& value,
        QWindow *_parent )
                 : QVLCDialog( _parent, NULL )
{
    ui.setupUi( this );
    ui.buttonGroup->setObjectName( CATPROP2NAME( CATANDPROP( "muxer", "mux" ) ) );
    if( !qs_name.isEmpty() )
    {
        ui.profileLine->setText( qs_name );
        ui.profileLine->setReadOnly( true );
    }
    loadCapabilities();
    registerCodecs();
    registerFilters();

    QPushButton *saveButton = new QPushButton(
                ( qs_name.isEmpty() ) ? qtr( "Create" ) : qtr( "Save" ) );
    ui.buttonBox->addButton( saveButton, QDialogButtonBox::AcceptRole );
    connect( ui.buttonBox, &QDialogButtonBox::accepted, this, &VLCProfileEditor::accept );
    QPushButton *cancelButton = new QPushButton( qtr( "Cancel" ) );
    ui.buttonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
    connect( ui.buttonBox, &QDialogButtonBox::rejected, this, &VLCProfileEditor::reject );

    connect( ui.valueholder_video_copy, &QtCheckboxChanged,
             this, &VLCProfileEditor::activatePanels );
    connect( ui.valueholder_audio_copy, &QtCheckboxChanged,
             this, &VLCProfileEditor::activatePanels );
    connect( ui.valueholder_subtitles_overlay, &QtCheckboxChanged,
             this, &VLCProfileEditor::activatePanels );
    connect( ui.valueholder_vcodec_bitrate, &QSpinBox::editingFinished,
             this, &VLCProfileEditor::fixBirateState );
    connect( ui.valueholder_vcodec_qp, &QSpinBox::editingFinished,
             this, &VLCProfileEditor::fixQPState );
    connect( ui.valueholder_video_codec, QOverload<int>::of(&QComboBox::currentIndexChanged),
             this, &VLCProfileEditor::codecSelected );
    reset();

    fillProfile( value );
    muxSelected();
    codecSelected();
}

void VLCProfileEditor::loadCapabilities()
{
    size_t count;
    module_t **p_all = module_list_get (&count);

    /* Parse the module list for capabilities and probe each of them */
    for (size_t i = 0; i < count; i++)
    {
         module_t *p_module = p_all[i];

         if( module_provides( p_module, "sout mux" ) )
             caps["muxers"].insert( module_get_object( p_module ) );
//        else if ( module_provides( p_module, "encoder" ) )
//            caps["encoders"].insert( module_get_object( p_module ) );
    }
    module_list_free (p_all);
}

inline void VLCProfileEditor::registerFilters()
{
    size_t count;
    module_t **p_all = module_list_get (&count);

    for (size_t i = 0; i < count; i++)
    {
        module_t *p_module = p_all[i];
        if ( module_get_score( p_module ) > 0 ) continue;

        QString capability = module_get_capability( p_module );
        QListWidget *listWidget = NULL;
        QListWidgetItem *item;

        if ( capability == "video filter" )
            listWidget = ui.valueholder_video_filters;
        else if ( capability == "audio filter" )
            listWidget = ui.valueholder_audio_filters;

        if ( !listWidget ) continue;

        item = new QListWidgetItem( module_GetLongName( p_module ) );
        item->setCheckState( Qt::Unchecked );
        item->setToolTip( QString( module_get_help( p_module ) ) );
        item->setData( Qt::UserRole, QString( module_get_object( p_module ) ) );
        listWidget->addItem( item );
    }
    module_list_free (p_all);

    ui.valueholder_video_filters->sortItems();
    ui.valueholder_audio_filters->sortItems();
}

inline void VLCProfileEditor::registerCodecs()
{
#define SETMUX( button, val, mod, vid, aud, men, sub, stream, chaps ) \
    ui.button->setProperty( "sout", val );\
    ui.button->setProperty( "module", mod );\
    ui.button->setProperty( "capvideo", vid );\
    ui.button->setProperty( "capaudio", aud );\
    ui.button->setProperty( "capmenu", men );\
    ui.button->setProperty( "capsubs", sub );\
    ui.button->setProperty( "capstream", stream );\
    ui.button->setProperty( "capchaps", chaps );\
    connect( ui.button, &QRadioButton::clicked, this, &VLCProfileEditor::muxSelected );
    SETMUX( PSMux, "ps", "ps",  true, true, false, true, false, true )
    SETMUX( TSMux, "ts", "ts",  true, true, false, true, true, false )
    SETMUX( WEBMux, "webm", "avformat", true, true, false, false, true, false )
    SETMUX( MPEG1Mux, "mpeg1", "ps", true, true, false, false, false, false )
    SETMUX( OggMux, "ogg", "ogg", true, true, false, false, true, true )
    SETMUX( ASFMux, "asf", "asf", true, true, false, true, true, true )
    SETMUX( MOVMux, "mp4", "mp4", true, true, true, true, true, false )
    SETMUX( WAVMux, "wav", "wav", false, true, false, false, false, false )
    SETMUX( FLACMux, "flac", "dummy", false, true, false, false, false, false )
    SETMUX( MP3Mux, "mp3", "dummy", false, true, false, false, false, false )
    SETMUX( RAWMux, "raw", "dummy", true, true, false, false, false, false )
    SETMUX( FLVMux, "flv", "avformat", true, true, false, false, true, false )
    SETMUX( MKVMux, "mkv", "avformat", true, true, true, true, true, true )
    SETMUX( AVIMux, "avi", "avi", true, true, false, false, false, false )
    SETMUX( MJPEGMux, "mpjpeg", "mpjpeg", true, false, false, false, false, false )
#undef SETMUX

#define ADD_VCODEC( name, fourcc ) \
            ui.valueholder_video_codec->addItem( name, QVariant( fourcc ) );
    ADD_VCODEC( "MPEG-1", "mp1v" )
    ADD_VCODEC( "MPEG-2", "mp2v" )
    ADD_VCODEC( "MPEG-4", "mp4v" )
    ADD_VCODEC( "DIVX 1" , "DIV1" )
    ADD_VCODEC( "DIVX 2" , "DIV2" )
    ADD_VCODEC( "DIVX 3" , "DIV3" )
    ADD_VCODEC( "H-263", "H263" )
    ADD_VCODEC( "H-264 (AVC)", "h264" )
    ADD_VCODEC( "H-265 (HEVC)", "hevc" )
    ADD_VCODEC( "AV1", "av01" )
    ADD_VCODEC( "VP8", "VP80" )
    ADD_VCODEC( "WMV1", "WMV1" )
    ADD_VCODEC( "WMV2" , "WMV2" )
    ADD_VCODEC( "M-JPEG", "MJPG" )
    ADD_VCODEC( "Theora", "theo" )
#undef ADD_VCODEC
    /* can do quality */
    qpcodecsList << "h264";

#define ADD_ACODEC( name, fourcc ) ui.valueholder_audio_codec->addItem( name, QVariant( fourcc ) );
    ADD_ACODEC( "MPEG Audio", "mpga" )
    ADD_ACODEC( "MP3", "mp3" )
    ADD_ACODEC( "MPEG 4 Audio ( AAC )", "mp4a" )
    ADD_ACODEC( "A52/AC-3", "a52" )
    ADD_ACODEC( "Vorbis", "vorb" )
    ADD_ACODEC( "Flac", "flac" )
    ADD_ACODEC( "Opus", "opus" )
    ADD_ACODEC( "Speex", "spx" )
    ADD_ACODEC( "PCM 16-bit", "s16l" )
    ADD_ACODEC( "WMA2", "wma2" )
#undef ADD_ACODEC

#define ADD_SCALING( factor ) ui.valueholder_vcodec_scale->addItem( factor );
    ADD_SCALING( qtr("Auto") );
    ADD_SCALING( "1" )
    ADD_SCALING( "0.25" )
    ADD_SCALING( "0.5" )
    ADD_SCALING( "0.75" )
    ADD_SCALING( "1.25" )
    ADD_SCALING( "1.5" )
    ADD_SCALING( "1.75" )
    ADD_SCALING( "2" )
#undef ADD_SCALING

#define ADD_SAMPLERATE( sample, val ) ui.valueholder_acodec_samplerate->addItem( sample, val );
    ADD_SAMPLERATE( "8000 Hz", 8000 )
    ADD_SAMPLERATE( "11025 Hz", 11025 )
    ADD_SAMPLERATE( "22050 Hz", 22050 )
    ADD_SAMPLERATE( "44100 Hz", 44100 )
    ADD_SAMPLERATE( "48000 Hz", 48000 )
#undef ADD_SAMPLERATE

#define ADD_SCODEC( name, fourcc ) ui.valueholder_subtitles_codec->addItem( name, QVariant( fourcc ) );
    ADD_SCODEC( "DVBS (DVB subtitles)", "dvbs" )
    ADD_SCODEC( "tx3g (MPEG-4 timed text)", "tx3g" )
    ADD_SCODEC( "T-REC 140 (for rtp)", "t140" )
#undef ADD_SCODEC
}

void VLCProfileEditor::muxSelected()
{
    QRadioButton *current =
            qobject_cast<QRadioButton *>( ui.buttonGroup->checkedButton() );

#define SETYESNOSTATE( name, prop ) \
    ui.name->setChecked( current->property( prop ).toBool() )

    /* dumb :/ */
    SETYESNOSTATE( capvideo, "capvideo" );
    SETYESNOSTATE( capaudio, "capaudio" );
    SETYESNOSTATE( capmenu, "capmenu" );
    SETYESNOSTATE( capsubs, "capsubs" );
    SETYESNOSTATE( capstream, "capstream" );
    SETYESNOSTATE( capchaps, "capchaps" );

    int textsize = QFontMetrics(ui.muxerwarning->font()).ascent();
    if( current->property("module").toString() == "avformat" )
        ui.muxerwarning->setText(
                    QString( "<img src=\":/menu/info.svg\" width=%2 height=%2/> %1" )
                    .arg( qtr( "This muxer is not provided directly by VLC: It could be missing." ) )
                    .arg(textsize)
                    );
    else if ( !caps["muxers"].contains( current->property("module").toString() ) &&
              !caps["muxers"].contains( "mux_" + current->property("module").toString() ) )
        ui.muxerwarning->setText(
                    QString( "<img src=\":/menu/clear.svg\" width=%2 height=%2/> %1" )
                    .arg( qtr( "This muxer is missing. Using this profile will fail" ) )
                    .arg(textsize)
                    );
    else
        ui.muxerwarning->setText("");
    return;

#undef SETYESNOSTATE
}

void VLCProfileEditor::codecSelected()
{
    /* Enable quality preset */
    QString currentcodec = ui.valueholder_video_codec->
            itemData(ui.valueholder_video_codec->currentIndex() ).toString();
    ui.valueholder_vcodec_qp->setEnabled( qpcodecsList.contains( currentcodec ) );
}

void VLCProfileEditor::fillProfile( const QString& qs )
{
    QRegularExpression rx(QStringLiteral(OLDFORMAT));
    if ( rx.match( qs ).hasMatch() ) return fillProfileOldFormat( qs );

    QStringList tuples = qs.split( ";" );
    foreach ( const QString &tuple, tuples )
    {
        QStringList keyvalue = tuple.split( "=" );
        if ( keyvalue.count() != 2 ) continue;
        QString key = keyvalue[0];
        QString value = keyvalue[1];
        QObject *object = findChild<QObject *>( CATPROP2NAME( key ) );
        if ( object )
        {
            if( object->inherits( "QButtonGroup" ) )
            { /* Buttongroup for Radios */
                const QButtonGroup *group = qobject_cast<const QButtonGroup *>( object );
                foreach( QAbstractButton *button, group->buttons() )
                {
                    if ( button->property("sout").toString() == value )
                    {
                        button->setChecked( true );
                        break;/* radios are exclusive */
                    }
                }
            }
            else if( object->inherits( "QCheckBox" ) )
            {
                QCheckBox *box = qobject_cast<QCheckBox *>( object );
                box->setChecked( ! value.isEmpty() );
            }
            else if( object->inherits( "QGroupBox" ) )
            {
                QGroupBox *box = qobject_cast<QGroupBox *>( object );
                box->setChecked( ! value.isEmpty() );
            }
            else if( object->inherits( "QSpinBox" ) )
            {
                QSpinBox *box = qobject_cast<QSpinBox *>( object );
                box->setValue( value.toInt() );
            }
            else if( object->inherits( "QDoubleSpinBox" ) )
            {
                QDoubleSpinBox *box = qobject_cast<QDoubleSpinBox *>( object );
                box->setValue( value.toDouble() );
            }
            else if( object->inherits( "QComboBox" ) )
            {
                QComboBox *box = qobject_cast<QComboBox *>( object );
                box->setCurrentIndex( box->findData( value ) );
                if ( box->lineEdit() && box->currentIndex() == -1 )
                    box->lineEdit()->setText( value );
            }
            else if( object->inherits( "QLineEdit" ) )
            {
                QLineEdit *box = qobject_cast<QLineEdit *>( object );
                box->setText( QUrl::fromPercentEncoding( value.toLatin1() ) );
            }
            else if ( object->inherits( "QListWidget" ) )
            {
                QStringList valuesList = QUrl::fromPercentEncoding( value.toLatin1() ).split( ";" );
                const QListWidget *list = qobject_cast<const QListWidget *>( object );
                for( int i=0; i < list->count(); i++ )
                {
                    QListWidgetItem *item = list->item( i );
                    if ( valuesList.contains( item->data( Qt::UserRole ).toString() ) )
                        item->setCheckState( Qt::Checked );
                    else
                        item->setCheckState( Qt::Unchecked );
                }
            }
        }
    }
}

void VLCProfileEditor::fillProfileOldFormat( const QString& qs )
{
    QStringList options = qs.split( ";" );
    if( options.count() < 16 )
        return;

    const QString mux = options[0];
    for ( int i=0; i< ui.muxer->layout()->count(); i++ )
    {
        QRadioButton *current =
                qobject_cast<QRadioButton *>(ui.muxer->layout()->itemAt(i)->widget());
        if ( unlikely( !current ) ) continue;/* someone is messing up with ui */
        if ( current->property("sout").toString() == mux )
        {
            current->setChecked( true );
            break;/* radios are exclusive */
        }
    }

    ui.valueholder_video_copy->setChecked( !options[1].toInt() );
    ui.valueholder_video_enable->setChecked( ( options[4] != "none" ) );
    ui.valueholder_audio_copy->setChecked( !options[2].toInt() );
    ui.valueholder_audio_enable->setChecked( ( options[10] != "none" ) );
    ui.valueholder_subtitles_enable->setChecked( options[3].toInt() );

    ui.valueholder_video_codec->setCurrentIndex( ui.valueholder_video_codec->findData( options[4] ) );
    ui.valueholder_vcodec_bitrate->setValue( options[5].toInt() );
    if ( options[6].toInt() > 0 )
        ui.valueholder_vcodec_scale->setEditText( options[6] );
    else
        ui.valueholder_vcodec_scale->setCurrentIndex( 0 );
    ui.valueholder_vcodec_framerate->setValue( options[7].toDouble() );
    ui.valueholder_vcodec_width->setValue( options[8].toInt() );
    ui.valueholder_vcodec_height->setValue( options[9].toInt() );

    ui.valueholder_audio_codec->setCurrentIndex( ui.valueholder_audio_codec->findData( options[10] ) );
    ui.valueholder_acodec_bitrate->setValue( options[11].toInt() );
    ui.valueholder_acodec_channels->setValue( options[12].toInt() );

    int index = ui.valueholder_acodec_samplerate->findData( options[13] );
    if ( index == -1 ) index = ui.valueholder_acodec_samplerate->findData( 44100 );
    ui.valueholder_acodec_samplerate->setCurrentIndex( index );

    ui.valueholder_subtitles_codec->setCurrentIndex( ui.valueholder_subtitles_codec->findData( options[14] ) );
    ui.valueholder_subtitles_overlay->setChecked( options[15].toInt() );
}

void VLCProfileEditor::accept()
{
    if( ui.profileLine->text().isEmpty() )
    {
        QMessageBox::warning( this, qtr(" Profile Name Missing" ),
                qtr( "You must set a name for the profile." ) );
        ui.profileLine->setFocus();
        return;
    }
    name = ui.profileLine->text();

    QVLCDialog::accept();
}

#define currentData( box ) box->itemData( box->currentIndex() )

QString VLCProfileEditor::transcodeValue()
{
    QList<QObject *> allwidgets = findChildren<QObject *>();
    QStringList configuration;

    foreach( const QObject *object, allwidgets )
    {
        if ( ! object->objectName().startsWith( CATPROP2NAME( "" ) ) )
            continue;
        if ( object->inherits( "QWidget" ) &&
             ! qobject_cast<const QWidget *>(object)->isEnabled() ) continue;

        QString name = object->objectName();
        QStringList vals = object->objectName().split( "_" );
        if ( vals.count() != 3 ) continue;
        QString &categ = vals[1];
        QString &prop = vals[2];
        QString value;

        if( object->inherits( "QButtonGroup" ) )
        {
            const QButtonGroup *group = qobject_cast<const QButtonGroup *>( object );
            value = group->checkedButton()->property( "sout" ).toString();
        }
        else if( object->inherits( "QCheckBox" ) )
        {
            const QCheckBox *box = qobject_cast<const QCheckBox *>( object );
            value = box->isChecked() ? "yes" : "";
        }
        else if( object->inherits( "QGroupBox" ) )
        {
            const QGroupBox *box = qobject_cast<const QGroupBox *>( object );
            value = box->isChecked() ? "yes" : "";
        }
        else if( object->inherits( "QSpinBox" ) )
        {
            const QSpinBox *box = qobject_cast<const QSpinBox *>( object );
            value = QString::number( box->value() );
        }
        else if( object->inherits( "QDoubleSpinBox" ) )
        {
            const QDoubleSpinBox *box = qobject_cast<const QDoubleSpinBox *>( object );
            value =  QString::number( box->value() );
        }
        else if( object->inherits( "QComboBox" ) )
        {
            const QComboBox *box = qobject_cast<const QComboBox *>( object );
            value = currentData( box ).toString();
            if ( value.isEmpty() && box->lineEdit() ) value = box->lineEdit()->text();
        }
        else if( object->inherits( "QLineEdit" ) )
        {
            const QLineEdit *box = qobject_cast<const QLineEdit *>( object );
            value = QUrl::toPercentEncoding( box->text(), "", "_;" );
        }
        else if ( object->inherits( "QListWidget" ) )
        {
            const QListWidget *list = qobject_cast<const QListWidget *>( object );
            QStringList valuesList;
            for( int i=0; i < list->count(); i++ )
            {
                const QListWidgetItem *item = list->item( i );
                if ( item->checkState() == Qt::Checked )
                    valuesList.append( item->data( Qt::UserRole ).toString() );
            }
            value = QUrl::toPercentEncoding( valuesList.join( ";" ), "", "_;" );
        }

        if ( !value.isEmpty() )
            configuration << QString( "%1_%2=%3" )
                             .arg( categ ).arg( prop ).arg( value );
    }

    return configuration.join( ";" );
}

void VLCProfileEditor::reset()
{
    /* reset to default state as we can only check/enable existing values */
    ui.valueholder_video_copy->setChecked( false );
    ui.valueholder_audio_copy->setChecked( false );
    activatePanels();
    fixBirateState(); /* defaults to bitrate, not qp */
    /* end with top level ones for cascaded setEnabled() */
    ui.valueholder_video_enable->setChecked( false );
    ui.valueholder_audio_enable->setChecked( false );
    ui.valueholder_subtitles_enable->setChecked( false );
}

void VLCProfileEditor::activatePanels()
{
    ui.transcodevideo->setEnabled( ! ui.valueholder_video_copy->isChecked() );
    ui.transcodeaudio->setEnabled( ! ui.valueholder_audio_copy->isChecked() );
    ui.valueholder_subtitles_codec->setEnabled( ! ui.valueholder_subtitles_overlay->isChecked() );
}

void VLCProfileEditor::fixBirateState()
{
    /* exclusive bitrate choice */
    ui.valueholder_vcodec_qp->setValue( 0 );
}

void VLCProfileEditor::fixQPState()
{
    /* exclusive bitrate choice */
    ui.valueholder_vcodec_bitrate->setValue( 0 );
}

#undef CATPROP2NAME
#undef CATANDPROP
#undef OLDFORMAT

Messung
CHZG
83989090

¤ Dauer der Verarbeitung: 0.5 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104857
#Domains=418424