audiowrapper_qtmultimedia.cpp 8.4 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
78
79
80
}

QUrl AudioWrapper::source() const
{
    return d->mPlayer.media().canonicalUrl();
}

81
QMediaPlayer::Error AudioWrapper::error() const
82
{
83
84
85
86
87
    if (d->mPlayer.error() != QMediaPlayer::NoError) {
        qDebug() << "AudioWrapper::error" << d->mPlayer.errorString();
    }

    return d->mPlayer.error();
88
89
90
91
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
}

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

120
void AudioWrapper::setVolume(qreal volume)
121
{
122
123
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::setVolume" << volume;

124
125
    auto realVolume = static_cast<qreal>(QAudio::convertVolume(volume / 100.0, QAudio::LogarithmicVolumeScale, QAudio::LinearVolumeScale));
    d->mPlayer.setVolume(qRound(realVolume * 100));
126
127
}

128
void AudioWrapper::setSource(const QUrl &source)
129
{
130
131
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::setSource" << source;

132
133
134
135
136
    d->mPlayer.setMedia({source});
}

void AudioWrapper::setPosition(qint64 position)
{
137
138
139
140
141
142
143
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::setPosition" << position;

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

144
145
146
147
148
    d->mPlayer.setPosition(position);
}

void AudioWrapper::play()
{
149
150
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::play";

151
    d->mPlayer.play();
152
153
154
155
156
157
158

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

        setPosition(d->mSavedPosition);
        d->mHasSavedPosition = false;
    }
159
160
161
162
}

void AudioWrapper::pause()
{
163
164
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::pause";

165
166
167
168
169
    d->mPlayer.pause();
}

void AudioWrapper::stop()
{
170
171
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::stop";

172
173
174
    d->mPlayer.stop();
}

175
void AudioWrapper::seek(qint64 position)
176
{
177
178
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::seek" << position;

179
180
181
    d->mPlayer.setPosition(position);
}

182
183
void AudioWrapper::mediaStatusChanged()
{
184
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::mediaStatusChanged";
185
186
}

187
188
void AudioWrapper::playerStateChanged()
{
189
190
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerStateChanged";

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

void AudioWrapper::playerVolumeChanged()
{
210
211
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerVolumeChanged";

212
213
214
    QTimer::singleShot(0, [this]() {Q_EMIT volumeChanged();});
}

215
216
void AudioWrapper::playerMutedChanged()
{
217
218
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerMutedChanged";

219
    QTimer::singleShot(0, [this]() {Q_EMIT mutedChanged(muted());});
220
221
}

222
223
void AudioWrapper::playerStateSignalChanges(QMediaPlayer::State newState)
{
224
225
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerStateSignalChanges" << newState;

226
227
228
229
230
    QMetaObject::invokeMethod(this, [this, newState]() {Q_EMIT playbackStateChanged(newState);}, Qt::QueuedConnection);
}

void AudioWrapper::mediaStatusSignalChanges(QMediaPlayer::MediaStatus newStatus)
{
231
232
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::mediaStatusSignalChanges" << newStatus;

233
234
235
236
237
    QMetaObject::invokeMethod(this, [this, newStatus]() {Q_EMIT statusChanged(newStatus);}, Qt::QueuedConnection);
}

void AudioWrapper::playerDurationSignalChanges(qint64 newDuration)
{
238
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerDurationSignalChanges" << newDuration;
239

240
    QMetaObject::invokeMethod(this, [this, newDuration]() {Q_EMIT durationChanged(newDuration);}, Qt::QueuedConnection);
241
242
243
244
245
246
247
248
249
250
251
252
}

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

253
void AudioWrapper::playerMutedSignalChanges(bool isMuted)
254
{
255
    QMetaObject::invokeMethod(this, [this, isMuted]() {Q_EMIT mutedChanged(isMuted);}, Qt::QueuedConnection);
256
257
258
259
260
261
262
}

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

263
264
void AudioWrapper::saveUndoPosition(qint64 position)
{
265
266
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::saveUndoPosition" << position;

267
268
269
270
271
    d->mUndoSavedPosition = position;
}

void AudioWrapper::restoreUndoPosition()
{
272
273
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::restoreUndoPosition";

274
275
276
277
278
279
    d->mHasSavedPosition = true;
    d->mSavedPosition = d->mUndoSavedPosition;
}

void AudioWrapper::savePosition(qint64 position)
{
280
281
    qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::savePosition" << position;

282
283
284
    if (!d->mHasSavedPosition) {
        d->mHasSavedPosition = true;
        d->mSavedPosition = position;
285
        qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::savePosition" << "restore old position" << d->mSavedPosition;
286
287
288
    }
}

289
290

#include "moc_audiowrapper.cpp"