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