<commit_before>/*
    Copyright (C) 2007-2008 <NAME> <<EMAIL>>
    Copyright (C) 2008 <NAME> <<EMAIL>>
    Copyright (C) 2009 <NAME> <<EMAIL>>
    Copyright (C) 2009-2011 vlc-phonon AUTHORS
    Copyright (C) 2011 <NAME> <<EMAIL>>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "backend.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QLatin1Literal>
#include <QtCore/QtPlugin>
#include <QtCore/QVariant>
#include <QMessageBox>

#include <phonon/GlobalDescriptionContainer>
#include <phonon/pulsesupport.h>

#include <vlc/libvlc_version.h>

#include "audio/audiooutput.h"
#include "audio/audiodataoutput.h"
#include "audio/volumefadereffect.h"
#include "devicemanager.h"
#include "effect.h"
#include "effectmanager.h"
#include "mediaobject.h"
#include "sinknode.h"
#include "utils/debug.h"
#include "utils/libvlc.h"
#include "utils/mime.h"
#ifdef PHONON_EXPERIMENTAL
#include "video/videodataoutput.h"
#endif
#ifndef PHONON_NO_GRAPHICSVIEW
#include "video/videographicsobject.h"
#endif
#include "video/videowidget.h"

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
Q_EXPORT_PLUGIN2(phonon_vlc, Phonon::VLC::Backend)
#endif

namespace Phonon
{
namespace VLC
{

Backend *Backend::self;

Backend::Backend(QObject *parent, const QVariantList &)
    : QObject(parent)
    , m_deviceManager(0)
    , m_effectManager(0)
{
    self = this;

    // Backend information properties
    setProperty("identifier",     QLatin1String("phonon_vlc"));
    setProperty("backendName",    QLatin1String("VLC"));
    setProperty("backendComment", QLatin1String("VLC backend for Phonon"));
    setProperty("backendVersion", QLatin1String(PHONON_VLC_VERSION));
    setProperty("backendIcon",    QLatin1String("vlc"));
    setProperty("backendWebsite", QLatin1String("https://projects.kde.org/projects/kdesupport/phonon/phonon-vlc"));

    // Check if we should enable debug output
    int debugLevel = qgetenv("PHONON_BACKEND_DEBUG").toInt();
    if (debugLevel > 3) // 3 is maximum
        debugLevel = 3;
    Debug::setMinimumDebugLevel((Debug::DebugLevel)((int) Debug::DEBUG_NONE - 1 - debugLevel));

    // Actual libVLC initialisation
    if (LibVLC::init()) {
        debug() << "Using VLC version" << libvlc_get_version();
        if (!QCoreApplication::applicationName().isEmpty()) {
            QString userAgent =
                    QString("%0/%1 (Phonon/%2; Phonon-VLC/%3)").arg(
                        QCoreApplication::applicationName(),
                        QCoreApplication::applicationVersion(),
                        PHONON_VERSION_STR,
                        PHONON_VLC_VERSION);
            libvlc_set_user_agent(libvlc,
                                  QCoreApplication::applicationName().toUtf8().constData(),
                                  userAgent.toUtf8().constData());
        } else {
            qWarning("WARNING: Setting the user agent for streaming and PulseAudio requires you to set QCoreApplication::applicationName()");
        }
    } else {
#ifdef __GNUC__
#warning TODO - this error message is about as useful as a cooling unit in the arctic
#endif
        QMessageBox msg;
        msg.setIcon(QMessageBox::Critical);
        msg.setWindowTitle(tr("LibVLC Failed to Initialize"));
        msg.setText(tr("Phonon's VLC backend failed to start."
                       "\n\n"
                       "This usually means a problem with your VLC installation,"
                       " please report a bug with your distributor."));
        msg.setDetailedText(LibVLC::errorMessage());
        msg.exec();
        fatal() << "Phonon::VLC::vlcInit: Failed to initialize VLC";
    }

    // Initialise PulseAudio support
    PulseSupport *pulse = PulseSupport::getInstance();
    pulse->enable();
    connect(pulse, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)),
            SIGNAL(objectDescriptionChanged(ObjectDescriptionType)));

    m_deviceManager = new DeviceManager(this);
    m_effectManager = new EffectManager(this);
}

Backend::~Backend()
{
    if (LibVLC::self)
        delete LibVLC::self;
    if (GlobalAudioChannels::self)
        delete GlobalAudioChannels::self;
    if (GlobalSubtitles::self)
        delete GlobalSubtitles::self;
    PulseSupport::shutdown();
}

QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &/*args*/)
{
    if (!LibVLC::self || !libvlc)
        return 0;

    switch (c) {
    case MediaObjectClass:
        return new MediaObject(parent);
    case AudioOutputClass:
        return new AudioOutput(parent);
#ifdef __GNUC__
#warning using sout in VLC2 breaks libvlcs vout functions, see vlc bug 6992
// https://trac.videolan.org/vlc/ticket/6992
#endif
#if (LIBVLC_VERSION_INT < LIBVLC_VERSION(2, 0, 0, 0))
    // FWIW: the case is inside the if because that gives clear indication which
    // frontend objects are not supported!
    case AudioDataOutputClass:
        return new AudioDataOutput(parent);
#endif
#ifdef PHONON_EXPERIMENTAL
    case VideoDataOutputClass:
        return new VideoDataOutput(parent);
#endif
#ifndef PHONON_NO_GRAPHICSVIEW
    case VideoGraphicsObjectClass:
        return new VideoGraphicsObject(parent);
#endif
    case VideoWidgetClass:
        return new VideoWidget(qobject_cast<QWidget *>(parent));
//    case VolumeFaderEffectClass:
#warning VFE crashes and has volume bugs ... deactivated
//        return new VolumeFaderEffect(parent);
    }

    warning() << "Backend class" << c << "is not supported by Phonon VLC :(";
    return 0;
}

