/**************************************************************************** ** ** Copyright (C) 2016 Jolla Ltd, author: ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include "resourcepolicyint.h" #include "resourcepolicyimpl.h" #include #include #include static int clientid = 0; ResourcePolicyInt::ResourcePolicyInt(QObject *parent) : QObject(parent) , m_acquired(0) , m_status(Initial) , m_video(0) , m_available(false) , m_resourceSet(0) { const char *resourceClass = "player"; QByteArray envVar = qgetenv("NEMO_RESOURCE_CLASS_OVERRIDE"); if (!envVar.isEmpty()) { QString data(envVar); // Only allow few resource classes if (data == "navigator" || data == "call" || data == "camera" || data == "game" || data == "player" || data == "event") resourceClass = envVar.constData(); } #ifdef RESOURCE_DEBUG qDebug() << "##### Using resource class " << resourceClass; #endif m_resourceSet = new ResourcePolicy::ResourceSet(resourceClass, this); m_resourceSet->setAlwaysReply(); connect(m_resourceSet, SIGNAL(resourcesGranted(QList)), this, SLOT(handleResourcesGranted())); connect(m_resourceSet, SIGNAL(resourcesDenied()), this, SLOT(handleResourcesDenied())); connect(m_resourceSet, SIGNAL(resourcesReleased()), this, SLOT(handleResourcesReleased())); connect(m_resourceSet, SIGNAL(lostResources()), this, SLOT(handleResourcesLost())); connect(m_resourceSet, SIGNAL(resourcesReleasedByManager()), this, SLOT(handleResourcesReleasedByManager())); connect(m_resourceSet, SIGNAL(resourcesBecameAvailable(const QList)), this, SLOT(handleResourcesBecameAvailable(const QList))); ResourcePolicy::AudioResource *audioResource = new ResourcePolicy::AudioResource(resourceClass); audioResource->setProcessID(QCoreApplication::applicationPid()); audioResource->setStreamTag("media.name", "*"); m_resourceSet->addResourceObject(audioResource); m_resourceSet->update(); } ResourcePolicyInt::~ResourcePolicyInt() { delete m_resourceSet; m_resourceSet = 0; #ifdef RESOURCE_DEBUG qDebug() << "##### Tearing down singleton."; #endif } void ResourcePolicyInt::addClient(ResourcePolicyImpl *client) { clientEntry entry; entry.id = clientid++; entry.client = client; entry.status = Initial; entry.videoEnabled = false; m_clients.insert(entry.client, entry); #ifdef RESOURCE_DEBUG qDebug() << "##### Add client " << client << " : " << entry.id; #endif } void ResourcePolicyInt::removeClient(ResourcePolicyImpl *client) { QMap::iterator i = m_clients.find(client); if (i != m_clients.end()) { #ifdef RESOURCE_DEBUG qDebug() << "##### Remove client " << client << " : " << i.value().id; #endif if (i.value().status == GrantedResource) --m_acquired; m_clients.erase(i); } if (m_acquired == 0 && m_status != Initial) { #ifdef RESOURCE_DEBUG qDebug() << "##### Remove client, acquired = 0, release"; #endif m_resourceSet->release(); m_status = Initial; } } bool ResourcePolicyInt::isVideoEnabled(const ResourcePolicyImpl *client) const { QMap::const_iterator i = m_clients.find(client); if (i != m_clients.constEnd()) return i.value().videoEnabled; return false; } void ResourcePolicyInt::setVideoEnabled(const ResourcePolicyImpl *client, bool videoEnabled) { bool update = false; QMap::iterator i = m_clients.find(client); if (i != m_clients.end()) { if (videoEnabled == i.value().videoEnabled) return; if (videoEnabled) { if (m_video > 0) { i.value().videoEnabled = true; } else { m_resourceSet->addResource(ResourcePolicy::VideoPlaybackType); update = true; } ++m_video; } else { --m_video; i.value().videoEnabled = false; if (m_video == 0) { m_resourceSet->deleteResource(ResourcePolicy::VideoPlaybackType); update = true; } } } if (update) m_resourceSet->update(); } void ResourcePolicyInt::acquire(const ResourcePolicyImpl *client) { QMap::iterator i = m_clients.find(client); if (i != m_clients.end()) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": ACQUIRE"; #endif if (i.value().status == Initial) { if (m_status == RequestedResource) { i.value().status = RequestedResource; #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": Already requesting, set client as RequestResource and return"; #endif return; } if (m_status == GrantedResource) { ++m_acquired; #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": Already granted, set as GrantedResource and return"; #endif i.value().status = GrantedResource; emit i.value().client->resourcesGranted(); return; } } else if (i.value().status == RequestedResource) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": Already requesting, return"; #endif return; } else { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": Already granted, return "; #endif return; } i.value().status = RequestedResource; m_status = RequestedResource; #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": ACQUIRE call resourceSet->acquire()"; #endif // If m_status was Initial this is the first time resources are requested, // so let's actually do the acquiring m_resourceSet->acquire(); } } void ResourcePolicyInt::release(const ResourcePolicyImpl *client) { QMap::iterator i = m_clients.find(client); if (i != m_clients.end()) { if (i.value().status == GrantedResource) { i.value().status = Initial; --m_acquired; #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": RELEASE, acquired (" << m_acquired << ")"; #endif emit i.value().client->resourcesReleased(); } } if (m_acquired == 0 && m_status != Initial) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": RELEASE call resourceSet->release()"; #endif m_resourceSet->release(); m_status = Initial; } } bool ResourcePolicyInt::isGranted(const ResourcePolicyImpl *client) const { QMap::const_iterator i = m_clients.find(client); if (i != m_clients.constEnd()) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": IS GRANTED, status: " << i.value().status; #endif return i.value().status == GrantedResource; } return false; } bool ResourcePolicyInt::isAvailable() const { #ifdef RESOURCE_DEBUG qDebug() << "##### isAvailable " << m_available; #endif return m_available; } void ResourcePolicyInt::handleResourcesGranted() { m_status = GrantedResource; QMap::iterator i = m_clients.begin(); while (i != m_clients.end()) { if (i.value().status == RequestedResource) { ++m_acquired; #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": HANDLE GRANTED, acquired (" << m_acquired << ") emitting resourcesGranted()"; #endif i.value().status = GrantedResource; emit i.value().client->resourcesGranted(); } ++i; } } void ResourcePolicyInt::handleResourcesDenied() { m_status = Initial; m_acquired = 0; QMap::iterator i = m_clients.begin(); while (i != m_clients.end()) { if (i.value().status == RequestedResource) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": HANDLE DENIED, acquired (" << m_acquired << ") emitting resourcesDenied()"; #endif i.value().status = Initial; emit i.value().client->resourcesDenied(); } // Do we need to act for clients that are in granted state? ++i; } } void ResourcePolicyInt::handleResourcesReleased() { m_status = Initial; m_acquired = 0; QMap::iterator i = m_clients.begin(); while (i != m_clients.end()) { if (i.value().status != Initial) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": HANDLE RELEASED, acquired (" << m_acquired << ") emitting resourcesReleased()"; #endif i.value().status = Initial; emit i.value().client->resourcesReleased(); } ++i; } } void ResourcePolicyInt::handleResourcesLost() { // If resources were granted switch to acquiring state, // so that if the resources are freed elsewhere we // will acquire them again properly. if (m_status == GrantedResource) m_status = RequestedResource; m_acquired = 0; QMap::iterator i = m_clients.begin(); while (i != m_clients.end()) { if (i.value().status == GrantedResource) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": HANDLE LOST, acquired (" << m_acquired << ") emitting resourcesLost()"; #endif i.value().status = RequestedResource; emit i.value().client->resourcesLost(); } ++i; } } void ResourcePolicyInt::handleResourcesReleasedByManager() { if (m_status != Initial) m_status = Initial; m_acquired = 0; QMap::iterator i = m_clients.begin(); while (i != m_clients.end()) { if (i.value().status != Initial) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": HANDLE RELEASEDBYMANAGER, acquired (" << m_acquired << ") emitting resourcesLost()"; #endif i.value().status = Initial; emit i.value().client->resourcesLost(); } ++i; } } void ResourcePolicyInt::handleResourcesBecameAvailable(const QList &resources) { bool available = false; for (int i = 0; i < resources.size(); ++i) { if (resources.at(i) == ResourcePolicy::AudioPlaybackType) available = true; } availabilityChanged(available); } void ResourcePolicyInt::availabilityChanged(bool available) { if (available == m_available) return; m_available = available; QMap::const_iterator i = m_clients.constBegin(); while (i != m_clients.constEnd()) { #ifdef RESOURCE_DEBUG qDebug() << "##### " << i.value().id << ": emitting availabilityChanged(" << m_available << ")"; #endif emit i.value().client->availabilityChanged(m_available); ++i; } }