[asterisk-scf-commits] asterisk-scf/integration/bridging.git branch "mediamixer" created.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Sun Aug 21 21:20:39 CDT 2011


branch "mediamixer" has been created
        at  251a67ec3b6186a871ce282304e55f8b0d4a019c (commit)

- Log -----------------------------------------------------------------
commit 251a67ec3b6186a871ce282304e55f8b0d4a019c
Author: Joshua Colp <jcolp at digium.com>
Date:   Sun Aug 21 23:19:55 2011 -0300

    Enable mixing when needed and disable it when not.

diff --git a/src/MediaSplicer.cpp b/src/MediaSplicer.cpp
index a634be7..4c8f5ce 100755
--- a/src/MediaSplicer.cpp
+++ b/src/MediaSplicer.cpp
@@ -398,7 +398,7 @@ public:
         mBridgeId(bridgeId),
         mReplicator(replicator),
         mLogger(logger),
-        mMixer(true),
+        mMixer(false),
 	mAdapter(adapter)
     {
     }
diff --git a/src/SessionCollection.cpp b/src/SessionCollection.cpp
index f778e86..5fd7b8d 100644
--- a/src/SessionCollection.cpp
+++ b/src/SessionCollection.cpp
@@ -87,6 +87,13 @@ SessionWrapperPtr SessionCollection::addSession(const SessionPrx& session)
     SessionWrapperPtr newSession(new SessionWrapper(bridgedSession, mSplicer,  mReplicator, mLogger));
     mMap[key] = newSession;
     ++mSessionCounter;
+
+    // If this collection now requires mixing turn it on
+    if (mMap.size() > 2)
+    {
+        mSplicer->enableMixing();
+    }
+
     return newSession;
 }
 
@@ -201,4 +208,10 @@ void SessionCollection::removeSession(const BridgedSessionPtr& session)
     {
         mMap.erase(i);
     }
+
+    // If this collection does not require mixing make sure it is disabled
+    if (mMap.size() < 3)
+    {
+	mSplicer->disableMixing();
+    }
 }

commit 7454202d6af18eadd942732a5121e90f90cd3480
Author: Joshua Colp <jcolp at digium.com>
Date:   Sun Aug 21 03:36:58 2011 -0300

    Add infrastructure for mixing support. Right now it always attempts to do mixing (this will be changed to dynamically change as the need changes) and the actual mixing thread is not yet implemented.

diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index 1039be3..a19fd8d 100755
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -687,7 +687,7 @@ BridgeImpl::BridgeImpl(const string& name, const Ice::ObjectAdapterPtr& adapter,
         const Logger& logger) :
     mActivated(false),
     mState(state),
-    mSessions(new SessionCollection(adapter->getCommunicator(), name, replicator, logger)),
+    mSessions(new SessionCollection(adapter->getCommunicator(), name, replicator, logger, adapter)),
     mName(name),
     mObjAdapter(adapter),
     mListeners(listenerMgr),
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c7fbc72..e7a72e2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -26,6 +26,8 @@ astscf_component_add_files(bridgeservice ServiceUtil.h)
 astscf_component_add_files(bridgeservice DebugUtil.h)
 astscf_component_add_files(bridgeservice MediaSplicer.h)
 astscf_component_add_files(bridgeservice MediaSplicer.cpp)
+astscf_component_add_files(bridgeservice MediaMixer.h)
+astscf_component_add_files(bridgeservice MediaMixer.cpp)
 astscf_component_add_files(bridgeservice Tasks.h)
 astscf_component_add_files(bridgeservice InternalExceptions.h)
 astscf_component_add_files(bridgeservice BridgeServiceConfig.h)
