diff --git a/apps/Makefile b/apps/Makefile index bdf491e35d1d747ca24dab2a616d076ff5cde867..9ac9736767584927ce6ee1e5a8e587a51e43e55f 100755 --- a/apps/Makefile +++ b/apps/Makefile @@ -17,7 +17,7 @@ USE_POSTGRES_VM_INTERFACE=0 #APPS=app_dial.so app_playback.so app_directory.so app_intercom.so app_mp3.so APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\ app_system.so app_echo.so app_record.so app_image.so app_url.so app_disa.so \ - app_agi.so app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \ + app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \ app_zapateller.so app_setcallerid.so app_festival.so \ app_queue.so app_senddtmf.so app_parkandannounce.so app_striplsd.so \ app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \ diff --git a/configs/musiconhold.conf.sample b/configs/musiconhold.conf.sample index 4cb296d9c6cbe2a790b8dbd50e37e4708674cdc3..991ccae9ec23aecb1a2b75b41758897054855bed 100755 --- a/configs/musiconhold.conf.sample +++ b/configs/musiconhold.conf.sample @@ -7,3 +7,5 @@ ;random => quietmp3:/var/lib/asterisk/mohmp3,-z ;unbuffered => mp3nb:/var/lib/asterisk/mohmp3 ;quietunbuf => quietmp3nb:/var/lib/asterisk/mohmp3 +; Note that the custom mode cannot handle escaped parameters (specifically embedded spaces) +;manual => custom:/var/lib/asterisk/mohmp3,/usr/bin/mpg123 -q -r 8000 -f 8192 -b 2048 --mono -s diff --git a/include/asterisk/agi.h b/include/asterisk/agi.h new file mode 100755 index 0000000000000000000000000000000000000000..25899d58cbe8e9f4aaefeb43b70f09a5d04bc815 --- /dev/null +++ b/include/asterisk/agi.h @@ -0,0 +1,48 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * AGI Extension interfaces + * + * Copyright (C) 1999, Mark Spencer + * + * Mark Spencer <markster@linux-support.net> + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#ifndef _ASTERISK_AGI_H +#define _ASTERISK_AGI_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +typedef struct agi_state { + int fd; /* FD for general output */ + int audio; /* FD for audio output */ + int ctrl; /* FD for input control */ +} AGI; + +typedef struct agi_command { + /* Null terminated list of the words of the command */ + char *cmda[AST_MAX_CMD_LEN]; + /* Handler for the command (channel, AGI state, # of arguments, argument list). + Returns RESULT_SHOWUSAGE for improper arguments */ + int (*handler)(struct ast_channel *chan, AGI *agi, int argc, char *argv[]); + /* Summary of the command (< 60 characters) */ + char *summary; + /* Detailed usage information */ + char *usage; + struct agi_command *next; +} agi_command; + + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + + + +#endif diff --git a/res/Makefile b/res/Makefile index 302c3499f6de825765bfd07cf51b62a86fc58630..afd3af93719b58a9d83c08883fa2c298490cc720 100755 --- a/res/Makefile +++ b/res/Makefile @@ -11,7 +11,8 @@ # the GNU General Public License # -MODS=res_adsi.so res_parking.so res_crypto.so res_musiconhold.so res_indications.so res_monitor.so +MODS=res_adsi.so res_parking.so res_crypto.so res_musiconhold.so res_indications.so res_monitor.so \ + res_agi.so MODS+=$(shell if [ -f "/usr/include/odbcinst.h" ]; then echo "res_odbc.so res_config_odbc.so"; fi) MODS+=$(shell if [ -f "/usr/local/include/odbcinst.h" ]; then echo "res_odbc.so res_config_odbc.so"; fi) MODS+=$(shell if [ -f "/usr/include/osp/osp.h" ]; then echo "res_osp.so"; fi) @@ -30,6 +31,7 @@ OSPLIB=/usr/lib/libosp.a all: depend $(MODS) install: all + rm -f $(DESTDIR)$(MODULES_DIR)/app_agi.so for x in $(MODS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done res_crypto.so: res_crypto.o diff --git a/apps/app_agi.c b/res/res_agi.c similarity index 98% rename from apps/app_agi.c rename to res/res_agi.c index 64790237c08cc2a7f67c2e9b5d5067734f48f08f..ba4ab0ec29704af9efcb0570167a20fee401974b 100755 --- a/apps/app_agi.c +++ b/res/res_agi.c @@ -38,32 +38,16 @@ #include <asterisk/musiconhold.h> #include <asterisk/utils.h> #include <asterisk/lock.h> +#include <asterisk/agi.h> #include "../asterisk.h" #include "../astconf.h" #define MAX_ARGS 128 +#define MAX_COMMANDS 128 /* Recycle some stuff from the CLI interface */ #define fdprintf ast_cli -typedef struct agi_state { - int fd; /* FD for general output */ - int audio; /* FD for audio output */ - int ctrl; /* FD for input control */ -} AGI; - -typedef struct agi_command { - /* Null terminated list of the words of the command */ - char *cmda[AST_MAX_CMD_LEN]; - /* Handler for the command (channel, AGI state, # of arguments, argument list). - Returns RESULT_SHOWUSAGE for improper arguments */ - int (*handler)(struct ast_channel *chan, AGI *agi, int argc, char *argv[]); - /* Summary of the command (< 60 characters) */ - char *summary; - /* Detailed usage information */ - char *usage; -} agi_command; - static char *tdesc = "Asterisk Gateway Interface (AGI)"; static char *app = "AGI"; @@ -1102,7 +1086,7 @@ static char usage_noop[] = " Usage: NOOP\n" " Does nothing.\n"; -static agi_command commands[] = { +static agi_command commands[MAX_COMMANDS] = { { { "answer", NULL }, handle_answer, "Asserts answer", usage_answer }, { { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit }, { { "send", "text", NULL }, handle_sendtext, "Sends text to channels supporting it", usage_sendtext }, @@ -1112,7 +1096,7 @@ static agi_command commands[] = { { { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage }, { { "say", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits }, { { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber }, - { { "say", "phonetic", NULL }, handle_sayphonetic, "Says a given character string with phonetics", usage_sayphonetic }, + { { "say", "phonetic", NULL }, handle_sayphonetic, "Says a given character string with phonetics", usage_sayphonetic }, { { "say", "time", NULL }, handle_saytime, "Says a given time", usage_saytime }, { { "get", "data", NULL }, handle_getdata, "Gets data on a channel", usage_getdata }, { { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext }, @@ -1159,6 +1143,7 @@ static int help_workhorse(int fd, char *match[]) if (match) join(matchstr, sizeof(matchstr), match); for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) { + if (!commands[x].cmda[0]) break; e = &commands[x]; if (e) join(fullcmd, sizeof(fullcmd), e->cmda); @@ -1181,6 +1166,7 @@ static agi_command *find_command(char *cmds[], int exact) int y; int match; for (x=0;x < sizeof(commands) / sizeof(commands[0]);x++) { + if (!commands[x].cmda[0]) break; /* start optimistic */ match = 1; for (y=0;match && cmds[y]; y++) { @@ -1430,6 +1416,7 @@ static int handle_dumpagihtml(int fd, int argc, char *argv[]) { for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) { char *stringp=NULL; + if (!commands[x].cmda[0]) break; e = &commands[x]; if (e) join(fullcmd, sizeof(fullcmd), e->cmda); diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index b446551c1d12381ccb9b4aab88fb0ad3cf6aa3c8..647956532afced286d5a61d33f6e4fe093a33648 100755 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -79,6 +79,7 @@ struct mohclass { int pid; /* PID of mpg123 */ int quiet; int single; + int custom; pthread_t thread; struct mohdata *members; /* Source of audio */ @@ -119,34 +120,49 @@ static int spawn_mp3(struct mohclass *class) ast_log(LOG_WARNING, "%s is not a valid directory\n", class->dir); return -1; } - argv[argc++] = "mpg123"; - argv[argc++] = "-q"; - argv[argc++] = "-s"; - argv[argc++] = "--mono"; - argv[argc++] = "-r"; - argv[argc++] = "8000"; - - if (!class->single) { - argv[argc++] = "-b"; - argv[argc++] = "2048"; - } - argv[argc++] = "-f"; - - if (class->quiet) { - argv[argc++] = "4096"; - } else - argv[argc++] = "8192"; - - /* Look for extra arguments and add them to the list */ - strncpy(xargs, class->miscargs, sizeof(xargs) - 1); - argptr = xargs; - while(argptr && !ast_strlen_zero(argptr)) { - argv[argc++] = argptr; - argptr = strchr(argptr, ','); - if (argptr) { - *argptr = '\0'; - argptr++; + if (!class->custom) { + argv[argc++] = "mpg123"; + argv[argc++] = "-q"; + argv[argc++] = "-s"; + argv[argc++] = "--mono"; + argv[argc++] = "-r"; + argv[argc++] = "8000"; + + if (!class->single) { + argv[argc++] = "-b"; + argv[argc++] = "2048"; + } + + argv[argc++] = "-f"; + + if (class->quiet) + argv[argc++] = "4096"; + else + argv[argc++] = "8192"; + + /* Look for extra arguments and add them to the list */ + strncpy(xargs, class->miscargs, sizeof(xargs) - 1); + argptr = xargs; + while(argptr && !ast_strlen_zero(argptr)) { + argv[argc++] = argptr; + argptr = strchr(argptr, ','); + if (argptr) { + *argptr = '\0'; + argptr++; + } + } + } else { + /* Format arguments for argv vector */ + strncpy(xargs, class->miscargs, sizeof(xargs) - 1); + argptr = xargs; + while(argptr && !ast_strlen_zero(argptr)) { + argv[argc++] = argptr; + argptr = strchr(argptr, ' '); + if (argptr) { + *argptr = '\0'; + argptr++; + } } } @@ -195,12 +211,16 @@ static int spawn_mp3(struct mohclass *class) close(x); /* Child */ chdir(class->dir); - /* Default install is /usr/local/bin */ - execv(LOCAL_MPG_123, argv); - /* Many places have it in /usr/bin */ - execv(MPG_123, argv); - /* Check PATH as a last-ditch effort */ - execvp("mpg123", argv); + if(class->custom) { + execv(argv[0], argv); + } else { + /* Default install is /usr/local/bin */ + execv(LOCAL_MPG_123, argv); + /* Many places have it in /usr/bin */ + execv(MPG_123, argv); + /* Check PATH as a last-ditch effort */ + execvp("mpg123", argv); + } ast_log(LOG_WARNING, "Exec failed: %s\n", strerror(errno)); close(fds[1]); exit(1); @@ -506,7 +526,9 @@ static int moh_register(char *classname, char *mode, char *param, char *miscargs strncpy(moh->class, classname, sizeof(moh->class) - 1); if (miscargs) strncpy(moh->miscargs, miscargs, sizeof(moh->miscargs) - 1); - if (!strcasecmp(mode, "mp3") || !strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb") || !strcasecmp(mode, "httpmp3")) { + if (!strcasecmp(mode, "mp3") || !strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb") || !strcasecmp(mode, "httpmp3") || !strcasecmp(mode, "custom")) { + if (!strcasecmp(mode, "custom")) + moh->custom = 1; if (!strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3nb")) moh->single = 1; if (!strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb"))