1/* 2 * Copyright (C) 2012 Samsung Electronics 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21#include "Vibration.h" 22 23#if ENABLE(VIBRATION) 24 25#include "VibrationClient.h" 26 27namespace WebCore { 28 29// Maximum number of entries in a vibration pattern. 30const unsigned MaxVibrationPatternLength = 99; 31// Maximum duration of a vibration in 10 seconds. 32const unsigned MaxVibrationDuration = 10000; 33 34Vibration::Vibration(VibrationClient* client) 35 : m_vibrationClient(client) 36 , m_timer(this, &Vibration::timerFired) 37 , m_state(State::Idle) 38{ 39} 40 41Vibration::~Vibration() 42{ 43 m_vibrationClient->vibrationDestroyed(); 44} 45 46bool Vibration::vibrate(const VibrationPattern& pattern) 47{ 48 VibrationPattern& sanitized = const_cast<VibrationPattern&>(pattern); 49 size_t length = sanitized.size(); 50 51 // If the pattern is too long then truncate it. 52 if (length > MaxVibrationPatternLength) { 53 sanitized.shrink(MaxVibrationPatternLength); 54 length = MaxVibrationPatternLength; 55 } 56 57 // If the length of pattern is even and is not zero, then remove the last entry in pattern. 58 if (length && !(length % 2)) { 59 sanitized.removeLast(); 60 length--; 61 } 62 63 // If any pattern entry is too long then truncate it. 64 for (auto& duration : sanitized) 65 duration = std::min(duration, MaxVibrationDuration); 66 67 // Pre-exisiting instance need to be canceled when vibrate() is called. 68 if (isVibrating()) 69 cancelVibration(); 70 71 // If pattern is an empty list, then return true and terminate these steps. 72 if (!length || (length == 1 && !sanitized[0])) { 73 cancelVibration(); 74 return true; 75 } 76 77 m_pattern = sanitized; 78 79 m_timer.startOneShot(0); 80 m_state = State::Waiting; 81 return true; 82} 83 84void Vibration::cancelVibration() 85{ 86 m_pattern.clear(); 87 if (isVibrating()) { 88 m_timer.stop(); 89 m_state = State::Idle; 90 m_vibrationClient->cancelVibration(); 91 } 92} 93 94void Vibration::timerFired(Timer<Vibration>* timer) 95{ 96 ASSERT_UNUSED(timer, timer == &m_timer); 97 98 m_timer.stop(); 99 100 if (m_pattern.isEmpty()) { 101 m_state = State::Idle; 102 return; 103 } 104 105 switch (m_state) { 106 case State::Vibrating: 107 m_state = State::Waiting; 108 break; 109 case State::Waiting: 110 case State::Idle: 111 m_state = State::Vibrating; 112 m_vibrationClient->vibrate(m_pattern[0]); 113 break; 114 } 115 m_timer.startOneShot(m_pattern[0] / 1000.0); 116 m_pattern.remove(0); 117} 118 119const char* Vibration::supplementName() 120{ 121 return "Vibration"; 122} 123 124void provideVibrationTo(Page* page, VibrationClient* client) 125{ 126 Vibration::provideTo(page, Vibration::supplementName(), std::make_unique<Vibration>(client)); 127} 128 129} // namespace WebCore 130 131#endif // ENABLE(VIBRATION) 132 133