diff --git a/src/MediaMixer.cpp b/src/MediaMixer.cpp
new file mode 100755
index 0000000..6ff52c6
--- /dev/null
+++ b/src/MediaMixer.cpp
@@ -0,0 +1,331 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#include "MediaMixer.h"
+#include <Ice/Ice.h>
+#include <IceUtil/Shared.h>
+#include <IceUtil/Handle.h>
+
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::Media::V1;
+using namespace std;
+
+namespace AsteriskSCF
+{
+namespace BridgeService
+{
+
+/**
+ * Interval (in milliseconds) that media is mixed in.
+ */
+#define MIXING_INTERVAL 20
+
+/**
+ * Implementation of a StreamSource which provides mixed audio.
+ */
+class MediaMixerSource : public StreamSource
+{
+public:
+    MediaMixerSource(const MediaMixerPtr& mixer) : mMixer(mixer) { }
+
+    void addSink(const StreamSinkPrx& sink, const Ice::Current&)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+        if (std::find(mSinks.begin(), mSinks.end(), sink) != mSinks.end())
+        {
+            return;
+        }
+
+        mSinks.push_back(sink);
+    }
+
+    void removeSink(const StreamSinkPrx& sink, const Ice::Current&)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+        mSinks.erase(std::remove(mSinks.begin(), mSinks.end(), sink), mSinks.end());
+
+        // If no more sinks exist then this should terminate
+        if (mSinks.empty())
+        {
+            mMixer->removeSource(this, mProxy);
+        }
+    }
+    
+    StreamSinkSeq getSinks(const Ice::Current&)
+    {
+        boost::shared_lock<boost::shared_mutex> lock(mLock);
+
+        return mSinks;
+    }
+    
+    FormatSeq getFormats(const Ice::Current&)
+    {
+        // This is not protected by the lock because once created this will never be altered
+        return mFormats;
+    }
+    
+    std::string getId(const Ice::Current&)
+    {
+        // Same goes for the id
+        return mProxy->ice_getIdentity().name;
+    }
+    
+    void requestFormat(const AsteriskSCF::Media::V1::FormatPtr&, const Ice::Current&)
+    {
+        throw MediaFormatSwitchException();
+    }
+
+    /**
+     * Internal function which sets our proxy.
+     */
+    void setProxy(const StreamSourcePrx& proxy)
+    {
+        mProxy = proxy;
+    }
+
+private:
+    /**
+     * Lock which protects this source.
+     */
+    boost::shared_mutex mLock;
+
+    /**
+     * Media mixer we are associated with.
+     */
+    MediaMixerPtr mMixer;
+
+    /**
+     * Proxy to ourselves.
+     */
+    StreamSourcePrx mProxy;
+
+    /**
+     * Sinks that we are writing media to.
+     */
+    StreamSinkSeq mSinks;
+
+    /**
+     * Formats supported by this source.
+     */
+    FormatSeq mFormats;
+};
+
+/**
+ * Implementation of a StreamSink which provides audio to be mixed into the bridge.
+ */
+class MediaMixerSink : public StreamSink
+{
+public:
+    MediaMixerSink(const MediaMixerPtr& mixer, const MediaMixerSourcePtr& source) :
+        mMixer(mixer), mLocalSource(source) { }
+
+    void write(const FrameSeq& frames, const Ice::Current&)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+        mFrames.insert(mFrames.begin(), frames.begin(), frames.end());
+    }
+    
+    void setSource(const StreamSourcePrx& source, const Ice::Current&)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+        if (source == 0)
+        {
+            mMixer->removeSink(this, mProxy);
+        }
+        else
+        {
+            mSource = source;
+        }
+    }
+    
+    StreamSourcePrx getSource(const Ice::Current&)
+    {
+        boost::shared_lock<boost::shared_mutex> lock(mLock);
+
+        return mSource;
+    }
+    
+    FormatSeq getFormats(const Ice::Current&)
+    {
+        return mFormats;
+    }
+    
+    std::string getId(const Ice::Current&)
+    {
+        return mProxy->ice_getIdentity().name;
+    }
+
+    /**
+     * Internal function which returns the latest frame to use in the mixer.
+     */
+    const FramePtr& getFrame()
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+        mProvidedFrame = mFrames.back();
+
+        if (mProvidedFrame)
+        {
+            mFrames.pop_back();
+        }
+
+        return mProvidedFrame;
+    }
+
+    /**
+     * Internal function which removes the latest frame, presumably having already been mixed.
+     */
+    const FramePtr popFrame()
+    {
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+        FramePtr frame = mProvidedFrame;
+        mProvidedFrame = 0;
+
+        return frame;
+    }
+
+    /**
+     * Internal function which sets our proxy.
+     */
+    void setProxy(const StreamSinkPrx& proxy)
+    {
+        mProxy = proxy;
+    }
+
+private:
+    /**
+     * Lock which protects this sink.
+     */
+    boost::shared_mutex mLock;
+
+    /**
+     * Media mixer we are associated with.
+     */
+    MediaMixerPtr mMixer;
+
+    /**
+     * Pointer to our source of media, this exists within this class because the two
+     * are inherently associated.
+     */
+    MediaMixerSourcePtr mLocalSource;
+
+    /**
+     * Proxy to ourselves.
+     */
+    StreamSinkPrx mProxy;
+
+    /**
+     * Sequence of received frames pending mixing.
+     */
+    FrameSeq mFrames;
+
+    /**
+     * Source of media for this sink.
+     */
+    StreamSourcePrx mSource;
+
+    /**
+     * Formats supported by this sink.
+     */
+    FormatSeq mFormats;
+
+    /**
+     * Frame we provided when getFrame was called.
+     */
+    FramePtr mProvidedFrame;
+};
+
+class MediaMixerI
+{
+public:
+    MediaMixerI(const Ice::ObjectAdapterPtr& adapter) : mAdapter(adapter), mTimer(new IceUtil::Timer()) { }
+
+    /**
+     * Object adapter that sinks/sources are on.
+     */
+    Ice::ObjectAdapterPtr mAdapter;
+
+    /**
+     * Vector of sinks for media.
+     */
+    std::vector<MediaMixerSinkPtr> mSinks;
+
+    /**
+     * Vector of sources for media.
+     */
+    std::vector<MediaMixerSourcePtr> mSources;
+
+    /**
+     * Timer thread used to mix the media.
+     */
+    IceUtil::TimerPtr mTimer;
+};
+
+MediaMixer::MediaMixer(const Ice::ObjectAdapterPtr& adapter) : mImpl(new MediaMixerI(adapter))
+{
+    mImpl->mTimer->scheduleRepeated(this, IceUtil::Time::milliSeconds(MIXING_INTERVAL));
+}
+
+void MediaMixer::createMixing(const Ice::Identity& sinkId, AsteriskSCF::Media::V1::StreamSinkPrx& mixerSink,
+                              const Ice::Identity& sourceId, AsteriskSCF::Media::V1::StreamSourcePrx& mixerSource)
+{
+    // The source is where mixed audio will originate from, within this implementation it essentially acts
+    // as a store of sinks we need to write to for this source
+    MediaMixerSourcePtr source = new MediaMixerSource(this);
+    mImpl->mSources.push_back(source);
+    Ice::Identity id = sourceId;
+    id.name += ".mixer";
+    mixerSource = StreamSourcePrx::uncheckedCast(mImpl->mAdapter->add(source, id));
+    source->setProxy(mixerSource);
+
+    // The sink is where the source will send audio to to be mixed into the bridge, the reason the local source
+    // is associated is because we need to know what media to remove from the mixed frame when writing out
+    MediaMixerSinkPtr sink = new MediaMixerSink(this, source);
+    mImpl->mSinks.push_back(sink);
+    id = sinkId;
+    id.name += ".mixer";
+    mixerSink = StreamSinkPrx::uncheckedCast(mImpl->mAdapter->add(sink, id));
+    sink->setProxy(mixerSink);
+}
+
+void MediaMixer::runTimerTask()
+{
+    // MIXING CODE GOES HERE
+}
+
+void MediaMixer::removeSource(const MediaMixerSourcePtr& source, const StreamSourcePrx& proxy)
+{
+    mImpl->mSources.erase(std::remove(mImpl->mSources.begin(), mImpl->mSources.end(), source), mImpl->mSources.end());
+    mImpl->mAdapter->remove(proxy->ice_getIdentity());
+}
+
+void MediaMixer::removeSink(const MediaMixerSinkPtr& sink, const StreamSinkPrx& proxy)
+{
+    mImpl->mSinks.erase(std::remove(mImpl->mSinks.begin(), mImpl->mSinks.end(), sink), mImpl->mSinks.end());
+    mImpl->mAdapter->remove(proxy->ice_getIdentity());
+}
+
+void MediaMixer::stop()
+{
+    mImpl->mTimer->destroy();
+}
+
+}
+}
diff --git a/src/MediaMixer.h b/src/MediaMixer.h
new file mode 100644
index 0000000..5475755
--- /dev/null
+++ b/src/MediaMixer.h
@@ -0,0 +1,76 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2011, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+#pragma once
+
+#include <IceUtil/Shared.h>
+#include <IceUtil/Timer.h>
+#include <AsteriskSCF/Media/MediaIf.h>
+#include <AsteriskSCF/logger.h>
+#include <boost/shared_ptr.hpp>
+
+namespace AsteriskSCF
+{
+namespace BridgeService
+{
+
+/**
+ * Forward declarations.
+ */
+class MediaMixerSource;
+class MediaMixerSink;
+
+/**
+ * Smart pointer type for MediaMixerSource class.
+ */
+typedef IceUtil::Handle<MediaMixerSource> MediaMixerSourcePtr;
+
+/**
+ * Smart pointer type for MediaMixerSink class.
+ */
+typedef IceUtil::Handle<MediaMixerSink> MediaMixerSinkPtr;
+
+/**
+ * Implementation details for MediaMixer class.
+ */ 
+class MediaMixerI;
+class MediaMixer : public IceUtil::TimerTask
+{
+public:
+    MediaMixer(const Ice::ObjectAdapterPtr&);
+
+    void createMixing(const Ice::Identity&, AsteriskSCF::Media::V1::StreamSinkPrx&,
+                      const Ice::Identity&, AsteriskSCF::Media::V1::StreamSourcePrx&);
+
+    void removeSource(const MediaMixerSourcePtr&, const AsteriskSCF::Media::V1::StreamSourcePrx&);
+    void removeSink(const MediaMixerSinkPtr&, const AsteriskSCF::Media::V1::StreamSinkPrx&);
+
+    void runTimerTask();
+    void stop();
+
+private:
+    /**
+     * Private implementation details for MediaMixer.
+     */
+    boost::shared_ptr<MediaMixerI> mImpl;
+};
+
+/**
+ * Smart pointer for above MediaMixer class.
+ */
+typedef IceUtil::Handle<MediaMixer> MediaMixerPtr;
+
+} // End of namespace BridgeService
+} // End of namespace AsteriskSCF
diff --git a/src/MediaSplicer.cpp b/src/MediaSplicer.cpp
index 2cde267..a634be7 100755
--- a/src/MediaSplicer.cpp
+++ b/src/MediaSplicer.cpp
@@ -14,6 +14,7 @@
  * at the top of the source tree.
  */
 #include "MediaSplicer.h"
