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