audiowrapper_qtmultimedia.cpp 8.5 KB
Newer Older
1
2
3
/*
 * Copyright 2017 Matthieu Gallien <matthieu_gallien@yahoo.fr>
 *
4
5
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
6
7
8
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
9
 * This program is distributed in the hope that it will be useful,
10
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Lesser General Public License for more details.
13
 *
14
15
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17
18
 */

#include "audiowrapper.h"
19
#include "powermanagementinterface.h"
20

21
22
#include "qtMultimediaLogging.h"

23
#include <QTimer>
24
#include <QAudio>
25
26
27
28
29
30
31
32

#include "config-upnp-qt.h"

class AudioWrapperPrivate
{

public:

33
34
    PowerManagementInterface mPowerInterface;

35
36
    QMediaPlayer mPlayer;

37
38
39
40
41
42
    qint64 mSavedPosition = 0.0;

    qint64 mUndoSavedPosition = 0.0;

    bool mHasSavedPosition = false;

43
44
};

45
AudioWrapper::AudioWrapper(QObject *parent) : QObject(parent), d(std::make_unique<AudioWrapperPrivate>())
46
{
47
    connect(&d->mPlayer, &QMediaPlayer::mutedChanged, this, &AudioWrapper::playerMutedChanged);
48
49
50
    connect(&d->mPlayer, &QMediaPlayer::volumeChanged, this, &AudioWrapper::playerVolumeChanged);
    connect(&d->mPlayer, &QMediaPlayer::mediaChanged, this, &AudioWrapper::sourceChanged);
    connect(&d->mPlayer, &QMediaPlayer::mediaStatusChanged, this, &AudioWrapper::statusChanged);
51
    connect(&d->mPlayer, &QMediaPlayer::mediaStatusChanged, this, &AudioWrapper::mediaStatusChanged);
52
53
    connect(&d->mPlayer, &QMediaPlayer::stateChanged, this, &AudioWrapper::playbackStateChanged);
    connect(&d->mPlayer, &QMediaPlayer::stateChanged, this, &AudioWrapper::playerStateChanged);
Alexander Stippich's avatar
Alexander Stippich committed
54
    connect(&d->mPlayer, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), this, &AudioWrapper::errorChanged);
55
56
57
58
59
60
    connect(&d->mPlayer, &QMediaPlayer::durationChanged, this, &AudioWrapper::durationChanged);
    connect(&d->mPlayer, &QMediaPlayer::positionChanged, this, &AudioWrapper::positionChanged);
    connect(&d->mPlayer, &QMediaPlayer::seekableChanged, this, &AudioWrapper::seekableChanged);
}

AudioWrapper::~AudioWrapper()
61
= default;
62
63
64
65
66
67

bool AudioWrapper::muted() const
{
    return d->mPlayer.isMuted();
}

68
qreal AudioWrapper::volume() const
69
{
70
71
72
73
    auto realVolume = static_cast<qreal>(d->mPlayer.volume() / 100.0);
    auto userVolume = static_cast<qreal>(QAudio::convertVolume(realVolume, QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale));

    return userVolume * 100.0;
74
75
76
77
}

QUrl AudioWrapper::source() const
{
78
79
80
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
    return d->mPlayer.media().request().url();
#else
81
    return d->mPlayer.media().canonicalUrl();
82
#endif
83
84
}

85
QMediaPlayer::Error AudioWrapper::error() const
86
{
87
88
89
90
91
    if (d->mPlayer.error() != QMediaPlayer::NoError) {
        qDebug() << "AudioWrapper::error" << d->mPlayer.errorString();
    }

    return d->mPlayer.error();
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
}

qint64 AudioWrapper::duration() const
{
    return d->mPlayer.duration();
}

qint64 AudioWrapper::position() const
{
    return d->mPlayer.position();
}

bool AudioWrapper::seekable() const
{
    return d->mPlayer.isSeekable();
}

QMediaPlayer::State AudioWrapper::playbackState() const
{
    return d->mPlayer.state();
}

QMediaPlayer::MediaStatus AudioWrapper::status() const
{
    return d->mPlayer.mediaStatus();
}

void AudioWrapper::setMuted(bool muted)
{
    d->mPlayer.setMuted(muted);
}

124
void AudioWrapper::setVolume(qreal volume)
125
{
126
127
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::setVolume" << volume;

128
129
    auto realVolume = static_cast<qreal>(QAudio::convertVolume(volume / 100.0, QAudio::LogarithmicVolumeScale, QAudio::LinearVolumeScale));
    d->mPlayer.setVolume(qRound(realVolume * 100));
130
131
}

132
void AudioWrapper::setSource(const QUrl &source)
133
{
134
135
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::setSource" << source;

136
137
138
139
140
    d->mPlayer.setMedia({source});
}

void AudioWrapper::setPosition(qint64 position)
{
141
142
143
144
145
146
147
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::setPosition" << position;

    if (d->mPlayer.duration() <= 0) {
        savePosition(position);
        return;
    }

148
149
150
151
152
    d->mPlayer.setPosition(position);
}

