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