Author: dlee
Date: Wed Jul 31 10:38:56 2013
New Revision: 395883

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=395883
Log:
Holding bridge, and playing into a holding bridge, works as expected

Modified:
    team/dlee/ari-async-bridge/include/asterisk/bridge_features.h
    team/dlee/ari-async-bridge/include/asterisk/bridge_internal.h
    team/dlee/ari-async-bridge/include/asterisk/stasis_app_impl.h
    team/dlee/ari-async-bridge/res/res_stasis.c
    team/dlee/ari-async-bridge/res/res_stasis_bridge.c
    team/dlee/ari-async-bridge/res/res_stasis_playback.c
    team/dlee/ari-async-bridge/res/stasis/control.c
    team/dlee/ari-async-bridge/res/stasis/control.h

Modified: team/dlee/ari-async-bridge/include/asterisk/bridge_features.h
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/ari-async-bridge/include/asterisk/bridge_features.h?view=diff&rev=395883&r1=395882&r2=395883
==============================================================================
--- team/dlee/ari-async-bridge/include/asterisk/bridge_features.h (original)
+++ team/dlee/ari-async-bridge/include/asterisk/bridge_features.h Wed Jul 31 
10:38:56 2013
@@ -24,6 +24,8 @@
 
 #ifndef _ASTERISK_BRIDGING_FEATURES_H
 #define _ASTERISK_BRIDGING_FEATURES_H
+
+#include "asterisk/channel.h"
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {

Modified: team/dlee/ari-async-bridge/include/asterisk/bridge_internal.h
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/ari-async-bridge/include/asterisk/bridge_internal.h?view=diff&rev=395883&r1=395882&r2=395883
==============================================================================
--- team/dlee/ari-async-bridge/include/asterisk/bridge_internal.h (original)
+++ team/dlee/ari-async-bridge/include/asterisk/bridge_internal.h Wed Jul 31 
10:38:56 2013
@@ -36,6 +36,7 @@
 
 struct ast_bridge;
 struct ast_bridge_channel;
+struct ast_bridge_methods;
 
 /*!
  * \brief Register the new bridge with the system.

Modified: team/dlee/ari-async-bridge/include/asterisk/stasis_app_impl.h
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/ari-async-bridge/include/asterisk/stasis_app_impl.h?view=diff&rev=395883&r1=395882&r2=395883
==============================================================================
--- team/dlee/ari-async-bridge/include/asterisk/stasis_app_impl.h (original)
+++ team/dlee/ari-async-bridge/include/asterisk/stasis_app_impl.h Wed Jul 31 
10:38:56 2013
@@ -87,17 +87,6 @@
 
 /*!
  * \since 12
- * \brief Changes the bridge currently associated with a control object.
- *
- * \param control Control object for the channel to query.
- * \param bridge New bridge to set on the control object. Or \c NULL to clear
- *               the association.
- */
-void stasis_app_set_bridge(struct stasis_app_control *control,
-       struct ast_bridge *bridge);
-
-/*!
- * \since 12
  * \brief Gets the bridge currently associated with a control object.
  *
  * \param control Control object for the channel to query.
@@ -106,4 +95,17 @@
  */
 struct ast_bridge *stasis_app_get_bridge(struct stasis_app_control *control);
 
+
+/*!
+ * \since 12
+ * \brief Imparts the associated channel into the bridge.
+ *
+ * \param control Control object for the channel to query.
+ * \param bridge New bridge to set on the control object.
+ */
+void stasis_app_add_to_bridge(struct stasis_app_control *control,
+       struct ast_bridge *bridge);
+
+void stasis_app_remove_from_bridge(struct stasis_app_control *control);
+
 #endif /* _ASTERISK_RES_STASIS_H */

Modified: team/dlee/ari-async-bridge/res/res_stasis.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/ari-async-bridge/res/res_stasis.c?view=diff&rev=395883&r1=395882&r2=395883
==============================================================================
--- team/dlee/ari-async-bridge/res/res_stasis.c (original)
+++ team/dlee/ari-async-bridge/res/res_stasis.c Wed Jul 31 10:38:56 2013
@@ -594,6 +594,13 @@
                int r;
                int command_count;
 
+               if (stasis_app_get_bridge(control)) {
+                       /* Bridge is handling channel frames */
+                       control_wait(control);
+                       control_dispatch_all(control, chan);
+                       continue;
+               }
+
                r = ast_waitfor(chan, MAX_WAIT_MS);
 
                if (r < 0) {
@@ -614,10 +621,6 @@
                        continue;
                }
 
-               if (stasis_app_get_bridge(control)) {
-                       /* Bridge is handling channel frames */
-                       continue;
-               }
 
                f = ast_read(chan);
                if (!f) {

Modified: team/dlee/ari-async-bridge/res/res_stasis_bridge.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/ari-async-bridge/res/res_stasis_bridge.c?view=diff&rev=395883&r1=395882&r2=395883
==============================================================================
--- team/dlee/ari-async-bridge/res/res_stasis_bridge.c (original)
+++ team/dlee/ari-async-bridge/res/res_stasis_bridge.c Wed Jul 31 10:38:56 2013
@@ -40,23 +40,12 @@
        struct stasis_app_control *control,
        struct ast_channel *chan, void *data)
 {
-       struct ast_bridge_features *features;
        struct ast_bridge *bridge = data;
 
        ast_debug(3, "%s: Adding to bridge\n",
                        stasis_app_control_get_channel_id(control));
 
-       features = ast_bridge_features_new();
-       if (!features) {
-               ast_log(LOG_ERROR,
-                       "Failed to allocate bridge features; proceeding 
without.\n");
-       }
-
-       ast_bridge_impart(bridge,
-               chan,
-               NULL, /* swap channel */
-               features,
-               0); /* independent - false allows us to ast_bridge_depart() */
+       stasis_app_add_to_bridge(control, bridge);
 
        return NULL;
 }
@@ -85,7 +74,8 @@
                return NULL;
        }
 
-       ast_bridge_depart(chan);
+       stasis_app_remove_from_bridge(control);
+
        return NULL;
 }
 

