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