Merge Mahmut's recording patches
[asterisk/asterisk.git] / channel.c
index 87d527d..f1ea7f7 100755 (executable)
--- a/channel.c
+++ b/channel.c
@@ -18,9 +18,9 @@
 #include <sys/time.h>
 #include <signal.h>
 #include <errno.h>
-#include <asterisk/lock.h>
 #include <unistd.h>
 #include <math.h>                      /* For PI */
+#include <asterisk/pbx.h>
 #include <asterisk/frame.h>
 #include <asterisk/sched.h>
 #include <asterisk/options.h>
@@ -32,6 +32,8 @@
 #include <asterisk/manager.h>
 #include <asterisk/chanvars.h>
 #include <asterisk/linkedlists.h>
+#include <asterisk/indications.h>
+#include <asterisk/monitor.h>
 
 
 static int shutting_down = 0;
@@ -132,7 +134,10 @@ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
 time_t myt;
 
        time(&myt);
-       chan->whentohangup = myt + offset;
+        if (offset)
+         chan->whentohangup = myt + offset;
+        else
+          chan->whentohangup = 0;
        return;
 }
 
@@ -290,6 +295,8 @@ struct ast_channel *ast_channel_alloc(int needqueue)
                                        tmp->streamid = -1;
                                        tmp->appl = NULL;
                                        tmp->data = NULL;
+                                       tmp->fin = 0;
+                                       tmp->fout = 0;
                                        headp=&tmp->varshead;
                                        ast_pthread_mutex_init(&tmp->lock);
                                        AST_LIST_HEAD_INIT(headp);
@@ -326,6 +333,7 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
        struct ast_frame *prev, *cur;
        int blah = 1;
        int qlen = 0;
+       /* Build us a copy and free the original one */
        f = ast_frdup(fin);
        if (!f) {
                ast_log(LOG_WARNING, "Unable to duplicate frame\n");
@@ -340,6 +348,19 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
                cur = cur->next;
                qlen++;
        }
+       /* 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;
+               } else {
+                       ast_log(LOG_DEBUG, "Dropping voice to exceptionally long queue on %s\n", chan->name);
+                       ast_frfree(fin);
+                       if (lock)
+                               ast_pthread_mutex_unlock(&chan->lock);
+                       return 0;
+               }
+       }
        if (prev)
                prev->next = f;
        else
@@ -349,9 +370,6 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
                        ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
                                chan->name, f->frametype, f->subclass, qlen, strerror(errno));
        }
-       if (qlen  > 128) {
-               ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name);
-       }
        if (lock)
                ast_pthread_mutex_unlock(&chan->lock);
        return 0;
@@ -360,6 +378,7 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
 int ast_queue_hangup(struct ast_channel *chan, int lock)
 {
        struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_HANGUP };
+       chan->_softhangup |= AST_SOFTHANGUP_DEV;
        return ast_queue_frame(chan, &f, lock);
 }
 
@@ -405,6 +424,27 @@ struct ast_channel *ast_channel_walk(struct ast_channel *prev)
        
 }
 
+int ast_safe_sleep_conditional(        struct ast_channel *chan, int ms,
+                                                               int (*cond)(void*), void *data )
+{
+       struct ast_frame *f;
+
+       while(ms > 0) {
+               if( cond && ((*cond)(data) == 0 ) )
+                       return 0;
+               ms = ast_waitfor(chan, ms);
+               if (ms <0)
+                       return -1;
+               if (ms > 0) {
+                       f = ast_read(chan);
+                       if (!f)
+                               return -1;
+                       ast_frfree(f);
+               }
+       }
+       return 0;
+}
+
 int ast_safe_sleep(struct ast_channel *chan, int ms)
 {
        struct ast_frame *f;
@@ -449,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);
@@ -462,6 +506,8 @@ void ast_channel_free(struct ast_channel *chan)
                free(chan->callerid);   
        if (chan->ani)
                free(chan->ani);
+       if (chan->rdnis)
+               free(chan->rdnis);
        pthread_mutex_destroy(&chan->lock);
        /* Close pipes if appropriate */
        if ((fd = chan->pvt->alertpipe[0]) > -1)
