#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/say.h"
#include "asterisk/musiconhold.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
Include dependency graph for res_musiconhold.c:
Go to the source code of this file.
Data Structures | |
struct | moh_files_state |
struct | mohclass |
struct | mohdata |
Defines | |
#define | LOCAL_MPG_123 "/usr/local/bin/mpg123" |
#define | MAX_MOHFILE_LEN 128 |
#define | MAX_MOHFILES 512 |
#define | MAX_MP3S 256 |
#define | MOH_CUSTOM (1 << 2) |
#define | MOH_MS_INTERVAL 100 |
#define | MOH_QUIET (1 << 0) |
#define | MOH_RANDOMIZE (1 << 3) |
#define | MOH_SINGLE (1 << 1) |
#define | MPG_123 "/usr/bin/mpg123" |
Functions | |
static void | ast_moh_destroy (void) |
static int | ast_moh_files_next (struct ast_channel *chan) |
static void | ast_moh_free_class (struct mohclass **class) |
AST_MUTEX_DEFINE_STATIC (moh_lock) | |
static int | cli_files_show (int fd, int argc, char *argv[]) |
char * | description (void) |
Provides a description of the module. | |
static struct mohclass * | get_mohbyname (char *name) |
static int | init_classes (int reload) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
static int | load_moh_classes (int reload) |
static void | local_ast_moh_cleanup (struct ast_channel *chan) |
static int | local_ast_moh_start (struct ast_channel *chan, char *class) |
static void | local_ast_moh_stop (struct ast_channel *chan) |
static int | moh0_exec (struct ast_channel *chan, void *data) |
static int | moh1_exec (struct ast_channel *chan, void *data) |
static int | moh2_exec (struct ast_channel *chan, void *data) |
static int | moh3_exec (struct ast_channel *chan, void *data) |
static int | moh4_exec (struct ast_channel *chan, void *data) |
static void * | moh_alloc (struct ast_channel *chan, void *params) |
static struct mohclass * | moh_class_malloc (void) |
static int | moh_classes_show (int fd, int argc, char *argv[]) |
static int | moh_cli (int fd, int argc, char *argv[]) |
static void * | moh_files_alloc (struct ast_channel *chan, void *params) |
static int | moh_files_generator (struct ast_channel *chan, void *data, int len, int samples) |
static struct ast_frame * | moh_files_readframe (struct ast_channel *chan) |
static void | moh_files_release (struct ast_channel *chan, void *data) |
static int | moh_generate (struct ast_channel *chan, void *data, int len, int samples) |
static void | moh_on_off (int on) |
static int | moh_register (struct mohclass *moh, int reload) |
static void | moh_release (struct ast_channel *chan, void *data) |
static int | moh_scan_files (struct mohclass *class) |
static struct mohdata * | mohalloc (struct mohclass *cl) |
static void * | monmp3thread (void *data) |
int | reload (void) |
Reload stuff. | |
static int | spawn_mp3 (struct mohclass *class) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static char * | app0 = "MusicOnHold" |
static char * | app1 = "WaitMusicOnHold" |
static char * | app2 = "SetMusicOnHold" |
static char * | app3 = "StartMusicOnHold" |
static char * | app4 = "StopMusicOnHold" |
static struct ast_cli_entry | cli_moh = { { "moh", "reload"}, moh_cli, "Music On Hold", "Music On Hold", NULL} |
static struct ast_cli_entry | cli_moh_classes_show = { { "moh", "classes", "show"}, moh_classes_show, "List MOH classes", "Lists all MOH classes", NULL} |
static struct ast_cli_entry | cli_moh_files_show = { { "moh", "files", "show"}, cli_files_show, "List MOH file-based classes", "Lists all loaded file-based MOH classes and their files", NULL} |
static char * | descrip0 |
static char * | descrip1 |
static char * | descrip2 |
static char * | descrip3 |
static char * | descrip4 |
static struct ast_generator | moh_file_stream |
static struct mohclass * | mohclasses |
static struct ast_generator | mohgen |
static int | respawn_time = 20 |
static char * | synopsis0 = "Play Music On Hold indefinitely" |
static char * | synopsis1 = "Wait, playing Music On Hold" |
static char * | synopsis2 = "Set default Music On Hold class" |
static char * | synopsis3 = "Play Music On Hold" |
static char * | synopsis4 = "Stop Playing Music On Hold" |
Definition in file res_musiconhold.c.
#define LOCAL_MPG_123 "/usr/local/bin/mpg123" |
Definition at line 154 of file res_musiconhold.c.
#define MAX_MOHFILE_LEN 128 |
#define MAX_MOHFILES 512 |
#define MAX_MP3S 256 |
#define MOH_CUSTOM (1 << 2) |
Definition at line 120 of file res_musiconhold.c.
Referenced by moh_classes_show(), moh_register(), and spawn_mp3().
#define MOH_MS_INTERVAL 100 |
Referenced by monmp3thread().
#define MOH_QUIET (1 << 0) |
#define MOH_RANDOMIZE (1 << 3) |
Definition at line 121 of file res_musiconhold.c.
Referenced by ast_moh_files_next(), load_moh_classes(), and moh_register().
#define MOH_SINGLE (1 << 1) |
#define MPG_123 "/usr/bin/mpg123" |
Definition at line 155 of file res_musiconhold.c.
static void ast_moh_destroy | ( | void | ) | [static] |
Definition at line 1078 of file res_musiconhold.c.
References ast_log(), ast_moh_free_class(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_wait_for_input(), moh, mohclasses, option_verbose, mohclass::pid, and VERBOSE_PREFIX_2.
Referenced by load_module(), and moh_cli().
01079 { 01080 struct mohclass *moh, *tmp; 01081 char buff[8192]; 01082 int bytes, tbytes=0, stime = 0, pid = 0; 01083 01084 if (option_verbose > 1) 01085 ast_verbose(VERBOSE_PREFIX_2 "Destroying musiconhold processes\n"); 01086 ast_mutex_lock(&moh_lock); 01087 moh = mohclasses; 01088 01089 while (moh) { 01090 if (moh->pid) { 01091 ast_log(LOG_DEBUG, "killing %d!\n", moh->pid); 01092 stime = time(NULL) + 2; 01093 pid = moh->pid; 01094 moh->pid = 0; 01095 /* Back when this was just mpg123, SIGKILL was fine. Now we need 01096 * to give the process a reason and time enough to kill off its 01097 * children. */ 01098 kill(pid, SIGHUP); 01099 usleep(100000); 01100 kill(pid, SIGTERM); 01101 usleep(100000); 01102 kill(pid, SIGKILL); 01103 while ((ast_wait_for_input(moh->srcfd, 100) > 0) && (bytes = read(moh->srcfd, buff, 8192)) && time(NULL) < stime) { 01104 tbytes = tbytes + bytes; 01105 } 01106 ast_log(LOG_DEBUG, "mpg123 pid %d and child died after %d bytes read\n", pid, tbytes); 01107 close(moh->srcfd); 01108 } 01109 tmp = moh; 01110 moh = moh->next; 01111 ast_moh_free_class(&tmp); 01112 } 01113 mohclasses = NULL; 01114 ast_mutex_unlock(&moh_lock); 01115 }
static int ast_moh_files_next | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 198 of file res_musiconhold.c.
References ast_closestream(), ast_fileexists(), ast_test_flag, moh_files_state::class, mohclass::filearray, MOH_RANDOMIZE, ast_channel::music_state, moh_files_state::pos, moh_files_state::samples, moh_files_state::save_pos, ast_channel::stream, and mohclass::total_files.
Referenced by moh_files_readframe().
00199 { 00200 struct moh_files_state *state = chan->music_state; 00201 int tries; 00202 00203 if (state->save_pos) { 00204 state->pos = state->save_pos - 1; 00205 state->save_pos = 0; 00206 } else { 00207 /* Try 20 times to find something good */ 00208 for (tries=0;tries < 20;tries++) { 00209 state->samples = 0; 00210 if (chan->stream) { 00211 ast_closestream(chan->stream); 00212 chan->stream = NULL; 00213 state->pos++; 00214 } 00215 00216 if (ast_test_flag(state->class, MOH_RANDOMIZE)) 00217 state->pos = rand(); 00218 00219 state->pos %= state->class->total_files; 00220 00221 /* check to see if this file's format can be opened */ 00222 if (ast_fileexists(state->class->filearray[state->pos], NULL, NULL) > 0) 00223 break; 00224 00225 } 00226 } 00227 00228 state->pos = state->pos % state->class->total_files; 00229 00230 if (!ast_openstream_full(chan, state->class->filearray[state->pos], chan->language, 1)) { 00231 ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", state->class->filearray[state->pos], strerror(errno)); 00232 state->pos++; 00233 return -1; 00234 } 00235 00236 if (option_debug) 00237 ast_log(LOG_DEBUG, "%s Opened file %d '%s'\n", chan->name, state->pos, state->class->filearray[state->pos]); 00238 00239 if (state->samples) 00240 ast_seekstream(chan->stream, state->samples, SEEK_SET); 00241 00242 return 0; 00243 }
static void ast_moh_free_class | ( | struct mohclass ** | class | ) | [static] |
Definition at line 159 of file res_musiconhold.c.
References free, and mohdata::next.
Referenced by ast_moh_destroy(), and moh_register().
00160 { 00161 struct mohdata *members, *mtmp; 00162 00163 members = (*class)->members; 00164 while(members) { 00165 mtmp = members; 00166 members = members->next; 00167 free(mtmp); 00168 } 00169 if ((*class)->thread) { 00170 pthread_cancel((*class)->thread); 00171 (*class)->thread = 0; 00172 } 00173 free(*class); 00174 *class = NULL; 00175 }
AST_MUTEX_DEFINE_STATIC | ( | moh_lock | ) |
static int cli_files_show | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1144 of file res_musiconhold.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), and mohclasses.
01145 { 01146 int i; 01147 struct mohclass *class; 01148 01149 ast_mutex_lock(&moh_lock); 01150 for (class = mohclasses; class; class = class->next) { 01151 if (!class->total_files) 01152 continue; 01153 01154 ast_cli(fd, "Class: %s\n", class->name); 01155 for (i = 0; i < class->total_files; i++) 01156 ast_cli(fd, "\tFile: %s\n", class->filearray[i]); 01157 } 01158 ast_mutex_unlock(&moh_lock); 01159 01160 return 0; 01161 }
char* description | ( | void | ) |
Provides a description of the module.
Definition at line 1242 of file res_musiconhold.c.
static struct mohclass* get_mohbyname | ( | char * | name | ) | [static] |
Definition at line 612 of file res_musiconhold.c.
References moh, and mohclasses.
Referenced by load_moh_classes(), local_ast_moh_start(), and moh_register().
00613 { 00614 struct mohclass *moh; 00615 moh = mohclasses; 00616 while (moh) { 00617 if (!strcasecmp(name, moh->name)) 00618 return moh; 00619 moh = moh->next; 00620 } 00621 return NULL; 00622 }
static int init_classes | ( | int | reload | ) | [static] |
Definition at line 1187 of file res_musiconhold.c.
References load_moh_classes(), moh, moh_scan_files(), and mohclasses.
Referenced by load_module(), and reload().
01188 { 01189 struct mohclass *moh; 01190 01191 if (!load_moh_classes(reload)) /* Load classes from config */ 01192 return 0; /* Return if nothing is found */ 01193 moh = mohclasses; 01194 while (moh) { 01195 if (moh->total_files) 01196 moh_scan_files(moh); 01197 moh = moh->next; 01198 } 01199 return 1; 01200 }
char* key | ( | void | ) |
Returns the ASTERISK_GPL_KEY.
This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 1260 of file res_musiconhold.c.
References ASTERISK_GPL_KEY.
01261 { 01262 return ASTERISK_GPL_KEY; 01263 }
int load_module | ( | void | ) |
Initialize the module.
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 1202 of file res_musiconhold.c.
References ast_cli_register(), ast_install_music_functions(), ast_log(), ast_moh_destroy(), ast_register_application(), ast_register_atexit(), cli_moh, cli_moh_classes_show, cli_moh_files_show, init_classes(), local_ast_moh_cleanup(), local_ast_moh_start(), local_ast_moh_stop(), LOG_WARNING, moh0_exec(), moh1_exec(), moh2_exec(), moh3_exec(), and moh4_exec().
01203 { 01204 int res; 01205 01206 res = ast_register_application(app0, moh0_exec, synopsis0, descrip0); 01207 ast_register_atexit(ast_moh_destroy); 01208 ast_cli_register(&cli_moh); 01209 ast_cli_register(&cli_moh_files_show); 01210 ast_cli_register(&cli_moh_classes_show); 01211 if (!res) 01212 res = ast_register_application(app1, moh1_exec, synopsis1, descrip1); 01213 if (!res) 01214 res = ast_register_application(app2, moh2_exec, synopsis2, descrip2); 01215 if (!res) 01216 res = ast_register_application(app3, moh3_exec, synopsis3, descrip3); 01217 if (!res) 01218 res = ast_register_application(app4, moh4_exec, synopsis4, descrip4); 01219 01220 if (!init_classes(0)) { /* No music classes configured, so skip it */ 01221 ast_log(LOG_WARNING, "No music on hold classes configured, disabling music on hold."); 01222 } else { 01223 ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop, local_ast_moh_cleanup); 01224 } 01225 01226 return 0; 01227 }
static int load_moh_classes | ( | int | reload | ) | [static] |
Definition at line 940 of file res_musiconhold.c.
References mohclass::args, ast_category_browse(), ast_config_destroy(), ast_config_load(), AST_FORMAT_SLINEAR, ast_getformatbyname(), ast_log(), ast_set2_flag, ast_strlen_zero(), ast_true(), ast_variable_browse(), cfg, dep_warning, free, get_mohbyname(), LOG_WARNING, moh_class_malloc(), MOH_RANDOMIZE, moh_register(), and var.
Referenced by init_classes(), and moh_cli().
00941 { 00942 struct ast_config *cfg; 00943 struct ast_variable *var; 00944 struct mohclass *class; 00945 char *data; 00946 char *args; 00947 char *cat; 00948 int numclasses = 0; 00949 static int dep_warning = 0; 00950 00951 cfg = ast_config_load("musiconhold.conf"); 00952 00953 if (!cfg) 00954 return 0; 00955 00956 cat = ast_category_browse(cfg, NULL); 00957 for (; cat; cat = ast_category_browse(cfg, cat)) { 00958 if (strcasecmp(cat, "classes") && strcasecmp(cat, "moh_files")) { 00959 class = moh_class_malloc(); 00960 if (!class) { 00961 ast_log(LOG_WARNING, "Out of memory!\n"); 00962 break; 00963 } 00964 ast_copy_string(class->name, cat, sizeof(class->name)); 00965 var = ast_variable_browse(cfg, cat); 00966 while (var) { 00967 if (!strcasecmp(var->name, "mode")) 00968 ast_copy_string(class->mode, var->value, sizeof(class->mode)); 00969 else if (!strcasecmp(var->name, "directory")) 00970 ast_copy_string(class->dir, var->value, sizeof(class->dir)); 00971 else if (!strcasecmp(var->name, "application")) 00972 ast_copy_string(class->args, var->value, sizeof(class->args)); 00973 else if (!strcasecmp(var->name, "random")) 00974 ast_set2_flag(class, ast_true(var->value), MOH_RANDOMIZE); 00975 else if (!strcasecmp(var->name, "format")) { 00976 class->format = ast_getformatbyname(var->value); 00977 if (!class->format) { 00978 ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value); 00979 class->format = AST_FORMAT_SLINEAR; 00980 } 00981 } 00982 var = var->next; 00983 } 00984 00985 if (ast_strlen_zero(class->dir)) { 00986 if (!strcasecmp(class->mode, "custom")) { 00987 strcpy(class->dir, "nodir"); 00988 } else { 00989 ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", class->name); 00990 free(class); 00991 continue; 00992 } 00993 } 00994 if (ast_strlen_zero(class->mode)) { 00995 ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", class->name); 00996 free(class); 00997 continue; 00998 } 00999 if (ast_strlen_zero(class->args) && !strcasecmp(class->mode, "custom")) { 01000 ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", class->name); 01001 free(class); 01002 continue; 01003 } 01004 01005 /* Don't leak a class when it's already registered */ 01006 moh_register(class, reload); 01007 01008 numclasses++; 01009 } 01010 } 01011 01012 01013 /* Deprecated Old-School Configuration */ 01014 var = ast_variable_browse(cfg, "classes"); 01015 while (var) { 01016 if (!dep_warning) { 01017 ast_log(LOG_WARNING, "The old musiconhold.conf syntax has been deprecated! Please refer to the sample configuration for information on the new syntax.\n"); 01018 dep_warning = 1; 01019 } 01020 data = strchr(var->value, ':'); 01021 if (data) { 01022 *data++ = '\0'; 01023 args = strchr(data, ','); 01024 if (args) 01025 *args++ = '\0'; 01026 if (!(get_mohbyname(var->name))) { 01027 class = moh_class_malloc(); 01028 if (!class) { 01029 ast_log(LOG_WARNING, "Out of memory!\n"); 01030 return numclasses; 01031 } 01032 01033 ast_copy_string(class->name, var->name, sizeof(class->name)); 01034 ast_copy_string(class->dir, data, sizeof(class->dir)); 01035 ast_copy_string(class->mode, var->value, sizeof(class->mode)); 01036 if (args) 01037 ast_copy_string(class->args, args, sizeof(class->args)); 01038 01039 moh_register(class, reload); 01040 numclasses++; 01041 } 01042 } 01043 var = var->next; 01044 } 01045 var = ast_variable_browse(cfg, "moh_files"); 01046 while (var) { 01047 if (!dep_warning) { 01048 ast_log(LOG_WARNING, "The old musiconhold.conf syntax has been deprecated! Please refer to the sample configuration for information on the new syntax.\n"); 01049 dep_warning = 1; 01050 } 01051 if (!(get_mohbyname(var->name))) { 01052 args = strchr(var->value, ','); 01053 if (args) 01054 *args++ = '\0'; 01055 class = moh_class_malloc(); 01056 if (!class) { 01057 ast_log(LOG_WARNING, "Out of memory!\n"); 01058 return numclasses; 01059 } 01060 01061 ast_copy_string(class->name, var->name, sizeof(class->name)); 01062 ast_copy_string(class->dir, var->value, sizeof(class->dir)); 01063 strcpy(class->mode, "files"); 01064 if (args) 01065 ast_copy_string(class->args, args, sizeof(class->args)); 01066 01067 moh_register(class, reload); 01068 numclasses++; 01069 } 01070 var = var->next; 01071 } 01072 01073 ast_config_destroy(cfg); 01074 01075 return numclasses; 01076 }
static void local_ast_moh_cleanup | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 879 of file res_musiconhold.c.
References free, and ast_channel::music_state.
Referenced by load_module(), and reload().
00880 { 00881 if (chan->music_state) { 00882 free(chan->music_state); 00883 chan->music_state = NULL; 00884 } 00885 }
static int local_ast_moh_start | ( | struct ast_channel * | chan, | |
char * | class | |||
) | [static] |
Definition at line 887 of file res_musiconhold.c.
References ast_activate_generator(), AST_FLAG_MOH, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_strlen_zero(), get_mohbyname(), LOG_WARNING, moh_file_stream, mohgen, and mohclass::total_files.
Referenced by load_module(), moh_on_off(), and reload().
00888 { 00889 struct mohclass *mohclass; 00890 00891 if (ast_strlen_zero(class)) 00892 class = chan->musicclass; 00893 if (ast_strlen_zero(class)) 00894 class = "default"; 00895 ast_mutex_lock(&moh_lock); 00896 mohclass = get_mohbyname(class); 00897 ast_mutex_unlock(&moh_lock); 00898 00899 if (!mohclass) { 00900 ast_log(LOG_WARNING, "No class: %s\n", (char *)class); 00901 return -1; 00902 } 00903 00904 ast_set_flag(chan, AST_FLAG_MOH); 00905 if (mohclass->total_files) { 00906 return ast_activate_generator(chan, &moh_file_stream, mohclass); 00907 } else 00908 return ast_activate_generator(chan, &mohgen, mohclass); 00909 }
static void local_ast_moh_stop | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 911 of file res_musiconhold.c.
References ast_clear_flag, ast_closestream(), ast_deactivate_generator(), AST_FLAG_MOH, ast_channel::music_state, and ast_channel::stream.
Referenced by load_module(), and reload().
00912 { 00913 ast_clear_flag(chan, AST_FLAG_MOH); 00914 ast_deactivate_generator(chan); 00915 00916 if (chan->music_state) { 00917 if (chan->stream) { 00918 ast_closestream(chan->stream); 00919 chan->stream = NULL; 00920 } 00921 } 00922 }
static int moh0_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 557 of file res_musiconhold.c.
References ast_log(), ast_moh_start(), ast_moh_stop(), ast_safe_sleep(), LOG_WARNING, and ast_channel::name.
Referenced by load_module().
00558 { 00559 if (ast_moh_start(chan, data)) { 00560 ast_log(LOG_WARNING, "Unable to start music on hold (class '%s') on channel %s\n", (char *)data, chan->name); 00561 return -1; 00562 } 00563 while (!ast_safe_sleep(chan, 10000)); 00564 ast_moh_stop(chan); 00565 return -1; 00566 }
static int moh1_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 568 of file res_musiconhold.c.
References ast_log(), ast_moh_start(), ast_moh_stop(), ast_safe_sleep(), LOG_WARNING, and ast_channel::name.
Referenced by load_module().
00569 { 00570 int res; 00571 if (!data || !atoi(data)) { 00572 ast_log(LOG_WARNING, "WaitMusicOnHold requires an argument (number of seconds to wait)\n"); 00573 return -1; 00574 } 00575 if (ast_moh_start(chan, NULL)) { 00576 ast_log(LOG_WARNING, "Unable to start music on hold for %d seconds on channel %s\n", atoi(data), chan->name); 00577 return -1; 00578 } 00579 res = ast_safe_sleep(chan, atoi(data) * 1000); 00580 ast_moh_stop(chan); 00581 return res; 00582 }
static int moh2_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 584 of file res_musiconhold.c.
References ast_log(), ast_strlen_zero(), LOG_WARNING, and ast_channel::musicclass.
Referenced by load_module().
00585 { 00586 if (ast_strlen_zero(data)) { 00587 ast_log(LOG_WARNING, "SetMusicOnHold requires an argument (class)\n"); 00588 return -1; 00589 } 00590 strncpy(chan->musicclass, data, sizeof(chan->musicclass) - 1); 00591 return 0; 00592 }
static int moh3_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 594 of file res_musiconhold.c.
References ast_log(), ast_moh_start(), and LOG_NOTICE.
Referenced by load_module().
00595 { 00596 char *class = NULL; 00597 if (data && strlen(data)) 00598 class = data; 00599 if (ast_moh_start(chan, class)) 00600 ast_log(LOG_NOTICE, "Unable to start music on hold class '%s' on channel %s\n", class ? class : "default", chan->name); 00601 00602 return 0; 00603 }
static int moh4_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 605 of file res_musiconhold.c.
References ast_moh_stop().
Referenced by load_module().
00606 { 00607 ast_moh_stop(chan); 00608 00609 return 0; 00610 }
static void* moh_alloc | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 680 of file res_musiconhold.c.
References ast_codec2str(), ast_log(), ast_set_write_format(), ast_verbose(), LOG_WARNING, moh_release(), mohalloc(), ast_channel::name, option_verbose, VERBOSE_PREFIX_3, and ast_channel::writeformat.
00681 { 00682 struct mohdata *res; 00683 struct mohclass *class = params; 00684 00685 res = mohalloc(class); 00686 if (res) { 00687 res->origwfmt = chan->writeformat; 00688 if (ast_set_write_format(chan, class->format)) { 00689 ast_log(LOG_WARNING, "Unable to set channel '%s' to format '%s'\n", chan->name, ast_codec2str(class->format)); 00690 moh_release(NULL, res); 00691 res = NULL; 00692 } 00693 if (option_verbose > 2) 00694 ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on channel '%s'\n", class->name, chan->name); 00695 } 00696 return res; 00697 }
static struct mohclass* moh_class_malloc | ( | void | ) | [static] |
Definition at line 924 of file res_musiconhold.c.
References AST_FORMAT_SLINEAR, and malloc.
Referenced by load_moh_classes().
00925 { 00926 struct mohclass *class; 00927 00928 class = malloc(sizeof(struct mohclass)); 00929 00930 if (!class) 00931 return NULL; 00932 00933 memset(class, 0, sizeof(struct mohclass)); 00934 00935 class->format = AST_FORMAT_SLINEAR; 00936 00937 return class; 00938 }
static int moh_classes_show | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1163 of file res_musiconhold.c.
References ast_cli(), ast_getformatname(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_test_flag, MOH_CUSTOM, and mohclasses.
01164 { 01165 struct mohclass *class; 01166 01167 ast_mutex_lock(&moh_lock); 01168 for (class = mohclasses; class; class = class->next) { 01169 ast_cli(fd, "Class: %s\n", class->name); 01170 ast_cli(fd, "\tMode: %s\n", ast_strlen_zero(class->mode) ? "<none>" : class->mode); 01171 ast_cli(fd, "\tDirectory: %s\n", ast_strlen_zero(class->dir) ? "<none>" : class->dir); 01172 if (ast_test_flag(class, MOH_CUSTOM)) 01173 ast_cli(fd, "\tApplication: %s\n", ast_strlen_zero(class->args) ? "<none>" : class->args); 01174 ast_cli(fd, "\tFormat: %s\n", ast_getformatname(class->format)); 01175 } 01176 ast_mutex_unlock(&moh_lock); 01177 01178 return 0; 01179 }
static int moh_cli | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1132 of file res_musiconhold.c.
References ast_cli(), ast_moh_destroy(), load_moh_classes(), and moh_on_off().
01133 { 01134 int x; 01135 01136 moh_on_off(0); 01137 ast_moh_destroy(); 01138 x = load_moh_classes(1); 01139 moh_on_off(1); 01140 ast_cli(fd, "\n%d class%s reloaded.\n", x, x == 1 ? "" : "es"); 01141 return 0; 01142 }
static void* moh_files_alloc | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 283 of file res_musiconhold.c.
References ast_verbose(), moh_files_state::class, malloc, ast_channel::music_state, ast_channel::name, option_verbose, moh_files_state::origwfmt, VERBOSE_PREFIX_3, and ast_channel::writeformat.
00284 { 00285 struct moh_files_state *state; 00286 struct mohclass *class = params; 00287 int allocated = 0; 00288 00289 if (!chan->music_state && (state = malloc(sizeof(struct moh_files_state)))) { 00290 chan->music_state = state; 00291 allocated = 1; 00292 } else 00293 state = chan->music_state; 00294 00295 if (state) { 00296 if (allocated || state->class != class) { 00297 /* initialize */ 00298 memset(state, 0, sizeof(struct moh_files_state)); 00299 state->class = class; 00300 } 00301 00302 state->origwfmt = chan->writeformat; 00303 00304 if (option_verbose > 2) 00305 ast_verbose(VERBOSE_PREFIX_3 "Started music on hold, class '%s', on %s\n", class->name, chan->name); 00306 } 00307 00308 return chan->music_state; 00309 }
static int moh_files_generator | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 258 of file res_musiconhold.c.
References ast_frfree(), ast_log(), ast_write(), LOG_WARNING, moh_files_readframe(), ast_channel::music_state, ast_channel::name, moh_files_state::sample_queue, ast_frame::samples, and moh_files_state::samples.
00259 { 00260 struct moh_files_state *state = chan->music_state; 00261 struct ast_frame *f = NULL; 00262 int res = 0; 00263 00264 state->sample_queue += samples; 00265 00266 while (state->sample_queue > 0) { 00267 if ((f = moh_files_readframe(chan))) { 00268 state->samples += f->samples; 00269 res = ast_write(chan, f); 00270 state->sample_queue -= f->samples; 00271 ast_frfree(f); 00272 if (res < 0) { 00273 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno)); 00274 return -1; 00275 } 00276 } else 00277 return -1; 00278 } 00279 return res; 00280 }
static struct ast_frame* moh_files_readframe | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 246 of file res_musiconhold.c.
References ast_moh_files_next(), ast_readframe(), and ast_channel::stream.
Referenced by moh_files_generator().
00247 { 00248 struct ast_frame *f = NULL; 00249 00250 if (!(chan->stream && (f = ast_readframe(chan->stream)))) { 00251 if (!ast_moh_files_next(chan)) 00252 f = ast_readframe(chan->stream); 00253 } 00254 00255 return f; 00256 }
static void moh_files_release | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 178 of file res_musiconhold.c.
References ast_closestream(), ast_log(), ast_set_write_format(), ast_verbose(), LOG_WARNING, ast_channel::music_state, ast_channel::name, option_verbose, moh_files_state::origwfmt, moh_files_state::pos, moh_files_state::save_pos, ast_channel::stream, and VERBOSE_PREFIX_3.
00179 { 00180 struct moh_files_state *state = chan->music_state; 00181 00182 if (chan && state) { 00183 if (chan->stream) { 00184 ast_closestream(chan->stream); 00185 chan->stream = NULL; 00186 } 00187 if (option_verbose > 2) 00188 ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name); 00189 00190 if (state->origwfmt && ast_set_write_format(chan, state->origwfmt)) { 00191 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, state->origwfmt); 00192 } 00193 state->save_pos = state->pos + 1; 00194 } 00195 }
static int moh_generate | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 699 of file res_musiconhold.c.
References ast_codec_get_len(), ast_codec_get_samples(), AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), LOG_WARNING, moh, and ast_channel::name.
00700 { 00701 struct ast_frame f; 00702 struct mohdata *moh = data; 00703 short buf[1280 + AST_FRIENDLY_OFFSET / 2]; 00704 int res; 00705 00706 if (!moh->parent->pid) 00707 return -1; 00708 00709 len = ast_codec_get_len(moh->parent->format, samples); 00710 00711 if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) { 00712 ast_log(LOG_WARNING, "Only doing %d of %d requested bytes on %s\n", (int)sizeof(buf), len, chan->name); 00713 len = sizeof(buf) - AST_FRIENDLY_OFFSET; 00714 } 00715 res = read(moh->pipe[0], buf + AST_FRIENDLY_OFFSET/2, len); 00716 #if 0 00717 if (res != len) { 00718 ast_log(LOG_WARNING, "Read only %d of %d bytes: %s\n", res, len, strerror(errno)); 00719 } 00720 #endif 00721 if (res <= 0) 00722 return 0; 00723 00724 memset(&f, 0, sizeof(f)); 00725 00726 f.frametype = AST_FRAME_VOICE; 00727 f.subclass = moh->parent->format; 00728 f.mallocd = 0; 00729 f.datalen = res; 00730 f.data = buf + AST_FRIENDLY_OFFSET / 2; 00731 f.offset = AST_FRIENDLY_OFFSET; 00732 f.samples = ast_codec_get_samples(&f); 00733 00734 if (ast_write(chan, &f) < 0) { 00735 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno)); 00736 return -1; 00737 } 00738 00739 return 0; 00740 }
static void moh_on_off | ( | int | on | ) | [static] |
Definition at line 1117 of file res_musiconhold.c.
References ast_channel_walk_locked(), ast_deactivate_generator(), AST_FLAG_MOH, ast_mutex_unlock(), ast_test_flag, and local_ast_moh_start().
Referenced by moh_cli().
01118 { 01119 struct ast_channel *chan = NULL; 01120 01121 while ( (chan = ast_channel_walk_locked(chan)) != NULL) { 01122 if (ast_test_flag(chan, AST_FLAG_MOH)) { 01123 if (on) 01124 local_ast_moh_start(chan, NULL); 01125 else 01126 ast_deactivate_generator(chan); 01127 } 01128 ast_mutex_unlock(&chan->lock); 01129 } 01130 }
static int moh_register | ( | struct mohclass * | moh, | |
int | reload | |||
) | [static] |
Definition at line 807 of file res_musiconhold.c.
References ast_log(), ast_moh_free_class(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_set_flag, free, get_mohbyname(), LOG_WARNING, moh, MOH_CUSTOM, MOH_QUIET, MOH_RANDOMIZE, moh_scan_files(), MOH_SINGLE, mohclasses, and monmp3thread().
Referenced by load_moh_classes().
00808 { 00809 #ifdef ZAPATA_MOH 00810 int x; 00811 #endif 00812 ast_mutex_lock(&moh_lock); 00813 if (get_mohbyname(moh->name)) { 00814 if (reload) { 00815 ast_log(LOG_DEBUG, "Music on Hold class '%s' left alone from initial load.\n", moh->name); 00816 } else { 00817 ast_log(LOG_WARNING, "Music on Hold class '%s' already exists\n", moh->name); 00818 } 00819 free(moh); 00820 ast_mutex_unlock(&moh_lock); 00821 return -1; 00822 } 00823 ast_mutex_unlock(&moh_lock); 00824 00825 time(&moh->start); 00826 moh->start -= respawn_time; 00827 00828 if (!strcasecmp(moh->mode, "files")) { 00829 if (!moh_scan_files(moh)) { 00830 ast_moh_free_class(&moh); 00831 return -1; 00832 } 00833 if (strchr(moh->args, 'r')) 00834 ast_set_flag(moh, MOH_RANDOMIZE); 00835 } else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") || !strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") || !strcasecmp(moh->mode, "httpmp3") || !strcasecmp(moh->mode, "custom")) { 00836 00837 if (!strcasecmp(moh->mode, "custom")) 00838 ast_set_flag(moh, MOH_CUSTOM); 00839 else if (!strcasecmp(moh->mode, "mp3nb")) 00840 ast_set_flag(moh, MOH_SINGLE); 00841 else if (!strcasecmp(moh->mode, "quietmp3nb")) 00842 ast_set_flag(moh, MOH_SINGLE | MOH_QUIET); 00843 else if (!strcasecmp(moh->mode, "quietmp3")) 00844 ast_set_flag(moh, MOH_QUIET); 00845 00846 moh->srcfd = -1; 00847 #ifdef ZAPATA_MOH 00848 /* Open /dev/zap/pseudo for timing... Is 00849 there a better, yet reliable way to do this? */ 00850 moh->pseudofd = open("/dev/zap/pseudo", O_RDONLY); 00851 if (moh->pseudofd < 0) { 00852 ast_log(LOG_WARNING, "Unable to open pseudo channel for timing... Sound may be choppy.\n"); 00853 } else { 00854 x = 320; 00855 ioctl(moh->pseudofd, ZT_SET_BLOCKSIZE, &x); 00856 } 00857 #else 00858 moh->pseudofd = -1; 00859 #endif 00860 if (ast_pthread_create(&moh->thread, NULL, monmp3thread, moh)) { 00861 ast_log(LOG_WARNING, "Unable to create moh...\n"); 00862 if (moh->pseudofd > -1) 00863 close(moh->pseudofd); 00864 ast_moh_free_class(&moh); 00865 return -1; 00866 } 00867 } else { 00868 ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", moh->mode); 00869 ast_moh_free_class(&moh); 00870 return -1; 00871 } 00872 ast_mutex_lock(&moh_lock); 00873 moh->next = mohclasses; 00874 mohclasses = moh; 00875 ast_mutex_unlock(&moh_lock); 00876 return 0; 00877 }
static void moh_release | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 648 of file res_musiconhold.c.
References ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_write_format(), ast_verbose(), free, LOG_WARNING, moh, ast_channel::name, option_verbose, and VERBOSE_PREFIX_3.
Referenced by moh_alloc().
00649 { 00650 struct mohdata *moh = data, *prev, *cur; 00651 int oldwfmt; 00652 ast_mutex_lock(&moh_lock); 00653 /* Unlink */ 00654 prev = NULL; 00655 cur = moh->parent->members; 00656 while (cur) { 00657 if (cur == moh) { 00658 if (prev) 00659 prev->next = cur->next; 00660 else 00661 moh->parent->members = cur->next; 00662 break; 00663 } 00664 prev = cur; 00665 cur = cur->next; 00666 } 00667 ast_mutex_unlock(&moh_lock); 00668 close(moh->pipe[0]); 00669 close(moh->pipe[1]); 00670 oldwfmt = moh->origwfmt; 00671 free(moh); 00672 if (chan) { 00673 if (oldwfmt && ast_set_write_format(chan, oldwfmt)) 00674 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(oldwfmt)); 00675 if (option_verbose > 2) 00676 ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name); 00677 } 00678 }
static int moh_scan_files | ( | struct mohclass * | class | ) | [static] |
Definition at line 749 of file res_musiconhold.c.
References ast_log(), mohclass::dir, mohclass::filearray, LOG_WARNING, MAX_MOHFILE_LEN, MAX_MOHFILES, and mohclass::total_files.
Referenced by init_classes(), and moh_register().
00749 { 00750 00751 DIR *files_DIR; 00752 struct dirent *files_dirent; 00753 char path[512]; 00754 char filepath[MAX_MOHFILE_LEN]; 00755 char *ext; 00756 struct stat statbuf; 00757 int dirnamelen; 00758 int i; 00759 00760 files_DIR = opendir(class->dir); 00761 if (!files_DIR) { 00762 ast_log(LOG_WARNING, "Cannot open dir %s or dir does not exist", class->dir); 00763 return -1; 00764 } 00765 00766 class->total_files = 0; 00767 dirnamelen = strlen(class->dir) + 2; 00768 getcwd(path, 512); 00769 chdir(class->dir); 00770 memset(class->filearray, 0, MAX_MOHFILES*MAX_MOHFILE_LEN); 00771 while ((files_dirent = readdir(files_DIR))) { 00772 if ((strlen(files_dirent->d_name) < 4) || ((strlen(files_dirent->d_name) + dirnamelen) >= MAX_MOHFILE_LEN)) 00773 continue; 00774 00775 snprintf(filepath, MAX_MOHFILE_LEN, "%s/%s", class->dir, files_dirent->d_name); 00776 00777 if (stat(filepath, &statbuf)) 00778 continue; 00779 00780 if (!S_ISREG(statbuf.st_mode)) 00781 continue; 00782 00783 if ((ext = strrchr(filepath, '.'))) { 00784 *ext = '\0'; 00785 ext++; 00786 } 00787 00788 /* if the file is present in multiple formats, ensure we only put it into the list once */ 00789 for (i = 0; i < class->total_files; i++) 00790 if (!strcmp(filepath, class->filearray[i])) 00791 break; 00792 00793 if (i == class->total_files) 00794 strcpy(class->filearray[class->total_files++], filepath); 00795 00796 /* If the new total files is equal to the maximum allowed, stop adding new ones */ 00797 if (class->total_files == MAX_MOHFILES) 00798 break; 00799 00800 } 00801 00802 closedir(files_DIR); 00803 chdir(path); 00804 return class->total_files; 00805 }
Definition at line 624 of file res_musiconhold.c.
References ast_log(), free, LOG_WARNING, malloc, mohclass::members, moh, and mohdata::pipe.
Referenced by moh_alloc().
00625 { 00626 struct mohdata *moh; 00627 long flags; 00628 moh = malloc(sizeof(struct mohdata)); 00629 if (!moh) 00630 return NULL; 00631 memset(moh, 0, sizeof(struct mohdata)); 00632 if (pipe(moh->pipe)) { 00633 ast_log(LOG_WARNING, "Failed to create pipe: %s\n", strerror(errno)); 00634 free(moh); 00635 return NULL; 00636 } 00637 /* Make entirely non-blocking */ 00638 flags = fcntl(moh->pipe[0], F_GETFL); 00639 fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK); 00640 flags = fcntl(moh->pipe[1], F_GETFL); 00641 fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK); 00642 moh->parent = cl; 00643 moh->next = cl->members; 00644 cl->members = moh; 00645 return moh; 00646 }
static void* monmp3thread | ( | void * | data | ) | [static] |
Definition at line 474 of file res_musiconhold.c.
References ast_codec_get_len(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_tvadd(), LOG_NOTICE, LOG_WARNING, moh, MOH_MS_INTERVAL, option_debug, and spawn_mp3().
Referenced by moh_register().
00475 { 00476 #define MOH_MS_INTERVAL 100 00477 00478 struct mohclass *class = data; 00479 struct mohdata *moh; 00480 char buf[8192]; 00481 short sbuf[8192]; 00482 int res, res2; 00483 int len; 00484 struct timeval tv, tv_tmp; 00485 00486 tv.tv_sec = 0; 00487 tv.tv_usec = 0; 00488 for(;/* ever */;) { 00489 pthread_testcancel(); 00490 /* Spawn mp3 player if it's not there */ 00491 if (class->srcfd < 0) { 00492 if ((class->srcfd = spawn_mp3(class)) < 0) { 00493 ast_log(LOG_WARNING, "Unable to spawn mp3player\n"); 00494 /* Try again later */ 00495 sleep(500); 00496 pthread_testcancel(); 00497 } 00498 } 00499 if (class->pseudofd > -1) { 00500 /* Pause some amount of time */ 00501 res = read(class->pseudofd, buf, sizeof(buf)); 00502 pthread_testcancel(); 00503 } else { 00504 long delta; 00505 /* Reliable sleep */ 00506 tv_tmp = ast_tvnow(); 00507 if (ast_tvzero(tv)) 00508 tv = tv_tmp; 00509 delta = ast_tvdiff_ms(tv_tmp, tv); 00510 if (delta < MOH_MS_INTERVAL) { /* too early */ 00511 tv = ast_tvadd(tv, ast_samp2tv(MOH_MS_INTERVAL, 1000)); /* next deadline */ 00512 usleep(1000 * (MOH_MS_INTERVAL - delta)); 00513 pthread_testcancel(); 00514 } else { 00515 ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n"); 00516 tv = tv_tmp; 00517 } 00518 res = 8 * MOH_MS_INTERVAL; /* 8 samples per millisecond */ 00519 } 00520 if (!class->members) 00521 continue; 00522 /* Read mp3 audio */ 00523 len = ast_codec_get_len(class->format, res); 00524 00525 if ((res2 = read(class->srcfd, sbuf, len)) != len) { 00526 if (!res2) { 00527 close(class->srcfd); 00528 class->srcfd = -1; 00529 pthread_testcancel(); 00530 if (class->pid) { 00531 kill(class->pid, SIGHUP); 00532 usleep(100000); 00533 kill(class->pid, SIGTERM); 00534 usleep(100000); 00535 kill(class->pid, SIGKILL); 00536 class->pid = 0; 00537 } 00538 } else 00539 ast_log(LOG_DEBUG, "Read %d bytes of audio while expecting %d\n", res2, len); 00540 continue; 00541 } 00542 pthread_testcancel(); 00543 ast_mutex_lock(&moh_lock); 00544 moh = class->members; 00545 while (moh) { 00546 /* Write data */ 00547 if ((res = write(moh->pipe[1], sbuf, res2)) != res2) 00548 if (option_debug) 00549 ast_log(LOG_DEBUG, "Only wrote %d of %d bytes to pipe\n", res, res2); 00550 moh = moh->next; 00551 } 00552 ast_mutex_unlock(&moh_lock); 00553 } 00554 return NULL; 00555 }
int reload | ( | void | ) |
Reload stuff.
This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.
Definition at line 1229 of file res_musiconhold.c.
References ast_install_music_functions(), init_classes(), local_ast_moh_cleanup(), local_ast_moh_start(), and local_ast_moh_stop().
01230 { 01231 if (init_classes(1)) 01232 ast_install_music_functions(local_ast_moh_start, local_ast_moh_stop, local_ast_moh_cleanup); 01233 01234 return 0; 01235 }
static int spawn_mp3 | ( | struct mohclass * | class | ) | [static] |
Definition at line 318 of file res_musiconhold.c.
References mohclass::args, ast_log(), ast_set_priority(), ast_strlen_zero(), ast_test_flag, mohclass::dir, LOCAL_MPG_123, LOG_WARNING, MAX_MP3S, MOH_CUSTOM, MOH_QUIET, MOH_SINGLE, MPG_123, option_highpriority, mohclass::pid, and mohclass::start.
Referenced by monmp3thread().
00319 { 00320 int fds[2]; 00321 int files = 0; 00322 char fns[MAX_MP3S][80]; 00323 char *argv[MAX_MP3S + 50]; 00324 char xargs[256]; 00325 char *argptr; 00326 int argc = 0; 00327 DIR *dir = NULL; 00328 struct dirent *de; 00329 00330 00331 if (!strcasecmp(class->dir, "nodir")) { 00332 files = 1; 00333 } else { 00334 dir = opendir(class->dir); 00335 if (!dir && !strstr(class->dir,"http://") && !strstr(class->dir,"HTTP://")) { 00336 ast_log(LOG_WARNING, "%s is not a valid directory\n", class->dir); 00337 return -1; 00338 } 00339 } 00340 00341 if (!ast_test_flag(class, MOH_CUSTOM)) { 00342 argv[argc++] = "mpg123"; 00343 argv[argc++] = "-q"; 00344 argv[argc++] = "-s"; 00345 argv[argc++] = "--mono"; 00346 argv[argc++] = "-r"; 00347 argv[argc++] = "8000"; 00348 00349 if (!ast_test_flag(class, MOH_SINGLE)) { 00350 argv[argc++] = "-b"; 00351 argv[argc++] = "2048"; 00352 } 00353 00354 argv[argc++] = "-f"; 00355 00356 if (ast_test_flag(class, MOH_QUIET)) 00357 argv[argc++] = "4096"; 00358 else 00359 argv[argc++] = "8192"; 00360 00361 /* Look for extra arguments and add them to the list */ 00362 strncpy(xargs, class->args, sizeof(xargs) - 1); 00363 argptr = xargs; 00364 while (!ast_strlen_zero(argptr)) { 00365 argv[argc++] = argptr; 00366 argptr = strchr(argptr, ','); 00367 if (argptr) { 00368 *argptr = '\0'; 00369 argptr++; 00370 } 00371 } 00372 } else { 00373 /* Format arguments for argv vector */ 00374 strncpy(xargs, class->args, sizeof(xargs) - 1); 00375 argptr = xargs; 00376 while (!ast_strlen_zero(argptr)) { 00377 argv[argc++] = argptr; 00378 argptr = strchr(argptr, ' '); 00379 if (argptr) { 00380 *argptr = '\0'; 00381 argptr++; 00382 } 00383 } 00384 } 00385 00386 00387 if (strstr(class->dir,"http://") || strstr(class->dir,"HTTP://")) { 00388 strncpy(fns[files], class->dir, sizeof(fns[files]) - 1); 00389 argv[argc++] = fns[files]; 00390 files++; 00391 } else if (dir) { 00392 while ((de = readdir(dir)) && (files < MAX_MP3S)) { 00393 if ((strlen(de->d_name) > 3) && 00394 ((ast_test_flag(class, MOH_CUSTOM) && 00395 (!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".raw") || 00396 !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".sln"))) || 00397 !strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3"))) { 00398 strncpy(fns[files], de->d_name, sizeof(fns[files]) - 1); 00399 argv[argc++] = fns[files]; 00400 files++; 00401 } 00402 } 00403 } 00404 argv[argc] = NULL; 00405 if (dir) { 00406 closedir(dir); 00407 } 00408 if (pipe(fds)) { 00409 ast_log(LOG_WARNING, "Pipe failed\n"); 00410 return -1; 00411 } 00412 #if 0 00413 printf("%d files total, %d args total\n", files, argc); 00414 { 00415 int x; 00416 for (x=0;argv[x];x++) 00417 printf("arg%d: %s\n", x, argv[x]); 00418 } 00419 #endif 00420 if (!files) { 00421 ast_log(LOG_WARNING, "Found no files in '%s'\n", class->dir); 00422 close(fds[0]); 00423 close(fds[1]); 00424 return -1; 00425 } 00426 if (time(NULL) - class->start < respawn_time) { 00427 sleep(respawn_time - (time(NULL) - class->start)); 00428 } 00429 time(&class->start); 00430 class->pid = fork(); 00431 if (class->pid < 0) { 00432 close(fds[0]); 00433 close(fds[1]); 00434 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno)); 00435 return -1; 00436 } 00437 if (!class->pid) { 00438 int x; 00439 00440 if (option_highpriority) 00441 ast_set_priority(0); 00442 00443 close(fds[0]); 00444 /* Stdout goes to pipe */ 00445 dup2(fds[1], STDOUT_FILENO); 00446 /* Close unused file descriptors */ 00447 for (x=3;x<8192;x++) { 00448 if (-1 != fcntl(x, F_GETFL)) { 00449 close(x); 00450 } 00451 } 00452 /* Child */ 00453 chdir(class->dir); 00454 if (ast_test_flag(class, MOH_CUSTOM)) { 00455 execv(argv[0], argv); 00456 } else { 00457 /* Default install is /usr/local/bin */ 00458 execv(LOCAL_MPG_123, argv); 00459 /* Many places have it in /usr/bin */ 00460 execv(MPG_123, argv); 00461 /* Check PATH as a last-ditch effort */ 00462 execvp("mpg123", argv); 00463 } 00464 ast_log(LOG_WARNING, "Exec failed: %s\n", strerror(errno)); 00465 close(fds[1]); 00466 exit(1); 00467 } else { 00468 /* Parent */ 00469 close(fds[1]); 00470 } 00471 return fds[0]; 00472 }
int unload_module | ( | void | ) |
Cleanup all module structures, sockets, etc.
Standard module functions ...
Definition at line 1237 of file res_musiconhold.c.
int usecount | ( | void | ) |
Provides a usecount.
This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 1247 of file res_musiconhold.c.
References STANDARD_USECOUNT.
01248 { 01249 /* Never allow Music On Hold to be unloaded 01250 unresolve needed symbols in the dialer */ 01251 #if 0 01252 int res; 01253 STANDARD_USECOUNT(res); 01254 return res; 01255 #else 01256 return 1; 01257 #endif 01258 }
char* app0 = "MusicOnHold" [static] |
Definition at line 70 of file res_musiconhold.c.
char* app1 = "WaitMusicOnHold" [static] |
Definition at line 71 of file res_musiconhold.c.
char* app2 = "SetMusicOnHold" [static] |
Definition at line 72 of file res_musiconhold.c.
char* app3 = "StartMusicOnHold" [static] |
Definition at line 73 of file res_musiconhold.c.
char* app4 = "StopMusicOnHold" [static] |
Definition at line 74 of file res_musiconhold.c.
struct ast_cli_entry cli_moh = { { "moh", "reload"}, moh_cli, "Music On Hold", "Music On Hold", NULL} [static] |
struct ast_cli_entry cli_moh_classes_show = { { "moh", "classes", "show"}, moh_classes_show, "List MOH classes", "Lists all MOH classes", NULL} [static] |
struct ast_cli_entry cli_moh_files_show = { { "moh", "files", "show"}, cli_files_show, "List MOH file-based classes", "Lists all loaded file-based MOH classes and their files", NULL} [static] |
char* descrip0 [static] |
Definition at line 82 of file res_musiconhold.c.
char* descrip1 [static] |
Initial value:
"WaitMusicOnHold(delay): " "Plays hold music specified number of seconds. Returns 0 when\n" "done, or -1 on hangup. If no hold music is available, the delay will\n" "still occur with no sound.\n"
Definition at line 89 of file res_musiconhold.c.
char* descrip2 [static] |
Initial value:
"SetMusicOnHold(class): " "Sets the default class for music on hold for a given channel. When\n" "music on hold is activated, this class will be used to select which\n" "music is played.\n"
Definition at line 94 of file res_musiconhold.c.
char* descrip3 [static] |
Initial value:
"StartMusicOnHold(class): " "Starts playing music on hold, uses default music class for channel.\n" "Starts playing music specified by class. If omitted, the default\n" "music source for the channel will be used. Always returns 0.\n"
Definition at line 99 of file res_musiconhold.c.
char* descrip4 [static] |
Initial value:
"StopMusicOnHold: " "Stops playing music on hold.\n"
Definition at line 104 of file res_musiconhold.c.
struct ast_generator moh_file_stream [static] |
struct mohclass* mohclasses [static] |
Definition at line 150 of file res_musiconhold.c.
Referenced by ast_moh_destroy(), cli_files_show(), get_mohbyname(), init_classes(), moh_classes_show(), and moh_register().
struct ast_generator mohgen [static] |
int respawn_time = 20 [static] |
Definition at line 107 of file res_musiconhold.c.
char* synopsis0 = "Play Music On Hold indefinitely" [static] |
Definition at line 76 of file res_musiconhold.c.
char* synopsis1 = "Wait, playing Music On Hold" [static] |
Definition at line 77 of file res_musiconhold.c.
char* synopsis2 = "Set default Music On Hold class" [static] |
Definition at line 78 of file res_musiconhold.c.
char* synopsis3 = "Play Music On Hold" [static] |
Definition at line 79 of file res_musiconhold.c.
char* synopsis4 = "Stop Playing Music On Hold" [static] |
Definition at line 80 of file res_musiconhold.c.