153 lines
4.3 KiB
C++
153 lines
4.3 KiB
C++
#include "mediaparticlegenerator.h"
|
|
#include "networkmanager.h"
|
|
#include "store.h"
|
|
#include <QFile>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QNetworkAccessManager>
|
|
#include <QNetworkReply>
|
|
#include <QNetworkRequest>
|
|
|
|
MediaParticleGenerator::MediaParticleGenerator(Store *store, QObject *parent)
|
|
: QObject{parent}, m_store{store}, m_qnam{new QNetworkAccessManager{this}}
|
|
{
|
|
}
|
|
|
|
bool MediaParticleGenerator::isGenerating() const
|
|
{
|
|
return m_isGenerating;
|
|
}
|
|
|
|
void MediaParticleGenerator::generate(const QUrl &url, const QString &mimeType, const QString &networkId, qint64 durationMs, const QString &streamId)
|
|
{
|
|
if (m_isGenerating)
|
|
{
|
|
qWarning() << "Already generating media particle, ignoring request";
|
|
return;
|
|
}
|
|
if (!url.isValid())
|
|
{
|
|
emit errorOccurred("Invalid URL");
|
|
return;
|
|
}
|
|
|
|
assert(!mimeType.isEmpty() && "mimeType should never be empty here");
|
|
assert(!networkId.isEmpty() && "networkId should never be empty here");
|
|
|
|
QFile *file = new QFile{url.toLocalFile()};
|
|
assert(file->exists() && "File should exist at this point");
|
|
assert(file->size() > 0 && "File should have non-zero size at this point");
|
|
|
|
cleanup();
|
|
setGenerating(true);
|
|
|
|
m_uploadInfo = new UploadInfo{};
|
|
m_uploadInfo->networkId = networkId;
|
|
m_uploadInfo->streamId = streamId;
|
|
m_uploadInfo->mimeType = mimeType;
|
|
m_uploadInfo->durationMs = durationMs;
|
|
m_uploadInfo->file = file;
|
|
m_uploadInfo->bytes = file->size();
|
|
|
|
// 1. get presigned url
|
|
QJsonObject body;
|
|
body["network_id"] = m_uploadInfo->networkId;
|
|
body["name"] = url.fileName();
|
|
body["content_type"] = m_uploadInfo->mimeType;
|
|
body["content_length"] = m_uploadInfo->bytes;
|
|
QNetworkReply *reply = NetworkManager::instance().post("/depot/upload", QJsonDocument(body));
|
|
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
|
reply->deleteLater();
|
|
|
|
if (reply->error() != QNetworkReply::NoError)
|
|
{
|
|
QByteArray body = reply->readAll();
|
|
QJsonDocument doc = QJsonDocument::fromJson(body);
|
|
QString message = doc.isObject() ? doc.object().value("message").toString() : QString();
|
|
if (message.isEmpty())
|
|
{
|
|
message = reply->errorString();
|
|
}
|
|
qWarning() << message;
|
|
cleanup();
|
|
emit errorOccurred("Failed to upload media");
|
|
return;
|
|
}
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
|
|
onUploadUrlReceived(doc);
|
|
});
|
|
}
|
|
|
|
void MediaParticleGenerator::cleanup()
|
|
{
|
|
if (m_uploadInfo)
|
|
{
|
|
if (m_uploadInfo->file)
|
|
{
|
|
m_uploadInfo->file->close();
|
|
delete m_uploadInfo->file;
|
|
}
|
|
delete m_uploadInfo;
|
|
m_uploadInfo = nullptr;
|
|
}
|
|
|
|
setGenerating(false);
|
|
}
|
|
|
|
void MediaParticleGenerator::onUploadUrlReceived(const QJsonDocument &response)
|
|
{
|
|
QJsonObject obj = response.object();
|
|
m_uploadInfo->uploadUrl = obj["upload_url"].toString();
|
|
QJsonObject uploadHeaders = obj["upload_headers"].toObject();
|
|
m_uploadInfo->objectId = obj["object_id"].toString();
|
|
|
|
if (!m_uploadInfo->file->open(QIODevice::ReadOnly))
|
|
{
|
|
cleanup();
|
|
emit errorOccurred("Failed to open media file");
|
|
return;
|
|
}
|
|
|
|
QNetworkRequest request = QNetworkRequest(QUrl(m_uploadInfo->uploadUrl));
|
|
for (auto it = uploadHeaders.constBegin(); it != uploadHeaders.constEnd(); ++it)
|
|
{
|
|
request.setRawHeader(it.key().toUtf8(), it.value().toString().toUtf8());
|
|
}
|
|
QNetworkReply *reply = m_qnam->put(request, m_uploadInfo->file);
|
|
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
|
reply->deleteLater();
|
|
|
|
if (reply->error() != QNetworkReply::NoError)
|
|
{
|
|
qWarning() << "Failed to upload media: " << reply->errorString();
|
|
cleanup();
|
|
emit errorOccurred("Failed to upload media");
|
|
return;
|
|
}
|
|
|
|
onUploadComplete();
|
|
});
|
|
}
|
|
|
|
void MediaParticleGenerator::setGenerating(bool generating)
|
|
{
|
|
if (m_isGenerating != generating)
|
|
{
|
|
m_isGenerating = generating;
|
|
emit isGeneratingChanged();
|
|
}
|
|
}
|
|
|
|
void MediaParticleGenerator::onUploadComplete()
|
|
{
|
|
auto op = m_store->createParticle(m_uploadInfo->streamId, "media", {
|
|
{"object_id", m_uploadInfo->objectId},
|
|
{"duration_ms", m_uploadInfo->durationMs},
|
|
{"mime_type", m_uploadInfo->mimeType}
|
|
});
|
|
|
|
connect(op, &Operation::success, this, &MediaParticleGenerator::complete);
|
|
connect(op, &Operation::success, this, &MediaParticleGenerator::cleanup);
|
|
}
|