mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 11:58:52 +00:00
Version 0.3.0 from FTP
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@604 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
235
channel.c
235
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,7 @@
|
||||
#include <asterisk/manager.h>
|
||||
#include <asterisk/chanvars.h>
|
||||
#include <asterisk/linkedlists.h>
|
||||
#include <asterisk/indications.h>
|
||||
|
||||
|
||||
static int shutting_down = 0;
|
||||
@@ -132,7 +133,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 +294,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 +332,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 +347,18 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock)
|
||||
cur = cur->next;
|
||||
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)
|
||||
prev->next = f;
|
||||
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",
|
||||
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;
|
||||
@@ -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)
|
||||
{
|
||||
struct ast_frame *f;
|
||||
@@ -462,6 +499,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 +527,7 @@ void ast_channel_free(struct ast_channel *chan)
|
||||
|
||||
|
||||
free(chan->pvt);
|
||||
chan->pvt = NULL;
|
||||
free(chan);
|
||||
PTHREAD_MUTEX_UNLOCK(&chlock);
|
||||
}
|
||||
@@ -516,6 +556,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 +577,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 +676,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 +753,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)
|
||||
{
|
||||
@@ -901,8 +948,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 +961,14 @@ 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 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);
|
||||
if (!f)
|
||||
f = &null_frame;
|
||||
@@ -948,14 +1003,14 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
chan->fin++;
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
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,6 +1097,51 @@ 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']);
|
||||
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 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");
|
||||
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)
|
||||
@@ -1068,6 +1193,8 @@ 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
|
||||
chan->fout++;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1129,7 +1256,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 +1265,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);
|
||||
@@ -1370,11 +1499,20 @@ int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clo
|
||||
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 +1522,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 +1594,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 +1624,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 +1639,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 +1667,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 +1726,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;
|
||||
@@ -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);
|
||||
if (!who) {
|
||||
ast_log(LOG_WARNING, "Nobody there??\n");
|
||||
ast_log(LOG_DEBUG, "Nobody there, continuing...\n");
|
||||
continue;
|
||||
}
|
||||
f = ast_read(who);
|
||||
@@ -1649,6 +1805,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;
|
||||
@@ -1748,7 +1905,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 +1916,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 +1928,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 +1944,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 +1968,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);
|
||||
|
@@ -192,7 +192,7 @@ static int ast_read_callback(void *data)
|
||||
s->adj -= (ms - delay);
|
||||
s->adj -= 2;
|
||||
}
|
||||
s->fr.timelen = delay;
|
||||
s->fr.samples = delay * 8;
|
||||
#if 0
|
||||
ast_log(LOG_DEBUG, "delay is %d, adjusting by %d, as last was %d\n", delay, s->adj, ms);
|
||||
#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. */
|
||||
s->owner = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mp3_play(struct ast_filestream *s)
|
||||
{
|
||||
ast_read_callback(s);
|
||||
return 0;
|
||||
}
|
||||
@@ -240,6 +245,21 @@ static int mp3_write(struct ast_filestream *fs, struct ast_frame *f)
|
||||
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)
|
||||
{
|
||||
return NULL;
|
||||
@@ -251,7 +271,11 @@ int load_module()
|
||||
mp3_open,
|
||||
mp3_rewrite,
|
||||
mp3_apply,
|
||||
mp3_play,
|
||||
mp3_write,
|
||||
mp3_seek,
|
||||
mp3_trunc,
|
||||
mp3_tell,
|
||||
mp3_read,
|
||||
mp3_close,
|
||||
mp3_getcomment);
|
||||
|
Reference in New Issue
Block a user