@@ -488,6 +534,7 @@ void ast_channel_free(struct ast_channel *chan)
                                                         
 
        free(chan->pvt);
+       chan->pvt = NULL;
        free(chan);
        PTHREAD_MUTEX_UNLOCK(&chlock);
 }
@@ -516,6 +563,8 @@ int ast_softhangup(struct ast_channel *chan, int cause)
        return res;
 }
 
+static int ast_do_masquerade(struct ast_channel *original);
+
 static void free_translation(struct ast_channel *clone)
 {
        if (clone->pvt->writetrans)
@@ -535,7 +584,12 @@ int ast_hangup(struct ast_channel *chan)
           if someone is going to masquerade as us */
        ast_pthread_mutex_lock(&chan->lock);
        if (chan->masq) {
-               ast_log(LOG_WARNING, "We're getting hung up, but someone is trying to masq into us?!?\n");
+               if (ast_do_masquerade(chan)) 
+                       ast_log(LOG_WARNING, "Failed to perform masquerade\n");
+       }
+
+       if (chan->masq) {
+               ast_log(LOG_WARNING, "%s getting hung up, but someone is trying to masq into us?!?\n", chan->name);
                ast_pthread_mutex_unlock(&chan->lock);
                return 0;
        }
@@ -629,6 +683,8 @@ int ast_answer(struct ast_channel *chan)
                return res;
                break;
        case AST_STATE_UP:
+               if (chan->cdr)
+                       ast_cdr_answer(chan->cdr);
                break;
        }
        return 0;
@@ -704,8 +760,6 @@ int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
        return winner;
 }
 
