/* * Copyright (C) 2012 Samsung Electronics * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "config.h" #include "Vibration.h" #if ENABLE(VIBRATION) #include "VibrationClient.h" namespace WebCore { // Maximum number of entries in a vibration pattern. const unsigned MaxVibrationPatternLength = 99; // Maximum duration of a vibration in 10 seconds. const unsigned MaxVibrationDuration = 10000; Vibration::Vibration(VibrationClient* client) : m_vibrationClient(client) , m_timer(*this, &Vibration::timerFired) , m_state(State::Idle) { } Vibration::~Vibration() { m_vibrationClient->vibrationDestroyed(); } bool Vibration::vibrate(const VibrationPattern& pattern) { VibrationPattern& sanitized = const_cast(pattern); size_t length = sanitized.size(); // If the pattern is too long then truncate it. if (length > MaxVibrationPatternLength) { sanitized.shrink(MaxVibrationPatternLength); length = MaxVibrationPatternLength; } // If the length of pattern is even and is not zero, then remove the last entry in pattern. if (length && !(length % 2)) { sanitized.removeLast(); length--; } // If any pattern entry is too long then truncate it. for (auto& duration : sanitized) duration = std::min(duration, MaxVibrationDuration); // Pre-exisiting instance need to be canceled when vibrate() is called. if (isVibrating()) cancelVibration(); // If pattern is an empty list, then return true and terminate these steps. if (!length || (length == 1 && !sanitized[0])) { cancelVibration(); return true; } m_pattern = sanitized; m_timer.startOneShot(0); m_state = State::Waiting; return true; } void Vibration::cancelVibration() { m_pattern.clear(); if (isVibrating()) { m_timer.stop(); m_state = State::Idle; m_vibrationClient->cancelVibration(); } } void Vibration::timerFired() { m_timer.stop(); if (m_pattern.isEmpty()) { m_state = State::Idle; return; } switch (m_state) { case State::Vibrating: m_state = State::Waiting; break; case State::Waiting: case State::Idle: m_state = State::Vibrating; m_vibrationClient->vibrate(m_pattern[0]); break; } m_timer.startOneShot(m_pattern[0] / 1000.0); m_pattern.remove(0); } const char* Vibration::supplementName() { return "Vibration"; } void provideVibrationTo(Page* page, VibrationClient* client) { Vibration::provideTo(page, Vibration::supplementName(), std::make_unique(client)); } } // namespace WebCore #endif // ENABLE(VIBRATION)