summaryrefslogtreecommitdiff
path: root/src/player/Publisher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/player/Publisher.cpp')
-rw-r--r--src/player/Publisher.cpp248
1 files changed, 248 insertions, 0 deletions
diff --git a/src/player/Publisher.cpp b/src/player/Publisher.cpp
new file mode 100644
index 0000000..01bbea3
--- /dev/null
+++ b/src/player/Publisher.cpp
@@ -0,0 +1,248 @@
+//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+
+#include "Publisher.h"
+
+#include "SubscriberInfo.h"
+#include "PublisherDefinitionRegistry.h"
+#include "Player.h"
+
+#include "../base/Exception.h"
+#include "../base/StringHelper.h"
+
+using namespace std;
+
+namespace avg {
+
+int Publisher::s_LastSubscriberID = 0;
+
+Publisher::Publisher()
+{
+ m_pPublisherDef = PublisherDefinition::create("");
+}
+
+Publisher::Publisher(const string& sTypeName)
+{
+ m_pPublisherDef = PublisherDefinitionRegistry::get()->getDefinition(sTypeName);
+ vector<MessageID> messageIDs = m_pPublisherDef->getMessageIDs();
+ for (unsigned i=0; i<messageIDs.size(); ++i) {
+ m_SignalMap[messageIDs[i]] = list<SubscriberInfoPtr>();
+ }
+}
+
+Publisher::~Publisher()
+{
+}
+
+int Publisher::subscribe(MessageID messageID, const py::object& callable)
+{
+ SubscriberInfoList& subscribers = safeFindSubscribers(messageID);
+ int subscriberID = s_LastSubscriberID;
+ s_LastSubscriberID++;
+// cerr << this << " subscribe " << messageID << ", " << subscriberID << endl;
+ subscribers.push_front(SubscriberInfoPtr(new SubscriberInfo(subscriberID, callable)));
+ return subscriberID;
+}
+
+void Publisher::unsubscribe(MessageID messageID, int subscriberID)
+{
+// cerr << this << " unsubscribe " << messageID << ", " << subscriberID << endl;
+// cerr << " ";
+// dumpSubscribers(messageID);
+ SubscriberInfoList& subscribers = safeFindSubscribers(messageID);
+ SubscriberInfoList::iterator it;
+ for (it = subscribers.begin(); it != subscribers.end(); it++) {
+ if ((*it)->getID() == subscriberID) {
+ unsubscribeIterator(messageID, it);
+ return;
+ }
+ }
+// cerr << " End of unsubscribe: ";
+// dumpSubscribers(messageID);
+ throwSubscriberNotFound(messageID, subscriberID);
+}
+
+void Publisher::unsubscribe1(int subscriberID)
+{
+ SignalMap::iterator it;
+ for (it = m_SignalMap.begin(); it != m_SignalMap.end(); ++it) {
+ SubscriberInfoList& subscribers = it->second;
+ SubscriberInfoList::iterator it2;
+ for (it2 = subscribers.begin(); it2 != subscribers.end(); it2++) {
+ if ((*it2)->getID() == subscriberID) {
+ MessageID messageID = it->first;
+ unsubscribeIterator(messageID, it2);
+ return;
+ }
+ }
+ }
+ throw Exception(AVG_ERR_INVALID_ARGS,
+ "Subscriber with ID "+toString(subscriberID)+" not found.");
+}
+
+void Publisher::unsubscribeCallable(MessageID messageID, const py::object& callable)
+{
+ SubscriberInfoList& subscribers = safeFindSubscribers(messageID);
+ SubscriberInfoList::iterator it;
+ for (it = subscribers.begin(); it != subscribers.end(); it++) {
+ if ((*it)->isCallable(callable)) {
+ unsubscribeIterator(messageID, it);
+ return;
+ }
+ }
+ throwSubscriberNotFound(messageID, -1);
+}
+
+int Publisher::getNumSubscribers(MessageID messageID)
+{
+ SubscriberInfoList& subscribers = safeFindSubscribers(messageID);
+ return subscribers.size();
+}
+
+bool Publisher::isSubscribed(MessageID messageID, int subscriberID)
+{
+ SubscriberInfoList& subscribers = safeFindSubscribers(messageID);
+ SubscriberInfoList::iterator it;
+ for (it = subscribers.begin(); it != subscribers.end(); it++) {
+ if ((*it)->getID() == subscriberID) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Publisher::isSubscribedCallable(MessageID messageID, const py::object& callable)
+{
+ SubscriberInfoList& subscribers = safeFindSubscribers(messageID);
+ SubscriberInfoList::iterator it;
+ for (it = subscribers.begin(); it != subscribers.end(); it++) {
+ if ((*it)->isCallable(callable)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void Publisher::publish(MessageID messageID)
+{
+ if (m_SignalMap.find(messageID) != m_SignalMap.end()) {
+ throw Exception(AVG_ERR_INVALID_ARGS, "Signal with ID "+toString(messageID)+
+ "already registered.");
+ }
+ m_SignalMap[messageID] = SubscriberInfoList();
+}
+
+void Publisher::removeSubscribers()
+{
+ SignalMap::iterator it;
+ for (it = m_SignalMap.begin(); it != m_SignalMap.end(); ++it) {
+ it->second = SubscriberInfoList();
+ }
+}
+
+void Publisher::notifySubscribers(MessageID messageID)
+{
+ SubscriberInfoList& subscribers = safeFindSubscribers(messageID);
+ if (!subscribers.empty()) {
+ py::list args;
+ notifySubscribersPy(messageID, args);
+ }
+}
+
+void Publisher::notifySubscribers(const string& sMsgName)
+{
+ MessageID messageID = m_pPublisherDef->getMessageID(sMsgName);
+ notifySubscribers(messageID);
+}
+
+void Publisher::notifySubscribersPy(MessageID messageID, const py::list& args)
+{
+// cerr << this << " notifySubscribers " << messageID << endl;
+// cerr << " ";
+// dumpSubscribers(messageID);
+ AVG_ASSERT(!(Player::get()->isTraversingTree()));
+ SubscriberInfoList& subscribers = safeFindSubscribers(messageID);
+ WeakSubscriberInfoList subRefs;
+ for (SubscriberInfoList::iterator it = subscribers.begin(); it != subscribers.end();
+ ++it)
+ {
+ subRefs.push_back(*it);
+ }
+ WeakSubscriberInfoList::iterator it;
+ for (it = subRefs.begin(); it != subRefs.end(); ++it) {
+// cerr << " next" << endl;
+ if (!(*it).expired()) {
+ SubscriberInfoPtr pSub = (*it).lock();
+ if (pSub->hasExpired()) {
+ // Python subscriber doesn't exist anymore -> auto-unsubscribe.
+ unsubscribe(messageID, pSub->getID());
+ } else {
+// cerr << " invoke: " << (*it)->getID() << endl;
+ pSub->invoke(args);
+ }
+ }
+ }
+// cerr << " end notify" << endl;
+}
+
+MessageID Publisher::genMessageID()
+{
+ return PublisherDefinitionRegistry::get()->genMessageID();
+}
+
+void Publisher::unsubscribeIterator(MessageID messageID, SubscriberInfoList::iterator it)
+{
+ m_SignalMap[messageID].erase(it);
+}
+
+
+Publisher::SubscriberInfoList& Publisher::safeFindSubscribers(MessageID messageID)
+{
+ if (m_SignalMap.find(messageID) == m_SignalMap.end()) {
+ throw Exception(AVG_ERR_INVALID_ARGS, "No signal with ID "+toString(messageID));
+ }
+ SubscriberInfoList& subscribers = m_SignalMap[messageID];
+ return subscribers;
+}
+
+void Publisher::throwSubscriberNotFound(MessageID messageID, int subscriberID)
+{
+ if (subscriberID == -1) {
+ throw Exception(AVG_ERR_INVALID_ARGS, "Signal with ID "+toString(messageID)+
+ " doesn't have a subscriber with the given callable.");
+ } else {
+ throw Exception(AVG_ERR_INVALID_ARGS, "Signal with ID "+toString(messageID)+
+ " doesn't have a subscriber with ID "+toString(subscriberID));
+ }
+}
+
+void Publisher::dumpSubscribers(MessageID messageID)
+{
+ SubscriberInfoList& subscribers = safeFindSubscribers(messageID);
+ SubscriberInfoList::iterator it;
+ for (it = subscribers.begin(); it != subscribers.end(); it++) {
+ cerr << (*it)->getID() << " ";
+ }
+ cerr << endl;
+}
+
+
+}