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