Files
llink/cpp/src/mediaparticlegenerator.cpp

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);
}