-static int ast_do_masquerade(struct ast_channel *original);
-
 struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds, 
        int *exception, int *outfd, int *ms)
 {
@@ -821,6 +875,7 @@ int ast_waitfor(struct ast_channel *c, int ms)
 
 char ast_waitfordigit(struct ast_channel *c, int ms)
 {
+       /* XXX Should I be merged with waitfordigit_full XXX */
        struct ast_frame *f;
        char result = 0;
        /* Stop if we're a zombie or need a soft hangup */
@@ -845,6 +900,36 @@ char ast_waitfordigit(struct ast_channel *c, int ms)
        return result;
 }
 
+char ast_waitfordigit_full(struct ast_channel *c, int ms, int audio, int ctrl)
+{
+       struct ast_frame *f;
+       char result = 0;
+       struct ast_channel *rchan;
+       int outfd;
+       /* Stop if we're a zombie or need a soft hangup */
+       if (c->zombie || ast_check_hangup(c)) 
+               return -1;
+       /* Wait for a digit, no more than ms milliseconds total. */
+       while(ms && !result) {
+               rchan = ast_waitfor_nandfds(&c, 1, &audio, (audio > -1) ? 1 : 0, NULL, &outfd, &ms);
+               if ((!rchan) && (outfd < 0) && (ms)) /* Error */
+                       result = -1; 
+               else if (outfd > -1) {
+                       result = 1;
+               } else if (rchan) {
+                       /* Read something */
+                       f = ast_read(c);
+                       if (f) {
+                               if (f->frametype == AST_FRAME_DTMF) 
+                                       result = f->subclass;
+                               ast_frfree(f);
+                       } else
+                               result = -1;
+               }
+       }
+       return result;
+}
+
 struct ast_frame *ast_read(struct ast_channel *chan)
 {
        struct ast_frame *f = NULL;
@@ -901,8 +986,10 @@ struct ast_frame *ast_read(struct ast_channel *chan)
                if (chan->exception) {
                        if (chan->pvt->exception) 
                                f = chan->pvt->exception(chan);
-                       else
-                               ast_log(LOG_WARNING, "Exception flag set, but no exception handler\n");
+                       else {
+                               ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
+                               f = &null_frame;
+                       }
                        /* Clear the exception flag */
                        chan->exception = 0;
                } else
@@ -912,8 +999,15 @@ struct ast_frame *ast_read(struct ast_channel *chan)
                        ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
        }
 
+
        if (f && (f->frametype == AST_FRAME_VOICE)) {
-               if (chan->pvt->readtrans) {
+               if (!(f->subclass & chan->nativeformats)) {
+                       /* This frame can't be from the current native formats -- drop it on the
+                          floor */
+                       ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %d since our native format has changed to %d\n", chan->name, f->subclass, chan->nativeformats);
+                       ast_frfree(f);
+                       f = &null_frame;
+               } else if (chan->pvt->readtrans) {
                        f = ast_translate(chan->pvt->readtrans, f, 1);
                        if (!f)
                                f = &null_frame;
@@ -938,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);
 
@@ -948,14 +1046,19 @@ struct ast_frame *ast_read(struct ast_channel *chan)
                int res;
                tmp = chan->generatordata;
                chan->generatordata = NULL;
-               res = chan->generator->generate(chan, tmp, f->datalen);
+               res = chan->generator->generate(chan, tmp, f->datalen, f->samples);
                chan->generatordata = tmp;
                if (res) {
                        ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
                        ast_deactivate_generator(chan);
                }
        }
-
+       if (chan->fin & 0x80000000)
+               ast_frame_dump(chan->name, f, "<<");
+       if ((chan->fin & 0x7fffffff) == 0x7fffffff)
+               chan->fin &= 0x80000000;
+       else
+               chan->fin++;
        return f;
 }
 
@@ -965,13 +1068,39 @@ int ast_indicate(struct ast_channel *chan, int condition)
        /* Stop if we're a zombie or need a soft hangup */
        if (chan->zombie || ast_check_hangup(chan)) 
                return -1;
-       if (chan->pvt->indicate) {
+       if (chan->pvt->indicate)
                res = chan->pvt->indicate(chan, condition);
-               if (res)
-                       ast_log(LOG_WARNING, "Driver for channel '%s' failed to indicate condition %d\n", chan->name, condition);
-       } else
-               ast_log(LOG_WARNING, "Driver for channel '%s' does not support indication\n", chan->name);
-       return res;
+       if (!chan->pvt->indicate || res) {
+               /*
+                * Device does not support (that) indication, lets fake
+                * it by doing our own tone generation. (PM2002)
+                */
+               if (condition >= 0) {
+                       const struct tone_zone_sound *ts = NULL;
+                       switch (condition) {
+                        case AST_CONTROL_RINGING:
+                               ts = ast_get_indication_tone(chan->zone, "ring");
+                               break;
+                        case AST_CONTROL_BUSY:
+                               ts = ast_get_indication_tone(chan->zone, "busy");
+                               break;
+                        case AST_CONTROL_CONGESTION:
+                               ts = ast_get_indication_tone(chan->zone, "congestion");
+                               break;
+                       }
+                       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, 1);
+                       }
+                       else  {
+                               /* not handled */
+                               ast_log(LOG_WARNING, "Unable to handle indication %d for '%s'\n", condition, chan->name);
+                               return -1;
+                       }
+               }
+               else ast_playtones_stop(chan);
+       }
+       return 0;
 }
 
 int ast_recvchar(struct ast_channel *chan, int timeout)
@@ -1016,10 +1145,55 @@ int ast_sendtext(struct ast_channel *chan, char *text)
        return res;
 }
 
