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