Modified: team/dlee/ari-async-bridge/res/res_stasis_playback.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/ari-async-bridge/res/res_stasis_playback.c?view=diff&rev=395883&r1=395882&r2=395883
==============================================================================
--- team/dlee/ari-async-bridge/res/res_stasis_playback.c (original)
+++ team/dlee/ari-async-bridge/res/res_stasis_playback.c Wed Jul 31 10:38:56 
2013
@@ -34,6 +34,8 @@
 
 #include "asterisk/app.h"
 #include "asterisk/astobj2.h"
+#include "asterisk/bridge.h"
+#include "asterisk/bridge_internal.h"
 #include "asterisk/file.h"
 #include "asterisk/logger.h"
 #include "asterisk/module.h"
@@ -200,6 +202,7 @@
        RAII_VAR(char *, file, NULL, ast_free);
        int res;
        long offsetms;
+       struct ast_bridge *bridge;
 
        /* Even though these local variables look fairly pointless, the avoid
         * having a bunch of NULL's passed directly into
@@ -248,8 +251,19 @@
                return NULL;
        }
 
-       res = ast_control_streamfile_lang(chan, file, fwd, rev, stop, pause,
-               restart, playback->skipms, playback->language, &offsetms);
+       bridge = stasis_app_get_bridge(control);
+       if (bridge) {
+               struct ast_bridge_channel *bridge_chan;
+               ast_bridge_lock(bridge);
+               bridge_chan = bridge_find_channel(bridge, chan);
+               if (bridge_chan) {
+                       res = ast_bridge_channel_queue_playfile(bridge_chan, 
NULL, file, NULL);
+               }
+               ast_bridge_unlock(bridge);
+       } else {
+               res = ast_control_streamfile_lang(chan, file, fwd, rev, stop, 
pause,
+                       restart, playback->skipms, playback->language, 
&offsetms);
+       }
 
        playback_final_update(playback, offsetms, res,
                ast_channel_uniqueid(chan));

Modified: team/dlee/ari-async-bridge/res/stasis/control.c
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/ari-async-bridge/res/stasis/control.c?view=diff&rev=395883&r1=395882&r2=395883
==============================================================================
--- team/dlee/ari-async-bridge/res/stasis/control.c (original)
+++ team/dlee/ari-async-bridge/res/stasis/control.c Wed Jul 31 10:38:56 2013
@@ -40,6 +40,7 @@
 #include "asterisk/musiconhold.h"
 
 struct stasis_app_control {
+       ast_cond_t wait_cond;
        /*! Queue of commands to dispatch on the channel */
        struct ao2_container *command_queue;
        /*!
@@ -53,17 +54,37 @@
         */
        struct ast_bridge *bridge;
        /*!
+        * Holding place for channel's PBX while imparted to a bridge.
+        */
+       struct ast_pbx *pbx;
+       /*!
         * When set, /c app_stasis should exit and continue in the dialplan.
         */
        int is_done:1;
 };
 
