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