aboutsummaryrefslogtreecommitdiffstats
path: root/Common
diff options
context:
space:
mode:
Diffstat (limited to 'Common')
-rw-r--r--Common/Common.cpp361
-rw-r--r--Common/Common.h46
-rw-r--r--Common/CommonExport.h33
-rw-r--r--Common/Config.cpp1983
-rw-r--r--Common/Config.h463
-rw-r--r--Common/Info.plist225
-rw-r--r--Common/QOptions.cpp375
-rw-r--r--Common/QOptions.h113
-rwxr-xr-xCommon/QtQuick2ApplicationViewer.cpp104
-rwxr-xr-xCommon/QtQuick2ApplicationViewer.h32
-rw-r--r--Common/Viper.icnsbin0 -> 62464 bytes
-rw-r--r--Common/ViperBuffer.cpp119
-rw-r--r--Common/ViperBuffer.h51
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
new file mode 100644
index 00000000..eccc7bdb
--- /dev/null
+++ b/Common/Viper.icns
Binary files differ
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