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