initial bits to make a ytdl addition
This commit is contained in:
parent
405a310e02
commit
666c22ae66
12 changed files with 353 additions and 1 deletions
|
|
@ -53,6 +53,7 @@
|
|||
#include "cxx-qt-gen/slide_obj.cxxqt.h"
|
||||
#include "cxx-qt-gen/slide_model.cxxqt.h"
|
||||
#include "cxx-qt-gen/settings.cxxqt.h"
|
||||
#include "cxx-qt-gen/ytdl.cxxqt.h"
|
||||
// #include "cxx-qt-gen/image_model.cxxqt.h"
|
||||
|
||||
static QWindow *windowFromEngine(QQmlApplicationEngine *engine)
|
||||
|
|
@ -203,6 +204,7 @@ int main(int argc, char *argv[])
|
|||
qmlRegisterType<ImageSqlModel>("org.presenter", 1, 0, "ImageSqlModel");
|
||||
qmlRegisterType<PresentationSqlModel>("org.presenter", 1, 0, "PresentationSqlModel");
|
||||
qmlRegisterType<FileHelper>("org.presenter", 1, 0, "FileHelper");
|
||||
qmlRegisterType<Ytdl>("org.presenter", 1, 0, "Ytdl");
|
||||
qmlRegisterType<ServiceThing>("org.presenter", 1, 0, "ServiceThing");
|
||||
qmlRegisterType<SlideObject>("org.presenter", 1, 0, "SlideHelper");
|
||||
qmlRegisterSingletonInstance("org.presenter", 1, 0,
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ Item {
|
|||
count: innerModel.count()
|
||||
newItemFunction: (function() {
|
||||
videoProxyModel.setFilterRegularExpression("");
|
||||
newVideo.open();
|
||||
})
|
||||
deleteItemFunction: (function(rows) {
|
||||
videoProxyModel.deleteVideos(rows)
|
||||
|
|
@ -75,6 +76,19 @@ Item {
|
|||
|
||||
}
|
||||
|
||||
Presenter.NewVideo {
|
||||
id: newVideo
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: videoDLTimer
|
||||
interval: 3000
|
||||
running: !newVideo.sheetOpen
|
||||
onTriggered: {
|
||||
newVideo.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Presenter.LibraryItem {
|
||||
id: imageLibrary
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
|
|
|||
133
src/qml/presenter/NewVideo.qml
Normal file
133
src/qml/presenter/NewVideo.qml
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as Controls
|
||||
import QtQuick.Dialogs 1.3
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import org.kde.kirigami 2.13 as Kirigami
|
||||
import "./" as Presenter
|
||||
import org.presenter 1.0
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
Kirigami.OverlaySheet {
|
||||
id: root
|
||||
|
||||
property bool ytdlLoaded: false
|
||||
|
||||
header: Kirigami.Heading {
|
||||
text: "Add a new video"
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Controls.ToolBar {
|
||||
id: toolbar
|
||||
Layout.fillWidth: true
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
Controls.Label {
|
||||
id: videoInputLabel
|
||||
text: "Enter a video"
|
||||
}
|
||||
|
||||
Controls.TextField {
|
||||
id: videoInput
|
||||
Layout.fillWidth: true
|
||||
hoverEnabled: true
|
||||
placeholderText: "Enter a video url..."
|
||||
text: ""
|
||||
onEditingFinished: videoInput.text.startsWith("http") ? loadVideo() : showPassiveNotification("Coach called, this isn't it.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: centerItem
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 25
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
visible: true
|
||||
|
||||
Controls.BusyIndicator {
|
||||
id: loadingIndicator
|
||||
anchors.centerIn: parent
|
||||
running: ytdl.loading
|
||||
}
|
||||
|
||||
Ytdl {
|
||||
id: ytdl
|
||||
loaded: false
|
||||
loading: false
|
||||
}
|
||||
|
||||
/* Rectangle { */
|
||||
/* color: "blue" */
|
||||
/* anchors.fill: parent */
|
||||
/* } */
|
||||
ColumnLayout {
|
||||
id: loadedItem
|
||||
anchors.fill: parent
|
||||
visible: ytdl.loaded
|
||||
Image {
|
||||
id: thumbnailImage
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: width * 9 / 16
|
||||
source: ytdl.thumbnail
|
||||
fillMode: Image.PreserveAspectFit
|
||||
clip: true
|
||||
|
||||
Item {
|
||||
id: mask
|
||||
anchors.fill: thumbnailImage
|
||||
visible: false
|
||||
|
||||
Rectangle {
|
||||
color: "white"
|
||||
radius: 20
|
||||
anchors.centerIn: parent
|
||||
width: thumbnailImage.paintedWidth
|
||||
height: thumbnailImage.paintedHeight
|
||||
}
|
||||
}
|
||||
OpacityMask {
|
||||
anchors.fill: thumbnailImage
|
||||
source: thumbnailImage
|
||||
maskSource: mask
|
||||
}
|
||||
|
||||
}
|
||||
Item {
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Controls.Label {
|
||||
id: videoTitle
|
||||
text: ytdl.title
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
||||
Controls.Button {
|
||||
anchors.right: parent.right
|
||||
text: "Ok"
|
||||
onClicked: { clear(); root.close();}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function loadVideo() {
|
||||
if (ytdl.getVideo(videoInput.text))
|
||||
loadingIndicator.visible = true;
|
||||
}
|
||||
|
||||
function clear() {
|
||||
ytdl.title = "";
|
||||
ytdl.thumbnail = "";
|
||||
ytdl.loaded = false;
|
||||
ytdl.loading = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import QtQuick.Layouts 1.15
|
|||
import org.kde.kirigami 2.13 as Kirigami
|
||||
import "./" as Presenter
|
||||
import mpv 1.0
|
||||
import org.presenter 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
<file>qml/presenter/PreviewSlide.qml</file>
|
||||
<file>qml/presenter/Settings.qml</file>
|
||||
<file>qml/presenter/RangedSlider.qml</file>
|
||||
<file>qml/presenter/NewVideo.qml</file>
|
||||
<file>assets/parallel.jpg</file>
|
||||
<file>assets/black.jpg</file>
|
||||
</qresource>
|
||||
|
|
|
|||
|
|
@ -8,4 +8,5 @@ mod settings;
|
|||
mod slide_model;
|
||||
mod slide_obj;
|
||||
pub mod video_model;
|
||||
pub mod ytdl;
|
||||
// mod video_thumbnail;
|
||||
|
|
|
|||
69
src/rust/ytdl.rs
Normal file
69
src/rust/ytdl.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#[cxx_qt::bridge]
|
||||
mod ytdl {
|
||||
use dirs;
|
||||
use std::{fs, thread};
|
||||
use youtube_dl::YoutubeDl;
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("cxx-qt-lib/qurl.h");
|
||||
type QUrl = cxx_qt_lib::QUrl;
|
||||
include!("cxx-qt-lib/qstring.h");
|
||||
type QString = cxx_qt_lib::QString;
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[cxx_qt::qobject]
|
||||
pub struct Ytdl {
|
||||
#[qproperty]
|
||||
title: QString,
|
||||
#[qproperty]
|
||||
thumbnail: QUrl,
|
||||
#[qproperty]
|
||||
loaded: bool,
|
||||
#[qproperty]
|
||||
loading: bool,
|
||||
}
|
||||
|
||||
impl qobject::Ytdl {
|
||||
#[qinvokable]
|
||||
pub fn get_video(mut self: Pin<&mut Self>, url: QUrl) -> bool {
|
||||
if !url.is_valid() {
|
||||
false
|
||||
} else {
|
||||
let data_dir = dirs::data_local_dir().unwrap();
|
||||
if let Some(mut data_dir) = dirs::data_local_dir() {
|
||||
data_dir.push("librepresenter");
|
||||
data_dir.push("ytdl");
|
||||
if !data_dir.exists() {
|
||||
fs::create_dir(&data_dir);
|
||||
}
|
||||
println!("{:?}", data_dir);
|
||||
}
|
||||
self.as_mut().set_loading(true);
|
||||
let thread = self.qt_thread();
|
||||
thread::spawn(move || {
|
||||
let url = url.to_string();
|
||||
let output_dirs = "/home/chris/Videos/";
|
||||
let ytdl = YoutubeDl::new(url)
|
||||
.socket_timeout("15")
|
||||
.output_directory(output_dirs)
|
||||
.download(true)
|
||||
.run()
|
||||
.unwrap();
|
||||
let output = ytdl.into_single_video().unwrap();
|
||||
println!("{:?}", output.title);
|
||||
println!("{:?}", output.thumbnail);
|
||||
let title = QString::from(&output.title);
|
||||
let thumbnail = QUrl::from(&output.thumbnail.unwrap());
|
||||
thread.queue(move |mut qobject_ytdl| {
|
||||
qobject_ytdl.as_mut().set_loaded(true);
|
||||
qobject_ytdl.as_mut().set_loading(false);
|
||||
qobject_ytdl.as_mut().set_title(title);
|
||||
qobject_ytdl.as_mut().set_thumbnail(thumbnail);
|
||||
})
|
||||
});
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue