1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef DEVICE_GAMEPAD_ABSTRACT_HAPTIC_GAMEPAD_
6 #define DEVICE_GAMEPAD_ABSTRACT_HAPTIC_GAMEPAD_
7 
8 #include "base/memory/scoped_refptr.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/sequenced_task_runner.h"
11 #include "base/threading/thread_checker.h"
12 #include "base/time/time.h"
13 #include "device/gamepad/gamepad_export.h"
14 #include "device/gamepad/public/mojom/gamepad.mojom.h"
15 
16 namespace device {
17 
18 // AbstractHapticGamepad is a base class for gamepads that support dual-rumble
19 // vibration effects. To use it, override the SetVibration method so that it
20 // sets the vibration intensity on the device. Then, calling PlayEffect or
21 // ResetVibration will call your SetVibration method at the appropriate times
22 // to produce the desired vibration effect. When the effect is complete, or when
23 // it has been preempted by another effect, the callback is invoked with a
24 // result code.
25 //
26 // By default, SetZeroVibration simply calls SetVibration with both parameters
27 // set to zero. You may optionally override SetZeroVibration if the device has a
28 // more efficient means of stopping an ongoing effect.
29 class DEVICE_GAMEPAD_EXPORT AbstractHapticGamepad {
30  public:
31   AbstractHapticGamepad();
32   virtual ~AbstractHapticGamepad();
33 
34   // Start playing a haptic effect of type |type|, described by |params|. When
35   // the effect is complete, or if it encounters an error, the result code is
36   // passed back to the caller on its own sequence by calling |callback| using
37   // |callback_runner|.
38   void PlayEffect(
39       mojom::GamepadHapticEffectType type,
40       mojom::GamepadEffectParametersPtr params,
41       mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback callback,
42       scoped_refptr<base::SequencedTaskRunner> callback_runner);
43 
44   // Reset vibration on the gamepad, perhaps interrupting an ongoing effect. A
45   // result code is passed back to the caller on its own sequence by calling
46   // |callback| using |callback_runner|.
47   void ResetVibration(
48       mojom::GamepadHapticsManager::ResetVibrationActuatorCallback callback,
49       scoped_refptr<base::SequencedTaskRunner> callback_runner);
50 
51   // Stop vibration effects, run callbacks, and release held resources. Must be
52   // called exactly once before the device is destroyed.
53   void Shutdown();
54 
55   // Returns true if Shutdown() has been called.
IsShuttingDown()56   bool IsShuttingDown() { return is_shutting_down_; }
57 
58   // Set the vibration magnitude for the strong and weak vibration actuators.
59   virtual void SetVibration(double strong_magnitude, double weak_magnitude) = 0;
60 
61   // Set the vibration magnitude for both actuators to zero.
62   virtual void SetZeroVibration();
63 
64   // The maximum effect duration supported by this device. Long-running effects
65   // must be divided into effects of this duration or less.
66   virtual double GetMaxEffectDurationMillis();
67 
68   virtual base::WeakPtr<AbstractHapticGamepad> GetWeakPtr() = 0;
69 
70  private:
71   // Override to perform additional shutdown actions after vibration effects
72   // are halted and callbacks are issued.
DoShutdown()73   virtual void DoShutdown() {}
74 
75   void PlayDualRumbleEffect(int sequence_id,
76                             double duration,
77                             double start_delay,
78                             double strong_magnitude,
79                             double weak_magnitude);
80   void StartVibration(int sequence_id,
81                       double duration,
82                       double strong_magnitude,
83                       double weak_magnitude);
84   void FinishEffect(int sequence_id);
85 
86   bool is_shutting_down_ = false;
87   bool is_shut_down_ = false;
88   int sequence_id_ = 0;
89   mojom::GamepadHapticsManager::PlayVibrationEffectOnceCallback
90       playing_effect_callback_;
91   scoped_refptr<base::SequencedTaskRunner> callback_runner_;
92   THREAD_CHECKER(thread_checker_);
93 };
94 
95 }  // namespace device
96 
97 #endif  // DEVICE_GAMEPAD_ABSTRACT_HAPTIC_GAMEPAD_
98