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