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