Fix incorrect usages of ast_realloc().
[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                                 res = 320;
708                         } else {
709                                 ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno));
710                                 res = 0;
711                         }
712                         pthread_testcancel();
713                 } else {
714                         long delta;
715                         /* Reliable sleep */
716                         tv_tmp = ast_tvnow();
717                         if (ast_tvzero(deadline))
718                                 deadline = tv_tmp;
719                         delta = ast_tvdiff_ms(tv_tmp, deadline);
720                         if (delta < MOH_MS_INTERVAL) {  /* too early */
721                                 deadline = ast_tvadd(deadline, ast_samp2tv(MOH_MS_INTERVAL, 1000));     /* next deadline */
722                                 usleep(1000 * (MOH_MS_INTERVAL - delta));
723                                 pthread_testcancel();
724                         } else {
725                                 ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
726                                 deadline = tv_tmp;
727                         }
728                         res = 8 * MOH_MS_INTERVAL;      /* 8 samples per millisecond */
729                 }
730                 if ((strncasecmp(class->dir, "http://", 7) && strcasecmp(class->dir, "nodir")) && AST_LIST_EMPTY(&class->members))
731                         continue;
732                 /* Read mp3 audio */
733                 len = ast_codec_get_len(&class->format, res);
734
735                 if ((res2 = read(class->srcfd, sbuf, len)) != len) {
736                         if (!res2) {
737                                 close(class->srcfd);
738                                 class->srcfd = -1;
739                                 pthread_testcancel();
740                                 if (class->pid > 1) {
741                                         do {
742                                                 if (killpg(class->pid, SIGHUP) < 0) {
743                                                         if (errno == ESRCH) {
744                                                                 break;
745                                                         }
746                                                         ast_log(LOG_WARNING, "Unable to send a SIGHUP to MOH process?!!: %s\n", strerror(errno));
747                                                 }
748                                                 usleep(100000);
749                                                 if (killpg(class->pid, SIGTERM) < 0) {
750                                                         if (errno == ESRCH) {
751                                                                 break;
752                                                         }
753                                                         ast_log(LOG_WARNING, "Unable to terminate MOH process?!!: %s\n", strerror(errno));
754                                                 }
755                                                 usleep(100000);
756                                                 if (killpg(class->pid, SIGKILL) < 0) {
757                                                         if (errno == ESRCH) {
758                                                                 break;
759                                                         }
760                                                         ast_log(LOG_WARNING, "Unable to kill MOH process?!!: %s\n", strerror(errno));
761                                                 }
762                                         } while (0);
763                                         class->pid = 0;
764                                 }
765                         } else {
766                                 ast_debug(1, "Read %d bytes of audio while expecting %d\n", res2, len);
767                         }
768                         continue;
769                 }
770
771                 pthread_testcancel();
772
773                 ao2_lock(class);
774                 AST_LIST_TRAVERSE(&class->members, moh, list) {
775                         /* Write data */
776                         if ((res = write(moh->pipe[1], sbuf, res2)) != res2) {
777                                 ast_debug(1, "Only wrote %d of %d bytes to pipe\n", res, res2);
778                         }
779                 }
780                 ao2_unlock(class);
781         }
782         return NULL;
783 }
784
785 static int play_moh_exec(struct ast_channel *chan, const char *data)
786 {
787         char *parse;
788         char *class;
789         int timeout = -1;
790         int res;
791         AST_DECLARE_APP_ARGS(args,
792                 AST_APP_ARG(class);
793                 AST_APP_ARG(duration);
794         );
795
796         parse = ast_strdupa(data);
797
798         AST_STANDARD_APP_ARGS(args, parse);
799
800         if (!ast_strlen_zero(args.duration)) {
801                 if (sscanf(args.duration, "%30d", &timeout) == 1) {
802                         timeout *= 1000;
803                 } else {
804                         ast_log(LOG_WARNING, "Invalid MusicOnHold duration '%s'. Will wait indefinitely.\n", args.duration);
805                 }
806         }
807
808         class = S_OR(args.class, NULL);
809         if (ast_moh_start(chan, class, NULL)) {
810                 ast_log(LOG_WARNING, "Unable to start music on hold class '%s' on channel %s\n", class, ast_channel_name(chan));
811                 return 0;
812         }
813
814         if (timeout > 0)
815                 res = ast_safe_sleep(chan, timeout);
816         else {
817                 while (!(res = ast_safe_sleep(chan, 10000)));
818         }
819
820         ast_moh_stop(chan);
821
822         return res;
823 }
824
825 static int wait_moh_exec(struct ast_channel *chan, const char *data)
826 {
827         static int deprecation_warning = 0;
828         int res;
829
830         if (!deprecation_warning) {
831                 deprecation_warning = 1;
832                 ast_log(LOG_WARNING, "WaitMusicOnHold application is deprecated and will be removed. Use MusicOnHold with duration parameter instead\n");
833         }
834
835         if (!data || !atoi(data)) {
836                 ast_log(LOG_WARNING, "WaitMusicOnHold requires an argument (number of seconds to wait)\n");
837                 return -1;
838         }
839         if (ast_moh_start(chan, NULL, NULL)) {
840                 ast_log(LOG_WARNING, "Unable to start music on hold for %d seconds on channel %s\n", atoi(data), ast_channel_name(chan));
841                 return 0;
842         }
843         res = ast_safe_sleep(chan, atoi(data) * 1000);
844         ast_moh_stop(chan);
845         return res;
846 }
847
848 static int set_moh_exec(struct ast_channel *chan, const char *data)
849 {
850         static int deprecation_warning = 0;
851
852         if (!deprecation_warning) {
853                 deprecation_warning = 1;
854                 ast_log(LOG_WARNING, "SetMusicOnHold application is deprecated and will be removed. Use Set(CHANNEL(musicclass)=...) instead\n");
855         }
856
857         if (ast_strlen_zero(data)) {
858                 ast_log(LOG_WARNING, "SetMusicOnHold requires an argument (class)\n");
859                 return -1;
860         }
861         ast_channel_musicclass_set(chan, data);
862         return 0;
863 }
864
865 static int start_moh_exec(struct ast_channel *chan, const char *data)
866 {
867         char *parse;
868         char *class;
869         AST_DECLARE_APP_ARGS(args,
870                 AST_APP_ARG(class);
871         );
872
873         parse = ast_strdupa(data);
874
875         AST_STANDARD_APP_ARGS(args, parse);
876
877         class = S_OR(args.class, NULL);
878         if (ast_moh_start(chan, class, NULL)) 
879                 ast_log(LOG_WARNING, "Unable to start music on hold class '%s' on channel %s\n", class, ast_channel_name(chan));
880
881         return 0;
882 }
883
884 static int stop_moh_exec(struct ast_channel *chan, const char *data)
885 {
886         ast_moh_stop(chan);
887
888         return 0;
889 }
890
891 #define get_mohbyname(a,b,c)    _get_mohbyname(a,b,c,__FILE__,__LINE__,__PRETTY_FUNCTION__)
892
893 static struct mohclass *_get_mohbyname(const char *name, int warn, int flags, const char *file, int lineno, const char *funcname)
894 {
895         struct mohclass *moh = NULL;
896         struct mohclass tmp_class = {
897                 .flags = 0,
898         };
899
900         ast_copy_string(tmp_class.name, name, sizeof(tmp_class.name));
901
902 #ifdef REF_DEBUG
903         moh = __ao2_find_debug(mohclasses, &tmp_class, flags,
904                 "get_mohbyname", file, lineno, funcname);
905 #else
906         moh = __ao2_find(mohclasses, &tmp_class, flags);
907 #endif
908
909         if (!moh && warn) {
910                 ast_debug(1, "Music on Hold class '%s' not found in memory\n", name);
911         }
912
913         return moh;
914 }
915
916 static struct mohdata *mohalloc(struct mohclass *cl)
917 {
918         struct mohdata *moh;
919         long flags;
920
921         if (!(moh = ast_calloc(1, sizeof(*moh))))
922                 return NULL;
923
924         if (pipe(moh->pipe)) {
925                 ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno));
926                 ast_free(moh);
927                 return NULL;
928         }
929
930         /* Make entirely non-blocking */
931         flags = fcntl(moh->pipe[0], F_GETFL);
932         fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
933         flags = fcntl(moh->pipe[1], F_GETFL);
934         fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
935
936         moh->f.frametype = AST_FRAME_VOICE;
937         ast_format_copy(&moh->f.subclass.format, &cl->format);
938         moh->f.offset = AST_FRIENDLY_OFFSET;
939
940         moh->parent = mohclass_ref(cl, "Reffing music class for mohdata parent");
941
942         ao2_lock(cl);
943         AST_LIST_INSERT_HEAD(&cl->members, moh, list);
944         ao2_unlock(cl);
945         
946         return moh;
947 }
948
949 static void moh_release(struct ast_channel *chan, void *data)
950 {
951         struct mohdata *moh = data;
952         struct mohclass *class = moh->parent;
953         struct ast_format oldwfmt;
954
955         ao2_lock(class);
956         AST_LIST_REMOVE(&moh->parent->members, moh, list);      
957         ao2_unlock(class);
958         
959         close(moh->pipe[0]);
960         close(moh->pipe[1]);
961
962         ast_format_copy(&oldwfmt, &moh->origwfmt);
963
964         moh->parent = class = mohclass_unref(class, "unreffing moh->parent upon deactivation of generator");
965
966         ast_free(moh);
967
968         if (chan) {
969                 struct moh_files_state *state;
970
971                 state = ast_channel_music_state(chan);
972                 if (state && state->class) {
973                         state->class = mohclass_unref(state->class, "Unreffing channel's music class upon deactivation of generator");
974                 }
975                 if (oldwfmt.id && ast_set_write_format(chan, &oldwfmt)) {
976                         ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n",
977                                         ast_channel_name(chan), ast_getformatname(&oldwfmt));
978                 }
979
980                 ast_verb(3, "Stopped music on hold on %s\n", ast_channel_name(chan));
981         }
982 }
983
984 static void *moh_alloc(struct ast_channel *chan, void *params)
985 {
986         struct mohdata *res;
987         struct mohclass *class = params;
988         struct moh_files_state *state;
989
990         /* Initiating music_state for current channel. Channel should know name of moh class */
991         if (!ast_channel_music_state(chan) && (state = ast_calloc(1, sizeof(*state)))) {
992                 ast_channel_music_state_set(chan, state);
993                 ast_module_ref(ast_module_info->self);
994         } else {
995                 state = ast_channel_music_state(chan);
996                 if (!state) {
997                         return NULL;
998                 }
999                 if (state->class) {
1000                         mohclass_unref(state->class, "Uh Oh. Restarting MOH with an active class");
1001                         ast_log(LOG_WARNING, "Uh Oh. Restarting MOH with an active class\n");
1002                 }
1003                 memset(state, 0, sizeof(*state));
1004         }
1005
1006         if ((res = mohalloc(class))) {
1007                 ast_format_copy(&res->origwfmt, ast_channel_writeformat(chan));
1008                 if (ast_set_write_format(chan, &class->format)) {
1009                         ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", ast_channel_name(chan), ast_codec2str(&class->format));
1010                         moh_release(NULL, res);
1011                         res = NULL;
1012                 } else {
1013                         state->class = mohclass_ref(class, "Placing reference into state container");
1014                 }
1015                 ast_verb(3, "Started music on hold, class '%s', on channel '%s'\n", class->name, ast_channel_name(chan));
1016         }
1017         return res;
1018 }
1019
1020 static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
1021 {
1022         struct mohdata *moh = data;
1023         short buf[1280 + AST_FRIENDLY_OFFSET / 2];
1024         int res;
1025
1026         len = ast_codec_get_len(&moh->parent->format, samples);
1027
1028         if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
1029                 ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), len, ast_channel_name(chan));
1030                 len = sizeof(buf) - AST_FRIENDLY_OFFSET;
1031         }
1032         res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len);
1033         if (res <= 0)
1034                 return 0;
1035
1036         moh->f.datalen = res;
1037         moh->f.data.ptr = buf + AST_FRIENDLY_OFFSET / 2;
1038         moh->f.samples = ast_codec_get_samples(&moh->f);
1039
1040         if (ast_write(chan, &moh->f) < 0) {
1041                 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));
1042                 return -1;
1043         }
1044
1045         return 0;
1046 }
1047
1048 static struct ast_generator mohgen = {
1049         .alloc    = moh_alloc,
1050         .release  = moh_release,
1051         .generate = moh_generate,
1052         .digit    = moh_handle_digit,
1053 };
1054
1055 static int moh_add_file(struct mohclass *class, const char *filepath)
1056 {
1057         if (!class->allowed_files) {
1058                 class->filearray = ast_calloc(1, INITIAL_NUM_FILES * sizeof(*class->filearray));
1059                 if (!class->filearray) {
1060                         return -1;
1061                 }
1062                 class->allowed_files = INITIAL_NUM_FILES;
1063         } else if (class->total_files == class->allowed_files) {
1064                 char **new_array;
1065
1066                 new_array = ast_realloc(class->filearray, class->allowed_files * sizeof(*class->filearray) * 2);
1067                 if (!new_array) {
1068                         return -1;
1069                 }
1070                 class->filearray = new_array;
1071                 class->allowed_files *= 2;
1072         }
1073
1074         class->filearray[class->total_files] = ast_strdup(filepath);
1075         if (!class->filearray[class->total_files]) {
1076                 return -1;
1077         }
1078
1079         class->total_files++;
1080
1081         return 0;
1082 }
1083
1084 static int moh_sort_compare(const void *i1, const void *i2)
1085 {
1086         char *s1, *s2;
1087
1088         s1 = ((char **)i1)[0];
1089         s2 = ((char **)i2)[0];
1090
1091         return strcasecmp(s1, s2);
1092 }
1093
1094 static int moh_scan_files(struct mohclass *class) {
1095
1096         DIR *files_DIR;
1097         struct dirent *files_dirent;
1098         char dir_path[PATH_MAX];
1099         char path[PATH_MAX];
1100         char filepath[PATH_MAX];
1101         char *ext;
1102         struct stat statbuf;
1103         int i;
1104
1105         if (class->dir[0] != '/') {
1106                 ast_copy_string(dir_path, ast_config_AST_DATA_DIR, sizeof(dir_path));
1107                 strncat(dir_path, "/", sizeof(dir_path) - 1);
1108                 strncat(dir_path, class->dir, sizeof(dir_path) - 1);
1109         } else {
1110                 ast_copy_string(dir_path, class->dir, sizeof(dir_path));
1111         }
1112         ast_debug(4, "Scanning '%s' for files for class '%s'\n", dir_path, class->name);
1113         files_DIR = opendir(dir_path);
1114         if (!files_DIR) {
1115                 ast_log(LOG_WARNING, "Cannot open dir %s or dir does not exist\n", dir_path);
1116                 return -1;
1117         }
1118
1119         for (i = 0; i < class->total_files; i++) {
1120                 ast_free(class->filearray[i]);
1121         }
1122         class->total_files = 0;
1123
1124         if (!getcwd(path, sizeof(path))) {
1125                 ast_log(LOG_WARNING, "getcwd() failed: %s\n", strerror(errno));
1126                 closedir(files_DIR);
1127                 return -1;
1128         }
1129         if (chdir(dir_path) < 0) {
1130                 ast_log(LOG_WARNING, "chdir() failed: %s\n", strerror(errno));
1131                 closedir(files_DIR);
1132                 return -1;
1133         }
1134         while ((files_dirent = readdir(files_DIR))) {
1135                 /* The file name must be at least long enough to have the file type extension */
1136                 if ((strlen(files_dirent->d_name) < 4))
1137                         continue;
1138
1139                 /* Skip files that starts with a dot */
1140                 if (files_dirent->d_name[0] == '.')
1141                         continue;
1142
1143                 /* Skip files without extensions... they are not audio */
1144                 if (!strchr(files_dirent->d_name, '.'))
1145                         continue;
1146
1147                 snprintf(filepath, sizeof(filepath), "%s/%s", dir_path, files_dirent->d_name);
1148
1149                 if (stat(filepath, &statbuf))
1150                         continue;
1151
1152                 if (!S_ISREG(statbuf.st_mode))
1153                         continue;
1154
1155                 if ((ext = strrchr(filepath, '.')))
1156                         *ext = '\0';
1157
1158                 /* if the file is present in multiple formats, ensure we only put it into the list once */
1159                 for (i = 0; i < class->total_files; i++)
1160                         if (!strcmp(filepath, class->filearray[i]))
1161                                 break;
1162
1163                 if (i == class->total_files) {
1164                         if (moh_add_file(class, filepath))
1165                                 break;
1166                 }
1167         }
1168
1169         closedir(files_DIR);
1170         if (chdir(path) < 0) {
1171                 ast_log(LOG_WARNING, "chdir() failed: %s\n", strerror(errno));
1172                 return -1;
1173         }
1174         if (ast_test_flag(class, MOH_SORTALPHA))
1175                 qsort(&class->filearray[0], class->total_files, sizeof(char *), moh_sort_compare);
1176         return class->total_files;
1177 }
1178
1179 static int init_files_class(struct mohclass *class)
1180 {
1181         int res;
1182
1183         res = moh_scan_files(class);
1184
1185         if (res < 0) {
1186                 return -1;
1187         }
1188
1189         if (!res) {
1190                 ast_verb(3, "Files not found in %s for moh class:%s\n",
1191                         class->dir, class->name);
1192                 return -1;
1193         }
1194
1195 #if 0
1196         /* XXX This isn't correct.  Args is an application for custom mode. XXX */
1197         if (strchr(class->args, 'r')) {
1198                 ast_set_flag(class, MOH_RANDOMIZE);
1199         }
1200 #endif
1201
1202         return 0;
1203 }
1204
1205 static void moh_rescan_files(void) {
1206         struct ao2_iterator i;
1207         struct mohclass *c;
1208
1209         i = ao2_iterator_init(mohclasses, 0);
1210
1211         while ((c = ao2_iterator_next(&i))) {
1212                 if (!strcasecmp(c->mode, "files")) {
1213                         moh_scan_files(c);
1214                 }
1215                 ao2_ref(c, -1);
1216         }
1217
1218         ao2_iterator_destroy(&i);
1219 }
1220
1221 static int moh_diff(struct mohclass *old, struct mohclass *new)
1222 {
1223         if (!old || !new) {
1224                 return -1;
1225         }
1226
1227         if (strcmp(old->dir, new->dir)) {
1228                 return -1;
1229         } else if (strcmp(old->mode, new->mode)) {
1230                 return -1;
1231         } else if (strcmp(old->args, new->args)) {
1232                 return -1;
1233         } else if (old->flags != new->flags) {
1234                 return -1;
1235         }
1236
1237         return 0;
1238 }
1239
1240 static int init_app_class(struct mohclass *class)
1241 {
1242         if (!strcasecmp(class->mode, "custom")) {
1243                 ast_set_flag(class, MOH_CUSTOM);
1244         } else if (!strcasecmp(class->mode, "mp3nb")) {
1245                 ast_set_flag(class, MOH_SINGLE);
1246         } else if (!strcasecmp(class->mode, "quietmp3nb")) {
1247                 ast_set_flag(class, MOH_SINGLE | MOH_QUIET);
1248         } else if (!strcasecmp(class->mode, "quietmp3")) {
1249                 ast_set_flag(class, MOH_QUIET);
1250         }
1251
1252         class->srcfd = -1;
1253
1254         if (!(class->timer = ast_timer_open())) {
1255                 ast_log(LOG_WARNING, "Unable to create timer: %s\n", strerror(errno));
1256                 return -1;
1257         }
1258         if (class->timer && ast_timer_set_rate(class->timer, 25)) {
1259                 ast_log(LOG_WARNING, "Unable to set 40ms frame rate: %s\n", strerror(errno));
1260                 ast_timer_close(class->timer);
1261                 class->timer = NULL;
1262         }
1263
1264         if (ast_pthread_create_background(&class->thread, NULL, monmp3thread, class)) {
1265                 ast_log(LOG_WARNING, "Unable to create moh thread...\n");
1266                 if (class->timer) {
1267                         ast_timer_close(class->timer);
1268                         class->timer = NULL;
1269                 }
1270                 return -1;
1271         }
1272
1273         return 0;
1274 }
1275
1276 /*!
1277  * \note This function owns the reference it gets to moh if unref is true
1278  */
1279 #define moh_register(a,b,c)     _moh_register(a,b,c,__FILE__,__LINE__,__PRETTY_FUNCTION__)
1280 static int _moh_register(struct mohclass *moh, int reload, int unref, const char *file, int line, const char *funcname)
1281 {
1282         struct mohclass *mohclass = NULL;
1283
1284         mohclass = _get_mohbyname(moh->name, 0, MOH_NOTDELETED, file, line, funcname);
1285
1286         if (mohclass && !moh_diff(mohclass, moh)) {
1287                 ast_log(LOG_WARNING, "Music on Hold class '%s' already exists\n", moh->name);
1288                 mohclass = mohclass_unref(mohclass, "unreffing mohclass we just found by name");
1289                 if (unref) {
1290                         moh = mohclass_unref(moh, "unreffing potential new moh class (it is a duplicate)");
1291                 }
1292                 return -1;
1293         } else if (mohclass) {
1294                 /* Found a class, but it's different from the one being registered */
1295                 mohclass = mohclass_unref(mohclass, "unreffing mohclass we just found by name");
1296         }
1297
1298         time(&moh->start);
1299         moh->start -= respawn_time;
1300
1301         if (!strcasecmp(moh->mode, "files")) {
1302                 if (init_files_class(moh)) {
1303                         if (unref) {
1304                                 moh = mohclass_unref(moh, "unreffing potential new moh class (init_files_class failed)");
1305                         }
1306                         return -1;
1307                 }
1308         } else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") || 
1309                         !strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") || 
1310                         !strcasecmp(moh->mode, "httpmp3") || !strcasecmp(moh->mode, "custom")) {
1311                 if (init_app_class(moh)) {
1312                         if (unref) {
1313                                 moh = mohclass_unref(moh, "unreffing potential new moh class (init_app_class_failed)");
1314                         }
1315                         return -1;
1316                 }
1317         } else {
1318                 ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", moh->mode);
1319                 if (unref) {
1320                         moh = mohclass_unref(moh, "unreffing potential new moh class (unknown mode)");
1321                 }
1322                 return -1;
1323         }
1324
1325         ao2_t_link(mohclasses, moh, "Adding class to container");
1326
1327         if (unref) {
1328                 moh = mohclass_unref(moh, "Unreffing new moh class because we just added it to the container");
1329         }
1330
1331         return 0;
1332 }
1333
1334 static void local_ast_moh_cleanup(struct ast_channel *chan)
1335 {
1336         struct moh_files_state *state = ast_channel_music_state(chan);
1337
1338         if (state) {
1339                 if (state->class) {
1340                         /* This should never happen.  We likely just leaked some resource. */
1341                         state->class =
1342                                 mohclass_unref(state->class, "Uh Oh. Cleaning up MOH with an active class");
1343                         ast_log(LOG_WARNING, "Uh Oh. Cleaning up MOH with an active class\n");
1344                 }
1345                 ast_free(ast_channel_music_state(chan));
1346                 ast_channel_music_state_set(chan, NULL);
1347                 /* Only held a module reference if we had a music state */
1348                 ast_module_unref(ast_module_info->self);
1349         }
1350 }
1351
1352 static void moh_class_destructor(void *obj);
1353
1354 #define moh_class_malloc()      _moh_class_malloc(__FILE__,__LINE__,__PRETTY_FUNCTION__)
1355
1356 static struct mohclass *_moh_class_malloc(const char *file, int line, const char *funcname)
1357 {
1358         struct mohclass *class;
1359
1360         if ((class =
1361 #ifdef REF_DEBUG
1362                         __ao2_alloc_debug(sizeof(*class), moh_class_destructor,
1363                                 AO2_ALLOC_OPT_LOCK_MUTEX, "Allocating new moh class", file, line, funcname, 1)
1364 #elif defined(__AST_DEBUG_MALLOC)
1365                         __ao2_alloc_debug(sizeof(*class), moh_class_destructor,
1366                                 AO2_ALLOC_OPT_LOCK_MUTEX, "Allocating new moh class", file, line, funcname, 0)
1367 #else
1368                         ao2_alloc(sizeof(*class), moh_class_destructor)
1369 #endif
1370                 )) {
1371                 ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0);
1372                 class->srcfd = -1;
1373         }
1374
1375         return class;
1376 }
1377
1378 static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
1379 {
1380         struct mohclass *mohclass = NULL;
1381         struct moh_files_state *state = ast_channel_music_state(chan);
1382         struct ast_variable *var = NULL;
1383         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
1384         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1385         int res;
1386         int realtime_possible = ast_check_realtime("musiconhold");
1387
1388         /* The following is the order of preference for which class to use:
1389          * 1) The channels explicitly set musicclass, which should *only* be
1390          *    set by a call to Set(CHANNEL(musicclass)=whatever) in the dialplan.
1391          * 2) The mclass argument. If a channel is calling ast_moh_start() as the
1392          *    result of receiving a HOLD control frame, this should be the
1393          *    payload that came with the frame.
1394          * 3) The interpclass argument. This would be from the mohinterpret
1395          *    option from channel drivers. This is the same as the old musicclass
1396          *    option.
1397          * 4) The default class.
1398          */
1399         if (!ast_strlen_zero(ast_channel_musicclass(chan))) {
1400                 mohclass = get_mohbyname(ast_channel_musicclass(chan), 1, 0);
1401                 if (!mohclass && realtime_possible) {
1402                         var = ast_load_realtime("musiconhold", "name", ast_channel_musicclass(chan), SENTINEL);
1403                 }
1404         }
1405         if (!mohclass && !var && !ast_strlen_zero(mclass)) {
1406                 mohclass = get_mohbyname(mclass, 1, 0);
1407                 if (!mohclass && realtime_possible) {
1408                         var = ast_load_realtime("musiconhold", "name", mclass, SENTINEL);
1409                 }
1410         }
1411         if (!mohclass && !var && !ast_strlen_zero(interpclass)) {
1412                 mohclass = get_mohbyname(interpclass, 1, 0);
1413                 if (!mohclass && realtime_possible) {
1414                         var = ast_load_realtime("musiconhold", "name", interpclass, SENTINEL);
1415                 }
1416         }
1417
1418         if (!mohclass && !var) {
1419                 mohclass = get_mohbyname("default", 1, 0);
1420                 if (!mohclass && realtime_possible) {
1421                         var = ast_load_realtime("musiconhold", "name", "default", SENTINEL);
1422                 }
1423         }
1424
1425         /* If no moh class found in memory, then check RT. Note that the logic used
1426          * above guarantees that if var is non-NULL, then mohclass must be NULL.
1427          */
1428         if (var) {
1429                 struct ast_variable *tmp = NULL;
1430
1431                 if ((mohclass = moh_class_malloc())) {
1432                         mohclass->realtime = 1;
1433                         for (tmp = var; tmp; tmp = tmp->next) {
1434                                 if (!strcasecmp(tmp->name, "name"))
1435                                         ast_copy_string(mohclass->name, tmp->value, sizeof(mohclass->name));
1436                                 else if (!strcasecmp(tmp->name, "mode"))
1437                                         ast_copy_string(mohclass->mode, tmp->value, sizeof(mohclass->mode)); 
1438                                 else if (!strcasecmp(tmp->name, "directory"))
1439                                         ast_copy_string(mohclass->dir, tmp->value, sizeof(mohclass->dir));
1440                                 else if (!strcasecmp(tmp->name, "application"))
1441                                         ast_copy_string(mohclass->args, tmp->value, sizeof(mohclass->args));
1442                                 else if (!strcasecmp(tmp->name, "digit") && (isdigit(*tmp->value) || strchr("*#", *tmp->value)))
1443                                         mohclass->digit = *tmp->value;
1444                                 else if (!strcasecmp(tmp->name, "random"))
1445                                         ast_set2_flag(mohclass, ast_true(tmp->value), MOH_RANDOMIZE);
1446                                 else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "random"))
1447                                         ast_set_flag(mohclass, MOH_RANDOMIZE);
1448                                 else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "alpha")) 
1449                                         ast_set_flag(mohclass, MOH_SORTALPHA);
1450                                 else if (!strcasecmp(tmp->name, "format")) {
1451                                         ast_getformatbyname(tmp->value, &mohclass->format);
1452                                         if (!mohclass->format.id) {
1453                                                 ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", tmp->value);
1454                                                 ast_format_set(&mohclass->format, AST_FORMAT_SLINEAR, 0);
1455                                         }
1456                                 }
1457                         }
1458                         ast_variables_destroy(var);
1459                         if (ast_strlen_zero(mohclass->dir)) {
1460                                 if (!strcasecmp(mohclass->mode, "custom")) {
1461                                         strcpy(mohclass->dir, "nodir");
1462                                 } else {
1463                                         ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", mohclass->name);
1464                                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no directory specified)");
1465                                         return -1;
1466                                 }
1467                         }
1468                         if (ast_strlen_zero(mohclass->mode)) {
1469                                 ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", mohclass->name);
1470                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no mode specified)");
1471                                 return -1;
1472                         }
1473                         if (ast_strlen_zero(mohclass->args) && !strcasecmp(mohclass->mode, "custom")) {
1474                                 ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", mohclass->name);
1475                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no app specified for custom mode");
1476                                 return -1;
1477                         }
1478
1479                         if (ast_test_flag(global_flags, MOH_CACHERTCLASSES)) {
1480                                 /* CACHERTCLASSES enabled, let's add this class to default tree */
1481                                 if (state && state->class) {
1482                                         /* Class already exist for this channel */
1483                                         ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name);
1484                                         if (state->class->realtime && !ast_test_flag(global_flags, MOH_CACHERTCLASSES) && !strcasecmp(mohclass->name, state->class->name)) {
1485                                                 /* we found RT class with the same name, seems like we should continue playing existing one */
1486                                                 /* XXX This code is impossible to reach */
1487                                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (channel already has a class)");
1488                                                 mohclass = state->class;
1489                                         }
1490                                 }
1491                                 /* We don't want moh_register to unref the mohclass because we do it at the end of this function as well.
1492                                  * If we allowed moh_register to unref the mohclass,too, then the count would be off by one. The result would
1493                                  * be that the destructor would be called when the generator on the channel is deactivated. The container then
1494                                  * has a pointer to a freed mohclass, so any operations involving the mohclass container would result in reading
1495                                  * invalid memory.
1496                                  */
1497                                 if (moh_register(mohclass, 0, DONT_UNREF) == -1) {
1498                                         mohclass = mohclass_unref(mohclass, "unreffing mohclass failed to register");
1499                                         return -1;
1500                                 }
1501                         } else {
1502                                 /* We don't register RT moh class, so let's init it manualy */
1503
1504                                 time(&mohclass->start);
1505                                 mohclass->start -= respawn_time;
1506
1507                                 if (!strcasecmp(mohclass->mode, "files")) {
1508                                         if (!moh_scan_files(mohclass)) {
1509                                                 mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (moh_scan_files failed)");
1510                                                 return -1;
1511                                         }
1512                                         if (strchr(mohclass->args, 'r'))
1513                                                 ast_set_flag(mohclass, MOH_RANDOMIZE);
1514                                 } 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")) {
1515
1516                                         if (!strcasecmp(mohclass->mode, "custom"))
1517                                                 ast_set_flag(mohclass, MOH_CUSTOM);
1518                                         else if (!strcasecmp(mohclass->mode, "mp3nb"))
1519                                                 ast_set_flag(mohclass, MOH_SINGLE);
1520                                         else if (!strcasecmp(mohclass->mode, "quietmp3nb"))
1521                                                 ast_set_flag(mohclass, MOH_SINGLE | MOH_QUIET);
1522                                         else if (!strcasecmp(mohclass->mode, "quietmp3"))
1523                                                 ast_set_flag(mohclass, MOH_QUIET);
1524
1525                                         mohclass->srcfd = -1;
1526                                         if (!(mohclass->timer = ast_timer_open())) {
1527                                                 ast_log(LOG_WARNING, "Unable to create timer: %s\n", strerror(errno));
1528                                         }
1529                                         if (mohclass->timer && ast_timer_set_rate(mohclass->timer, 25)) {
1530                                                 ast_log(LOG_WARNING, "Unable to set 40ms frame rate: %s\n", strerror(errno));
1531                                                 ast_timer_close(mohclass->timer);
1532                                                 mohclass->timer = NULL;
1533                                         }
1534
1535                                         /* Let's check if this channel already had a moh class before */
1536                                         if (state && state->class) {
1537                                                 /* Class already exist for this channel */
1538                                                 ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name);
1539                                                 if (state->class->realtime && !ast_test_flag(global_flags, MOH_CACHERTCLASSES) && !strcasecmp(mohclass->name, state->class->name)) {
1540                                                         /* we found RT class with the same name, seems like we should continue playing existing one */
1541                                                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (channel already has one)");
1542                                                         mohclass = state->class;
1543                                                 }
1544                                         } else {
1545                                                 if (ast_pthread_create_background(&mohclass->thread, NULL, monmp3thread, mohclass)) {
1546                                                         ast_log(LOG_WARNING, "Unable to create moh...\n");
1547                                                         if (mohclass->timer) {
1548                                                                 ast_timer_close(mohclass->timer);
1549                                                                 mohclass->timer = NULL;
1550                                                         }
1551                                                         mohclass = mohclass_unref(mohclass, "Unreffing potential mohclass (failed to create background thread)");
1552                                                         return -1;
1553                                                 }
1554                                         }
1555                                 } else {
1556                                         ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mohclass->mode);
1557                                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (unknown mode)");
1558                                         return -1;
1559                                 }
1560                         }
1561                 } else {
1562                         ast_variables_destroy(var);
1563                         var = NULL;
1564                 }
1565         }
1566
1567         if (!mohclass) {
1568                 return -1;
1569         }
1570
1571         /* If we are using a cached realtime class with files, re-scan the files */
1572         if (!var && ast_test_flag(global_flags, MOH_CACHERTCLASSES) && mohclass->realtime && !strcasecmp(mohclass->mode, "files")) {
1573                 if (!moh_scan_files(mohclass)) {
1574                         mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (moh_scan_files failed)");
1575                         return -1;
1576                 }
1577         }
1578
1579         ast_channel_latest_musicclass_set(chan, mohclass->name);
1580         ast_set_flag(ast_channel_flags(chan), AST_FLAG_MOH);
1581
1582         if (mohclass->total_files) {
1583                 res = ast_activate_generator(chan, &moh_file_stream, mohclass);
1584         } else {
1585                 res = ast_activate_generator(chan, &mohgen, mohclass);
1586         }
1587
1588         json_object = ast_json_pack("{s: s}",
1589                         "class", mohclass->name);
1590         if (!json_object) {
1591                 mohclass = mohclass_unref(mohclass, "unreffing local reference to mohclass in local_ast_moh_start");
1592                 return -1;
1593         }
1594
1595         message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan),
1596                         ast_channel_moh_start_type(),
1597                         json_object);
1598         if (message) {
1599                 stasis_publish(ast_channel_topic(chan), message);
1600         }
1601
1602         mohclass = mohclass_unref(mohclass, "unreffing local reference to mohclass in local_ast_moh_start");
1603
1604         return res;
1605 }
1606
1607 static void local_ast_moh_stop(struct ast_channel *chan)
1608 {
1609         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
1610         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_MOH);
1611         ast_deactivate_generator(chan);
1612
1613         ast_channel_lock(chan);
1614         if (ast_channel_music_state(chan)) {
1615                 if (ast_channel_stream(chan)) {
1616                         ast_closestream(ast_channel_stream(chan));
1617                         ast_channel_stream_set(chan, NULL);
1618                 }
1619         }
1620
1621         message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), ast_channel_moh_stop_type(), NULL);
1622         if (message) {
1623                 stasis_publish(ast_channel_topic(chan), message);
1624         }
1625         ast_channel_unlock(chan);
1626 }
1627
1628 static void moh_class_destructor(void *obj)
1629 {
1630         struct mohclass *class = obj;
1631         struct mohdata *member;
1632         pthread_t tid = 0;
1633
1634         ast_debug(1, "Destroying MOH class '%s'\n", class->name);
1635
1636         ao2_lock(class);
1637         while ((member = AST_LIST_REMOVE_HEAD(&class->members, list))) {
1638                 free(member);
1639         }
1640         ao2_unlock(class);
1641
1642         /* Kill the thread first, so it cannot restart the child process while the
1643          * class is being destroyed */
1644         if (class->thread != AST_PTHREADT_NULL && class->thread != 0) {
1645                 tid = class->thread;
1646                 class->thread = AST_PTHREADT_NULL;
1647                 pthread_cancel(tid);
1648                 /* We'll collect the exit status later, after we ensure all the readers
1649                  * are dead. */
1650         }
1651
1652         if (class->pid > 1) {
1653                 char buff[8192];
1654                 int bytes, tbytes = 0, stime = 0, pid = 0;
1655
1656                 ast_debug(1, "killing %d!\n", class->pid);
1657
1658                 stime = time(NULL) + 2;
1659                 pid = class->pid;
1660                 class->pid = 0;
1661
1662                 /* Back when this was just mpg123, SIGKILL was fine.  Now we need
1663                  * to give the process a reason and time enough to kill off its
1664                  * children. */
1665                 do {
1666                         if (killpg(pid, SIGHUP) < 0) {
1667                                 ast_log(LOG_WARNING, "Unable to send a SIGHUP to MOH process?!!: %s\n", strerror(errno));
1668                         }
1669                         usleep(100000);
1670                         if (killpg(pid, SIGTERM) < 0) {
1671                                 if (errno == ESRCH) {
1672                                         break;
1673                                 }
1674                                 ast_log(LOG_WARNING, "Unable to terminate MOH process?!!: %s\n", strerror(errno));
1675                         }
1676                         usleep(100000);
1677                         if (killpg(pid, SIGKILL) < 0) {
1678                                 if (errno == ESRCH) {
1679                                         break;
1680                                 }
1681                                 ast_log(LOG_WARNING, "Unable to kill MOH process?!!: %s\n", strerror(errno));
1682                         }
1683                 } while (0);
1684
1685                 while ((ast_wait_for_input(class->srcfd, 100) > 0) && 
1686                                 (bytes = read(class->srcfd, buff, 8192)) && time(NULL) < stime) {
1687                         tbytes = tbytes + bytes;
1688                 }
1689
1690                 ast_debug(1, "mpg123 pid %d and child died after %d bytes read\n", pid, tbytes);
1691
1692                 close(class->srcfd);
1693                 class->srcfd = -1;
1694         }
1695
1696         if (class->filearray) {
1697                 int i;
1698                 for (i = 0; i < class->total_files; i++) {
1699                         free(class->filearray[i]);
1700                 }
1701                 free(class->filearray);
1702                 class->filearray = NULL;
1703         }
1704
1705         if (class->timer) {
1706                 ast_timer_close(class->timer);
1707                 class->timer = NULL;
1708         }
1709
1710         /* Finally, collect the exit status of the monitor thread */
1711         if (tid > 0) {
1712                 pthread_join(tid, NULL);
1713         }
1714
1715 }
1716
1717 static int moh_class_mark(void *obj, void *arg, int flags)
1718 {
1719         struct mohclass *class = obj;
1720
1721         class->delete = 1;
1722
1723         return 0;
1724 }
1725
1726 static int moh_classes_delete_marked(void *obj, void *arg, int flags)
1727 {
1728         struct mohclass *class = obj;
1729
1730         return class->delete ? CMP_MATCH : 0;
1731 }
1732
1733 static int load_moh_classes(int reload)
1734 {
1735         struct ast_config *cfg;
1736         struct ast_variable *var;
1737         struct mohclass *class; 
1738         char *cat;
1739         int numclasses = 0;
1740         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1741
1742         cfg = ast_config_load("musiconhold.conf", config_flags);
1743
1744         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
1745                 if (ast_check_realtime("musiconhold") && reload) {
1746                         ao2_t_callback(mohclasses, OBJ_NODATA, moh_class_mark, NULL, "Mark deleted classes");
1747                         ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, moh_classes_delete_marked, NULL, "Purge marked classes");
1748                 }
1749                 return 0;
1750         }
1751         if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
1752                 moh_rescan_files();
1753                 return 0;
1754         }
1755
1756         if (reload) {
1757                 ao2_t_callback(mohclasses, OBJ_NODATA, moh_class_mark, NULL, "Mark deleted classes");
1758         }
1759
1760         ast_clear_flag(global_flags, AST_FLAGS_ALL);
1761
1762         cat = ast_category_browse(cfg, NULL);
1763         for (; cat; cat = ast_category_browse(cfg, cat)) {
1764                 /* Setup common options from [general] section */
1765                 if (!strcasecmp(cat, "general")) {
1766                         for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
1767                                 if (!strcasecmp(var->name, "cachertclasses")) {
1768                                         ast_set2_flag(global_flags, ast_true(var->value), MOH_CACHERTCLASSES);
1769                                 } else {
1770                                         ast_log(LOG_WARNING, "Unknown option '%s' in [general] section of musiconhold.conf\n", var->name);
1771                                 }
1772                         }
1773                 }
1774                 /* These names were deprecated in 1.4 and should not be used until after the next major release. */
1775                 if (!strcasecmp(cat, "classes") || !strcasecmp(cat, "moh_files") || 
1776                                 !strcasecmp(cat, "general")) {
1777                         continue;
1778                 }
1779
1780                 if (!(class = moh_class_malloc())) {
1781                         break;
1782                 }
1783
1784                 ast_copy_string(class->name, cat, sizeof(class->name));
1785                 for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
1786                         if (!strcasecmp(var->name, "mode")) {
1787                                 ast_copy_string(class->mode, var->value, sizeof(class->mode));
1788                         } else if (!strcasecmp(var->name, "directory")) {
1789                                 ast_copy_string(class->dir, var->value, sizeof(class->dir));
1790                         } else if (!strcasecmp(var->name, "application")) {
1791                                 ast_copy_string(class->args, var->value, sizeof(class->args));
1792                         } else if (!strcasecmp(var->name, "announcement")) {
1793                                 ast_copy_string(class->announcement, var->value, sizeof(class->announcement));
1794                                 ast_set_flag(class, MOH_ANNOUNCEMENT);
1795                         } else if (!strcasecmp(var->name, "digit") && (isdigit(*var->value) || strchr("*#", *var->value))) {
1796                                 class->digit = *var->value;
1797                         } else if (!strcasecmp(var->name, "random")) {
1798                                 ast_set2_flag(class, ast_true(var->value), MOH_RANDOMIZE);
1799                         } else if (!strcasecmp(var->name, "sort") && !strcasecmp(var->value, "random")) {
1800                                 ast_set_flag(class, MOH_RANDOMIZE);
1801                         } else if (!strcasecmp(var->name, "sort") && !strcasecmp(var->value, "alpha")) {
1802                                 ast_set_flag(class, MOH_SORTALPHA);
1803                         } else if (!strcasecmp(var->name, "format")) {
1804                                 ast_getformatbyname(var->value, &class->format);
1805                                 if (!class->format.id) {
1806                                         ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value);
1807                                         ast_format_set(&class->format, AST_FORMAT_SLINEAR, 0);
1808                                 }
1809                         }
1810                 }
1811
1812                 if (ast_strlen_zero(class->dir)) {
1813                         if (!strcasecmp(class->mode, "custom")) {
1814                                 strcpy(class->dir, "nodir");
1815                         } else {
1816                                 ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", class->name);
1817                                 class = mohclass_unref(class, "unreffing potential mohclass (no directory)");
1818                                 continue;
1819                         }
1820                 }
1821                 if (ast_strlen_zero(class->mode)) {
1822                         ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", class->name);
1823                         class = mohclass_unref(class, "unreffing potential mohclass (no mode)");
1824                         continue;
1825                 }
1826                 if (ast_strlen_zero(class->args) && !strcasecmp(class->mode, "custom")) {
1827                         ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", class->name);
1828                         class = mohclass_unref(class, "unreffing potential mohclass (no app for custom mode)");
1829                         continue;
1830                 }
1831
1832                 /* Don't leak a class when it's already registered */
1833                 if (!moh_register(class, reload, HANDLE_REF)) {
1834                         numclasses++;
1835                 }
1836         }
1837
1838         ast_config_destroy(cfg);
1839
1840         ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, 
1841                         moh_classes_delete_marked, NULL, "Purge marked classes");
1842
1843         return numclasses;
1844 }
1845
1846 static void ast_moh_destroy(void)
1847 {
1848         ast_verb(2, "Destroying musiconhold processes\n");
1849         if (mohclasses) {
1850                 ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "Destroy callback");
1851                 ao2_ref(mohclasses, -1);
1852                 mohclasses = NULL;
1853         }
1854 }
1855
1856 static char *handle_cli_moh_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1857 {
1858         switch (cmd) {
1859         case CLI_INIT:
1860                 e->command = "moh reload";
1861                 e->usage =
1862                         "Usage: moh reload\n"
1863                         "       Reloads the MusicOnHold module.\n"
1864                         "       Alias for 'module reload res_musiconhold.so'\n";
1865                 return NULL;
1866         case CLI_GENERATE:
1867                 return NULL;
1868         }
1869
1870         if (a->argc != e->args)
1871                 return CLI_SHOWUSAGE;
1872
1873         reload();
1874
1875         return CLI_SUCCESS;
1876 }
1877
1878 static char *handle_cli_moh_show_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1879 {
1880         struct mohclass *class;
1881         struct ao2_iterator i;
1882
1883         switch (cmd) {
1884         case CLI_INIT:
1885                 e->command = "moh show files";
1886                 e->usage =
1887                         "Usage: moh show files\n"
1888                         "       Lists all loaded file-based MusicOnHold classes and their\n"
1889                         "       files.\n";
1890                 return NULL;
1891         case CLI_GENERATE:
1892                 return NULL;
1893         }
1894
1895         if (a->argc != e->args)
1896                 return CLI_SHOWUSAGE;
1897
1898         i = ao2_iterator_init(mohclasses, 0);
1899         for (; (class = ao2_t_iterator_next(&i, "Show files iterator")); mohclass_unref(class, "Unref iterator in moh show files")) {
1900                 int x;
1901
1902                 if (!class->total_files) {
1903                         continue;
1904                 }
1905
1906                 ast_cli(a->fd, "Class: %s\n", class->name);
1907                 for (x = 0; x < class->total_files; x++) {
1908                         ast_cli(a->fd, "\tFile: %s\n", class->filearray[x]);
1909                 }
1910         }
1911         ao2_iterator_destroy(&i);
1912
1913         return CLI_SUCCESS;
1914 }
1915
1916 static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1917 {
1918         struct mohclass *class;
1919         struct ao2_iterator i;
1920
1921         switch (cmd) {
1922         case CLI_INIT:
1923                 e->command = "moh show classes";
1924                 e->usage =
1925                         "Usage: moh show classes\n"
1926                         "       Lists all MusicOnHold classes.\n";
1927                 return NULL;
1928         case CLI_GENERATE:
1929                 return NULL;
1930         }
1931
1932         if (a->argc != e->args)
1933                 return CLI_SHOWUSAGE;
1934
1935         i = ao2_iterator_init(mohclasses, 0);
1936         for (; (class = ao2_t_iterator_next(&i, "Show classes iterator")); mohclass_unref(class, "Unref iterator in moh show classes")) {
1937                 ast_cli(a->fd, "Class: %s\n", class->name);
1938                 ast_cli(a->fd, "\tMode: %s\n", S_OR(class->mode, "<none>"));
1939                 ast_cli(a->fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>"));
1940                 if (ast_test_flag(class, MOH_CUSTOM)) {
1941                         ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
1942                 }
1943                 if (strcasecmp(class->mode, "files")) {
1944                         ast_cli(a->fd, "\tFormat: %s\n", ast_getformatname(&class->format));
1945                 }
1946         }
1947         ao2_iterator_destroy(&i);
1948
1949         return CLI_SUCCESS;
1950 }
1951
1952 static struct ast_cli_entry cli_moh[] = {
1953         AST_CLI_DEFINE(handle_cli_moh_reload,       "Reload MusicOnHold"),
1954         AST_CLI_DEFINE(handle_cli_moh_show_classes, "List MusicOnHold classes"),
1955         AST_CLI_DEFINE(handle_cli_moh_show_files,   "List MusicOnHold file-based classes")
1956 };
1957
1958 static int moh_class_hash(const void *obj, const int flags)
1959 {
1960         const struct mohclass *class = obj;
1961
1962         return ast_str_case_hash(class->name);
1963 }
1964
1965 static int moh_class_cmp(void *obj, void *arg, int flags)
1966 {
1967         struct mohclass *class = obj, *class2 = arg;
1968
1969         return strcasecmp(class->name, class2->name) ? 0 :
1970                 (flags & MOH_NOTDELETED) && (class->delete || class2->delete) ? 0 :
1971                 CMP_MATCH | CMP_STOP;
1972 }
1973
1974 /*!
1975  * \brief Load the module
1976  *
1977  * Module loading including tests for configuration or dependencies.
1978  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
1979  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
1980  * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the 
1981  * configuration file or other non-critical problem return 
1982  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
1983  */
1984 static int load_module(void)
1985 {
1986         int res;
1987
1988         if (!(mohclasses = ao2_t_container_alloc(53, moh_class_hash, moh_class_cmp, "Moh class container"))) {
1989                 return AST_MODULE_LOAD_DECLINE;
1990         }
1991
1992         if (!load_moh_classes(0) && ast_check_realtime("musiconhold") == 0) {   /* No music classes configured, so skip it */
1993                 ast_log(LOG_WARNING, "No music on hold classes configured, "
1994                                 "disabling music on hold.\n");
1995         } else {
1996                 ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop,
1997                                 local_ast_moh_cleanup);
1998         }
1999
2000         res = ast_register_application_xml(play_moh, play_moh_exec);
2001         ast_register_atexit(ast_moh_destroy);
2002         ast_cli_register_multiple(cli_moh, ARRAY_LEN(cli_moh));
2003         if (!res)
2004                 res = ast_register_application_xml(wait_moh, wait_moh_exec);
2005         if (!res)
2006                 res = ast_register_application_xml(set_moh, set_moh_exec);
2007         if (!res)
2008                 res = ast_register_application_xml(start_moh, start_moh_exec);
2009         if (!res)
2010                 res = ast_register_application_xml(stop_moh, stop_moh_exec);
2011
2012         return AST_MODULE_LOAD_SUCCESS;
2013 }
2014
2015 static int reload(void)
2016 {
2017         if (load_moh_classes(1)) {
2018                 ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop,
2019                                 local_ast_moh_cleanup);
2020         }
2021
2022         return AST_MODULE_LOAD_SUCCESS;
2023 }
2024
2025 static int moh_class_inuse(void *obj, void *arg, int flags)
2026 {
2027         struct mohclass *class = obj;
2028
2029         return AST_LIST_EMPTY(&class->members) ? 0 : CMP_MATCH | CMP_STOP;
2030 }
2031
2032 static int unload_module(void)
2033 {
2034         int res = 0;
2035         struct mohclass *class = NULL;
2036
2037         /* XXX This check shouldn't be required if module ref counting was being used
2038          * properly ... */
2039         if ((class = ao2_t_callback(mohclasses, 0, moh_class_inuse, NULL, "Module unload callback"))) {
2040                 class = mohclass_unref(class, "unref of class from module unload callback");
2041                 res = -1;
2042         }
2043
2044         if (res < 0) {
2045                 ast_log(LOG_WARNING, "Unable to unload res_musiconhold due to active MOH channels\n");
2046                 return res;
2047         }
2048
2049         ast_uninstall_music_functions();
2050
2051         ast_moh_destroy();
2052         res = ast_unregister_application(play_moh);
2053         res |= ast_unregister_application(wait_moh);
2054         res |= ast_unregister_application(set_moh);
2055         res |= ast_unregister_application(start_moh);
2056         res |= ast_unregister_application(stop_moh);
2057         ast_cli_unregister_multiple(cli_moh, ARRAY_LEN(cli_moh));
2058         ast_unregister_atexit(ast_moh_destroy);
2059
2060         return res;
2061 }
2062
2063 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Music On Hold Resource",
2064         .load = load_module,
2065         .unload = unload_module,
2066         .reload = reload,
2067         .load_pri = AST_MODPRI_CHANNEL_DEPEND,
2068 );