+#include "MediaMixer.h"
 #include <IceUtil/Shared.h>
 #include <IceUtil/Handle.h>
 #include "BridgeServiceConfig.h"
@@ -385,19 +386,20 @@ private:
 };
 
 QueuedTasks createMediaConnectTasks(const SessionWrapperPtr& session, 
-    const AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionPrx,
-    const MediaConnectorIPtr& peer, const MediaSplicerIPtr& splicer);
-//
-// TODO: This needs to register the streams with an active threaded mixing element.
-//
+                                    const AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionPrx,
+                                    const MediaConnectorIPtr& peer, const MediaSplicerIPtr& splicer, bool mixer);
+
 class MediaSplicerI : public boost::enable_shared_from_this<MediaSplicerI>
 {
 public:
-    MediaSplicerI(const Ice::CommunicatorPtr& communicator, const string& bridgeId, const ReplicatorSmartPrx& replicator, const Logger& logger) :
+    MediaSplicerI(const Ice::CommunicatorPtr& communicator, const string& bridgeId, const ReplicatorSmartPrx& replicator, const Logger& logger,
+                  const Ice::ObjectAdapterPtr& adapter) :
         mCommunicator(communicator),
         mBridgeId(bridgeId),
         mReplicator(replicator),
-        mLogger(logger)
+        mLogger(logger),
+        mMixer(true),
+	mAdapter(adapter)
     {
     }
 
@@ -460,7 +462,7 @@ public:
         // An alternative is to pass back the queued tasks to the caller and let them start and stop the process.
         //
         ExecutorPtr taskExecutor(new Executor(createMediaConnectTasks(session, sessionPrx, existing, 
-            shared_from_this()), mLogger));
+                                                                      shared_from_this(), mMixer), mLogger));
         taskExecutor->start();
     }
 