QStringList Backend::availableMimeTypes() const
{
    if (m_supportedMimeTypes.isEmpty())
        const_cast<Backend *>(this)->m_supportedMimeTypes = mimeTypeList();
    return m_supportedMimeTypes;
}

QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const<commit_msg>Add _GNU_ guarding defines are #warning<commit_after>/*
    Copyright (C) 2007-2008 <NAME> <<EMAIL>>
    Copyright (C) 2008 <NAME> <<EMAIL>>
    Copyright (C) 2009 <NAME> <<EMAIL>>
    Copyright (C) 2009-2011 vlc-phonon AUTHORS
    Copyright (C) 2011 <NAME> <<EMAIL>>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "backend.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QLatin1Literal>
#include <QtCore/QtPlugin>
#include <QtCore/QVariant>
#include <QMessageBox>

#include <phonon/GlobalDescriptionContainer>
#include <phonon/pulsesupport.h>

#include <vlc/libvlc_version.h>

#include "audio/audiooutput.h"
#include "audio/audiodataoutput.h"
#include "audio/volumefadereffect.h"
#include "devicemanager.h"
#include "effect.h"
#include "effectmanager.h"
#include "mediaobject.h"
#include "sinknode.h"
#include "utils/debug.h"
#include "utils/libvlc.h"
#include "utils/mime.h"
#ifdef PHONON_EXPERIMENTAL
#include "video/videodataoutput.h"
#endif
#ifndef PHONON_NO_GRAPHICSVIEW
#include "video/videographicsobject.h"
#endif
#include "video/videowidget.h"

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
Q_EXPORT_PLUGIN2(phonon_vlc, Phonon::VLC::Backend)
#endif

