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