Skip to content

Commit aed5220

Browse files
committed
Add PreviewSoundPlayer
1 parent c564324 commit aed5220

3 files changed

Lines changed: 203 additions & 0 deletions

File tree

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#include "PreviewSoundPlayer.h"
2+
#include "PreviewSoundPlayer_p.h"
3+
4+
#include <QMetaObject>
5+
#include <QPointer>
6+
7+
#include <atomic>
8+
9+
#include <TalcsCore/AudioSource.h>
10+
#include <TalcsCore/MixerAudioSource.h>
11+
#include <TalcsFormat/AbstractAudioFormatIO.h>
12+
#include <TalcsFormat/AudioFormatInputSource.h>
13+
14+
#include <audio/GlobalAudioContext.h>
15+
16+
namespace Audio {
17+
18+
class PreviewSoundFinishedFilter final : public talcs::AudioSource {
19+
public:
20+
PreviewSoundFinishedFilter(PreviewSoundPlayer *player, PreviewSoundPlayerPrivate *playerPrivate,
21+
talcs::AudioFormatInputSource *source, quint64 serial)
22+
: m_player(player), m_playerPrivate(playerPrivate), m_source(source), m_serial(serial) {
23+
}
24+
25+
protected:
26+
qint64 processReading(const talcs::AudioSourceReadData &readData) override {
27+
if (m_finished.load()) {
28+
return readData.length;
29+
}
30+
31+
if (!m_source || m_source->nextReadPosition() < m_source->length()) {
32+
return readData.length;
33+
}
34+
35+
if (!m_finished.exchange(true)) {
36+
auto player = m_player;
37+
auto playerPrivate = m_playerPrivate;
38+
auto source = m_source;
39+
auto serial = m_serial;
40+
QMetaObject::invokeMethod(player, [playerPrivate, source, serial] {
41+
playerPrivate->finish(source, serial);
42+
}, Qt::QueuedConnection);
43+
}
44+
return readData.length;
45+
}
46+
47+
private:
48+
PreviewSoundPlayer *m_player{};
49+
PreviewSoundPlayerPrivate *m_playerPrivate{};
50+
talcs::AudioFormatInputSource *m_source{};
51+
quint64 m_serial{};
52+
std::atomic_bool m_finished{false};
53+
};
54+
55+
PreviewSoundPlayerPrivate::PreviewSoundPlayerPrivate(talcs::AbstractAudioFormatIO *audioFormatIo)
56+
: audioFormatIo(audioFormatIo) {
57+
}
58+
59+
PreviewSoundPlayerPrivate::~PreviewSoundPlayerPrivate() = default;
60+
61+
void PreviewSoundPlayerPrivate::destroySource(talcs::AudioFormatInputSource *expectedSource) {
62+
if (!source || (expectedSource && source.get() != expectedSource)) {
63+
return;
64+
}
65+
66+
auto oldSource = std::move(source);
67+
auto oldFilter = std::move(finishedFilter);
68+
++serial;
69+
70+
GlobalAudioContext::preMixer()->removeSource(oldSource.get());
71+
oldSource->close();
72+
oldSource->setReadingFilter(nullptr);
73+
oldFilter.reset();
74+
}
75+
76+
void PreviewSoundPlayerPrivate::finish(talcs::AudioFormatInputSource *source, quint64 serial) {
77+
Q_Q(PreviewSoundPlayer);
78+
if (this->serial != serial || this->source.get() != source) {
79+
return;
80+
}
81+
82+
QPointer<PreviewSoundPlayer> guard(q);
83+
Q_EMIT q->finished();
84+
if (!guard) {
85+
return;
86+
}
87+
destroySource(source);
88+
}
89+
90+
PreviewSoundPlayer::PreviewSoundPlayer(talcs::AbstractAudioFormatIO *audioFormatIo, QObject *parent)
91+
: QObject(parent), d_ptr(new PreviewSoundPlayerPrivate(audioFormatIo)) {
92+
Q_D(PreviewSoundPlayer);
93+
d->q_ptr = this;
94+
}
95+
96+
PreviewSoundPlayer::~PreviewSoundPlayer() {
97+
stop();
98+
}
99+
100+
void PreviewSoundPlayer::play() {
101+
Q_D(PreviewSoundPlayer);
102+
d->destroySource();
103+
if (!d->audioFormatIo) {
104+
return;
105+
}
106+
107+
auto source = std::make_unique<talcs::AudioFormatInputSource>(d->audioFormatIo.get(), false);
108+
source->setNextReadPosition(0);
109+
110+
const auto serial = ++d->serial;
111+
auto filter = std::make_unique<PreviewSoundFinishedFilter>(this, d, source.get(), serial);
112+
source->setReadingFilter(filter.get());
113+
114+
if (!GlobalAudioContext::preMixer()->addSource(source.get(), false)) {
115+
source->close();
116+
source->setReadingFilter(nullptr);
117+
return;
118+
}
119+
120+
d->finishedFilter = std::move(filter);
121+
d->source = std::move(source);
122+
}
123+
124+
void PreviewSoundPlayer::stop() {
125+
Q_D(PreviewSoundPlayer);
126+
d->destroySource();
127+
}
128+
129+
}
130+
131+
#include "moc_PreviewSoundPlayer.cpp"
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifndef DIFFSCOPE_AUDIO_PREVIEWSOUNDPLAYER_H
2+
#define DIFFSCOPE_AUDIO_PREVIEWSOUNDPLAYER_H
3+
4+
#include <QObject>
5+
6+
#include <audio/audioglobal.h>
7+
8+
namespace talcs {
9+
class AbstractAudioFormatIO;
10+
}
11+
12+
namespace Audio {
13+
14+
class PreviewSoundPlayerPrivate;
15+
16+
class AUDIO_EXPORT PreviewSoundPlayer : public QObject {
17+
Q_OBJECT
18+
Q_DECLARE_PRIVATE(PreviewSoundPlayer)
19+
20+
public:
21+
explicit PreviewSoundPlayer(talcs::AbstractAudioFormatIO *audioFormatIo, QObject *parent = nullptr);
22+
~PreviewSoundPlayer() override;
23+
24+
void play();
25+
void stop();
26+
27+
Q_SIGNALS:
28+
void finished();
29+
30+
private:
31+
QScopedPointer<PreviewSoundPlayerPrivate> d_ptr;
32+
};
33+
34+
}
35+
36+
using PreviewSoundPlayer = Audio::PreviewSoundPlayer;
37+
38+
#endif // DIFFSCOPE_AUDIO_PREVIEWSOUNDPLAYER_H
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef DIFFSCOPE_AUDIO_PREVIEWSOUNDPLAYER_P_H
2+
#define DIFFSCOPE_AUDIO_PREVIEWSOUNDPLAYER_P_H
3+
4+
#include <audio/PreviewSoundPlayer.h>
5+
6+
#include <memory>
7+
8+
namespace talcs {
9+
class AudioFormatInputSource;
10+
}
11+
12+
namespace Audio {
13+
14+
class PreviewSoundFinishedFilter;
15+
16+
class PreviewSoundPlayerPrivate {
17+
Q_DECLARE_PUBLIC(PreviewSoundPlayer)
18+
public:
19+
explicit PreviewSoundPlayerPrivate(talcs::AbstractAudioFormatIO *audioFormatIo);
20+
~PreviewSoundPlayerPrivate();
21+
22+
void destroySource(talcs::AudioFormatInputSource *expectedSource = nullptr);
23+
void finish(talcs::AudioFormatInputSource *source, quint64 serial);
24+
25+
PreviewSoundPlayer *q_ptr{};
26+
std::unique_ptr<talcs::AbstractAudioFormatIO> audioFormatIo;
27+
std::unique_ptr<PreviewSoundFinishedFilter> finishedFilter;
28+
std::unique_ptr<talcs::AudioFormatInputSource> source;
29+
quint64 serial{};
30+
};
31+
32+
}
33+
34+
#endif // DIFFSCOPE_AUDIO_PREVIEWSOUNDPLAYER_P_H

0 commit comments

Comments
 (0)