1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the QtFeedback module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include <QtCore/QtPlugin>
38#include <QtCore/QCoreApplication>
39#include <QtCore/QFile>
40
41#include <QDebug>
42#include "qfeedback.h"
43
44QT_BEGIN_NAMESPACE
45
46QFeedbackMMK::QFeedbackMMK() : QObject(qApp)
47{
48}
49
50QFeedbackMMK::~QFeedbackMMK()
51{
52 foreach(FeedbackInfo fi, mEffects.values()) {
53 delete fi.soundEffect;
54 }
55}
56
57void QFeedbackMMK::setLoaded(QFeedbackFileEffect *effect, bool load)
58{
59 if (!effect)
60 return;
61
62 // See if we have seen this effect before
63 FeedbackInfo fi = mEffects.value(akey: effect);
64
65 if (load) {
66 // Well.. we might already have an effect, since we don't create them until
67 // we load...
68 if (fi.loaded) {
69 // We've already loaded?
70 return;
71 } else {
72 if (fi.soundEffect) {
73 // We've started a load, they must just be impatient
74 // Pushing this elevator button does nothing..
75 return;
76 } else {
77 // New sound effect!
78 QUrl url = effect->source();
79 if (QFile::exists(fileName: url.toLocalFile())) {
80 fi.soundEffect = new QSoundEffect(this);
81 mEffects.insert(akey: effect, avalue: fi);
82 mEffectMap.insert(akey: fi.soundEffect, avalue: effect);
83
84 connect(sender: fi.soundEffect, SIGNAL(statusChanged()), receiver: this, SLOT(soundEffectStatusChanged()));
85 connect(sender: fi.soundEffect, SIGNAL(playingChanged()), receiver: this, SLOT(soundEffectPlayingChanged()));
86 fi.soundEffect->setSource(url);
87
88 // conceptually we're now loading, so we have to do this manually??
89 QMetaObject::invokeMethod(obj: effect, member: "stateChanged");
90 } else {
91 reportLoadFinished(effect, success: false);
92 }
93 }
94 }
95 } else {
96 // Time to unload.
97 if (fi.soundEffect) {
98 mEffectMap.remove(akey: fi.soundEffect);
99 fi.soundEffect->deleteLater();
100 }
101 mEffects.remove(akey: effect);
102 }
103}
104
105void QFeedbackMMK::setEffectState(QFeedbackFileEffect *effect, QFeedbackEffect::State state)
106{
107 FeedbackInfo fi = mEffects.value(akey: effect);
108 switch (state)
109 {
110 case QFeedbackEffect::Stopped:
111 if (fi.playing) {
112 Q_ASSERT(fi.soundEffect);
113 fi.playing = false;
114 mEffects.insert(akey: effect, avalue: fi); // overwrite previous version
115 fi.soundEffect->stop();
116 }
117 break;
118
119 case QFeedbackEffect::Paused:
120 // Well, we can't pause, really
121 reportError(effect, QFeedbackEffect::UnknownError);
122 break;
123
124 case QFeedbackEffect::Running:
125 if (fi.playing) {
126 // We're already playing.
127 } else if (fi.soundEffect) {
128 fi.playing = true;
129 mEffects.insert(akey: effect, avalue: fi); // overwrite previous version
130 fi.soundEffect->play();
131 }
132 break;
133 default:
134 break;
135 }
136}
137
138QFeedbackEffect::State QFeedbackMMK::effectState(const QFeedbackFileEffect *effect)
139{
140 FeedbackInfo fi = mEffects.value(akey: effect);
141 if (fi.soundEffect) {
142 if (fi.playing) // we might not be loaded, however
143 return QFeedbackEffect::Running;
144 if (fi.loaded)
145 return QFeedbackEffect::Stopped; // No idle?
146 return QFeedbackEffect::Loading;
147 }
148 return QFeedbackEffect::Stopped;
149}
150
151int QFeedbackMMK::effectDuration(const QFeedbackFileEffect *effect)
152{
153 Q_UNUSED(effect);
154 // XXX This isn't supported by MMK currently
155 return 0;
156}
157
158QStringList QFeedbackMMK::supportedMimeTypes()
159{
160 return QSoundEffect::supportedMimeTypes();
161}
162
163void QFeedbackMMK::soundEffectStatusChanged()
164{
165 QSoundEffect* se = qobject_cast<QSoundEffect*>(object: sender());
166 if (se) {
167 // Hmm, now look up the right sound effect
168 QFeedbackFileEffect* fe = mEffectMap.value(akey: se);
169 if (!fe)
170 return;
171
172 FeedbackInfo fi = mEffects.value(akey: fe);
173
174 switch(se->status()) {
175 case QSoundEffect::Error:
176 if (!fi.soundEffect || !fi.loaded) {
177 // Error before we got loaded, so fail the load
178 mEffectMap.remove(akey: se);
179 mEffects.remove(akey: fe);
180 se->deleteLater();
181 reportLoadFinished(fe, success: false); // this ends our involvement
182 } else {
183 reportError(fe, QFeedbackEffect::UnknownError); // this doesn't do much
184 }
185 break;
186
187 case QSoundEffect::Ready:
188 if (fe->state() == QFeedbackEffect::Loading) {
189 reportLoadFinished(fe, success: true);
190
191 FeedbackInfo fi = mEffects.value(akey: fe);
192 fi.loaded = true;
193 mEffects.insert(akey: fe, avalue: fi);
194
195 QMetaObject::invokeMethod(obj: fe, member: "stateChanged");
196 }
197 break;
198
199 default:
200 // Nothing to handle here?
201 break;
202 }
203 }
204}
205
206void QFeedbackMMK::soundEffectPlayingChanged()
207{
208 QSoundEffect* se = qobject_cast<QSoundEffect*>(object: sender());
209 if (se) {
210 QFeedbackFileEffect* fileEffect = mEffectMap.value(akey: se);
211 FeedbackInfo fi = mEffects.value(akey: fileEffect);
212
213 if (fi.soundEffect == se) {
214 if (fi.playing != se->isPlaying()) {
215 fi.playing = se->isPlaying();
216 mEffects.insert(akey: fileEffect, avalue: fi); // overwrite previous version
217
218 QFeedbackFileEffect* fe = mEffectMap.value(akey: se);
219 // Emit the stateChanged() signal
220 if (fe) {
221 QMetaObject::invokeMethod(obj: fe, member: "stateChanged");
222 }
223 } else {
224 // Do nothing, internal state is already ok
225 }
226 }
227 }
228}
229
230QT_END_NAMESPACE
231

source code of qtfeedback/src/plugins/feedback/mmk/qfeedback.cpp