+static void control_dtor(void *obj)
+{
+       struct stasis_app_control *control = obj;
+
+       ao2_cleanup(control->command_queue);
+       ast_cond_destroy(&control->wait_cond);
+}
+
 struct stasis_app_control *control_create(struct ast_channel *channel)
 {
-       struct stasis_app_control *control;
-
-       control = ao2_alloc(sizeof(*control), NULL);
+       RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+       int res;
+
+       control = ao2_alloc(sizeof(*control), control_dtor);
        if (!control) {
+               return NULL;
+       }
+
+       res = ast_cond_init(&control->wait_cond, NULL);
+       if (res != 0) {
+               ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
+                       strerror(errno));
                return NULL;
        }
 
@@ -71,12 +92,12 @@
                AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, NULL);
 
        if (!control->command_queue) {
-               ao2_cleanup(control);
                return NULL;
        }
 
        control->channel = channel;
 
+       ao2_ref(control, +1);
        return control;
 }
 
@@ -93,7 +114,10 @@
        }
 
        /* command_queue is a thread safe list; no lock needed */
-       ao2_link(control->command_queue, command);
+       ao2_lock(control->command_queue);
+       ao2_link_flags(control->command_queue, command, OBJ_NOLOCK);
+       ast_cond_signal(&control->wait_cond);
+       ao2_unlock(control->command_queue);
 
        ao2_ref(command, +1);
        return command;
@@ -421,21 +445,55 @@
        return 0;
 }
 
-void stasis_app_set_bridge(struct stasis_app_control *control,
+struct ast_bridge *stasis_app_get_bridge(struct stasis_app_control *control)
+{
+       if (!control) {
+               return NULL;
+       }
+       return control->bridge;
+}
+
+void stasis_app_add_to_bridge(struct stasis_app_control *control,
        struct ast_bridge *bridge)
+{
+       int res;
+
+       if (!control || !bridge) {
+               return;
+       }
+
+       /* Save off the channel's PBX */
+       ast_assert(!control->pbx || !ast_channel_pbx(control->channel));
+       if (!control->pbx) {
+               control->pbx = ast_channel_pbx(control->channel);
+               ast_channel_pbx_set(control->channel, NULL);
+       }
+
+       res = ast_bridge_impart(bridge,
+               control->channel,
+               NULL, /* swap channel */
+               NULL, /* features */
+               0); /* independent - false allows us to ast_bridge_depart() */
+
+       if (res != 0) {
+               ast_log(LOG_ERROR, "Error adding channel to bridge\n");
+               ast_channel_pbx_set(control->channel, control->pbx);
+               control->pbx = NULL;
+               return;
+       }
+
+       control->bridge = bridge;
+}
+
+void stasis_app_remove_from_bridge(struct stasis_app_control *control)
 {
        if (!control) {
                return;
        }
-       control->bridge = bridge;
-}
-
-struct ast_bridge *stasis_app_get_bridge(struct stasis_app_control *control)
-{
-       if (!control) {
-               return NULL;
-       }
-       return control->bridge;
+
+       ast_bridge_depart(control->channel);
+       ast_channel_pbx_set(control->channel, control->pbx);
+       control->pbx = NULL;
 }
 
 const char *stasis_app_control_get_channel_id(
@@ -479,3 +537,24 @@
        ao2_iterator_destroy(&i);
        return count;
 }
+
+void control_wait(struct stasis_app_control *control)
+{
+       ast_mutex_t *queue_lock;
+       if (!control) {
+               return;
+       }
+
+       ast_assert(control->command_queue != NULL);
+
+       queue_lock = ao2_object_get_lockaddr(control->command_queue);
+       ao2_lock(control->command_queue);
+       while (ao2_container_count(control->command_queue) == 0) {
+               int r = ast_cond_wait(&control->wait_cond, queue_lock);
+               if (r < 0) {
+                       ast_log(LOG_ERROR, "Error waiting on command queue\n");
+                       break;
+               }
+       }
+       ao2_unlock(control->command_queue);
+}

Modified: team/dlee/ari-async-bridge/res/stasis/control.h
URL: 
http://svnview.digium.com/svn/asterisk/team/dlee/ari-async-bridge/res/stasis/control.h?view=diff&rev=395883&r1=395882&r2=395883
==============================================================================
--- team/dlee/ari-async-bridge/res/stasis/control.h (original)
+++ team/dlee/ari-async-bridge/res/stasis/control.h Wed Jul 31 10:38:56 2013
@@ -48,6 +48,8 @@
 int control_dispatch_all(struct stasis_app_control *control,
        struct ast_channel *chan);
 
+void control_wait(struct stasis_app_control *control);
+
 int control_is_done(struct stasis_app_control *control);
 
 void control_continue(struct stasis_app_control *control);


--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits

Reply via email to