Reduce volume of hold music to 8k / 4k
[asterisk/asterisk.git] / res / res_musiconhold.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Routines implementing call parking
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
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 <stdlib.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <signal.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <sys/time.h>
34 #include <sys/signal.h>
35 #include <netinet/in.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
38 #ifdef ZAPATA_MOH
39 #include <linux/zaptel.h>
40 #endif
41 #include <unistd.h>
42 #include <sys/ioctl.h>
43
44 #include <pthread.h>
45
46 static char *app0 = "MusicOnHold";
47 static char *app1 = "WaitMusicOnHold";
48 static char *app2 = "SetMusicOnHold";
49
50 static char *synopsis0 = "Play Music On Hold indefinitely";
51 static char *synopsis1 = "Wait, playing Music On Hold";
52 static char *synopsis2 = "Set default Music On Hold class";
53
54 static char *descrip0 = "MusicOnHold(class): "
55 "Plays hold music specified by class.  If omitted, the default\n"
56 "music source for the channel will be used. Set the default \n"
57 "class with the SetMusicOnHold() application.\n"
58 "Returns -1 on hangup.\n"
59 "Never returns otherwise.\n";
60
61 static char *descrip1 = "WaitMusicOnHold(delay): "
62 "Plays hold music specified number of seconds.  Returns 0 when\n"
63 "done, or -1 on hangup.  If no hold music is available, the delay will\n"
64 "still occur with no sound.\n";
65
66 static char *descrip2 = "SetMusicOnHold(class): "
67 "Sets the default class for music on hold for a given channel.  When\n"
68 "music on hold is activated, this class will be used to select which\n"
69 "music is played.\n";
70
71 struct mohclass {
72         char class[80];
73         char dir[256];
74         char miscargs[256];
75         int destroyme;
76         int pid;                /* PID of mpg123 */
77         int quiet;
78         pthread_t thread;
79         struct mohdata *members;
80         /* Source of audio */
81         int srcfd;
82         /* FD for timing source */
83         int pseudofd;
84         struct mohclass *next;
85 };
86
87 struct mohdata {
88         int pipe[2];
89         int origwfmt;
90         struct mohclass *parent;
91         struct mohdata *next;
92 };
93
94 static struct mohclass *mohclasses;
95
96 static ast_mutex_t moh_lock = AST_MUTEX_INITIALIZER;
97
98 #define LOCAL_MPG_123 "/usr/local/bin/mpg123"
99 #define MPG_123 "/usr/bin/mpg123"
100 #define MAX_MP3S 256
101
102 static int spawn_mp3(struct mohclass *class)
103 {
104         int fds[2];
105         int files;
106         char fns[MAX_MP3S][80];
107         char *argv[MAX_MP3S + 50];
108         char xargs[256];
109         char *argptr;
110         int argc;
111         DIR *dir;
112         struct dirent *de;
113         dir = opendir(class->dir);
114         if (!dir) {
115                 ast_log(LOG_WARNING, "%s is not a valid directory\n", class->dir);
116                 return -1;
117         }
118         argv[0] = "mpg123";
119         argv[1] = "-q";
120         argv[2] = "-s";
121         argv[3] = "--mono";
122         argv[4] = "-r";
123         argv[5] = "8000";
124         argv[6] = "-b";
125         argv[7] = "2048";
126         argv[8] = "-f";
127         argc = 9;
128         if (class->quiet) {
129                 argv[argc++] = "4096";
130         } else
131                 argv[argc++] = "8192";
132
133         /* Look for extra arguments and add them to the list */
134         strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
135         argptr = xargs;
136         while(argptr && strlen(argptr)) {
137                 argv[argc++] = argptr;
138                 argptr = strchr(argptr, ',');
139                 if (argptr) {
140                         *argptr = '\0';
141                         argptr++;
142                 }
143         }
144
145         files = 0;
146         while((de = readdir(dir)) && (files < MAX_MP3S)) {
147                 if ((strlen(de->d_name) > 3) && !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3")) {
148                         strncpy(fns[files], de->d_name, sizeof(fns[files]));
149                         argv[argc++] = fns[files];
150                         files++;
151                 }
152         }
153         argv[argc] = NULL;
154         closedir(dir);
155         if (pipe(fds)) {        
156                 ast_log(LOG_WARNING, "Pipe failed\n");
157                 return -1;
158         }
159 #if 0
160         printf("%d files total, %d args total\n", files, argc);
161         {
162                 int x;
163                 for (x=0;argv[x];x++)
164                         printf("arg%d: %s\n", x, argv[x]);
165         }
166 #endif  
167         if (!files) {
168                 ast_log(LOG_WARNING, "Found no files in '%s'\n", class->dir);
169                 close(fds[0]);
170                 close(fds[1]);
171                 return -1;
172         }
173         class->pid = fork();
174         if (class->pid < 0) {
175                 close(fds[0]);
176                 close(fds[1]);
177                 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
178                 return -1;
179         }
180         if (!class->pid) {
181                 int x;
182                 close(fds[0]);
183                 /* Stdout goes to pipe */
184                 dup2(fds[1], STDOUT_FILENO);
185                 /* Close unused file descriptors */
186                 for (x=3;x<8192;x++)
187                         close(x);
188                 /* Child */
189                 chdir(class->dir);
190                 /* Default install is /usr/local/bin */
191                 execv(LOCAL_MPG_123, argv);
192                 /* Many places have it in /usr/bin */
193                 execv(MPG_123, argv);
194                 /* Check PATH as a last-ditch effort */
195                 execvp("mpg123", argv);
196                 ast_log(LOG_WARNING, "Exec failed: %s\n", strerror(errno));
197                 close(fds[1]);
198                 exit(1);
199         } else {
200                 /* Parent */
201                 close(fds[1]);
202         }
203         return fds[0];
204 }
205
206 static void *monmp3thread(void *data)
207 {
208 #define MOH_MS_INTERVAL         100
209
210         struct mohclass *class = data;
211         struct mohdata *moh;
212         char buf[8192];
213         short sbuf[8192];
214         int res, res2;
215         struct timeval tv;
216         struct timeval tv_tmp;
217         long error_sec, error_usec;
218         long delay;
219
220         tv_tmp.tv_sec = 0;
221         tv_tmp.tv_usec = 0;
222         tv.tv_sec = 0;
223         tv.tv_usec = 0;
224         error_sec = 0;
225         error_usec = 0;
226         for(;/* ever */;) {
227                 /* Spawn mp3 player if it's not there */
228                 if (class->srcfd < 0)  {
229                         if ((class->srcfd = spawn_mp3(class)) < 0) {
230                                 ast_log(LOG_WARNING, "unable to spawn mp3player\n");
231                                 /* Try again later */
232                                 sleep(500);
233                         }
234                 }
235                 if (class->pseudofd > -1) {
236                         /* Pause some amount of time */
237                         res = read(class->pseudofd, buf, sizeof(buf));
238                 } else {
239                         /* Reliable sleep */
240                         if (gettimeofday(&tv_tmp, NULL) < 0) {
241                                 ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
242                                 return NULL;
243                         }
244                         if (((unsigned long)(tv.tv_sec) > 0)&&((unsigned long)(tv.tv_usec) > 0)) {
245                                 if ((unsigned long)(tv_tmp.tv_usec) < (unsigned long)(tv.tv_usec)) {
246                                         tv_tmp.tv_usec += 1000000;
247                                         tv_tmp.tv_sec -= 1;
248                                 }
249                                 error_sec = (unsigned long)(tv_tmp.tv_sec) - (unsigned long)(tv.tv_sec);
250                                 error_usec = (unsigned long)(tv_tmp.tv_usec) - (unsigned long)(tv.tv_usec);
251                         } else {
252                                 error_sec = 0;
253                                 error_usec = 0;
254                         }
255                         if (error_sec * 1000 + error_usec / 1000 < MOH_MS_INTERVAL) {
256                                 tv.tv_sec = tv_tmp.tv_sec + (MOH_MS_INTERVAL/1000 - error_sec);
257                                 tv.tv_usec = tv_tmp.tv_usec + ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec);
258                                 delay = (MOH_MS_INTERVAL/1000 - error_sec) * 1000 +
259                                                         ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec) / 1000;
260                         } else {
261                                 ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
262                                 tv.tv_sec = tv_tmp.tv_sec;
263                                 tv.tv_usec = tv_tmp.tv_usec;
264                                 delay = 0;
265                         }
266                         if (tv.tv_usec > 1000000) {
267                                 tv.tv_sec++;
268                                 tv.tv_usec-= 1000000;
269                         }
270                         if (delay > 0)
271                                 usleep(delay * 1000);
272                         res = 800;              /* 800 samples */
273                 }
274                 if (!class->members)
275                         continue;
276                 /* Read mp3 audio */
277                 if ((res2 = read(class->srcfd, sbuf, res * 2)) != res * 2) {
278                         if (!res2) {
279                                 close(class->srcfd);
280                                 class->srcfd = -1;
281                                 if (class->pid) {
282                                         kill(class->pid, SIGKILL);
283                                         class->pid = 0;
284                                 }
285                         } else
286                                 ast_log(LOG_DEBUG, "Read %d bytes of audio while expecting %d\n", res2, res * 2);
287                         continue;
288                 }
289                 ast_mutex_lock(&moh_lock);
290                 moh = class->members;
291                 while(moh) {
292                         /* Write data */
293                         if ((res = write(moh->pipe[1], sbuf, res2)) != res2) 
294                                 if (option_debug)
295                                     ast_log(LOG_DEBUG, "Only wrote %d of %d bytes to pipe\n", res, res2);
296                         moh = moh->next;
297                 }
298                 ast_mutex_unlock(&moh_lock);
299         }
300         return NULL;
301 }
302
303 static int moh0_exec(struct ast_channel *chan, void *data)
304 {
305         if (ast_moh_start(chan, data)) {
306                 ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
307                 return -1;
308         }
309         while(!ast_safe_sleep(chan, 10000));
310         return -1;
311 }
312
313 static int moh1_exec(struct ast_channel *chan, void *data)
314 {
315         int res;
316         if (!data || !atoi(data)) {
317                 ast_log(LOG_WARNING, "WaitMusicOnHold requires an argument (number of seconds to wait)\n");
318                 return -1;
319         }
320         if (ast_moh_start(chan, NULL)) {
321                 ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name);
322                 return -1;
323         }
324         res = ast_safe_sleep(chan, atoi(data) * 1000);
325         ast_moh_stop(chan);
326         return res;
327 }
328
329 static int moh2_exec(struct ast_channel *chan, void *data)
330 {
331         if (!data || !strlen(data)) {
332                 ast_log(LOG_WARNING, "SetMusicOnHold requires an argument (class)\n");
333                 return -1;
334         }
335         strncpy(chan->musicclass, data, sizeof(chan->musicclass));
336         return 0;
337 }
338
339 static struct mohclass *get_mohbyname(char *name)
340 {
341         struct mohclass *moh;
342         moh = mohclasses;
343         while(moh) {
344                 if (!strcasecmp(name, moh->class))
345                         return moh;
346                 moh = moh->next;
347         }
348         return NULL;
349 }
350
351 static struct mohdata *mohalloc(struct mohclass *cl)
352 {
353         struct mohdata *moh;
354         long flags;
355         moh = malloc(sizeof(struct mohdata));
356         if (!moh)
357                 return NULL;
358         memset(moh, 0, sizeof(struct mohdata));
359         if (pipe(moh->pipe)) {
360                 ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno));
361                 free(moh);
362                 return NULL;
363         }
364         /* Make entirely non-blocking */
365         flags = fcntl(moh->pipe[0], F_GETFL);
366         fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
367         flags = fcntl(moh->pipe[1], F_GETFL);
368         fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
369         moh->parent = cl;
370         moh->next = cl->members;
371         cl->members = moh;
372         return moh;
373 }
374
375 static void moh_release(struct ast_channel *chan, void *data)
376 {
377         struct mohdata *moh = data, *prev, *cur;
378         int oldwfmt;
379         ast_mutex_lock(&moh_lock);
380         /* Unlink */
381         prev = NULL;
382         cur = moh->parent->members;
383         while(cur) {
384                 if (cur == moh) {
385                         if (prev)
386                                 prev->next = cur->next;
387                         else
388                                 moh->parent->members = cur->next;
389                         break;
390                 }
391                 prev = cur;
392                 cur = cur->next;
393         }
394         ast_mutex_unlock(&moh_lock);
395         close(moh->pipe[0]);
396         close(moh->pipe[1]);
397         oldwfmt = moh->origwfmt;
398         free(moh);
399         if (chan) {
400                 if (oldwfmt && ast_set_write_format(chan, oldwfmt)) 
401                         ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(oldwfmt));
402                 if (option_verbose > 2)
403                         ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name);
404         }
405 }
406
407 static void *moh_alloc(struct ast_channel *chan, void *params)
408 {
409         struct mohdata *res;
410         struct mohclass *class;
411         ast_mutex_lock(&moh_lock);
412         class = get_mohbyname(params);
413         if (class)
414                 res = mohalloc(class);
415         else {
416                 if (strcasecmp(params, "default"))
417                         ast_log(LOG_WARNING, "No class: %s\n", (char *)params);
418                 res = NULL;
419         }
420         ast_mutex_unlock(&moh_lock);
421         if (res) {
422                 res->origwfmt = chan->writeformat;
423                 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
424                         ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format\n", chan->name);
425                         moh_release(NULL, res);
426                         res = NULL;
427                 }
428 #if 0
429                 /* Allow writes to interrupt */
430                 chan->writeinterrupt = 1;
431 #endif          
432                 if (option_verbose > 2)
433                         ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on %s\n", (char *)params, chan->name);
434         }
435         return res;
436 }
437
438 static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
439 {
440         struct ast_frame f;
441         struct mohdata *moh = data;
442         short buf[1280 + AST_FRIENDLY_OFFSET / 2];
443         int res;
444
445         len = samples * 2;
446         if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
447                 ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", sizeof(buf), len, chan->name);
448                 len = sizeof(buf) - AST_FRIENDLY_OFFSET;
449         }
450         res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
451 #if 0
452         if (res != len) {
453                 ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno));
454         }
455 #endif
456         if (res > 0) {
457                 memset(&f, 0, sizeof(f));
458                 f.frametype = AST_FRAME_VOICE;
459                 f.subclass = AST_FORMAT_SLINEAR;
460                 f.mallocd = 0;
461                 f.datalen = res;
462                 f.samples = res / 2;
463                 f.data = buf + AST_FRIENDLY_OFFSET / 2;
464                 f.offset = AST_FRIENDLY_OFFSET;
465                 if (ast_write(chan, &f)< 0) {
466                         ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
467                         return -1;
468                 }
469         }
470         return 0;
471 }
472
473 static struct ast_generator mohgen = 
474 {
475         alloc: moh_alloc,
476         release: moh_release,
477         generate: moh_generate,
478 };
479
480 static int moh_register(char *classname, char *mode, char *param, char *miscargs)
481 {
482         struct mohclass *moh;
483 #ifdef ZAPATA_MOH
484         int x;
485 #endif
486         ast_mutex_lock(&moh_lock);
487         moh = get_mohbyname(classname);
488         ast_mutex_unlock(&moh_lock);
489         if (moh) {
490                 ast_log(LOG_WARNING, "Music on Hold '%s' already exists\n", classname);
491                 return -1;
492         }
493         moh = malloc(sizeof(struct mohclass));
494         if (!moh)
495                 return -1;
496         memset(moh, 0, sizeof(struct mohclass));
497
498         strncpy(moh->class, classname, sizeof(moh->class) - 1);
499         if (miscargs)
500                 strncpy(moh->miscargs, miscargs, sizeof(moh->miscargs) - 1);
501         if (!strcasecmp(mode, "mp3") || !strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "httpmp3")) {
502                 if (!strcasecmp(mode, "quietmp3"))
503                         moh->quiet = 1;
504                 strncpy(moh->dir, param, sizeof(moh->dir) - 1);
505                 moh->srcfd = -1;
506 #ifdef ZAPATA_MOH
507                 /* It's an MP3 Moh -- Open /dev/zap/pseudo for timing...  Is
508                    there a better, yet reliable way to do this? */
509                 moh->pseudofd = open("/dev/zap/pseudo", O_RDONLY);
510                 if (moh->pseudofd < 0) {
511                         ast_log(LOG_WARNING, "Unable to open pseudo channel for timing...  Sound may be choppy.\n");
512                 } else {
513                         x = 320;
514                         ioctl(moh->pseudofd, ZT_SET_BLOCKSIZE, &x);
515                 }
516 #else
517                 moh->pseudofd = -1;
518 #endif
519                 if (pthread_create(&moh->thread, NULL, monmp3thread, moh)) {
520                         ast_log(LOG_WARNING, "Unable to create moh...\n");
521                         if (moh->pseudofd > -1)
522                                 close(moh->pseudofd);
523                         free(moh);
524                         return -1;
525                 }
526         } else {
527                 ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mode);
528                 free(moh);
529                 return -1;
530         }
531         ast_mutex_lock(&moh_lock);
532         moh->next = mohclasses;
533         mohclasses = moh;
534         ast_mutex_unlock(&moh_lock);
535         return 0;
536 }
537
538 int ast_moh_start(struct ast_channel *chan, char *class)
539 {
540         if (!class || !strlen(class))
541                 class = chan->musicclass;
542         if (!class || !strlen(class))
543                 class = "default";
544         return ast_activate_generator(chan, &mohgen, class);
545 }
546
547 void ast_moh_stop(struct ast_channel *chan)
548 {
549         ast_deactivate_generator(chan);
550 }
551
552 static void load_moh_classes(void)
553 {
554         struct ast_config *cfg;
555         struct ast_variable *var;
556         char *data;
557         char *args;
558         cfg = ast_load("musiconhold.conf");
559         if (cfg) {
560                 var = ast_variable_browse(cfg, "classes");
561                 while(var) {
562                         data = strchr(var->value, ':');
563                         if (data) {
564                                 *data = '\0';
565                                 data++;
566                                 args = strchr(data, ',');
567                                 if (args) {
568                                         *args = '\0';
569                                         args++;
570                                 }
571                                 moh_register(var->name, var->value, data,args);
572                         }
573                         var = var->next;
574                 }
575                 ast_destroy(cfg);
576         }
577 }
578
579 static void ast_moh_destroy(void)
580 {
581         struct mohclass *moh;
582         char buff[8192];
583         int bytes, tbytes=0, stime = 0;
584         if (option_verbose > 1)
585                 ast_verbose(VERBOSE_PREFIX_2 "Destroying any remaining musiconhold processes\n");
586         ast_mutex_lock(&moh_lock);
587         moh = mohclasses;
588         while(moh) {
589                 if (moh->pid) {
590                         ast_log(LOG_DEBUG, "killing %d!\n", moh->pid);
591                         stime = time(NULL);
592                         kill(moh->pid, SIGKILL);
593                         while ((bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime + 5) {
594                                 tbytes = tbytes + bytes;
595                         }
596                         ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", moh->pid, tbytes);
597                         close(moh->srcfd);
598                         moh->pid = 0;
599                         }
600                 moh = moh->next;
601         }
602         ast_mutex_unlock(&moh_lock);
603 }
604
605 int load_module(void)
606 {
607         int res;
608         load_moh_classes();
609         res = ast_register_application(app0, moh0_exec, synopsis0, descrip0);
610         ast_register_atexit(ast_moh_destroy);
611         if (!res)
612                 res = ast_register_application(app1, moh1_exec, synopsis1, descrip1);
613         if (!res)
614                 res = ast_register_application(app2, moh2_exec, synopsis2, descrip2);
615         return res;
616 }
617
618 int unload_module(void)
619 {
620         return -1;
621 }
622
623 char *description(void)
624 {
625         return "Music On Hold Resource";
626 }
627
628 int usecount(void)
629 {
630         /* Never allow Music On Hold to be unloaded
631            unresolve needed symbols in the dialer */
632 #if 0
633         int res;
634         STANDARD_USECOUNT(res);
635         return res;
636 #else
637         return 1;
638 #endif
639 }
640
641 char *key()
642 {
643         return ASTERISK_GPL_KEY;
644 }