diff options
Diffstat (limited to 'Common')
-rw-r--r-- | Common/Common.cpp | 361 | ||||
-rw-r--r-- | Common/Common.h | 46 | ||||
-rw-r--r-- | Common/CommonExport.h | 33 | ||||
-rw-r--r-- | Common/Config.cpp | 1983 | ||||
-rw-r--r-- | Common/Config.h | 463 | ||||
-rw-r--r-- | Common/Info.plist | 225 | ||||
-rw-r--r-- | Common/QOptions.cpp | 375 | ||||
-rw-r--r-- | Common/QOptions.h | 113 | ||||
-rwxr-xr-x | Common/QtQuick2ApplicationViewer.cpp | 104 | ||||
-rwxr-xr-x | Common/QtQuick2ApplicationViewer.h | 32 | ||||
-rw-r--r-- | Common/Viper.icns | bin | 0 -> 62464 bytes | |||
-rw-r--r-- | Common/ViperBuffer.cpp | 119 | ||||
-rw-r--r-- | Common/ViperBuffer.h | 51 |
13 files changed, 3905 insertions, 0 deletions
diff --git a/Common/Common.cpp b/Common/Common.cpp new file mode 100644 index 00000000..56600ebe --- /dev/null +++ b/Common/Common.cpp @@ -0,0 +1,361 @@ +/****************************************************************************** + QtAV Player Demo: this file is part of QtAV examples + Copyright (C) 2012-2017 Wang Bin <wbsecg1@gmail.com> +* This file is part of QtAV (from 2014) + 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 3 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, see <http://www.gnu.org/licenses/>. +******************************************************************************/ + +#include "Common.h" +#include <cstdio> +#include <cstdlib> +#include <QtCore/QSettings> +#include <QFileOpenEvent> +#include <QtCore/QLocale> +#include <QtCore/QTranslator> +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QTextStream> +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include <QtGui/QDesktopServices> +#else +#include <QtCore/QStandardPaths> +#endif +#include <QtDebug> + +#ifdef Q_OS_WINRT +#include <wrl.h> +#include <windows.foundation.h> +#include <windows.storage.pickers.h> +#include <Windows.ApplicationModel.activation.h> +#include <qfunctions_winrt.h> +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::ApplicationModel::Activation; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::Storage::Pickers; + +#define COM_LOG_COMPONENT "WinRT" +#define COM_ENSURE(f, ...) COM_CHECK(f, return __VA_ARGS__;) +#define COM_WARN(f) COM_CHECK(f) +#define COM_CHECK(f, ...) \ + do { \ + HRESULT hr = f; \ + if (FAILED(hr)) { \ + qWarning() << QString::fromLatin1(COM_LOG_COMPONENT " error@%1. " #f ": (0x%2) %3").arg(__LINE__).arg(hr, 0, 16).arg(qt_error_string(hr)); \ + __VA_ARGS__ \ + } \ + } while (0) + +QString UrlFromFileArgs(IInspectable *args) +{ + ComPtr<IFileActivatedEventArgs> fileArgs; + COM_ENSURE(args->QueryInterface(fileArgs.GetAddressOf()), QString()); + ComPtr<IVectorView<IStorageItem*>> files; + COM_ENSURE(fileArgs->get_Files(&files), QString()); + ComPtr<IStorageItem> item; + COM_ENSURE(files->GetAt(0, &item), QString()); + HString path; + COM_ENSURE(item->get_Path(path.GetAddressOf()), QString()); + + quint32 pathLen; + const wchar_t *pathStr = path.GetRawBuffer(&pathLen); + const QString filePath = QString::fromWCharArray(pathStr, pathLen); + qDebug() << "file path: " << filePath; + item->AddRef(); //ensure we can access it later. TODO: how to release? + return QString::fromLatin1("winrt:@%1:%2").arg((qint64)(qptrdiff)item.Get()).arg(filePath); +} +#endif + +Q_GLOBAL_STATIC(QFile, fileLogger) +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +class QMessageLogContext {}; +typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &); +QtMsgHandler qInstallMessageHandler(QtMessageHandler h) { + static QtMessageHandler hh; + hh = h; + struct MsgHandlerWrapper { + static void handler(QtMsgType type, const char *msg) { + static QMessageLogContext ctx; + hh(type, ctx, QString::fromUtf8(msg)); + } + }; + return qInstallMsgHandler(MsgHandlerWrapper::handler); +} +#endif +void Logger(QtMsgType type, const QMessageLogContext &, const QString& qmsg) +{ + const QByteArray msgArray = qmsg.toUtf8(); + const char* msg = msgArray.constData(); + switch (type) { + case QtDebugMsg: + printf("Debug: %s\n", msg); + fileLogger()->write(QByteArray("Debug: ")); + break; + case QtWarningMsg: + printf("Warning: %s\n", msg); + fileLogger()->write(QByteArray("Warning: ")); + break; + case QtCriticalMsg: + fprintf(stderr, "Critical: %s\n", msg); + fileLogger()->write(QByteArray("Critical: ")); + break; + case QtFatalMsg: + fprintf(stderr, "Fatal: %s\n", msg); + fileLogger()->write(QByteArray("Fatal: ")); + abort(); + } + fflush(0); + fileLogger()->write(msgArray); + fileLogger()->write(QByteArray("\n")); + fileLogger()->flush(); +} + +QOptions get_common_options() +{ + static QOptions ops = QOptions().addDescription(QString::fromLatin1("Options for QtAV players")) + .add(QString::fromLatin1("common options")) + ("help,h", QLatin1String("print this")) + ("ao", QString(), QLatin1String("audio output. Can be ordered combination of available backends (-ao help). Leave empty to use the default setting. Set 'null' to disable audio.")) + ("-egl", QLatin1String("Use EGL. Only works for Qt>=5.5+XCB")) + ("-gl", QLatin1String("OpenGL backend for Qt>=5.4(windows). can be 'desktop', 'opengles' and 'software'")) + ("x", 0, QString()) + ("y", 0, QLatin1String("y")) + ("-width", 800, QLatin1String("width of player")) + ("height", 450, QLatin1String("height of player")) + ("fullscreen", QLatin1String("fullscreen")) + ("decoder", QLatin1String("FFmpeg"), QLatin1String("use a given decoder")) + ("decoders,-vd", QLatin1String("cuda;vaapi;vda;dxva;cedarv;ffmpeg"), QLatin1String("decoder name list in priority order separated by ';'")) + ("file,f", QString(), QLatin1String("file or url to play")) + ("language", QString(), QLatin1String("language on UI. can be 'system' and locale name e.g. zh_CN")) + ("log", QString(), QLatin1String("log level. can be 'off', 'fatal', 'critical', 'warning', 'debug', 'all'")) + ("logfile" +#if defined(Q_OS_IOS) + , appDataDir().append(QString::fromLatin1("/log-%1.txt")) +#elif defined(Q_OS_WINRT) || defined(Q_OS_ANDROID) + , QString() +#else + , QString::fromLatin1("log-%1.txt") +#endif + , QString::fromLatin1("log to file. Set empty to disable log file (-logfile '')")) + ; + return ops; +} + +void do_common_options_before_qapp(const QOptions& options) +{ +#ifdef Q_OS_LINUX + QSettings cfg(Config::defaultConfigFile(), QSettings::IniFormat); + const bool set_egl = cfg.value("opengl/egl").toBool(); + //https://bugreports.qt.io/browse/QTBUG-49529 + // it's too late if qApp is created. but why ANGLE is not? + if (options.value(QString::fromLatin1("egl")).toBool() || set_egl) { //FIXME: Config is constructed too early because it requires qApp + // only apply to current run. no config change + qputenv("QT_XCB_GL_INTEGRATION", "xcb_egl"); + } else { + qputenv("QT_XCB_GL_INTEGRATION", "xcb_glx"); + } + qDebug() << "QT_XCB_GL_INTEGRATION: " << qgetenv("QT_XCB_GL_INTEGRATION"); +#endif //Q_OS_LINUX +} + +void do_common_options(const QOptions &options, const QString& appName) +{ + if (options.value(QString::fromLatin1("help")).toBool()) { + options.print(); + exit(0); + } + // has no effect if qInstallMessageHandler() called + //qSetMessagePattern("%{function} @%{line}: %{message}"); +#if !defined(Q_OS_WINRT) && !defined(Q_OS_ANDROID) + QString app(appName); + if (app.isEmpty() && qApp) + app = qApp->applicationName(); + QString logfile(options.option(QString::fromLatin1("logfile")).value().toString().arg(app)); + if (!logfile.isEmpty()) { + if (QDir(logfile).isRelative()) { + QString log_path(QString::fromLatin1("%1/%2").arg(qApp->applicationDirPath()).arg(logfile)); + QFile f(log_path); + if (!f.open(QIODevice::WriteOnly)) { + log_path = QString::fromLatin1("%1/%2").arg(appDataDir()).arg(logfile); + qDebug() << "executable dir is not writable. log to " << log_path; + } + logfile = log_path; + } + qDebug() << "set log file: " << logfile; + fileLogger()->setFileName(logfile); + if (fileLogger()->open(QIODevice::WriteOnly)) { + qDebug() << "Logger"; + qInstallMessageHandler(Logger); + } else { + qWarning() << "Failed to open log file '" << fileLogger()->fileName() << "': " << fileLogger()->errorString(); + } + } +#endif + QByteArray level(options.value(QString::fromLatin1("log")).toByteArray()); + if (level.isEmpty()) + level = Config::instance().logLevel().toLatin1(); + if (!level.isEmpty()) + qputenv("QTAV_LOG", level); +} + +void load_qm(const QStringList &names, const QString& lang) +{ + QString l(Config::instance().language()); + if (!lang.isEmpty()) + l = lang; + if (l.toLower() == QLatin1String("system")) + l = QLocale::system().name(); + QStringList qms(names); + qms << QLatin1String("QtAV") << QLatin1String("qt"); + foreach(QString qm, qms) { + QTranslator *ts = new QTranslator(qApp); + QString path = qApp->applicationDirPath() + QLatin1String("/i18n/") + qm + QLatin1String("_") + l; + //qDebug() << "loading qm: " << path; + if (ts->load(path)) { + qApp->installTranslator(ts); + } else { + path = QString::fromUtf8(":/i18n/%1_%2").arg(qm).arg(l); + //qDebug() << "loading qm: " << path; + if (ts->load(path)) + qApp->installTranslator(ts); + else + delete ts; + } + } + QTranslator qtts; + if (qtts.load(QLatin1String("qt_") + QLocale::system().name())) + qApp->installTranslator(&qtts); +} + +void set_opengl_backend(const QString& glopt, const QString &appname) +{ + QString gl = appname.toLower().replace(QLatin1String("\\"), QLatin1String("/")); + int idx = gl.lastIndexOf(QLatin1String("/")); + if (idx >= 0) + gl = gl.mid(idx + 1); + idx = gl.lastIndexOf(QLatin1String(".")); + if (idx > 0) + gl = gl.left(idx); + if (gl.indexOf(QLatin1String("-desktop")) > 0) + gl = QLatin1String("desktop"); + else if (gl.indexOf(QLatin1String("-es")) > 0 || gl.indexOf(QLatin1String("-angle")) > 0) + gl = gl.mid(gl.indexOf(QLatin1String("-es")) + 1); + else if (gl.indexOf(QLatin1String("-sw")) > 0 || gl.indexOf(QLatin1String("-software")) > 0) + gl = QLatin1String("software"); + else + gl = glopt.toLower(); + if (gl.isEmpty()) { + switch (Config::instance().openGLType()) { + case Config::Desktop: + gl = QLatin1String("desktop"); + break; + case Config::OpenGLES: + gl = QLatin1String("es"); + break; + case Config::Software: + gl = QLatin1String("software"); + break; + default: + break; + } + } + if (gl == QLatin1String("es") || gl == QLatin1String("angle") || gl == QLatin1String("opengles")) { + gl = QLatin1String("es_"); + gl.append(Config::instance().getANGLEPlatform().toLower()); + } +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + if (gl.startsWith(QLatin1String("es"))) { + qApp->setAttribute(Qt::AA_UseOpenGLES); +#ifdef QT_OPENGL_DYNAMIC + qputenv("QT_OPENGL", "angle"); +#endif +#ifdef Q_OS_WIN + if (gl.endsWith(QLatin1String("d3d11"))) + qputenv("QT_ANGLE_PLATFORM", "d3d11"); + else if (gl.endsWith(QLatin1String("d3d9"))) + qputenv("QT_ANGLE_PLATFORM", "d3d9"); + else if (gl.endsWith(QLatin1String("warp"))) + qputenv("QT_ANGLE_PLATFORM", "warp"); +#endif + } else if (gl == QLatin1String("desktop")) { + qApp->setAttribute(Qt::AA_UseDesktopOpenGL); + } else if (gl == QLatin1String("software")) { + qApp->setAttribute(Qt::AA_UseSoftwareOpenGL); + } +#endif +} + + +QString appDataDir() +{ +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + return QDesktopServices::storageLocation(QDesktopServices::DataLocation); +#else +#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) + return QStandardPaths::writableLocation(QStandardPaths::DataLocation); +#else + return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); +#endif //5.4.0 +#endif // 5.0.0 +} + +AppEventFilter::AppEventFilter(QObject *player, QObject *parent) + : QObject(parent) + , m_player(player) +{} + +bool AppEventFilter::eventFilter(QObject *obj, QEvent *ev) +{ + //qDebug() << __FUNCTION__ << " watcher: " << obj << ev; + if (obj != qApp) + return false; + if (ev->type() == QEvent::WinEventAct) { + // winrt file open/pick. since qt5.6.1 + qDebug("QEvent::WinEventAct"); +#ifdef Q_OS_WINRT + class QActivationEvent : public QEvent { + public: + void* args() const {return d;} //IInspectable* + }; + QActivationEvent *ae = static_cast<QActivationEvent*>(ev); + const QString url(UrlFromFileArgs((IInspectable*)ae->args())); + if (!url.isEmpty()) { + qDebug() << "winrt url: " << url; + if (m_player) + QMetaObject::invokeMethod(m_player, "play", Q_ARG(QUrl, QUrl(url))); + } + return true; +#endif + } + if (ev->type() != QEvent::FileOpen) + return false; + QFileOpenEvent *foe = static_cast<QFileOpenEvent*>(ev); + if (m_player) + QMetaObject::invokeMethod(m_player, "play", Q_ARG(QUrl, QUrl(foe->url()))); + return true; +} + +static void initResources() { + //Q_INIT_RESOURCE(theme); +} + +namespace { + struct ResourceLoader { + public: + ResourceLoader() { initResources(); } + } qrc; +} + + diff --git a/Common/Common.h b/Common/Common.h new file mode 100644 index 00000000..84991d8a --- /dev/null +++ b/Common/Common.h @@ -0,0 +1,46 @@ +/****************************************************************************** + QtAV Player Demo: this file is part of QtAV examples + Copyright (C) 2012-2017 Wang Bin <wbsecg1@gmail.com> +* This file is part of QtAV (from 2014) + 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 3 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, see <http://www.gnu.org/licenses/>. +******************************************************************************/ + +#ifndef COMMON_H +#define COMMON_H +#include <QtCore/QObject> +#include <QtCore/QStringList> +#include <QtCore/QUrl> +#include "QOptions.h" +#include "Config.h" + +QOptions COMMON_EXPORT get_common_options(); +void COMMON_EXPORT do_common_options_before_qapp(const QOptions& options); +/// help, log file, ffmpeg log level +void COMMON_EXPORT do_common_options(const QOptions& options, const QString& appName = QString()); +void COMMON_EXPORT load_qm(const QStringList& names, const QString &lang = QLatin1String("system")); +// if appname ends with 'desktop', 'es', 'angle', software', 'sw', set by appname. otherwise set by command line option glopt, or Config file +// TODO: move to do_common_options_before_qapp +void COMMON_EXPORT set_opengl_backend(const QString& glopt = QString::fromLatin1("auto"), const QString& appname = QString()); + +QString COMMON_EXPORT appDataDir(); + +class COMMON_EXPORT AppEventFilter : public QObject +{ +public: + AppEventFilter(QObject *player = 0, QObject* parent = 0); + QUrl url() const; + virtual bool eventFilter(QObject *obj, QEvent *ev); +private: + QObject *m_player; +}; + +#endif // COMMON_H diff --git a/Common/CommonExport.h b/Common/CommonExport.h new file mode 100644 index 00000000..0307a079 --- /dev/null +++ b/Common/CommonExport.h @@ -0,0 +1,33 @@ +/****************************************************************************** + QtAV Player Demo: this file is part of QtAV examples + Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com> +* This file is part of QtAV (from 2014) + 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 3 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, see <http://www.gnu.org/licenses/>. +******************************************************************************/ + +#ifndef COMMON_EXPORT_H +#define COMMON_EXPORT_H + +#include <QtCore/qglobal.h> + +#ifdef BUILD_COMMON_STATIC +#define COMMON_EXPORT +#else +#if defined(BUILD_COMMON_LIB) +# undef COMMON_EXPORT +# define COMMON_EXPORT Q_DECL_EXPORT +#else +# undef COMMON_EXPORT +# define COMMON_EXPORT //Q_DECL_IMPORT //only for vc? link to static lib error +#endif +#endif //BUILD_COMMON_STATIC +#endif // COMMON_EXPORT_H diff --git a/Common/Config.cpp b/Common/Config.cpp new file mode 100644 index 00000000..04d999c5 --- /dev/null +++ b/Common/Config.cpp @@ -0,0 +1,1983 @@ +/****************************************************************************** + QtAV Player Demo: this file is part of QtAV examples + Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com> +* This file is part of QtAV (from 2014) + 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 3 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, see <http://www.gnu.org/licenses/>. +******************************************************************************/ + +#include "Config.h" +#include <QtCore/QSettings> +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QMetaEnum> +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +#include <QtGui/QDesktopServices> +#else +#include <QtCore/QStandardPaths> +#endif +#include <QtSql/QSqlDatabase> +#include <QtSql/QSqlQuery> +#include <QtDebug> +#include "Common.h" + +class Config::Data +{ +public: + Data() { + is_loading = false; + if (!Data::name.isEmpty()) { + //this->configPath = appDataDir(); + file = appDataDir() + QString::fromLatin1("/") + Data::name + QString::fromLatin1(".ini"); + } else { + //this->configPath = appDataDir() + QString::fromLatin1("/") + qApp->applicationName(); + file = appDataDir() + QString::fromLatin1("/") + qApp->applicationName() + QString::fromLatin1(".ini"); + } + if (!QDir(appDataDir()).exists()) { + if (!QDir().mkpath(appDataDir())) { + qWarning() << "Failed to create appDataDir: " << appDataDir(); + } + } + + moveOldCfg(); + } + + void moveOldCfg() { + // for old config data migration + QString dir_old = qApp->applicationDirPath() + QString::fromLatin1("/data"); + if (!QDir(dir_old).exists()) { + dir_old = QDir::homePath() + QString::fromLatin1("/.QtAV"); + } + if (QDir(dir_old).exists()) { + if (!QFile(file).exists()) { + QString old = dir_old + QString::fromLatin1("/") + qApp->applicationName() + QString::fromLatin1(".ini"); + if (QFile(old).exists()) { + QFile::copy(old, file); + QFile::remove(old); + } + old = dir_old + QString::fromLatin1("/playlist.qds"); + if (QFile(old).exists()) { + if (!QFile::copy(old, appDataDir() + QString::fromLatin1("/playlist.qds"))) + qWarning("error to move old playlist data"); + QFile::remove(old); + } + old = dir_old + QString::fromLatin1("/history.qds"); + if (QFile(old).exists()) { + if (!QFile::copy(old, appDataDir() + QString::fromLatin1("/history.qds"))) + qWarning("error to move old history data"); + QFile::remove(old); + } + } + } + } + + void save() { + if (is_loading) + return; + qDebug() << "sync config to " << file; + QSettings settings(file, QSettings::IniFormat); + // TODO: why crash on mac qt5.4 if call on aboutToQuit() + settings.setValue(QString::fromLatin1("log"), log); + settings.setValue(QString::fromLatin1("language"), lang); + settings.setValue(QString::fromLatin1("last_file"), last_file); + settings.setValue(QString::fromLatin1("timeout"), timeout); + settings.setValue(QString::fromLatin1("abort_timeout"), abort_timeout); + settings.setValue(QString::fromLatin1("force_fps"), force_fps); + settings.beginGroup(QString::fromLatin1("decoder")); + settings.beginGroup(QString::fromLatin1("video")); + settings.setValue(QString::fromLatin1("priority"), video_decoders.join(QString::fromLatin1(" "))); + settings.endGroup(); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("capture")); + settings.setValue(QString::fromLatin1("zeroCopy"), zero_copy); + settings.setValue(QString::fromLatin1("dir"), capture_dir); + settings.setValue(QString::fromLatin1("format"), capture_fmt); + settings.setValue(QString::fromLatin1("quality"), capture_quality); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("subtitle")); + settings.setValue(QString::fromLatin1("enabled"), subtitle_enabled); + settings.setValue(QString::fromLatin1("autoLoad"), subtitle_autoload); + settings.setValue(QString::fromLatin1("engines"), subtitle_engines); + settings.setValue(QString::fromLatin1("delay"), subtitle_delay); + settings.setValue(QString::fromLatin1("font"), subtitle_font); + settings.setValue(QString::fromLatin1("color"), subtitle_color); + settings.setValue(QString::fromLatin1("outline_color"), subtitle_outline_color); + settings.setValue(QString::fromLatin1("outline"), subtitle_outline); + settings.setValue(QString::fromLatin1("bottom margin"), subtilte_bottom_margin); + settings.beginGroup(QString::fromLatin1("ass")); + settings.setValue(QString::fromLatin1("font_file"), ass_font_file); + settings.setValue(QString::fromLatin1("force_font_file"), ass_force_font_file); + settings.setValue(QString::fromLatin1("fonts_dir"), ass_fonts_dir); + settings.endGroup(); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("preview")); + settings.setValue(QString::fromLatin1("enabled"), preview_enabled); + settings.setValue(QString::fromLatin1("width"), preview_w); + settings.setValue(QString::fromLatin1("height"), preview_h); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("avformat")); + settings.setValue(QString::fromLatin1("enable"), avformat_on); + settings.setValue(QString::fromLatin1("avioflags"), direct ? QString::fromLatin1("direct") : QString::fromLatin1("0")); + settings.setValue(QString::fromLatin1("probesize"), probe_size); + settings.setValue(QString::fromLatin1("analyzeduration"), analyze_duration); + settings.setValue(QString::fromLatin1("extra"), avformat_extra); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("avfilterVideo")); + settings.setValue(QString::fromLatin1("enable"), avfilterVideo_on); + settings.setValue(QString::fromLatin1("options"), avfilterVideo); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("avfilterAudio")); + settings.setValue(QString::fromLatin1("enable"), avfilterAudio_on); + settings.setValue(QString::fromLatin1("options"), avfilterAudio); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("opengl")); + settings.setValue(QString::fromLatin1("egl"), egl); + const char* glname = Config::staticMetaObject.enumerator(Config::staticMetaObject.indexOfEnumerator("OpenGLType")).valueToKey(opengl); + settings.setValue(QString::fromLatin1("type"), QString::fromLatin1(glname)); + settings.setValue(QString::fromLatin1("angle_platform"), angle_dx); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("shader")); + settings.setValue(QString::fromLatin1("enable"), user_shader); + settings.setValue(QString::fromLatin1("fbo"), fbo); + settings.setValue(QString::fromLatin1("fragHeader"), frag_header); + settings.setValue(QString::fromLatin1("fragSample"), frag_sample); + settings.setValue(QString::fromLatin1("fragPostProcess"), frag_pp); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("buffer")); + settings.setValue(QString::fromLatin1("value"), buffer_value); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("backend")); + settings.setValue(QString::fromLatin1("icn_prefix"), icn_prefix); + settings.setValue(QString::fromLatin1("http_prefix"), http_prefix); + settings.setValue(QString::fromLatin1("icn_suffix"), icn_suffix); + settings.setValue(QString::fromLatin1("http_suffix"), http_suffix); + settings.setValue(QString::fromLatin1("segment_buffer_size"), segment_buffer_size); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("playback")); + settings.setValue(QString::fromLatin1("last_played"), last_played); + settings.setValue(QString::fromLatin1("adaptation_logic"), adaptation_logic); + settings.setValue(QString::fromLatin1("icn"), icn); + settings.endGroup(); + + + settings.beginGroup(QString::fromLatin1("rate_conf")); + settings.setValue(QString::fromLatin1("rate_alpha"), rate_alpha); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("buffer_rate_based_conf")); + settings.setValue(QString::fromLatin1("adaptech_first_threshold"), adaptech_first_threshold); + settings.setValue(QString::fromLatin1("adaptech_second_threshold"), adaptech_second_threshold); + settings.setValue(QString::fromLatin1("adaptech_switch_up_margin"), adaptech_switch_up_margin); + settings.setValue(QString::fromLatin1("adaptech_slack_parameter"), adaptech_slack_parameter); + settings.setValue(QString::fromLatin1("adaptech_alpha"), adaptech_alpha); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("buffer_three_threshold_conf")); + settings.setValue(QString::fromLatin1("buffer_3Threshold_first"), buffer_3Threshold_first); + settings.setValue(QString::fromLatin1("buffer_3Threshold_second"), buffer_3Threshold_second); + settings.setValue(QString::fromLatin1("buffer_3Threshold_third"), buffer_3Threshold_third); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("panda_conf")); + settings.setValue(QString::fromLatin1("panda_param_alpha"), panda_param_alpha); + settings.setValue(QString::fromLatin1("panda_param_beta"), panda_param_beta); + settings.setValue(QString::fromLatin1("panda_param_Bmin"), panda_param_Bmin); + settings.setValue(QString::fromLatin1("panda_param_K"), panda_param_K); + settings.setValue(QString::fromLatin1("panda_param_W"), panda_param_W); + settings.setValue(QString::fromLatin1("panda_param_epsilon"), panda_param_epsilon); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("bola_conf")); + settings.setValue(QString::fromLatin1("bola_buffer_target"), bola_buffer_target); + settings.setValue(QString::fromLatin1("bola_alpha"), bola_alpha); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("status_conf")); + settings.setValue(QString::fromLatin1("repeat"), repeat); + settings.setValue(QString::fromLatin1("graph"), graph); + settings.setValue(QString::fromLatin1("full_screen"), full_screen); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("consumer_conf")); + settings.setValue(QString::fromLatin1("autotune"), autotune); + settings.setValue(QString::fromLatin1("lifetime"), lifetime); + settings.setValue(QString::fromLatin1("retrasmisisons"), retransmissions); + settings.setValue(QString::fromLatin1("alpha"), alpha); + settings.setValue(QString::fromLatin1("beta"), beta); + settings.setValue(QString::fromLatin1("drop"), drop); + settings.setValue(QString::fromLatin1("beta_wifi"), beta_wifi); + settings.setValue(QString::fromLatin1("drop_wifi"), drop_wifi); + settings.setValue(QString::fromLatin1("delay_wifi"), delay_wifi); + settings.setValue(QString::fromLatin1("beta_lte"), beta_lte); + settings.setValue(QString::fromLatin1("drop_lte"), drop_lte); + settings.setValue(QString::fromLatin1("delay_lte"), delay_lte); + settings.setValue(QString::fromLatin1("batching_parameter"), batching_parameter); + settings.setValue(QString::fromLatin1("rate_estimator"), rate_estimator); + settings.endGroup(); + + + qDebug() << "sync end"; + } + + QString file; + bool is_loading; + + qreal force_fps; + QStringList video_decoders; + bool zero_copy; + + QString last_file; + + QString capture_dir; + QString capture_fmt; + int capture_quality; + + bool avformat_on; + bool direct; + unsigned int probe_size; + int analyze_duration; + QString avformat_extra; + bool avfilterVideo_on; + QString avfilterVideo; + bool avfilterAudio_on; + QString avfilterAudio; + + QStringList subtitle_engines; + bool subtitle_autoload; + bool subtitle_enabled; + QFont subtitle_font; + QColor subtitle_color, subtitle_outline_color; + bool subtitle_outline; + int subtilte_bottom_margin; + qreal subtitle_delay; + + bool ass_force_font_file; + QString ass_font_file; + QString ass_fonts_dir; + + bool preview_enabled; + int preview_w, preview_h; + + bool egl; + Config::OpenGLType opengl; + QString angle_dx; + bool abort_timeout; + qreal timeout; + int buffer_value; + QString log; + QString lang; + + QVariantList history; + + bool user_shader; + bool fbo; + QString frag_header; + QString frag_sample; + QString frag_pp; + QString icn_prefix; + QString http_prefix; + QString icn_suffix; + QString http_suffix; + qreal segment_buffer_size; + QString last_played; + QString adaptation_logic; + bool icn; + qreal rate_alpha; + qreal buffer_reservoir_threshold; + qreal buffer_max_threshold; + qreal adaptech_first_threshold; + qreal adaptech_second_threshold; + qreal adaptech_switch_up_margin; + qreal adaptech_slack_parameter; + qreal adaptech_alpha; + qreal buffer_3Threshold_first; + qreal buffer_3Threshold_second; + qreal buffer_3Threshold_third; + qreal panda_param_alpha; + qreal panda_param_beta; + qreal panda_param_Bmin; + qreal panda_param_K; + qreal panda_param_W; + qreal panda_param_epsilon; + qreal bola_buffer_target; + qreal bola_alpha; + bool repeat; + bool graph; + bool full_screen; + bool autotune; + int lifetime; + int retransmissions; + qreal alpha; + qreal beta; + qreal drop; + qreal beta_wifi; + qreal drop_wifi; + int delay_wifi; + qreal beta_lte; + qreal drop_lte; + int delay_lte; + int batching_parameter; + int rate_estimator; + static QString name; +}; + +QString Config::Data::name; + +Config& Config::instance() +{ + static Config cfg; + return cfg; +} + +void Config::setName(const QString &name) +{ + Config::Data::name = name; +} + +QString Config::getName() +{ + return Config::Data::name; +} + +QString Config::defaultConfigFile() +{ + return appDataDir() + QString::fromLatin1("/") + Data::name + QString::fromLatin1(".ini");; +} + +Config::Config(QObject *parent) + : QObject(parent) + , mpData(new Data()) +{ + // DO NOT call save() in dtor because it's a singleton and may be deleted later than qApp, QFont is not valid + connect(qApp, SIGNAL(aboutToQuit()), SLOT(save())); //FIXME: what if qapp not ready + reload(); +} + +Config::~Config() +{ + delete mpData; +} + +QString Config::defaultDir() +{ + return appDataDir(); +} + +bool Config::reset() +{ + QFile cf(mpData->file); + if (!cf.remove()) { + qWarning() << "Failed to remove config file: " << cf.errorString(); + return false; + } + reload(); + save(); + return true; +} + +void Config::reload() +{ + QSqlDatabase db(QSqlDatabase::database()); + if (!db.isOpen()) { + db = QSqlDatabase::addDatabase(QString::fromUtf8("QSQLITE")); + db.setDatabaseName(appDataDir().append(QString("/%1.db").arg(mpData->name))); + if (!db.open()) + qWarning("error open db"); + db.exec("CREATE TABLE IF NOT EXISTS history (url TEXT primary key, start BIGINT, duration BIGINT)"); + } + QSqlQuery query(db.exec(QString::fromUtf8("SELECT * FROM history"))); + while (query.next()) { + QVariantMap var; + var[QString::fromUtf8("url")] = query.value(0).toString(); + var[QString::fromUtf8("start")] = query.value(1).toLongLong(); + var[QString::fromUtf8("duration")] = query.value(2).toLongLong(); + mpData->history.append(var); + } + mpData->is_loading = true; + QSettings settings(mpData->file, QSettings::IniFormat); + setLogLevel(settings.value(QString::fromLatin1("log"), QString()).toString()); + setLanguage(settings.value(QString::fromLatin1("language"), +#if QT_VERSION == QT_VERSION_CHECK(5, 6, 0) && defined(Q_OS_WINPHONE) //qt bug + QString::fromLatin1("en_US") +#else + QString::fromLatin1("system") +#endif + ).toString()); + setLastFile(settings.value(QString::fromLatin1("last_file"), QString()).toString()); + setTimeout(settings.value(QString::fromLatin1("timeout"), 30.0).toReal()); + setAbortOnTimeout(settings.value(QString::fromLatin1("abort_timeout"), true).toBool()); + setForceFrameRate(settings.value(QString::fromLatin1("force_fps"), 0.0).toReal()); + settings.beginGroup(QString::fromLatin1("decoder")); + settings.beginGroup(QString::fromLatin1("video")); + QString decs_default(QString::fromLatin1("FFmpeg")); + setDecoderPriorityNames(settings.value(QString::fromLatin1("priority"), decs_default).toString().split(QString::fromLatin1(" "), QString::SkipEmptyParts)); + setZeroCopy(settings.value(QString::fromLatin1("zeroCopy"), true).toBool()); + settings.endGroup(); //video + settings.endGroup(); //decoder + + settings.beginGroup(QString::fromLatin1("capture")); + setCaptureDir(settings.value(QString::fromLatin1("dir"), QString()).toString()); + if (captureDir().isEmpty()) { +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + setCaptureDir(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); +#else + setCaptureDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); +#endif + } + setCaptureFormat(settings.value(QString::fromLatin1("format"), QString::fromLatin1("png")).toString()); + setCaptureQuality(settings.value(QString::fromLatin1("quality"), 100).toInt()); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("subtitle")); + setSubtitleAutoLoad(settings.value(QString::fromLatin1("autoLoad"), true).toBool()); + setSubtitleEnabled(settings.value(QString::fromLatin1("enabled"), true).toBool()); + setSubtitleEngines(settings.value(QString::fromLatin1("engines"), QStringList() << QString::fromLatin1("FFmpeg") << QString::fromLatin1("LibASS")).toStringList()); + setSubtitleDelay(settings.value(QString::fromLatin1("delay"), 0.0).toInt()); + QFont f; + f.setPointSize(20); + f.setBold(true); + setSubtitleFont(settings.value(QString::fromLatin1("font"), f).value<QFont>()); + setSubtitleColor(settings.value(QString::fromLatin1("color"), QColor("white")).value<QColor>()); + setSubtitleOutlineColor(settings.value(QString::fromLatin1("outline_color"), QColor("blue")).value<QColor>()); + setSubtitleOutline(settings.value(QString::fromLatin1("outline"), true).toBool()); + setSubtitleBottomMargin(settings.value(QString::fromLatin1("bottom margin"), 8).toInt()); + settings.beginGroup(QString::fromLatin1("ass")); + setAssFontFile(settings.value(QString::fromLatin1("font_file"), QString()).toString()); + setAssFontFileForced(settings.value(QString::fromLatin1("force_font_file"), false).toBool()); + setAssFontsDir(settings.value(QString::fromLatin1("fonts_dir"), QString()).toString()); + settings.endGroup(); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("preview")); + setPreviewEnabled(settings.value(QString::fromLatin1("enabled"), true).toBool()); + setPreviewWidth(settings.value(QString::fromLatin1("width"), 160).toInt()); + setPreviewHeight(settings.value(QString::fromLatin1("height"), 90).toInt()); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("avformat")); + setAvformatOptionsEnabled(settings.value(QString::fromLatin1("enable"), false).toBool()); + reduceBuffering(settings.value(QString::fromLatin1("avioflags"), 0).toString() == QLatin1String("direct")); + probeSize(settings.value(QString::fromLatin1("probesize"), 5000000).toUInt()); + analyzeDuration(settings.value(QString::fromLatin1("analyzeduration"), 5000000).toInt()); + avformatExtra(settings.value(QString::fromLatin1("extra"), QString()).toString()); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("avfilterVideo")); + avfilterVideoEnable(settings.value(QString::fromLatin1("enable"), true).toBool()); + avfilterVideoOptions(settings.value(QString::fromLatin1("options"), QString()).toString()); + settings.endGroup(); + settings.beginGroup(QString::fromLatin1("avfilterAudio")); + avfilterAudioEnable(settings.value(QString::fromLatin1("enable"), true).toBool()); + avfilterAudioOptions(settings.value(QString::fromLatin1("options"), QString()).toString()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("opengl")); + setEGL(settings.value(QString::fromLatin1("egl"), false).toBool()); + const QString glname = settings.value(QString::fromLatin1("type"), QString::fromLatin1("OpenGLES")).toString(); + setOpenGLType((Config::OpenGLType)Config::staticMetaObject.enumerator(Config::staticMetaObject.indexOfEnumerator("OpenGLType")).keysToValue(glname.toLatin1().constData())); + // d3d11 bad performance (gltexsubimage2d) + setANGLEPlatform(settings.value(QString::fromLatin1("angle_platform"), QString::fromLatin1("d3d9")).toString()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("shader")); + setUserShaderEnabled(settings.value(QString::fromLatin1("enable"), false).toBool()); + setIntermediateFBO(settings.value(QString::fromLatin1("fbo"), false).toBool()); + setFragHeader(settings.value(QString::fromLatin1("fragHeader"), QString()).toString()); + setFragSample(settings.value(QString::fromLatin1("fragSample"), QString::fromLatin1("// horizontal mirror effect\n" + "vec4 sample2d(sampler2D tex, vec2 pos, int p) {\n" + " return texture(tex, vec2(1.0-pos.x, pos.y));\n" + "}")).toString()); + setFragPostProcess(settings.value(QString::fromLatin1("fragPostProcess"), QString::fromLatin1("//negate color effect\n" + "gl_FragColor.rgb = vec3(1.0-gl_FragColor.r, 1.0-gl_FragColor.g, 1.0-gl_FragColor.b);")).toString()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("buffer")); + setBufferValue(settings.value(QString::fromLatin1("value"), -1).toInt()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("rate_conf")); + setRateAlpha(settings.value(QString::fromLatin1("rate_alpha"), 0.8).toReal()); + settings.endGroup(); + + + settings.beginGroup(QString::fromLatin1("buffer_based_conf")); + setBufferReservoirThreshold(settings.value(QString::fromLatin1("buffer_reservoir_threshold"), 20).toReal()); + setBufferMaxThreshold(settings.value(QString::fromLatin1("buffer_max_threshold"), 80).toReal()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("buffer_rate_based_conf")); + setAdaptechFirstThreshold(settings.value(QString::fromLatin1("adaptech_first_threshold"), 30).toReal()); + setAdaptechSecondThreshold(settings.value(QString::fromLatin1("adaptech_second_threshold"), 70).toReal()); + setAdaptechSwitchUpMargin(settings.value(QString::fromLatin1("adaptech_switch_up_margin"), 5).toReal()); + setAdaptechSlackParameter(settings.value(QString::fromLatin1("adaptech_slack_parameter"), 0.8).toReal()); + setAdaptechAlpha(settings.value(QString::fromLatin1("adaptech_alpha"), 0.8).toReal()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("buffer_three_threshold_conf")); + setBufferThreeThresholdFirst(settings.value(QString::fromLatin1("buffer_3Threshold_first"), 15).toReal()); + setBufferThreeThresholdSecond(settings.value(QString::fromLatin1("buffer_3Threshold_second"), 35).toReal()); + setBufferThreeThresholdThird(settings.value(QString::fromLatin1("buffer_3Threshold_third"), 75).toReal()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("backend")); + setIcnPrefix(settings.value(QString::fromLatin1("icn_prefix"), QString::fromLatin1("ccnx:/webserver/get/")).toString()); + setHttpPrefix(settings.value(QString::fromLatin1("http_prefix"), QString::fromLatin1("http://10.60.17.153:8080/")).toString()); + setIcnSuffix(settings.value(QString::fromLatin1("icn_suffix"), QString::fromLatin1("/mpd")).toString()); + setHttpSuffix(settings.value(QString::fromLatin1("http_suffix"), QString::fromLatin1("/mpd")).toString()); + + setSegmentBufferSize(settings.value(QString::fromLatin1("segment_buffer_size"), 20).toReal()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("playback")); + setLastPlayed(settings.value(QString::fromLatin1("last_played"), QString::fromLatin1("sintel")).toString()); + setAdaptationLogic(settings.value(QString::fromLatin1("adaptation_logic"), QString::fromLatin1("Buffer Based")).toString()); + setIcn(settings.value(QString::fromLatin1("icn"), true).toBool()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("panda_conf")); + setPandaParamAlpha(settings.value(QString::fromLatin1("panda_param_alpha"), 0.4).toReal()); + setPandaParamBeta(settings.value(QString::fromLatin1("panda_param_beta"), 0.6).toReal()); + setPandaParamBMin(settings.value(QString::fromLatin1("panda_param_Bmin"), 67).toReal()); + setPandaParamK(settings.value(QString::fromLatin1("panda_param_K"), 0.5).toReal()); + setPandaParamW(settings.value(QString::fromLatin1("panda_param_W"), 270000).toReal()); + setPandaParamEpsilon(settings.value(QString::fromLatin1("panda_param_epsilon"), 0.19).toReal()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("bola_conf")); + setBolaBufferTarget(settings.value(QString::fromLatin1("bola_buffer_target"), 23).toReal()); + setBolaAlpha(settings.value(QString::fromLatin1("bola_alpha"), 0.8).toReal()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("status_conf")); + setRepeat(settings.value(QString::fromLatin1("repeat"), false).toBool()); + setGraph(settings.value(QString::fromLatin1("graph"), false).toBool()); + setFullScreen(settings.value(QString::fromLatin1("full_screen"), false).toBool()); + settings.endGroup(); + + settings.beginGroup(QString::fromLatin1("consumer_conf")); + setAutotune(settings.value(QString::fromLatin1("autotune"), false).toBool()); + setLifetime(settings.value(QString::fromLatin1("lifetime"), 500).toInt()); + setRetransmissions(settings.value(QString::fromLatin1("retrasmisisons"), 128).toInt()); + setAlpha(settings.value(QString::fromLatin1("alpha"), 0.95).toReal()); + setBeta(settings.value(QString::fromLatin1("beta"), 0.99).toReal()); + setDrop(settings.value(QString::fromLatin1("drop"), 0.003).toReal()); + setBetaWifi(settings.value(QString::fromLatin1("beta_wifi"), 0.99).toReal()); + setDropWifi(settings.value(QString::fromLatin1("drop_wifi"), 0.6).toReal()); + setDelayWifi(settings.value(QString::fromLatin1("delay_wifi"), 200).toInt()); + setBetaLte(settings.value(QString::fromLatin1("beta_lte"), 0.99).toReal()); + setDropLte(settings.value(QString::fromLatin1("drop_lte"), 0.003).toReal()); + setDelayLte(settings.value(QString::fromLatin1("delay_lte"), 9000).toInt()); + setBatchingParameter(settings.value(QString::fromLatin1("batching_parameter"), 200).toInt()); + setRateEstimator(settings.value(QString::fromLatin1("rate_estimator"), 0).toInt()); + settings.endGroup(); + mpData->is_loading = false; +} + +qreal Config::forceFrameRate() const +{ + return mpData->force_fps; +} + +Config& Config::setForceFrameRate(qreal value) +{ + if (mpData->force_fps == value) + return *this; + mpData->force_fps = value; + Q_EMIT forceFrameRateChanged(); + Q_EMIT changed(); + return *this; +} + +QStringList Config::decoderPriorityNames() const +{ + return mpData->video_decoders; +} + +Config& Config::setDecoderPriorityNames(const QStringList &value) +{ + if (mpData->video_decoders == value) { + qDebug("decoderPriority not changed"); + return *this; + } + mpData->video_decoders = value; + Q_EMIT decoderPriorityNamesChanged(); + Q_EMIT changed(); + mpData->save(); + return *this; +} + +bool Config::zeroCopy() const +{ + return mpData->zero_copy; +} + +Config& Config::setZeroCopy(bool value) +{ + if (mpData->zero_copy == value) + return *this; + mpData->zero_copy = value; + Q_EMIT zeroCopyChanged(); + Q_EMIT changed(); + mpData->save(); + return *this; +} + +QString Config::captureDir() const +{ + return mpData->capture_dir; +} + +Config& Config::setCaptureDir(const QString& dir) +{ + if (mpData->capture_dir == dir) + return *this; + mpData->capture_dir = dir; + Q_EMIT captureDirChanged(dir); + Q_EMIT changed(); + return *this; +} + +QString Config::captureFormat() const +{ + return mpData->capture_fmt; +} + +Config& Config::setCaptureFormat(const QString& format) +{ + if (mpData->capture_fmt == format) + return *this; + mpData->capture_fmt = format; + Q_EMIT captureFormatChanged(format); + Q_EMIT changed(); + return *this; +} + +// only works for non-yuv capture +int Config::captureQuality() const +{ + return mpData->capture_quality; +} + +Config& Config::setCaptureQuality(int quality) +{ + if (mpData->capture_quality == quality) + return *this; + mpData->capture_quality = quality; + Q_EMIT captureQualityChanged(quality); + Q_EMIT changed(); + return *this; +} + +QStringList Config::subtitleEngines() const +{ + return mpData->subtitle_engines; +} + +Config& Config::setSubtitleEngines(const QStringList &value) +{ + if (mpData->subtitle_engines == value) + return *this; + mpData->subtitle_engines = value; + Q_EMIT subtitleEnginesChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::subtitleAutoLoad() const +{ + return mpData->subtitle_autoload; +} + +Config& Config::setSubtitleAutoLoad(bool value) +{ + if (mpData->subtitle_autoload == value) + return *this; + mpData->subtitle_autoload = value; + Q_EMIT subtitleAutoLoadChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::subtitleEnabled() const +{ + return mpData->subtitle_enabled; +} + +Config& Config::setSubtitleEnabled(bool value) +{ + if (mpData->subtitle_enabled == value) + return *this; + mpData->subtitle_enabled = value; + Q_EMIT subtitleEnabledChanged(); + Q_EMIT changed(); + return *this; +} + +QFont Config::subtitleFont() const +{ + return mpData->subtitle_font; +} + +Config& Config::setSubtitleFont(const QFont& value) +{ + if (mpData->subtitle_font == value) + return *this; + mpData->subtitle_font = value; + Q_EMIT subtitleFontChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::subtitleOutline() const +{ + return mpData->subtitle_outline; +} +Config& Config::setSubtitleOutline(bool value) +{ + if (mpData->subtitle_outline == value) + return *this; + mpData->subtitle_outline = value; + Q_EMIT subtitleOutlineChanged(); + Q_EMIT changed(); + return *this; +} + +QColor Config::subtitleColor() const +{ + return mpData->subtitle_color; +} + +Config& Config::setSubtitleColor(const QColor& value) +{ + if (mpData->subtitle_color == value) + return *this; + mpData->subtitle_color = value; + Q_EMIT subtitleColorChanged(); + Q_EMIT changed(); + return *this; +} + +QColor Config::subtitleOutlineColor() const +{ + return mpData->subtitle_outline_color; +} +Config& Config::setSubtitleOutlineColor(const QColor& value) +{ + if (mpData->subtitle_outline_color == value) + return *this; + mpData->subtitle_outline_color = value; + Q_EMIT subtitleOutlineColorChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::subtitleBottomMargin() const +{ + return mpData->subtilte_bottom_margin; +} + +Config& Config::setSubtitleBottomMargin(int value) +{ + if (mpData->subtilte_bottom_margin == value) + return *this; + mpData->subtilte_bottom_margin = value; + Q_EMIT subtitleBottomMarginChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::subtitleDelay() const +{ + return mpData->subtitle_delay; +} + +Config& Config::setSubtitleDelay(qreal value) +{ + if (mpData->subtitle_delay == value) + return *this; + mpData->subtitle_delay = value; + Q_EMIT subtitleDelayChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::assFontFile() const +{ + return mpData->ass_font_file; +} + +Config& Config::setAssFontFile(const QString &value) +{ + if (mpData->ass_font_file == value) + return *this; + mpData->ass_font_file = value; + Q_EMIT assFontFileChanged(); + Q_EMIT changed(); + return *this; +} + + +QString Config::assFontsDir() const +{ + return mpData->ass_fonts_dir; +} + +Config& Config::setAssFontsDir(const QString &value) +{ + if (mpData->ass_fonts_dir == value) + return *this; + mpData->ass_fonts_dir = value; + Q_EMIT assFontsDirChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::isAssFontFileForced() const +{ + return mpData->ass_force_font_file; +} + +Config& Config::setAssFontFileForced(bool value) +{ + if (mpData->ass_force_font_file == value) + return *this; + mpData->ass_force_font_file = value; + Q_EMIT assFontFileForcedChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::previewEnabled() const +{ + return mpData->preview_enabled; +} + +Config& Config::setPreviewEnabled(bool value) +{ + if (mpData->preview_enabled == value) + return *this; + mpData->preview_enabled = value; + Q_EMIT previewEnabledChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::previewWidth() const +{ + return mpData->preview_w; +} + +Config& Config::setPreviewWidth(int value) +{ + if (mpData->preview_w == value) + return *this; + mpData->preview_w = value; + Q_EMIT previewWidthChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::previewHeight() const +{ + return mpData->preview_h; +} + +Config& Config::setPreviewHeight(int value) +{ + if (mpData->preview_h == value) + return *this; + mpData->preview_h = value; + Q_EMIT previewHeightChanged(); + Q_EMIT changed(); + return *this; +} +QVariantHash Config::avformatOptions() const +{ + QVariantHash vh; + if (!mpData->avformat_extra.isEmpty()) { + QStringList s(mpData->avformat_extra.split(QString::fromLatin1(" "))); + for (int i = 0; i < s.size(); ++i) { + int eq = s[i].indexOf(QLatin1String("=")); + if (eq < 0) { + continue; + } else { + vh[s[i].mid(0, eq)] = s[i].mid(eq+1); + } + } + } + if (mpData->probe_size > 0) { + vh[QString::fromLatin1("probesize")] = mpData->probe_size; + } + if (mpData->analyze_duration) { + vh[QString::fromLatin1("analyzeduration")] = mpData->analyze_duration; + } + if (mpData->direct) { + vh[QString::fromLatin1("avioflags")] = QString::fromLatin1("direct"); + }; + return vh; +} + +bool Config::avformatOptionsEnabled() const +{ + return mpData->avformat_on; +} + +Config& Config::setAvformatOptionsEnabled(bool value) +{ + if (mpData->avformat_on == value) + return *this; + mpData->avformat_on = value; + Q_EMIT avformatOptionsEnabledChanged(); + Q_EMIT changed(); + return *this; +} + +unsigned int Config::probeSize() const +{ + return mpData->probe_size; +} + +Config& Config::probeSize(unsigned int ps) +{ + mpData->probe_size = ps; + return *this; +} + +int Config::analyzeDuration() const +{ + return mpData->analyze_duration; +} + +Config& Config::analyzeDuration(int ad) +{ + mpData->analyze_duration = ad; + return *this; +} + +bool Config::reduceBuffering() const +{ + return mpData->direct; +} + +Config& Config::reduceBuffering(bool y) +{ + mpData->direct = y; + return *this; +} + +QString Config::avformatExtra() const +{ + return mpData->avformat_extra; +} + +Config& Config::avformatExtra(const QString &text) +{ + mpData->avformat_extra = text; + return *this; +} + +QString Config::avfilterVideoOptions() const +{ + return mpData->avfilterVideo; +} + +Config& Config::avfilterVideoOptions(const QString& options) +{ + if (mpData->avfilterVideo == options) + return *this; + mpData->avfilterVideo = options; + Q_EMIT avfilterVideoChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::avfilterVideoEnable() const +{ + return mpData->avfilterVideo_on; +} + +Config& Config::avfilterVideoEnable(bool e) +{ + if (mpData->avfilterVideo_on == e) + return *this; + mpData->avfilterVideo_on = e; + Q_EMIT avfilterVideoChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::avfilterAudioOptions() const +{ + return mpData->avfilterAudio; +} + +Config& Config::avfilterAudioOptions(const QString& options) +{ + if (mpData->avfilterAudio == options) + return *this; + mpData->avfilterAudio = options; + Q_EMIT avfilterAudioChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::avfilterAudioEnable() const +{ + return mpData->avfilterAudio_on; +} + +Config& Config::avfilterAudioEnable(bool e) +{ + if (mpData->avfilterAudio_on == e) + return *this; + mpData->avfilterAudio_on = e; + Q_EMIT avfilterAudioChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::isEGL() const +{ + return mpData->egl; +} + +Config& Config::setEGL(bool value) +{ + if (mpData->egl == value) + return *this; + mpData->egl = value; + Q_EMIT EGLChanged(); + Q_EMIT changed(); + return *this; +} + +Config::OpenGLType Config::openGLType() const +{ + return mpData->opengl; +} + +Config& Config::setOpenGLType(OpenGLType value) +{ + if (mpData->opengl == value) + return *this; + mpData->opengl = value; + Q_EMIT openGLTypeChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::getANGLEPlatform() const +{ + return mpData->angle_dx; +} + +Config& Config::setANGLEPlatform(const QString& value) +{ + if (mpData->angle_dx == value) + return *this; + mpData->angle_dx = value; + Q_EMIT ANGLEPlatformChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::userShaderEnabled() const +{ + return mpData->user_shader; +} + +Config& Config::setUserShaderEnabled(bool value) +{ + if (mpData->user_shader == value) + return *this; + mpData->user_shader = value; + Q_EMIT userShaderEnabledChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::intermediateFBO() const +{ + return mpData->fbo; +} + +Config& Config::setIntermediateFBO(bool value) +{ + if (mpData->fbo == value) + return *this; + mpData->fbo = value; + Q_EMIT intermediateFBOChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::fragHeader() const +{ + return mpData->frag_header; +} + +Config& Config::setFragHeader(const QString &text) +{ + if (mpData->frag_header == text) + return *this; + mpData->frag_header = text; + Q_EMIT fragHeaderChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::fragSample() const +{ + return mpData->frag_sample; +} + +Config& Config::setFragSample(const QString &text) +{ + if (mpData->frag_sample == text) + return *this; + mpData->frag_sample = text; + Q_EMIT fragSampleChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::fragPostProcess() const +{ + return mpData->frag_pp; +} + +Config& Config::setFragPostProcess(const QString &text) +{ + if (mpData->frag_pp == text) + return *this; + mpData->frag_pp = text; + Q_EMIT fragPostProcessChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::bufferValue() const +{ + return mpData->buffer_value; +} + +Config& Config::setBufferValue(int value) +{ + if (mpData->buffer_value == value) + return *this; + mpData->buffer_value = value; + Q_EMIT bufferValueChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::timeout() const +{ + return mpData->timeout; +} + +Config& Config::setTimeout(qreal value) +{ + if (mpData->timeout == value) + return *this; + mpData->timeout = value; + Q_EMIT timeoutChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::logLevel() const +{ + return mpData->log; +} + +Config& Config::setLogLevel(const QString& value) +{ + if (mpData->log == value.toLower()) + return *this; + mpData->log = value.toLower(); + Q_EMIT logLevelChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::language() const +{ + return mpData->lang; +} + +Config& Config::setLanguage(const QString& value) +{ + if (mpData->lang == value) + return *this; + mpData->lang = value; + Q_EMIT languageChanged(); + Q_EMIT changed(); + return *this; +} + +QVariantList Config::history() const +{ + return mpData->history; +} + +void Config::addHistory(const QVariantMap &value) +{ + mpData->history.prepend(value); + Q_EMIT historyChanged(); + QSqlDatabase db = QSqlDatabase::database(); + QSqlQuery query(db); + if (!query.prepare(QString::fromUtf8("INSERT INTO history (url, start, duration) " + "VALUES (:url, :start, :duration)"))) { + qWarning("error prepare sql query"); + } + query.bindValue(QString::fromUtf8(":url"), value.value("url").toString()); + query.bindValue(QString::fromUtf8(":start"), value.value("start").toLongLong()); + query.bindValue(QString::fromUtf8(":duration"), value.value("duration").toLongLong()); + if (!query.exec()) + qWarning("failed to add history: %d", db.isOpen()); +} + +void Config::removeHistory(const QString &url) +{ + QVariantList::Iterator it = mpData->history.begin(); + bool change = false; + while (it != mpData->history.end()) { + if (it->toMap().value("url") != url) { + ++it; + continue; + } + it = mpData->history.erase(it); + change = true; + } + if (!change) + return; + Q_EMIT historyChanged(); + QSqlDatabase db = QSqlDatabase::database(); + QSqlQuery query(db); + query.prepare(QString::fromUtf8("DELETE FROM history WHERE url = :url")); + query.bindValue(QString::fromUtf8(":url"), url); + if (!query.exec()) + qWarning("failed to remove history"); +} + +void Config::clearHistory() +{ + if (mpData->history.isEmpty()) + return; + mpData->history.clear(); + Q_EMIT historyChanged(); + QSqlDatabase db = QSqlDatabase::database(); + QSqlQuery query(db); + query.prepare(QString::fromUtf8("DELETE FROM history")); + // 'TRUNCATE table history' is faster + if (!query.exec()) + qWarning("failed to clear history"); +} + +bool Config::abortOnTimeout() const +{ + return mpData->abort_timeout; +} + +Config& Config::setAbortOnTimeout(bool value) +{ + if (mpData->abort_timeout == value) + return *this; + mpData->abort_timeout = value; + Q_EMIT abortOnTimeoutChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::icnPrefix() const +{ + return mpData->icn_prefix; +} + +Config& Config::setIcnPrefix(const QString &text) +{ + if (mpData->icn_prefix == text) + return *this; + mpData->icn_prefix = text; + Q_EMIT icnPrefixChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::icnSuffix() const +{ + return mpData->icn_suffix; +} + +Config& Config::setIcnSuffix(const QString &text) +{ + if (mpData->icn_suffix == text) + return *this; + mpData->icn_suffix = text; + Q_EMIT icnSuffixChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::httpPrefix() const +{ + return mpData->http_prefix; +} + +Config& Config::setHttpPrefix(const QString &text) +{ + if (mpData->http_prefix == text) + return *this; + mpData->http_prefix = text; + Q_EMIT httpPrefixChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::httpSuffix() const +{ + return mpData->http_suffix; +} + +Config& Config::setHttpSuffix(const QString &text) +{ + if (mpData->http_suffix == text) + return *this; + mpData->http_suffix = text; + Q_EMIT httpSuffixChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::segmentBufferSize() const +{ + return mpData->segment_buffer_size; +} + +Config& Config::setSegmentBufferSize(qreal value) +{ + if (mpData->segment_buffer_size == value) + return *this; + mpData->segment_buffer_size = value; + Q_EMIT segmentBufferSizeChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::lastPlayed() const +{ + return mpData->last_played; +} + +Config& Config::setLastPlayed(const QString &text) +{ + if (mpData->last_played == text) + return *this; + mpData->last_played = text; + Q_EMIT lastPlayedChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::adaptationLogic() const +{ + return mpData->adaptation_logic; +} + +Config& Config::setAdaptationLogic(const QString &text) +{ + if (mpData->adaptation_logic == text) + return *this; + mpData->adaptation_logic = text; + Q_EMIT adaptationLogicChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::rateAlpha() const +{ + return mpData->rate_alpha; +} + +Config& Config::setRateAlpha(qreal value) +{ + if (mpData->rate_alpha == value) + return *this; + mpData->rate_alpha = value; + Q_EMIT rateAlphaChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::bufferReservoirThreshold() const +{ + return mpData->buffer_reservoir_threshold; +} + +bool Config::icn() const +{ + return mpData->icn; +} + +Config& Config::setIcn(bool value) +{ + if (mpData->icn == value) + return *this; + mpData->icn = value; + Q_EMIT icnChanged(); + Q_EMIT changed(); + return *this; +} + +Config& Config::setBufferReservoirThreshold(qreal value) +{ + if (mpData->buffer_reservoir_threshold == value) + return *this; + mpData->buffer_reservoir_threshold = value; + Q_EMIT bufferReservoirThresholdChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::bufferMaxThreshold() const +{ + return mpData->buffer_max_threshold; +} + +Config& Config::setBufferMaxThreshold(qreal value) +{ + if (mpData->buffer_max_threshold == value) + return *this; + mpData->buffer_max_threshold = value; + Q_EMIT bufferMaxThresholdChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::adaptechFirstThreshold() const +{ + return mpData->adaptech_first_threshold; +} + +Config& Config::setAdaptechFirstThreshold(qreal value) +{ + if (mpData->adaptech_first_threshold == value) + return *this; + mpData->adaptech_first_threshold = value; + Q_EMIT adaptechFirstThresholdChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::adaptechSecondThreshold() const +{ + return mpData->adaptech_second_threshold; +} + +Config& Config::setAdaptechSecondThreshold(qreal value) +{ + if (mpData->adaptech_second_threshold == value) + return *this; + mpData->adaptech_second_threshold = value; + Q_EMIT adaptechSecondThresholdChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::adaptechSwitchUpMargin() const +{ + return mpData->adaptech_switch_up_margin; +} + +Config& Config::setAdaptechSwitchUpMargin(qreal value) +{ + if (mpData->adaptech_switch_up_margin == value) + return *this; + mpData->adaptech_switch_up_margin = value; + Q_EMIT adaptechSwitchUpMarginChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::adaptechSlackParameter() const +{ + return mpData->adaptech_slack_parameter; +} + +Config& Config::setAdaptechSlackParameter(qreal value) +{ + if (mpData->adaptech_slack_parameter == value) + return *this; + mpData->adaptech_slack_parameter = value; + Q_EMIT adaptechSlackParameterChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::adaptechAlpha() const +{ + return mpData->adaptech_alpha; +} + +Config& Config::setAdaptechAlpha(qreal value) +{ + if (mpData->adaptech_alpha == value) + return *this; + mpData->adaptech_alpha = value; + Q_EMIT adaptechAlphaChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::bufferThreeThresholdFirst() const +{ + return mpData->buffer_3Threshold_first; +} + +Config& Config::setBufferThreeThresholdFirst(qreal value) +{ + if (mpData->buffer_3Threshold_first == value) + return *this; + mpData->buffer_3Threshold_first = value; + Q_EMIT bufferThreeThresholdFirstChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::bufferThreeThresholdSecond() const +{ + return mpData->buffer_3Threshold_second; +} + +Config& Config::setBufferThreeThresholdSecond(qreal value) +{ + if (mpData->buffer_3Threshold_second == value) + return *this; + mpData->buffer_3Threshold_second = value; + Q_EMIT bufferThreeThresholdSecondChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::bufferThreeThresholdThird() const +{ + return mpData->buffer_3Threshold_third; +} + +Config& Config::setBufferThreeThresholdThird(qreal value) +{ + if (mpData->buffer_3Threshold_third == value) + return *this; + mpData->buffer_3Threshold_third = value; + Q_EMIT bufferThreeThresholdThirdChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::pandaParamAlpha() const +{ + return mpData->panda_param_alpha; +} + +Config& Config::setPandaParamAlpha(qreal value) +{ + if (mpData->panda_param_alpha == value) + return *this; + mpData->panda_param_alpha = value; + Q_EMIT pandaParamAlphaChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::pandaParamBeta() const +{ + return mpData->panda_param_beta; +} + +Config& Config::setPandaParamBeta(qreal value) +{ + if (mpData->panda_param_beta == value) + return *this; + mpData->panda_param_beta = value; + Q_EMIT pandaParamBetaChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::pandaParamBMin() const +{ + return mpData->panda_param_Bmin; +} + +Config& Config::setPandaParamBMin(qreal value) +{ + if (mpData->panda_param_Bmin == value) + return *this; + mpData->panda_param_Bmin = value; + Q_EMIT pandaParamBMinChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::pandaParamK() const +{ + return mpData->panda_param_K; +} + +Config& Config::setPandaParamK(qreal value) +{ + if (mpData->panda_param_K == value) + return *this; + mpData->panda_param_K = value; + Q_EMIT pandaParamKChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::pandaParamW() const +{ + return mpData->panda_param_W; +} + +Config& Config::setPandaParamW(qreal value) +{ + if (mpData->panda_param_W == value) + return *this; + mpData->panda_param_W = value; + Q_EMIT pandaParamWChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::pandaParamEpsilon() const +{ + return mpData->panda_param_epsilon; +} + +Config& Config::setPandaParamEpsilon(qreal value) +{ + if (mpData->panda_param_epsilon == value) + return *this; + mpData->panda_param_epsilon = value; + Q_EMIT pandaParamEpsilon(); + Q_EMIT changed(); + return *this; +} + +qreal Config::bolaBufferTarget() const +{ + return mpData->bola_buffer_target; +} + +Config& Config::setBolaBufferTarget(qreal value) +{ + if (mpData->bola_buffer_target == value) + return *this; + mpData->bola_buffer_target = value; + Q_EMIT bolaBufferTargetChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::bolaAlpha() const +{ + return mpData->bola_alpha; +} + +Config& Config::setBolaAlpha(qreal value) +{ + if (mpData->bola_alpha == value) + return *this; + mpData->bola_alpha = value; + Q_EMIT bolaAlphaChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::repeat() const +{ + return mpData->repeat; +} + +Config& Config::setRepeat(bool value) +{ + if (mpData->repeat == value) + return *this; + mpData->repeat = value; + Q_EMIT repeatChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::graph() const +{ + return mpData->graph; +} + +Config& Config::setGraph(bool value) +{ + if (mpData->graph == value) + return *this; + mpData->graph = value; + Q_EMIT graphChanged(); + Q_EMIT changed(); + return *this; +} + +bool Config::fullScreen() const +{ + return mpData->full_screen; +} + +Config& Config::setFullScreen(bool value) +{ + if (mpData->full_screen == value) + return *this; + mpData->full_screen = value; + Q_EMIT fullScreenChanged(); + Q_EMIT changed(); + return *this; +} + +QString Config::lastFile() const +{ + return mpData->last_file; +} + +Config& Config::setLastFile(const QString &value) +{ + if (mpData->last_file == value) + return *this; + mpData->last_file = value; + Q_EMIT lastFileChanged(); + Q_EMIT changed(); + return *this; +} + +void Config::save() +{ + mpData->save(); +} + +QString Config::getConfigPath() { + return appDataDir(); +} + +bool Config::autotune() const +{ + return mpData->autotune; +} + +Config& Config::setAutotune(bool value) +{ + if (mpData->autotune == value) + return *this; + mpData->autotune = value; + Q_EMIT autotuneChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::lifetime() const +{ + return mpData->lifetime; +} + +Config& Config::setLifetime(int value) +{ + if (mpData->lifetime == value) + return *this; + mpData->lifetime = value; + Q_EMIT lifetimeChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::retransmissions() const +{ + return mpData->retransmissions; +} + +Config& Config::setRetransmissions(int value) +{ + if (mpData->retransmissions == value) + return *this; + mpData->retransmissions = value; + Q_EMIT retransmissionsChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::alpha() const +{ + return mpData->alpha; +} + +Config& Config::setAlpha(qreal value) +{ + if (mpData->alpha == value) + return *this; + mpData->alpha = value; + Q_EMIT alphaChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::beta() const +{ + return mpData->beta; +} + +Config& Config::setBeta(qreal value) +{ + if (mpData->beta == value) + return *this; + mpData->beta = value; + Q_EMIT betaChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::drop() const +{ + return mpData->drop; +} + +Config& Config::setDrop(qreal value) +{ + if (mpData->drop == value) + return *this; + mpData->drop = value; + Q_EMIT dropChanged(); + Q_EMIT changed(); + return *this; +} + + +qreal Config::betaWifi() const +{ + return mpData->beta_wifi; +} + +Config& Config::setBetaWifi(qreal value) +{ + if (mpData->beta_wifi == value) + return *this; + mpData->beta_wifi = value; + Q_EMIT betaWifiChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::dropWifi() const +{ + return mpData->drop_wifi; +} + +Config& Config::setDropWifi(qreal value) +{ + if (mpData->drop_wifi == value) + return *this; + mpData->drop_wifi = value; + Q_EMIT dropWifiChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::delayWifi() const +{ + return mpData->delay_wifi; +} + +Config& Config::setDelayWifi(int value) +{ + if (mpData->delay_wifi == value) + return *this; + mpData->delay_wifi = value; + Q_EMIT delayWifiChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::betaLte() const +{ + return mpData->beta_lte; +} + +Config& Config::setBetaLte(qreal value) +{ + if (mpData->beta_lte == value) + return *this; + mpData->beta_lte = value; + Q_EMIT betaLteChanged(); + Q_EMIT changed(); + return *this; +} + +qreal Config::dropLte() const +{ + return mpData->drop_lte; +} + +Config& Config::setDropLte(qreal value) +{ + if (mpData->drop_lte == value) + return *this; + mpData->drop_lte = value; + Q_EMIT dropLteChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::delayLte() const +{ + return mpData->delay_lte; +} + +Config& Config::setDelayLte(int value) +{ + if (mpData->delay_lte == value) + return *this; + mpData->delay_lte = value; + Q_EMIT delayLteChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::batchingParameter() const +{ + return mpData->batching_parameter; +} + +Config& Config::setBatchingParameter(int value) +{ + if (mpData->batching_parameter == value) + return *this; + mpData->batching_parameter = value; + Q_EMIT batchingParameterChanged(); + Q_EMIT changed(); + return *this; +} + +int Config::rateEstimator() const +{ + return mpData->rate_estimator; +} + +Config& Config::setRateEstimator(int value) +{ + if (mpData->rate_estimator == value) + return *this; + mpData->rate_estimator = value; + Q_EMIT rateEstimatorChanged(); + Q_EMIT changed(); + return *this; +} diff --git a/Common/Config.h b/Common/Config.h new file mode 100644 index 00000000..018b757f --- /dev/null +++ b/Common/Config.h @@ -0,0 +1,463 @@ +/****************************************************************************** + QtAV Player Demo: this file is part of QtAV examples + Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com> +* This file is part of QtAV (from 2014) + 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 3 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, see <http://www.gnu.org/licenses/>. +******************************************************************************/ + +#ifndef PLAYER_CONFIG_H +#define PLAYER_CONFIG_H + +#include "CommonExport.h" +#include <QtCore/QObject> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtGui/QColor> +#include <QtGui/QFont> + + +class COMMON_EXPORT Config : public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariantList history READ history NOTIFY historyChanged) + // last file opened by file dialog + Q_PROPERTY(QString lastFile READ lastFile WRITE setLastFile NOTIFY lastFileChanged) + Q_PROPERTY(qreal forceFrameRate READ forceFrameRate WRITE setForceFrameRate NOTIFY forceFrameRateChanged) + Q_PROPERTY(QStringList decoderPriorityNames READ decoderPriorityNames WRITE setDecoderPriorityNames NOTIFY decoderPriorityNamesChanged) + Q_PROPERTY(bool zeroCopy READ zeroCopy WRITE setZeroCopy NOTIFY zeroCopyChanged) + Q_PROPERTY(QString captureDir READ captureDir WRITE setCaptureDir NOTIFY captureDirChanged) + Q_PROPERTY(QString captureFormat READ captureFormat WRITE setCaptureFormat NOTIFY captureFormatChanged) + Q_PROPERTY(int captureQuality READ captureQuality WRITE setCaptureQuality NOTIFY captureQualityChanged) + Q_PROPERTY(QStringList subtitleEngines READ subtitleEngines WRITE setSubtitleEngines NOTIFY subtitleEnginesChanged) + Q_PROPERTY(bool subtitleAutoLoad READ subtitleAutoLoad WRITE setSubtitleAutoLoad NOTIFY subtitleAutoLoadChanged) + Q_PROPERTY(bool subtitleEnabled READ subtitleEnabled WRITE setSubtitleEnabled NOTIFY subtitleEnabledChanged) + Q_PROPERTY(QFont subtitleFont READ subtitleFont WRITE setSubtitleFont NOTIFY subtitleFontChanged) + Q_PROPERTY(QColor subtitleColor READ subtitleColor WRITE setSubtitleColor NOTIFY subtitleColorChanged) + Q_PROPERTY(QColor subtitleOutlineColor READ subtitleOutlineColor WRITE setSubtitleOutlineColor NOTIFY subtitleOutlineColorChanged) + Q_PROPERTY(bool subtitleOutline READ subtitleOutline WRITE setSubtitleOutline NOTIFY subtitleOutlineChanged) + Q_PROPERTY(int subtitleBottomMargin READ subtitleBottomMargin WRITE setSubtitleBottomMargin NOTIFY subtitleBottomMarginChanged) + Q_PROPERTY(qreal subtitleDelay READ subtitleDelay WRITE setSubtitleDelay NOTIFY subtitleDelayChanged) + // font properties for libass engine + Q_PROPERTY(QString assFontFile READ assFontFile WRITE setAssFontFile NOTIFY assFontFileChanged) + Q_PROPERTY(QString assFontsDir READ assFontsDir WRITE setAssFontsDir NOTIFY assFontsDirChanged) + Q_PROPERTY(bool assFontFileForced READ isAssFontFileForced WRITE setAssFontFileForced NOTIFY assFontFileForcedChanged) + + Q_PROPERTY(bool previewEnabled READ previewEnabled WRITE setPreviewEnabled NOTIFY previewEnabledChanged) + Q_PROPERTY(int previewWidth READ previewWidth WRITE setPreviewWidth NOTIFY previewWidthChanged) + Q_PROPERTY(int previewHeight READ previewHeight WRITE setPreviewHeight NOTIFY previewHeightChanged) + Q_PROPERTY(bool EGL READ isEGL WRITE setEGL NOTIFY EGLChanged) + Q_PROPERTY(OpenGLType openGLType READ openGLType WRITE setOpenGLType NOTIFY openGLTypeChanged) + Q_PROPERTY(QString ANGLEPlatform READ getANGLEPlatform WRITE setANGLEPlatform NOTIFY ANGLEPlatformChanged) + Q_PROPERTY(bool avformatOptionsEnabled READ avformatOptionsEnabled WRITE setAvformatOptionsEnabled NOTIFY avformatOptionsEnabledChanged) + Q_PROPERTY(qreal timeout READ timeout WRITE setTimeout NOTIFY timeoutChanged) + Q_PROPERTY(int bufferValue READ bufferValue WRITE setBufferValue NOTIFY bufferValueChanged) + Q_PROPERTY(QString logLevel READ logLevel WRITE setLogLevel NOTIFY logLevelChanged) + Q_ENUMS(OpenGLType) + Q_PROPERTY(QString language READ language WRITE setLanguage NOTIFY languageChanged) + + Q_PROPERTY(bool userShaderEnabled READ userShaderEnabled WRITE setUserShaderEnabled NOTIFY userShaderEnabledChanged) + Q_PROPERTY(bool intermediateFBO READ intermediateFBO WRITE setIntermediateFBO NOTIFY intermediateFBOChanged) + Q_PROPERTY(QString fragHeader READ fragHeader WRITE setFragHeader NOTIFY fragHeaderChanged) + Q_PROPERTY(QString fragSample READ fragSample WRITE setFragSample NOTIFY fragSampleChanged) + Q_PROPERTY(QString fragPostProcess READ fragPostProcess WRITE setFragPostProcess NOTIFY fragPostProcessChanged) + Q_PROPERTY(QString icnPrefix READ icnPrefix WRITE setIcnPrefix NOTIFY icnPrefixChanged) + Q_PROPERTY(QString httpPrefix READ httpPrefix WRITE setHttpPrefix NOTIFY httpPrefixChanged) + Q_PROPERTY(QString icnSuffix READ icnSuffix WRITE setIcnSuffix NOTIFY icnSuffixChanged) + Q_PROPERTY(QString httpSuffix READ httpSuffix WRITE setHttpSuffix NOTIFY httpSuffixChanged) + + Q_PROPERTY(qreal segmentBufferSize READ segmentBufferSize WRITE setSegmentBufferSize NOTIFY segmentBufferSizeChanged) + Q_PROPERTY(QString lastPlayed READ lastPlayed WRITE setLastPlayed NOTIFY lastPlayedChanged) + Q_PROPERTY(QString adaptationLogic READ adaptationLogic WRITE setAdaptationLogic NOTIFY adaptationLogicChanged) + Q_PROPERTY(bool icn READ icn WRITE setIcn NOTIFY icnChanged) + Q_PROPERTY(qreal rateAlpha READ rateAlpha WRITE setRateAlpha NOTIFY rateAlphaChanged) + Q_PROPERTY(qreal bufferReservoirThreshold READ bufferReservoirThreshold WRITE setBufferReservoirThreshold NOTIFY bufferReservoirThresholdChanged) + Q_PROPERTY(qreal bufferMaxThreshold READ bufferMaxThreshold WRITE setBufferMaxThreshold NOTIFY bufferMaxThresholdChanged) + Q_PROPERTY(qreal adaptechFirstThreshold READ adaptechFirstThreshold WRITE setAdaptechFirstThreshold NOTIFY adaptechFirstThresholdChanged) + Q_PROPERTY(qreal adaptechSecondThreshold READ adaptechSecondThreshold WRITE setAdaptechSecondThreshold NOTIFY adaptechSecondThresholdChanged) + Q_PROPERTY(qreal adaptechSwitchUpMargin READ adaptechSwitchUpMargin WRITE setAdaptechSwitchUpMargin NOTIFY adaptechSwitchUpMarginChanged) + Q_PROPERTY(qreal adaptechSlackParameter READ adaptechSlackParameter WRITE setAdaptechSlackParameter NOTIFY adaptechSlackParameterChanged) + Q_PROPERTY(qreal adaptechAlpha READ adaptechAlpha WRITE setAdaptechAlpha NOTIFY adaptechAlphaChanged) + Q_PROPERTY(qreal bufferThreeThresholdFirst READ bufferThreeThresholdFirst WRITE setBufferThreeThresholdFirst NOTIFY bufferThreeThresholdFirstChanged) + Q_PROPERTY(qreal bufferThreeThresholdSecond READ bufferThreeThresholdSecond WRITE setBufferThreeThresholdSecond NOTIFY bufferThreeThresholdSecondChanged) + Q_PROPERTY(qreal bufferThreeThresholdThird READ bufferThreeThresholdThird WRITE setBufferThreeThresholdThird NOTIFY bufferThreeThresholdThirdChanged) + Q_PROPERTY(qreal pandaParamAlpha READ pandaParamAlpha WRITE setPandaParamAlpha NOTIFY pandaParamAlphaChanged) + Q_PROPERTY(qreal pandaParamBeta READ pandaParamBeta WRITE setPandaParamBeta NOTIFY pandaParamBetaChanged) + Q_PROPERTY(qreal pandaParamBMin READ pandaParamBMin WRITE setPandaParamBMin NOTIFY pandaParamBMinChanged) + Q_PROPERTY(qreal pandaParamK READ pandaParamK WRITE setPandaParamK NOTIFY pandaParamKChanged) + Q_PROPERTY(qreal pandaParamW READ pandaParamW WRITE setPandaParamW NOTIFY pandaParamWChanged) + Q_PROPERTY(qreal pandaParamEpsilon READ pandaParamEpsilon WRITE setPandaParamAlpha NOTIFY pandaParamEpsilonChanged) + Q_PROPERTY(qreal bolaBufferTarget READ bolaBufferTarget WRITE setBolaBufferTarget NOTIFY bolaBufferTargetChanged) + Q_PROPERTY(qreal bolaAlpha READ bolaAlpha WRITE setBolaAlpha NOTIFY bolaAlphaChanged) + Q_PROPERTY(bool repeat READ repeat WRITE setRepeat NOTIFY repeatChanged) + Q_PROPERTY(bool graph READ graph WRITE setGraph NOTIFY graphChanged) + Q_PROPERTY(bool fullScreen READ fullScreen WRITE setFullScreen NOTIFY fullScreenChanged) + Q_PROPERTY(bool autotune READ autotune WRITE setAutotune NOTIFY autotuneChanged) + Q_PROPERTY(int lifetime READ lifetime WRITE setLifetime NOTIFY lifetimeChanged) + Q_PROPERTY(int retransmissions READ retransmissions WRITE setRetransmissions NOTIFY retransmissionsChanged) + Q_PROPERTY(qreal alpha READ alpha WRITE setAlpha NOTIFY alphaChanged) + Q_PROPERTY(qreal beta READ beta WRITE setBeta NOTIFY betaChanged) + Q_PROPERTY(qreal drop READ drop WRITE setDrop NOTIFY dropChanged) + Q_PROPERTY(qreal betaWifi READ betaWifi WRITE setBetaWifi NOTIFY betaWifiChanged) + Q_PROPERTY(qreal dropWifi READ dropWifi WRITE setDropWifi NOTIFY dropWifiChanged) + Q_PROPERTY(int delayWifi READ delayWifi WRITE setDelayWifi NOTIFY delayWifiChanged) + Q_PROPERTY(qreal betaLte READ betaLte WRITE setBetaLte NOTIFY betaLteChanged) + Q_PROPERTY(qreal dropLte READ dropLte WRITE setDropLte NOTIFY dropLteChanged) + Q_PROPERTY(int delayLte READ delayLte WRITE setDelayLte NOTIFY delayLteChanged) + Q_PROPERTY(int batchingParameter READ batchingParameter WRITE setBatchingParameter NOTIFY batchingParameterChanged) + Q_PROPERTY(int rateEstimator READ rateEstimator WRITE setRateEstimator NOTIFY rateEstimatorChanged) + +public: + enum OpenGLType { // currently only for windows + Auto, + Desktop, + OpenGLES, + Software + }; + + static Config& instance(); + static void setName(const QString& name); // config file base name + static QString getName(); + /*! + * \brief defaultConfigFile + * Config file name is $appname.ini. Must call Config::setName() first + */ + static QString defaultConfigFile(); + static QString defaultDir(); + Q_INVOKABLE bool reset(); + void reload(); + //void loadFromFile(const QString& file); + QString getConfigPath(); + QString lastFile() const; + Config& setLastFile(const QString& value); + + qreal forceFrameRate() const; + Config& setForceFrameRate(qreal value); + // in priority order. the same order as displayed in ui + QStringList decoderPriorityNames() const; + Config& setDecoderPriorityNames(const QStringList& names); + + bool zeroCopy() const; + Config& setZeroCopy(bool value); + + QString captureDir() const; + Config& setCaptureDir(const QString& dir); + + /*! + * \brief captureFormat + * can be "yuv" to capture yuv image without convertion. the suffix is the yuv format, e.g. "yuv420p", "nv12" + * or can be "jpg", "png" + * \return + */ + QString captureFormat() const; + Config& setCaptureFormat(const QString& format); + // only works for non-yuv capture. value: -1~100, -1: default + int captureQuality() const; + Config& setCaptureQuality(int quality); + + QStringList subtitleEngines() const; + Config& setSubtitleEngines(const QStringList& value); + bool subtitleAutoLoad() const; + Config& setSubtitleAutoLoad(bool value); + bool subtitleEnabled() const; + Config& setSubtitleEnabled(bool value); + + QFont subtitleFont() const; + Config& setSubtitleFont(const QFont& value); + bool subtitleOutline() const; + Config& setSubtitleOutline(bool value); + QColor subtitleColor() const; + Config& setSubtitleColor(const QColor& value); + QColor subtitleOutlineColor() const; + Config& setSubtitleOutlineColor(const QColor& value); + int subtitleBottomMargin() const; + Config& setSubtitleBottomMargin(int value); + + qreal subtitleDelay() const; + Config& setSubtitleDelay(qreal value); + + QString assFontFile() const; + Config& setAssFontFile(const QString& value); + QString assFontsDir() const; + Config& setAssFontsDir(const QString& value); + bool isAssFontFileForced() const; + Config& setAssFontFileForced(bool value); + + bool previewEnabled() const; + Config& setPreviewEnabled(bool value); + int previewWidth() const; + Config& setPreviewWidth(int value); + int previewHeight() const; + Config& setPreviewHeight(int value); + + QVariantHash avformatOptions() const; + bool avformatOptionsEnabled() const; + Config& setAvformatOptionsEnabled(bool value); + int analyzeDuration() const; + Config& analyzeDuration(int ad); + unsigned int probeSize() const; + Config& probeSize(unsigned int ps); + bool reduceBuffering() const; + Config& reduceBuffering(bool y); + QString avformatExtra() const; + Config& avformatExtra(const QString& text); + + QString avfilterVideoOptions() const; + Config& avfilterVideoOptions(const QString& options); + bool avfilterVideoEnable() const; + Config& avfilterVideoEnable(bool e); + + QString avfilterAudioOptions() const; + Config& avfilterAudioOptions(const QString& options); + bool avfilterAudioEnable() const; + Config& avfilterAudioEnable(bool e); + + // currently only for xcb + bool isEGL() const; + Config& setEGL(bool value); + // can be "Desktop", "OpenGLES", "Software" + OpenGLType openGLType() const; + Config& setOpenGLType(OpenGLType value); + + QString getANGLEPlatform() const; + Config& setANGLEPlatform(const QString &value); + + // ms >0. default 30000ms + qreal timeout() const; + Config& setTimeout(qreal value); + + bool abortOnTimeout() const; + Config& setAbortOnTimeout(bool value); + + // <0: auto + int bufferValue() const; + Config& setBufferValue(int value); + + // can be: "", "off", "debug", "warning", "critical", "fatal", "all" + QString logLevel() const; + Config& setLogLevel(const QString& value); + + QString language() const; + Config& setLanguage(const QString& value); + + Q_INVOKABLE QVariant operator ()(const QString& key) const; + Q_INVOKABLE Config& operator ()(const QString& key, const QVariant& value); + + /// history will not be clear in reset() + QVariantList history() const; + // {url: urlString, start: ms, duration: ms} + Q_INVOKABLE void addHistory(const QVariantMap& value); + Q_INVOKABLE void removeHistory(const QString& url); + Q_INVOKABLE void clearHistory(); + + Config& setUserShaderEnabled(bool value); + bool userShaderEnabled() const; + Config& setIntermediateFBO(bool value); + bool intermediateFBO() const; + Config& setFragHeader(const QString& text); + QString fragHeader() const; + Config& setFragSample(const QString& text); + QString fragSample() const; + Config& setFragPostProcess(const QString& text); + QString fragPostProcess() const; + Config& setIcnPrefix(const QString &value); + QString icnPrefix() const; + Config& setIcnSuffix(const QString &value); + QString icnSuffix() const; + Config& setHttpPrefix(const QString &value); + QString httpPrefix() const; + Config& setHttpSuffix(const QString &value); + QString httpSuffix() const; + Config& setSegmentBufferSize(qreal value); + qreal segmentBufferSize() const; + Config& setLastPlayed(const QString &value); + QString lastPlayed() const; + Config& setAdaptationLogic(const QString &value); + QString adaptationLogic() const; + Config& setIcn(bool value); + bool icn() const; + Config& setRateAlpha(qreal value); + qreal rateAlpha() const; + Config& setBufferReservoirThreshold(qreal value); + qreal bufferReservoirThreshold() const; + Config& setBufferMaxThreshold(qreal value); + qreal bufferMaxThreshold() const; + Config& setAdaptechFirstThreshold(qreal value); + qreal adaptechFirstThreshold() const; + Config& setAdaptechSecondThreshold(qreal value); + qreal adaptechSecondThreshold() const; + Config& setAdaptechSwitchUpMargin(qreal value); + qreal adaptechSwitchUpMargin() const; + Config& setAdaptechSlackParameter(qreal value); + qreal adaptechSlackParameter() const; + Config& setAdaptechAlpha(qreal value); + qreal adaptechAlpha() const; + Config& setBufferThreeThresholdFirst(qreal value); + qreal bufferThreeThresholdFirst() const; + Config& setBufferThreeThresholdSecond(qreal value); + qreal bufferThreeThresholdSecond() const; + Config& setBufferThreeThresholdThird(qreal value); + qreal bufferThreeThresholdThird() const; + Config& setPandaParamAlpha(qreal value); + qreal pandaParamAlpha() const; + Config& setPandaParamBeta(qreal value); + qreal pandaParamBeta() const; + Config& setPandaParamBMin(qreal value); + qreal pandaParamBMin() const; + Config& setPandaParamK(qreal value); + qreal pandaParamK() const; + Config& setPandaParamW(qreal value); + qreal pandaParamW() const; + Config& setPandaParamEpsilon(qreal value); + qreal pandaParamEpsilon() const; + Config& setBolaBufferTarget(qreal value); + qreal bolaBufferTarget() const; + Config& setBolaAlpha(qreal value); + qreal bolaAlpha() const; + Config& setRepeat(bool value); + bool repeat() const; + Config& setGraph(bool value); + bool graph() const; + Config& setFullScreen(bool value); + bool fullScreen() const; + Config& setAutotune(bool value); + bool autotune() const; + Config& setLifetime(int value); + int lifetime() const; + Config& setRetransmissions(int value); + int retransmissions() const; + Config& setAlpha(qreal value); + qreal alpha() const; + Config& setBeta(qreal value); + qreal beta() const; + Config& setDrop(qreal value); + qreal drop() const; + Config& setBetaWifi(qreal value); + qreal betaWifi() const; + Config& setDropWifi(qreal value); + qreal dropWifi() const; + Config& setDelayWifi(int value); + int delayWifi() const; + Config& setBetaLte(qreal value); + qreal betaLte() const; + Config& setDropLte(qreal value); + qreal dropLte() const; + Config& setDelayLte(int value); + int delayLte() const; + Config& setBatchingParameter(int value); + int batchingParameter() const; + Config& setRateEstimator(int value); + int rateEstimator() const; + + +public: + Q_SIGNAL void changed(); + Q_SIGNAL void userShaderEnabledChanged(); + Q_SIGNAL void intermediateFBOChanged(); + Q_SIGNAL void fragHeaderChanged(); + Q_SIGNAL void fragSampleChanged(); + Q_SIGNAL void fragPostProcessChanged(); + + Q_SIGNAL void lastFileChanged(); + //keyword 'signals' maybe protected. we need call the signals in other classes. Q_SIGNAL is empty + Q_SIGNAL void forceFrameRateChanged(); + Q_SIGNAL void decodingThreadsChanged(int n); + Q_SIGNAL void decoderPriorityNamesChanged(); + Q_SIGNAL void registeredDecodersChanged(const QVector<int>& r); + Q_SIGNAL void zeroCopyChanged(); + Q_SIGNAL void captureDirChanged(const QString& dir); + Q_SIGNAL void captureFormatChanged(const QString& fmt); + Q_SIGNAL void captureQualityChanged(int quality); + Q_SIGNAL void avfilterVideoChanged(); + Q_SIGNAL void avfilterAudioChanged(); + Q_SIGNAL void subtitleEnabledChanged(); + Q_SIGNAL void subtitleAutoLoadChanged(); + Q_SIGNAL void subtitleEnginesChanged(); + Q_SIGNAL void subtitleFontChanged(); + Q_SIGNAL void subtitleColorChanged(); + Q_SIGNAL void subtitleOutlineChanged(); + Q_SIGNAL void subtitleOutlineColorChanged(); + Q_SIGNAL void subtitleBottomMarginChanged(); + Q_SIGNAL void subtitleDelayChanged(); + Q_SIGNAL void assFontFileChanged(); + Q_SIGNAL void assFontsDirChanged(); + Q_SIGNAL void assFontFileForcedChanged(); + Q_SIGNAL void previewEnabledChanged(); + Q_SIGNAL void previewWidthChanged(); + Q_SIGNAL void previewHeightChanged(); + Q_SIGNAL void EGLChanged(); + Q_SIGNAL void openGLTypeChanged(); + Q_SIGNAL void ANGLEPlatformChanged(); + Q_SIGNAL void avformatOptionsEnabledChanged(); + Q_SIGNAL void bufferValueChanged(); + Q_SIGNAL void timeoutChanged(); + Q_SIGNAL void abortOnTimeoutChanged(); + Q_SIGNAL void logLevelChanged(); + Q_SIGNAL void languageChanged(); + Q_SIGNAL void historyChanged(); + Q_SIGNAL void icnSuffixChanged(); + Q_SIGNAL void httpSuffixChanged(); + Q_SIGNAL void icnPrefixChanged(); + Q_SIGNAL void httpPrefixChanged(); + Q_SIGNAL void segmentBufferSizeChanged(); + Q_SIGNAL void lastPlayedChanged(); + Q_SIGNAL void adaptationLogicChanged(); + Q_SIGNAL void icnChanged(); + Q_SIGNAL void rateAlphaChanged(); + Q_SIGNAL void bufferReservoirThresholdChanged(); + Q_SIGNAL void bufferMaxThresholdChanged(); + Q_SIGNAL void adaptechFirstThresholdChanged(); + Q_SIGNAL void adaptechSecondThresholdChanged(); + Q_SIGNAL void adaptechSwitchUpMarginChanged(); + Q_SIGNAL void adaptechSlackParameterChanged(); + Q_SIGNAL void adaptechAlphaChanged(); + Q_SIGNAL void bufferThreeThresholdFirstChanged(); + Q_SIGNAL void bufferThreeThresholdSecondChanged(); + Q_SIGNAL void bufferThreeThresholdThirdChanged(); + Q_SIGNAL void pandaParamAlphaChanged(); + Q_SIGNAL void pandaParamBetaChanged(); + Q_SIGNAL void pandaParamBMinChanged(); + Q_SIGNAL void pandaParamKChanged(); + Q_SIGNAL void pandaParamWChanged(); + Q_SIGNAL void pandaParamEpsilonChanged(); + Q_SIGNAL void bolaAlphaChanged(); + Q_SIGNAL void bolaBufferTargetChanged(); + Q_SIGNAL void repeatChanged(); + Q_SIGNAL void graphChanged(); + Q_SIGNAL void fullScreenChanged(); + Q_SIGNAL void autotuneChanged(); + Q_SIGNAL void lifetimeChanged(); + Q_SIGNAL void retransmissionsChanged(); + Q_SIGNAL void alphaChanged(); + Q_SIGNAL void betaChanged(); + Q_SIGNAL void dropChanged(); + Q_SIGNAL void betaWifiChanged(); + Q_SIGNAL void dropWifiChanged(); + Q_SIGNAL void delayWifiChanged(); + Q_SIGNAL void betaLteChanged(); + Q_SIGNAL void dropLteChanged(); + Q_SIGNAL void delayLteChanged(); + Q_SIGNAL void batchingParameterChanged(); + Q_SIGNAL void rateEstimatorChanged(); + +protected: + explicit Config(QObject *parent = 0); + ~Config(); + +public Q_SLOTS: + void save(); + +private: + class Data; + Data *mpData; +}; + +#endif // PLAYER_CONFIG_H diff --git a/Common/Info.plist b/Common/Info.plist new file mode 100644 index 00000000..8e33963e --- /dev/null +++ b/Common/Info.plist @@ -0,0 +1,225 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>AAC</string> + <string>AC3</string> + <string>AIFF</string> + <string>M4A</string> + <string>MKA</string> + <string>MP3</string> + <string>OGG</string> + <string>PCM</string> + <string>VAW</string> + <string>WAV</string> + <string>WAW</string> + <string>WMA</string> + <string>aac</string> + <string>ac3</string> + <string>aiff</string> + <string>m4a</string> + <string>mka</string> + <string>mp3</string> + <string>ogg</string> + <string>pcm</string> + <string>vaw</string> + <string>wav</string> + <string>waw</string> + <string>wma</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeName</key> + <string>Audio file</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSTypeIsPackage</key> + <false/> + <key>NSPersistentStoreTypeKey</key> + <string>XML</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>*</string> + <string>*</string> + <string>3GP</string> + <string>3IV</string> + <string>3gp</string> + <string>3iv</string> + <string>ASF</string> + <string>AVI</string> + <string>CPK</string> + <string>DAT</string> + <string>DIVX</string> + <string>DV</string> + <string>FLAC</string> + <string>FLI</string> + <string>FLV</string> + <string>H264</string> + <string>I263</string> + <string>M2TS</string> + <string>M4V</string> + <string>MKV</string> + <string>MOV</string> + <string>MP2</string> + <string>MP4</string> + <string>MPEG</string> + <string>MPG</string> + <string>MPG2</string> + <string>MPG4</string> + <string>NSV</string> + <string>NUT</string> + <string>NUV</string> + <string>OGG</string> + <string>OGM</string> + <string>QT</string> + <string>RM</string> + <string>RMVB</string> + <string>VCD</string> + <string>VFW</string> + <string>VOB</string> + <string>WEBM</string> + <string>WMV</string> + <string>asf</string> + <string>avi</string> + <string>cpk</string> + <string>dat</string> + <string>divx</string> + <string>dv</string> + <string>flac</string> + <string>fli</string> + <string>flv</string> + <string>h264</string> + <string>i263</string> + <string>m2ts</string> + <string>m4v</string> + <string>mkv</string> + <string>mov</string> + <string>mp2</string> + <string>mp4</string> + <string>mpeg</string> + <string>mpg</string> + <string>mpg2</string> + <string>mpg4</string> + <string>mts</string> + <string>nsv</string> + <string>nut</string> + <string>nuv</string> + <string>ogg</string> + <string>ogm</string> + <string>qt</string> + <string>rm</string> + <string>rmvb</string> + <string>vcd</string> + <string>vfw</string> + <string>vob</string> + <string>webm</string> + <string>wmv</string> + <string>f4v</string> + <string>ts</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeName</key> + <string>Movie file</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSTypeIsPackage</key> + <false/> + <key>NSPersistentStoreTypeKey</key> + <string>XML</string> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>AQT</string> + <string>ASS</string> + <string>JSS</string> + <string>RT</string> + <string>SMI</string> + <string>SRT</string> + <string>SSA</string> + <string>SUB</string> + <string>TXT</string> + <string>UTF</string> + <string>aqt</string> + <string>ass</string> + <string>jss</string> + <string>rt</string> + <string>smi</string> + <string>srt</string> + <string>ssa</string> + <string>sub</string> + <string>txt</string> + <string>utf</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>document.icns</string> + <key>CFBundleTypeName</key> + <string>Subtitles file</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSTypeIsPackage</key> + <false/> + <key>NSPersistentStoreTypeKey</key> + <string>XML</string> + </dict> + </array> + <key>CFBundleExecutable</key> + <string>@EXECUTABLE@</string> + <key>CFBundleIconFile</key> + <string>Cisco.icns</string> + <key>CFBundleIdentifier</key> + <string>com.cisco.@EXECUTABLE@</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>QtPlayer @EXECUTABLE@</string> + <key>CFBundleDisplayName</key> + <string>QtPlayer @EXECUTABLE@</string> + <key>LSMinimumSystemVersionByArchitecture</key> + <dict> + <key>x86_64</key> + <string>10.6.0</string> + </dict> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>@SHORT_VERSION@</string> + <key>CFBundleVersion</key> + <string>@FULL_VERSION@</string> + <key>NSHighResolutionCapable</key> + <true/> + <key>UIFileSharingEnabled</key> + <true/> + <key>CFBundleURLTypes</key> + <array> + <dict> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>CFBundleURLName</key> + <string>Streaming Protocol</string> + <key>CFBundleURLSchemes</key> + <array> + <string>mms</string> + <string>mmst</string> + <string>http</string> + <string>httpproxy</string> + <string>rtp</string> + <string>rtsp</string> + <string>ftp</string> + <string>udp</string> + <string>smb</string> + </array> + </dict> + </array> +</dict> +</plist> diff --git a/Common/QOptions.cpp b/Common/QOptions.cpp new file mode 100644 index 00000000..82bf2184 --- /dev/null +++ b/Common/QOptions.cpp @@ -0,0 +1,375 @@ +/****************************************************************************** + QOptions: make command line options easy. https://github.com/wang-bin/qoptions + Copyright (C) 2011-2015 Wang Bin <wbsecg1@gmail.com> + 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 "QOptions.h" +#include <QtCore/QStringList> +#include <QtCore/QtDebug> + +QOption::QOption() +{} + +QOption::QOption(const char *name, const QVariant &defaultValue, Type type, const QString &description) +:mType(type),mDescription(description),mDefaultValue(defaultValue) +{ + setName(QLatin1String(name)); +} + +QOption::QOption(const char *name, Type type, const QString &description) +:mType(type),mDescription(description),mDefaultValue(QVariant()) +{ + //if (mType==QOption::NoToken) + // mValue = false; + setName(QLatin1String(name)); +} +/* +QOption::QOption(const char *name, const QVariant& value, Type type, const QString &description) +:mType(type),mDescription(description),mDefaultValue(*value),mValue(value) +{qDebug("%s %s %d", __FILE__, __FUNCTION__, __LINE__); + setName(name); +} +*/ + +QString QOption::shortName() const +{ + return mShortName; +} + +QString QOption::longName() const +{ + return mLongName; +} + +QString QOption::formatName() const +{ + if (mLongName.isEmpty()) + return QLatin1String("-") + mShortName; + if (mShortName.isEmpty()) + return QLatin1String("--") + mLongName; + return QString::fromLatin1("-%1 [--%2]").arg(mShortName).arg(mLongName); +} + +QString QOption::description() const +{ + return mDescription; +} + +QVariant QOption::value() const +{ + if (mValue.isValid()) + return mValue; + return mDefaultValue; +} + +void QOption::setValue(const QVariant &value) +{ + mValue = value; +} + +bool QOption::isSet() const +{ + return mValue.isValid(); +} + +bool QOption::isValid() const +{ + return !shortName().isEmpty() || !longName().isEmpty(); +} + +void QOption::setType(QOption::Type type) +{ + mType = type; + if (mType==NoToken) + mValue = false; +} + +QOption::Type QOption::type() const +{ + return mType; +} + +QString QOption::help() const +{ + QString message = formatName(); + if (type()==QOption::SingleToken) + message.append(QLatin1String(" value")); + else if (type()==QOption::MultiToken) + message.append(QLatin1String(" value1 ... valueN")); + + message = QString::fromLatin1("%1").arg(message, -33); + message.append(mDescription); + if (mDefaultValue.isValid() && !mDefaultValue.toString().isEmpty()) + message.append(QLatin1String(" (default: ") + mDefaultValue.toString() + QLatin1String(")")); + return message; +} + +bool QOption::operator <(const QOption& o) const +{ + return mType < o.type() || mShortName < o.shortName() || mLongName < o.longName() || mDescription < o.description(); +} + +static QString get_short(const QString& name) +{ + if (name.startsWith(QLatin1String("--"))) + return QString(); + if (name.startsWith(QLatin1String("-"))) + return name.mid(1); + return name; +} + +static QString get_long(const QString& name) +{ + if (name.startsWith(QLatin1String("--"))) + return name.mid(2); + if (name.startsWith(QLatin1String("-"))) + return QString(); + return name; +} + +void QOption::setName(const QString &name) +{ + int comma = name.indexOf(QLatin1Char(',')); + if (comma>0) { + QString name1 = name.left(comma); + QString name2 = name.mid(comma+1); + if (name1.startsWith(QLatin1String("--"))) { + mLongName = name1.mid(2); + mShortName = get_short(name2); + } else if (name1.startsWith(QLatin1String("-"))) { + mShortName = name1.mid(1); + mLongName = get_long(name2); + } else { + if (name2.startsWith(QLatin1String("--"))) { + mLongName = name2.mid(2); + mShortName = name1; + } else if (name2.startsWith(QLatin1String("-"))) { + mShortName = name2.mid(1); + mLongName = name1; + } else { + mShortName = name2; + mLongName = name1; + } + } + } else { + if (name.startsWith(QLatin1String("--"))) + mLongName = name.mid(2); + else if (name.startsWith(QLatin1String("-"))) + mShortName = name.mid(1); + else + mShortName = name; + } +} + + + +QOptions::QOptions() +{ +} + +QOptions::~QOptions() +{ + mOptionGroupMap.clear(); + mOptions.clear(); +} + +bool QOptions::parse(int argc, const char *const*argv) +{ + if (mOptionGroupMap.isEmpty()) + return false; + + if (argc==1) + return true; + + bool result = true; + QStringList args; + for (int i=1;i<argc;++i) { + args.append(QString::fromLocal8Bit(argv[i])); + } + + QStringList::Iterator it = args.begin(); + QList<QOption>::Iterator it_list; + mOptions = mOptionGroupMap.keys(); + + while (it != args.end()) { + if (it->startsWith(QLatin1String("--"))) { + int e = it->indexOf(QLatin1Char('=')); + for (it_list = mOptions.begin(); it_list != mOptions.end(); ++it_list) { + if (it_list->longName() == it->mid(2,e-2)) { + if (it_list->type()==QOption::NoToken) { + it_list->setValue(true); + //qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString())); + it = args.erase(it); + break; + } + if (e>0) { // + it_list->setValue(it->mid(e+1)); + //qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString())); + } else { + it = args.erase(it); + if (it == args.end()) + break; + it_list->setValue(*it); + //qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString())); + } + it = args.erase(it); + break; + } + } + if (it_list == mOptions.end()) { + qWarning() << "unknown option: " << *it; + result = false; + ++it; + } + //handle unknown option + } else if (it->startsWith(QLatin1Char('-'))) { + for (it_list = mOptions.begin(); it_list != mOptions.end(); ++it_list) { + QString sname = it_list->shortName(); + int sname_len = sname.length(); //usally is 1 + //TODO: startsWith(-height,-h) Not endsWith, -oabco + if (it->midRef(1).compare(sname) == 0) { + if (it_list->type() == QOption::NoToken) { + it_list->setValue(true); + it = args.erase(it); + break; + } + if (it->length() == sname_len+1) {//-o abco + it = args.erase(it); + if (it == args.end()) + break; + it_list->setValue(*it); + //qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString())); + } else { + it_list->setValue(it->mid(sname_len+1)); + //qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString())); + } + it = args.erase(it); + break; + } + } + if (it_list==mOptions.end()) { + qWarning() << "unknown option: " << *it; + result = false; + ++it; + } + //handle unknown option + } else { + qWarning() << "unknown option: " << *it; + ++it; + } + } + if (!result) { + print(); + } + return result; +} + +QOptions& QOptions::add(const QString &group_description) +{ + mCurrentDescription = group_description; + return *this; +} + +QOptions& QOptions::addDescription(const QString &description) +{ + mDescription = description; + return *this; +} + +QOptions& QOptions::operator ()(const char* name, const QString& description) +{ + QOption op(name, QOption::NoToken, description); + mOptions.append(op); + mOptionGroupMap.insert(op, mCurrentDescription); + return *this; +} + +QOptions& QOptions::operator ()(const char* name, QOption::Type type, const QString& description) +{ + QOption op(name, type, description); + mOptions.append(op); + mOptionGroupMap.insert(op, mCurrentDescription); + return *this; +} + +QOptions& QOptions::operator ()(const char* name, const QVariant& defaultValue, const QString& description) +{ + QOption op(name, defaultValue, QOption::SingleToken, description); + mOptions.append(op); + mOptionGroupMap.insert(op, mCurrentDescription); + return *this; +} + +QOptions& QOptions::operator ()(const char* name, const QVariant& defaultValue, QOption::Type type, const QString& description) +{ + QOption op(name, defaultValue, type, description); + mOptions.append(op); + mOptionGroupMap.insert(op, mCurrentDescription); + return *this; +} +/* + +QOptions& QOptions::operator ()(const char* name, const QVariant& value, QOption::Type type, const QString& description) +{ + QOption op(name, value, type, description); + mOptions.append(op); + mOptionGroupMap.insert(op, mCurrentDescription); + return *this; +} +*/ + +QOption QOptions::option(const QString &name) const +{ + if (mOptions.isEmpty()) + return QOption(); + QList<QOption>::ConstIterator it_list; + for (it_list=mOptions.constBegin(); it_list!=mOptions.constEnd(); ++it_list) { + if (it_list->shortName()==name || it_list->longName()==name) { + return *it_list; + } + } + return QOption(); +} + +QVariant QOptions::value(const QString& name) const +{ + return option(name).value(); +} + +QVariant QOptions::operator [](const QString& name) const +{ + return value(name); +} + +QString QOptions::help() const +{ + QString message = mDescription; + QStringList groups = mOptionGroupMap.values(); + groups.removeDuplicates(); + QList<QString>::ConstIterator it; + + QList<QOption>::ConstIterator it_op; + for (it=groups.constBegin(); it!=groups.constEnd(); ++it) { + message.append(QLatin1String("\n")).append(*it); + QList<QOption> options = mOptionGroupMap.keys(*it); + for (it_op=options.constBegin();it_op!=options.constEnd();++it_op) + message.append(QLatin1String("\n ")).append(it_op->help()); + } + return message; +} + +void QOptions::print() const +{ + qDebug("%s", help().toUtf8().constData()); +} diff --git a/Common/QOptions.h b/Common/QOptions.h new file mode 100644 index 00000000..7e02867e --- /dev/null +++ b/Common/QOptions.h @@ -0,0 +1,113 @@ +/****************************************************************************** + QOptions: make command line options easy. https://github.com/wang-bin/qoptions + Copyright (C) 2011-2015 Wang Bin <wbsecg1@gmail.com> + 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. +******************************************************************************/ + +#ifndef QOPTIONS_H +#define QOPTIONS_H + +#include <QtCore/QVariant> +#include <QtCore/QMap> +#include <QtCore/QList> + +#if defined(BUILD_QOPT_LIB) +# define QOPT_EXPORT Q_DECL_EXPORT +#elif defined(BUILD_QOPT_IMPORT) +# define QOPT_EXPORT Q_DECL_IMPORT //only for vc? +#else +# define QOPT_EXPORT +#endif + + +class QOPT_EXPORT QOption { +public: + // TODO: MultiToken -name value1 -name value2 ... + enum Type { + NoToken, SingleToken, MultiToken + }; + QOption(); + explicit QOption(const char* name, const QVariant& defaultValue, Type type, const QString& description); + explicit QOption(const char* name, Type type, const QString& description); + //explicit QOption(const char* name, const QVariant& value, Type type, const QString& description); + + QString shortName() const; + QString longName() const; + QString formatName() const; + QString description() const; + QVariant value() const; + void setValue(const QVariant& value); + bool isSet() const; + bool isValid() const; + + void setType(QOption::Type type); + QOption::Type type() const; + + QString help() const; + void print() const; + bool operator <(const QOption& o) const; +private: + /*! + * \brief setName + * short/long name format: + * "--long", "-short", "short" + * "long,short", "--long,short", "--long,-short", "long,-short" + * "short,--long", "-short,long", "-short,--long" + * \param name + */ + void setName(const QString& name); + + QOption::Type mType; + QString mShortName, mLongName, mDescription; + QVariant mDefaultValue; + QVariant mValue; +}; + + +class QOPT_EXPORT QOptions { +public: + //e.g. application information, copyright etc. + QOptions(); + //QOptions(const QOptions& o); + ~QOptions(); + //QOptions& operator=(const QOptions& o); + + /*! + * \brief parse + * \param argc + * \param argv + * \return false if invalid option found + */ + bool parse(int argc, const char*const* argv); + QOptions& add(const QString& group_description); + QOptions& addDescription(const QString& description); + + QOptions& operator ()(const char* name, const QString& description = QString()); + QOptions& operator ()(const char* name, QOption::Type type, const QString& description = QString()); + QOptions& operator ()(const char* name, const QVariant& defaultValue, const QString& description); + QOptions& operator ()(const char* name, const QVariant& defaultValue, QOption::Type type, const QString& description = QString()); + //QOptions& operator ()(const char* name, QVariant* value, QOption::Type type, const QString& description = QString()); + + QOption option(const QString& name) const; + QVariant value(const QString& name) const; + QVariant operator [](const QString& name) const; + + QString help() const; + void print() const; +private: + QString mDescription, mCurrentDescription; + QList<QOption> mOptions; + QMap<QOption, QString/*group*/> mOptionGroupMap; +}; + +#endif // QOPTIONS_H diff --git a/Common/QtQuick2ApplicationViewer.cpp b/Common/QtQuick2ApplicationViewer.cpp new file mode 100755 index 00000000..f2efdf3d --- /dev/null +++ b/Common/QtQuick2ApplicationViewer.cpp @@ -0,0 +1,104 @@ +/* + This file was generated by the Qt Quick 2 Application wizard of Qt Creator. + QtQuick2ApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#include "QtQuick2ApplicationViewer.h" + +#include <QApplication> +#include <QtCore/QDir> +#include <QtQml/QQmlEngine> + +class QtQuick2ApplicationViewerPrivate +{ + QString mainQmlFile; + friend class QtQuick2ApplicationViewer; + static QString adjustPath(const QString &path); +}; + +QString QtQuick2ApplicationViewerPrivate::adjustPath(const QString &path) +{ + if (path.startsWith(QLatin1String("qrc:"))) + return path; +#if defined(Q_OS_IOS) + if (!QDir::isAbsolutePath(path)) + return QString::fromLatin1("%1/%2") + .arg(QCoreApplication::applicationDirPath(), path); +#elif defined(Q_OS_MAC) + if (!QDir::isAbsolutePath(path)) + return QString::fromLatin1("%1/../Resources/%2") + .arg(QCoreApplication::applicationDirPath(), path); +#elif defined(Q_OS_BLACKBERRY) + if (!QDir::isAbsolutePath(path)) + return QString::fromLatin1("app/native/%1").arg(path); +#elif !defined(Q_OS_ANDROID) + QString pathInInstallDir = + QString::fromLatin1("%1/../%2").arg(QCoreApplication::applicationDirPath(), path); + if (QFileInfo(pathInInstallDir).exists()) + return pathInInstallDir; + pathInInstallDir = + QString::fromLatin1("%1/%2").arg(QCoreApplication::applicationDirPath(), path); + if (QFileInfo(pathInInstallDir).exists()) + return pathInInstallDir; +#elif defined(Q_OS_ANDROID_NO_SDK) + return QLatin1String("/data/user/qt/") + path; +#endif + return path; +} + +QtQuick2ApplicationViewer::QtQuick2ApplicationViewer(QWindow *parent) + : QQuickView(parent) + , d(new QtQuick2ApplicationViewerPrivate()) +{ + connect(engine(), SIGNAL(quit()), SLOT(close())); + setResizeMode(QQuickView::SizeRootObjectToView); +} + +QtQuick2ApplicationViewer::~QtQuick2ApplicationViewer() +{ + delete d; +} + +void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file) +{ + if (file.startsWith(QLatin1String("qrc:"))) { + d->mainQmlFile = file; + setSource(QUrl(d->mainQmlFile)); + return; + } + d->mainQmlFile = QtQuick2ApplicationViewerPrivate::adjustPath(file); +#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) + QUrl qmlUrl(QUrl(QLatin1String("assets:/")+d->mainQmlFile)); +#else + QUrl qmlUrl(QUrl::fromLocalFile(d->mainQmlFile)); +#endif + if (d->mainQmlFile.startsWith(QLatin1String("qrc:/"))) { + qmlUrl = QUrl(d->mainQmlFile); + } + setSource(qmlUrl); +} + +void QtQuick2ApplicationViewer::addImportPath(const QString &path) +{ + engine()->addImportPath(QtQuick2ApplicationViewerPrivate::adjustPath(path)); +} + +void QtQuick2ApplicationViewer::showExpanded() +{ + if (QApplication::platformName() == QLatin1String("qnx") || + QApplication::platformName() == QLatin1String("eglfs")) { + showFullScreen(); + } else { + show(); + } + return; +#if defined(Q_OS_QNX) //|| defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_MAEMO) + showFullScreen(); +#else + show(); +#endif +} diff --git a/Common/QtQuick2ApplicationViewer.h b/Common/QtQuick2ApplicationViewer.h new file mode 100755 index 00000000..6eee3c89 --- /dev/null +++ b/Common/QtQuick2ApplicationViewer.h @@ -0,0 +1,32 @@ +/* + This file was generated by the Qt Quick 2 Application wizard of Qt Creator. + QtQuick2ApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#ifndef QTQUICK2APPLICATIONVIEWER_H +#define QTQUICK2APPLICATIONVIEWER_H + +#include <QtQuick/QQuickView> + +class QtQuick2ApplicationViewer : public QQuickView +{ + Q_OBJECT + +public: + explicit QtQuick2ApplicationViewer(QWindow *parent = 0); + virtual ~QtQuick2ApplicationViewer(); + + void setMainQmlFile(const QString &file); + void addImportPath(const QString &path); + + void showExpanded(); + +private: + class QtQuick2ApplicationViewerPrivate *d; +}; + +#endif // QTQUICK2APPLICATIONVIEWER_H diff --git a/Common/Viper.icns b/Common/Viper.icns Binary files differnew file mode 100644 index 00000000..eccc7bdb --- /dev/null +++ b/Common/Viper.icns diff --git a/Common/ViperBuffer.cpp b/Common/ViperBuffer.cpp new file mode 100644 index 00000000..27ec8b5e --- /dev/null +++ b/Common/ViperBuffer.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ViperBuffer.h" +ViperBuffer::ViperBuffer(QObject* parent) : + QIODevice(parent) +{ + readMax = 32768; + readBuffer = (uint8_t*)malloc(sizeof(uint8_t)*readMax); + pthread_mutex_init(&(this->monitorMutex), NULL); + qByteArrayVector.reserve(2); + qByteArrayVector.push_back(new QByteArray()); + qByteArrayVector.push_back(new QByteArray()); + indexReadBuffer = 0; + indexWriteBuffer = 0; +} + +ViperBuffer::~ViperBuffer() +{ + pthread_mutex_destroy(&(this->monitorMutex)); + free(readBuffer); +} + +bool ViperBuffer::isSequential() const +{ + return true; +} + +bool ViperBuffer::open(OpenMode mode) +{ + setOpenMode(mode); + return true; +} + +void ViperBuffer::close() +{ + qByteArrayVector.clear(); + setOpenMode(NotOpen); +} + +void ViperBuffer::clear() +{ + qByteArrayVector.at(0)->clear(); + qByteArrayVector.at(1)->clear(); + indexReadBuffer = 0; + indexWriteBuffer = 0; +} + +qint64 ViperBuffer::readData(char* data, qint64 maxSize) +{ + pthread_mutex_lock(&(this->monitorMutex)); + if ((maxSize = qMin(maxSize, qint64(qByteArrayVector.at(indexReadBuffer)->size()))) <= 0) + { + pthread_mutex_unlock(&(this->monitorMutex)); + return qint64(0); + } + memcpy(data, qByteArrayVector.at(indexReadBuffer)->constData(), maxSize); + qByteArrayVector.at(indexReadBuffer)->remove(0,maxSize); + pthread_mutex_unlock(&(this->monitorMutex)); + return maxSize; + +} + +qint64 ViperBuffer::writeData(libdash::framework::input::MediaObject* media) +{ + pthread_mutex_lock(&(this->monitorMutex)); + int ret = 0; + int total = 0; + ret = media->ReadInitSegment(readBuffer,readMax); + total += ret; + this->writeData((const char *)readBuffer, ret); + + ret = media->Read(readBuffer,readMax); + while(ret) + { + total += ret; + this->writeData((const char *)readBuffer, ret); + ret = media->Read(readBuffer,readMax); + } + pthread_mutex_unlock(&(this->monitorMutex)); + return total; +} + +qint64 ViperBuffer::writeData(const char* data, qint64 maxSize) +{ + qByteArrayVector.at(indexWriteBuffer)->append(data, maxSize); + return maxSize; +} + + +void ViperBuffer::writeToNextBuffer() +{ + + pthread_mutex_lock(&(this->monitorMutex)); + indexWriteBuffer = (indexWriteBuffer + 1 ) % 2; + pthread_mutex_unlock(&(this->monitorMutex)); + +} + +void ViperBuffer::readFromNextBuffer() +{ + pthread_mutex_lock(&(this->monitorMutex)); + indexReadBuffer = (indexReadBuffer + 1 ) % 2; + pthread_mutex_unlock(&(this->monitorMutex)); + +} + diff --git a/Common/ViperBuffer.h b/Common/ViperBuffer.h new file mode 100644 index 00000000..37060178 --- /dev/null +++ b/Common/ViperBuffer.h @@ -0,0 +1,51 @@ +#ifndef VIPERBUFFER_H +#define VIPERBUFFER_H + +#include <QIODevice> +#include <qobject.h> +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <iostream> +#include <vector> +#include "../Input/MediaObject.h" + +class ViperBuffer : public QIODevice +{ + Q_OBJECT +public: + ViperBuffer(QObject* parent = 0); + ~ViperBuffer(); + bool open(OpenMode mode); + void close(); + bool isSequential() const; + qint64 readData(char* data, qint64 maxSize); + qint64 writeData(libdash::framework::input::MediaObject* segment); + QByteArray* buffer(); + void clear(); + void writeToNextBuffer(); + void readFromNextBuffer(); + +private: + std::vector<QByteArray*> qByteArrayVector; + unsigned int indexReadBuffer; + unsigned int indexWriteBuffer; + pthread_mutex_t monitorMutex; + int readMax; + uint8_t* readBuffer; + qint64 writeData(const char* data, qint64 maxSize); + Q_DISABLE_COPY(ViperBuffer) +}; +#endif // VIPERBUFFER_H |