void AudioWrapper::play()
{
153
154
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::play";

155
    d->mPlayer.play();
156
157
158
159
160
161
162

    if (d->mHasSavedPosition) {
        qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerDurationSignalChanges" << "restore old position" << d->mSavedPosition;

        setPosition(d->mSavedPosition);
        d->mHasSavedPosition = false;
    }
163
164
165
166
}

void AudioWrapper::pause()
{
167
168
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::pause";

169
170
171
172
173
    d->mPlayer.pause();
}

void AudioWrapper::stop()
{
174
175
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::stop";

176
177
178
    d->mPlayer.stop();
}

179
void AudioWrapper::seek(qint64 position)
180
{
181
182
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::seek" << position;

183
184
185
    d->mPlayer.setPosition(position);
}

186
187
void AudioWrapper::mediaStatusChanged()
{
188
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::mediaStatusChanged";
189
190
}

191
192
void AudioWrapper::playerStateChanged()
{
193
194
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerStateChanged";

195
196
    switch(d->mPlayer.state())
    {
197
198
    case QMediaPlayer::State::StoppedState:
        Q_EMIT stopped();
199
        d->mPowerInterface.setPreventSleep(false);
200
201
202
        break;
    case QMediaPlayer::State::PlayingState:
        Q_EMIT playing();
203
        d->mPowerInterface.setPreventSleep(true);
204
205
206
        break;
    case QMediaPlayer::State::PausedState:
        Q_EMIT paused();
207
        d->mPowerInterface.setPreventSleep(false);
208
209
210
211
212
213
        break;
    }
}

void AudioWrapper::playerVolumeChanged()
{
214
215
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerVolumeChanged";

216
217
218
    QTimer::singleShot(0, [this]() {Q_EMIT volumeChanged();});
}

219
220
void AudioWrapper::playerMutedChanged()
{
221
222
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerMutedChanged";

223
    QTimer::singleShot(0, [this]() {Q_EMIT mutedChanged(muted());});
224
225
}

226
227
void AudioWrapper::playerStateSignalChanges(QMediaPlayer::State newState)
{
228
229
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerStateSignalChanges" << newState;

230
231
232
233
234
    QMetaObject::invokeMethod(this, [this, newState]() {Q_EMIT playbackStateChanged(newState);}, Qt::QueuedConnection);
}

void AudioWrapper::mediaStatusSignalChanges(QMediaPlayer::MediaStatus newStatus)
{
235
236
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::mediaStatusSignalChanges" << newStatus;

237
238
239
240
241
    QMetaObject::invokeMethod(this, [this, newStatus]() {Q_EMIT statusChanged(newStatus);}, Qt::QueuedConnection);
}

void AudioWrapper::playerDurationSignalChanges(qint64 newDuration)
{
242
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerDurationSignalChanges" << newDuration;
243

244
    QMetaObject::invokeMethod(this, [this, newDuration]() {Q_EMIT durationChanged(newDuration);}, Qt::QueuedConnection);
245
246
247
248
249
250
251
252
253
254
255
256
}

void AudioWrapper::playerPositionSignalChanges(qint64 newPosition)
{
    QMetaObject::invokeMethod(this, [this, newPosition]() {Q_EMIT positionChanged(newPosition);}, Qt::QueuedConnection);
}

void AudioWrapper::playerVolumeSignalChanges()
{
    QMetaObject::invokeMethod(this, [this]() {Q_EMIT volumeChanged();}, Qt::QueuedConnection);
}

257
void AudioWrapper::playerMutedSignalChanges(bool isMuted)
258
{
259
    QMetaObject::invokeMethod(this, [this, isMuted]() {Q_EMIT mutedChanged(isMuted);}, Qt::QueuedConnection);
260
261
262
263
264
265
266
}

void AudioWrapper::playerSeekableSignalChanges(bool isSeekable)
{
    QMetaObject::invokeMethod(this, [this, isSeekable]() {Q_EMIT seekableChanged(isSeekable);}, Qt::QueuedConnection);
}

267
268
void AudioWrapper::saveUndoPosition(qint64 position)
{
269
270
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::saveUndoPosition" << position;

271
272
273
274
275
    d->mUndoSavedPosition = position;
}

void AudioWrapper::restoreUndoPosition()
{
276
277
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::restoreUndoPosition";

278
279
280
281
282
283
    d->mHasSavedPosition = true;
    d->mSavedPosition = d->mUndoSavedPosition;
}

void AudioWrapper::savePosition(qint64 position)
{
284
285
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::savePosition" << position;

286
287
288
    if (!d->mHasSavedPosition) {
        d->mHasSavedPosition = true;
        d->mSavedPosition = position;
289
        qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::savePosition" << "restore old position" << d->mSavedPosition;
290
291
292
    }
}

293
294

#include "moc_audiowrapper.cpp"