Version 0.3.0 from FTP

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@604 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 23 years ago
parent e403f86b4b
commit b413c00ad1

@ -18,9 +18,9 @@
#include <sys/time.h> #include <sys/time.h>
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
#include <asterisk/lock.h>
#include <unistd.h> #include <unistd.h>
#include <math.h> /* For PI */ #include <math.h> /* For PI */
#include <asterisk/pbx.h>
#include <asterisk/frame.h> #include <asterisk/frame.h>
#include <asterisk/sched.h> #include <asterisk/sched.h>
#include <asterisk/options.h> #include <asterisk/options.h>
@ -32,6 +32,7 @@
#include <asterisk/manager.h> #include <asterisk/manager.h>
#include <asterisk/chanvars.h> #include <asterisk/chanvars.h>
#include <asterisk/linkedlists.h> #include <asterisk/linkedlists.h>
#include <asterisk/indications.h>
static int shutting_down = 0; static int shutting_down = 0;
@ -132,7 +133,10 @@ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
time_t myt; time_t myt;
time(&myt); time(&myt);
if (offset)
chan->whentohangup = myt + offset; chan->whentohangup = myt + offset;
else
chan->whentohangup = 0;
return; return;
} }
@ -290,6 +294,8 @@ struct ast_channel *ast_channel_alloc(int needqueue)
tmp->streamid = -1; tmp->streamid = -1;
tmp->appl = NULL; tmp->appl = NULL;
tmp->data = NULL; tmp->data = NULL;
tmp->fin = 0;
tmp->fout = 0;
headp=&tmp->varshead; headp=&tmp->varshead;
ast_pthread_mutex_init(&tmp->lock); ast_pthread_mutex_init(&tmp->lock);
AST_LIST_HEAD_INIT(headp); AST_LIST_HEAD_INIT(headp);
@ -326,6 +332,7 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
struct ast_frame *prev, *cur; struct ast_frame *prev, *cur;
int blah = 1; int blah = 1;
int qlen = 0; int qlen = 0;
/* Build us a copy and free the original one */
f = ast_frdup(fin); f = ast_frdup(fin);
if (!f) { if (!f) {
ast_log(LOG_WARNING, "Unable to duplicate frame\n"); ast_log(LOG_WARNING, "Unable to duplicate frame\n");
@ -340,6 +347,18 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
cur = cur->next; cur = cur->next;
qlen++; qlen++;
} }
if (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) if (prev)
prev->next = f; prev->next = f;
else else
@ -349,9 +368,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", 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)); 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) if (lock)
ast_pthread_mutex_unlock(&chan->lock); ast_pthread_mutex_unlock(&chan->lock);
return 0; return 0;
@ -405,6 +421,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) int ast_safe_sleep(struct ast_channel *chan, int ms)
{ {
struct ast_frame *f; struct ast_frame *f;
@ -462,6 +499,8 @@ void ast_channel_free(struct ast_channel *chan)
free(chan->callerid); free(chan->callerid);
if (chan->ani) if (chan->ani)
free(chan->ani); free(chan->ani);
if (chan->rdnis)
free(chan->rdnis);
pthread_mutex_destroy(&chan->lock); pthread_mutex_destroy(&chan->lock);
/* Close pipes if appropriate */ /* Close pipes if appropriate */
if ((fd = chan->pvt->alertpipe[0]) > -1) if ((fd = chan->pvt->alertpipe[0]) > -1)
@ -488,6 +527,7 @@ void ast_channel_free(struct ast_channel *chan)
free(chan->pvt); free(chan->pvt);
chan->pvt = NULL;
free(chan); free(chan);
PTHREAD_MUTEX_UNLOCK(&chlock); PTHREAD_MUTEX_UNLOCK(&chlock);
} }
@ -516,6 +556,8 @@ int ast_softhangup(struct ast_channel *chan, int cause)
return res; return res;
} }
static int ast_do_masquerade(struct ast_channel *original);
static void free_translation(struct ast_channel *clone) static void free_translation(struct ast_channel *clone)
{ {
if (clone->pvt->writetrans) if (clone->pvt->writetrans)
@ -535,7 +577,12 @@ int ast_hangup(struct ast_channel *chan)
if someone is going to masquerade as us */ if someone is going to masquerade as us */
ast_pthread_mutex_lock(&chan->lock); ast_pthread_mutex_lock(&chan->lock);
if (chan->masq) { 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); ast_pthread_mutex_unlock(&chan->lock);
return 0; return 0;
} }
@ -629,6 +676,8 @@ int ast_answer(struct ast_channel *chan)
return res; return res;
break; break;
case AST_STATE_UP: case AST_STATE_UP:
if (chan->cdr)
ast_cdr_answer(chan->cdr);
break; break;
} }
return 0; return 0;
@ -704,8 +753,6 @@ int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
return winner; 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, struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds,
int *exception, int *outfd, int *ms) int *exception, int *outfd, int *ms)
{ {
@ -901,8 +948,10 @@ struct ast_frame *ast_read(struct ast_channel *chan)
if (chan->exception) { if (chan->exception) {
if (chan->pvt->exception) if (chan->pvt->exception)
f = chan->pvt->exception(chan); f = chan->pvt->exception(chan);
else else {
ast_log(LOG_WARNING, "Exception flag set, but no exception handler\n"); ast_log(LOG_WARNING, "Exception flag set on '%s', but no exception handler\n", chan->name);
f = &null_frame;
}
/* Clear the exception flag */ /* Clear the exception flag */
chan->exception = 0; chan->exception = 0;
} else } else
@ -912,8 +961,14 @@ struct ast_frame *ast_read(struct ast_channel *chan)
ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name); ast_log(LOG_WARNING, "No read routine on channel %s\n", chan->name);
} }
if (f && (f->frametype == AST_FRAME_VOICE)) { 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 since our native format has changed\n", chan->name);
f = &null_frame;
} else if (chan->pvt->readtrans) {
f = ast_translate(chan->pvt->readtrans, f, 1); f = ast_translate(chan->pvt->readtrans, f, 1);
if (!f) if (!f)
f = &null_frame; f = &null_frame;
@ -948,14 +1003,14 @@ struct ast_frame *ast_read(struct ast_channel *chan)
int res; int res;
tmp = chan->generatordata; tmp = chan->generatordata;
chan->generatordata = NULL; chan->generatordata = NULL;
res = chan->generator->generate(chan, tmp, f->datalen); res = chan->generator->generate(chan, tmp, f->datalen, f->samples);
chan->generatordata = tmp; chan->generatordata = tmp;
if (res) { if (res) {
ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
ast_deactivate_generator(chan); ast_deactivate_generator(chan);
} }
} }
chan->fin++;
return f; return f;
} }
@ -965,13 +1020,39 @@ int ast_indicate(struct ast_channel *chan, int condition)
/* Stop if we're a zombie or need a soft hangup */ /* Stop if we're a zombie or need a soft hangup */
if (chan->zombie || ast_check_hangup(chan)) if (chan->zombie || ast_check_hangup(chan))
return -1; return -1;
if (chan->pvt->indicate) { if (chan->pvt->indicate)
res = chan->pvt->indicate(chan, condition); res = chan->pvt->indicate(chan, condition);
if (res) if (!chan->pvt->indicate || res) {
ast_log(LOG_WARNING, "Driver for channel '%s' failed to indicate condition %d\n", chan->name, condition); /*
} else * Device does not support (that) indication, lets fake
ast_log(LOG_WARNING, "Driver for channel '%s' does not support indication\n", chan->name); * it by doing our own tone generation. (PM2002)
return res; */
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);
}
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) int ast_recvchar(struct ast_channel *chan, int timeout)
@ -1016,6 +1097,51 @@ int ast_sendtext(struct ast_channel *chan, char *text)
return res; 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']);
else if (digit >= 'A' && digit <= 'D')
ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10]);
else if (digit == '*')
ast_playtones_start(chan,0,dtmf_tones[14]);
else if (digit == '#')
ast_playtones_start(chan,0,dtmf_tones[15]);
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 ast_write(struct ast_channel *chan, struct ast_frame *fr)
{ {
int res = -1; int res = -1;
@ -1045,8 +1171,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"); ast_log(LOG_WARNING, "Don't know how to handle control frames yet\n");
break; break;
case AST_FRAME_DTMF: case AST_FRAME_DTMF:
if (chan->pvt->send_digit) res = do_senddigit(chan,fr->subclass);
res = chan->pvt->send_digit(chan, fr->subclass);
break; break;
case AST_FRAME_TEXT: case AST_FRAME_TEXT:
if (chan->pvt->send_text) if (chan->pvt->send_text)
@ -1068,6 +1193,8 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
/* Consider a write failure to force a soft hangup */ /* Consider a write failure to force a soft hangup */
if (res < 0) if (res < 0)
chan->_softhangup |= AST_SOFTHANGUP_DEV; chan->_softhangup |= AST_SOFTHANGUP_DEV;
else
chan->fout++;
return res; return res;
} }
@ -1129,7 +1256,7 @@ int ast_set_read_format(struct ast_channel *chan, int fmts)
return 0; 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; int state = 0;
struct ast_channel *chan; struct ast_channel *chan;
@ -1138,6 +1265,8 @@ struct ast_channel *ast_request_and_dial(char *type, int format, void *data, int
chan = ast_request(type, format, data); chan = ast_request(type, format, data);
if (chan) { if (chan) {
if (callerid)
ast_set_callerid(chan, callerid, 1);
if (!ast_call(chan, data, 0)) { if (!ast_call(chan, data, 0)) {
while(timeout && (chan->_state != AST_STATE_UP)) { while(timeout && (chan->_state != AST_STATE_UP)) {
res = ast_waitfor(chan, timeout); res = ast_waitfor(chan, timeout);
@ -1370,11 +1499,20 @@ int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clo
return 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) static int ast_do_masquerade(struct ast_channel *original)
{ {
int x; int x;
int res=0; int res=0;
char *tmp; char *tmp;
void *tmpv;
struct ast_channel_pvt *p; struct ast_channel_pvt *p;
struct ast_channel *clone = original->masq; struct ast_channel *clone = original->masq;
int rformat = original->readformat; int rformat = original->readformat;
@ -1384,9 +1522,9 @@ static int ast_do_masquerade(struct ast_channel *original)
char masqn[100]; char masqn[100];
char zombn[100]; char zombn[100];
#if 0 #if 1
ast_log(LOG_DEBUG, "Actually Masquerading %s(%d) into the structure of %s(%d)\n", 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 #endif
/* XXX This is a seriously wacked out operation. We're essentially putting the guts of /* 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 the clone channel into the original channel. Start by killing off the original
@ -1456,6 +1594,10 @@ static int ast_do_masquerade(struct ast_channel *original)
/* Copy the FD's */ /* Copy the FD's */
for (x=0;x<AST_MAX_FDS;x++) for (x=0;x<AST_MAX_FDS;x++)
original->fds[x] = clone->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 */ /* Presense of ADSI capable CPE follows clone */
original->adsicpe = clone->adsicpe; original->adsicpe = clone->adsicpe;
/* Bridge remains the same */ /* Bridge remains the same */
@ -1483,6 +1625,11 @@ static int ast_do_masquerade(struct ast_channel *original)
/* Our native formats are different now */ /* Our native formats are different now */
original->nativeformats = clone->nativeformats; 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 */ /* Context, extension, priority, app data, jump table, remain the same */
/* pvt switches. pbx stays the same, as does next */ /* pvt switches. pbx stays the same, as does next */
@ -1492,6 +1639,7 @@ static int ast_do_masquerade(struct ast_channel *original)
if (clone->zombie) { if (clone->zombie) {
pthread_mutex_unlock(&clone->lock); pthread_mutex_unlock(&clone->lock);
ast_channel_free(clone); ast_channel_free(clone);
manager_event(EVENT_FLAG_CALL, "Hangup", "Channel: %s\r\n", zombn);
} else { } else {
clone->zombie=1; clone->zombie=1;
pthread_mutex_unlock(&clone->lock); pthread_mutex_unlock(&clone->lock);
@ -1519,19 +1667,26 @@ static int ast_do_masquerade(struct ast_channel *original)
/* Signal any blocker */ /* Signal any blocker */
if (original->blocking) if (original->blocking)
pthread_kill(original->blocker, SIGURG); 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; 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) if (chan->callerid)
free(chan->callerid); free(chan->callerid);
if (callerid) if (anitoo && chan->ani)
free(chan->ani);
if (callerid) {
chan->callerid = strdup(callerid); chan->callerid = strdup(callerid);
else if (anitoo)
chan->ani = strdup(callerid);
} else {
chan->callerid = NULL; chan->callerid = NULL;
if (anitoo)
chan->ani = NULL;
}
if (chan->cdr)
ast_cdr_setcid(chan->cdr, chan);
manager_event(EVENT_FLAG_CALL, "Newcallerid", manager_event(EVENT_FLAG_CALL, "Newcallerid",
"Channel: %s\r\n" "Channel: %s\r\n"
"Callerid: %s\r\n", "Callerid: %s\r\n",
@ -1571,6 +1726,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
struct ast_channel *who = NULL; struct ast_channel *who = NULL;
int res; int res;
int nativefailed=0; int nativefailed=0;
/* Stop if we're a zombie or need a soft hangup */ /* Stop if we're a zombie or need a soft hangup */
if (c0->zombie || ast_check_hangup(c0) || c1->zombie || ast_check_hangup(c1)) if (c0->zombie || ast_check_hangup(c0) || c1->zombie || ast_check_hangup(c1))
return -1; return -1;
@ -1639,7 +1795,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
} }
who = ast_waitfor_n(cs, 2, &to); who = ast_waitfor_n(cs, 2, &to);
if (!who) { if (!who) {
ast_log(LOG_WARNING, "Nobody there??\n"); ast_log(LOG_DEBUG, "Nobody there, continuing...\n");
continue; continue;
} }
f = ast_read(who); f = ast_read(who);
@ -1649,6 +1805,7 @@ int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
res = 0; res = 0;
break; break;
} }
if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) { if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
*fo = f; *fo = f;
*rc = who; *rc = who;
@ -1748,7 +1905,6 @@ struct tonepair_state {
float vol; float vol;
int duration; int duration;
int pos; int pos;
int origrfmt;
int origwfmt; int origwfmt;
struct ast_frame f; struct ast_frame f;
unsigned char offset[AST_FRIENDLY_OFFSET]; unsigned char offset[AST_FRIENDLY_OFFSET];
@ -1760,7 +1916,6 @@ static void tonepair_release(struct ast_channel *chan, void *params)
struct tonepair_state *ts = params; struct tonepair_state *ts = params;
if (chan) { if (chan) {
ast_set_write_format(chan, ts->origwfmt); ast_set_write_format(chan, ts->origwfmt);
ast_set_read_format(chan, ts->origrfmt);
} }
free(ts); free(ts);
} }
@ -1773,17 +1928,11 @@ static void * tonepair_alloc(struct ast_channel *chan, void *params)
if (!ts) if (!ts)
return NULL; return NULL;
memset(ts, 0, sizeof(struct tonepair_state)); memset(ts, 0, sizeof(struct tonepair_state));
ts->origrfmt = chan->readformat;
ts->origwfmt = chan->writeformat; ts->origwfmt = chan->writeformat;
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { 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); ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", chan->name);
tonepair_release(NULL, ts); tonepair_release(NULL, ts);
ts = NULL; 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 { } else {
ts->freq1 = td->freq1; ts->freq1 = td->freq1;
ts->freq2 = td->freq2; ts->freq2 = td->freq2;
@ -1795,10 +1944,16 @@ static void * tonepair_alloc(struct ast_channel *chan, void *params)
return ts; 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; struct tonepair_state *ts = data;
int x; 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) { if (len > sizeof(ts->data) / 2 - 1) {
ast_log(LOG_WARNING, "Can't generate that much data!\n"); ast_log(LOG_WARNING, "Can't generate that much data!\n");
return -1; return -1;
@ -1813,7 +1968,7 @@ static int tonepair_generator(struct ast_channel *chan, void *data, int len)
ts->f.frametype = AST_FRAME_VOICE; ts->f.frametype = AST_FRAME_VOICE;
ts->f.subclass = AST_FORMAT_SLINEAR; ts->f.subclass = AST_FORMAT_SLINEAR;
ts->f.datalen = len; ts->f.datalen = len;
ts->f.timelen = len/8; ts->f.samples = samples;
ts->f.offset = AST_FRIENDLY_OFFSET; ts->f.offset = AST_FRIENDLY_OFFSET;
ts->f.data = ts->data; ts->f.data = ts->data;
ast_write(chan, &ts->f); ast_write(chan, &ts->f);

@ -192,7 +192,7 @@ static int ast_read_callback(void *data)
s->adj -= (ms - delay); s->adj -= (ms - delay);
s->adj -= 2; s->adj -= 2;
} }
s->fr.timelen = delay; s->fr.samples = delay * 8;
#if 0 #if 0
ast_log(LOG_DEBUG, "delay is %d, adjusting by %d, as last was %d\n", delay, s->adj, ms); ast_log(LOG_DEBUG, "delay is %d, adjusting by %d, as last was %d\n", delay, s->adj, ms);
#endif #endif
@ -218,6 +218,11 @@ static int mp3_apply(struct ast_channel *c, struct ast_filestream *s)
{ {
/* Select our owner for this stream, and get the ball rolling. */ /* Select our owner for this stream, and get the ball rolling. */
s->owner = c; s->owner = c;
return 0;
}
static int mp3_play(struct ast_filestream *s)
{
ast_read_callback(s); ast_read_callback(s);
return 0; return 0;
} }
@ -240,6 +245,21 @@ static int mp3_write(struct ast_filestream *fs, struct ast_frame *f)
return 0; return 0;
} }
static int mp3_seek(struct ast_filestream *fs, long sample_offset, int whence)
{
return -1;
}
static int mp3_trunc(struct ast_filestream *fs)
{
return -1;
}
static long mp3_tell(struct ast_filestream *fs)
{
return -1;
}
static char *mp3_getcomment(struct ast_filestream *s) static char *mp3_getcomment(struct ast_filestream *s)
{ {
return NULL; return NULL;
@ -251,7 +271,11 @@ int load_module()
mp3_open, mp3_open,
mp3_rewrite, mp3_rewrite,
mp3_apply, mp3_apply,
mp3_play,
mp3_write, mp3_write,
mp3_seek,
mp3_trunc,
mp3_tell,
mp3_read, mp3_read,
mp3_close, mp3_close,
mp3_getcomment); mp3_getcomment);

Loading…
Cancel
Save