2 * Asterisk -- A telephony toolkit for Linux.
4 * Routines implementing music on hold
6 * Copyright (C) 1999, Mark Spencer
8 * Mark Spencer <markster@linux-support.net>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
14 #include <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/options.h>
20 #include <asterisk/module.h>
21 #include <asterisk/translate.h>
22 #include <asterisk/say.h>
23 #include <asterisk/channel_pvt.h>
24 #include <asterisk/musiconhold.h>
25 #include <asterisk/config.h>
26 #include <asterisk/utils.h>
35 #include <sys/signal.h>
36 #include <netinet/in.h>
41 #include <linux/zaptel.h>
44 #endif /* __linux__ */
47 #include <sys/ioctl.h>
49 static char *app0 = "MusicOnHold";
50 static char *app1 = "WaitMusicOnHold";
51 static char *app2 = "SetMusicOnHold";
53 static char *synopsis0 = "Play Music On Hold indefinitely";
54 static char *synopsis1 = "Wait, playing Music On Hold";
55 static char *synopsis2 = "Set default Music On Hold class";
57 static char *descrip0 = "MusicOnHold(class): "
58 "Plays hold music specified by class. If omitted, the default\n"
59 "music source for the channel will be used. Set the default \n"
60 "class with the SetMusicOnHold() application.\n"
61 "Returns -1 on hangup.\n"
62 "Never returns otherwise.\n";
64 static char *descrip1 = "WaitMusicOnHold(delay): "
65 "Plays hold music specified number of seconds. Returns 0 when\n"
66 "done, or -1 on hangup. If no hold music is available, the delay will\n"
67 "still occur with no sound.\n";
69 static char *descrip2 = "SetMusicOnHold(class): "
70 "Sets the default class for music on hold for a given channel. When\n"
71 "music on hold is activated, this class will be used to select which\n"
74 static int respawn_time = 20;
81 int pid; /* PID of mpg123 */
87 struct mohdata *members;
90 /* FD for timing source */
92 struct mohclass *next;
98 struct mohclass *parent;
102 static struct mohclass *mohclasses;
105 AST_MUTEX_DEFINE_STATIC(moh_lock);
107 #define LOCAL_MPG_123 "/usr/local/bin/mpg123"
108 #define MPG_123 "/usr/bin/mpg123"
111 static int spawn_mp3(struct mohclass *class)
115 char fns[MAX_MP3S][80];
116 char *argv[MAX_MP3S + 50];
122 dir = opendir(class->dir);
123 if (!dir && !strstr(class->dir,"http://") && !strstr(class->dir,"HTTP://")) {
124 ast_log(LOG_WARNING, "%s is not a valid directory\n", class->dir);
128 if (!class->custom) {
129 argv[argc++] = "mpg123";
132 argv[argc++] = "--mono";
134 argv[argc++] = "8000";
136 if (!class->single) {
138 argv[argc++] = "2048";
144 argv[argc++] = "4096";
146 argv[argc++] = "8192";
148 /* Look for extra arguments and add them to the list */
149 strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
151 while(argptr && !ast_strlen_zero(argptr)) {
152 argv[argc++] = argptr;
153 argptr = strchr(argptr, ',');
160 /* Format arguments for argv vector */
161 strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
163 while(argptr && !ast_strlen_zero(argptr)) {
164 argv[argc++] = argptr;
165 argptr = strchr(argptr, ' ');
174 if (strstr(class->dir,"http://") || strstr(class->dir,"HTTP://"))
176 strncpy(fns[files], class->dir, sizeof(fns[files]) - 1);
177 argv[argc++] = fns[files];
182 while((de = readdir(dir)) && (files < MAX_MP3S)) {
183 if ((strlen(de->d_name) > 3) && !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3")) {
184 strncpy(fns[files], de->d_name, sizeof(fns[files]) - 1);
185 argv[argc++] = fns[files];
193 ast_log(LOG_WARNING, "Pipe failed\n");
197 printf("%d files total, %d args total\n", files, argc);
200 for (x=0;argv[x];x++)
201 printf("arg%d: %s\n", x, argv[x]);
205 ast_log(LOG_WARNING, "Found no files in '%s'\n", class->dir);
210 if (time(NULL) - class->start < respawn_time) {
211 sleep(respawn_time - (time(NULL) - class->start));
215 if (class->pid < 0) {
218 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
224 /* Stdout goes to pipe */
225 dup2(fds[1], STDOUT_FILENO);
226 /* Close unused file descriptors */
232 execv(argv[0], argv);
234 /* Default install is /usr/local/bin */
235 execv(LOCAL_MPG_123, argv);
236 /* Many places have it in /usr/bin */
237 execv(MPG_123, argv);
238 /* Check PATH as a last-ditch effort */
239 execvp("mpg123", argv);
241 ast_log(LOG_WARNING, "Exec failed: %s\n", strerror(errno));
251 static void *monmp3thread(void *data)
253 #define MOH_MS_INTERVAL 100
255 struct mohclass *class = data;
261 struct timeval tv_tmp;
262 long error_sec, error_usec;
272 /* Spawn mp3 player if it's not there */
273 if (class->srcfd < 0) {
274 if ((class->srcfd = spawn_mp3(class)) < 0) {
275 ast_log(LOG_WARNING, "unable to spawn mp3player\n");
276 /* Try again later */
280 if (class->pseudofd > -1) {
281 /* Pause some amount of time */
282 res = read(class->pseudofd, buf, sizeof(buf));
285 if (gettimeofday(&tv_tmp, NULL) < 0) {
286 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
289 if (((unsigned long)(tv.tv_sec) > 0)&&((unsigned long)(tv.tv_usec) > 0)) {
290 if ((unsigned long)(tv_tmp.tv_usec) < (unsigned long)(tv.tv_usec)) {
291 tv_tmp.tv_usec += 1000000;
294 error_sec = (unsigned long)(tv_tmp.tv_sec) - (unsigned long)(tv.tv_sec);
295 error_usec = (unsigned long)(tv_tmp.tv_usec) - (unsigned long)(tv.tv_usec);
300 if (error_sec * 1000 + error_usec / 1000 < MOH_MS_INTERVAL) {
301 tv.tv_sec = tv_tmp.tv_sec + (MOH_MS_INTERVAL/1000 - error_sec);
302 tv.tv_usec = tv_tmp.tv_usec + ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec);
303 delay = (MOH_MS_INTERVAL/1000 - error_sec) * 1000 +
304 ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec) / 1000;
306 ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
307 tv.tv_sec = tv_tmp.tv_sec;
308 tv.tv_usec = tv_tmp.tv_usec;
311 if (tv.tv_usec > 1000000) {
313 tv.tv_usec-= 1000000;
316 usleep(delay * 1000);
317 res = 800; /* 800 samples */
322 if ((res2 = read(class->srcfd, sbuf, res * 2)) != res * 2) {
327 kill(class->pid, SIGKILL);
331 ast_log(LOG_DEBUG, "Read %d bytes of audio while expecting %d\n", res2, res * 2);
334 ast_mutex_lock(&moh_lock);
335 moh = class->members;
338 if ((res = write(moh->pipe[1], sbuf, res2)) != res2)
340 ast_log(LOG_DEBUG, "Only wrote %d of %d bytes to pipe\n", res, res2);
343 ast_mutex_unlock(&moh_lock);
348 static int moh0_exec(struct ast_channel *chan, void *data)
350 if (ast_moh_start(chan, data)) {
351 ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
354 while(!ast_safe_sleep(chan, 10000));
358 static int moh1_exec(struct ast_channel *chan, void *data)
361 if (!data || !atoi(data)) {
362 ast_log(LOG_WARNING, "WaitMusicOnHold requires an argument (number of seconds to wait)\n");
365 if (ast_moh_start(chan, NULL)) {
366 ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
369 res = ast_safe_sleep(chan, atoi(data) * 1000);
374 static int moh2_exec(struct ast_channel *chan, void *data)
376 if (!data || ast_strlen_zero(data)) {
377 ast_log(LOG_WARNING, "SetMusicOnHold requires an argument (class)\n");
380 strncpy(chan->musicclass, data, sizeof(chan->musicclass) - 1);
384 static struct mohclass *get_mohbyname(char *name)
386 struct mohclass *moh;
389 if (!strcasecmp(name, moh->class))
396 static struct mohdata *mohalloc(struct mohclass *cl)
400 moh = malloc(sizeof(struct mohdata));
403 memset(moh, 0, sizeof(struct mohdata));
404 if (pipe(moh->pipe)) {
405 ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno));
409 /* Make entirely non-blocking */
410 flags = fcntl(moh->pipe[0], F_GETFL);
411 fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
412 flags = fcntl(moh->pipe[1], F_GETFL);
413 fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
415 moh->next = cl->members;
420 static void moh_release(struct ast_channel *chan, void *data)
422 struct mohdata *moh = data, *prev, *cur;
424 ast_mutex_lock(&moh_lock);
427 cur = moh->parent->members;
431 prev->next = cur->next;
433 moh->parent->members = cur->next;
439 ast_mutex_unlock(&moh_lock);
442 oldwfmt = moh->origwfmt;
445 if (oldwfmt && ast_set_write_format(chan, oldwfmt))
446 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(oldwfmt));
447 if (option_verbose > 2)
448 ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name);
452 static void *moh_alloc(struct ast_channel *chan, void *params)
455 struct mohclass *class;
456 ast_mutex_lock(&moh_lock);
457 class = get_mohbyname(params);
459 res = mohalloc(class);
461 if (strcasecmp(params, "default"))
462 ast_log(LOG_WARNING, "No class: %s\n", (char *)params);
465 ast_mutex_unlock(&moh_lock);
467 res->origwfmt = chan->writeformat;
468 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
469 ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format\n", chan->name);
470 moh_release(NULL, res);
474 /* Allow writes to interrupt */
475 chan->writeinterrupt = 1;
477 if (option_verbose > 2)
478 ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on %s\n", (char *)params, chan->name);
483 static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
486 struct mohdata *moh = data;
487 short buf[1280 + AST_FRIENDLY_OFFSET / 2];
491 if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
492 ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), (int)len, chan->name);
493 len = sizeof(buf) - AST_FRIENDLY_OFFSET;
495 res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
498 ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno));
502 memset(&f, 0, sizeof(f));
503 f.frametype = AST_FRAME_VOICE;
504 f.subclass = AST_FORMAT_SLINEAR;
508 f.data = buf + AST_FRIENDLY_OFFSET / 2;
509 f.offset = AST_FRIENDLY_OFFSET;
510 if (ast_write(chan, &f)< 0) {
511 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
518 static struct ast_generator mohgen =
521 release: moh_release,
522 generate: moh_generate,
525 static int moh_register(char *classname, char *mode, char *param, char *miscargs)
527 struct mohclass *moh;
531 ast_mutex_lock(&moh_lock);
532 moh = get_mohbyname(classname);
533 ast_mutex_unlock(&moh_lock);
535 ast_log(LOG_WARNING, "Music on Hold '%s' already exists\n", classname);
538 moh = malloc(sizeof(struct mohclass));
541 memset(moh, 0, sizeof(struct mohclass));
543 moh->start -= respawn_time;
544 strncpy(moh->class, classname, sizeof(moh->class) - 1);
546 strncpy(moh->miscargs, miscargs, sizeof(moh->miscargs) - 1);
547 if (!strcasecmp(mode, "mp3") || !strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb") || !strcasecmp(mode, "httpmp3") || !strcasecmp(mode, "custom")) {
548 if (!strcasecmp(mode, "custom"))
550 if (!strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3nb"))
552 if (!strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb"))
554 strncpy(moh->dir, param, sizeof(moh->dir) - 1);
557 /* It's an MP3 Moh -- Open /dev/zap/pseudo for timing... Is
558 there a better, yet reliable way to do this? */
559 moh->pseudofd = open("/dev/zap/pseudo", O_RDONLY);
560 if (moh->pseudofd < 0) {
561 ast_log(LOG_WARNING, "Unable to open pseudo channel for timing... Sound may be choppy.\n");
564 ioctl(moh->pseudofd, ZT_SET_BLOCKSIZE, &x);
569 if (ast_pthread_create(&moh->thread, NULL, monmp3thread, moh)) {
570 ast_log(LOG_WARNING, "Unable to create moh...\n");
571 if (moh->pseudofd > -1)
572 close(moh->pseudofd);
577 ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mode);
581 ast_mutex_lock(&moh_lock);
582 moh->next = mohclasses;
584 ast_mutex_unlock(&moh_lock);
588 int ast_moh_start(struct ast_channel *chan, char *class)
590 if (!class || ast_strlen_zero(class))
591 class = chan->musicclass;
592 if (!class || ast_strlen_zero(class))
594 return ast_activate_generator(chan, &mohgen, class);
597 void ast_moh_stop(struct ast_channel *chan)
599 ast_deactivate_generator(chan);
602 static void load_moh_classes(void)
604 struct ast_config *cfg;
605 struct ast_variable *var;
608 cfg = ast_load("musiconhold.conf");
610 var = ast_variable_browse(cfg, "classes");
612 data = strchr(var->value, ':');
616 args = strchr(data, ',');
621 moh_register(var->name, var->value, data,args);
629 static void ast_moh_destroy(void)
631 struct mohclass *moh;
633 int bytes, tbytes=0, stime = 0;
634 if (option_verbose > 1)
635 ast_verbose(VERBOSE_PREFIX_2 "Destroying any remaining musiconhold processes\n");
636 ast_mutex_lock(&moh_lock);
640 ast_log(LOG_DEBUG, "killing %d!\n", moh->pid);
642 kill(moh->pid, SIGKILL);
643 while ((bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime + 5) {
644 tbytes = tbytes + bytes;
646 ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", moh->pid, tbytes);
652 ast_mutex_unlock(&moh_lock);
655 int load_module(void)
659 res = ast_register_application(app0, moh0_exec, synopsis0, descrip0);
660 ast_register_atexit(ast_moh_destroy);
662 res = ast_register_application(app1, moh1_exec, synopsis1, descrip1);
664 res = ast_register_application(app2, moh2_exec, synopsis2, descrip2);
668 int unload_module(void)
673 char *description(void)
675 return "Music On Hold Resource";
680 /* Never allow Music On Hold to be unloaded
681 unresolve needed symbols in the dialer */
684 STANDARD_USECOUNT(res);
693 return ASTERISK_GPL_KEY;