mirror of
https://gitlab.com/kelteseth/ScreenPlay.git
synced 2024-09-18 08:22:33 +02:00
Add MultimediaWebView
This is for now macOS only because macOS MM only can play h264, so we still need the webview to render webm
This commit is contained in:
parent
6a081b4f25
commit
0419676af2
@ -102,4 +102,27 @@ namespace InstalledType {
|
||||
Q_ENUM_NS(InstalledType)
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
\namespace ScreenPlay::InstalledType
|
||||
\inmodule ScreenPlayUtil
|
||||
\brief When changing the enum, one also needs to change:
|
||||
GlobalVariables::getAvailableWallpaper
|
||||
GlobalVariables::getAvailableWidgets
|
||||
Common/Util.js isWallpaper() and isWidget()
|
||||
ScreenPlayWallpaper: BaseWindow::parseWallpaperType()
|
||||
*/
|
||||
namespace VideoCodec {
|
||||
Q_NAMESPACE
|
||||
|
||||
enum class VideoCodec {
|
||||
Unknown,
|
||||
VP8,
|
||||
VP9,
|
||||
AV1,
|
||||
H264,
|
||||
H265
|
||||
};
|
||||
Q_ENUM_NS(VideoCodec)
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ namespace ScreenPlayUtil {
|
||||
QJsonArray fillArray(const QVector<QString>& items);
|
||||
ScreenPlay::SearchType::SearchType getSearchTypeFromInstalledType(const ScreenPlay::InstalledType::InstalledType type);
|
||||
std::optional<ScreenPlay::InstalledType::InstalledType> getInstalledTypeFromString(const QString& type);
|
||||
std::optional<ScreenPlay::VideoCodec::VideoCodec> getVideoCodecFromString(const QString& type);
|
||||
std::optional<QJsonObject> parseQByteArrayToQJsonObject(const QByteArray& byteArray);
|
||||
std::optional<QJsonObject> openJsonFileToObject(const QString& path);
|
||||
std::optional<QString> openJsonFileToString(const QString& path);
|
||||
|
@ -266,6 +266,33 @@ std::optional<ScreenPlay::InstalledType::InstalledType> getInstalledTypeFromStri
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Maps the video codec type from a QString to an enum. Used for parsing the project.json.
|
||||
*/
|
||||
std::optional<ScreenPlay::VideoCodec::VideoCodec> getVideoCodecFromString(const QString &type)
|
||||
{
|
||||
if(type.isEmpty())
|
||||
return std::nullopt;
|
||||
|
||||
if(type.contains("vp8",Qt::CaseInsensitive))
|
||||
return ScreenPlay::VideoCodec::VideoCodec::VP8;
|
||||
|
||||
if(type.contains("vp9",Qt::CaseInsensitive))
|
||||
return ScreenPlay::VideoCodec::VideoCodec::VP9;
|
||||
|
||||
if(type.contains("av1",Qt::CaseInsensitive))
|
||||
return ScreenPlay::VideoCodec::VideoCodec::AV1;
|
||||
|
||||
if(type.contains("h264",Qt::CaseInsensitive))
|
||||
return ScreenPlay::VideoCodec::VideoCodec::H264;
|
||||
|
||||
if(type.contains("h265",Qt::CaseInsensitive))
|
||||
return ScreenPlay::VideoCodec::VideoCodec::H264;
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Converts the given \a url string to a local file path.
|
||||
*/
|
||||
@ -368,4 +395,5 @@ std::optional<QVector<int>> parseStringToIntegerList(const QString string)
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -9,5 +9,6 @@
|
||||
<file>qml/WebsiteWallpaper.qml</file>
|
||||
<file>qml/WebView.qml</file>
|
||||
<file>qml/MultimediaView.qml</file>
|
||||
<file>qml/MultimediaWebView.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -13,11 +13,4 @@ Video {
|
||||
if (Wallpaper.loops)
|
||||
root.play()
|
||||
}
|
||||
|
||||
//loops: MediaPlayer.Infinite
|
||||
// onErrorOccurred: function (error, errorString) {
|
||||
// console.log("[qmlvideo] VideoItem.onError error " + error
|
||||
// + " errorString " + errorString)
|
||||
// root.fatalError()
|
||||
// }
|
||||
}
|
||||
|
157
ScreenPlayWallpaper/qml/MultimediaWebView.qml
Normal file
157
ScreenPlayWallpaper/qml/MultimediaWebView.qml
Normal file
@ -0,0 +1,157 @@
|
||||
import QtQuick
|
||||
import QtWebEngine
|
||||
import ScreenPlay.Enums.InstalledType 1.0
|
||||
import ScreenPlayWallpaper 1.0
|
||||
|
||||
/*!
|
||||
* The native macOS multimedia stack does not support VP8/VP9. For this we must use the WebEngine.
|
||||
*/
|
||||
Item {
|
||||
id: root
|
||||
|
||||
signal requestFadeIn()
|
||||
|
||||
function getSetVideoCommand() {
|
||||
// TODO 30:
|
||||
// Currently wont work. Commit anyways til QtCreator and Qt work with js template literals
|
||||
var src = ""
|
||||
src += "var videoPlayer = document.getElementById('videoPlayer');"
|
||||
src += "var videoSource = document.getElementById('videoSource');"
|
||||
src += "videoSource.src = '" + Wallpaper.projectSourceFileAbsolute + "';"
|
||||
src += "videoPlayer.load();"
|
||||
src += "videoPlayer.volume = " + Wallpaper.volume + ";"
|
||||
src += "videoPlayer.setAttribute('style', 'object-fit :" + Wallpaper.fillMode + ";');"
|
||||
src += "videoPlayer.play();"
|
||||
print(src)
|
||||
return src
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
WebEngine.settings.localContentCanAccessFileUrls = true
|
||||
WebEngine.settings.localContentCanAccessRemoteUrls = true
|
||||
WebEngine.settings.allowRunningInsecureContent = true
|
||||
WebEngine.settings.accelerated2dCanvasEnabled = true
|
||||
WebEngine.settings.javascriptCanOpenWindows = false
|
||||
WebEngine.settings.showScrollBars = false
|
||||
WebEngine.settings.playbackRequiresUserGesture = false
|
||||
WebEngine.settings.focusOnNavigationEnabled = true
|
||||
}
|
||||
|
||||
WebEngineView {
|
||||
id: webView
|
||||
anchors.fill: parent
|
||||
// url:"https://www.google.de"
|
||||
url: "qrc:/index.html"
|
||||
onJavaScriptConsoleMessage:(lineNumber, message)=> print(lineNumber, message)
|
||||
onLoadProgressChanged: {
|
||||
if (loadProgress === 100) {
|
||||
loadHtml("")
|
||||
requestFadeIn()
|
||||
return
|
||||
webView.runJavaScript(root.getSetVideoCommand(),
|
||||
function (result) {
|
||||
requestFadeIn()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Text {
|
||||
id: txtVisualsPaused
|
||||
text: qsTr("If you can read this, then the VisualsPaused optimization does not work on your system. You can fix this by disable this in: \n Settings -> Perfromance -> Pause wallpaper video rendering while another app is in the foreground ")
|
||||
font.pointSize: 32
|
||||
visible: false
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
anchors.centerIn: parent
|
||||
width: parent.width * 0.8
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timerCover
|
||||
|
||||
interval: 300
|
||||
onTriggered: {
|
||||
webView.visible = !Wallpaper.visualsPaused
|
||||
txtVisualsPaused.visible = Wallpaper.visualsPaused
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
function onReloadVideo(oldType) {
|
||||
webView.runJavaScript(root.getSetVideoCommand())
|
||||
}
|
||||
|
||||
function onQmlExit() {
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;")
|
||||
}
|
||||
|
||||
function onMutedChanged(muted) {
|
||||
if (muted)
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = 0;")
|
||||
else
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + Wallpaper.volume + ";")
|
||||
}
|
||||
|
||||
function onFillModeChanged(fillMode) {
|
||||
if (webView.loadProgress === 100)
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.setAttribute('style', 'object-fit :" + fillMode + ";');")
|
||||
}
|
||||
|
||||
function onLoopsChanged(loops) {
|
||||
if (webView.loadProgress === 100)
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.loop = " + loops + ";")
|
||||
}
|
||||
|
||||
function onVolumeChanged(volume) {
|
||||
if (webView.loadProgress === 100)
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.volume = " + volume + ";")
|
||||
}
|
||||
|
||||
function onCurrentTimeChanged(currentTime) {
|
||||
if (webView.loadProgress === 100)
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.currentTime = "
|
||||
+ currentTime + " * videoPlayer.duration;")
|
||||
}
|
||||
|
||||
function onPlaybackRateChanged(playbackRate) {
|
||||
if (webView.loadProgress === 100)
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.playbackRate = " + playbackRate + ";")
|
||||
}
|
||||
|
||||
function onVisualsPausedChanged(visualsPaused) {
|
||||
if (visualsPaused) {
|
||||
// Wait until Wallpaper animation is finsihed
|
||||
timerCover.restart()
|
||||
} else {
|
||||
webView.visible = true
|
||||
txtVisualsPaused.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
function onIsPlayingChanged(isPlaying) {
|
||||
if (webView.loadProgress === 100) {
|
||||
if (isPlaying)
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.play();")
|
||||
else
|
||||
webView.runJavaScript(
|
||||
"var videoPlayer = document.getElementById('videoPlayer'); videoPlayer.pause();")
|
||||
}
|
||||
}
|
||||
|
||||
target: Wallpaper
|
||||
}
|
||||
}
|
@ -3,16 +3,31 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import ScreenPlayWallpaper 1.0
|
||||
import ScreenPlay.Enums.InstalledType 1.0
|
||||
import ScreenPlay.Enums.VideoCodec 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
onStateChanged: print(state)
|
||||
|
||||
property bool canFadeByWallpaperFillMode: true
|
||||
|
||||
function init() {
|
||||
print("init")
|
||||
switch (Wallpaper.type) {
|
||||
case InstalledType.VideoWallpaper:
|
||||
if(Wallpaper.videoCodec === VideoCodec.Unknown){
|
||||
Wallpaper.terminate()
|
||||
}
|
||||
if(Qt.platform.os === "osx") {
|
||||
// macOS only supports h264 via the native Qt MM
|
||||
if(Wallpaper.videoCodec === VideoCodec.VP8 || Wallpaper.videoCodec === VideoCodec.VP9){
|
||||
print(Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute))
|
||||
loader.source = "qrc:/qml/MultimediaWebView.qml";
|
||||
print(loader.status)
|
||||
}else {
|
||||
loader.source = "qrc:/qml/MultimediaView.qml";
|
||||
}
|
||||
}
|
||||
fadeIn();
|
||||
break;
|
||||
case InstalledType.HTMLWallpaper:
|
||||
@ -106,11 +121,11 @@ Rectangle {
|
||||
anchors.fill: parent
|
||||
// QML Engine deadlocks in 5.15.2 when a loader cannot load
|
||||
// an item. QApplication::quit(); waits for the destruction forever.
|
||||
asynchronous: true
|
||||
//asynchronous: true
|
||||
onStatusChanged: {
|
||||
if (loader.status === Loader.Error) {
|
||||
loader.source = "";
|
||||
Wallpaper.terminate();
|
||||
// Wallpaper.terminate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,12 @@ BaseWindow::BaseWindow(
|
||||
"InstalledType",
|
||||
"Error: only enums");
|
||||
|
||||
qmlRegisterUncreatableMetaObject(ScreenPlay::VideoCodec::staticMetaObject,
|
||||
"ScreenPlay.Enums.VideoCodec",
|
||||
1, 0,
|
||||
"VideoCodec",
|
||||
"Error: only enums");
|
||||
|
||||
qmlRegisterType<BaseWindow>("ScreenPlay.Wallpaper", 1, 0, "Wallpaper");
|
||||
|
||||
if (!appID.contains("appID=")) {
|
||||
@ -76,8 +82,33 @@ BaseWindow::BaseWindow(
|
||||
QApplication::exit(-4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (auto typeOpt = ScreenPlayUtil::getInstalledTypeFromString(project.value("type").toString())) {
|
||||
setType(typeOpt.value());
|
||||
|
||||
if (!project.contains("videoCodec") ) {
|
||||
qWarning("No videoCodec was specified inside the json object!");
|
||||
// QApplication::exit(-4);
|
||||
const QString filename = project.value("file").toString();
|
||||
qInfo() << filename;
|
||||
if(filename.endsWith(".mp4")){
|
||||
setVideoCodec(ScreenPlay::VideoCodec::VideoCodec::H264);
|
||||
} else if(filename.endsWith(".webm")){
|
||||
setVideoCodec(ScreenPlay::VideoCodec::VideoCodec::VP8);
|
||||
}
|
||||
} else {
|
||||
if(this->type() == ScreenPlay::InstalledType::InstalledType::VideoWallpaper){
|
||||
if (auto videoCodecOpt = ScreenPlayUtil::getVideoCodecFromString(project.value("videoCodec").toString())) {
|
||||
setVideoCodec(videoCodecOpt.value());
|
||||
} else {
|
||||
qCritical() << "Cannot parse Wallpaper video codec from value" << project.value("type");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
qCritical() << "Cannot parse Wallpaper type from value" << project.value("type");
|
||||
}
|
||||
@ -239,3 +270,16 @@ void BaseWindow::setupLiveReloading()
|
||||
QObject::connect(&m_liveReloadLimiter, &QTimer::timeout, this, reloadQMLLambda);
|
||||
m_fileSystemWatcher.addPaths({ QUrl::fromUserInput(projectPath()).toLocalFile() });
|
||||
}
|
||||
|
||||
ScreenPlay::VideoCodec::VideoCodec BaseWindow::videoCodec() const
|
||||
{
|
||||
return m_videoCodec;
|
||||
}
|
||||
|
||||
void BaseWindow::setVideoCodec(ScreenPlay::VideoCodec::VideoCodec newVideoCodec)
|
||||
{
|
||||
if (m_videoCodec == newVideoCodec)
|
||||
return;
|
||||
m_videoCodec = newVideoCodec;
|
||||
emit videoCodecChanged();
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ public:
|
||||
Q_PROPERTY(float currentTime READ currentTime WRITE setCurrentTime NOTIFY currentTimeChanged)
|
||||
|
||||
Q_PROPERTY(ScreenPlay::InstalledType::InstalledType type READ type WRITE setType NOTIFY typeChanged)
|
||||
Q_PROPERTY(ScreenPlay::VideoCodec::VideoCodec videoCodec READ videoCodec WRITE setVideoCodec NOTIFY videoCodecChanged)
|
||||
Q_PROPERTY(QString OSVersion READ OSVersion WRITE setOSVersion NOTIFY OSVersionChanged)
|
||||
|
||||
Q_PROPERTY(ScreenPlaySDK* sdk READ sdk WRITE setSdk NOTIFY sdkChanged)
|
||||
@ -117,6 +118,9 @@ public:
|
||||
const QString& projectSourceFile() const { return m_projectSourceFile; }
|
||||
const QUrl& projectSourceFileAbsolute() const { return m_projectSourceFileAbsolute; }
|
||||
|
||||
ScreenPlay::VideoCodec::VideoCodec videoCodec() const;
|
||||
void setVideoCodec(ScreenPlay::VideoCodec::VideoCodec newVideoCodec);
|
||||
|
||||
signals:
|
||||
void qmlExit();
|
||||
void reloadQML(const ScreenPlay::InstalledType::InstalledType oldType);
|
||||
@ -146,6 +150,8 @@ signals:
|
||||
void projectSourceFileChanged(const QString& projectSourceFile);
|
||||
void projectSourceFileAbsoluteChanged(const QUrl& rojectSourceFileAbsolute);
|
||||
|
||||
void videoCodecChanged();
|
||||
|
||||
public slots:
|
||||
virtual void destroyThis() { }
|
||||
virtual void setVisible(bool show) { Q_UNUSED(show) }
|
||||
@ -385,4 +391,5 @@ private:
|
||||
QSysInfo m_sysinfo;
|
||||
std::unique_ptr<ScreenPlaySDK> m_sdk;
|
||||
QUrl m_projectSourceFileAbsolute;
|
||||
ScreenPlay::VideoCodec::VideoCodec m_videoCodec = ScreenPlay::VideoCodec::VideoCodec::Unknown;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user