Various moh fixes (bug #3291)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4724 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2-netsec
Mark Spencer 21 years ago
parent 89fb8c1037
commit 03458dc73a

@ -79,7 +79,6 @@ static int respawn_time = 20;
struct moh_files_state {
struct mohclass *class;
struct ast_filestream *stream;
int origwfmt;
int samples;
int sample_queue;
@ -87,18 +86,19 @@ struct moh_files_state {
unsigned char save_pos;
};
#define MOH_QUIET (1 << 0)
#define MOH_SINGLE (1 << 1)
#define MOH_CUSTOM (1 << 2)
#define MOH_RANDOMIZE (1 << 3)
struct mohclass {
char class[80];
char dir[256];
char miscargs[256];
char filearray[MAX_MOHFILES][MAX_MOHFILE_LEN];
unsigned int flags;
int total_files;
int destroyme;
int pid; /* PID of mpg123 */
int quiet;
int single;
int custom;
int randomize;
time_t start;
pthread_t thread;
struct mohdata *members;
@ -154,7 +154,7 @@ static int ast_moh_files_next(struct ast_channel *chan) {
state->pos++;
}
if (state->class->randomize) {
if (ast_test_flag(state->class, MOH_RANDOMIZE)) {
srand(time(NULL)+getpid()+strlen(chan->name)-state->class->total_files);
state->pos = rand();
}
@ -175,19 +175,18 @@ static int ast_moh_files_next(struct ast_channel *chan) {
if (option_verbose > 2)
ast_log(LOG_NOTICE, "%s Opened file %d '%s'\n", chan->name, state->pos, state->class->filearray[state->pos]);
if (state->samples)
ast_seekstream(chan->stream, state->samples, SEEK_SET);
return state->pos;
return 0;
}
static struct ast_frame *moh_files_readframe(struct ast_channel *chan) {
struct ast_frame *f = NULL;
if (!chan->stream || !(f = ast_readframe(chan->stream))) {
if (ast_moh_files_next(chan) > -1)
if (!(chan->stream && (f = ast_readframe(chan->stream)))) {
if (!ast_moh_files_next(chan))
f = ast_readframe(chan->stream);
}
@ -224,13 +223,12 @@ static void *moh_files_alloc(struct ast_channel *chan, void *params)
struct mohclass *class = params;
int allocated = 0;
if ((!chan->music_state) && ((state = malloc(sizeof(struct moh_files_state))))) {
if (!chan->music_state && (state = malloc(sizeof(struct moh_files_state)))) {
chan->music_state = state;
allocated = 1;
} else
state = chan->music_state;
if (state) {
if (allocated || state->class != class) {
/* initialize */
@ -246,10 +244,8 @@ static void *moh_files_alloc(struct ast_channel *chan, void *params)
chan->music_state = NULL;
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on %s\n", (char *)params, chan->name);
ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on %s\n", class->class, chan->name);
}
}
return chan->music_state;
@ -281,7 +277,7 @@ static int spawn_mp3(struct mohclass *class)
return -1;
}
if (!class->custom) {
if (!ast_test_flag(class, MOH_CUSTOM)) {
argv[argc++] = "mpg123";
argv[argc++] = "-q";
argv[argc++] = "-s";
@ -289,14 +285,14 @@ static int spawn_mp3(struct mohclass *class)
argv[argc++] = "-r";
argv[argc++] = "8000";
if (!class->single) {
if (!ast_test_flag(class, MOH_SINGLE)) {
argv[argc++] = "-b";
argv[argc++] = "2048";
}
argv[argc++] = "-f";
if (class->quiet)
if (ast_test_flag(class, MOH_QUIET))
argv[argc++] = "4096";
else
argv[argc++] = "8192";
@ -334,10 +330,10 @@ static int spawn_mp3(struct mohclass *class)
} else {
while ((de = readdir(dir)) && (files < MAX_MP3S)) {
if ((strlen(de->d_name) > 3) &&
((class->custom &&
((ast_test_flag(class, MOH_CUSTOM) &&
(!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".raw") ||
!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".sln")))
|| !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3"))) {
!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".sln"))) ||
!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3"))) {
strncpy(fns[files], de->d_name, sizeof(fns[files]) - 1);
argv[argc++] = fns[files];
files++;
@ -389,7 +385,7 @@ static int spawn_mp3(struct mohclass *class)
}
/* Child */
chdir(class->dir);
if(class->custom) {
if (ast_test_flag(class, MOH_CUSTOM)) {
execv(argv[0], argv);
} else {
/* Default install is /usr/local/bin */
@ -525,7 +521,7 @@ static int moh1_exec(struct ast_channel *chan, void *data)
return -1;
}
if (ast_moh_start(chan, NULL)) {
ast_log(LOG_WARNING, "Unable to start music on hold for %d seconds on channel %s\n", atoi((char *)data), chan->name);
ast_log(LOG_WARNING, "Unable to start music on hold for %d seconds on channel %s\n", atoi(data), chan->name);
return -1;
}
res = ast_safe_sleep(chan, atoi(data) * 1000);
@ -616,13 +612,8 @@ static void *moh_alloc(struct ast_channel *chan, void *params)
struct mohdata *res;
struct mohclass *class;
class = params;
if (class)
res = mohalloc(class);
else {
if (strcasecmp(params, "default"))
ast_log(LOG_WARNING, "No class: %s\n", (char *)params);
res = NULL;
}
if (res) {
res->origwfmt = chan->writeformat;
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
@ -631,7 +622,7 @@ static void *moh_alloc(struct ast_channel *chan, void *params)
res = NULL;
}
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on %s\n", (char *)params, chan->name);
ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on %s\n", class->class, chan->name);
}
return res;
}
@ -642,11 +633,13 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
struct mohdata *moh = data;
short buf[1280 + AST_FRIENDLY_OFFSET / 2];
int res;
if (!moh->parent->pid)
return -1;
len = samples * 2;
if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), (int)len, chan->name);
ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), len, chan->name);
len = sizeof(buf) - AST_FRIENDLY_OFFSET;
}
res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
@ -655,7 +648,9 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno));
}
#endif
if (res > 0) {
if (res <= 0)
return 0;
memset(&f, 0, sizeof(f));
f.frametype = AST_FRAME_VOICE;
f.subclass = AST_FORMAT_SLINEAR;
@ -668,7 +663,6 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
return -1;
}
}
return 0;
}
@ -759,7 +753,7 @@ static int moh_register(char *classname, char *mode, char *param, char *miscargs
if (miscargs) {
strncpy(moh->miscargs, miscargs, sizeof(moh->miscargs) - 1);
if (strchr(miscargs,'r'))
moh->randomize=1;
ast_set_flag(moh, MOH_RANDOMIZE);
}
if (!strcasecmp(mode, "files")) {
if (param)
@ -774,11 +768,11 @@ static int moh_register(char *classname, char *mode, char *param, char *miscargs
strncpy(moh->dir, param, sizeof(moh->dir) - 1);
if (!strcasecmp(mode, "custom"))
moh->custom = 1;
ast_set_flag(moh, MOH_CUSTOM);
else if (!strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3nb"))
moh->single = 1;
ast_set_flag(moh, MOH_SINGLE);
else if (!strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb"))
moh->quiet = 1;
ast_set_flag(moh, MOH_QUIET);
moh->srcfd = -1;
#ifdef ZAPATA_MOH
@ -865,19 +859,20 @@ static int load_moh_classes(void)
char *data;
char *args;
int x = 0;
cfg = ast_load("musiconhold.conf");
if (cfg) {
if (!cfg)
return 0;
var = ast_variable_browse(cfg, "classes");
while (var) {
data = strchr(var->value, ':');
if (data) {
*data = '\0';
data++;
*data++ = '\0';
args = strchr(data, ',');
if (args) {
*args = '\0';
args++;
}
if (args)
*args++ = '\0';
if (!(get_mohbyname(var->name))) {
moh_register(var->name, var->value, data, args);
x++;
@ -889,10 +884,8 @@ static int load_moh_classes(void)
while (var) {
if (!(get_mohbyname(var->name))) {
args = strchr(var->value, ',');
if (args) {
*args = '\0';
args++;
}
if (args)
*args++ = '\0';
moh_register(var->name, "files", var->value, args);
x++;
}
@ -900,7 +893,6 @@ static int load_moh_classes(void)
}
ast_destroy(cfg);
}
return x;
}
@ -909,6 +901,7 @@ static void ast_moh_destroy(void)
struct mohclass *moh,*tmp;
char buff[8192];
int bytes, tbytes=0, stime = 0, pid = 0;
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Destroying musiconhold processes\n");
ast_mutex_lock(&moh_lock);
@ -917,11 +910,11 @@ static void ast_moh_destroy(void)
while (moh) {
if (moh->pid) {
ast_log(LOG_DEBUG, "killing %d!\n", moh->pid);
stime = time(NULL);
stime = time(NULL) + 5;
pid = moh->pid;
moh->pid = 0;
kill(pid, SIGKILL);
while ((bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime + 5) {
while ((bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime) {
tbytes = tbytes + bytes;
}
ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", pid, tbytes);
@ -935,9 +928,9 @@ static void ast_moh_destroy(void)
ast_mutex_unlock(&moh_lock);
}
static void moh_on_off(int on) {
struct ast_channel *chan = ast_channel_walk_locked(NULL);
while (chan) {
if (ast_test_flag(chan, AST_FLAG_MOH)) {
if (on)
@ -952,7 +945,8 @@ static void moh_on_off(int on) {
static int moh_cli(int fd, int argc, char *argv[])
{
int x = 0;
int x;
moh_on_off(0);
ast_moh_destroy();
x = load_moh_classes();
@ -984,8 +978,9 @@ static struct ast_cli_entry cli_moh = { { "moh", "reload"}, moh_cli, "Music On
static struct ast_cli_entry cli_moh_files_show = { { "moh", "files", "show"}, cli_files_show, "List MOH file-based classes", "Lists all loaded file-based MOH classes and their files", NULL};
static int init_classes(void) {
static void init_classes(void) {
struct mohclass *moh;
load_moh_classes();
moh = mohclasses;
while (moh) {
@ -993,12 +988,12 @@ static int init_classes(void) {
moh_scan_files(moh);
moh = moh->next;
}
return 0;
}
int load_module(void)
{
int res;
ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop, local_ast_moh_cleanup);
res = ast_register_application(app0, moh0_exec, synopsis0, descrip0);
ast_register_atexit(ast_moh_destroy);
@ -1009,14 +1004,17 @@ int load_module(void)
if (!res)
res = ast_register_application(app2, moh2_exec, synopsis2, descrip2);
return init_classes();
init_classes();
return 0;
}
int reload(void)
{
return init_classes();
}
init_classes();
return 0;
}
int unload_module(void)
{

Loading…
Cancel
Save