bc3d2f34301683ece43e12f9b24bb407c88009bc
[asterisk/asterisk.git] / res / res_musiconhold.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2010, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Routines implementing music on hold
22  *
23  * \arg See also \ref Config_moh
24  * 
25  * \author Mark Spencer <markster@digium.com>
26  */
27
28 /*** MODULEINFO
29         <conflict>win32</conflict>
30         <support_level>core</support_level>
31  ***/
32
33 #include "asterisk.h"
34
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36
37 #include <ctype.h>
38 #include <signal.h>
39 #include <sys/time.h>
40 #include <sys/signal.h>
41 #include <netinet/in.h>
42 #include <sys/stat.h>
43 #include <dirent.h>
44
45 #ifdef SOLARIS
46 #include <thread.h>
47 #endif
48
49 #include "asterisk/lock.h"
50 #include "asterisk/file.h"
51 #include "asterisk/channel.h"
52 #include "asterisk/pbx.h"
53 #include "asterisk/app.h"
54 #include "asterisk/module.h"
55 #include "asterisk/translate.h"
56 #include "asterisk/say.h"
57 #include "asterisk/musiconhold.h"
58 #include "asterisk/config.h"
59 #include "asterisk/utils.h"
60 #include "asterisk/cli.h"
61 #include "asterisk/stringfields.h"
62 #include "asterisk/linkedlists.h"
63 #include "asterisk/manager.h"
64 #include "asterisk/paths.h"
65 #include "asterisk/astobj2.h"
66 #include "asterisk/timing.h"
67 #include "asterisk/time.h"
68 #include "asterisk/poll-compat.h"
69
70 #define INITIAL_NUM_FILES   8
71 #define HANDLE_REF      1
72 #define DONT_UNREF      0
73
74 /*** DOCUMENTATION
75         <application name="MusicOnHold" language="en_US">
76                 <synopsis>
77                         Play Music On Hold indefinitely.
78                 </synopsis>
79                 <syntax>
80                         <parameter name="class" required="true" />
81                         <parameter name="duration" />
82                 </syntax>
83                 <description>
84                         <para>Plays hold music specified by class. If omitted, the default music
85                         source for the channel will be used. Change the default class with
86                         Set(CHANNEL(musicclass)=...). If duration is given, hold music will be played
87                         specified number of seconds. If duration is ommited, music plays indefinitely.
88                         Returns <literal>0</literal> when done, <literal>-1</literal> on hangup.</para>
89                 </description>
90         </application>
91         <application name="WaitMusicOnHold" language="en_US">
92                 <synopsis>
93                         Wait, playing Music On Hold.
94                 </synopsis>
95                 <syntax>
96                         <parameter name="delay" required="true" />
97                 </syntax>
98                 <description>
99                         <para> !!! DEPRECATED. Use MusicOnHold instead !!!</para>
100                         <para>Plays hold music specified number of seconds. Returns <literal>0</literal> when done,
101                         or <literal>-1</literal> on hangup. If no hold music is available, the delay will still occur
102                         with no sound.</para>
103                         <para> !!! DEPRECATED. Use MusicOnHold instead !!!</para>
104                 </description>
105         </application>
106         <application name="SetMusicOnHold" language="en_US">
107                 <synopsis>
108                         Set default Music On Hold class.
109                 </synopsis>
110                 <syntax>
111                         <parameter name="class" required="yes" />
112                 </syntax>
113                 <description>
114                         <para>!!! DEPRECATED. USe Set(CHANNEL(musicclass)=...) instead !!!</para>
115                         <para>Sets the default class for music on hold for a given channel.
116                         When music on hold is activated, this class will be used to select which
117                         music is played.</para>
118                         <para>!!! DEPRECATED. USe Set(CHANNEL(musicclass)=...) instead !!!</para>
119                 </description>
120         </application>
121         <application name="StartMusicOnHold" language="en_US">
122                 <synopsis>
123                         Play Music On Hold.
124                 </synopsis>
125                 <syntax>
126                         <parameter name="class" required="true" />
127                 </syntax>
128                 <description>
129                         <para>Starts playing music on hold, uses default music class for channel.
130                         Starts playing music specified by class. If omitted, the default music
131                         source for the channel will be used. Always returns <literal>0</literal>.</para>
132                 </description>
133         </application>
134         <application name="StopMusicOnHold" language="en_US">
135                 <synopsis>
136                         Stop playing Music On Hold.
137                 </synopsis>
138                 <syntax />
139                 <description>
140                         <para>Stops playing music on hold.</para>
141                 </description>
142         </application>
143  ***/
144
145 static const char play_moh[] = "MusicOnHold";
146 static const char wait_moh[] = "WaitMusicOnHold";
147 static const char set_moh[] = "SetMusicOnHold";
148 static const char start_moh[] = "StartMusicOnHold";
149 static const char stop_moh[] = "StopMusicOnHold";
150
151 static int respawn_time = 20;
152
153 struct moh_files_state {
154         /*! Holds a reference to the MOH class. */
155         struct mohclass *class;
156         char name[MAX_MUSICCLASS];
157         struct ast_format origwfmt;
158         struct ast_format mohwfmt;
159         int samples;
160         int sample_queue;
161         int pos;
162         int save_pos;
163         int save_total;
164         char *save_pos_filename;
165 };
166
167 #define MOH_QUIET               (1 << 0)
168 #define MOH_SINGLE              (1 << 1)
169 #define MOH_CUSTOM              (1 << 2)
170 #define MOH_RANDOMIZE           (1 << 3)
171 #define MOH_SORTALPHA           (1 << 4)
172
173 #define MOH_CACHERTCLASSES      (1 << 5)        /*!< Should we use a separate instance of MOH for each user or not */
174
175 /* Custom astobj2 flag */
176 #define MOH_NOTDELETED          (1 << 30)       /*!< Find only records that aren't deleted? */
177
178 static struct ast_flags global_flags[1] = {{0}};        /*!< global MOH_ flags */
179
180 struct mohclass {
181         char name[MAX_MUSICCLASS];
182         char dir[256];
183         char args[256];
184         char mode[80];
185         char digit;
186         /*! A dynamically sized array to hold the list of filenames in "files" mode */
187         char **filearray;
188         /*! The current size of the filearray */
189         int allowed_files;
190         /*! The current number of files loaded into the filearray */
191         int total_files;
192         unsigned int flags;
193         /*! The format from the MOH source, not applicable to "files" mode */
194         struct ast_format format;
195         /*! The pid of the external application delivering MOH */
196         int pid;
197         time_t start;
198         pthread_t thread;
199         /*! Source of audio */
200         int srcfd;
201         /*! Generic timer */
202         struct ast_timer *timer;
203         /*! Created on the fly, from RT engine */
204         unsigned int realtime:1;
205         unsigned int delete:1;
206         AST_LIST_HEAD_NOLOCK(, mohdata) members;
207         AST_LIST_ENTRY(mohclass) list;
208 };
209
210 struct mohdata {
211         int pipe[2];
212         struct ast_format origwfmt;
213         struct mohclass *parent;
214         struct ast_frame f;
215         AST_LIST_ENTRY(mohdata) list;
216 };
217
218 static struct ao2_container *mohclasses;
219
220 #define LOCAL_MPG_123 "/usr/local/bin/mpg123"
221 #define MPG_123 "/usr/bin/mpg123"
222 #define MAX_MP3S 256
223
224 static int reload(void);
225
226 #define mohclass_ref(class,string)   (ao2_t_ref((class), +1, (string)), class)
227
228 #ifndef REF_DEBUG
229 #define mohclass_unref(class,string) (ao2_t_ref((class), -1, (string)), (struct mohclass *) NULL)
230 #else
231 #define mohclass_unref(class,string) _mohclass_unref(class, string, __FILE__,__LINE__,__PRETTY_FUNCTION__)
232 static struct mohclass *_mohclass_unref(struct mohclass *class, const char *tag, const char *file, int line, const char *funcname)
233 {
234         struct mohclass *dup;
235         if ((dup = ao2_find(mohclasses, class, OBJ_POINTER))) {
236                 if (__ao2_ref_debug(dup, -1, (char *) tag, (char *) file, line, funcname) == 2) {
237                         FILE *ref = fopen("/tmp/refs", "a");
238                         if (ref) {
239                                 fprintf(ref, "%p =1   %s:%d:%s (%s) BAD ATTEMPT!\n", class, file, line, funcname, tag);
240                                 fclose(ref);
241                         }
242                         ast_log(LOG_WARNING, "Attempt to unref mohclass %p (%s) when only 1 ref remained, and class is still in a container! (at %s:%d (%s))\n",
243                                 class, class->name, file, line, funcname);
244                 } else {
245                         ao2_ref(class, -1);
246                 }
247         } else {
248                 ao2_t_ref(class, -1, (char *) tag);
249         }
250         return NULL;
251 }
252 #endif
253
254 static void moh_files_release(struct ast_channel *chan, void *data)
255 {
256         struct moh_files_state *state;
257
258         if (!chan || !chan->music_state) {
259                 return;
260         }
261
262         state = chan->music_state;
263
264         if (chan->stream) {
265                 ast_closestream(chan->stream);
266                 chan->stream = NULL;
267         }
268         
269         if (option_verbose > 2) {
270                 ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name);
271         }
272
273         ast_format_clear(&state->mohwfmt); /* make sure to clear this format before restoring the original format. */
274         if (state->origwfmt.id && ast_set_write_format(chan, &state->origwfmt)) {
275                 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n", chan->name, ast_getformatname(&state->origwfmt));
276         }
277
278         state->save_pos = state->pos;
279
280         state->class = mohclass_unref(state->class, "Unreffing channel's music class upon deactivation of generator");
281 }
282
283 static int ast_moh_files_next(struct ast_channel *chan) 
284 {
285         struct moh_files_state *state = chan->music_state;
286         int tries;
287
288         /* Discontinue a stream if it is running already */
289         if (chan->stream) {
290                 ast_closestream(chan->stream);
291                 chan->stream = NULL;
292         }
293
294         if (!state->class->total_files) {
295                 ast_log(LOG_WARNING, "No files available for class '%s'\n", state->class->name);
296                 return -1;
297         }
298
299         if (state->pos == 0 && state->save_pos_filename == NULL) {
300                 /* First time so lets play the file. */
301                 state->save_pos = -1;
302         } else if (state->save_pos >= 0 && state->save_pos < state->class->total_files && state->class->filearray[state->save_pos] == state->save_pos_filename) {
303                 /* If a specific file has been saved confirm it still exists and that it is still valid */
304                 state->pos = state->save_pos;
305                 state->save_pos = -1;
306         } else if (ast_test_flag(state->class, MOH_RANDOMIZE)) {
307                 /* Get a random file and ensure we can open it */
308                 for (tries = 0; tries < 20; tries++) {
309                         state->pos = ast_random() % state->class->total_files;
310                         if (ast_fileexists(state->class->filearray[state->pos], NULL, NULL) > 0) {
311                                 break;
312                         }
313                 }
314                 state->save_pos = -1;
315                 state->samples = 0;
316         } else {
317                 /* This is easy, just increment our position and make sure we don't exceed the total file count */
318                 state->pos++;
319                 state->pos %= state->class->total_files;
320                 state->save_pos = -1;
321                 state->samples = 0;
322         }
323
324         for (tries = 0; tries < state->class->total_files; ++tries) {
325                 if (ast_openstream_full(chan, state->class->filearray[state->pos], chan->language, 1)) {
326                         break;
327                 }
328
329                 ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", state->class->filearray[state->pos], strerror(errno));
330                 state->pos++;
331                 state->pos %= state->class->total_files;
332         }
333
334         if (tries == state->class->total_files) {
335                 return -1;
336         }
337
338         /* Record the pointer to the filename for position resuming later */
339         state->save_pos_filename = state->class->filearray[state->pos];
340
341         ast_debug(1, "%s Opened file %d '%s'\n", chan->name, state->pos, state->class->filearray[state->pos]);
342
343         if (state->samples) {
344                 size_t loc;
345                 /* seek *SHOULD* be good since it's from a known location */
346                 ast_seekstream(chan->stream, state->samples, SEEK_SET);
347                 /* if the seek failed then recover because if there is not a valid read,
348                  * moh_files_generate will return -1 and MOH will stop */
349                 loc = ast_tellstream(chan->stream);
350                 if (state->samples > loc && loc) {
351                         /* seek one sample from the end for one guaranteed valid read */
352                         ast_seekstream(chan->stream, 1, SEEK_END);
353                 }
354         }
355
356         return 0;
357 }
358
359 static struct ast_frame *moh_files_readframe(struct ast_channel *chan)
360 {
361         struct ast_frame *f = NULL;
362
363         if (!(chan->stream && (f = ast_readframe(chan->stream)))) {
364                 if (!ast_moh_files_next(chan))
365                         f = ast_readframe(chan->stream);
366         }
367
368         return f;
369 }
370
371 static void moh_files_write_format_change(struct ast_channel *chan, void *data)
372 {
373         struct moh_files_state *state = chan->music_state;
374
375         /* In order to prevent a recursive call to this function as a result
376          * of setting the moh write format back on the channel. Clear
377          * the moh write format before setting the write format on the channel.*/
378         if (&state->origwfmt.id) {
379                 struct ast_format tmp;
380
381                 ast_format_copy(&tmp, &chan->writeformat);
382                 if (state->mohwfmt.id) {
383                         ast_format_clear(&state->origwfmt);
384                         ast_set_write_format(chan, &state->mohwfmt);
385                 }
386                 ast_format_copy(&state->origwfmt, &tmp);
387         }
388 }
389
390 static int moh_files_generator(struct ast_channel *chan, void *data, int len, int samples)
391 {
392         struct moh_files_state *state = chan->music_state;
393         struct ast_frame *f = NULL;
394         int res = 0;
395
396         state->sample_queue += samples;
397
398         while (state->sample_queue > 0) {
399                 ast_channel_lock(chan);
400                 if ((f = moh_files_readframe(chan))) {
401                         /* We need to be sure that we unlock
402                          * the channel prior to calling
403                          * ast_write. Otherwise, the recursive locking
404                          * that occurs can cause deadlocks when using
405                          * indirect channels, like local channels
406                          */
407                         ast_channel_unlock(chan);
408                         state->samples += f->samples;
409                         state->sample_queue -= f->samples;
410                         if (ast_format_cmp(&f->subclass.format, &state->mohwfmt) == AST_FORMAT_CMP_NOT_EQUAL) {
411                                 ast_format_copy(&state->mohwfmt, &f->subclass.format);
412                         }
413                         res = ast_write(chan, f);
414                         ast_frfree(f);
415                         if (res < 0) {
416                                 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
417                                 return -1;
418                         }
419                 } else {
420                         ast_channel_unlock(chan);
421                         return -1;      
422                 }
423         }
424         return res;
425 }
426
427 static void *moh_files_alloc(struct ast_channel *chan, void *params)
428 {
429         struct moh_files_state *state;
430         struct mohclass *class = params;
431
432         if (!chan->music_state && (state = ast_calloc(1, sizeof(*state)))) {
433                 chan->music_state = state;
434                 ast_module_ref(ast_module_info->self);
435         } else {
436                 state = chan->music_state;
437                 if (!state) {
438                         return NULL;
439                 }
440                 if (state->class) {
441                         mohclass_unref(state->class, "Uh Oh. Restarting MOH with an active class");
442                         ast_log(LOG_WARNING, "Uh Oh. Restarting MOH with an active class\n");
443                 }
444         }
445
446         /* LOGIC: Comparing an unrefcounted pointer is a really bad idea, because
447          * malloc may allocate a different class to the same memory block.  This
448          * might only happen when two reloads are generated in a short period of
449          * time, but it's still important to protect against.
450          * PROG: Compare the quick operation first, to save CPU. */
451         if (state->save_total != class->total_files || strcmp(state->name, class->name) != 0) {
452                 memset(state, 0, sizeof(*state));
453                 if (ast_test_flag(class, MOH_RANDOMIZE) && class->total_files) {
454                         state->pos = ast_random() % class->total_files;
455                 }
456         }
457
458         state->class = mohclass_ref(class, "Reffing music class for channel");
459         ast_format_copy(&state->origwfmt, &chan->writeformat);
460         ast_format_copy(&state->mohwfmt, &chan->writeformat);
461
462         /* For comparison on restart of MOH (see above) */
463         ast_copy_string(state->name, class->name, sizeof(state->name));
464         state->save_total = class->total_files;
465
466         ast_verb(3, "Started music on hold, class '%s', on %s\n", class->name, chan->name);
467         
468         return chan->music_state;
469 }
470
471 static int moh_digit_match(void *obj, void *arg, int flags)
472 {
473         char *digit = arg;
474         struct mohclass *class = obj;
475
476         return (*digit == class->digit) ? CMP_MATCH | CMP_STOP : 0;
477 }
478
479 /*! \note This function should be called with the mohclasses list locked */
480 static struct mohclass *get_mohbydigit(char digit)
481 {
482         return ao2_t_callback(mohclasses, 0, moh_digit_match, &digit, "digit callback");
483 }
484
485 static void moh_handle_digit(struct ast_channel *chan, char digit)
486 {
487         struct mohclass *class;
488         const char *classname = NULL;
489
490         if ((class = get_mohbydigit(digit))) {
491                 classname = ast_strdupa(class->name);
492                 class = mohclass_unref(class, "Unreffing ao2_find from finding by digit");
493                 ast_string_field_set(chan,musicclass,classname);
494                 ast_moh_stop(chan);
495                 ast_moh_start(chan, classname, NULL);
496         }
497 }
498
499 static struct ast_generator moh_file_stream = 
500 {
501         .alloc    = moh_files_alloc,
502         .release  = moh_files_release,
503         .generate = moh_files_generator,
504         .digit    = moh_handle_digit,
505         .write_format_change = moh_files_write_format_change,
506 };
507
508 static int spawn_mp3(struct mohclass *class)
509 {
510         int fds[2];
511         int files = 0;
512         char fns[MAX_MP3S][80];
513         char *argv[MAX_MP3S + 50];
514         char xargs[256];
515         char *argptr;
516         int argc = 0;
517         DIR *dir = NULL;
518         struct dirent *de;
519
520         
521         if (!strcasecmp(class->dir, "nodir")) {
522                 files = 1;
523         } else {
524                 dir = opendir(class->dir);
525                 if (!dir && strncasecmp(class->dir, "http://", 7)) {
526                         ast_log(LOG_WARNING, "%s is not a valid directory\n", class->dir);
527                         return -1;
528                 }
529         }
530
531         if (!ast_test_flag(class, MOH_CUSTOM)) {
532                 argv[argc++] = "mpg123";
533                 argv[argc++] = "-q";
534                 argv[argc++] = "-s";
535                 argv[argc++] = "--mono";
536                 argv[argc++] = "-r";
537                 argv[argc++] = "8000";
538                 
539                 if (!ast_test_flag(class, MOH_SINGLE)) {
540                         argv[argc++] = "-b";
541                         argv[argc++] = "2048";
542                 }
543                 
544                 argv[argc++] = "-f";
545                 
546                 if (ast_test_flag(class, MOH_QUIET))
547                         argv[argc++] = "4096";
548                 else
549                         argv[argc++] = "8192";
550                 
551                 /* Look for extra arguments and add them to the list */
552                 ast_copy_string(xargs, class->args, sizeof(xargs));
553                 argptr = xargs;
554                 while (!ast_strlen_zero(argptr)) {
555                         argv[argc++] = argptr;
556                         strsep(&argptr, ",");
557                 }
558         } else  {
559                 /* Format arguments for argv vector */
560                 ast_copy_string(xargs, class->args, sizeof(xargs));
561                 argptr = xargs;
562                 while (!ast_strlen_zero(argptr)) {
563                         argv[argc++] = argptr;
564                         strsep(&argptr, " ");
565                 }
566         }
567
568         if (!strncasecmp(class->dir, "http://", 7)) {
569                 ast_copy_string(fns[files], class->dir, sizeof(fns[files]));
570                 argv[argc++] = fns[files];
571                 files++;
572         } else if (dir) {
573                 while ((de = readdir(dir)) && (files < MAX_MP3S)) {
574                         if ((strlen(de->d_name) > 3) && 
575                             ((ast_test_flag(class, MOH_CUSTOM) && 
576                               (!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".raw") || 
577                                !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".sln"))) ||
578                              !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3"))) {
579                                 ast_copy_string(fns[files], de->d_name, sizeof(fns[files]));
580                                 argv[argc++] = fns[files];
581                                 files++;
582                         }
583                 }
584         }
585         argv[argc] = NULL;
586         if (dir) {
587                 closedir(dir);
588         }
589         if (pipe(fds)) {        
590                 ast_log(LOG_WARNING, "Pipe failed\n");
591                 return -1;
592         }
593         if (!files) {
594                 ast_log(LOG_WARNING, "Found no files in '%s'\n", class->dir);
595                 close(fds[0]);
596                 close(fds[1]);
597                 return -1;
598         }
599         if (!strncasecmp(class->dir, "http://", 7) && time(NULL) - class->start < respawn_time) {
600                 sleep(respawn_time - (time(NULL) - class->start));
601         }
602
603         time(&class->start);
604         class->pid = ast_safe_fork(0);
605         if (class->pid < 0) {
606                 close(fds[0]);
607                 close(fds[1]);
608                 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
609                 return -1;
610         }
611         if (!class->pid) {
612                 if (ast_opt_high_priority)
613                         ast_set_priority(0);
614
615                 close(fds[0]);
616                 /* Stdout goes to pipe */
617                 dup2(fds[1], STDOUT_FILENO);
618
619                 /* Close everything else */
620                 ast_close_fds_above_n(STDERR_FILENO);
621
622                 /* Child */
623                 if (strncasecmp(class->dir, "http://", 7) && strcasecmp(class->dir, "nodir") && chdir(class->dir) < 0) {
624                         ast_log(LOG_WARNING, "chdir() failed: %s\n", strerror(errno));
625                         _exit(1);
626                 }
627                 setpgid(0, getpid());
628                 if (ast_test_flag(class, MOH_CUSTOM)) {
629                         execv(argv[0], argv);
630                 } else {
631                         /* Default install is /usr/local/bin */
632                         execv(LOCAL_MPG_123, argv);
633                         /* Many places have it in /usr/bin */
634                         execv(MPG_123, argv);
635                         /* Check PATH as a last-ditch effort */
636                         execvp("mpg123", argv);
637                 }
638                 /* Can't use logger, since log FDs are closed */
639                 fprintf(stderr, "MOH: exec failed: %s\n", strerror(errno));
640                 close(fds[1]);
641                 _exit(1);
642         } else {
643                 /* Parent */
644                 close(fds[1]);
645         }
646         return fds[0];
647 }
648
649 static void *monmp3thread(void *data)
650 {
651 #define MOH_MS_INTERVAL         100
652
653         struct mohclass *class = data;
654         struct mohdata *moh;
655         short sbuf[8192];
656         int res = 0, res2;
657         int len;
658         struct timeval deadline, tv_tmp;
659
660         deadline.tv_sec = 0;
661         deadline.tv_usec = 0;
662         for(;/* ever */;) {
663                 pthread_testcancel();
664                 /* Spawn mp3 player if it's not there */
665                 if (class->srcfd < 0) {
666                         if ((class->srcfd = spawn_mp3(class)) < 0) {
667                                 ast_log(LOG_WARNING, "Unable to spawn mp3player\n");
668                                 /* Try again later */
669                                 sleep(500);
670                                 pthread_testcancel();
671                         }
672                 }
673                 if (class->timer) {
674                         struct pollfd pfd = { .fd = ast_timer_fd(class->timer), .events = POLLIN, };
675
676 #ifdef SOLARIS
677                         thr_yield();
678 #endif
679                         /* Pause some amount of time */
680                         if (ast_poll(&pfd, 1, -1) > 0) {
681                                 ast_timer_ack(class->timer, 1);
682                                 res = 320;
683                         } else {
684                                 ast_log(LOG_ERROR, "poll() failed: %s\n", strerror(errno));
685                                 res = 0;
686                         }
687                         pthread_testcancel();
688                 } else {
689                         long delta;
690                         /* Reliable sleep */
691                         tv_tmp = ast_tvnow();
692                         if (ast_tvzero(deadline))
693                                 deadline = tv_tmp;
694                         delta = ast_tvdiff_ms(tv_tmp, deadline);
695                         if (delta < MOH_MS_INTERVAL) {  /* too early */
696                                 deadline = ast_tvadd(deadline, ast_samp2tv(MOH_MS_INTERVAL, 1000));     /* next deadline */
697                                 usleep(1000 * (MOH_MS_INTERVAL - delta));
698                                 pthread_testcancel();
699                         } else {
700                                 ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
701                                 deadline = tv_tmp;
702                         }
703                         res = 8 * MOH_MS_INTERVAL;      /* 8 samples per millisecond */
704                 }
705                 if ((strncasecmp(class->dir, "http://", 7) && strcasecmp(class->dir, "nodir")) && AST_LIST_EMPTY(&class->members))
706                         continue;
707                 /* Read mp3 audio */
708                 len = ast_codec_get_len(&class->format, res);
709
710                 if ((res2 = read(class->srcfd, sbuf, len)) != len) {
711                         if (!res2) {
712                                 close(class->srcfd);
713                                 class->srcfd = -1;
714                                 pthread_testcancel();
715                                 if (class->pid > 1) {
716                                         do {
717                                                 if (killpg(class->pid, SIGHUP) < 0) {
718                                                         if (errno == ESRCH) {
719                                                                 break;
720                                                         }
721                                                         ast_log(LOG_WARNING, "Unable to send a SIGHUP to MOH process?!!: %s\n", strerror(errno));
722                                                 }
723                                                 usleep(100000);
724                                                 if (killpg(class->pid, SIGTERM) < 0) {
725                                                         if (errno == ESRCH) {
726                                                                 break;
727                                                         }
728                                                         ast_log(LOG_WARNING, "Unable to terminate MOH process?!!: %s\n", strerror(errno));
729                                                 }
730                                                 usleep(100000);
731                                                 if (killpg(class->pid, SIGKILL) < 0) {
732                                                         if (errno == ESRCH) {
733                                                                 break;
734                                                         }
735                                                         ast_log(LOG_WARNING, "Unable to kill MOH process?!!: %s\n", strerror(errno));
736                                                 }
737                                         } while (0);
738                                         class->pid = 0;
739                                 }
740                         } else {
741                                 ast_debug(1, "Read %d bytes of audio while expecting %d\n", res2, len);
742                         }
743                         continue;
744                 }
745
746                 pthread_testcancel();
747
748                 ao2_lock(class);
749                 AST_LIST_TRAVERSE(&class->members, moh, list) {
750                         /* Write data */
751                         if ((res = write(moh->pipe[1], sbuf, res2)) != res2) {
752                                 ast_debug(1, "Only wrote %d of %d bytes to pipe\n", res, res2);
753                         }
754                 }
755                 ao2_unlock(class);
756         }
757         return NULL;
758 }
759
760 static int play_moh_exec(struct ast_channel *chan, const char *data)
761 {
762         char *parse;
763         char *class;
764         int timeout = -1;
765         int res;
766         AST_DECLARE_APP_ARGS(args,
767                 AST_APP_ARG(class);
768                 AST_APP_ARG(duration);
769         );
770
771         parse = ast_strdupa(data);
772
773         AST_STANDARD_APP_ARGS(args, parse);
774
775         if (!ast_strlen_zero(args.duration)) {
776                 if (sscanf(args.duration, "%30d", &timeout) == 1) {
777                         timeout *= 1000;
778                 } else {
779                         ast_log(LOG_WARNING, "Invalid MusicOnHold duration '%s'. Will wait indefinitely.\n", args.duration);
780                 }
781         }
782
783         class = S_OR(args.class, NULL);
784         if (ast_moh_start(chan, class, NULL)) {
785                 ast_log(LOG_WARNING, "Unable to start music on hold class '%s' on channel %s\n", class, chan->name);
786                 return 0;
787         }
788
789         if (timeout > 0)
790                 res = ast_safe_sleep(chan, timeout);
791         else {
792                 while (!(res = ast_safe_sleep(chan, 10000)));
793         }
794
795         ast_moh_stop(chan);
796
797         return res;
798 }
799
800 static int wait_moh_exec(struct ast_channel *chan, const char *data)
801 {
802         static int deprecation_warning = 0;
803         int res;
804
805         if (!deprecation_warning) {
806                 deprecation_warning = 1;
807                 ast_log(LOG_WARNING, "WaitMusicOnHold application is deprecated and will be removed. Use MusicOnHold with duration parameter instead\n");
808         }
809
810         if (!data || !atoi(data)) {
811                 ast_log(LOG_WARNING, "WaitMusicOnHold requires an argument (number of seconds to wait)\n");
812                 return -1;
813         }
814         if (ast_moh_start(chan, NULL, NULL)) {
815                 ast_log(LOG_WARNING, "Unable to start music on hold for %d seconds on channel %s\n", atoi(data), chan->name);
816                 return 0;
817         }
818         res = ast_safe_sleep(chan, atoi(data) * 1000);
819         ast_moh_stop(chan);
820         return res;
821 }
822
823 static int set_moh_exec(struct ast_channel *chan, const char *data)
824 {
825         static int deprecation_warning = 0;
826
827         if (!deprecation_warning) {
828                 deprecation_warning = 1;
829                 ast_log(LOG_WARNING, "SetMusicOnHold application is deprecated and will be removed. Use Set(CHANNEL(musicclass)=...) instead\n");
830         }
831
832         if (ast_strlen_zero(data)) {
833                 ast_log(LOG_WARNING, "SetMusicOnHold requires an argument (class)\n");
834                 return -1;
835         }
836         ast_string_field_set(chan, musicclass, data);
837         return 0;
838 }
839
840 static int start_moh_exec(struct ast_channel *chan, const char *data)
841 {
842         char *parse;
843         char *class;
844         AST_DECLARE_APP_ARGS(args,
845                 AST_APP_ARG(class);
846         );
847
848         parse = ast_strdupa(data);
849
850         AST_STANDARD_APP_ARGS(args, parse);
851
852         class = S_OR(args.class, NULL);
853         if (ast_moh_start(chan, class, NULL)) 
854                 ast_log(LOG_WARNING, "Unable to start music on hold class '%s' on channel %s\n", class, chan->name);
855
856         return 0;
857 }
858
859 static int stop_moh_exec(struct ast_channel *chan, const char *data)
860 {
861         ast_moh_stop(chan);
862
863         return 0;
864 }
865
866 #define get_mohbyname(a,b,c)    _get_mohbyname(a,b,c,__FILE__,__LINE__,__PRETTY_FUNCTION__)
867
868 static struct mohclass *_get_mohbyname(const char *name, int warn, int flags, const char *file, int lineno, const char *funcname)
869 {
870         struct mohclass *moh = NULL;
871         struct mohclass tmp_class = {
872                 .flags = 0,
873         };
874
875         ast_copy_string(tmp_class.name, name, sizeof(tmp_class.name));
876
877 #ifdef REF_DEBUG
878         moh = __ao2_find_debug(mohclasses, &tmp_class, flags, "get_mohbyname", (char *) file, lineno, funcname);
879 #else
880         moh = __ao2_find(mohclasses, &tmp_class, flags);
881 #endif
882
883         if (!moh && warn) {
884                 ast_debug(1, "Music on Hold class '%s' not found in memory\n", name);
885         }
886
887         return moh;
888 }
889
890 static struct mohdata *mohalloc(struct mohclass *cl)
891 {
892         struct mohdata *moh;
893         long flags;
894
895         if (!(moh = ast_calloc(1, sizeof(*moh))))
896                 return NULL;
897
898         if (pipe(moh->pipe)) {
899                 ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno));
900                 ast_free(moh);
901                 return NULL;
902         }
903
904         /* Make entirely non-blocking */
905         flags = fcntl(moh->pipe[0], F_GETFL);
906         fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
907         flags = fcntl(moh->pipe[1], F_GETFL);
908         fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
909
910         moh->f.frametype = AST_FRAME_VOICE;
911         ast_format_copy(&moh->f.subclass.format, &cl->format);
912         moh->f.offset = AST_FRIENDLY_OFFSET;
913
914         moh->parent = mohclass_ref(cl, "Reffing music class for mohdata parent");
915
916         ao2_lock(cl);
917         AST_LIST_INSERT_HEAD(&cl->members, moh, list);
918         ao2_unlock(cl);
919         
920         return moh;
921 }
922
923 static void moh_release(struct ast_channel *chan, void *data)
924 {
925         struct mohdata *moh = data;
926         struct mohclass *class = moh->parent;
927         struct ast_format oldwfmt;
928
929         ao2_lock(class);
930         AST_LIST_REMOVE(&moh->parent->members, moh, list);      
931         ao2_unlock(class);
932         
933         close(moh->pipe[0]);
934         close(moh->pipe[1]);
935
936         ast_format_copy(&oldwfmt, &moh->origwfmt);
937
938         moh->parent = class = mohclass_unref(class, "unreffing moh->parent upon deactivation of generator");
939
940         ast_free(moh);
941
942         if (chan) {
943                 struct moh_files_state *state;
944
945                 state = chan->music_state;
946                 if (state && state->class) {
947                         state->class = mohclass_unref(state->class, "Unreffing channel's music class upon deactivation of generator");
948                 }
949                 if (oldwfmt.id && ast_set_write_format(chan, &oldwfmt)) {
950                         ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n",
951                                         chan->name, ast_getformatname(&oldwfmt));
952                 }
953
954                 ast_verb(3, "Stopped music on hold on %s\n", chan->name);
955         }
956 }
957
958 static void *moh_alloc(struct ast_channel *chan, void *params)
959 {
960         struct mohdata *res;
961         struct mohclass *class = params;
962         struct moh_files_state *state;
963
964         /* Initiating music_state for current channel. Channel should know name of moh class */
965         if (!chan->music_state && (state = ast_calloc(1, sizeof(*state)))) {
966                 chan->music_state = state;
967                 ast_module_ref(ast_module_info->self);
968         } else {
969                 state = chan->music_state;
970                 if (!state) {
971                         return NULL;
972                 }
973                 if (state->class) {
974                         mohclass_unref(state->class, "Uh Oh. Restarting MOH with an active class");
975                         ast_log(LOG_WARNING, "Uh Oh. Restarting MOH with an active class\n");
976                 }
977                 memset(state, 0, sizeof(*state));
978         }
979
980         if ((res = mohalloc(class))) {
981                 ast_format_copy(&res->origwfmt, &chan->writeformat);
982                 if (ast_set_write_format(chan, &class->format)) {
983                         ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", chan->name, ast_codec2str(&class->format));
984                         moh_release(NULL, res);
985                         res = NULL;
986                 } else {
987                         state->class = mohclass_ref(class, "Placing reference into state container");
988                 }
989                 ast_verb(3, "Started music on hold, class '%s', on channel '%s'\n", class->name, chan->name);
990         }
991         return res;
992 }
993
994 static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
995 {
996         struct mohdata *moh = data;
997         short buf[1280 + AST_FRIENDLY_OFFSET / 2];
998         int res;
999
1000         len = ast_codec_get_len(&moh->parent->format, samples);
1001
1002         if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
1003                 ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), len, chan->name);
1004                 len = sizeof(buf) - AST_FRIENDLY_OFFSET;
1005         }
1006         res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
1007         if (res <= 0)
1008                 return 0;
1009
1010         moh->f.datalen = res;
1011         moh->f.data.ptr = buf + AST_FRIENDLY_OFFSET / 2;
1012         moh->f.samples = ast_codec_get_samples(&moh->f);
1013
1014         if (ast_write(chan, &moh->f) < 0) {
1015                 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
1016                 return -1;
1017         }
1018
1019         return 0;
1020 }
1021
1022 static struct ast_generator mohgen = {
1023         .alloc    = moh_alloc,
1024         .release  = moh_release,
1025         .generate = moh_generate,
1026         .digit    = moh_handle_digit,
1027 };
1028
1029 static int moh_add_file(struct mohclass *class, const char *filepath)
1030 {
1031         if (!class->allowed_files) {
1032                 if (!(class->filearray = ast_calloc(1, INITIAL_NUM_FILES * sizeof(*class->filearray))))
1033                         return -1;
1034                 class->allowed_files = INITIAL_NUM_FILES;
1035         } else if (class->total_files == class->allowed_files) {
1036                 if (!(class->filearray = ast_realloc(class->filearray, class->allowed_files * sizeof(*class->filearray) * 2))) {
1037                         class->allowed_files = 0;
1038                         class->total_files = 0;
1039                         return -1;
1040                 }
1041                 class->allowed_files *= 2;
1042         }
1043
1044         if (!(class->filearray[class->total_files] = ast_strdup(filepath)))
1045                 return -1;
1046
1047         class->total_files++;
1048
1049         return 0;
1050 }
1051
1052 static int moh_sort_compare(const void *i1, const void *i2)
1053 {
1054         char *s1, *s2;
1055
1056         s1 = ((char **)i1)[0];
1057         s2 = ((char **)i2)[0];
1058
1059         return strcasecmp(s1, s2);
1060 }
1061
1062 static int moh_scan_files(struct mohclass *class) {
1063
1064         DIR *files_DIR;
1065         struct dirent *files_dirent;
1066         char dir_path[PATH_MAX];
1067         char path[PATH_MAX];
1068         char filepath[PATH_MAX];
1069         char *ext;
1070         struct stat statbuf;
1071         int i;
1072
1073         if (class->dir[0] != '/') {
1074                 ast_copy_string(dir_path, ast_config_AST_DATA_DIR, sizeof(dir_path));
1075                 strncat(dir_path, "/", sizeof(dir_path) - 1);
1076                 strncat(dir_path, class->dir, sizeof(dir_path) - 1);
1077         } else {
1078                 ast_copy_string(dir_path, class->dir, sizeof(dir_path));
1079         }
1080         ast_debug(4, "Scanning '%s' for files for class '%s'\n", dir_path, class->name);
1081         files_DIR = opendir(dir_path);
1082         if (!files_DIR) {
1083                 ast_log(LOG_WARNING, "Cannot open dir %s or dir does not exist\n", dir_path);
1084                 return -1;
1085         }
1086
1087         for (i = 0; i < class->total_files; i++)
1088                 ast_free(class->filearray[i]);
1089
1090         class->total_files = 0;
1091         if (!getcwd(path, sizeof(path))) {
1092                 ast_log(LOG_WARNING, "getcwd() failed: %s\n", strerror(errno));
1093                 return -1;
1094         }
1095         if (chdir(dir_path) < 0) {
1096                 ast_log(LOG_WARNING, "chdir() failed: %s\n", strerror(errno));
1097                 return -1;
1098         }
1099         while ((files_dirent = readdir(files_DIR))) {
1100                 /* The file name must be at least long enough to have the file type extension */
1101                 if ((strlen(files_dirent->d_name) < 4))
1102                         continue;
1103
1104                 /* Skip files that starts with a dot */
1105                 if (files_dirent->d_name[0] == '.')
1106                         continue;
1107
1108                 /* Skip files without extensions... they are not audio */
1109                 if (!strchr(files_dirent->d_name, '.'))
1110                         continue;
1111
1112                 snprintf(filepath, sizeof(filepath), "%s/%s", dir_path, files_dirent->d_name);
1113
1114                 if (stat(filepath, &statbuf))
1115                         continue;
1116
1117                 if (!S_ISREG(statbuf.st_mode))
1118                         continue;
1119
1120                 if ((ext = strrchr(filepath, '.')))
1121                         *ext = '\0';
1122
1123                 /* if the file is present in multiple formats, ensure we only put it into the list once */
1124                 for (i = 0; i < class->total_files; i++)
1125                         if (!strcmp(filepath, class->filearray[i]))
1126                                 break;
1127
1128                 if (i == class->total_files) {
1129                         if (moh_add_file(class, filepath))
1130                                 break;
1131                 }
1132         }
1133
1134         closedir(files_DIR);
1135         if (chdir(path) < 0) {
1136                 ast_log(LOG_WARNING, "chdir() failed: %s\n", strerror(errno));
1137                 return -1;
1138         }
1139         if (ast_test_flag(class, MOH_SORTALPHA))
1140                 qsort(&class->filearray[0], class->total_files, sizeof(char *), moh_sort_compare);
1141         return class->total_files;
1142 }
1143
1144 static int init_files_class(struct mohclass *class)
1145 {
1146         int res;
1147
1148         res = moh_scan_files(class);
1149
1150         if (res < 0) {
1151                 return -1;
1152         }
1153
1154         if (!res) {
1155                 if (option_verbose > 2) {
1156                         ast_verbose(VERBOSE_PREFIX_3 "Files not found in %s for moh class:%s\n",
1157                                         class->dir, class->name);
1158                 }
1159                 return -1;
1160         }
1161
1162 #if 0
1163         /* XXX This isn't correct.  Args is an application for custom mode. XXX */
1164         if (strchr(class->args, 'r')) {
1165                 ast_set_flag(class, MOH_RANDOMIZE);
1166         }
1167 #endif
1168
1169         return 0;
1170 }
1171
1172 static void moh_rescan_files(void) {
1173         struct ao2_iterator i;
1174         struct mohclass *c;
1175
1176         i = ao2_iterator_init(mohclasses, 0);
1177
1178         while ((c = ao2_iterator_next(&i))) {
1179                 if (!strcasecmp(c->mode, "files")) {
1180                         moh_scan_files(c);
1181                 }
1182                 ao2_ref(c, -1);
1183         }
1184
1185         ao2_iterator_destroy(&i);
1186 }
1187
1188 static int moh_diff(struct mohclass *old, struct mohclass *new)
1189 {
1190         if (!old || !new) {
1191                 return -1;
1192         }
1193
1194         if (strcmp(old->dir, new->dir)) {
1195                 return -1;
1196         } else if (strcmp(old->mode, new->mode)) {
1197                 return -1;
1198         } else if (strcmp(old->args, new->args)) {
1199                 return -1;
1200         } else if (old->flags != new->flags) {
1201                 return -1;
1202         }
1203
1204         return 0;
1205 }
1206
1207 static int init_app_class(struct mohclass *class)
1208 {
1209         if (!strcasecmp(class->mode, "custom")) {
1210                 ast_set_flag(class, MOH_CUSTOM);
1211         } else if (!strcasecmp(class->mode, "mp3nb")) {
1212                 ast_set_flag(class, MOH_SINGLE);
1213         } else if (!strcasecmp(class->mode, "quietmp3nb")) {
1214                 ast_set_flag(class, MOH_SINGLE | MOH_QUIET);
1215         } else if (!strcasecmp(class->mode, "quietmp3")) {
1216                 ast_set_flag(class, MOH_QUIET);
1217         }
1218
1219         class->srcfd = -1;
1220
1221         if (!(class->timer = ast_timer_open())) {
1222                 ast_log(LOG_WARNING, "Unable to create timer: %s\n", strerror(errno));
1223         }
1224         if (class->timer && ast_timer_set_rate(class->timer, 25)) {
1225                 ast_log(LOG_WARNING, "Unable to set 40ms frame rate: %s\n", strerror(errno));
1226                 ast_timer_close(class->timer);
1227                 class->timer = NULL;
1228         }
1229
1230         if (ast_pthread_create_background(&class->thread, NULL, monmp3thread, class)) {
1231                 ast_log(LOG_WARNING, "Unable to create moh thread...\n");
1232                 if (class->timer) {
1233                         ast_timer_close(class->timer);
1234                         class->timer = NULL;
1235                 }
1236                 return -1;
1237         }
1238
1239         return 0;
1240 }
1241
1242 /*!
1243  * \note This function owns the reference it gets to moh if unref is true
1244  */
1245 #define moh_register(a,b,c)     _moh_register(a,b,c,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1246 static int _moh_register(struct mohclass *moh, int reload, int unref, const char *file, int line, const char *funcname)
1247 {
1248         struct mohclass *mohclass = NULL;
1249
1250         if ((mohclass = _get_mohbyname(moh->name, 0, MOH_NOTDELETED, file, line, funcname)) && !moh_diff(mohclass, moh)) {
1251                 ast_log(LOG_WARNING, "Music on Hold class '%s' already exists\n", moh->name);
1252                 mohclass = mohclass_unref(mohclass, "unreffing mohclass we just found by name");
1253                 if (unref) {
1254                         moh = mohclass_unref(moh, "unreffing potential new moh class (it is a duplicate)");
1255                 }
1256                 return -1;
1257         } else if (mohclass) {
1258                 /* Found a class, but it's different from the one being registered */
1259                 mohclass = mohclass_unref(mohclass, "unreffing mohclass we just found by name");
1260         }
1261
1262         time(&moh->start);
1263         moh->start -= respawn_time;
1264
1265         if (!strcasecmp(moh->mode, "files")) {
1266                 if (init_files_class(moh)) {
1267                         if (unref) {
1268                                 moh = mohclass_unref(moh, "unreffing potential new moh class (init_files_class failed)");
1269                         }
1270                         return -1;
1271                 }
1272         } else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") || 
1273                         !strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") || 
1274                         !strcasecmp(moh->mode, "httpmp3") || !strcasecmp(moh->mode, "custom")) {
1275                 if (init_app_class(moh)) {
1276                         if (unref) {
1277                                 moh = mohclass_unref(moh, "unreffing potential new moh class (init_app_class_failed)");
1278                         }
1279                         return -1;
1280                 }
1281         } else {
1282                 ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", moh->mode);
1283                 if (unref) {
1284                         moh = mohclass_unref(moh, "unreffing potential new moh class (unknown mode)");
1285                 }
1286                 return -1;
1287         }
1288
1289         ao2_t_link(mohclasses, moh, "Adding class to container");
1290
1291         if (unref) {
1292                 moh = mohclass_unref(moh, "Unreffing new moh class because we just added it to the container");
1293         }
1294
1295         return 0;
1296 }
1297
1298 static void local_ast_moh_cleanup(struct ast_channel *chan)
1299 {
1300         struct moh_files_state *state = chan->music_state;
1301
1302         if (state) {
1303                 if (state->class) {
1304                         /* This should never happen.  We likely just leaked some resource. */
1305                         state->class =
1306                                 mohclass_unref(state->class, "Uh Oh. Cleaning up MOH with an active class");
1307                         ast_log(LOG_WARNING, "Uh Oh. Cleaning up MOH with an active class\n");
1308                 }
1309                 ast_free(chan->music_state);
1310                 chan->music_state = NULL;
1311                 /* Only held a module reference if we had a music state */
1312                 ast_module_unref(ast_module_info->self);
1313         }
1314 }
1315
1316 static void moh_class_destructor(void *obj);
1317
1318 #define moh_class_malloc()      _moh_class_malloc(__FILE__,__LINE__,__PRETTY_FUNCTION__)
1319
1320 static struct mohclass *_moh_class_malloc(const char *file, int line, const char *funcname)
1321 {
1322         struct mohclass *class;
1323
1324         if ((class =
1325 #ifdef REF_DEBUG
1326                         __ao2_alloc_debug(sizeof(*class), moh_class_destructor, "Allocating new moh class", file, line, funcname, 1)
1327 #elif defined(__AST_DEBUG_MALLOC)
1328                         __ao2_alloc_debug(sizeof(*class), moh_class_destructor, "Allocating new moh class", file, line, funcname, 0)
1329 #else
1330                         ao2_alloc(sizeof(*class), moh_class_destructor)
1331 #endif
1332                 )) {
1333                 ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0);
1334                 class->srcfd = -1;
1335         }
1336
1337         return class;
1338 }
1339
1340 static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
1341 {
1342         struct mohclass *mohclass = NULL;
1343         struct moh_files_state *state = chan->music_state;
1344         struct ast_variable *var = NULL;
1345         int res;
1346         int realtime_possible = ast_check_realtime("musiconhold");
1347
1348         /* The following is the order of preference for which class to use:
1349          * 1) The channels explicitly set musicclass, which should *only* be
1350          *    set by a call to Set(CHANNEL(musicclass)=whatever) in the dialplan.
1351          * 2) The mclass argument. If a channel is calling ast_moh_start() as the
1352          *    result of receiving a HOLD control frame, this should be the
1353          *    payload that came with the frame.
1354          * 3) The interpclass argument. This would be from the mohinterpret
1355          *    option from channel drivers. This is the same as the old musicclass
1356          *    option.
1357          * 4) The default class.
1358          */
1359         if (!ast_strlen_zero(chan->musicclass)) {
1360                 mohclass = get_mohbyname(chan->musicclass, 1, 0);
1361                 if (!mohclass && realtime_possible) {
1362                         var = ast_load_realtime("musiconhold", "name", chan->musicclass, SENTINEL);
1363                 }
1364         }
1365         if (!mohclass && !var && !ast_strlen_zero(mclass)) {
1366                 mohclass = get_mohbyname(mclass, 1, 0);
1367                 if (!mohclass && realtime_possible) {
1368                         var = ast_load_realtime("musiconhold", "name", mclass, SENTINEL);
1369                 }
1370         }
1371         if (!mohclass && !var && !ast_strlen_zero(interpclass)) {
1372                 mohclass = get_mohbyname(interpclass, 1, 0);
1373                 if (!mohclass && realtime_possible) {
1374                         var = ast_load_realtime("musiconhold", "name", interpclass, SENTINEL);
1375                 }
1376         }
1377
1378         if (!mohclass && !var) {
1379                 mohclass = get_mohbyname("default", 1, 0);
1380                 if (!mohclass && realtime_possible) {
1381                         var = ast_load_realtime("musiconhold", "name", "default", SENTINEL);
1382                 }
1383         }
1384
1385         /* If no moh class found in memory, then check RT. Note that the logic used
1386          * above guarantees that if var is non-NULL, then mohclass must be NULL.
1387          */
1388         if (var) {
1389                 struct ast_variable *tmp = NULL;
1390
1391                 if ((mohclass = moh_class_malloc())) {
1392                         mohclass->realtime = 1;
1393                         for (tmp = var; tmp; tmp = tmp->next) {
1394                                 if (!strcasecmp(tmp->name, "name"))
1395                                         ast_copy_string(mohclass->name, tmp->value, sizeof(mohclass->name));
1396                                 else if (!strcasecmp(tmp->name, "mode"))
1397                                         ast_copy_string(mohclass->mode, tmp->value, sizeof(mohclass->mode)); 
1398                                 else if (!strcasecmp(tmp->name, "directory"))
1399                                         ast_copy_string(mohclass->dir, tmp->value, sizeof(mohclass->dir));
1400                                 else if (!strcasecmp(tmp->name, "application"))
1401                                         ast_copy_string(mohclass->args, tmp->value, sizeof(mohclass->args));
1402                                 else if (!strcasecmp(tmp->name, "digit") && (isdigit(*tmp->value) || strchr("*#", *tmp->value)))
1403                                         mohclass->digit = *tmp->value;
1404                                 else if (!strcasecmp(tmp->name, "random"))
1405                                         ast_set2_flag(mohclass, ast_true(tmp->value), MOH_RANDOMIZE);
1406                                 else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "random"))
1407                                         ast_set_flag(mohclass, MOH_RANDOMIZE);
1408                                 else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "alpha")) 
1409                                         ast_set_flag(mohclass, MOH_SORTALPHA);
1410                                 else if (!strcasecmp(tmp->name, "format")) {
1411                                         ast_getformatbyname(tmp->value, &mohclass->format);
1412                                         if (!mohclass->format.id) {
1413                                                 ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", tmp->value);
1414                                                 ast_format_set(&mohclass->format, AST_FORMAT_SLINEAR, 0);
1415                                         }
1416                                 }
1417                         }
1418                         ast_variables_destroy(var);
1419                         if (ast_strlen_zero(mohclass->dir)) {
1420                                 if (!strcasecmp(mohclass->mode, "custom")) {
1421                                         strcpy(mohclass->dir, "nodir");
1422                                 } else {
1423                                         ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", mohclass->name);
1424                                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no directory specified)");
1425                                         return -1;
1426                                 }
1427                         }
1428                         if (ast_strlen_zero(mohclass->mode)) {
1429                                 ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", mohclass->name);
1430                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no mode specified)");
1431                                 return -1;
1432                         }
1433                         if (ast_strlen_zero(mohclass->args) && !strcasecmp(mohclass->mode, "custom")) {
1434                                 ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", mohclass->name);
1435                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no app specified for custom mode");
1436                                 return -1;
1437                         }
1438
1439                         if (ast_test_flag(global_flags, MOH_CACHERTCLASSES)) {
1440                                 /* CACHERTCLASSES enabled, let's add this class to default tree */
1441                                 if (state && state->class) {
1442                                         /* Class already exist for this channel */
1443                                         ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name);
1444                                         if (state->class->realtime && !ast_test_flag(global_flags, MOH_CACHERTCLASSES) && !strcasecmp(mohclass->name, state->class->name)) {
1445                                                 /* we found RT class with the same name, seems like we should continue playing existing one */
1446                                                 /* XXX This code is impossible to reach */
1447                                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (channel already has a class)");
1448                                                 mohclass = state->class;
1449                                         }
1450                                 }
1451                                 /* We don't want moh_register to unref the mohclass because we do it at the end of this function as well.
1452                                  * If we allowed moh_register to unref the mohclass,too, then the count would be off by one. The result would
1453                                  * be that the destructor would be called when the generator on the channel is deactivated. The container then
1454                                  * has a pointer to a freed mohclass, so any operations involving the mohclass container would result in reading
1455                                  * invalid memory.
1456                                  */
1457                                 if (moh_register(mohclass, 0, DONT_UNREF) == -1) {
1458                                         mohclass = mohclass_unref(mohclass, "unreffing mohclass failed to register");
1459                                         return -1;
1460                                 }
1461                         } else {
1462                                 /* We don't register RT moh class, so let's init it manualy */
1463
1464                                 time(&mohclass->start);
1465                                 mohclass->start -= respawn_time;
1466
1467                                 if (!strcasecmp(mohclass->mode, "files")) {
1468                                         if (!moh_scan_files(mohclass)) {
1469                                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (moh_scan_files failed)");
1470                                                 return -1;
1471                                         }
1472                                         if (strchr(mohclass->args, 'r'))
1473                                                 ast_set_flag(mohclass, MOH_RANDOMIZE);
1474                                 } else if (!strcasecmp(mohclass->mode, "mp3") || !strcasecmp(mohclass->mode, "mp3nb") || !strcasecmp(mohclass->mode, "quietmp3") || !strcasecmp(mohclass->mode, "quietmp3nb") || !strcasecmp(mohclass->mode, "httpmp3") || !strcasecmp(mohclass->mode, "custom")) {
1475
1476                                         if (!strcasecmp(mohclass->mode, "custom"))
1477                                                 ast_set_flag(mohclass, MOH_CUSTOM);
1478                                         else if (!strcasecmp(mohclass->mode, "mp3nb"))
1479                                                 ast_set_flag(mohclass, MOH_SINGLE);
1480                                         else if (!strcasecmp(mohclass->mode, "quietmp3nb"))
1481                                                 ast_set_flag(mohclass, MOH_SINGLE | MOH_QUIET);
1482                                         else if (!strcasecmp(mohclass->mode, "quietmp3"))
1483                                                 ast_set_flag(mohclass, MOH_QUIET);
1484
1485                                         mohclass->srcfd = -1;
1486                                         if (!(mohclass->timer = ast_timer_open())) {
1487                                                 ast_log(LOG_WARNING, "Unable to create timer: %s\n", strerror(errno));
1488                                         }
1489                                         if (mohclass->timer && ast_timer_set_rate(mohclass->timer, 25)) {
1490                                                 ast_log(LOG_WARNING, "Unable to set 40ms frame rate: %s\n", strerror(errno));
1491                                                 ast_timer_close(mohclass->timer);
1492                                                 mohclass->timer = NULL;
1493                                         }
1494
1495                                         /* Let's check if this channel already had a moh class before */
1496                                         if (state && state->class) {
1497                                                 /* Class already exist for this channel */
1498                                                 ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name);
1499                                                 if (state->class->realtime && !ast_test_flag(global_flags, MOH_CACHERTCLASSES) && !strcasecmp(mohclass->name, state->class->name)) {
1500                                                         /* we found RT class with the same name, seems like we should continue playing existing one */
1501                                                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (channel already has one)");
1502                                                         mohclass = state->class;
1503                                                 }
1504                                         } else {
1505                                                 if (ast_pthread_create_background(&mohclass->thread, NULL, monmp3thread, mohclass)) {
1506                                                         ast_log(LOG_WARNING, "Unable to create moh...\n");
1507                                                         if (mohclass->timer) {
1508                                                                 ast_timer_close(mohclass->timer);
1509                                                                 mohclass->timer = NULL;
1510                                                         }
1511                                                         mohclass = mohclass_unref(mohclass, "Unreffing potential mohclass (failed to create background thread)");
1512                                                         return -1;
1513                                                 }
1514                                         }
1515                                 } else {
1516                                         ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mohclass->mode);
1517                                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (unknown mode)");
1518                                         return -1;
1519                                 }
1520                         }
1521                 } else {
1522                         ast_variables_destroy(var);
1523                 }
1524         }
1525
1526         if (!mohclass) {
1527                 return -1;
1528         }
1529
1530         ast_manager_event(chan, EVENT_FLAG_CALL, "MusicOnHold",
1531                 "State: Start\r\n"
1532                 "Channel: %s\r\n"
1533                 "UniqueID: %s\r\n"
1534                 "Class: %s\r\n",
1535                 chan->name, chan->uniqueid,
1536                 mohclass->name);
1537
1538         ast_set_flag(chan, AST_FLAG_MOH);
1539
1540         if (mohclass->total_files) {
1541                 res = ast_activate_generator(chan, &moh_file_stream, mohclass);
1542         } else {
1543                 res = ast_activate_generator(chan, &mohgen, mohclass);
1544         }
1545
1546         mohclass = mohclass_unref(mohclass, "unreffing local reference to mohclass in local_ast_moh_start");
1547
1548         return res;
1549 }
1550
1551 static void local_ast_moh_stop(struct ast_channel *chan)
1552 {
1553         ast_clear_flag(chan, AST_FLAG_MOH);
1554         ast_deactivate_generator(chan);
1555
1556         ast_channel_lock(chan);
1557         if (chan->music_state) {
1558                 if (chan->stream) {
1559                         ast_closestream(chan->stream);
1560                         chan->stream = NULL;
1561                 }
1562         }
1563
1564         ast_manager_event(chan, EVENT_FLAG_CALL, "MusicOnHold",
1565                 "State: Stop\r\n"
1566                 "Channel: %s\r\n"
1567                 "UniqueID: %s\r\n",
1568                 chan->name, chan->uniqueid);
1569         ast_channel_unlock(chan);
1570 }
1571
1572 static void moh_class_destructor(void *obj)
1573 {
1574         struct mohclass *class = obj;
1575         struct mohdata *member;
1576         pthread_t tid = 0;
1577
1578         ast_debug(1, "Destroying MOH class '%s'\n", class->name);
1579
1580         /* Kill the thread first, so it cannot restart the child process while the
1581          * class is being destroyed */
1582         if (class->thread != AST_PTHREADT_NULL && class->thread != 0) {
1583                 tid = class->thread;
1584                 class->thread = AST_PTHREADT_NULL;
1585                 pthread_cancel(tid);
1586                 /* We'll collect the exit status later, after we ensure all the readers
1587                  * are dead. */
1588         }
1589
1590         if (class->pid > 1) {
1591                 char buff[8192];
1592                 int bytes, tbytes = 0, stime = 0, pid = 0;
1593
1594                 ast_debug(1, "killing %d!\n", class->pid);
1595
1596                 stime = time(NULL) + 2;
1597                 pid = class->pid;
1598                 class->pid = 0;
1599
1600                 /* Back when this was just mpg123, SIGKILL was fine.  Now we need
1601                  * to give the process a reason and time enough to kill off its
1602                  * children. */
1603                 do {
1604                         if (killpg(pid, SIGHUP) < 0) {
1605                                 ast_log(LOG_WARNING, "Unable to send a SIGHUP to MOH process?!!: %s\n", strerror(errno));
1606                         }
1607                         usleep(100000);
1608                         if (killpg(pid, SIGTERM) < 0) {
1609                                 if (errno == ESRCH) {
1610                                         break;
1611                                 }
1612                                 ast_log(LOG_WARNING, "Unable to terminate MOH process?!!: %s\n", strerror(errno));
1613                         }
1614                         usleep(100000);
1615                         if (killpg(pid, SIGKILL) < 0) {
1616                                 if (errno == ESRCH) {
1617                                         break;
1618                                 }
1619                                 ast_log(LOG_WARNING, "Unable to kill MOH process?!!: %s\n", strerror(errno));
1620                         }
1621                 } while (0);
1622
1623                 while ((ast_wait_for_input(class->srcfd, 100) > 0) && 
1624                                 (bytes = read(class->srcfd, buff, 8192)) && time(NULL) < stime) {
1625                         tbytes = tbytes + bytes;
1626                 }
1627
1628                 ast_debug(1, "mpg123 pid %d and child died after %d bytes read\n", pid, tbytes);
1629
1630                 close(class->srcfd);
1631         }
1632
1633         while ((member = AST_LIST_REMOVE_HEAD(&class->members, list))) {
1634                 free(member);
1635         }
1636
1637         if (class->filearray) {
1638                 int i;
1639                 for (i = 0; i < class->total_files; i++) {
1640                         free(class->filearray[i]);
1641                 }
1642                 free(class->filearray);
1643                 class->filearray = NULL;
1644         }
1645
1646         if (class->timer) {
1647                 ast_timer_close(class->timer);
1648                 class->timer = NULL;
1649         }
1650
1651         /* Finally, collect the exit status of the monitor thread */
1652         if (tid > 0) {
1653                 pthread_join(tid, NULL);
1654         }
1655 }
1656
1657 static int moh_class_mark(void *obj, void *arg, int flags)
1658 {
1659         struct mohclass *class = obj;
1660
1661         class->delete = 1;
1662
1663         return 0;
1664 }
1665
1666 static int moh_classes_delete_marked(void *obj, void *arg, int flags)
1667 {
1668         struct mohclass *class = obj;
1669
1670         return class->delete ? CMP_MATCH : 0;
1671 }
1672
1673 static int load_moh_classes(int reload)
1674 {
1675         struct ast_config *cfg;
1676         struct ast_variable *var;
1677         struct mohclass *class; 
1678         char *cat;
1679         int numclasses = 0;
1680         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1681
1682         cfg = ast_config_load("musiconhold.conf", config_flags);
1683
1684         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
1685                 if (ast_check_realtime("musiconhold") && reload) {
1686                         ao2_t_callback(mohclasses, OBJ_NODATA, moh_class_mark, NULL, "Mark deleted classes");
1687                         ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, moh_classes_delete_marked, NULL, "Purge marked classes");
1688                 }
1689                 return 0;
1690         }
1691         if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
1692                 moh_rescan_files();
1693                 return 0;
1694         }
1695
1696         if (reload) {
1697                 ao2_t_callback(mohclasses, OBJ_NODATA, moh_class_mark, NULL, "Mark deleted classes");
1698         }
1699
1700         ast_clear_flag(global_flags, AST_FLAGS_ALL);
1701
1702         cat = ast_category_browse(cfg, NULL);
1703         for (; cat; cat = ast_category_browse(cfg, cat)) {
1704                 /* Setup common options from [general] section */
1705                 if (!strcasecmp(cat, "general")) {
1706                         for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
1707                                 if (!strcasecmp(var->name, "cachertclasses")) {
1708                                         ast_set2_flag(global_flags, ast_true(var->value), MOH_CACHERTCLASSES);
1709                                 } else {
1710                                         ast_log(LOG_WARNING, "Unknown option '%s' in [general] section of musiconhold.conf\n", var->name);
1711                                 }
1712                         }
1713                 }
1714                 /* These names were deprecated in 1.4 and should not be used until after the next major release. */
1715                 if (!strcasecmp(cat, "classes") || !strcasecmp(cat, "moh_files") || 
1716                                 !strcasecmp(cat, "general")) {
1717                         continue;
1718                 }
1719
1720                 if (!(class = moh_class_malloc())) {
1721                         break;
1722                 }
1723
1724                 ast_copy_string(class->name, cat, sizeof(class->name)); 
1725                 for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
1726                         if (!strcasecmp(var->name, "mode"))
1727                                 ast_copy_string(class->mode, var->value, sizeof(class->mode)); 
1728                         else if (!strcasecmp(var->name, "directory"))
1729                                 ast_copy_string(class->dir, var->value, sizeof(class->dir));
1730                         else if (!strcasecmp(var->name, "application"))
1731                                 ast_copy_string(class->args, var->value, sizeof(class->args));
1732                         else if (!strcasecmp(var->name, "digit") && (isdigit(*var->value) || strchr("*#", *var->value)))
1733                                 class->digit = *var->value;
1734                         else if (!strcasecmp(var->name, "random"))
1735                                 ast_set2_flag(class, ast_true(var->value), MOH_RANDOMIZE);
1736                         else if (!strcasecmp(var->name, "sort") && !strcasecmp(var->value, "random"))
1737                                 ast_set_flag(class, MOH_RANDOMIZE);
1738                         else if (!strcasecmp(var->name, "sort") && !strcasecmp(var->value, "alpha")) 
1739                                 ast_set_flag(class, MOH_SORTALPHA);
1740                         else if (!strcasecmp(var->name, "format")) {
1741                                 ast_getformatbyname(var->value, &class->format);
1742                                 if (!class->format.id) {
1743                                         ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value);
1744                                         ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0);
1745                                 }
1746                         }
1747                 }
1748
1749                 if (ast_strlen_zero(class->dir)) {
1750                         if (!strcasecmp(class->mode, "custom")) {
1751                                 strcpy(class->dir, "nodir");
1752                         } else {
1753                                 ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", class->name);
1754                                 class = mohclass_unref(class, "unreffing potential mohclass (no directory)");
1755                                 continue;
1756                         }
1757                 }
1758                 if (ast_strlen_zero(class->mode)) {
1759                         ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", class->name);
1760                         class = mohclass_unref(class, "unreffing potential mohclass (no mode)");
1761                         continue;
1762                 }
1763                 if (ast_strlen_zero(class->args) && !strcasecmp(class->mode, "custom")) {
1764                         ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", class->name);
1765                         class = mohclass_unref(class, "unreffing potential mohclass (no app for custom mode)");
1766                         continue;
1767                 }
1768
1769                 /* Don't leak a class when it's already registered */
1770                 if (!moh_register(class, reload, HANDLE_REF)) {
1771                         numclasses++;
1772                 }
1773         }
1774
1775         ast_config_destroy(cfg);
1776
1777         ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, 
1778                         moh_classes_delete_marked, NULL, "Purge marked classes");
1779
1780         return numclasses;
1781 }
1782
1783 static void ast_moh_destroy(void)
1784 {
1785         ast_verb(2, "Destroying musiconhold processes\n");
1786         ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "Destroy callback");
1787 }
1788
1789 static char *handle_cli_moh_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1790 {
1791         switch (cmd) {
1792         case CLI_INIT:
1793                 e->command = "moh reload";
1794                 e->usage =
1795                         "Usage: moh reload\n"
1796                         "       Reloads the MusicOnHold module.\n"
1797                         "       Alias for 'module reload res_musiconhold.so'\n";
1798                 return NULL;
1799         case CLI_GENERATE:
1800                 return NULL;
1801         }
1802
1803         if (a->argc != e->args)
1804                 return CLI_SHOWUSAGE;
1805
1806         reload();
1807
1808         return CLI_SUCCESS;
1809 }
1810
1811 static char *handle_cli_moh_show_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1812 {
1813         struct mohclass *class;
1814         struct ao2_iterator i;
1815
1816         switch (cmd) {
1817         case CLI_INIT:
1818                 e->command = "moh show files";
1819                 e->usage =
1820                         "Usage: moh show files\n"
1821                         "       Lists all loaded file-based MusicOnHold classes and their\n"
1822                         "       files.\n";
1823                 return NULL;
1824         case CLI_GENERATE:
1825                 return NULL;
1826         }
1827
1828         if (a->argc != e->args)
1829                 return CLI_SHOWUSAGE;
1830
1831         i = ao2_iterator_init(mohclasses, 0);
1832         for (; (class = ao2_t_iterator_next(&i, "Show files iterator")); mohclass_unref(class, "Unref iterator in moh show files")) {
1833                 int x;
1834
1835                 if (!class->total_files) {
1836                         continue;
1837                 }
1838
1839                 ast_cli(a->fd, "Class: %s\n", class->name);
1840                 for (x = 0; x < class->total_files; x++) {
1841                         ast_cli(a->fd, "\tFile: %s\n", class->filearray[x]);
1842                 }
1843         }
1844         ao2_iterator_destroy(&i);
1845
1846         return CLI_SUCCESS;
1847 }
1848
1849 static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1850 {
1851         struct mohclass *class;
1852         struct ao2_iterator i;
1853
1854         switch (cmd) {
1855         case CLI_INIT:
1856                 e->command = "moh show classes";
1857                 e->usage =
1858                         "Usage: moh show classes\n"
1859                         "       Lists all MusicOnHold classes.\n";
1860                 return NULL;
1861         case CLI_GENERATE:
1862                 return NULL;
1863         }
1864
1865         if (a->argc != e->args)
1866                 return CLI_SHOWUSAGE;
1867
1868         i = ao2_iterator_init(mohclasses, 0);
1869         for (; (class = ao2_t_iterator_next(&i, "Show classes iterator")); mohclass_unref(class, "Unref iterator in moh show classes")) {
1870                 ast_cli(a->fd, "Class: %s\n", class->name);
1871                 ast_cli(a->fd, "\tMode: %s\n", S_OR(class->mode, "<none>"));
1872                 ast_cli(a->fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>"));
1873                 if (ast_test_flag(class, MOH_CUSTOM)) {
1874                         ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
1875                 }
1876                 if (strcasecmp(class->mode, "files")) {
1877                         ast_cli(a->fd, "\tFormat: %s\n", ast_getformatname(&class->format));
1878                 }
1879         }
1880         ao2_iterator_destroy(&i);
1881
1882         return CLI_SUCCESS;
1883 }
1884
1885 static struct ast_cli_entry cli_moh[] = {
1886         AST_CLI_DEFINE(handle_cli_moh_reload,       "Reload MusicOnHold"),
1887         AST_CLI_DEFINE(handle_cli_moh_show_classes, "List MusicOnHold classes"),
1888         AST_CLI_DEFINE(handle_cli_moh_show_files,   "List MusicOnHold file-based classes")
1889 };
1890
1891 static int moh_class_hash(const void *obj, const int flags)
1892 {
1893         const struct mohclass *class = obj;
1894
1895         return ast_str_case_hash(class->name);
1896 }
1897
1898 static int moh_class_cmp(void *obj, void *arg, int flags)
1899 {
1900         struct mohclass *class = obj, *class2 = arg;
1901
1902         return strcasecmp(class->name, class2->name) ? 0 :
1903                 (flags & MOH_NOTDELETED) && (class->delete || class2->delete) ? 0 :
1904                 CMP_MATCH | CMP_STOP;
1905 }
1906
1907 static int load_module(void)
1908 {
1909         int res;
1910
1911         if (!(mohclasses = ao2_t_container_alloc(53, moh_class_hash, moh_class_cmp, "Moh class container"))) {
1912                 return AST_MODULE_LOAD_DECLINE;
1913         }
1914
1915         if (!load_moh_classes(0) && ast_check_realtime("musiconhold") == 0) {   /* No music classes configured, so skip it */
1916                 ast_log(LOG_WARNING, "No music on hold classes configured, "
1917                                 "disabling music on hold.\n");
1918         } else {
1919                 ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop,
1920                                 local_ast_moh_cleanup);
1921         }
1922
1923         res = ast_register_application_xml(play_moh, play_moh_exec);
1924         ast_register_atexit(ast_moh_destroy);
1925         ast_cli_register_multiple(cli_moh, ARRAY_LEN(cli_moh));
1926         if (!res)
1927                 res = ast_register_application_xml(wait_moh, wait_moh_exec);
1928         if (!res)
1929                 res = ast_register_application_xml(set_moh, set_moh_exec);
1930         if (!res)
1931                 res = ast_register_application_xml(start_moh, start_moh_exec);
1932         if (!res)
1933                 res = ast_register_application_xml(stop_moh, stop_moh_exec);
1934
1935         return AST_MODULE_LOAD_SUCCESS;
1936 }
1937
1938 static int reload(void)
1939 {
1940         if (load_moh_classes(1)) {
1941                 ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop,
1942                                 local_ast_moh_cleanup);
1943         }
1944
1945         return AST_MODULE_LOAD_SUCCESS;
1946 }
1947
1948 static int moh_class_inuse(void *obj, void *arg, int flags)
1949 {
1950         struct mohclass *class = obj;
1951
1952         return AST_LIST_EMPTY(&class->members) ? 0 : CMP_MATCH | CMP_STOP;
1953 }
1954
1955 static int unload_module(void)
1956 {
1957         int res = 0;
1958         struct mohclass *class = NULL;
1959
1960         /* XXX This check shouldn't be required if module ref counting was being used
1961          * properly ... */
1962         if ((class = ao2_t_callback(mohclasses, 0, moh_class_inuse, NULL, "Module unload callback"))) {
1963                 class = mohclass_unref(class, "unref of class from module unload callback");
1964                 res = -1;
1965         }
1966
1967         if (res < 0) {
1968                 ast_log(LOG_WARNING, "Unable to unload res_musiconhold due to active MOH channels\n");
1969                 return res;
1970         }
1971
1972         ast_uninstall_music_functions();
1973
1974         ast_moh_destroy();
1975         res = ast_unregister_application(play_moh);
1976         res |= ast_unregister_application(wait_moh);
1977         res |= ast_unregister_application(set_moh);
1978         res |= ast_unregister_application(start_moh);
1979         res |= ast_unregister_application(stop_moh);
1980         ast_cli_unregister_multiple(cli_moh, ARRAY_LEN(cli_moh));
1981         ast_unregister_atexit(ast_moh_destroy);
1982
1983         return res;
1984 }
1985
1986 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Music On Hold Resource",
1987         .load = load_module,
1988         .unload = unload_module,
1989         .reload = reload,
1990         .load_pri = AST_MODPRI_CHANNEL_DEPEND,
1991 );