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 "qfeedbackeffect.h" |
38 | #include "qfeedbackeffect_p.h" |
39 | #include "qfeedbackplugininterfaces.h" |
40 | |
41 | #include <QtCore> |
42 | #include <QDebug> |
43 | |
44 | |
45 | QT_BEGIN_NAMESPACE |
46 | |
47 | /*! |
48 | \class QFeedbackEffect |
49 | \brief The QFeedbackEffect class is the abstract base class for feedback effects. |
50 | \ingroup feedback |
51 | \inmodule QtFeedback |
52 | |
53 | It represents an effect to provide feedback to a person (i.e., an effect that |
54 | affect human senses). The technology available today usually only |
55 | provides haptic effects, which deal with the sense of touch, and audio effects. The |
56 | QFeedbackHapticsEffect and QFeedbackFileEffect are implementations |
57 | of haptic effects and can be used to control a mobile device's |
58 | vibrator. In addition, the QFeedbackFileEffect can also be used to play |
59 | audio feedback. |
60 | |
61 | Feedback effects have a duration, which is measured in |
62 | milliseconds. Subclasses reimplement duration() to inform how long |
63 | the effect lasts. The duration is the total time the effect will |
64 | last, and thus includes any envelope modifiers (attack and fade). |
65 | |
66 | At any given time, a feedback effect is in one of four states: |
67 | Loading, Stopped, Running, or Paused. See the |
68 | \l{QFeedbackEffect::}{State} enum documentation for further |
69 | details. Subclasses must reimplement state() to report which |
70 | state an effect is in, and setState() to receive state change |
71 | requests. The start(), pause(), and stop() slots calls |
72 | setState() with the corresponding new \l{QFeedbackEffect::}{State}. Changes |
73 | in state are reported through the stateChanged() signal and may happen |
74 | asynchronously some time after the state change request. |
75 | |
76 | A system often has a set of standard feedback effects for user |
77 | interface interaction (e.g., button clicks). The |
78 | \l{QFeedbackEffect::}{Effect} describes the standard effects |
79 | that QFeedbackEffect supports. It is named so because the effects |
80 | often depend on the theme of the user interface. You can play |
81 | these effects using the playThemeEffect() function. |
82 | |
83 | \code |
84 | QFeedbackEffect::playThemeEffect(QFeedbackEffect::Press); |
85 | \endcode |
86 | |
87 | The playThemeEffect() function returns true if the effect was |
88 | played successfully. An effect may not be played if the system does |
89 | not support it or if an error occurred. |
90 | */ |
91 | |
92 | /*! |
93 | \fn void QFeedbackEffect::error(QFeedbackEffect::ErrorType error) const |
94 | |
95 | This signal is emitted by subclasses if an \a error occurred during |
96 | playback of an effect. The \l{QFeedbackEffect::}{ErrorType} enum |
97 | describes the errors that can be reported. |
98 | */ |
99 | |
100 | /*! |
101 | \fn void QFeedbackEffect::stateChanged() |
102 | |
103 | This signal is emitted by subclasses when the \l State of the |
104 | effect changes. |
105 | |
106 | \sa state() |
107 | */ |
108 | |
109 | /*! |
110 | \enum QFeedbackEffect::State |
111 | |
112 | This enum describes the state of the effect. An effect will be in |
113 | one of these states. |
114 | |
115 | \value Stopped The effect is not running. This is the initial |
116 | state. The state changes to either Loading when loading an effect |
117 | or to Running when the effect is started by calling start(). When |
118 | an effect has finished playing, it will enter the Stopped state |
119 | again. |
120 | |
121 | \value Paused The effect is paused. Calling start() will resume it. |
122 | |
123 | \value Running The effect is running. You can control the current state |
124 | by calling the stop() or pause() functions. |
125 | |
126 | \value Loading The effect is loading. That can happen when loading |
127 | is done asynchronously. When the effect has loaded, the state will change |
128 | to either Running (if start() has been called) or Stopped. |
129 | |
130 | \sa state() |
131 | */ |
132 | |
133 | |
134 | /*! |
135 | \enum QFeedbackEffect::ErrorType |
136 | |
137 | This enum describes the possible errors happening on the effect. |
138 | |
139 | \value UnknownError An unknown error occurred. |
140 | |
141 | \value DeviceBusy The feedback could not start because the device is busy. |
142 | |
143 | \sa error() |
144 | */ |
145 | |
146 | /*! |
147 | \enum QFeedbackEffect::Effect |
148 | |
149 | This enum describes all possible effect types. Effects might |
150 | be tactile, or audio or visual. |
151 | |
152 | Not all platforms and devices have distinct effects for each type. |
153 | |
154 | \value Effect.Undefined - Undefined feedback. No feedback is given. |
155 | \value Effect.Press - Feedback for when the screen is pressed. |
156 | \value Effect.Release - Feedback for touch release. |
157 | \value Effect.PressWeak - A weak feedback for press. |
158 | \value Effect.ReleaseWeak - A weak feedback for release. |
159 | \value Effect.PressStrong - A strong feedback for press. |
160 | \value Effect.ReleaseStrong - A strong feedback for release. |
161 | \value Effect.DragStart - Feedback for when dragging starts. |
162 | \value Effect.DragDropInZone - Feedback for when dragging ends and touch is released inside a drop zone. |
163 | \value Effect.DragDropOutOfZone - Feedback for when dragging ends and touch is released outside a drop zone. |
164 | \value Effect.DragCrossBoundary - Feedback for when crossing a boundary while dragging. |
165 | \value Effect.Appear - Feedback for when an item is shown. |
166 | \value Effect.Disappear - Feedback for when an item is closed. |
167 | \value Effect.Move - Feedback for dragging on screen. |
168 | \value NumberOfEffects The number of built-in effects. |
169 | \value UserEffect The starting point for any user defined effects, where supported. |
170 | */ |
171 | |
172 | /*! |
173 | \enum QFeedbackEffect::Duration |
174 | This enum describes the possible effect predefined duration types. Generally a specific |
175 | milliseconds value can be supplied instead of one of these values. |
176 | |
177 | \value Infinite Infinite effect duration |
178 | */ |
179 | |
180 | /*! |
181 | \property QFeedbackEffect::state |
182 | \brief state of the feedback effect. |
183 | |
184 | This returns the state of the feedback effect. The \l State enumeration reports |
185 | the possible states. |
186 | */ |
187 | |
188 | /*! |
189 | \property QFeedbackEffect::duration |
190 | \brief duration of the feedback effect, in milliseconds. |
191 | |
192 | In some cases the duration will be unknown, which will be reported as 0. If the duration |
193 | is infinite, QFeedbackEffect::Infinite will be returned. Some subclasses may have |
194 | more than one type of duration (for example, \l QFeedbackHapticsEffect), and this |
195 | property will return the total duration of the effect. |
196 | */ |
197 | |
198 | /*! |
199 | Constructs the QFeedbackEffect base class, and passes \a parent to |
200 | QObject's constructor. This is called by the classes that inherit |
201 | from this class. |
202 | */ |
203 | QFeedbackEffect::QFeedbackEffect(QObject *parent) : QObject(parent) |
204 | { |
205 | } |
206 | |
207 | /*! |
208 | \fn void QFeedbackEffect::start() |
209 | |
210 | Starts playing the effect. If an error occurs the |
211 | error() signal will be emitted. |
212 | |
213 | \sa stop() |
214 | */ |
215 | void QFeedbackEffect::start() |
216 | { |
217 | setState(Running); |
218 | } |
219 | |
220 | /*! |
221 | \fn void QFeedbackEffect::stop() |
222 | |
223 | Stops a playing effect. If an error occurs the |
224 | error() signal will be emitted. |
225 | |
226 | \sa start(), pause(), setState() |
227 | */ |
228 | void QFeedbackEffect::stop() |
229 | { |
230 | setState(Stopped); |
231 | } |
232 | |
233 | /*! |
234 | \fn void QFeedbackEffect::pause() |
235 | |
236 | Pauses a playing effect. If an error occurs the |
237 | error() signal will be emitted. Not all systems |
238 | support pausing an effect during playback. |
239 | */ |
240 | void QFeedbackEffect::pause() |
241 | { |
242 | setState(Paused); |
243 | } |
244 | |
245 | /*! |
246 | \fn QFeedbackEffect::playThemeEffect(Effect effect) |
247 | |
248 | This function plays \a effect instantly and returns true if the |
249 | effect could be played; otherwise, returns false. |
250 | */ |
251 | bool QFeedbackEffect::playThemeEffect(Effect effect) |
252 | { |
253 | if (QFeedbackThemeInterface *iface = QFeedbackThemeInterface::instance()) |
254 | return iface->play(effect); |
255 | return false; |
256 | } |
257 | |
258 | /*! |
259 | \fn QFeedbackEffect::supportsThemeEffect() |
260 | |
261 | Returns true if playing themed feedback is available. |
262 | |
263 | */ |
264 | bool QFeedbackEffect::supportsThemeEffect() |
265 | { |
266 | return QFeedbackThemeInterface::instance() != 0; |
267 | } |
268 | |
269 | /*! |
270 | \class QFeedbackHapticsEffect |
271 | \ingroup feedback |
272 | \inmodule QtFeedback |
273 | \brief The QFeedbackHapticsEffect class allows you to play a haptics effect. |
274 | |
275 | A haptics effect is an effect that takes advantage of the sense of |
276 | touch. Most mobile devices today supports one such effect, |
277 | vibration, which will then be the default when you create a |
278 | QFeedbackHapticsEffect. |
279 | |
280 | A haptics effect has a few parameters that must be set up before |
281 | it can be played: |
282 | |
283 | \list |
284 | \li duration(): The total duration of the effect in milliseconds. |
285 | \li intensity(): The intensity, e.g., how hard the device will vibrate. |
286 | \endlist |
287 | |
288 | An effect can, for example, be set up as follows: |
289 | |
290 | \omit I'm right that this is all that is required to be set? \endomit |
291 | \code |
292 | QFeedbackHapticsEffect rumble; |
293 | rumble.setIntensity(1.0); |
294 | rumble.setDuration(100); |
295 | \endcode |
296 | |
297 | You can now start() the effect. |
298 | |
299 | \code |
300 | rumble.start(); |
301 | \endcode |
302 | |
303 | At any given time, the effect is in one of four states: |
304 | \l{QFeedbackEffect::}{Stopped}, \l{QFeedbackEffect::}{Paused}, |
305 | \l{QFeedbackEffect::}{Running}, or \l{QFeedbackEffect::}{Loading}. |
306 | You can request a state change by calling start(), pause(), or |
307 | stop(). The state is queried with state(). |
308 | |
309 | The haptics effect also supports a fade-in of the effect. For |
310 | vibration, this means that the vibration will grow (or sink) in |
311 | intensity from when the effect starts until intensity() is |
312 | reached. You can set that up as follows: |
313 | |
314 | \code |
315 | rumble.setAttackIntensity(0.0); |
316 | rumble.setAttackTime(250); |
317 | \endcode |
318 | |
319 | Attack intensity is the start intensity and attack time is the |
320 | duration of the fade-in. We have a similar fade-out: |
321 | |
322 | \code |
323 | rumble.setFadeTime(250); |
324 | rumble.setFadeIntensity(0.0); |
325 | \endcode |
326 | |
327 | When using fade-in and fade-out the total duration of the haptics |
328 | effect will be: duration(); the main intensity() will be played for |
329 | (duration() - (attackTime() + fadeTime())) milliseconds. |
330 | |
331 | A QFeedbackHapticsEffect is played on an |
332 | \l{QFeedbackHapticsEffect::}{actuator()}, which is the physical component that |
333 | performs the effect. You can query if other actuators are |
334 | available - see the QFeedbackActuator::actuators() function |
335 | documentation for details. |
336 | |
337 | Errors occurring during playback are notified through the |
338 | error() signal. |
339 | |
340 | \sa QFeedbackActuator |
341 | */ |
342 | |
343 | /*! |
344 | \fn virtual void QFeedbackEffect::setState(State state) = 0 |
345 | |
346 | Requests the effect to change its State to change to the specified \a state. |
347 | |
348 | Subclasses reimplement this function to handle state change requests |
349 | for the effect. |
350 | */ |
351 | |
352 | /*! |
353 | Constructs the QFeedbackHapticsEffect class, and passes \a parent to |
354 | QObject's constructor. The default QFeedbackActuator will be used. |
355 | |
356 | \sa QFeedbackActuator::actuators() |
357 | */ |
358 | QFeedbackHapticsEffect::QFeedbackHapticsEffect(QObject *parent) : QFeedbackEffect(parent), priv(new QFeedbackHapticsEffectPrivate) |
359 | { |
360 | setActuator(0); |
361 | } |
362 | |
363 | |
364 | /*! |
365 | Destroys this effect and stops the feedback if it is running. |
366 | */ |
367 | QFeedbackHapticsEffect::~QFeedbackHapticsEffect() |
368 | { |
369 | stop(); |
370 | } |
371 | |
372 | /*! |
373 | \property QFeedbackHapticsEffect::duration |
374 | \brief the expected duration of the effect. |
375 | |
376 | This property defines the total duration of the feedback effect, in milliseconds. |
377 | It includes the duration of any fade-in or fade-out parts, if any, in non-periodic |
378 | effects, and includes all repetitions of the period in periodic-effects, if any. |
379 | |
380 | If the duration is set to a value less than attackTime() + fadeTime(), or less |
381 | than the period() of the effect, the waveform which will result is |
382 | backend-specific. |
383 | |
384 | \sa fadeTime(), attackTime(), period() |
385 | */ |
386 | int QFeedbackHapticsEffect::duration() const |
387 | { |
388 | return priv->duration; |
389 | } |
390 | void QFeedbackHapticsEffect::setDuration(int msecs) |
391 | { |
392 | if (priv->duration == msecs) |
393 | return; |
394 | priv->duration = msecs; |
395 | QFeedbackHapticsInterface::instance()->updateEffectProperty(this, QFeedbackHapticsInterface::Duration); |
396 | } |
397 | |
398 | /*! |
399 | \property QFeedbackHapticsEffect::intensity |
400 | \brief the intensity of the effect. |
401 | |
402 | This property defines the intensity of the feedback effect. |
403 | The value can be between 0 and 1. |
404 | |
405 | For non-periodic effects, the effect will be at this intensity for |
406 | (duration() - (attackTime() + fadeTime())) milliseconds. |
407 | For periodic effects, the effect will be at this intensity once per |
408 | period for (period() - (attackTime() + fadeTime())) milliseconds. |
409 | */ |
410 | qreal QFeedbackHapticsEffect::intensity() const |
411 | { |
412 | return priv->intensity; |
413 | } |
414 | void QFeedbackHapticsEffect::setIntensity(qreal intensity) |
415 | { |
416 | if (priv->intensity == intensity) |
417 | return; |
418 | priv->intensity = intensity; |
419 | QFeedbackHapticsInterface::instance()->updateEffectProperty(this, QFeedbackHapticsInterface::Intensity); |
420 | } |
421 | |
422 | /*! |
423 | \property QFeedbackHapticsEffect::attackTime |
424 | \brief the duration of the fade-in effect. |
425 | |
426 | This property defines the duration of the fade-in effect in milliseconds. |
427 | The effect will ramp up (or down) from attackIntensity() to intensity() in attackTime() milliseconds. |
428 | |
429 | If the attack time is set to a value such that attackTime() + fadeTime() |
430 | is greater than duration() for non-periodic effects, or greater than |
431 | period() for periodic effects, the waveform which will result is |
432 | backend-specific. |
433 | |
434 | \sa duration(), period() |
435 | */ |
436 | int QFeedbackHapticsEffect::attackTime() const |
437 | { |
438 | return priv->attackTime; |
439 | } |
440 | void QFeedbackHapticsEffect::setAttackTime(int msecs) |
441 | { |
442 | if (priv->attackTime == msecs) |
443 | return; |
444 | priv->attackTime = msecs; |
445 | QFeedbackHapticsInterface::instance()->updateEffectProperty(this, QFeedbackHapticsInterface::AttackTime); |
446 | } |
447 | |
448 | /*! |
449 | \property QFeedbackHapticsEffect::attackIntensity |
450 | \brief the initial intensity of the effect. |
451 | |
452 | This property defines the initial intensity of the effect, before it fades in. |
453 | It is usually lower than \l intensity. The effect will ramp up (or down) from |
454 | attackIntensity() to intensity() in attackTime() milliseconds. |
455 | */ |
456 | qreal QFeedbackHapticsEffect::attackIntensity() const |
457 | { |
458 | return priv->attackIntensity; |
459 | } |
460 | void QFeedbackHapticsEffect::setAttackIntensity(qreal intensity) |
461 | { |
462 | if (priv->attackIntensity == intensity) |
463 | return; |
464 | priv->attackIntensity = intensity; |
465 | QFeedbackHapticsInterface::instance()->updateEffectProperty(this, QFeedbackHapticsInterface::AttackIntensity); |
466 | } |
467 | |
468 | /*! |
469 | \property QFeedbackHapticsEffect::fadeTime |
470 | \brief the duration of the fade-out effect. |
471 | |
472 | This property defines the duration of the fade-out effect in milliseconds. |
473 | The effect will ramp down (or up) from intensity() to fadeIntensity() in fadeTime() milliseconds. |
474 | |
475 | If the fade time is set to a value such that attackTime() + fadeTime() |
476 | is greater than duration() for non-periodic effects, or greater than |
477 | period() for periodic effects, the waveform which will result is |
478 | backend-specific. |
479 | |
480 | \sa duration(), period() |
481 | */ |
482 | int QFeedbackHapticsEffect::fadeTime() const |
483 | { |
484 | return priv->fadeTime; |
485 | } |
486 | void QFeedbackHapticsEffect::setFadeTime(int msecs) |
487 | { |
488 | if (priv->fadeTime == msecs) |
489 | return; |
490 | priv->fadeTime = msecs; |
491 | QFeedbackHapticsInterface::instance()->updateEffectProperty(this, QFeedbackHapticsInterface::FadeTime); |
492 | } |
493 | |
494 | /*! |
495 | \property QFeedbackHapticsEffect::fadeIntensity |
496 | \brief the final intensity of the effect. |
497 | |
498 | This property defines the final intensity of the effect, after it fades out. |
499 | It is usually lower than \l intensity. |
500 | The effect will ramp down (or up) from intensity() to fadeIntensity() in fadeTime() milliseconds. |
501 | */ |
502 | qreal QFeedbackHapticsEffect::fadeIntensity() const |
503 | { |
504 | return priv->fadeIntensity; |
505 | } |
506 | void QFeedbackHapticsEffect::setFadeIntensity(qreal intensity) |
507 | { |
508 | if (priv->fadeIntensity == intensity) |
509 | return; |
510 | priv->fadeIntensity = intensity; |
511 | QFeedbackHapticsInterface::instance()->updateEffectProperty(this, QFeedbackHapticsInterface::FadeIntensity); |
512 | } |
513 | |
514 | /*! |
515 | \property QFeedbackHapticsEffect::actuator |
516 | \brief the actuator on which the effect operates. |
517 | |
518 | This property defines the actuator on which the effect operates. You can only |
519 | change the actuator used when the effect is stopped. Setting a null actuator |
520 | resets the effect to use the default actuator. |
521 | */ |
522 | QFeedbackActuator* QFeedbackHapticsEffect::actuator() const |
523 | { |
524 | return priv->actuator; |
525 | } |
526 | void QFeedbackHapticsEffect::setActuator(QFeedbackActuator *actuator) |
527 | { |
528 | if (state() != Stopped) { |
529 | qWarning(msg: "QFeedbackHapticsEffect::setActuator: The effect is not stopped" ); |
530 | return; |
531 | } |
532 | |
533 | if (actuator) { |
534 | priv->actuator = actuator; |
535 | } else { |
536 | QList<QFeedbackActuator*> list = QFeedbackActuator::actuators(); |
537 | if (!list.isEmpty()) { |
538 | priv->actuator = list.first(); |
539 | } else { |
540 | priv->actuator = new QFeedbackActuator(this); |
541 | } |
542 | } |
543 | } |
544 | |
545 | /*! |
546 | \property QFeedbackHapticsEffect::period |
547 | \brief set the period for the effect. |
548 | |
549 | It has a default value of -1, which means that it is not a periodic effect. |
550 | You can only change the period when the effect is stopped. |
551 | The duration of the effect should be set to a value larger than the |
552 | period of the effect if you wish the periodicity to be discernable. |
553 | \note Not all actuators support periodic effects |
554 | |
555 | The period defines the total length of the periodic envelope, which will |
556 | be repeated up until duration() milliseconds has elapsed. For a periodic |
557 | effect, the intensity will start at attackIntensity(), ramp to intensity() |
558 | (where it stays for (period() - (attackTime() + fadeTime())) milliseconds), |
559 | then ramp to fadeIntensity(). This waveform will be repeated as many times |
560 | as required until the duration() has elapsed. |
561 | |
562 | If the period is set to a value which is less than attackTime() + fadeTime(), |
563 | the waveform which will result is backend-specific. |
564 | */ |
565 | int QFeedbackHapticsEffect::period() const |
566 | { |
567 | return priv->period; |
568 | } |
569 | void QFeedbackHapticsEffect::setPeriod(int msecs) |
570 | { |
571 | if (state() != Stopped) { |
572 | qWarning(msg: "QFeedbackHapticsEffect::setPeriod: the period can only be changed if the effect is stopped" ); |
573 | return; |
574 | } |
575 | priv->period = msecs; |
576 | } |
577 | |
578 | /*! |
579 | \internal |
580 | */ |
581 | void QFeedbackHapticsEffect::setState(State state) |
582 | { |
583 | State oldState = this->state(); |
584 | if (oldState != state) { |
585 | QFeedbackHapticsInterface::instance()->setEffectState(this, state); |
586 | emit stateChanged(); |
587 | } |
588 | } |
589 | |
590 | /*! |
591 | \internal |
592 | */ |
593 | QFeedbackEffect::State QFeedbackHapticsEffect::state() const |
594 | { |
595 | return QFeedbackHapticsInterface::instance()->effectState(this); |
596 | } |
597 | |
598 | /*! |
599 | \internal |
600 | \class QFeedbackFileEffect |
601 | \ingroup feedback |
602 | \inmodule QtFeedback |
603 | \brief The QFeedbackFileEffect class allows to play feedback from a file. |
604 | |
605 | Several different mime types may be supported on a system, including |
606 | both haptic data files, and audio files. |
607 | |
608 | The files containing haptics data are usually suffixed \c .ivt. |
609 | The feedback is usually varying in |
610 | \l{QFeedbackHapticsEffect::}{intensity()}, and is for that reason |
611 | often referred to as a "haptic tune". They are created, for |
612 | instance, from music files where the feedback is based on a |
613 | specific feature in the audio data. For example, you could have a |
614 | phone vibrating along with the bass of a rock song. |
615 | |
616 | Although Qt Feedback does not let you record \c .ivt files, it lets |
617 | you play them back using the QFeedbackFileEffect class. Setting |
618 | up a QFeedbackFileEffect and starting it is done as follows: |
619 | |
620 | \code |
621 | QFeedbackFileEffect hapticTune; |
622 | hapticTune.setSource(QUrl::fromLocalFile("mySavedRumble.ivt")); |
623 | hapticTune.load(); |
624 | hapticTune.start(); |
625 | \endcode |
626 | |
627 | As with other \l{QFeedbackEffect}s, QFeedbackFileEffect is at any |
628 | given time in one of four states: \l{QFeedbackEffect::}{Loading}, |
629 | \l{QFeedbackEffect::}{Running}, \l{QFeedbackEffect::}{Paused}, or |
630 | \l{QFeedbackEffect::}{Stopped}. You request state changes with |
631 | start(), pause(), and stop(). |
632 | |
633 | You can load() and unload() the file at will to free resources or |
634 | be as fast as possible. The file must be loaded before it can be |
635 | started, and it cannot be unloaded while playing. After the file is |
636 | loaded, you can query its duration(). Some mime types may not |
637 | support duration information - in these cases, 0 will be returned. |
638 | |
639 | QFeedbackFileEffect reports errors through the error() signal. |
640 | |
641 | \sa QFeedbackHapticsEffect |
642 | */ |
643 | |
644 | |
645 | /*! |
646 | \internal |
647 | */ |
648 | void QFeedbackFileEffectPrivate::loadFinished(bool success) |
649 | { |
650 | loaded = success; |
651 | if( !success) |
652 | backendUsed = -1; |
653 | } |
654 | |
655 | |
656 | /*! |
657 | \internal |
658 | Constructs the QFeedbackFileEffect class, and passes \a parent to |
659 | QObject's constructor. |
660 | */ |
661 | QFeedbackFileEffect::QFeedbackFileEffect(QObject *parent) : QFeedbackEffect(parent), priv(new QFeedbackFileEffectPrivate(this)) |
662 | { |
663 | } |
664 | |
665 | /*! |
666 | \internal |
667 | Stops the feedback and unloads the file if necessary. |
668 | */ |
669 | QFeedbackFileEffect::~QFeedbackFileEffect() |
670 | { |
671 | setLoaded(false); //ensures we unload the file and frees resources |
672 | } |
673 | |
674 | /*! |
675 | \reimp |
676 | */ |
677 | int QFeedbackFileEffect::duration() const |
678 | { |
679 | return QFeedbackFileInterface::instance()->effectDuration(this); |
680 | } |
681 | |
682 | /*! |
683 | \internal |
684 | \property QFeedbackFileEffect::source |
685 | \brief the url of the file that is loaded. |
686 | |
687 | Setting that property will automatically unload the previous file (if any) and load the new one. |
688 | Some backends may not support all URL schemes - for example, they may only support |
689 | local files. |
690 | |
691 | You can only change the source of an effect when it is stopped. |
692 | */ |
693 | QUrl QFeedbackFileEffect::source() const |
694 | { |
695 | return priv->url; |
696 | } |
697 | void QFeedbackFileEffect::setSource(const QUrl &source) |
698 | { |
699 | if (state() != QFeedbackEffect::Stopped) { |
700 | qWarning(msg: "QFeedbackFileEffect::setSource: can't set the file while the feedback is running" ); |
701 | return; |
702 | } |
703 | if (source != priv->url) { |
704 | setLoaded(false); |
705 | priv->url = source; |
706 | setLoaded(true); |
707 | } |
708 | } |
709 | |
710 | /*! |
711 | \internal |
712 | \property QFeedbackFileEffect::loaded |
713 | \brief reports if the file has been successfully loaded. |
714 | */ |
715 | bool QFeedbackFileEffect::isLoaded() const |
716 | { |
717 | return priv->loaded; |
718 | } |
719 | void QFeedbackFileEffect::setLoaded(bool load) |
720 | { |
721 | if (priv->loaded == load) |
722 | return; |
723 | |
724 | if (state() != QFeedbackEffect::Stopped) { |
725 | qWarning() << "QFeedbackFileEffect::setLoaded: can't load/unload a file while the effect is not stopped" ; |
726 | return; |
727 | } |
728 | |
729 | QFeedbackFileInterface::instance()->setLoaded(this, load); |
730 | } |
731 | |
732 | |
733 | /*! |
734 | \internal |
735 | \fn void QFeedbackFileEffect::load() |
736 | |
737 | Makes sure that the file associated with the feedback object is loaded. |
738 | It will be automatically loaded when the setSource() or start() functions |
739 | are called. |
740 | */ |
741 | void QFeedbackFileEffect::load() |
742 | { |
743 | setLoaded(true); |
744 | } |
745 | |
746 | /*! |
747 | \internal |
748 | \fn void QFeedbackFileEffect::unload() |
749 | |
750 | makes sure that the file associated with the feedback object is unloaded. |
751 | It will be automatically unloaded when the setSource function is called with |
752 | another file or the object is destroyed. |
753 | */ |
754 | void QFeedbackFileEffect::unload() |
755 | { |
756 | setLoaded(false); |
757 | } |
758 | |
759 | |
760 | /*! |
761 | \internal |
762 | \fn QStringList QFeedbackFileEffect::supportedMimeTypes() |
763 | |
764 | returns the MIME types supported for playing effects from file. |
765 | */ |
766 | QStringList QFeedbackFileEffect::supportedMimeTypes() |
767 | { |
768 | return QFeedbackFileInterface::instance()->supportedMimeTypes(); |
769 | } |
770 | |
771 | |
772 | /*! |
773 | \reimp |
774 | */ |
775 | void QFeedbackFileEffect::setState(State newState) |
776 | { |
777 | State oldState = state(); |
778 | if (oldState != newState) { |
779 | if (newState != Stopped && state() == Stopped) |
780 | load(); // makes sure the file is loaded |
781 | QFeedbackFileInterface::instance()->setEffectState(this, newState); |
782 | emit stateChanged(); |
783 | } |
784 | } |
785 | |
786 | /*! |
787 | \reimp |
788 | */ |
789 | QFeedbackEffect::State QFeedbackFileEffect::state() const |
790 | { |
791 | return QFeedbackFileInterface::instance()->effectState(this); |
792 | } |
793 | |
794 | QT_END_NAMESPACE |
795 | |