|
|
@ -43,10 +43,6 @@ struct ast_format {
|
|
|
|
struct ast_filestream * (*open)(int fd);
|
|
|
|
struct ast_filestream * (*open)(int fd);
|
|
|
|
/* Open an output stream, of a given file descriptor and comment it appropriately if applicable */
|
|
|
|
/* Open an output stream, of a given file descriptor and comment it appropriately if applicable */
|
|
|
|
struct ast_filestream * (*rewrite)(int fd, char *comment);
|
|
|
|
struct ast_filestream * (*rewrite)(int fd, char *comment);
|
|
|
|
/* Apply a reading filestream to a channel */
|
|
|
|
|
|
|
|
int (*apply)(struct ast_channel *, struct ast_filestream *);
|
|
|
|
|
|
|
|
/* play filestream on a channel */
|
|
|
|
|
|
|
|
int (*play)(struct ast_filestream *);
|
|
|
|
|
|
|
|
/* Write a frame to a channel */
|
|
|
|
/* Write a frame to a channel */
|
|
|
|
int (*write)(struct ast_filestream *, struct ast_frame *);
|
|
|
|
int (*write)(struct ast_filestream *, struct ast_frame *);
|
|
|
|
/* seek num samples into file, whence(think normal seek) */
|
|
|
|
/* seek num samples into file, whence(think normal seek) */
|
|
|
@ -55,8 +51,9 @@ struct ast_format {
|
|
|
|
int (*trunc)(struct ast_filestream *fs);
|
|
|
|
int (*trunc)(struct ast_filestream *fs);
|
|
|
|
/* tell current position */
|
|
|
|
/* tell current position */
|
|
|
|
long (*tell)(struct ast_filestream *fs);
|
|
|
|
long (*tell)(struct ast_filestream *fs);
|
|
|
|
/* Read the next frame from the filestream (if available) */
|
|
|
|
/* Read the next frame from the filestream (if available) and report when to get next one
|
|
|
|
struct ast_frame * (*read)(struct ast_filestream *);
|
|
|
|
(in samples) */
|
|
|
|
|
|
|
|
struct ast_frame * (*read)(struct ast_filestream *, int *whennext);
|
|
|
|
/* Close file, and destroy filestream structure */
|
|
|
|
/* Close file, and destroy filestream structure */
|
|
|
|
void (*close)(struct ast_filestream *);
|
|
|
|
void (*close)(struct ast_filestream *);
|
|
|
|
/* Retrieve file comment */
|
|
|
|
/* Retrieve file comment */
|
|
|
@ -72,6 +69,8 @@ struct ast_filestream {
|
|
|
|
struct ast_trans_pvt *trans;
|
|
|
|
struct ast_trans_pvt *trans;
|
|
|
|
struct ast_tranlator_pvt *tr;
|
|
|
|
struct ast_tranlator_pvt *tr;
|
|
|
|
int lastwriteformat;
|
|
|
|
int lastwriteformat;
|
|
|
|
|
|
|
|
int lasttimeout;
|
|
|
|
|
|
|
|
struct ast_channel *owner;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static pthread_mutex_t formatlock = AST_MUTEX_INITIALIZER;
|
|
|
|
static pthread_mutex_t formatlock = AST_MUTEX_INITIALIZER;
|
|
|
@ -81,13 +80,11 @@ static struct ast_format *formats = NULL;
|
|
|
|
int ast_format_register(char *name, char *exts, int format,
|
|
|
|
int ast_format_register(char *name, char *exts, int format,
|
|
|
|
struct ast_filestream * (*open)(int fd),
|
|
|
|
struct ast_filestream * (*open)(int fd),
|
|
|
|
struct ast_filestream * (*rewrite)(int fd, char *comment),
|
|
|
|
struct ast_filestream * (*rewrite)(int fd, char *comment),
|
|
|
|
int (*apply)(struct ast_channel *, struct ast_filestream *),
|
|
|
|
|
|
|
|
int (*play)(struct ast_filestream *),
|
|
|
|
|
|
|
|
int (*write)(struct ast_filestream *, struct ast_frame *),
|
|
|
|
int (*write)(struct ast_filestream *, struct ast_frame *),
|
|
|
|
int (*seek)(struct ast_filestream *, long sample_offset, int whence),
|
|
|
|
int (*seek)(struct ast_filestream *, long sample_offset, int whence),
|
|
|
|
int (*trunc)(struct ast_filestream *),
|
|
|
|
int (*trunc)(struct ast_filestream *),
|
|
|
|
long (*tell)(struct ast_filestream *),
|
|
|
|
long (*tell)(struct ast_filestream *),
|
|
|
|
struct ast_frame * (*read)(struct ast_filestream *),
|
|
|
|
struct ast_frame * (*read)(struct ast_filestream *, int *whennext),
|
|
|
|
void (*close)(struct ast_filestream *),
|
|
|
|
void (*close)(struct ast_filestream *),
|
|
|
|
char * (*getcomment)(struct ast_filestream *))
|
|
|
|
char * (*getcomment)(struct ast_filestream *))
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -115,8 +112,6 @@ int ast_format_register(char *name, char *exts, int format,
|
|
|
|
strncpy(tmp->exts, exts, sizeof(tmp->exts)-1);
|
|
|
|
strncpy(tmp->exts, exts, sizeof(tmp->exts)-1);
|
|
|
|
tmp->open = open;
|
|
|
|
tmp->open = open;
|
|
|
|
tmp->rewrite = rewrite;
|
|
|
|
tmp->rewrite = rewrite;
|
|
|
|
tmp->apply = apply;
|
|
|
|
|
|
|
|
tmp->play = play;
|
|
|
|
|
|
|
|
tmp->read = read;
|
|
|
|
tmp->read = read;
|
|
|
|
tmp->write = write;
|
|
|
|
tmp->write = write;
|
|
|
|
tmp->seek = seek;
|
|
|
|
tmp->seek = seek;
|
|
|
@ -164,7 +159,7 @@ int ast_stopstream(struct ast_channel *tmp)
|
|
|
|
/* Stop a running stream if there is one */
|
|
|
|
/* Stop a running stream if there is one */
|
|
|
|
if (!tmp->stream)
|
|
|
|
if (!tmp->stream)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
tmp->stream->fmt->close(tmp->stream);
|
|
|
|
ast_closestream(tmp->stream);
|
|
|
|
if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat))
|
|
|
|
if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat))
|
|
|
|
ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
|
|
|
|
ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@ -255,7 +250,7 @@ static char *build_filename(char *filename, char *ext)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char *fn;
|
|
|
|
char *fn;
|
|
|
|
char tmp[AST_CONFIG_MAX_PATH];
|
|
|
|
char tmp[AST_CONFIG_MAX_PATH];
|
|
|
|
snprintf((char *)tmp,sizeof(tmp)-1,"%s/%s",(char *)ast_config_AST_VAR_DIR,"sounds");
|
|
|
|
snprintf(tmp,sizeof(tmp)-1,"%s/%s",(char *)ast_config_AST_VAR_DIR,"sounds");
|
|
|
|
fn = malloc(strlen(tmp) + strlen(filename) + strlen(ext) + 10);
|
|
|
|
fn = malloc(strlen(tmp) + strlen(filename) + strlen(ext) + 10);
|
|
|
|
if (fn) {
|
|
|
|
if (fn) {
|
|
|
|
if (filename[0] == '/')
|
|
|
|
if (filename[0] == '/')
|
|
|
@ -345,6 +340,7 @@ static int ast_filehelper(char *filename, char *filename2, char *fmt, int action
|
|
|
|
if (ret >= 0) {
|
|
|
|
if (ret >= 0) {
|
|
|
|
s = f->open(ret);
|
|
|
|
s = f->open(ret);
|
|
|
|
if (s) {
|
|
|
|
if (s) {
|
|
|
|
|
|
|
|
s->lasttimeout = -1;
|
|
|
|
s->fmt = f;
|
|
|
|
s->fmt = f;
|
|
|
|
s->trans = NULL;
|
|
|
|
s->trans = NULL;
|
|
|
|
chan->stream = s;
|
|
|
|
chan->stream = s;
|
|
|
@ -427,24 +423,43 @@ struct ast_filestream *ast_openstream(struct ast_channel *chan, char *filename,
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
|
|
|
|
static int ast_readaudio_callback(void *data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(chan->stream->fmt->apply(chan,s)){
|
|
|
|
struct ast_filestream *s = data;
|
|
|
|
chan->stream->fmt->close(s);
|
|
|
|
struct ast_frame *fr;
|
|
|
|
chan->stream = NULL;
|
|
|
|
int whennext = 0;
|
|
|
|
ast_log(LOG_WARNING, "Unable to apply stream to channel %s\n", chan->name);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
while(!whennext) {
|
|
|
|
|
|
|
|
fr = s->fmt->read(s, &whennext);
|
|
|
|
|
|
|
|
if (fr) {
|
|
|
|
|
|
|
|
if (ast_write(s->owner, fr)) {
|
|
|
|
|
|
|
|
ast_log(LOG_WARNING, "Failed to write frame\n");
|
|
|
|
|
|
|
|
s->owner->streamid = -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* Stream has finished */
|
|
|
|
|
|
|
|
s->owner->streamid = -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (whennext != s->lasttimeout) {
|
|
|
|
|
|
|
|
s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_readaudio_callback, s);
|
|
|
|
|
|
|
|
s->lasttimeout = whennext;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
s->owner = chan;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ast_playstream(struct ast_filestream *s)
|
|
|
|
int ast_playstream(struct ast_filestream *s)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(s->fmt->play(s)){
|
|
|
|
ast_readaudio_callback(s);
|
|
|
|
ast_closestream(s);
|
|
|
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to start playing stream\n");
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -481,6 +496,12 @@ int ast_stream_rewind(struct ast_filestream *fs, long ms)
|
|
|
|
int ast_closestream(struct ast_filestream *f)
|
|
|
|
int ast_closestream(struct ast_filestream *f)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Stop a running stream if there is one */
|
|
|
|
/* Stop a running stream if there is one */
|
|
|
|
|
|
|
|
if (f->owner) {
|
|
|
|
|
|
|
|
f->owner->stream = NULL;
|
|
|
|
|
|
|
|
if (f->owner->streamid > -1)
|
|
|
|
|
|
|
|
ast_sched_del(f->owner->sched, f->owner->streamid);
|
|
|
|
|
|
|
|
f->owner->streamid = -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
f->fmt->close(f);
|
|
|
|
f->fmt->close(f);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|