namespace Phonon
{
namespace VLC
{

Backend *Backend::self;

Backend::Backend(QObject *parent, const QVariantList &)
    : QObject(parent)
    , m_deviceManager(0)
    , m_effectManager(0)
{
    self = this;

    // Backend information properties
    setProperty("identifier",     QLatin1String("phonon_vlc"));
    setProperty("backendName",    QLatin1String("VLC"));
    setProperty("backendComment", QLatin1String("VLC backend for Phonon"));
    setProperty("backendVersion", QLatin1String(PHONON_VLC_VERSION));
    setProperty("backendIcon",    QLatin1String("vlc"));
    setProperty("backendWebsite", QLatin1String("https://projects.kde.org/projects/kdesupport/phonon/phonon-vlc"));

    // Check if we should enable debug output
    int debugLevel = qgetenv("PHONON_BACKEND_DEBUG").toInt();
    if (debugLevel > 3) // 3 is maximum
        debugLevel = 3;
    Debug::setMinimumDebugLevel((Debug::DebugLevel)((int) Debug::DEBUG_NONE - 1 - debugLevel));

    // Actual libVLC initialisation
    if (LibVLC::init()) {
        debug() << "Using VLC version" << libvlc_get_version();
        if (!QCoreApplication::applicationName().isEmpty()) {
            QString userAgent =
                    QString("%0/%1 (Phonon/%2; Phonon-VLC/%3)").arg(
                        QCoreApplication::applicationName(),
                        QCoreApplication::applicationVersion(),
                        PHONON_VERSION_STR,
                        PHONON_VLC_VERSION);
            libvlc_set_user_agent(libvlc,
                                  QCoreApplication::applicationName().toUtf8().constData(),
                                  userAgent.toUtf8().constData());
        } else {
            qWarning("WARNING: Setting the user agent for streaming and PulseAudio requires you to set QCoreApplication::applicationName()");
        }
    } else {
#ifdef __GNUC__
#warning TODO - this error message is about as useful as a cooling unit in the arctic
#endif
        QMessageBox msg;
        msg.setIcon(QMessageBox::Critical);
        msg.setWindowTitle(tr("LibVLC Failed to Initialize"));
        msg.setText(tr("Phonon's VLC backend failed to start."
                       "\n\n"
                       "This usually means a problem with your VLC installation,"
                       " please report a bug with your distributor."));
        msg.setDetailedText(LibVLC::errorMessage());
        msg.exec();
        fatal() << "Phonon::VLC::vlcInit: Failed to initialize VLC";
    }

    // Initialise PulseAudio support
    PulseSupport *pulse = PulseSupport::getInstance();
    pulse->enable();
    connect(pulse, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)),
            SIGNAL(objectDescriptionChanged(ObjectDescriptionType)));

    m_deviceManager = new DeviceManager(this);
    m_effectManager = new EffectManager(this);
}

Backend::~Backend()
{
    if (LibVLC::self)
        delete LibVLC::self;
    if (GlobalAudioChannels::self)
        delete GlobalAudioChannels::self;
    if (GlobalSubtitles::self)
        delete GlobalSubtitles::self;
    PulseSupport::shutdown();
}

QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &/*args*/)
{
    if (!LibVLC::self || !libvlc)
        return 0;

    switch (c) {
    case MediaObjectClass:
        return new MediaObject(parent);
    case AudioOutputClass:
        return new AudioOutput(parent);
#ifdef __GNUC__
#warning using sout in VLC2 breaks libvlcs vout functions, see vlc bug 6992
// https://trac.videolan.org/vlc/ticket/6992
#endif
#if (LIBVLC_VERSION_INT < LIBVLC_VERSION(2, 0, 0, 0))
    // FWIW: the case is inside the if because that gives clear indication which
    // frontend objects are not supported!
    case AudioDataOutputClass:
        return new AudioDataOutput(parent);
#endif
#ifdef PHONON_EXPERIMENTAL
    case VideoDataOutputClass:
        return new VideoDataOutput(parent);
#endif
#ifndef PHONON_NO_GRAPHICSVIEW
    case VideoGraphicsObjectClass:
        return new VideoGraphicsObject(parent);
#endif
    case VideoWidgetClass:
        return new VideoWidget(qobject_cast<QWidget *>(parent));
//    case VolumeFaderEffectClass:
#ifdef __GNUC__
#warning VFE crashes and has volume bugs ... deactivated
//        return new VolumeFaderEffect(parent);
#endif
    }

    warning() << "Backend class" << c << "is not supported by Phonon VLC :(";
    return 0;
}

QStringList Backend::availableMimeTypes() const
{
    if (m_supportedMimeTypes.isEmpty())
        const_cast<Backend *>(this)->m_supportedMimeTypes = mimeTypeList();
    return m_supportedMimeTypes;
}

QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
{'fraction_non_alphanumeric': 0.10880508015178503, 'fraction_numerical': 0.010532021993340045, 'mean_word_length': 3.454639530872715, 'pattern_counts': {'":': 0, '<': 81, '<?xml version=': 0, '>': 59, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3167525', 'n_tokens_mistral': 4008, 'n_tokens_neox': 3843, 'n_words': 1013}