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