8#include <QMimeDatabase>
9#include <QtCore/qloggingcategory.h>
10#include <QMediaDevices>
13#include <QMimeDatabase>
35 m_videoElement = videoElement;
38emscripten::val QWasmAudioOutput::videoElement()
40 return m_videoElement;
45 emscripten::val realElement = videoElement();
46 if (!realElement.isUndefined()) {
47 realElement.set(
"muted",
muted);
50 if (m_audio.isUndefined() || m_audio.isNull()) {
51 qCDebug(qWasmMediaAudioOutput) <<
"Error"
52 <<
"Audio element could not be created";
57 m_audio.set(
"mute",
muted);
63 emscripten::val realElement = videoElement();
64 if (!realElement.isUndefined()) {
65 realElement.set(
"volume",
volume);
68 if (m_audio.isUndefined() || m_audio.isNull()) {
69 qCDebug(qWasmMediaAudioOutput) <<
"Error"
70 <<
"Audio element not available";
76 m_audio.set(
"volume",
volume);
89 if (m_audio.isUndefined() || m_audio.isNull()) {
90 qCDebug(qWasmMediaAudioOutput) <<
"Error"
91 <<
"Audio element could not be created";
97 emscripten::val document = emscripten::val::global(
"document");
98 emscripten::val body = document[
"body"];
102 body.call<
void>(
"appendChild", m_audio);
106 qCDebug(qWasmMediaAudioOutput) <<
"is localfile";
109 QFile mediaFile(m_source);
111 qCDebug(qWasmMediaAudioOutput) <<
"Error"
112 <<
"Media file could not be opened";
125 emscripten::val contentUrl =
126 qstdweb::window()[
"URL"].call<emscripten::val>(
"createObjectURL", contentBlob.val());
128 emscripten::val audioSourceElement =
129 document.call<emscripten::val>(
"createElement", std::string(
"source"));
131 audioSourceElement.set(
"src", contentUrl);
137 audioSourceElement.set(
"type",
mimeType.name().toStdString());
138 m_audio.call<
void>(
"appendChild", audioSourceElement);
140 m_audio.call<
void>(
"setAttribute", emscripten::val(
"srcObject"), contentUrl);
148 body.call<
void>(
"appendChild", m_audio);
151 doElementCallbacks();
161 if (m_audio.isNull() || m_audio.isUndefined()) {
162 qCDebug(qWasmMediaAudioOutput) <<
"audio failed to start";
168 m_audio.call<
void>(
"play");
173 if (m_audio.isNull() || m_audio.isUndefined()) {
174 qCDebug(qWasmMediaAudioOutput) <<
"audio failed to start";
181 m_audio.set(
"currentTime", emscripten::val(0));
183 if (m_audioIODevice) {
184 m_audioIODevice->
close();
185 delete m_audioIODevice;
192 if (m_audio.isNull() || m_audio.isUndefined()) {
193 qCDebug(qWasmMediaAudioOutput) <<
"audio failed to start";
198 m_audio.call<emscripten::val>(
"pause");
201void QWasmAudioOutput::createAudioElement(
const std::string &
id)
203 emscripten::val document = emscripten::val::global(
"document");
204 m_audio = document.call<emscripten::val>(
"createElement", std::string(
"audio"));
210 if (!m_audio.hasOwnProperty(
"sinkId") || m_audio[
"sinkId"].isUndefined()) {
214 std::string usableId =
id;
215 if (usableId.empty())
219 .
thenFunc = [](emscripten::val) {
qCWarning(qWasmMediaAudioOutput) <<
"setSinkId ok"; },
221 [](emscripten::val) {
222 qCWarning(qWasmMediaAudioOutput) <<
"Error while trying to setSinkId";
227 m_audio.set(
"id", usableId.c_str());
230void QWasmAudioOutput::doElementCallbacks()
233 auto errorCallback = [&](emscripten::val
event) {
234 qCDebug(qWasmMediaAudioOutput) <<
"error";
243 switch (m_audio[
"error"][
"code"].as<int>()) {
265 auto loadedDataCallback = [&](emscripten::val
event) {
267 qCDebug(qWasmMediaAudioOutput) <<
"loaded data";
268 qstdweb::window()[
"URL"].call<emscripten::val>(
"revokeObjectURL", m_audio[
"src"]);
273 auto canPlayCallback = [&](emscripten::val
event) {
274 if (
event.isUndefined() ||
event.isNull())
276 qCDebug(qWasmMediaAudioOutput) <<
"can play";
283 auto canPlayThroughCallback = [&](emscripten::val
event) {
287 m_canPlayThroughChangeEvent.
reset(
291 auto playCallback = [&](emscripten::val
event) {
293 qCDebug(qWasmMediaAudioOutput) <<
"play";
299 auto durationChangeCallback = [&](emscripten::val
event) {
300 qCDebug(qWasmMediaAudioOutput) <<
"durationChange";
305 m_durationChangeEvent.
reset(
309 auto endedCallback = [&](emscripten::val
event) {
311 qCDebug(qWasmMediaAudioOutput) <<
"ended";
318 auto progesssCallback = [&](emscripten::val
event) {
319 if (
event.isUndefined() ||
event.isNull())
321 qCDebug(qWasmMediaAudioOutput) <<
"progress";
322 float duration =
event[
"target"][
"duration"].as<
int>();
326 emscripten::val timeRanges =
event[
"target"][
"buffered"];
328 if ((!timeRanges.isNull() || !timeRanges.isUndefined())
329 && timeRanges[
"length"].as<
int>() == 1) {
330 emscripten::val dVal = timeRanges.call<emscripten::val>(
"end", 0);
332 if (!dVal.isNull() || !dVal.isUndefined()) {
333 double bufferedEnd = dVal.as<
double>();
335 if (duration > 0 && bufferedEnd > 0) {
336 float bufferedValue = (bufferedEnd / duration * 100);
337 qCDebug(qWasmMediaAudioOutput) <<
"progress buffered" << bufferedValue;
340 if (bufferedEnd == duration)
353 auto timeUpdateCallback = [&](emscripten::val
event) {
355 <<
"timeupdate" << (
event[
"target"][
"currentTime"].as<
double>() * 1000);
363 auto pauseCallback = [&](emscripten::val
event) {
365 qCDebug(qWasmMediaAudioOutput) <<
"pause";
367 int currentTime = m_audio[
"currentTime"].as<
int>();
368 int duration = m_audio[
"duration"].as<
int>();
The QAudioDevice class provides an information about audio devices and their functionality.
QByteArray id
\qmlproperty string QtMultimedia::audioDevice::id
\qmltype AudioOutput \instantiates QAudioOutput
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
std::string toStdString() const
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
\inmodule QtCore \reentrant
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
QMimeType mimeTypeForData(const QByteArray &data) const
Returns a MIME type for data.
QMimeType mimeTypeForFile(const QString &fileName, MatchMode mode=MatchDefault) const
Returns a MIME type for the file named fileName using mode.
QString name
the name of the MIME type
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromStdString(const std::string &s)
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
std::string toStdString() const
Returns a std::string object with the data contained in this QString.
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
void progressChanged(qint32 position)
void bufferingChanged(qint32 percent)
void errorOccured(qint32 code, const QString &message)
void setMuted(bool muted) override
void stateChanged(QWasmMediaPlayer::QWasmMediaPlayerState newState)
void statusChanged(QMediaPlayer::MediaStatus status)
void setVideoElement(emscripten::val videoElement)
@ MEDIA_ERR_SRC_NOT_SUPPORTED
void durationChanged(qint64 duration)
void setVolume(float volume) override
void setAudioDevice(const QAudioDevice &device) final
void setSource(const QUrl &url)
static Blob copyFrom(const char *buffer, uint32_t size, std::string mimeType)
Combined button and popup list for selecting options.
void make(emscripten::val target, QString methodName, PromiseCallbacks callbacks, Args... args)
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qBound(const T &min, const T &val, const T &max)
#define QStringLiteral(str)
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
static double currentTime()
QUrl url("example.com")
[constructor-url-reference]
std::function< void(emscripten::val)> thenFunc