@@ -493,18 +495,90 @@ public:
         return result;
     }
 
+    void enableMixing()
+    {
+        mMixer = true;
+    }
+
+    void disableMixing()
+    {
+        MediaMixerPtr mixer;
+        while ((mixer = mMediaMixers.back()))
+        {
+            mixer->stop();
+            mMediaMixers.pop_back();
+        }
+
+        mMixer = false;
+    }
+
+    void findCompatiblePairings(const StreamInformationDict& streams, vector<OutgoingPairing>& outgoing,
+                                vector<IncomingPairing>& incoming)
+    {
+        boost::shared_lock<boost::shared_mutex> lock(mLock);
+
+	// We create a copy of the vector so we do not end up connecting multiple streams to the same mixer
+	MediaMixers mixers = mMediaMixers;
+
+        for (StreamInformationDict::const_iterator stream = streams.begin();
+             stream != streams.end();
+             ++stream)
+        {
+            if (stream->second->state == Removed)
+            {
+                continue;
+            }
+
+	    MediaMixerPtr mixer = mixers.back();
+
+	    // How do we determine what the 'right' mixer is to use?
+	    if (mixer == 0)
+	    {
+		mLogger(Debug) << FUNLOG << ": creating media mixer.";
+		mixer = new MediaMixer(mAdapter);
+		mMediaMixers.push_back(mixer);
+	    }
+	    else
+	    {
+		mLogger(Debug) << FUNLOG << ": using found media mixer.";
+		mixers.pop_back();
+	    }
+
+            StreamSinkSeq sinks = stream->second->sinks;
+            StreamSourceSeq sources = stream->second->sources;
+
+            // Iterate through sources and sinks to connect them to the mixer
+            // Note that we must have a matching number of sinks and sources, this is so we can cancel out
+            // their media from the mixing
+            while (!sinks.empty() && !sources.empty())
+            {
+                // These proxies will contain the details for the mixer
+                StreamSourcePrx mixerSource;
+                StreamSinkPrx mixerSink;
+
+                // Ask the mixer to create a source and sink for our source and sink
+                mixer->createMixing(sinks.back()->ice_getIdentity(), mixerSink,
+                                    sources.back()->ice_getIdentity(), mixerSource);
+
+                // Now that we have done so we can create pairings
+                outgoing.push_back(OutgoingPairing(sinks.back(), mixerSource));
+                outgoing.push_back(OutgoingPairing(mixerSink, sources.back()));
+                incoming.push_back(IncomingPairing(sources.back(), mixerSink));
+                incoming.push_back(IncomingPairing(mixerSource, sinks.back()));
+
+                // These sink and source are completely done, don't touch them again
+                sinks.pop_back();
+                sources.pop_back();
+            }
+        }
+    }
+
     void findCompatiblePairings(const StreamInformationDict& streams, vector<OutgoingPairing>& outgoing,
                                 vector<IncomingPairing>& incoming,
                                 MediaConnectorIPtr connector,
                                 std::map<std::string, std::string>& connections,
                                 DirectMediaConnectionDict& directConnections)
     {
-        // If no streams are present we can not establish any pairings
-        if (streams.empty())
-        {
-            return;
-        }
-
         boost::shared_lock<boost::shared_mutex> lock(mLock);
 
         for (MediaConnectors::const_iterator i = mConnectors.begin(); i != mConnectors.end(); ++i)
@@ -586,11 +660,17 @@ private:
     string mBridgeId;
     ReplicatorSmartPrx mReplicator;
     Logger mLogger;
+    bool mMixer;
+    Ice::ObjectAdapterPtr mAdapter;
 
     typedef vector<MediaConnectorIPtr> MediaConnectors;
 
     MediaConnectors mConnectors;
 
+    typedef vector<MediaMixerPtr> MediaMixers;
+
+    MediaMixers mMediaMixers;
+
     bool hasPreferredCodecOverride()
     {
         //
@@ -676,24 +756,39 @@ private:
 class GetCompatiblePairings : public QueuedTask
 {
 public:
-    GetCompatiblePairings(const MediaSplicerIPtr& splicer, const MediaConnectorBuilderPtr& materials) :
+    GetCompatiblePairings(const MediaSplicerIPtr& splicer, const MediaConnectorBuilderPtr& materials, bool mixer) :
         QueuedTask("GetCompatiblePairings"),
         mSplicer(splicer),
-        mMaterials(materials)
+        mMaterials(materials),
+        mMixer(mixer)
     {
     }
 
 protected:
     bool executeImpl()
     {
-	mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings,
-                                         mMaterials->connector, mMaterials->connections, mMaterials->directConnections);
+        if (mMaterials->streams.empty())
+        {
+            return true;
+        }
+
+        if (mMixer == true)
+        {
+            mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings);
+        }
+        else
+        {
+            mSplicer->findCompatiblePairings(mMaterials->streams, mMaterials->outgoingPairings, mMaterials->incomingPairings,
+                                             mMaterials->connector, mMaterials->connections, mMaterials->directConnections);
+        }
+
         return true;
     }
 
 private:
     MediaSplicerIPtr mSplicer;
     MediaConnectorBuilderPtr mMaterials;
+    bool mMixer;
 };
 
 //