+static int do_senddigit(struct ast_channel *chan, char digit)
+{
+       int res = -1;
+
+       if (chan->pvt->send_digit)
+               res = chan->pvt->send_digit(chan, digit);
+       if (!chan->pvt->send_digit || res) {
+               /*
+                * Device does not support DTMF tones, lets fake
+                * it by doing our own generation. (PM2002)
+                */
+               static const char* dtmf_tones[] = {
+                       "!941+1336/50,!0/50",   /* 0 */
+                       "!697+1209/50,!0/50",   /* 1 */
+                       "!697+1336/50,!0/50",   /* 2 */
+                       "!697+1477/50,!0/50",   /* 3 */
+                       "!770+1209/50,!0/50",   /* 4 */
+                       "!770+1336/50,!0/50",   /* 5 */
+                       "!770+1477/50,!0/50",   /* 6 */
+                       "!852+1209/50,!0/50",   /* 7 */
+                       "!852+1336/50,!0/50",   /* 8 */
+                       "!852+1477/50,!0/50",   /* 9 */
+                       "!697+1633/50,!0/50",   /* A */
+                       "!770+1633/50,!0/50",   /* B */
+                       "!852+1633/50,!0/50",   /* C */
+                       "!941+1633/50,!0/50",   /* D */
+                       "!941+1209/50,!0/50",   /* * */
+                       "!941+1477/50,!0/50" }; /* # */
+               if (digit >= '0' && digit <='9')
+                       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], 0);
+               else if (digit == '*')
+                       ast_playtones_start(chan,0,dtmf_tones[14], 0);
+               else if (digit == '#')
+                       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);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
 int ast_write(struct ast_channel *chan, struct ast_frame *fr)
 {
        int res = -1;
-       struct ast_frame *f;
+       struct ast_frame *f = NULL;
        /* Stop if we're a zombie or need a soft hangup */
        if (chan->zombie || ast_check_hangup(chan)) 
                return -1;
@@ -1038,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:
@@ -1045,8 +1221,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
                ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
                break;
        case AST_FRAME_DTMF:
-               if (chan->pvt->send_digit)
-                       res = chan->pvt->send_digit(chan, fr->subclass);
+               res = do_senddigit(chan,fr->subclass);
                break;
        case AST_FRAME_TEXT:
                if (chan->pvt->send_text)
@@ -1055,19 +1230,37 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
        default:
                if (chan->pvt->write) {
                        if (chan->pvt->writetrans) {
-                               f = ast_translate(chan->pvt->writetrans, fr, 1);
+                               f = ast_translate(chan->pvt->writetrans, fr, 0);
                        } 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;
                }
        }
+       if (f && (f != fr))
+               ast_frfree(f);
        chan->blocking = 0;
        /* Consider a write failure to force a soft hangup */
        if (res < 0)
                chan->_softhangup |= AST_SOFTHANGUP_DEV;
+       else {
+               if ((chan->fout & 0x7fffffff) == 0x7fffffff)
+                       chan->fout &= 0x80000000;
+               else
+                       chan->fout++;
+               chan->fout++;
+       }
        return res;
 }
 
@@ -1129,7 +1322,7 @@ int ast_set_read_format(struct ast_channel *chan, int fmts)
        return 0;
 }
 
-struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate)
+struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int timeout, int *outstate, char *callerid)
 {
        int state = 0;
        struct ast_channel *chan;
@@ -1138,6 +1331,8 @@ struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int
        
        chan = ast_request(type, format, data);
        if (chan) {
+               if (callerid)
+                       ast_set_callerid(chan, callerid, 1);
                if (!ast_call(chan, data, 0)) {
                        while(timeout && (chan->_state != AST_STATE_UP)) {
                                res = ast_waitfor(chan, timeout);
@@ -1250,6 +1445,7 @@ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int fti
        int pos=0;
        int to = ftimeout;
        char d;
+       /* XXX Merge with full version? XXX */
        /* Stop if we're a zombie or need a soft hangup */
        if (c->zombie || ast_check_hangup(c)) 
                return -1;
@@ -1283,6 +1479,48 @@ int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int fti
        return 0;
 }
 
+int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
+{
+       int pos=0;
+       int to = ftimeout;
+       char d;
+       /* Stop if we're a zombie or need a soft hangup */
+       if (c->zombie || ast_check_hangup(c)) 
+               return -1;
+       if (!len)
+               return -1;
+       do {
+               if (c->streamid > -1) {
+                       d = ast_waitstream_full(c, AST_DIGIT_ANY, audiofd, ctrlfd);
+                       ast_stopstream(c);
+                       usleep(1000);
+                       if (!d)
+                               d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
+               } else {
+                       d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
+               }
+               if (d < 0)
+                       return -1;
+               if (d == 0) {
+                       s[pos]='\0';
+                       return 1;
+               }
+               if (d == 1) {
+                       s[pos]='\0';
+                       return 2;
+               }
+               if (!strchr(enders, d))
+                       s[pos++] = d;
+               if (strchr(enders, d) || (pos >= len)) {
+                       s[pos]='\0';
+                       return 0;
+               }
+               to = timeout;
+       } while(1);
+       /* Never reached */
+       return 0;
+}
+
 int ast_channel_supports_html(struct ast_channel *chan)
 {
        if (chan->pvt->send_html)
@@ -1353,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) {
@@ -1367,14 +1606,26 @@ 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;
 }
 
+void ast_change_name(struct ast_channel *chan, char *newname)
+{
+       char tmp[256];
+       strncpy(tmp, chan->name, 256);
+       strncpy(chan->name, newname, sizeof(chan->name) - 1);
+       manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\n", tmp, chan->name);
+}
+
 static int ast_do_masquerade(struct ast_channel *original)
 {
        int x;
        int res=0;
        char *tmp;
+       void *tmpv;
        struct ast_channel_pvt *p;
        struct ast_channel *clone = original->masq;
        int rformat = original->readformat;
@@ -1384,9 +1635,9 @@ static int ast_do_masquerade(struct ast_channel *original)
        char masqn[100];
        char zombn[100];
        
-#if 0
+#if 1
        ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
-               clone->name, clone->state, original->name, original->state);
+               clone->name, clone->_state, original->name, original->_state);
 #endif
        /* XXX This is a seriously wacked out operation.  We're essentially putting the guts of
           the clone channel into the original channel.  Start by killing off the original
@@ -1456,6 +1707,10 @@ static int ast_do_masquerade(struct ast_channel *original)
        /* Copy the FD's */
        for (x=0;x<AST_MAX_FDS;x++)
                original->fds[x] = clone->fds[x];
+       /* Move the variables */
+       tmpv = original->varshead.first;
+       original->varshead.first = clone->varshead.first;
+       clone->varshead.first = tmpv;
        /* Presense of ADSI capable CPE follows clone */
        original->adsicpe = clone->adsicpe;
        /* Bridge remains the same */
@@ -1482,6 +1737,11 @@ static int ast_do_masquerade(struct ast_channel *original)
        
        /* Our native formats are different now */
        original->nativeformats = clone->nativeformats;
+
+       /* And of course, so does our current state.  Note we need not
+          call ast_setstate since the event manager doesn't really consider
+          these separate */
+       original->_state = clone->_state;
        
        /* Context, extension, priority, app data, jump table,  remain the same */
        /* pvt switches.  pbx stays the same, as does next */
@@ -1492,6 +1752,7 @@ static int ast_do_masquerade(struct ast_channel *original)
        if (clone->zombie) {
                pthread_mutex_unlock(&clone->lock);
                ast_channel_free(clone);
+               manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
        } else {
                clone->zombie=1;
                pthread_mutex_unlock(&clone->lock);
@@ -1519,19 +1780,26 @@ static int ast_do_masquerade(struct ast_channel *original)
        /* Signal any blocker */
        if (original->blocking)
                pthread_kill(original->blocker, SIGURG);
-       ast_log(LOG_DEBUG, "Done Masquerading %s(%d) into the structure of %s(%d)\n",
-               clone->name, clone->_state, original->name, original->_state);
        return 0;
 }
 
-void ast_set_callerid(struct ast_channel *chan, char *callerid)
+void ast_set_callerid(struct ast_channel *chan, char *callerid, int anitoo)
 {
        if (chan->callerid)
                free(chan->callerid);
-       if (callerid)
+       if (anitoo && chan->ani)
+               free(chan->ani);
+       if (callerid) {
                chan->callerid = strdup(callerid);
-       else
+               if (anitoo)
+                       chan->ani = strdup(callerid);
+       } else {
                chan->callerid = NULL;
+               if (anitoo)
+                       chan->ani = NULL;
+       }
+       if (chan->cdr)
+               ast_cdr_setcid(chan->cdr, chan);
        manager_event(EVENT_FLAG_CALL, "Newcallerid", 
                                "Channel: %s\r\n"
                                "Callerid: %s\r\n",
@@ -1571,6 +1839,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
        struct ast_channel *who = NULL;
        int res;
        int nativefailed=0;
+
        /* Stop if we're a zombie or need a soft hangup */
        if (c0->zombie || ast_check_hangup(c0) || c1->zombie || ast_check_hangup(c1)) 
                return -1;
@@ -1605,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);
@@ -1639,7 +1908,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
                }
                who = ast_waitfor_n(cs, 2, &to);
                if (!who) {
-                       ast_log(LOG_WARNING, "Nobody there??\n"); 
+                       ast_log(LOG_DEBUG, "Nobody there, continuing...\n"); 
                        continue;
                }
                f = ast_read(who);
@@ -1649,6 +1918,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
                        res = 0;
                        break;
                }
+
                if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
                        *fo = f;
                        *rc = who;
@@ -1691,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
@@ -1748,7 +2016,6 @@ struct tonepair_state {
        float vol;
        int duration;
        int pos;
-       int origrfmt;
        int origwfmt;
        struct ast_frame f;
        unsigned char offset[AST_FRIENDLY_OFFSET];
@@ -1760,7 +2027,6 @@ static void tonepair_release(struct ast_channel *chan, void *params)
        struct tonepair_state *ts = params;
        if (chan) {
                ast_set_write_format(chan, ts->origwfmt);
-               ast_set_read_format(chan, ts->origrfmt);
        }
        free(ts);
 }
@@ -1773,17 +2039,11 @@ static void * tonepair_alloc(struct ast_channel *chan, void *params)
        if (!ts)
                return NULL;
        memset(ts, 0, sizeof(struct tonepair_state));
-       ts->origrfmt = chan->readformat;
        ts->origwfmt = chan->writeformat;
        if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
                ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
                tonepair_release(NULL, ts);
                ts = NULL;
-       } else if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
-               ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (read)\n", chan->name);
-               ast_set_write_format(chan, ts->origwfmt);
-               tonepair_release(NULL, ts);
-               ts = NULL;
        } else {
                ts->freq1 = td->freq1;
                ts->freq2 = td->freq2;
@@ -1795,10 +2055,16 @@ static void * tonepair_alloc(struct ast_channel *chan, void *params)
        return ts;
 }
 
-static int tonepair_generator(struct ast_channel *chan, void *data, int len)
+static int tonepair_generator(struct ast_channel *chan, void *data, int len, int samples)
 {
        struct tonepair_state *ts = data;
        int x;
+
+       /* we need to prepare a frame with 16 * timelen samples as we're 
+        * generating SLIN audio
+        */
+       len = samples * 2;
+
        if (len > sizeof(ts->data) / 2 - 1) {
                ast_log(LOG_WARNING, "Can't generate that much data!\n");
                return -1;
@@ -1813,7 +2079,7 @@ static int tonepair_generator(struct ast_channel *chan, void *data, int len)
        ts->f.frametype = AST_FRAME_VOICE;
        ts->f.subclass = AST_FORMAT_SLINEAR;
        ts->f.datalen = len;
-       ts->f.timelen = len/8;
+       ts->f.samples = samples;
        ts->f.offset = AST_FRIENDLY_OFFSET;
        ts->f.data = ts->data;
        ast_write(chan, &ts->f);
@@ -1868,3 +2134,5 @@ int ast_tonepair(struct ast_channel *chan, int freq1, int freq2, int duration, i
        }
        return 0;
 }
+
+