Merge Mahmut's recording patches
[asterisk/asterisk.git] / channel.c
index 6e6638c..f1ea7f7 100755 (executable)
--- a/channel.c
+++ b/channel.c
@@ -33,6 +33,7 @@
 #include <asterisk/chanvars.h>
 #include <asterisk/linkedlists.h>
 #include <asterisk/indications.h>
+#include <asterisk/monitor.h>
 
 
 static int shutting_down = 0;
@@ -347,7 +348,8 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
                cur = cur->next;
                qlen++;
        }
-       if (qlen  > 128) {
+       /* Allow up to 96 voice frames outstanding, and up to 128 total frames */
+       if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen  > 128)) {
                if (fin->frametype != AST_FRAME_VOICE) {
                        ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
                        CRASH;
@@ -487,6 +489,10 @@ void ast_channel_free(struct ast_channel *chan)
                ast_log(LOG_WARNING, "Unable to find channel in list\n");
        if (chan->pvt->pvt)
                ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
+       /* Stop monitoring */
+       if (chan->monitor) {
+               chan->monitor->stop( chan, 0 );
+       }
        /* Free translatosr */
        if (chan->pvt->readtrans)
                ast_translator_free_path(chan->pvt->readtrans);
@@ -1026,6 +1032,10 @@ struct ast_frame *ast_read(struct ast_channel *chan)
                /* Answer the CDR */
                ast_setstate(chan, AST_STATE_UP);
                ast_cdr_answer(chan->cdr);
+       } else if( ( f->frametype == AST_FRAME_VOICE ) && chan->monitor && chan->monitor->read_stream ) {
+               if( ast_writestream( chan->monitor->read_stream, f ) < 0 ) {
+                       ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
+               }
        }
        pthread_mutex_unlock(&chan->lock);
 
@@ -1043,7 +1053,12 @@ struct ast_frame *ast_read(struct ast_channel *chan)
                        ast_deactivate_generator(chan);
                }
        }
-       chan->fin++;
+       if (chan->fin & 0x80000000)
+               ast_frame_dump(chan->name, f, "<<");
+       if ((chan->fin & 0x7fffffff) == 0x7fffffff)
+               chan->fin &= 0x80000000;
+       else
+               chan->fin++;
        return f;
 }
 
@@ -1075,7 +1090,7 @@ int ast_indicate(struct ast_channel *chan, int condition)
                        }
                        if (ts && ts->data[0]) {
                                ast_log(LOG_DEBUG, "Driver for channel '%s' does not support indication %d, emulating it\n", chan->name, condition);
-                               ast_playtones_start(chan,0,ts->data);
+                               ast_playtones_start(chan,0,ts->data, 1);
                        }
                        else  {
                                /* not handled */
@@ -1159,13 +1174,13 @@ static int do_senddigit(struct ast_channel *chan, char digit)
                        "!941+1209/50,!0/50",   /* * */
                        "!941+1477/50,!0/50" }; /* # */
                if (digit >= '0' && digit <='9')
-                       ast_playtones_start(chan,0,dtmf_tones[digit-'0']);
+                       ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
                else if (digit >= 'A' && digit <= 'D')
-                       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10]);
+                       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
                else if (digit == '*')
-                       ast_playtones_start(chan,0,dtmf_tones[14]);
+                       ast_playtones_start(chan,0,dtmf_tones[14], 0);
                else if (digit == '#')
-                       ast_playtones_start(chan,0,dtmf_tones[15]);
+                       ast_playtones_start(chan,0,dtmf_tones[15], 0);
                else {
                        /* not handled */
                        ast_log(LOG_WARNING, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
@@ -1197,6 +1212,8 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
                else
                        return 0;
        }
+       if (chan->fout & 0x80000000)
+               ast_frame_dump(chan->name, fr, ">>");
        CHECK_BLOCKING(chan);
        switch(fr->frametype) {
        case AST_FRAME_CONTROL:
@@ -1217,7 +1234,16 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
                        } else
                                f = fr;
                        if (f)  
+                       {
                                res = chan->pvt->write(chan, f);
+                               if( chan->monitor &&
+                                               chan->monitor->write_stream &&
+                                               f && ( f->frametype == AST_FRAME_VOICE ) ) {
+                                       if( ast_writestream( chan->monitor->write_stream, f ) < 0 ) {
+                                               ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");
+                                       }
+                               }
+                       }
                        else
                                res = 0;
                }
@@ -1228,8 +1254,13 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
        /* Consider a write failure to force a soft hangup */
        if (res < 0)
                chan->_softhangup |= AST_SOFTHANGUP_DEV;
-       else
+       else {
+               if ((chan->fout & 0x7fffffff) == 0x7fffffff)
+                       chan->fout &= 0x80000000;
+               else
+                       chan->fout++;
                chan->fout++;
+       }
        return res;
 }
 
@@ -1560,6 +1591,7 @@ int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *pe
 
 int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
 {
+       struct ast_frame null = { AST_FRAME_NULL, };
        ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
                clone->name, original->name);
        if (original->masq) {
@@ -1574,6 +1606,9 @@ int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clo
        }
        original->masq = clone;
        clone->masqr = original;
+       /* XXX can't really hold the lock here, but at the same time, it' s
+          not really safe not to XXX */
+       ast_queue_frame(original, &null, 0);
        return 0;
 }
 
@@ -1839,7 +1874,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
                        break;
                }
                if (c0->pvt->bridge && 
-                       (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed) {
+                       (c0->pvt->bridge == c1->pvt->bridge) && !nativefailed && !c0->monitor && !c1->monitor) {
                                /* Looks like they share a bridge code */
                        if (option_verbose > 2) 
                                ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
@@ -1926,12 +1961,10 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
 tackygoto:
                                /* Don't copy packets if there is a generator on either one, since they're
                                   not supposed to be listening anyway */
-                               if (!c0->generator && !c1->generator) {
-                                       if (who == c0) 
-                                               ast_write(c1, f);
-                                       else 
-                                               ast_write(c0, f);
-                               }
+                               if (who == c0) 
+                                       ast_write(c1, f);
+                               else 
+                                       ast_write(c0, f);
                        }
                        ast_frfree(f);
                } else
@@ -2101,3 +2134,5 @@ int ast_tonepair(struct ast_channel *chan, int freq1, int freq2, int duration, i
        }
        return 0;
 }
+
+