mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-29 18:19:30 +00:00
Merge musiconhold stuff (bug #2027), restructure AGI to eventually support registration
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3460 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -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_directory.so app_intercom.so app_mp3.so
|
||||||
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.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_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_zapateller.so app_setcallerid.so app_festival.so \
|
||||||
app_queue.so app_senddtmf.so app_parkandannounce.so app_striplsd.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 \
|
app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \
|
||||||
|
@@ -7,3 +7,5 @@
|
|||||||
;random => quietmp3:/var/lib/asterisk/mohmp3,-z
|
;random => quietmp3:/var/lib/asterisk/mohmp3,-z
|
||||||
;unbuffered => mp3nb:/var/lib/asterisk/mohmp3
|
;unbuffered => mp3nb:/var/lib/asterisk/mohmp3
|
||||||
;quietunbuf => quietmp3nb:/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
|
||||||
|
48
include/asterisk/agi.h
Executable file
48
include/asterisk/agi.h
Executable file
@@ -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
|
@@ -11,7 +11,8 @@
|
|||||||
# the GNU General Public License
|
# 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/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/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)
|
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)
|
all: depend $(MODS)
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
|
rm -f $(DESTDIR)$(MODULES_DIR)/app_agi.so
|
||||||
for x in $(MODS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
|
for x in $(MODS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
|
||||||
|
|
||||||
res_crypto.so: res_crypto.o
|
res_crypto.so: res_crypto.o
|
||||||
|
@@ -38,32 +38,16 @@
|
|||||||
#include <asterisk/musiconhold.h>
|
#include <asterisk/musiconhold.h>
|
||||||
#include <asterisk/utils.h>
|
#include <asterisk/utils.h>
|
||||||
#include <asterisk/lock.h>
|
#include <asterisk/lock.h>
|
||||||
|
#include <asterisk/agi.h>
|
||||||
#include "../asterisk.h"
|
#include "../asterisk.h"
|
||||||
#include "../astconf.h"
|
#include "../astconf.h"
|
||||||
|
|
||||||
#define MAX_ARGS 128
|
#define MAX_ARGS 128
|
||||||
|
#define MAX_COMMANDS 128
|
||||||
|
|
||||||
/* Recycle some stuff from the CLI interface */
|
/* Recycle some stuff from the CLI interface */
|
||||||
#define fdprintf ast_cli
|
#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 *tdesc = "Asterisk Gateway Interface (AGI)";
|
||||||
|
|
||||||
static char *app = "AGI";
|
static char *app = "AGI";
|
||||||
@@ -1102,7 +1086,7 @@ static char usage_noop[] =
|
|||||||
" Usage: NOOP\n"
|
" Usage: NOOP\n"
|
||||||
" Does nothing.\n";
|
" Does nothing.\n";
|
||||||
|
|
||||||
static agi_command commands[] = {
|
static agi_command commands[MAX_COMMANDS] = {
|
||||||
{ { "answer", NULL }, handle_answer, "Asserts answer", usage_answer },
|
{ { "answer", NULL }, handle_answer, "Asserts answer", usage_answer },
|
||||||
{ { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit },
|
{ { "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 },
|
{ { "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 },
|
{ { "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", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits },
|
||||||
{ { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber },
|
{ { "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 },
|
{ { "say", "time", NULL }, handle_saytime, "Says a given time", usage_saytime },
|
||||||
{ { "get", "data", NULL }, handle_getdata, "Gets data on a channel", usage_getdata },
|
{ { "get", "data", NULL }, handle_getdata, "Gets data on a channel", usage_getdata },
|
||||||
{ { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext },
|
{ { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext },
|
||||||
@@ -1159,6 +1143,7 @@ static int help_workhorse(int fd, char *match[])
|
|||||||
if (match)
|
if (match)
|
||||||
join(matchstr, sizeof(matchstr), match);
|
join(matchstr, sizeof(matchstr), match);
|
||||||
for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
|
for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
|
||||||
|
if (!commands[x].cmda[0]) break;
|
||||||
e = &commands[x];
|
e = &commands[x];
|
||||||
if (e)
|
if (e)
|
||||||
join(fullcmd, sizeof(fullcmd), e->cmda);
|
join(fullcmd, sizeof(fullcmd), e->cmda);
|
||||||
@@ -1181,6 +1166,7 @@ static agi_command *find_command(char *cmds[], int exact)
|
|||||||
int y;
|
int y;
|
||||||
int match;
|
int match;
|
||||||
for (x=0;x < sizeof(commands) / sizeof(commands[0]);x++) {
|
for (x=0;x < sizeof(commands) / sizeof(commands[0]);x++) {
|
||||||
|
if (!commands[x].cmda[0]) break;
|
||||||
/* start optimistic */
|
/* start optimistic */
|
||||||
match = 1;
|
match = 1;
|
||||||
for (y=0;match && cmds[y]; y++) {
|
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++) {
|
for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
|
||||||
char *stringp=NULL;
|
char *stringp=NULL;
|
||||||
|
if (!commands[x].cmda[0]) break;
|
||||||
e = &commands[x];
|
e = &commands[x];
|
||||||
if (e)
|
if (e)
|
||||||
join(fullcmd, sizeof(fullcmd), e->cmda);
|
join(fullcmd, sizeof(fullcmd), e->cmda);
|
@@ -79,6 +79,7 @@ struct mohclass {
|
|||||||
int pid; /* PID of mpg123 */
|
int pid; /* PID of mpg123 */
|
||||||
int quiet;
|
int quiet;
|
||||||
int single;
|
int single;
|
||||||
|
int custom;
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
struct mohdata *members;
|
struct mohdata *members;
|
||||||
/* Source of audio */
|
/* 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);
|
ast_log(LOG_WARNING, "%s is not a valid directory\n", class->dir);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
argv[argc++] = "mpg123";
|
|
||||||
argv[argc++] = "-q";
|
|
||||||
argv[argc++] = "-s";
|
|
||||||
argv[argc++] = "--mono";
|
|
||||||
argv[argc++] = "-r";
|
|
||||||
argv[argc++] = "8000";
|
|
||||||
|
|
||||||
if (!class->single) {
|
if (!class->custom) {
|
||||||
argv[argc++] = "-b";
|
argv[argc++] = "mpg123";
|
||||||
argv[argc++] = "2048";
|
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";
|
argv[argc++] = "-f";
|
||||||
|
|
||||||
if (class->quiet) {
|
|
||||||
argv[argc++] = "4096";
|
|
||||||
} else
|
|
||||||
argv[argc++] = "8192";
|
|
||||||
|
|
||||||
/* Look for extra arguments and add them to the list */
|
if (class->quiet)
|
||||||
strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
|
argv[argc++] = "4096";
|
||||||
argptr = xargs;
|
else
|
||||||
while(argptr && !ast_strlen_zero(argptr)) {
|
argv[argc++] = "8192";
|
||||||
argv[argc++] = argptr;
|
|
||||||
argptr = strchr(argptr, ',');
|
/* Look for extra arguments and add them to the list */
|
||||||
if (argptr) {
|
strncpy(xargs, class->miscargs, sizeof(xargs) - 1);
|
||||||
*argptr = '\0';
|
argptr = xargs;
|
||||||
argptr++;
|
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);
|
close(x);
|
||||||
/* Child */
|
/* Child */
|
||||||
chdir(class->dir);
|
chdir(class->dir);
|
||||||
/* Default install is /usr/local/bin */
|
if(class->custom) {
|
||||||
execv(LOCAL_MPG_123, argv);
|
execv(argv[0], argv);
|
||||||
/* Many places have it in /usr/bin */
|
} else {
|
||||||
execv(MPG_123, argv);
|
/* Default install is /usr/local/bin */
|
||||||
/* Check PATH as a last-ditch effort */
|
execv(LOCAL_MPG_123, argv);
|
||||||
execvp("mpg123", 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));
|
ast_log(LOG_WARNING, "Exec failed: %s\n", strerror(errno));
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
exit(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);
|
strncpy(moh->class, classname, sizeof(moh->class) - 1);
|
||||||
if (miscargs)
|
if (miscargs)
|
||||||
strncpy(moh->miscargs, miscargs, sizeof(moh->miscargs) - 1);
|
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"))
|
if (!strcasecmp(mode, "mp3nb") || !strcasecmp(mode, "quietmp3nb"))
|
||||||
moh->single = 1;
|
moh->single = 1;
|
||||||
if (!strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb"))
|
if (!strcasecmp(mode, "quietmp3") || !strcasecmp(mode, "quietmp3nb"))
|
||||||
|
Reference in New Issue
Block a user