mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-25 06:00:36 +00:00
Various moh fixes (bug #3291)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4724 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -79,7 +79,6 @@ static int respawn_time = 20;
|
|||||||
|
|
||||||
struct moh_files_state {
|
struct moh_files_state {
|
||||||
struct mohclass *class;
|
struct mohclass *class;
|
||||||
struct ast_filestream *stream;
|
|
||||||
int origwfmt;
|
int origwfmt;
|
||||||
int samples;
|
int samples;
|
||||||
int sample_queue;
|
int sample_queue;
|
||||||
@@ -87,18 +86,19 @@ struct moh_files_state {
|
|||||||
unsigned char save_pos;
|
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 {
|
struct mohclass {
|
||||||
char class[80];
|
char class[80];
|
||||||
char dir[256];
|
char dir[256];
|
||||||
char miscargs[256];
|
char miscargs[256];
|
||||||
char filearray[MAX_MOHFILES][MAX_MOHFILE_LEN];
|
char filearray[MAX_MOHFILES][MAX_MOHFILE_LEN];
|
||||||
|
unsigned int flags;
|
||||||
int total_files;
|
int total_files;
|
||||||
int destroyme;
|
|
||||||
int pid; /* PID of mpg123 */
|
int pid; /* PID of mpg123 */
|
||||||
int quiet;
|
|
||||||
int single;
|
|
||||||
int custom;
|
|
||||||
int randomize;
|
|
||||||
time_t start;
|
time_t start;
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
struct mohdata *members;
|
struct mohdata *members;
|
||||||
@@ -143,7 +143,7 @@ static void moh_files_release(struct ast_channel *chan, void *data)
|
|||||||
static int ast_moh_files_next(struct ast_channel *chan) {
|
static int ast_moh_files_next(struct ast_channel *chan) {
|
||||||
struct moh_files_state *state = chan->music_state;
|
struct moh_files_state *state = chan->music_state;
|
||||||
|
|
||||||
if(state->save_pos) {
|
if (state->save_pos) {
|
||||||
state->pos = state->save_pos - 1;
|
state->pos = state->save_pos - 1;
|
||||||
state->save_pos = 0;
|
state->save_pos = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -154,7 +154,7 @@ static int ast_moh_files_next(struct ast_channel *chan) {
|
|||||||
state->pos++;
|
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);
|
srand(time(NULL)+getpid()+strlen(chan->name)-state->class->total_files);
|
||||||
state->pos = rand();
|
state->pos = rand();
|
||||||
}
|
}
|
||||||
@@ -175,19 +175,18 @@ static int ast_moh_files_next(struct ast_channel *chan) {
|
|||||||
if (option_verbose > 2)
|
if (option_verbose > 2)
|
||||||
ast_log(LOG_NOTICE, "%s Opened file %d '%s'\n", chan->name, state->pos, state->class->filearray[state->pos]);
|
ast_log(LOG_NOTICE, "%s Opened file %d '%s'\n", chan->name, state->pos, state->class->filearray[state->pos]);
|
||||||
|
|
||||||
|
|
||||||
if (state->samples)
|
if (state->samples)
|
||||||
ast_seekstream(chan->stream, state->samples, SEEK_SET);
|
ast_seekstream(chan->stream, state->samples, SEEK_SET);
|
||||||
|
|
||||||
return state->pos;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct ast_frame *moh_files_readframe(struct ast_channel *chan) {
|
static struct ast_frame *moh_files_readframe(struct ast_channel *chan) {
|
||||||
struct ast_frame *f = NULL;
|
struct ast_frame *f = NULL;
|
||||||
|
|
||||||
if (!chan->stream || !(f = ast_readframe(chan->stream))) {
|
if (!(chan->stream && (f = ast_readframe(chan->stream)))) {
|
||||||
if (ast_moh_files_next(chan) > -1)
|
if (!ast_moh_files_next(chan))
|
||||||
f = ast_readframe(chan->stream);
|
f = ast_readframe(chan->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,12 +200,12 @@ static int moh_files_generator(struct ast_channel *chan, void *data, int len, in
|
|||||||
int res = 0;
|
int res = 0;
|
||||||
state->sample_queue += samples;
|
state->sample_queue += samples;
|
||||||
|
|
||||||
while(state->sample_queue > 0) {
|
while (state->sample_queue > 0) {
|
||||||
if ((f = moh_files_readframe(chan))) {
|
if ((f = moh_files_readframe(chan))) {
|
||||||
state->samples += f->samples;
|
state->samples += f->samples;
|
||||||
res = ast_write(chan, f);
|
res = ast_write(chan, f);
|
||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
if(res < 0) {
|
if (res < 0) {
|
||||||
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
|
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -224,14 +223,13 @@ static void *moh_files_alloc(struct ast_channel *chan, void *params)
|
|||||||
struct mohclass *class = params;
|
struct mohclass *class = params;
|
||||||
int allocated = 0;
|
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;
|
chan->music_state = state;
|
||||||
allocated = 1;
|
allocated = 1;
|
||||||
} else
|
} else
|
||||||
state = chan->music_state;
|
state = chan->music_state;
|
||||||
|
|
||||||
|
if (state) {
|
||||||
if(state) {
|
|
||||||
if (allocated || state->class != class) {
|
if (allocated || state->class != class) {
|
||||||
/* initialize */
|
/* initialize */
|
||||||
memset(state, 0, sizeof(struct moh_files_state));
|
memset(state, 0, sizeof(struct moh_files_state));
|
||||||
@@ -246,10 +244,8 @@ static void *moh_files_alloc(struct ast_channel *chan, void *params)
|
|||||||
chan->music_state = NULL;
|
chan->music_state = NULL;
|
||||||
} else {
|
} else {
|
||||||
if (option_verbose > 2)
|
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;
|
return chan->music_state;
|
||||||
@@ -281,7 +277,7 @@ static int spawn_mp3(struct mohclass *class)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!class->custom) {
|
if (!ast_test_flag(class, MOH_CUSTOM)) {
|
||||||
argv[argc++] = "mpg123";
|
argv[argc++] = "mpg123";
|
||||||
argv[argc++] = "-q";
|
argv[argc++] = "-q";
|
||||||
argv[argc++] = "-s";
|
argv[argc++] = "-s";
|
||||||
@@ -289,14 +285,14 @@ static int spawn_mp3(struct mohclass *class)
|
|||||||
argv[argc++] = "-r";
|
argv[argc++] = "-r";
|
||||||
argv[argc++] = "8000";
|
argv[argc++] = "8000";
|
||||||
|
|
||||||
if (!class->single) {
|
if (!ast_test_flag(class, MOH_SINGLE)) {
|
||||||
argv[argc++] = "-b";
|
argv[argc++] = "-b";
|
||||||
argv[argc++] = "2048";
|
argv[argc++] = "2048";
|
||||||
}
|
}
|
||||||
|
|
||||||
argv[argc++] = "-f";
|
argv[argc++] = "-f";
|
||||||
|
|
||||||
if (class->quiet)
|
if (ast_test_flag(class, MOH_QUIET))
|
||||||
argv[argc++] = "4096";
|
argv[argc++] = "4096";
|
||||||
else
|
else
|
||||||
argv[argc++] = "8192";
|
argv[argc++] = "8192";
|
||||||
@@ -304,7 +300,7 @@ static int spawn_mp3(struct mohclass *class)
|
|||||||
/* Look for extra arguments and add them to the list */
|
/* Look for extra arguments and add them to the list */
|
||||||
strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
|
strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
|
||||||
argptr = xargs;
|
argptr = xargs;
|
||||||
while(argptr && !ast_strlen_zero(argptr)) {
|
while (argptr && !ast_strlen_zero(argptr)) {
|
||||||
argv[argc++] = argptr;
|
argv[argc++] = argptr;
|
||||||
argptr = strchr(argptr, ',');
|
argptr = strchr(argptr, ',');
|
||||||
if (argptr) {
|
if (argptr) {
|
||||||
@@ -316,7 +312,7 @@ static int spawn_mp3(struct mohclass *class)
|
|||||||
/* Format arguments for argv vector */
|
/* Format arguments for argv vector */
|
||||||
strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
|
strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
|
||||||
argptr = xargs;
|
argptr = xargs;
|
||||||
while(argptr && !ast_strlen_zero(argptr)) {
|
while (argptr && !ast_strlen_zero(argptr)) {
|
||||||
argv[argc++] = argptr;
|
argv[argc++] = argptr;
|
||||||
argptr = strchr(argptr, ' ');
|
argptr = strchr(argptr, ' ');
|
||||||
if (argptr) {
|
if (argptr) {
|
||||||
@@ -332,12 +328,12 @@ static int spawn_mp3(struct mohclass *class)
|
|||||||
argv[argc++] = fns[files];
|
argv[argc++] = fns[files];
|
||||||
files++;
|
files++;
|
||||||
} else {
|
} else {
|
||||||
while((de = readdir(dir)) && (files < MAX_MP3S)) {
|
while ((de = readdir(dir)) && (files < MAX_MP3S)) {
|
||||||
if ((strlen(de->d_name) > 3) &&
|
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, ".raw") ||
|
||||||
!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".sln")))
|
!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, ".mp3"))) {
|
||||||
strncpy(fns[files], de->d_name, sizeof(fns[files]) - 1);
|
strncpy(fns[files], de->d_name, sizeof(fns[files]) - 1);
|
||||||
argv[argc++] = fns[files];
|
argv[argc++] = fns[files];
|
||||||
files++;
|
files++;
|
||||||
@@ -387,18 +383,18 @@ static int spawn_mp3(struct mohclass *class)
|
|||||||
close(x);
|
close(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Child */
|
/* Child */
|
||||||
chdir(class->dir);
|
chdir(class->dir);
|
||||||
if(class->custom) {
|
if (ast_test_flag(class, MOH_CUSTOM)) {
|
||||||
execv(argv[0], argv);
|
execv(argv[0], argv);
|
||||||
} else {
|
} else {
|
||||||
/* Default install is /usr/local/bin */
|
/* Default install is /usr/local/bin */
|
||||||
execv(LOCAL_MPG_123, argv);
|
execv(LOCAL_MPG_123, argv);
|
||||||
/* Many places have it in /usr/bin */
|
/* Many places have it in /usr/bin */
|
||||||
execv(MPG_123, argv);
|
execv(MPG_123, argv);
|
||||||
/* Check PATH as a last-ditch effort */
|
/* Check PATH as a last-ditch effort */
|
||||||
execvp("mpg123", argv);
|
execvp("mpg123", argv);
|
||||||
}
|
}
|
||||||
ast_log(LOG_WARNING, "Exec failed: %s\n", strerror(errno));
|
ast_log(LOG_WARNING, "Exec failed: %s\n", strerror(errno));
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -462,7 +458,7 @@ static void *monmp3thread(void *data)
|
|||||||
tv.tv_sec = tv_tmp.tv_sec + (MOH_MS_INTERVAL/1000 - error_sec);
|
tv.tv_sec = tv_tmp.tv_sec + (MOH_MS_INTERVAL/1000 - error_sec);
|
||||||
tv.tv_usec = tv_tmp.tv_usec + ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec);
|
tv.tv_usec = tv_tmp.tv_usec + ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec);
|
||||||
delay = (MOH_MS_INTERVAL/1000 - error_sec) * 1000 +
|
delay = (MOH_MS_INTERVAL/1000 - error_sec) * 1000 +
|
||||||
((MOH_MS_INTERVAL % 1000) * 1000 - error_usec) / 1000;
|
((MOH_MS_INTERVAL % 1000) * 1000 - error_usec) / 1000;
|
||||||
} else {
|
} else {
|
||||||
ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
|
ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
|
||||||
tv.tv_sec = tv_tmp.tv_sec;
|
tv.tv_sec = tv_tmp.tv_sec;
|
||||||
@@ -494,7 +490,7 @@ static void *monmp3thread(void *data)
|
|||||||
}
|
}
|
||||||
ast_mutex_lock(&moh_lock);
|
ast_mutex_lock(&moh_lock);
|
||||||
moh = class->members;
|
moh = class->members;
|
||||||
while(moh) {
|
while (moh) {
|
||||||
/* Write data */
|
/* Write data */
|
||||||
if ((res = write(moh->pipe[1], sbuf, res2)) != res2)
|
if ((res = write(moh->pipe[1], sbuf, res2)) != res2)
|
||||||
if (option_debug)
|
if (option_debug)
|
||||||
@@ -512,7 +508,7 @@ static int moh0_exec(struct ast_channel *chan, void *data)
|
|||||||
ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
|
ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
while(!ast_safe_sleep(chan, 10000));
|
while (!ast_safe_sleep(chan, 10000));
|
||||||
ast_moh_stop(chan);
|
ast_moh_stop(chan);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -525,7 +521,7 @@ static int moh1_exec(struct ast_channel *chan, void *data)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ast_moh_start(chan, NULL)) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
res = ast_safe_sleep(chan, atoi(data) * 1000);
|
res = ast_safe_sleep(chan, atoi(data) * 1000);
|
||||||
@@ -547,7 +543,7 @@ static struct mohclass *get_mohbyname(char *name)
|
|||||||
{
|
{
|
||||||
struct mohclass *moh;
|
struct mohclass *moh;
|
||||||
moh = mohclasses;
|
moh = mohclasses;
|
||||||
while(moh) {
|
while (moh) {
|
||||||
if (!strcasecmp(name, moh->class))
|
if (!strcasecmp(name, moh->class))
|
||||||
return moh;
|
return moh;
|
||||||
moh = moh->next;
|
moh = moh->next;
|
||||||
@@ -587,7 +583,7 @@ static void moh_release(struct ast_channel *chan, void *data)
|
|||||||
/* Unlink */
|
/* Unlink */
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
cur = moh->parent->members;
|
cur = moh->parent->members;
|
||||||
while(cur) {
|
while (cur) {
|
||||||
if (cur == moh) {
|
if (cur == moh) {
|
||||||
if (prev)
|
if (prev)
|
||||||
prev->next = cur->next;
|
prev->next = cur->next;
|
||||||
@@ -616,13 +612,8 @@ static void *moh_alloc(struct ast_channel *chan, void *params)
|
|||||||
struct mohdata *res;
|
struct mohdata *res;
|
||||||
struct mohclass *class;
|
struct mohclass *class;
|
||||||
class = params;
|
class = params;
|
||||||
if (class)
|
|
||||||
res = mohalloc(class);
|
res = mohalloc(class);
|
||||||
else {
|
|
||||||
if (strcasecmp(params, "default"))
|
|
||||||
ast_log(LOG_WARNING, "No class: %s\n", (char *)params);
|
|
||||||
res = NULL;
|
|
||||||
}
|
|
||||||
if (res) {
|
if (res) {
|
||||||
res->origwfmt = chan->writeformat;
|
res->origwfmt = chan->writeformat;
|
||||||
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
|
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;
|
res = NULL;
|
||||||
}
|
}
|
||||||
if (option_verbose > 2)
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -642,11 +633,13 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
|
|||||||
struct mohdata *moh = data;
|
struct mohdata *moh = data;
|
||||||
short buf[1280 + AST_FRIENDLY_OFFSET / 2];
|
short buf[1280 + AST_FRIENDLY_OFFSET / 2];
|
||||||
int res;
|
int res;
|
||||||
if(!moh->parent->pid)
|
|
||||||
return - 1;
|
if (!moh->parent->pid)
|
||||||
|
return -1;
|
||||||
|
|
||||||
len = samples * 2;
|
len = samples * 2;
|
||||||
if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
|
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;
|
len = sizeof(buf) - AST_FRIENDLY_OFFSET;
|
||||||
}
|
}
|
||||||
res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
|
res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
|
||||||
@@ -655,19 +648,20 @@ 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));
|
ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (res > 0) {
|
if (res <= 0)
|
||||||
memset(&f, 0, sizeof(f));
|
return 0;
|
||||||
f.frametype = AST_FRAME_VOICE;
|
|
||||||
f.subclass = AST_FORMAT_SLINEAR;
|
memset(&f, 0, sizeof(f));
|
||||||
f.mallocd = 0;
|
f.frametype = AST_FRAME_VOICE;
|
||||||
f.datalen = res;
|
f.subclass = AST_FORMAT_SLINEAR;
|
||||||
f.samples = res / 2;
|
f.mallocd = 0;
|
||||||
f.data = buf + AST_FRIENDLY_OFFSET / 2;
|
f.datalen = res;
|
||||||
f.offset = AST_FRIENDLY_OFFSET;
|
f.samples = res / 2;
|
||||||
if (ast_write(chan, &f)< 0) {
|
f.data = buf + AST_FRIENDLY_OFFSET / 2;
|
||||||
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
|
f.offset = AST_FRIENDLY_OFFSET;
|
||||||
return -1;
|
if (ast_write(chan, &f) < 0) {
|
||||||
}
|
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -759,7 +753,7 @@ static int moh_register(char *classname, char *mode, char *param, char *miscargs
|
|||||||
if (miscargs) {
|
if (miscargs) {
|
||||||
strncpy(moh->miscargs, miscargs, sizeof(moh->miscargs) - 1);
|
strncpy(moh->miscargs, miscargs, sizeof(moh->miscargs) - 1);
|
||||||
if (strchr(miscargs,'r'))
|
if (strchr(miscargs,'r'))
|
||||||
moh->randomize=1;
|
ast_set_flag(moh, MOH_RANDOMIZE);
|
||||||
}
|
}
|
||||||
if (!strcasecmp(mode, "files")) {
|
if (!strcasecmp(mode, "files")) {
|
||||||
if (param)
|
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);
|
strncpy(moh->dir, param, sizeof(moh->dir) - 1);
|
||||||
|
|
||||||
if (!strcasecmp(mode, "custom"))
|
if (!strcasecmp(mode, "custom"))
|
||||||
moh->custom = 1;
|
ast_set_flag(moh, MOH_CUSTOM);
|
||||||
else if (!strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3nb"))
|
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"))
|
else if (!strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb"))
|
||||||
moh->quiet = 1;
|
ast_set_flag(moh, MOH_QUIET);
|
||||||
|
|
||||||
moh->srcfd = -1;
|
moh->srcfd = -1;
|
||||||
#ifdef ZAPATA_MOH
|
#ifdef ZAPATA_MOH
|
||||||
@@ -815,7 +809,7 @@ static int moh_register(char *classname, char *mode, char *param, char *miscargs
|
|||||||
|
|
||||||
static void local_ast_moh_cleanup(struct ast_channel *chan)
|
static void local_ast_moh_cleanup(struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
if(chan->music_state) {
|
if (chan->music_state) {
|
||||||
free(chan->music_state);
|
free(chan->music_state);
|
||||||
chan->music_state = NULL;
|
chan->music_state = NULL;
|
||||||
}
|
}
|
||||||
@@ -850,8 +844,8 @@ static void local_ast_moh_stop(struct ast_channel *chan)
|
|||||||
ast_clear_flag(chan, AST_FLAG_MOH);
|
ast_clear_flag(chan, AST_FLAG_MOH);
|
||||||
ast_deactivate_generator(chan);
|
ast_deactivate_generator(chan);
|
||||||
|
|
||||||
if(chan->music_state) {
|
if (chan->music_state) {
|
||||||
if(chan->stream) {
|
if (chan->stream) {
|
||||||
ast_closestream(chan->stream);
|
ast_closestream(chan->stream);
|
||||||
chan->stream = NULL;
|
chan->stream = NULL;
|
||||||
}
|
}
|
||||||
@@ -865,42 +859,40 @@ static int load_moh_classes(void)
|
|||||||
char *data;
|
char *data;
|
||||||
char *args;
|
char *args;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|
||||||
cfg = ast_load("musiconhold.conf");
|
cfg = ast_load("musiconhold.conf");
|
||||||
if (cfg) {
|
|
||||||
var = ast_variable_browse(cfg, "classes");
|
if (!cfg)
|
||||||
while(var) {
|
return 0;
|
||||||
data = strchr(var->value, ':');
|
|
||||||
if (data) {
|
var = ast_variable_browse(cfg, "classes");
|
||||||
*data = '\0';
|
while (var) {
|
||||||
data++;
|
data = strchr(var->value, ':');
|
||||||
args = strchr(data, ',');
|
if (data) {
|
||||||
if (args) {
|
*data++ = '\0';
|
||||||
*args = '\0';
|
args = strchr(data, ',');
|
||||||
args++;
|
if (args)
|
||||||
}
|
*args++ = '\0';
|
||||||
if(!(get_mohbyname(var->name))) {
|
if (!(get_mohbyname(var->name))) {
|
||||||
moh_register(var->name, var->value, data, args);
|
moh_register(var->name, var->value, data, args);
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var = var->next;
|
|
||||||
}
|
|
||||||
var = ast_variable_browse(cfg, "moh_files");
|
|
||||||
while(var) {
|
|
||||||
if(!(get_mohbyname(var->name))) {
|
|
||||||
args = strchr(var->value, ',');
|
|
||||||
if (args) {
|
|
||||||
*args = '\0';
|
|
||||||
args++;
|
|
||||||
}
|
|
||||||
moh_register(var->name, "files", var->value, args);
|
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
var = var->next;
|
|
||||||
}
|
}
|
||||||
|
var = var->next;
|
||||||
ast_destroy(cfg);
|
|
||||||
}
|
}
|
||||||
|
var = ast_variable_browse(cfg, "moh_files");
|
||||||
|
while (var) {
|
||||||
|
if (!(get_mohbyname(var->name))) {
|
||||||
|
args = strchr(var->value, ',');
|
||||||
|
if (args)
|
||||||
|
*args++ = '\0';
|
||||||
|
moh_register(var->name, "files", var->value, args);
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
var = var->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_destroy(cfg);
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -909,19 +901,20 @@ static void ast_moh_destroy(void)
|
|||||||
struct mohclass *moh,*tmp;
|
struct mohclass *moh,*tmp;
|
||||||
char buff[8192];
|
char buff[8192];
|
||||||
int bytes, tbytes=0, stime = 0, pid = 0;
|
int bytes, tbytes=0, stime = 0, pid = 0;
|
||||||
|
|
||||||
if (option_verbose > 1)
|
if (option_verbose > 1)
|
||||||
ast_verbose(VERBOSE_PREFIX_2 "Destroying musiconhold processes\n");
|
ast_verbose(VERBOSE_PREFIX_2 "Destroying musiconhold processes\n");
|
||||||
ast_mutex_lock(&moh_lock);
|
ast_mutex_lock(&moh_lock);
|
||||||
moh = mohclasses;
|
moh = mohclasses;
|
||||||
|
|
||||||
while(moh) {
|
while (moh) {
|
||||||
if (moh->pid) {
|
if (moh->pid) {
|
||||||
ast_log(LOG_DEBUG, "killing %d!\n", moh->pid);
|
ast_log(LOG_DEBUG, "killing %d!\n", moh->pid);
|
||||||
stime = time(NULL);
|
stime = time(NULL) + 5;
|
||||||
pid = moh->pid;
|
pid = moh->pid;
|
||||||
moh->pid = 0;
|
moh->pid = 0;
|
||||||
kill(pid, SIGKILL);
|
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;
|
tbytes = tbytes + bytes;
|
||||||
}
|
}
|
||||||
ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", pid, tbytes);
|
ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", pid, tbytes);
|
||||||
@@ -935,13 +928,13 @@ static void ast_moh_destroy(void)
|
|||||||
ast_mutex_unlock(&moh_lock);
|
ast_mutex_unlock(&moh_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void moh_on_off(int on) {
|
static void moh_on_off(int on) {
|
||||||
struct ast_channel *chan = ast_channel_walk_locked(NULL);
|
struct ast_channel *chan = ast_channel_walk_locked(NULL);
|
||||||
while(chan) {
|
|
||||||
if(ast_test_flag(chan, AST_FLAG_MOH)) {
|
while (chan) {
|
||||||
if(on)
|
if (ast_test_flag(chan, AST_FLAG_MOH)) {
|
||||||
local_ast_moh_start(chan,NULL);
|
if (on)
|
||||||
|
local_ast_moh_start(chan, NULL);
|
||||||
else
|
else
|
||||||
ast_deactivate_generator(chan);
|
ast_deactivate_generator(chan);
|
||||||
}
|
}
|
||||||
@@ -952,12 +945,13 @@ static void moh_on_off(int on) {
|
|||||||
|
|
||||||
static int moh_cli(int fd, int argc, char *argv[])
|
static int moh_cli(int fd, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int x = 0;
|
int x;
|
||||||
|
|
||||||
moh_on_off(0);
|
moh_on_off(0);
|
||||||
ast_moh_destroy();
|
ast_moh_destroy();
|
||||||
x = load_moh_classes();
|
x = load_moh_classes();
|
||||||
moh_on_off(1);
|
moh_on_off(1);
|
||||||
ast_cli(fd,"\n%d class%s reloaded.\n",x,x == 1 ? "" : "es");
|
ast_cli(fd, "\n%d class%s reloaded.\n", x, x == 1 ? "" : "es");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -984,21 +978,22 @@ 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 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;
|
struct mohclass *moh;
|
||||||
load_moh_classes();
|
|
||||||
|
load_moh_classes();
|
||||||
moh = mohclasses;
|
moh = mohclasses;
|
||||||
while(moh) {
|
while (moh) {
|
||||||
if (moh->total_files)
|
if (moh->total_files)
|
||||||
moh_scan_files(moh);
|
moh_scan_files(moh);
|
||||||
moh = moh->next;
|
moh = moh->next;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_module(void)
|
int load_module(void)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop, local_ast_moh_cleanup);
|
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);
|
res = ast_register_application(app0, moh0_exec, synopsis0, descrip0);
|
||||||
ast_register_atexit(ast_moh_destroy);
|
ast_register_atexit(ast_moh_destroy);
|
||||||
@@ -1009,14 +1004,17 @@ int load_module(void)
|
|||||||
if (!res)
|
if (!res)
|
||||||
res = ast_register_application(app2, moh2_exec, synopsis2, descrip2);
|
res = ast_register_application(app2, moh2_exec, synopsis2, descrip2);
|
||||||
|
|
||||||
return init_classes();
|
init_classes();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int reload(void)
|
int reload(void)
|
||||||
{
|
{
|
||||||
return init_classes();
|
init_classes();
|
||||||
}
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int unload_module(void)
|
int unload_module(void)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user