@@ -986,8 +1081,8 @@ private:
 };
 
 QueuedTasks createMediaConnectTasks(const SessionWrapperPtr& session, 
-    const AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionPrx, 
-    const MediaConnectorIPtr& peer, const MediaSplicerIPtr& splicer)
+                                    const AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionPrx, 
+                                    const MediaConnectorIPtr& peer, const MediaSplicerIPtr& splicer, bool mixer)
 {
     QueuedTasks tasks;
     MediaConnectorBuilderPtr materials(new MediaConnectorBuilder);
@@ -995,9 +1090,15 @@ QueuedTasks createMediaConnectTasks(const SessionWrapperPtr& session,
     materials->sessionPrx = sessionPrx;
     tasks.push_back(new GetStreams(session, materials));
     tasks.push_back(new CreateAndRegisterConnector(session, splicer, materials));
-    tasks.push_back(new GetCompatiblePairings(splicer, materials));
+    tasks.push_back(new GetCompatiblePairings(splicer, materials, mixer));
     tasks.push_back(new MakeConnections(materials));
-    tasks.push_back(new MakeDirectConnections(materials));
+
+    // We can not establish direct connections when doing mixing
+    if (mixer == false)
+    {
+        tasks.push_back(new MakeDirectConnections(materials));
+    }
+
     return tasks;
 }
 
@@ -1007,8 +1108,9 @@ QueuedTasks createMediaConnectTasks(const SessionWrapperPtr& session,
 using namespace AsteriskSCF::BridgeService;
 
 MediaSplicer::MediaSplicer(const Ice::CommunicatorPtr& comm, const std::string& bridgeId, const ReplicatorSmartPrx& replicator,
-        const Logger& logger) :
-    mImpl(new MediaSplicerI(comm, bridgeId, replicator, logger))
+                           const Logger& logger,
+                           const Ice::ObjectAdapterPtr& adapter) :
+    mImpl(new MediaSplicerI(comm, bridgeId, replicator, logger, adapter))
 {
 }
 
@@ -1021,3 +1123,13 @@ MediaConnectorPtr MediaSplicer::createReplica(const SessionPairingPtr& pairings)
 {
     return mImpl->createReplica(pairings);
 }
+
+void MediaSplicer::enableMixing()
+{
+    mImpl->enableMixing();
+}
+
+void MediaSplicer::disableMixing()
+{
+    mImpl->disableMixing();
+}
diff --git a/src/MediaSplicer.h b/src/MediaSplicer.h
index 31b3f19..80aa187 100644
--- a/src/MediaSplicer.h
+++ b/src/MediaSplicer.h
@@ -85,10 +85,12 @@ class MediaSplicer : public IceUtil::Shared
 {
 public:
     MediaSplicer(const Ice::CommunicatorPtr& comm, const std::string& bridgeId, const ReplicatorSmartPrx& replicator,
-            const AsteriskSCF::System::Logging::Logger& logger);
+                 const AsteriskSCF::System::Logging::Logger& logger, const Ice::ObjectAdapterPtr&);
     
     void connect(const SessionWrapperPtr& session, const AsteriskSCF::SessionCommunications::V1::SessionPrx& sessionPrx);
     MediaConnectorPtr createReplica(const AsteriskSCF::Replication::BridgeService::V1::SessionPairingPtr& pairings);
+    void enableMixing();
+    void disableMixing();
 
 private:
     boost::shared_ptr<MediaSplicerI> mImpl;
diff --git a/src/SessionCollection.cpp b/src/SessionCollection.cpp
index eb15ad9..f778e86 100644
--- a/src/SessionCollection.cpp
+++ b/src/SessionCollection.cpp
@@ -26,14 +26,15 @@ using namespace AsteriskSCF;
 using namespace std;
 
 SessionCollection::SessionCollection(const Ice::CommunicatorPtr& comm, const string& bridgeId,
-        const ReplicatorSmartPrx& replicator,
-        const Logger& logger) :
+                                     const ReplicatorSmartPrx& replicator,
+                                     const Logger& logger,
+                                     const Ice::ObjectAdapterPtr& adapter) :
     mCommunicator(comm),
     mReplicator(replicator),
     mLogger(logger),
     mBridgeId(bridgeId),
     mSessionCounter(0),
