diff --git a/src/ChannelListener.cpp b/src/ChannelListener.cpp deleted file mode 100644 index c6cc0d2a4..000000000 --- a/src/ChannelListener.cpp +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2020-2021 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -#include "ChannelListener.h" -#include "Channel.h" -#include "User.h" - -#ifdef MUMBLE -# include "ServerHandler.h" -# include "Database.h" -# include "Global.h" -#endif - -#include -#include - -// init static instance -ChannelListener ChannelListener::s_instance; - -ChannelListener::ChannelListener() - : QObject(nullptr), m_listenerLock(), m_listeningUsers(), m_listenedChannels() -#ifdef MUMBLE - , - m_volumeLock(), m_listenerVolumeAdjustments(), m_initialSyncDone(false) -#endif -{ -} - -void ChannelListener::addListenerImpl(unsigned int userSession, int channelID) { - QWriteLocker lock(&m_listenerLock); - - m_listeningUsers[userSession] << channelID; - m_listenedChannels[channelID] << userSession; -} - -void ChannelListener::removeListenerImpl(unsigned int userSession, int channelID) { - QWriteLocker lock(&m_listenerLock); - - m_listeningUsers[userSession].remove(channelID); - m_listenedChannels[channelID].remove(userSession); -} - -bool ChannelListener::isListeningImpl(unsigned int userSession, int channelID) const { - QReadLocker lock(&m_listenerLock); - - return m_listenedChannels[channelID].contains(userSession); -} - -bool ChannelListener::isListeningToAnyImpl(unsigned int userSession) const { - QReadLocker lock(&m_listenerLock); - - return !m_listeningUsers[userSession].isEmpty(); -} - -bool ChannelListener::isListenedByAnyImpl(int channelID) const { - QReadLocker lock(&m_listenerLock); - - return !m_listenedChannels[channelID].isEmpty(); -} - -const QSet< unsigned int > ChannelListener::getListenersForChannelImpl(int channelID) const { - QReadLocker lock(&m_listenerLock); - - return m_listenedChannels[channelID]; -} - -const QSet< int > ChannelListener::getListenedChannelsForUserImpl(unsigned int userSession) const { - QReadLocker lock(&m_listenerLock); - - return m_listeningUsers[userSession]; -} - -int ChannelListener::getListenerCountForChannelImpl(int channelID) const { - QReadLocker lock(&m_listenerLock); - - return m_listenedChannels[channelID].size(); -} - -int ChannelListener::getListenedChannelCountForUserImpl(unsigned int userSession) const { - QReadLocker lock(&m_listenerLock); - - return m_listeningUsers[userSession].size(); -} - -#ifdef MUMBLE -void ChannelListener::setListenerLocalVolumeAdjustmentImpl(int channelID, float volumeAdjustment) { - float oldValue; - { - QWriteLocker lock(&m_volumeLock); - - oldValue = m_listenerVolumeAdjustments.value(channelID, 1.0f); - m_listenerVolumeAdjustments.insert(channelID, volumeAdjustment); - } - - if (oldValue != volumeAdjustment) { - emit localVolumeAdjustmentsChanged(channelID, volumeAdjustment, oldValue); - } -} - -float ChannelListener::getListenerLocalVolumeAdjustmentImpl(int channelID) const { - QReadLocker lock(&m_volumeLock); - - return m_listenerVolumeAdjustments.value(channelID, 1.0f); -} - -QHash< int, float > ChannelListener::getAllListenerLocalVolumeAdjustmentsImpl(bool filter) const { - QReadLocker lock(&m_volumeLock); - - if (!filter) { - return m_listenerVolumeAdjustments; - } else { - QHash< int, float > volumeMap; - - QHashIterator< int, float > it(m_listenerVolumeAdjustments); - - while (it.hasNext()) { - it.next(); - - if (it.value() != 1.0f) { - volumeMap.insert(it.key(), it.value()); - } - } - - return volumeMap; - } -} - -void ChannelListener::setInitialServerSyncDoneImpl(bool done) { - m_initialSyncDone.store(done); -} -#endif - -void ChannelListener::clearImpl(){ { QWriteLocker lock(&m_listenerLock); -m_listeningUsers.clear(); -m_listenedChannels.clear(); -} -#ifdef MUMBLE -{ - QWriteLocker lock(&m_volumeLock); - m_listenerVolumeAdjustments.clear(); -} -#endif -} - - -ChannelListener &ChannelListener::get() { - return s_instance; -} - - -void ChannelListener::addListener(unsigned int userSession, int channelID) { - get().addListenerImpl(userSession, channelID); -} - -void ChannelListener::addListener(const User *user, const Channel *channel) { - get().addListenerImpl(user->uiSession, channel->iId); -} - -void ChannelListener::removeListener(unsigned int userSession, int channelID) { - get().removeListenerImpl(userSession, channelID); -} - -void ChannelListener::removeListener(const User *user, const Channel *channel) { - get().removeListenerImpl(user->uiSession, channel->iId); -} - -bool ChannelListener::isListening(unsigned int userSession, int channelID) { - return get().isListeningImpl(userSession, channelID); -} - -bool ChannelListener::isListening(const User *user, const Channel *channel) { - return get().isListeningImpl(user->uiSession, channel->iId); -} - -bool ChannelListener::isListeningToAny(unsigned int userSession) { - return get().isListeningToAnyImpl(userSession); -} - -bool ChannelListener::isListeningToAny(const User *user) { - return get().isListeningToAnyImpl(user->uiSession); -} - -bool ChannelListener::isListenedByAny(int channelID) { - return get().isListenedByAnyImpl(channelID); -} - -bool ChannelListener::isListenedByAny(const Channel *channel) { - return get().isListenedByAnyImpl(channel->iId); -} - -const QSet< unsigned int > ChannelListener::getListenersForChannel(int channelID) { - return get().getListenersForChannelImpl(channelID); -} - -const QSet< unsigned int > ChannelListener::getListenersForChannel(const Channel *channel) { - return get().getListenersForChannelImpl(channel->iId); -} - -const QSet< int > ChannelListener::getListenedChannelsForUser(unsigned int userSession) { - return get().getListenedChannelsForUserImpl(userSession); -} - -const QSet< int > ChannelListener::getListenedChannelsForUser(const User *user) { - return get().getListenedChannelsForUserImpl(user->uiSession); -} - -int ChannelListener::getListenerCountForChannel(int channelID) { - return get().getListenerCountForChannelImpl(channelID); -} - -int ChannelListener::getListenerCountForChannel(const Channel *channel) { - return get().getListenerCountForChannelImpl(channel->iId); -} - -int ChannelListener::getListenedChannelCountForUser(unsigned int userSession) { - return get().getListenedChannelCountForUserImpl(userSession); -} - -int ChannelListener::getListenedChannelCountForUser(const User *user) { - return get().getListenedChannelCountForUserImpl(user->uiSession); -} - -#ifdef MUMBLE -void ChannelListener::setListenerLocalVolumeAdjustment(int channelID, float volumeAdjustment) { - get().setListenerLocalVolumeAdjustmentImpl(channelID, volumeAdjustment); -} - -void ChannelListener::setListenerLocalVolumeAdjustment(const Channel *channel, float volumeAdjustment) { - get().setListenerLocalVolumeAdjustmentImpl(channel->iId, volumeAdjustment); -} - - -float ChannelListener::getListenerLocalVolumeAdjustment(int channelID) { - return get().getListenerLocalVolumeAdjustmentImpl(channelID); -} - -float ChannelListener::getListenerLocalVolumeAdjustment(const Channel *channel) { - return get().getListenerLocalVolumeAdjustmentImpl(channel->iId); -} - -QHash< int, float > ChannelListener::getAllListenerLocalVolumeAdjustments(bool filter) { - return get().getAllListenerLocalVolumeAdjustmentsImpl(filter); -} - -void ChannelListener::setInitialServerSyncDone(bool done) { - get().setInitialServerSyncDoneImpl(done); -} - -void ChannelListener::saveToDB() { - if (!Global::get().sh || Global::get().sh->qbaDigest.isEmpty() || Global::get().uiSession == 0) { - // Can't save as we don't have enough context - return; - } - - if (!get().m_initialSyncDone.load()) { - // If we were to save the listeners before the sync is done, we'd overwrite the list of listeners in the - // DB with an empty set, effectively erasing all set-up listeners. - qWarning("ChannelListener: Aborting save of user's listeners as initial ServerSync is not done yet"); - return; - } - - // Save the currently listened channels - Global::get().db->setChannelListeners(Global::get().sh->qbaDigest, - ChannelListener::getListenedChannelsForUser(Global::get().uiSession)); - // And also the currently set volume adjustments (if they're not set to 1.0) - Global::get().db->setChannelListenerLocalVolumeAdjustments( - Global::get().sh->qbaDigest, ChannelListener::getAllListenerLocalVolumeAdjustments(true)); -} -#endif - -void ChannelListener::clear() { - get().clearImpl(); -} diff --git a/src/ChannelListener.h b/src/ChannelListener.h deleted file mode 100644 index 3a03722ae..000000000 --- a/src/ChannelListener.h +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2020-2021 The Mumble Developers. All rights reserved. -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file at the root of the -// Mumble source tree or at . - -#ifndef MUMBLE_CHANNEL_LISTENER_H_ -#define MUMBLE_CHANNEL_LISTENER_H_ - -#include -#include -#include -#include - -#include - -class User; -class Channel; - -/// This class serves as a namespace for storing information about ChannelListeners. This is a feature -/// that allows a user to listen to a channel without being in it. Kinda similar to linked channels -/// except that this is something each user can do individually. -class ChannelListener : public QObject { -private: - Q_OBJECT - Q_DISABLE_COPY(ChannelListener) - -protected: - /// A lock for guarding m_listeningUsers as well as m_listenedChannels - mutable QReadWriteLock m_listenerLock; - /// A map between a user's session and a list of IDs of all channels the user is listening to - QHash< unsigned int, QSet< int > > m_listeningUsers; - /// A map between a channel's ID and a list of all user-sessions of users listening to that channel - QHash< int, QSet< unsigned int > > m_listenedChannels; -#ifdef MUMBLE - /// A lock for guarding m_listenerVolumeAdjustments - mutable QReadWriteLock m_volumeLock; - /// A map between channel IDs and local volume adjustments to be made for ChannelListeners - /// in that channel - QHash< int, float > m_listenerVolumeAdjustments; - - /// A flag indicating whether the initial synchronization with the server has finished yet - std::atomic< bool > m_initialSyncDone; -#endif - - /// The static ChannelListener instance returned by ChannelListener::get() - static ChannelListener s_instance; - - /// Constructor - ChannelListener(); - - /// Adds a listener to the channel. - /// - /// @param userSession The session ID of the user - /// @param channelID The ID of the channel - void addListenerImpl(unsigned int userSession, int channelID); - - /// Removes a listener from the channel. - /// - /// @param userSession The session ID of the user - /// @param channelID The ID of the channel - void removeListenerImpl(unsigned int userSession, int channelID); - - /// @param userSession The session ID of the user - /// @param channelID The ID of the channel - /// @returns Whether the given user is listening to the given channel - bool isListeningImpl(unsigned int userSession, int channelID) const; - - /// @param userSession The session ID of the user - /// @returns Whether this user is listening to any channel via the ChannelListener feature - bool isListeningToAnyImpl(unsigned int userSession) const; - - /// @param channelID The ID of the channel - /// @returns Whether any user listens to this channel via the ChannelListener feature - bool isListenedByAnyImpl(int channelID) const; - - /// @param channelID The ID of the channel - /// @returns A set of user sessions of users listening to the given channel - const QSet< unsigned int > getListenersForChannelImpl(int channelID) const; - - /// @param userSession The session ID of the user - /// @returns A set of channel IDs of channels the given user is listening to - const QSet< int > getListenedChannelsForUserImpl(unsigned int userSession) const; - - /// @param channelID The ID of the channel - /// @returns The amount of users that are listening to the given channel - int getListenerCountForChannelImpl(int channelID) const; - - /// @param userSession The session ID of the user - /// @returns The amount of channels the given user is listening to - int getListenedChannelCountForUserImpl(unsigned int userSession) const; - -#ifdef MUMBLE - /// Sets the local volume adjustment for any channelListener in the given channel. - /// - /// @param channelID The ID of the channel - /// @param volumeAdjustment The volume adjustment to apply - void setListenerLocalVolumeAdjustmentImpl(int channelID, float volumeAdjustment); - - /// @param channelID The ID of the channel - /// @param The local volume adjustment for the given channel. If none has been set, - /// 1.0f is being returned. - float getListenerLocalVolumeAdjustmentImpl(int channelID) const; - - /// @param filter Whether to filter out adjustments of 1 (which have no effect) - /// @returns A map between channel IDs and the currently set volume adjustment - QHash< int, float > getAllListenerLocalVolumeAdjustmentsImpl(bool filter = false) const; - - /// @done Whether the initial synchronization with the server is done yet - void setInitialServerSyncDoneImpl(bool done); -#endif - - /// Clears all ChannelListeners and volume adjustments - void clearImpl(); - -public: - /// @returns The static ChannelListener instance - static ChannelListener &get(); - - /// Adds a listener to the channel. - /// - /// @param userSession The session ID of the user - /// @param channelID The ID of the channel - static void addListener(unsigned int userSession, int channelID); - - /// Adds a listener to the channel. - /// - /// @param userSession The session ID of the user - /// @param channelID The ID of the channel - static void addListener(const User *user, const Channel *channel); - - - /// Removes a listener from the channel. - /// - /// @param userSession The session ID of the user - /// @param channelID The ID of the channel - static void removeListener(unsigned int userSession, int channelID); - - /// Removes a listener from the channel. - /// - /// @param userSession The session ID of the user - /// @param channelID The ID of the channel - static void removeListener(const User *user, const Channel *channel); - - - /// @param userSession The session ID of the user - /// @param channelID The ID of the channel - /// @returns Whether the given user is listening to the given channel - static bool isListening(unsigned int userSession, int channelID); - - /// @param channel A pointer to the channel object - /// @param user A pointer to the user object - /// @returns Whether the given user is listening to the given channel - static bool isListening(const User *user, const Channel *channel); - - - /// @param userSession The session ID of the user - /// @returns Whether this user is listening to any channel via the ChannelListener feature - static bool isListeningToAny(unsigned int userSession); - - /// @param user A pointer to the user object - /// @returns Whether this user is listening to any channel via the ChannelListener feature - static bool isListeningToAny(const User *user); - - - /// @param channelID The ID of the channel - /// @returns Whether any user listens to this channel via the ChannelListener feature - static bool isListenedByAny(int channelID); - - /// @param channel A pointer to the channel object - /// @returns Whether any user listens to this channel via the ChannelListener feature - static bool isListenedByAny(const Channel *channel); - - - /// @param channelID The ID of the channel - /// @returns A set of user sessions of users listening to the given channel - static const QSet< unsigned int > getListenersForChannel(int channelID); - - /// @param channel A pointer to the channel object - /// @returns A set of user sessions of users listening to the given channel - static const QSet< unsigned int > getListenersForChannel(const Channel *channel); - - - /// @param userSession The session ID of the user - /// @returns A set of channel IDs of channels the given user is listening to - static const QSet< int > getListenedChannelsForUser(unsigned int userSession); - - /// @param user A pointer to the user object - /// @returns A set of channel IDs of channels the given user is listening to - static const QSet< int > getListenedChannelsForUser(const User *user); - - - /// @param channelID The ID of the channel - /// @returns The amount of users that are listening to the given channel - static int getListenerCountForChannel(int channelID); - - /// @param channel A pointer to the channel object - /// @returns The amount of users that are listening to the given channel - static int getListenerCountForChannel(const Channel *channel); - - - /// @param userSession The session ID of the user - /// @returns The amount of channels the given user is listening to - static int getListenedChannelCountForUser(unsigned int userSession); - - /// @param user A pointer to the user object - /// @returns The amount of channels the given user is listening to - static int getListenedChannelCountForUser(const User *user); - - -#ifdef MUMBLE - /// Sets the local volume adjustment for any channelListener in the given channel. - /// - /// @param channelID The ID of the channel - /// @param volumeAdjustment The volume adjustment to apply - static void setListenerLocalVolumeAdjustment(int channelID, float volumeAdjustment); - - /// Sets the local volume adjustment for any channelListener in the given channel. - /// - /// @param channel A pointer to the channel object - /// @param volumeAdjustment The volume adjustment to apply - static void setListenerLocalVolumeAdjustment(const Channel *channel, float volumeAdjustment); - - - /// @param channelID The ID of the channel - /// @param The local volume adjustment for the given channel. If none has been set, - /// 1.0f is being returned. - static float getListenerLocalVolumeAdjustment(int channelID); - - /// @param channel A pointer to the channel object - /// @param The local volume adjustment for the given channel. If none has been set, - /// 1.0f is being returned. - static float getListenerLocalVolumeAdjustment(const Channel *channel); - - /// @param filter Whether to filter out adjustments of 1 (which have no effect) - /// @returns A map between channel IDs and the currently set volume adjustment - static QHash< int, float > getAllListenerLocalVolumeAdjustments(bool filter = false); - - /// @done Whether the initial synchronization with the server is done yet - static void setInitialServerSyncDone(bool done); - - /// Saves the current ChannelListener state to the database. - /// NOTE: This function may only be called from the main thread! - static void saveToDB(); -#endif - - /// Clears all ChannelListeners and volume adjustments - static void clear(); - -signals: -#ifdef MUMBLE - void localVolumeAdjustmentsChanged(int channelID, float newAdjustment, float oldAdjustment); -#endif -}; - -#endif // MUMBLE_CHANNEL_LISTENER_H_ diff --git a/src/ChannelListenerManager.cpp b/src/ChannelListenerManager.cpp new file mode 100644 index 000000000..b8d99d957 --- /dev/null +++ b/src/ChannelListenerManager.cpp @@ -0,0 +1,165 @@ +// Copyright 2020-2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#include "ChannelListenerManager.h" +#include "Channel.h" +#include "User.h" + +#ifdef MUMBLE +# include "ServerHandler.h" +# include "Database.h" +# include "Global.h" +#endif + +#include +#include + +ChannelListenerManager::ChannelListenerManager() + : QObject(nullptr), m_listenerLock(), m_listeningUsers(), m_listenedChannels() +#ifdef MUMBLE + , + m_volumeLock(), m_listenerVolumeAdjustments(), m_initialSyncDone(false) +#endif +{ +} + +void ChannelListenerManager::addListener(unsigned int userSession, int channelID) { + QWriteLocker lock(&m_listenerLock); + + m_listeningUsers[userSession] << channelID; + m_listenedChannels[channelID] << userSession; +} + +void ChannelListenerManager::removeListener(unsigned int userSession, int channelID) { + QWriteLocker lock(&m_listenerLock); + + m_listeningUsers[userSession].remove(channelID); + m_listenedChannels[channelID].remove(userSession); +} + +bool ChannelListenerManager::isListening(unsigned int userSession, int channelID) const { + QReadLocker lock(&m_listenerLock); + + return m_listenedChannels[channelID].contains(userSession); +} + +bool ChannelListenerManager::isListeningToAny(unsigned int userSession) const { + QReadLocker lock(&m_listenerLock); + + return !m_listeningUsers[userSession].isEmpty(); +} + +bool ChannelListenerManager::isListenedByAny(int channelID) const { + QReadLocker lock(&m_listenerLock); + + return !m_listenedChannels[channelID].isEmpty(); +} + +const QSet< unsigned int > ChannelListenerManager::getListenersForChannel(int channelID) const { + QReadLocker lock(&m_listenerLock); + + return m_listenedChannels[channelID]; +} + +const QSet< int > ChannelListenerManager::getListenedChannelsForUser(unsigned int userSession) const { + QReadLocker lock(&m_listenerLock); + + return m_listeningUsers[userSession]; +} + +int ChannelListenerManager::getListenerCountForChannel(int channelID) const { + QReadLocker lock(&m_listenerLock); + + return m_listenedChannels[channelID].size(); +} + +int ChannelListenerManager::getListenedChannelCountForUser(unsigned int userSession) const { + QReadLocker lock(&m_listenerLock); + + return m_listeningUsers[userSession].size(); +} + +#ifdef MUMBLE +void ChannelListenerManager::setListenerLocalVolumeAdjustment(int channelID, float volumeAdjustment) { + float oldValue; + { + QWriteLocker lock(&m_volumeLock); + + oldValue = m_listenerVolumeAdjustments.value(channelID, 1.0f); + m_listenerVolumeAdjustments.insert(channelID, volumeAdjustment); + } + + if (oldValue != volumeAdjustment) { + emit localVolumeAdjustmentsChanged(channelID, volumeAdjustment, oldValue); + } +} + +float ChannelListenerManager::getListenerLocalVolumeAdjustment(int channelID) const { + QReadLocker lock(&m_volumeLock); + + return m_listenerVolumeAdjustments.value(channelID, 1.0f); +} + +QHash< int, float > ChannelListenerManager::getAllListenerLocalVolumeAdjustments(bool filter) const { + QReadLocker lock(&m_volumeLock); + + if (!filter) { + return m_listenerVolumeAdjustments; + } else { + QHash< int, float > volumeMap; + + QHashIterator< int, float > it(m_listenerVolumeAdjustments); + + while (it.hasNext()) { + it.next(); + + if (it.value() != 1.0f) { + volumeMap.insert(it.key(), it.value()); + } + } + + return volumeMap; + } +} + +void ChannelListenerManager::setInitialServerSyncDone(bool done) { + m_initialSyncDone.store(done); +} + +void ChannelListenerManager::saveToDB() const { + if (!Global::get().sh || Global::get().sh->qbaDigest.isEmpty() || Global::get().uiSession == 0) { + // Can't save as we don't have enough context + return; + } + + if (!m_initialSyncDone.load()) { + // If we were to save the listeners before the sync is done, we'd overwrite the list of listeners in the + // DB with an empty set, effectively erasing all set-up listeners. + qWarning("ChannelListener: Aborting save of user's listeners as initial ServerSync is not done yet"); + return; + } + + // Save the currently listened channels + Global::get().db->setChannelListeners(Global::get().sh->qbaDigest, + getListenedChannelsForUser(Global::get().uiSession)); + // And also the currently set volume adjustments (if they're not set to 1.0) + Global::get().db->setChannelListenerLocalVolumeAdjustments(Global::get().sh->qbaDigest, + getAllListenerLocalVolumeAdjustments(true)); +} +#endif + +void ChannelListenerManager::clear() { + { + QWriteLocker lock(&m_listenerLock); + m_listeningUsers.clear(); + m_listenedChannels.clear(); + } +#ifdef MUMBLE + { + QWriteLocker lock(&m_volumeLock); + m_listenerVolumeAdjustments.clear(); + } +#endif +} diff --git a/src/ChannelListenerManager.h b/src/ChannelListenerManager.h new file mode 100644 index 000000000..3808eff56 --- /dev/null +++ b/src/ChannelListenerManager.h @@ -0,0 +1,122 @@ +// Copyright 2020-2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#ifndef MUMBLE_CHANNELLISTENERMANAGER_H_ +#define MUMBLE_CHANNELLISTENERMANAGER_H_ + +#include +#include +#include +#include + +#include + +class User; +class Channel; + +/// This class serves as a namespace for storing information about ChannelListeners. This is a feature +/// that allows a user to listen to a channel without being in it. Kinda similar to linked channels +/// except that this is something each user can do individually. +class ChannelListenerManager : public QObject { +private: + Q_OBJECT + Q_DISABLE_COPY(ChannelListenerManager) + +protected: + /// A lock for guarding m_listeningUsers as well as m_listenedChannels + mutable QReadWriteLock m_listenerLock; + /// A map between a user's session and a list of IDs of all channels the user is listening to + QHash< unsigned int, QSet< int > > m_listeningUsers; + /// A map between a channel's ID and a list of all user-sessions of users listening to that channel + QHash< int, QSet< unsigned int > > m_listenedChannels; +#ifdef MUMBLE + /// A lock for guarding m_listenerVolumeAdjustments + mutable QReadWriteLock m_volumeLock; + /// A map between channel IDs and local volume adjustments to be made for ChannelListeners + /// in that channel + QHash< int, float > m_listenerVolumeAdjustments; + + /// A flag indicating whether the initial synchronization with the server has finished yet + std::atomic< bool > m_initialSyncDone; +#endif + +public: + /// Constructor + explicit ChannelListenerManager(); + + /// Adds a listener to the channel. + /// + /// @param userSession The session ID of the user + /// @param channelID The ID of the channel + void addListener(unsigned int userSession, int channelID); + + /// Removes a listener from the channel. + /// + /// @param userSession The session ID of the user + /// @param channelID The ID of the channel + void removeListener(unsigned int userSession, int channelID); + + /// @param userSession The session ID of the user + /// @param channelID The ID of the channel + /// @returns Whether the given user is listening to the given channel + bool isListening(unsigned int userSession, int channelID) const; + + /// @param userSession The session ID of the user + /// @returns Whether this user is listening to any channel via the ChannelListener feature + bool isListeningToAny(unsigned int userSession) const; + + /// @param channelID The ID of the channel + /// @returns Whether any user listens to this channel via the ChannelListener feature + bool isListenedByAny(int channelID) const; + + /// @param channelID The ID of the channel + /// @returns A set of user sessions of users listening to the given channel + const QSet< unsigned int > getListenersForChannel(int channelID) const; + + /// @param userSession The session ID of the user + /// @returns A set of channel IDs of channels the given user is listening to + const QSet< int > getListenedChannelsForUser(unsigned int userSession) const; + + /// @param channelID The ID of the channel + /// @returns The amount of users that are listening to the given channel + int getListenerCountForChannel(int channelID) const; + + /// @param userSession The session ID of the user + /// @returns The amount of channels the given user is listening to + int getListenedChannelCountForUser(unsigned int userSession) const; + +#ifdef MUMBLE + /// Sets the local volume adjustment for any channelListener in the given channel. + /// + /// @param channelID The ID of the channel + /// @param volumeAdjustment The volume adjustment to apply + void setListenerLocalVolumeAdjustment(int channelID, float volumeAdjustment); + + /// @param channelID The ID of the channel + /// @param The local volume adjustment for the given channel. If none has been set, + /// 1.0f is being returned. + float getListenerLocalVolumeAdjustment(int channelID) const; + + /// @param filter Whether to filter out adjustments of 1 (which have no effect) + /// @returns A map between channel IDs and the currently set volume adjustment + QHash< int, float > getAllListenerLocalVolumeAdjustments(bool filter = false) const; + + /// @done Whether the initial synchronization with the server is done yet + void setInitialServerSyncDone(bool done); + + /// Saves the current ChannelListener state to the database. + /// NOTE: This function may only be called from the main thread! + void saveToDB() const; +#endif + + /// Clears all ChannelListeners and volume adjustments + void clear(); +signals: +#ifdef MUMBLE + void localVolumeAdjustmentsChanged(int channelID, float newAdjustment, float oldAdjustment); +#endif +}; + +#endif // MUMBLE_CHANNELLISTENERMANAGER_H_ diff --git a/src/mumble/AudioOutput.cpp b/src/mumble/AudioOutput.cpp index 33ebf6c5d..a35a9d0d6 100644 --- a/src/mumble/AudioOutput.cpp +++ b/src/mumble/AudioOutput.cpp @@ -9,7 +9,7 @@ #include "AudioOutputSample.h" #include "AudioOutputSpeech.h" #include "Channel.h" -#include "ChannelListener.h" +#include "ChannelListenerManager.h" #include "Message.h" #include "PacketDataStream.h" #include "PluginManager.h" @@ -504,12 +504,12 @@ bool AudioOutput::mix(void *outbuff, unsigned int frameCount) { user = speech->p; volumeAdjustment *= user->getLocalVolumeAdjustments(); - if (user->cChannel && ChannelListener::isListening(Global::get().uiSession, user->cChannel->iId) + if (user->cChannel && Global::get().channelListenerManager->isListening(Global::get().uiSession, user->cChannel->iId) && (speech->ucFlags & SpeechFlags::Listen)) { // We are receiving this audio packet only because we are listening to the channel // the speaking user is in. Thus we receive the audio via our "listener proxy". // Thus we'll apply the volume adjustment for our listener proxy as well - volumeAdjustment *= ChannelListener::getListenerLocalVolumeAdjustment(user->cChannel); + volumeAdjustment *= Global::get().channelListenerManager->getListenerLocalVolumeAdjustment(user->cChannel->iId); } if (prioritySpeakerActive) { diff --git a/src/mumble/CMakeLists.txt b/src/mumble/CMakeLists.txt index 0d781c7d9..8432e7ee1 100644 --- a/src/mumble/CMakeLists.txt +++ b/src/mumble/CMakeLists.txt @@ -285,8 +285,8 @@ set(MUMBLE_SOURCES "${SHARED_SOURCE_DIR}/ACL.h" "${SHARED_SOURCE_DIR}/Channel.cpp" "${SHARED_SOURCE_DIR}/Channel.h" - "${SHARED_SOURCE_DIR}/ChannelListener.cpp" - "${SHARED_SOURCE_DIR}/ChannelListener.h" + "${SHARED_SOURCE_DIR}/ChannelListenerManager.cpp" + "${SHARED_SOURCE_DIR}/ChannelListenerManager.h" "${SHARED_SOURCE_DIR}/Connection.cpp" "${SHARED_SOURCE_DIR}/Connection.h" "${SHARED_SOURCE_DIR}/Group.cpp" diff --git a/src/mumble/Global.cpp b/src/mumble/Global.cpp index b8c001ad1..2a4dfb584 100644 --- a/src/mumble/Global.cpp +++ b/src/mumble/Global.cpp @@ -124,6 +124,8 @@ Global::Global(const QString &qsConfigPath) { bDebugDumpInput = false; bDebugPrintQueue = false; + channelListenerManager = std::make_unique(); + #if defined(Q_OS_WIN) QString appdata; wchar_t appData[MAX_PATH]; diff --git a/src/mumble/Global.h b/src/mumble/Global.h index d8748bb51..d5769169f 100644 --- a/src/mumble/Global.h +++ b/src/mumble/Global.h @@ -13,6 +13,9 @@ #include "Settings.h" #include "Timer.h" #include "Version.h" +#include "ChannelListenerManager.h" + +#include // Global helper class to spread variables around across threads. @@ -107,6 +110,7 @@ public: QString windowTitlePostfix; bool bDebugDumpInput; bool bDebugPrintQueue; + std::unique_ptr channelListenerManager; bool bHappyEaster; static const char ccHappyEaster[]; diff --git a/src/mumble/ListenerLocalVolumeDialog.cpp b/src/mumble/ListenerLocalVolumeDialog.cpp index 50ee97c24..2401da8b9 100644 --- a/src/mumble/ListenerLocalVolumeDialog.cpp +++ b/src/mumble/ListenerLocalVolumeDialog.cpp @@ -5,8 +5,9 @@ #include "ListenerLocalVolumeDialog.h" #include "Channel.h" -#include "ChannelListener.h" +#include "ChannelListenerManager.h" #include "ClientUser.h" +#include "Global.h" #include @@ -16,7 +17,7 @@ ListenerLocalVolumeDialog::ListenerLocalVolumeDialog(ClientUser *user, Channel * : QDialog(parent), m_user(user), m_channel(channel) { setupUi(this); - m_initialAdjustemt = ChannelListener::getListenerLocalVolumeAdjustment(m_channel); + m_initialAdjustemt = Global::get().channelListenerManager->getListenerLocalVolumeAdjustment(m_channel->iId); // Decibel formula: +6db = *2 // Calculate the db-shift from the set volume-faactor @@ -35,7 +36,7 @@ void ListenerLocalVolumeDialog::on_qsbUserLocalVolume_valueChanged(int value) { // Decibel formula: +6db = *2 // Calculate the volume-factor for the set db-shift - ChannelListener::setListenerLocalVolumeAdjustment(m_channel, + Global::get().channelListenerManager->setListenerLocalVolumeAdjustment(m_channel->iId, static_cast< float >(pow(2.0, qsUserLocalVolume->value() / 6.0))); } @@ -53,7 +54,7 @@ void ListenerLocalVolumeDialog::on_qbbUserLocalVolume_clicked(QAbstractButton *b void ListenerLocalVolumeDialog::reject() { // Restore to what has been set before the dialog - ChannelListener::setListenerLocalVolumeAdjustment(m_channel, m_initialAdjustemt); + Global::get().channelListenerManager->setListenerLocalVolumeAdjustment(m_channel->iId, m_initialAdjustemt); QDialog::reject(); } diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp index d4cbbb8c6..3fdf79f80 100644 --- a/src/mumble/MainWindow.cpp +++ b/src/mumble/MainWindow.cpp @@ -30,7 +30,7 @@ # include "OverlayClient.h" #endif #include "../SignalCurry.h" -#include "ChannelListener.h" +#include "ChannelListenerManager.h" #include "ListenerLocalVolumeDialog.h" #include "Markdown.h" #include "PTTButtonWidget.h" @@ -331,7 +331,7 @@ void MainWindow::setupGui() { QObject::connect( this, &MainWindow::userRemovedChannelListener, pmModel, static_cast< void (UserModel::*)(const ClientUser *, const Channel *) >(&UserModel::removeChannelListener)); - QObject::connect(&ChannelListener::get(), &ChannelListener::localVolumeAdjustmentsChanged, pmModel, + QObject::connect(Global::get().channelListenerManager.get(), &ChannelListenerManager::localVolumeAdjustmentsChanged, pmModel, &UserModel::on_channelListenerLocalVolumeAdjustmentChanged); // connect slots to PluginManager @@ -951,7 +951,7 @@ void MainWindow::toggleSearchDialogVisibility() { static void recreateServerHandler() { // New server connection, so the sync has not happened yet - ChannelListener::setInitialServerSyncDone(false); + Global::get().channelListenerManager->setInitialServerSyncDone(false); ServerHandlerPtr sh = Global::get().sh; if (sh && sh->isRunning()) { @@ -1696,7 +1696,7 @@ void MainWindow::qmListener_aboutToShow() { qmListener->addAction(qaListenerLocalVolume); if (cContextChannel) { qmListener->addAction(qaChannelListen); - qaChannelListen->setChecked(ChannelListener::isListening(Global::get().uiSession, cContextChannel->iId)); + qaChannelListen->setChecked(Global::get().channelListenerManager->isListening(Global::get().uiSession, cContextChannel->iId)); } } else { qmListener->addAction(qaEmpty); @@ -2148,7 +2148,7 @@ void MainWindow::qmChannel_aboutToShow() { // If the server's version is less than 1.4, the listening feature is not supported yet // and thus it doesn't make sense to show the action for it qmChannel->addAction(qaChannelListen); - qaChannelListen->setChecked(ChannelListener::isListening(Global::get().uiSession, c->iId)); + qaChannelListen->setChecked(Global::get().channelListenerManager->isListening(Global::get().uiSession, c->iId)); } qmChannel->addSeparator(); @@ -3198,11 +3198,11 @@ void MainWindow::serverDisconnected(QAbstractSocket::SocketError err, QString re if (Global::get().sh->hasSynchronized()) { // Note that the saving of the ChannelListeners has to be done, before resetting Global::get().uiSession // Save ChannelListeners - ChannelListener::saveToDB(); + Global::get().channelListenerManager->saveToDB(); } // clear ChannelListener - ChannelListener::clear(); + Global::get().channelListenerManager->clear(); Global::get().uiSession = 0; Global::get().pPermissions = ChanACL::None; diff --git a/src/mumble/Messages.cpp b/src/mumble/Messages.cpp index 2f8948397..80d2d3b0b 100644 --- a/src/mumble/Messages.cpp +++ b/src/mumble/Messages.cpp @@ -23,7 +23,7 @@ #ifdef USE_OVERLAY # include "Overlay.h" #endif -#include "ChannelListener.h" +#include "ChannelListenerManager.h" #include "PluginManager.h" #include "ServerHandler.h" #include "TalkingUI.h" @@ -188,11 +188,11 @@ void MainWindow::msgServerSync(const MumbleProto::ServerSync &msg) { QList< int > localListeners = Global::get().db->getChannelListeners(Global::get().sh->qbaDigest); if (!localListeners.isEmpty()) { - ChannelListener::setInitialServerSyncDone(false); + Global::get().channelListenerManager->setInitialServerSyncDone(false); Global::get().sh->startListeningToChannels(localListeners); } else { // If there are no listeners, then no synchronization is needed in the first place - ChannelListener::setInitialServerSyncDone(true); + Global::get().channelListenerManager->setInitialServerSyncDone(true); } { @@ -201,14 +201,14 @@ void MainWindow::msgServerSync(const MumbleProto::ServerSync &msg) { // officially exist. Therefore some code that would receive the change-event would try to get the respective // listener and fail due to it not existing yet. Therefore we block all signals while setting the volume // adjustments. - const QSignalBlocker blocker(ChannelListener::get()); + const QSignalBlocker blocker(Global::get().channelListenerManager.get()); QHash< int, float > volumeMap = Global::get().db->getChannelListenerLocalVolumeAdjustments(Global::get().sh->qbaDigest); QHashIterator< int, float > it(volumeMap); while (it.hasNext()) { it.next(); - ChannelListener::setListenerLocalVolumeAdjustment(it.key(), it.value()); + Global::get().channelListenerManager->setListenerLocalVolumeAdjustment(it.key(), it.value()); } } @@ -487,7 +487,7 @@ void MainWindow::msgUserState(const MumbleProto::UserState &msg) { continue; } - ChannelListener::addListener(pDst, c); + Global::get().channelListenerManager->addListener(pDst->uiSession, c->iId); emit userAddedChannelListener(pDst, c); QString logMsg; @@ -499,7 +499,7 @@ void MainWindow::msgUserState(const MumbleProto::UserState &msg) { // succecssfully told the server that we are listening to the respective channels. Even if this message // here has nothing to do with the actual initial synchronization, this means that we have been connected // to the server long enough for the synchronization to be done. - ChannelListener::setInitialServerSyncDone(true); + Global::get().channelListenerManager->setInitialServerSyncDone(true); } else if (pSelf && pSelf->cChannel == c) { logMsg = tr("%1 started listening to your channel").arg(Log::formatClientUser(pDst, Log::Target)); } @@ -516,7 +516,7 @@ void MainWindow::msgUserState(const MumbleProto::UserState &msg) { continue; } - ChannelListener::removeListener(pDst, c); + Global::get().channelListenerManager->removeListener(pDst->uiSession, c->iId); emit userRemovedChannelListener(pDst, c); QString logMsg; diff --git a/src/mumble/TalkingUI.cpp b/src/mumble/TalkingUI.cpp index eb394f42d..ab3da8aaa 100644 --- a/src/mumble/TalkingUI.cpp +++ b/src/mumble/TalkingUI.cpp @@ -5,7 +5,7 @@ #include "TalkingUI.h" #include "Channel.h" -#include "ChannelListener.h" +#include "ChannelListenerManager.h" #include "ClientUser.h" #include "MainWindow.h" #include "TalkingUIComponent.h" @@ -772,7 +772,7 @@ void TalkingUI::on_settingsChanged() { removeAllListeners(); if (Global::get().s.bTalkingUI_ShowLocalListeners) { if (self) { - const QSet< int > channels = ChannelListener::getListenedChannelsForUser(self->uiSession); + const QSet< int > channels = Global::get().channelListenerManager->getListenedChannelsForUser(self->uiSession); for (int currentChannelID : channels) { const Channel *channel = Channel::get(currentChannelID); diff --git a/src/mumble/UserModel.cpp b/src/mumble/UserModel.cpp index 0a0f8b349..a39b61dfe 100644 --- a/src/mumble/UserModel.cpp +++ b/src/mumble/UserModel.cpp @@ -15,7 +15,7 @@ #ifdef USE_OVERLAY # include "Overlay.h" #endif -#include "ChannelListener.h" +#include "ChannelListenerManager.h" #include "ServerHandler.h" #include "Usage.h" #include "User.h" @@ -1972,7 +1972,7 @@ QString UserModel::createDisplayString(const ClientUser &user, bool isChannelLis if (isChannelListener) { if (parentChannel && user.uiSession == Global::get().uiSession) { // Only the listener of the local user can have a volume adjustment - volumeAdjustment = ChannelListener::getListenerLocalVolumeAdjustment(parentChannel->iId); + volumeAdjustment = Global::get().channelListenerManager->getListenerLocalVolumeAdjustment(parentChannel->iId); } } else { volumeAdjustment = user.getLocalVolumeAdjustments(); diff --git a/src/mumble/main.cpp b/src/mumble/main.cpp index 0a8aae9a7..720d33dd8 100644 --- a/src/mumble/main.cpp +++ b/src/mumble/main.cpp @@ -28,7 +28,7 @@ #endif #include "ApplicationPalette.h" #include "Channel.h" -#include "ChannelListener.h" +#include "ChannelListenerManager.h" #include "ClientUser.h" #include "CrashReporter.h" #include "EnvUtils.h" @@ -671,7 +671,7 @@ int main(int argc, char **argv) { &TalkingUI::on_channelListenerAdded); QObject::connect(Global::get().mw, &MainWindow::userRemovedChannelListener, Global::get().talkingUI, &TalkingUI::on_channelListenerRemoved); - QObject::connect(&ChannelListener::get(), &ChannelListener::localVolumeAdjustmentsChanged, Global::get().talkingUI, + QObject::connect(Global::get().channelListenerManager.get(), &ChannelListenerManager::localVolumeAdjustmentsChanged, Global::get().talkingUI, &TalkingUI::on_channelListenerLocalVolumeAdjustmentChanged); QObject::connect(Global::get().mw, &MainWindow::serverSynchronized, Global::get().talkingUI, diff --git a/src/murmur/CMakeLists.txt b/src/murmur/CMakeLists.txt index 70e14e5a6..ee032f33e 100644 --- a/src/murmur/CMakeLists.txt +++ b/src/murmur/CMakeLists.txt @@ -41,8 +41,8 @@ set(MURMUR_SOURCES "${SHARED_SOURCE_DIR}/ACL.h" "${SHARED_SOURCE_DIR}/Channel.cpp" "${SHARED_SOURCE_DIR}/Channel.h" - "${SHARED_SOURCE_DIR}/ChannelListener.cpp" - "${SHARED_SOURCE_DIR}/ChannelListener.h" + "${SHARED_SOURCE_DIR}/ChannelListenerManager.cpp" + "${SHARED_SOURCE_DIR}/ChannelListenerManager.h" "${SHARED_SOURCE_DIR}/Connection.cpp" "${SHARED_SOURCE_DIR}/Connection.h" "${SHARED_SOURCE_DIR}/Group.cpp" diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index 16cb63221..3fd9ea74b 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -5,7 +5,6 @@ #include "ACL.h" #include "Channel.h" -#include "ChannelListener.h" #include "Connection.h" #include "Group.h" #include "Message.h" @@ -469,7 +468,7 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg if (!u->qsHash.isEmpty()) mpus.set_hash(u8(u->qsHash)); - foreach (int channelID, ChannelListener::getListenedChannelsForUser(u)) { + foreach (int channelID, m_channelListenerManager.getListenedChannelsForUser(u->uiSession)) { mpus.add_listening_channel_add(channelID); } @@ -700,7 +699,7 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) { } if (Meta::mp.iMaxListenersPerChannel >= 0 - && Meta::mp.iMaxListenersPerChannel - ChannelListener::getListenerCountForChannel(c) - 1 < 0) { + && Meta::mp.iMaxListenersPerChannel - m_channelListenerManager.getListenerCountForChannel(c->iId) - 1 < 0) { // A limit for the amount of listener proxies per channel is set and it has been reached already PERM_DENIED_FALLBACK(ChannelListenerLimit, 0x010400, QLatin1String("No more listeners allowed in this channel")); @@ -708,7 +707,7 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) { } if (Meta::mp.iMaxListenerProxiesPerUser >= 0 - && Meta::mp.iMaxListenerProxiesPerUser - ChannelListener::getListenedChannelCountForUser(uSource) + && Meta::mp.iMaxListenerProxiesPerUser - m_channelListenerManager.getListenedChannelCountForUser(uSource->uiSession) - passedChannelListener - 1 < 0) { // A limit for the amount of listener proxies per user is set and it has been reached already @@ -927,7 +926,7 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) { // Handle channel listening // Note that it is important to handle the listening channels after channel-joins foreach (Channel *c, listeningChannelsAdd) { - ChannelListener::addListener(uSource, c); + m_channelListenerManager.addListener(uSource->uiSession, c->iId); log(QString::fromLatin1("\"%1\" is now listening to channel \"%2\"").arg(QString(*uSource)).arg(QString(*c))); } @@ -935,7 +934,7 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) { Channel *c = qhChannels.value(msg.listening_channel_remove(i)); if (c) { - ChannelListener::removeListener(uSource, c); + m_channelListenerManager.removeListener(uSource->uiSession, c->iId); log(QString::fromLatin1("\"%1\" is no longer listening to \"%2\"").arg(QString(*uSource)).arg(QString(*c))); } @@ -1420,7 +1419,7 @@ void Server::msgTextMessage(ServerUser *uSource, MumbleProto::TextMessage &msg) foreach (User *p, c->qlUsers) { users.insert(static_cast< ServerUser * >(p)); } // Users only listening in that channel - foreach (unsigned int session, ChannelListener::getListenersForChannel(c)) { + foreach (unsigned int session, m_channelListenerManager.getListenersForChannel(c->iId)) { ServerUser *currentUser = qhUsers.value(session); if (currentUser) { users.insert(currentUser); @@ -1460,7 +1459,7 @@ void Server::msgTextMessage(ServerUser *uSource, MumbleProto::TextMessage &msg) // Users directly in that channel foreach (User *p, c->qlUsers) { users.insert(static_cast< ServerUser * >(p)); } // Users only listening in that channel - foreach (unsigned int session, ChannelListener::getListenersForChannel(c)) { + foreach (unsigned int session, m_channelListenerManager.getListenersForChannel(c->iId)) { ServerUser *currentUser = qhUsers.value(session); if (currentUser) { users.insert(currentUser); diff --git a/src/murmur/MurmurIce.cpp b/src/murmur/MurmurIce.cpp index db549c514..7f03b3ef5 100644 --- a/src/murmur/MurmurIce.cpp +++ b/src/murmur/MurmurIce.cpp @@ -7,7 +7,6 @@ #include "Ban.h" #include "Channel.h" -#include "ChannelListener.h" #include "Group.h" #include "Meta.h" #include "MurmurI.h" @@ -1736,7 +1735,7 @@ static void impl_Server_isListening(const ::Murmur::AMD_Server_isListeningPtr cb NEED_CHANNEL; NEED_PLAYER; - cb->ice_response(ChannelListener::isListening(user, channel)); + cb->ice_response(server->m_channelListenerManager.isListening(user->uiSession, channel->iId)); } static void impl_Server_getListeningChannels(const ::Murmur::AMD_Server_getListeningChannelsPtr cb, int server_id, @@ -1745,7 +1744,7 @@ static void impl_Server_getListeningChannels(const ::Murmur::AMD_Server_getListe NEED_PLAYER; ::Murmur::IntList channelIDs; - foreach (int currentChannelID, ChannelListener::getListenedChannelsForUser(user)) { + foreach (int currentChannelID, server->m_channelListenerManager.getListenedChannelsForUser(user->uiSession)) { channelIDs.push_back(currentChannelID); } @@ -1758,7 +1757,7 @@ static void impl_Server_getListeningUsers(const ::Murmur::AMD_Server_getListenin NEED_CHANNEL; ::Murmur::IntList userSessions; - foreach (unsigned int currentSession, ChannelListener::getListenersForChannel(channel)) { + foreach (unsigned int currentSession, server->m_channelListenerManager.getListenersForChannel(channel->iId)) { userSessions.push_back(currentSession); } diff --git a/src/murmur/RPC.cpp b/src/murmur/RPC.cpp index cb976c68b..f10147817 100644 --- a/src/murmur/RPC.cpp +++ b/src/murmur/RPC.cpp @@ -10,7 +10,6 @@ #endif #include "Channel.h" -#include "ChannelListener.h" #include "Group.h" #include "Meta.h" #include "Server.h" @@ -539,12 +538,12 @@ void Server::disconnectListener(QObject *obj) { } void Server::startListeningToChannel(ServerUser *user, Channel *cChannel) { - if (ChannelListener::isListening(user, cChannel)) { + if (m_channelListenerManager.isListening(user->uiSession, cChannel->iId)) { // The user is already listening to this channel return; } - ChannelListener::addListener(user, cChannel); + m_channelListenerManager.addListener(user->uiSession, cChannel->iId); MumbleProto::UserState mpus; mpus.set_session(user->uiSession); @@ -555,12 +554,12 @@ void Server::startListeningToChannel(ServerUser *user, Channel *cChannel) { } void Server::stopListeningToChannel(ServerUser *user, Channel *cChannel) { - if (!ChannelListener::isListening(user, cChannel)) { + if (!m_channelListenerManager.isListening(user->uiSession, cChannel->iId)) { // The user is not listening to this channel return; } - ChannelListener::removeListener(user, cChannel); + m_channelListenerManager.removeListener(user->uiSession, cChannel->iId); MumbleProto::UserState mpus; mpus.set_session(user->uiSession); diff --git a/src/murmur/Server.cpp b/src/murmur/Server.cpp index 5d8a789e0..0222590c0 100644 --- a/src/murmur/Server.cpp +++ b/src/murmur/Server.cpp @@ -7,7 +7,6 @@ #include "ACL.h" #include "Channel.h" -#include "ChannelListener.h" #include "Connection.h" #include "EnvUtils.h" #include "Group.h" @@ -1170,7 +1169,7 @@ void Server::processMsg(ServerUser *u, const char *data, int len) { buffer[0] = static_cast< char >(type | SpeechFlags::Normal); // Send audio to all users that are listening to the channel - foreach (unsigned int currentSession, ChannelListener::getListenersForChannel(c)) { + foreach (unsigned int currentSession, m_channelListenerManager.getListenersForChannel(c->iId)) { ServerUser *pDst = static_cast< ServerUser * >(qhUsers.value(currentSession)); if (pDst) { listeningUsers << pDst; @@ -1200,16 +1199,16 @@ void Server::processMsg(ServerUser *u, const char *data, int len) { // Send the audio stream to all users that are listening to the linked channel but are not // in the original channel the audio is coming from nor are they listening to the orignal // channel (in these cases they have received the audio already). - foreach (unsigned int currentSession, ChannelListener::getListenersForChannel(l)) { + foreach (unsigned int currentSession, m_channelListenerManager.getListenersForChannel(l->iId)) { ServerUser *pDst = static_cast< ServerUser * >(qhUsers.value(currentSession)); - if (pDst && pDst->cChannel != c && !ChannelListener::isListening(pDst, c)) { + if (pDst && pDst->cChannel != c && !m_channelListenerManager.isListening(pDst->uiSession, c->iId)) { listeningUsers << pDst; } } // Send audio to users in the linked channel foreach (User *p, l->qlUsers) { - if (!ChannelListener::isListening(p->uiSession, c->iId)) { + if (!m_channelListenerManager.isListening(p->uiSession, c->iId)) { ServerUser *pDst = static_cast< ServerUser * >(p); // As we send the audio to this particular user here, we want to make sure to not send it @@ -1248,7 +1247,7 @@ void Server::processMsg(ServerUser *u, const char *data, int len) { if (ChanACL::hasPermission(u, wc, ChanACL::Whisper, &acCache)) { foreach (User *p, wc->qlUsers) { channel.insert(static_cast< ServerUser * >(p)); } - foreach (unsigned int currentSession, ChannelListener::getListenersForChannel(wc)) { + foreach (unsigned int currentSession, m_channelListenerManager.getListenersForChannel(wc->iId)) { ServerUser *pDst = static_cast< ServerUser * >(qhUsers.value(currentSession)); if (pDst) { @@ -1276,7 +1275,7 @@ void Server::processMsg(ServerUser *u, const char *data, int len) { } } - foreach (unsigned int currentSession, ChannelListener::getListenersForChannel(tc)) { + foreach (unsigned int currentSession, m_channelListenerManager.getListenersForChannel(tc->iId)) { ServerUser *pDst = static_cast< ServerUser * >(qhUsers.value(currentSession)); if (pDst && (!group || Group::isMember(tc, tc, qsg, pDst))) { @@ -1637,17 +1636,17 @@ void Server::connectionClosed(QAbstractSocket::SocketError err, const QString &r setLastDisconnect(u); if (u->sState == ServerUser::Authenticated) { - if (ChannelListener::isListeningToAny(u)) { + if (m_channelListenerManager.isListeningToAny(u->uiSession)) { // Send nessage to all other clients that this particular user won't be listening // to any channel anymore MumbleProto::UserState mpus; mpus.set_session(u->uiSession); - foreach (int channelID, ChannelListener::getListenedChannelsForUser(u)) { + foreach (int channelID, m_channelListenerManager.getListenedChannelsForUser(u->uiSession)) { mpus.add_listening_channel_remove(channelID); // Also remove the client from the list on the server - ChannelListener::removeListener(u->uiSession, channelID); + m_channelListenerManager.removeListener(u->uiSession, channelID); } sendExcept(u, mpus); @@ -1868,8 +1867,8 @@ void Server::removeChannel(Channel *chan, Channel *dest) { emit userStateChanged(p); } - foreach (unsigned int userSession, ChannelListener::getListenersForChannel(chan)) { - ChannelListener::removeListener(userSession, chan->iId); + foreach (unsigned int userSession, m_channelListenerManager.getListenersForChannel(chan->iId)) { + m_channelListenerManager.removeListener(userSession, chan->iId); // Notify that all clients that have been listening to this channel, will do so no more MumbleProto::UserState mpus; diff --git a/src/murmur/Server.h b/src/murmur/Server.h index ac854cea6..f6e96bb5b 100644 --- a/src/murmur/Server.h +++ b/src/murmur/Server.h @@ -14,6 +14,7 @@ #include "ACL.h" #include "Ban.h" +#include "ChannelListenerManager.h" #include "HostAddress.h" #include "Message.h" #include "Mumble.pb.h" @@ -168,6 +169,8 @@ public: bool bValid; + ChannelListenerManager m_channelListenerManager; + void readParams(); int iCodecAlpha;