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