#include "mediaparticlewidget.h" #include "../models.h" #include "../networkmanager.h" #include #include #include #include #include #include #include #include MediaParticleWidget::MediaParticleWidget(QWidget *parent) : QWidget(parent) { m_nam = new QNetworkAccessManager(this); // To prevent our network request from fetching bytes in memory m_nam->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy); auto *layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(2); m_videoWidget = new QVideoWidget(); m_videoWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); layout->addWidget(m_videoWidget); m_durationLabel = new QLabel(); m_durationLabel->setAlignment(Qt::AlignCenter); layout->addWidget(m_durationLabel); m_player = new QMediaPlayer(this); m_audioOutput = new QAudioOutput(this); m_player->setAudioOutput(m_audioOutput); m_player->setVideoOutput(m_videoWidget); m_player->setLoops(QMediaPlayer::Infinite); connect(m_player, &QMediaPlayer::durationChanged, this, [this](qint64 duration) { if (duration > 0) { int secs = static_cast(duration / 1000); int mins = secs / 60; secs = secs % 60; m_durationLabel->setText(QString("%1:%2").arg(mins).arg(secs, 2, 10, QChar('0'))); } }); } void MediaParticleWidget::setParticle(const Particle *particle) { if (!particle) return; clear(); fetchAndPlay(particle->id); } void MediaParticleWidget::clear() { m_player->stop(); m_player->setSource(QUrl()); m_durationLabel->setText(""); } void MediaParticleWidget::fetchAndPlay(const QString &particleId) { QNetworkRequest request = NetworkManager::instance().buildRequest("/particles/" + particleId + "/download"); QNetworkReply *reply = m_nam->get(request); connect(reply, &QNetworkReply::finished, this, [this, reply]() { reply->deleteLater(); if (reply->error() != QNetworkReply::NoError) { qWarning() << "MediaParticleWidget: download request failed:" << reply->errorString(); return; } // m_nam uses ManualRedirectPolicy, so the reply stops at the 3xx // without downloading the media. Extract the pre-signed URL from Location. QUrl mediaUrl = reply->header(QNetworkRequest::LocationHeader).toUrl(); if (!mediaUrl.isValid()) { qWarning() << "MediaParticleWidget: no Location header in download response"; return; } if (mediaUrl.isRelative()) { mediaUrl = reply->url().resolved(mediaUrl); } m_player->setSource(mediaUrl); m_player->play(); }); }