-    mSplicer(new MediaSplicer(comm, bridgeId, replicator, logger))
+    mSplicer(new MediaSplicer(comm, bridgeId, replicator, logger, adapter))
 {
 }
  
diff --git a/src/SessionCollection.h b/src/SessionCollection.h
index d306da9..d758e85 100644
--- a/src/SessionCollection.h
+++ b/src/SessionCollection.h
@@ -47,7 +47,8 @@ class SessionCollection : public IceUtil::Shared
 public:
     
     SessionCollection(const Ice::CommunicatorPtr& communicator, const std::string& bridgeId,
-            const ReplicatorSmartPrx& replicator, const AsteriskSCF::System::Logging::Logger& logger);
+                      const ReplicatorSmartPrx& replicator, const AsteriskSCF::System::Logging::Logger& logger,
+                      const Ice::ObjectAdapterPtr& adapter);
 
     /**
      * Obtains the SessionWrapper instance for the specified proxy.
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 6f2f1af..f9fcf25 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -31,6 +31,7 @@ astscf_component_add_files(bridge_unit_tests ../src/SessionCollection.cpp)
 astscf_component_add_files(bridge_unit_tests ../src/SessionOperations.cpp)
 astscf_component_add_files(bridge_unit_tests ../src/SessionWrapper.cpp)
 astscf_component_add_files(bridge_unit_tests ../src/MediaSplicer.cpp)
+astscf_component_add_files(bridge_unit_tests ../src/MediaMixer.cpp)
 astscf_component_add_files(bridge_unit_tests UnitTests.cpp)
 astscf_component_add_ice_libraries(bridge_unit_tests Ice)
 astscf_component_add_boost_libraries(bridge_unit_tests unit_test_framework thread)
diff --git a/test/UnitTests.cpp b/test/UnitTests.cpp
index 8a8ebb7..7af1dd8 100644
--- a/test/UnitTests.cpp
+++ b/test/UnitTests.cpp
@@ -351,7 +351,7 @@ BOOST_FIXTURE_TEST_CASE(testGetSeq, Fixture)
 {
     IceEnvironment iceEnv;
     AsteriskSCF::BridgeService::ReplicatorSmartPrx rep;
-    SessionCollectionPtr collection(new SessionCollection(iceEnv.communicator(), "test", rep, getLogger()));
+    SessionCollectionPtr collection(new SessionCollection(iceEnv.communicator(), "test", rep, getLogger(), 0));
 
     SessionPrx dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo0:default"));
     collection->replicaUpdate(createBridgedSession(Added, dummy));

commit d2c181b0734e4f4396e6f6a239a4bc371a5a618e
Merge: 0d72a5a 8b90641
Author: Joshua Colp <jcolp at digium.com>
Date:   Sat Aug 20 22:21:31 2011 -0300

    Merge branch 'master' into mediamixer


commit 8b9064121d04e22ab3277b8549f0ce8c6e2f69a2
Author: Mark Michelson <mmichelson at digium.com>
Date:   Thu Aug 18 12:37:21 2011 -0500

    Accommodate changes from oneshot-hooks branches.

diff --git a/test/TestBridging.cpp b/test/TestBridging.cpp
index f23c73c..f58155f 100644
--- a/test/TestBridging.cpp
+++ b/test/TestBridging.cpp
@@ -378,7 +378,7 @@ public:
         assert(eps.size() > 0 && eps[0] != 0);
         AsteriskSCF::SessionCommunications::V1::SessionEndpointPrx proxy(AsteriskSCF::SessionCommunications::V1::SessionEndpointPrx::checkedCast(eps[0]));
         assert(proxy);
-        AsteriskSCF::SessionCommunications::V1::SessionPrx session(proxy->createSession(id, 0));
+        AsteriskSCF::SessionCommunications::V1::SessionPrx session(proxy->createSession(id, 0, 0));
         assert(session);
         return session;
     }

-----------------------------------------------------------------------


-- 
asterisk-scf/integration/bridging.git



More information about the asterisk-scf-commits mailing list