aboutsummaryrefslogtreecommitdiffstats
path: root/res/res_musiconhold.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_musiconhold.c')
-rw-r--r--res/res_musiconhold.c167
1 files changed, 74 insertions, 93 deletions
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 061934335..260a08c43 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -70,6 +70,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/stringfields.h"
+#include "asterisk/linkedlists.h"
#define MAX_MOHFILES 512
#define MAX_MOHFILE_LEN 128
@@ -139,24 +140,23 @@ struct mohclass {
int pid; /* PID of mpg123 */
time_t start;
pthread_t thread;
- struct mohdata *members;
/* Source of audio */
int srcfd;
/* FD for timing source */
int pseudofd;
- struct mohclass *next;
+ AST_LIST_HEAD_NOLOCK(, mohdata) members;
+ AST_LIST_ENTRY(mohclass) list;
};
struct mohdata {
int pipe[2];
int origwfmt;
struct mohclass *parent;
- struct mohdata *next;
+ struct ast_frame f;
+ AST_LIST_ENTRY(mohdata) list;
};
-static struct mohclass *mohclasses;
-
-AST_MUTEX_DEFINE_STATIC(moh_lock);
+AST_LIST_HEAD_STATIC(mohclasses, mohclass);
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
#define MPG_123 "/usr/bin/mpg123"
@@ -165,18 +165,16 @@ AST_MUTEX_DEFINE_STATIC(moh_lock);
static void ast_moh_free_class(struct mohclass **class)
{
- struct mohdata *members, *mtmp;
+ struct mohdata *member;
+
+ while ((member = AST_LIST_REMOVE_HEAD(&((*class)->members), list)))
+ free(member);
- members = (*class)->members;
- while(members) {
- mtmp = members;
- members = members->next;
- free(mtmp);
- }
if ((*class)->thread) {
pthread_cancel((*class)->thread);
(*class)->thread = 0;
}
+
free(*class);
*class = NULL;
}
@@ -515,7 +513,7 @@ static void *monmp3thread(void *data)
}
res = 8 * MOH_MS_INTERVAL; /* 8 samples per millisecond */
}
- if (!class->members)
+ if (AST_LIST_EMPTY(&class->members))
continue;
/* Read mp3 audio */
len = ast_codec_get_len(class->format, res);
@@ -538,16 +536,15 @@ static void *monmp3thread(void *data)
continue;
}
pthread_testcancel();
- ast_mutex_lock(&moh_lock);
- moh = class->members;
- while (moh) {
+ AST_LIST_LOCK(&mohclasses);
+ AST_LIST_TRAVERSE(&class->members, moh, list) {
/* Write data */
- if ((res = write(moh->pipe[1], sbuf, res2)) != res2)
+ if ((res = write(moh->pipe[1], sbuf, res2)) != res2) {
if (option_debug)
ast_log(LOG_DEBUG, "Only wrote %d of %d bytes to pipe\n", res, res2);
- moh = moh->next;
+ }
}
- ast_mutex_unlock(&moh_lock);
+ AST_LIST_UNLOCK(&mohclasses);
}
return NULL;
}
@@ -607,60 +604,58 @@ static int moh4_exec(struct ast_channel *chan, void *data)
return 0;
}
+/*! \note This function should be called with the mohclasses list locked */
static struct mohclass *get_mohbyname(const char *name)
{
- struct mohclass *moh;
- moh = mohclasses;
- while (moh) {
+ struct mohclass *moh = NULL;
+
+ AST_LIST_TRAVERSE(&mohclasses, moh, list) {
if (!strcasecmp(name, moh->name))
- return moh;
- moh = moh->next;
+ break;
}
- return NULL;
+
+ return moh;
}
static struct mohdata *mohalloc(struct mohclass *cl)
{
struct mohdata *moh;
long flags;
+
if (!(moh = ast_calloc(1, sizeof(*moh))))
return NULL;
+
if (pipe(moh->pipe)) {
ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno));
free(moh);
return NULL;
}
+
/* Make entirely non-blocking */
flags = fcntl(moh->pipe[0], F_GETFL);
fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
flags = fcntl(moh->pipe[1], F_GETFL);
fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
+
+ moh->f.frametype = AST_FRAME_VOICE;
+ moh->f.subclass = cl->format;
+ moh->f.offset = AST_FRIENDLY_OFFSET;
+
moh->parent = cl;
- moh->next = cl->members;
- cl->members = moh;
+ AST_LIST_INSERT_HEAD(&cl->members, moh, list);
+
return moh;
}
static void moh_release(struct ast_channel *chan, void *data)
{
- struct mohdata *moh = data, *prev, *cur;
+ struct mohdata *moh = data;
int oldwfmt;
- ast_mutex_lock(&moh_lock);
- /* Unlink */
- prev = NULL;
- cur = moh->parent->members;
- while (cur) {
- if (cur == moh) {
- if (prev)
- prev->next = cur->next;
- else
- moh->parent->members = cur->next;
- break;
- }
- prev = cur;
- cur = cur->next;
- }
- ast_mutex_unlock(&moh_lock);
+
+ AST_LIST_LOCK(&mohclasses);
+ AST_LIST_REMOVE(&moh->parent->members, moh, list);
+ AST_LIST_UNLOCK(&mohclasses);
+
close(moh->pipe[0]);
close(moh->pipe[1]);
oldwfmt = moh->origwfmt;
@@ -693,7 +688,6 @@ static void *moh_alloc(struct ast_channel *chan, void *params)
static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
{
- struct ast_frame f;
struct mohdata *moh = data;
short buf[1280 + AST_FRIENDLY_OFFSET / 2];
int res;
@@ -708,25 +702,14 @@ static int moh_generate(struct ast_channel *chan, void *data, int len, int sampl
len = sizeof(buf) - AST_FRIENDLY_OFFSET;
}
res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
-#if 0
- if (res != len) {
- ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno));
- }
-#endif
if (res <= 0)
return 0;
- memset(&f, 0, sizeof(f));
-
- f.frametype = AST_FRAME_VOICE;
- f.subclass = moh->parent->format;
- f.mallocd = 0;
- f.datalen = res;
- f.data = buf + AST_FRIENDLY_OFFSET / 2;
- f.offset = AST_FRIENDLY_OFFSET;
- f.samples = ast_codec_get_samples(&f);
-
- if (ast_write(chan, &f) < 0) {
+ moh->f.datalen = res;
+ moh->f.data = buf + AST_FRIENDLY_OFFSET / 2;
+ moh->f.samples = ast_codec_get_samples(&moh->f);
+
+ if (ast_write(chan, &moh->f) < 0) {
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
return -1;
}
@@ -804,7 +787,7 @@ static int moh_register(struct mohclass *moh, int reload)
#ifdef HAVE_ZAPTEL
int x;
#endif
- ast_mutex_lock(&moh_lock);
+ AST_LIST_LOCK(&mohclasses);
if (get_mohbyname(moh->name)) {
if (reload) {
ast_log(LOG_DEBUG, "Music on Hold class '%s' left alone from initial load.\n", moh->name);
@@ -812,10 +795,10 @@ static int moh_register(struct mohclass *moh, int reload)
ast_log(LOG_WARNING, "Music on Hold class '%s' already exists\n", moh->name);
}
free(moh);
- ast_mutex_unlock(&moh_lock);
+ AST_LIST_UNLOCK(&mohclasses);
return -1;
}
- ast_mutex_unlock(&moh_lock);
+ AST_LIST_UNLOCK(&mohclasses);
time(&moh->start);
moh->start -= respawn_time;
@@ -864,10 +847,11 @@ static int moh_register(struct mohclass *moh, int reload)
ast_moh_free_class(&moh);
return -1;
}
- ast_mutex_lock(&moh_lock);
- moh->next = mohclasses;
- mohclasses = moh;
- ast_mutex_unlock(&moh_lock);
+
+ AST_LIST_LOCK(&mohclasses);
+ AST_LIST_INSERT_HEAD(&mohclasses, moh, list);
+ AST_LIST_UNLOCK(&mohclasses);
+
return 0;
}
@@ -887,9 +871,9 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *class)
class = chan->musicclass;
if (ast_strlen_zero(class))
class = "default";
- ast_mutex_lock(&moh_lock);
+ AST_LIST_LOCK(&mohclasses);
mohclass = get_mohbyname(class);
- ast_mutex_unlock(&moh_lock);
+ AST_LIST_UNLOCK(&mohclasses);
if (!mohclass) {
ast_log(LOG_WARNING, "No class: %s\n", (char *)class);
@@ -1060,16 +1044,15 @@ static int load_moh_classes(int reload)
static void ast_moh_destroy(void)
{
- struct mohclass *moh, *tmp;
+ struct mohclass *moh;
char buff[8192];
- int bytes, tbytes=0, stime = 0, pid = 0;
+ 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);
- moh = mohclasses;
- while (moh) {
+ AST_LIST_LOCK(&mohclasses);
+ while ((moh = AST_LIST_REMOVE_HEAD(&mohclasses, list))) {
if (moh->pid) {
ast_log(LOG_DEBUG, "killing %d!\n", moh->pid);
stime = time(NULL) + 2;
@@ -1083,18 +1066,14 @@ static void ast_moh_destroy(void)
kill(pid, SIGTERM);
usleep(100000);
kill(pid, SIGKILL);
- while ((ast_wait_for_input(moh->srcfd, 100) > 0) && (bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime) {
+ while ((ast_wait_for_input(moh->srcfd, 100) > 0) && (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);
close(moh->srcfd);
}
- tmp = moh;
- moh = moh->next;
- ast_moh_free_class(&tmp);
+ ast_moh_free_class(&moh);
}
- mohclasses = NULL;
- ast_mutex_unlock(&moh_lock);
+ AST_LIST_UNLOCK(&mohclasses);
}
static void moh_on_off(int on)
@@ -1108,7 +1087,7 @@ static void moh_on_off(int on)
else
ast_deactivate_generator(chan);
}
- ast_mutex_unlock(&chan->lock);
+ ast_channel_unlock(chan);
}
}
@@ -1129,8 +1108,8 @@ static int cli_files_show(int fd, int argc, char *argv[])
int i;
struct mohclass *class;
- ast_mutex_lock(&moh_lock);
- for (class = mohclasses; class; class = class->next) {
+ AST_LIST_LOCK(&mohclasses);
+ AST_LIST_TRAVERSE(&mohclasses, class, list) {
if (!class->total_files)
continue;
@@ -1138,7 +1117,7 @@ static int cli_files_show(int fd, int argc, char *argv[])
for (i = 0; i < class->total_files; i++)
ast_cli(fd, "\tFile: %s\n", class->filearray[i]);
}
- ast_mutex_unlock(&moh_lock);
+ AST_LIST_UNLOCK(&mohclasses);
return 0;
}
@@ -1147,8 +1126,8 @@ static int moh_classes_show(int fd, int argc, char *argv[])
{
struct mohclass *class;
- ast_mutex_lock(&moh_lock);
- for (class = mohclasses; class; class = class->next) {
+ AST_LIST_LOCK(&mohclasses);
+ AST_LIST_TRAVERSE(&mohclasses, class, list) {
ast_cli(fd, "Class: %s\n", class->name);
ast_cli(fd, "\tMode: %s\n", S_OR(class->mode,"<none>"));
ast_cli(fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>"));
@@ -1156,7 +1135,7 @@ static int moh_classes_show(int fd, int argc, char *argv[])
ast_cli(fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
ast_cli(fd, "\tFormat: %s\n", ast_getformatname(class->format));
}
- ast_mutex_unlock(&moh_lock);
+ AST_LIST_UNLOCK(&mohclasses);
return 0;
}
@@ -1173,12 +1152,14 @@ static int init_classes(int reload)
if (!load_moh_classes(reload)) /* Load classes from config */
return 0; /* Return if nothing is found */
- moh = mohclasses;
- while (moh) {
+
+ AST_LIST_LOCK(&mohclasses);
+ AST_LIST_TRAVERSE(&mohclasses, moh, list) {
if (moh->total_files)
moh_scan_files(moh);
- moh = moh->next;
}
+ AST_LIST_UNLOCK(&mohclasses);
+
return 1;
}