diff options
author | kpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-08-21 02:11:39 +0000 |
---|---|---|
committer | kpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-08-21 02:11:39 +0000 |
commit | 8b0c007ad990aa27d9868da49215fd1076ac77cc (patch) | |
tree | 270b9c46c1e644483d6d2a35b509f43218ba3252 /utils | |
parent | a42edc84034f91932a3e12d503e07f76a6eb498a (diff) |
merge new_loader_completion branch, including (at least):
- restructured build tree and makefiles to eliminate recursion problems
- support for embedded modules
- support for static builds
- simpler cross-compilation support
- simpler module/loader interface (no exported symbols)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@40722 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'utils')
-rw-r--r-- | utils/Makefile | 34 | ||||
-rw-r--r-- | utils/ael_main.c | 4 | ||||
-rw-r--r-- | utils/muted.c | 688 |
3 files changed, 710 insertions, 16 deletions
diff --git a/utils/Makefile b/utils/Makefile index 1d7a9512a..ad42e859e 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -16,7 +16,7 @@ UTILS:=astman smsq stereorize streamplayer aelparse ifeq (${OSARCH},SunOS) - LIBS+=../strcompat.o -lsocket -lnsl + LIBS+=../main/strcompat.o -lsocket -lnsl endif ifeq ($(POPT_LIB),) @@ -51,23 +51,23 @@ clean-depend: clean: clean-depend rm -f *.o $(UTILS) check_expr -$(eval $(call ast_make_final,astman,astman.o ../md5.o)) -astman: LIBS+=-lnewt +$(eval $(call ast_make_final,astman,astman.o ../main/md5.o)) +astman: LIBS+=-lnewt -lslang -ldl $(eval $(call ast_make_final,stereorize,stereorize.o frame.o)) stereorize: LIBS+=-lm -../ast_expr2.c: - @echo " [BISON] ../ast_expr2.y -> $@" - @bison -o $@ -d --name-prefix=ast_yy ../ast_expr2.y +../main/ast_expr2.c: + @echo " [BISON] ../main/ast_expr2.y -> $@" + @bison -o $@ -d --name-prefix=ast_yy ../main/ast_expr2.y -../ast_expr2f.c: - @echo " [FLEX] ../ast_expr2.fl -> $@" - @flex -o $@ --full ../ast_expr2.fl +../main/ast_expr2f.c: + @echo " [FLEX] ../main/ast_expr2.fl -> $@" + @flex -o $@ --full ../main/ast_expr2.fl -$(eval $(call ast_make_o_c,ast_expr2.o,../ast_expr2.c)) +$(eval $(call ast_make_o_c,ast_expr2.o,../main/ast_expr2.c)) -$(eval $(call ast_make_o_c,ast_expr2f.o,../ast_expr2f.c)) +$(eval $(call ast_make_o_c,ast_expr2f.o,../main/ast_expr2f.c)) ast_expr2f.o: CFLAGS+=-DSTANDALONE $(eval $(call ast_make_final,check_expr,check_expr.c ast_expr2.o ast_expr2f.o)) @@ -79,23 +79,27 @@ $(eval $(call ast_make_o_c,aelbison.o,../pbx/ael/ael.tab.c ../pbx/ael/ael.tab.h aelbison.o: CFLAGS+=-I../pbx $(eval $(call ast_make_o_c,pbx_ael.o,../pbx/pbx_ael.c)) +pbx_ael.o: CFLAGS+=-DSTANDALONE_AEL $(eval $(call ast_make_final,aelparse,aelflex.o aelbison.o pbx_ael.o ael_main.o ast_expr2f.o ast_expr2.o)) $(eval $(call ast_make_o_c,ael_main.o,ael_main.c ../include/asterisk/ael_structs.h)) -testexpr2s: ../ast_expr2f.c ../ast_expr2.c ../ast_expr2.h - $(CC) -g -c -I../include -DSTANDALONE ../ast_expr2f.c -o ast_expr2f.o - $(CC) -g -c -I../include -DSTANDALONE ../ast_expr2.c -o ast_expr2.o +testexpr2s: ../main/ast_expr2f.c ../main/ast_expr2.c ../main/ast_expr2.h + $(CC) -g -c -I../include -DSTANDALONE ../main/ast_expr2f.c -o ast_expr2f.o + $(CC) -g -c -I../include -DSTANDALONE ../main/ast_expr2.c -o ast_expr2.o $(CC) -g -o testexpr2s ast_expr2f.o ast_expr2.o rm ast_expr2.o ast_expr2f.o ./testexpr2s expr2.testinput smsq: smsq.o -smsq: LIBS+=-lpopt +smsq: LIBS+=$(POPT_LIB) streamplayer: streamplayer.o +muted: muted.o +muted: LIBS+=$(AUDIO_LIBS) + ifneq ($(wildcard .depend),) include .depend endif diff --git a/utils/ael_main.c b/utils/ael_main.c index b930ad56b..e89a4b456 100644 --- a/utils/ael_main.c +++ b/utils/ael_main.c @@ -15,7 +15,9 @@ #include <limits.h> #include "asterisk/ast_expr.h" +#include "asterisk/channel.h" #include "asterisk/module.h" +#include "asterisk/app.h" #include "asterisk/ael_structs.h" struct namelist @@ -453,7 +455,7 @@ int main(int argc, char **argv) FIRST_TIME = 1; - mod_data.load_module(0); + ast_module_info->load(); ast_log(4, "ael2_parse", __LINE__, "main", "%d contexts, %d extensions, %d priorities\n", conts, extens, priors); diff --git a/utils/muted.c b/utils/muted.c new file mode 100644 index 000000000..73eadfa3d --- /dev/null +++ b/utils/muted.c @@ -0,0 +1,688 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2005, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * Updated for Mac OSX CoreAudio + * by Josh Roberson <josh@asteriasgi.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Mute Daemon + * + * \author Mark Spencer <markster@digium.com> + * + * Updated for Mac OSX CoreAudio + * \arg Josh Roberson <josh@asteriasgi.com> + * + * \note Specially written for Malcolm Davenport, but I think I'll use it too + * Connects to the Asterisk Manager Interface, AMI, and listens for events + * on certain devices. If a phone call is connected to one of the devices (phones) + * the local sound is muted to a lower volume during the call. + * + */ + +#ifndef __Darwin__ +#include <linux/soundcard.h> +#else +#include <CoreAudio/AudioHardware.h> +#endif +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <netdb.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +static char *config = "/etc/muted.conf"; + +static char host[256] = ""; +static char user[256] = ""; +static char pass[256] = ""; +static int smoothfade = 0; +static int mutelevel = 20; +static int muted = 0; +static int needfork = 1; +static int debug = 0; +static int stepsize = 3; +#ifndef __Darwin__ +static int mixchan = SOUND_MIXER_VOLUME; +#endif + +struct subchannel { + char *name; + struct subchannel *next; +}; + +static struct channel { + char *tech; + char *location; + struct channel *next; + struct subchannel *subs; +} *channels; + +static void add_channel(char *tech, char *location) +{ + struct channel *chan; + chan = malloc(sizeof(struct channel)); + if (chan) { + memset(chan, 0, sizeof(struct channel)); + chan->tech = strdup(tech); + chan->location = strdup(location); + chan->next = channels; + channels = chan; + } + +} + +static int load_config(void) +{ + FILE *f; + char buf[1024]; + char *val; + char *val2; + int lineno=0; + int x; + f = fopen(config, "r"); + if (!f) { + fprintf(stderr, "Unable to open config file '%s': %s\n", config, strerror(errno)); + return -1; + } + while(!feof(f)) { + fgets(buf, sizeof(buf), f); + if (!feof(f)) { + lineno++; + val = strchr(buf, '#'); + if (val) *val = '\0'; + while(strlen(buf) && (buf[strlen(buf) - 1] < 33)) + buf[strlen(buf) - 1] = '\0'; + if (!strlen(buf)) + continue; + val = buf; + while(*val) { + if (*val < 33) + break; + val++; + } + if (*val) { + *val = '\0'; + val++; + while(*val && (*val < 33)) val++; + } + if (!strcasecmp(buf, "host")) { + if (val && strlen(val)) + strncpy(host, val, sizeof(host) - 1); + else + fprintf(stderr, "host needs an argument (the host) at line %d\n", lineno); + } else if (!strcasecmp(buf, "user")) { + if (val && strlen(val)) + strncpy(user, val, sizeof(user) - 1); + else + fprintf(stderr, "user needs an argument (the user) at line %d\n", lineno); + } else if (!strcasecmp(buf, "pass")) { + if (val && strlen(val)) + strncpy(pass, val, sizeof(pass) - 1); + else + fprintf(stderr, "pass needs an argument (the password) at line %d\n", lineno); + } else if (!strcasecmp(buf, "smoothfade")) { + smoothfade = 1; + } else if (!strcasecmp(buf, "mutelevel")) { + if (val && (sscanf(val, "%d", &x) == 1) && (x > -1) && (x < 101)) { + mutelevel = x; + } else + fprintf(stderr, "mutelevel must be a number from 0 (most muted) to 100 (no mute) at line %d\n", lineno); + } else if (!strcasecmp(buf, "channel")) { + if (val && strlen(val)) { + val2 = strchr(val, '/'); + if (val2) { + *val2 = '\0'; + val2++; + add_channel(val, val2); + } else + fprintf(stderr, "channel needs to be of the format Tech/Location at line %d\n", lineno); + } else + fprintf(stderr, "channel needs an argument (the channel) at line %d\n", lineno); + } else { + fprintf(stderr, "ignoring unknown keyword '%s'\n", buf); + } + } + } + fclose(f); + if (!strlen(host)) + fprintf(stderr, "no 'host' specification in config file\n"); + else if (!strlen(user)) + fprintf(stderr, "no 'user' specification in config file\n"); + else if (!channels) + fprintf(stderr, "no 'channel' specifications in config file\n"); + else + return 0; + return -1; +} + +static FILE *astf; +#ifndef __Darwin__ +static int mixfd; + +static int open_mixer(void) +{ + mixfd = open("/dev/mixer", O_RDWR); + if (mixfd < 0) { + fprintf(stderr, "Unable to open /dev/mixer: %s\n", strerror(errno)); + return -1; + } + return 0; +} +#endif /* !__Darwin */ + +/*! Connect to the asterisk manager interface */ +static int connect_asterisk(void) +{ + int sock; + struct hostent *hp; + char *ports; + int port = 5038; + struct sockaddr_in sin; + + ports = strchr(host, ':'); + if (ports) { + *ports = '\0'; + ports++; + if ((sscanf(ports, "%d", &port) != 1) || (port < 1) || (port > 65535)) { + fprintf(stderr, "'%s' is not a valid port number in the hostname\n", ports); + return -1; + } + } + hp = gethostbyname(host); + if (!hp) { + fprintf(stderr, "Can't find host '%s'\n", host); + return -1; + } + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + fprintf(stderr, "Failed to create socket: %s\n", strerror(errno)); + return -1; + } + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); + if (connect(sock, &sin, sizeof(sin))) { + fprintf(stderr, "Failed to connect to '%s' port '%d': %s\n", host, port, strerror(errno)); + close(sock); + return -1; + } + astf = fdopen(sock, "r+"); + if (!astf) { + fprintf(stderr, "fdopen failed: %s\n", strerror(errno)); + close(sock); + return -1; + } + return 0; +} + +static char *get_line(void) +{ + static char buf[1024]; + if (fgets(buf, sizeof(buf), astf)) { + while(strlen(buf) && (buf[strlen(buf) - 1] < 33)) + buf[strlen(buf) - 1] = '\0'; + return buf; + } else + return NULL; +} + +/*! Login to the asterisk manager interface */ +static int login_asterisk(void) +{ + char *welcome; + char *resp; + if (!(welcome = get_line())) { + fprintf(stderr, "disconnected (1)\n"); + return -1; + } + fprintf(astf, + "Action: Login\r\n" + "Username: %s\r\n" + "Secret: %s\r\n\r\n", user, pass); + if (!(welcome = get_line())) { + fprintf(stderr, "disconnected (2)\n"); + return -1; + } + if (strcasecmp(welcome, "Response: Success")) { + fprintf(stderr, "login failed ('%s')\n", welcome); + return -1; + } + /* Eat the rest of the event */ + while((resp = get_line()) && strlen(resp)); + if (!resp) { + fprintf(stderr, "disconnected (3)\n"); + return -1; + } + fprintf(astf, + "Action: Status\r\n\r\n"); + if (!(welcome = get_line())) { + fprintf(stderr, "disconnected (4)\n"); + return -1; + } + if (strcasecmp(welcome, "Response: Success")) { + fprintf(stderr, "status failed ('%s')\n", welcome); + return -1; + } + /* Eat the rest of the event */ + while((resp = get_line()) && strlen(resp)); + if (!resp) { + fprintf(stderr, "disconnected (5)\n"); + return -1; + } + return 0; +} + +static struct channel *find_channel(char *channel) +{ + char tmp[256] = ""; + char *s, *t; + struct channel *chan; + strncpy(tmp, channel, sizeof(tmp) - 1); + s = strchr(tmp, '/'); + if (s) { + *s = '\0'; + s++; + t = strrchr(s, '-'); + if (t) { + *t = '\0'; + } + if (debug) + printf("Searching for '%s' tech, '%s' location\n", tmp, s); + chan = channels; + while(chan) { + if (!strcasecmp(chan->tech, tmp) && !strcasecmp(chan->location, s)) { + if (debug) + printf("Found '%s'/'%s'\n", chan->tech, chan->location); + break; + } + chan = chan->next; + } + } else + chan = NULL; + return chan; +} + +#ifndef __Darwin__ +static int getvol(void) +{ + int vol; + + if (ioctl(mixfd, MIXER_READ(mixchan), &vol)) { +#else +static float getvol(void) +{ + float volumeL, volumeR, vol; + OSStatus err; + AudioDeviceID device; + UInt32 size; + UInt32 channels[2]; + + size = sizeof(device); + err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &device); + size = sizeof(channels); + if (!err) + err = AudioDeviceGetProperty(device, 0, false, kAudioDevicePropertyPreferredChannelsForStereo, &size, &channels); + size = sizeof(vol); + if (!err) + err = AudioDeviceGetProperty(device, channels[0], false, kAudioDevicePropertyVolumeScalar, &size, &volumeL); + if (!err) + err = AudioDeviceGetProperty(device, channels[1], false, kAudioDevicePropertyVolumeScalar, &size, &volumeR); + if (!err) + vol = (volumeL < volumeR) ? volumeR : volumeL; + else { +#endif + fprintf(stderr, "Unable to read mixer volume: %s\n", strerror(errno)); + return -1; + } + return vol; +} + +#ifndef __Darwin__ +static int setvol(int vol) +#else +static int setvol(float vol) +#endif +{ +#ifndef __Darwin__ + if (ioctl(mixfd, MIXER_WRITE(mixchan), &vol)) { +#else + float volumeL = vol; + float volumeR = vol; + OSStatus err; + AudioDeviceID device; + UInt32 size; + UInt32 channels[2]; + + size = sizeof(device); + err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &device); + size = sizeof(channels); + err = AudioDeviceGetProperty(device, 0, false, kAudioDevicePropertyPreferredChannelsForStereo, &size, &channels); + size = sizeof(vol); + if (!err) + err = AudioDeviceSetProperty(device, 0, channels[0], false, kAudioDevicePropertyVolumeScalar, size, &volumeL); + if (!err) + err = AudioDeviceSetProperty(device, 0, channels[1], false, kAudioDevicePropertyVolumeScalar, size, &volumeR); + if (err) { +#endif + + fprintf(stderr, "Unable to write mixer volume: %s\n", strerror(errno)); + return -1; + + } + return 0; +} + +#ifndef __Darwin__ +static int oldvol = 0; +static int mutevol = 0; +#else +static float oldvol = 0; +static float mutevol = 0; +#endif + +#ifndef __Darwin__ +static int mutedlevel(int orig, int mutelevel) +{ + int l = orig >> 8; + int r = orig & 0xff; + l = (float)(mutelevel) * (float)(l) / 100.0; + r = (float)(mutelevel) * (float)(r) / 100.0; + + return (l << 8) | r; +#else +static float mutedlevel(float orig, float mutelevel) +{ + float master = orig; + master = mutelevel * master / 100.0; + return master; +#endif + +} + +static void mute(void) +{ +#ifndef __Darwin__ + int vol; + int start; + int x; +#else + float vol; + float start = 1.0; + float x; +#endif + vol = getvol(); + oldvol = vol; + if (smoothfade) +#ifdef __Darwin__ + start = mutelevel; +#else + start = 100; + else + start = mutelevel; +#endif + for (x=start;x>=mutelevel;x-=stepsize) { + mutevol = mutedlevel(vol, x); + setvol(mutevol); + /* Wait 0.01 sec */ + usleep(10000); + } + mutevol = mutedlevel(vol, mutelevel); + setvol(mutevol); + if (debug) +#ifdef __Darwin__ + printf("Mute from '%f' to '%f'!\n", oldvol, mutevol); +#else + printf("Mute from '%04x' to '%04x'!\n", oldvol, mutevol); +#endif + muted = 1; +} + +static void unmute(void) +{ +#ifdef __Darwin__ + float vol; + float start; + float x; +#else + int vol; + int start; + int x; +#endif + vol = getvol(); + if (debug) +#ifdef __Darwin__ + printf("Unmute from '%f' (should be '%f') to '%f'!\n", vol, mutevol, oldvol); + mutevol = vol; + if (vol == mutevol) { +#else + printf("Unmute from '%04x' (should be '%04x') to '%04x'!\n", vol, mutevol, oldvol); + if ((int)vol == mutevol) { +#endif + if (smoothfade) + start = mutelevel; + else +#ifdef __Darwin__ + start = 1.0; +#else + start = 100; +#endif + for (x=start;x<100;x+=stepsize) { + mutevol = mutedlevel(oldvol, x); + setvol(mutevol); + /* Wait 0.01 sec */ + usleep(10000); + } + setvol(oldvol); + } else + printf("Whoops, it's already been changed!\n"); + muted = 0; +} + +static void check_mute(void) +{ + int offhook = 0; + struct channel *chan; + chan = channels; + while(chan) { + if (chan->subs) { + offhook++; + break; + } + chan = chan->next; + } + if (offhook && !muted) + mute(); + else if (!offhook && muted) + unmute(); +} + +static void delete_sub(struct channel *chan, char *name) +{ + struct subchannel *sub, *prev; + prev = NULL; + sub = chan->subs; + while(sub) { + if (!strcasecmp(sub->name, name)) { + if (prev) + prev->next = sub->next; + else + chan->subs = sub->next; + free(sub->name); + free(sub); + return; + } + prev = sub; + sub = sub->next; + } +} + +static void append_sub(struct channel *chan, char *name) +{ + struct subchannel *sub; + sub = chan->subs; + while(sub) { + if (!strcasecmp(sub->name, name)) + return; + sub = sub->next; + } + sub = malloc(sizeof(struct subchannel)); + if (sub) { + memset(sub, 0, sizeof(struct subchannel)); + sub->name = strdup(name); + sub->next = chan->subs; + chan->subs = sub; + } +} + +static void hangup_chan(char *channel) +{ + struct channel *chan; + if (debug) + printf("Hangup '%s'\n", channel); + chan = find_channel(channel); + if (chan) + delete_sub(chan, channel); + check_mute(); +} + +static void offhook_chan(char *channel) +{ + struct channel *chan; + if (debug) + printf("Offhook '%s'\n", channel); + chan = find_channel(channel); + if (chan) + append_sub(chan, channel); + check_mute(); +} + +static int wait_event(void) +{ + char *resp; + char event[120]=""; + char channel[120]=""; + char oldname[120]=""; + char newname[120]=""; + + resp = get_line(); + if (!resp) { + fprintf(stderr, "disconnected (6)\n"); + return -1; + } + if (!strncasecmp(resp, "Event: ", strlen("Event: "))) { + strncpy(event, resp + strlen("Event: "), sizeof(event) - 1); + /* Consume the rest of the non-event */ + while((resp = get_line()) && strlen(resp)) { + if (!strncasecmp(resp, "Channel: ", strlen("Channel: "))) + strncpy(channel, resp + strlen("Channel: "), sizeof(channel) - 1); + if (!strncasecmp(resp, "Newname: ", strlen("Newname: "))) + strncpy(newname, resp + strlen("Newname: "), sizeof(newname) - 1); + if (!strncasecmp(resp, "Oldname: ", strlen("Oldname: "))) + strncpy(oldname, resp + strlen("Oldname: "), sizeof(oldname) - 1); + } + if (strlen(channel)) { + if (!strcasecmp(event, "Hangup")) + hangup_chan(channel); + else + offhook_chan(channel); + } + if (strlen(newname) && strlen(oldname)) { + if (!strcasecmp(event, "Rename")) { + hangup_chan(oldname); + offhook_chan(newname); + } + } + } else { + /* Consume the rest of the non-event */ + while((resp = get_line()) && strlen(resp)); + } + if (!resp) { + fprintf(stderr, "disconnected (7)\n"); + return -1; + } + return 0; +} + +static void usage(void) +{ + printf("Usage: muted [-f] [-d]\n" + " -f : Do not fork\n" + " -d : Debug (implies -f)\n"); +} + +int main(int argc, char *argv[]) +{ + int x; + while((x = getopt(argc, argv, "fhd")) > 0) { + switch(x) { + case 'd': + debug = 1; + needfork = 0; + break; + case 'f': + needfork = 0; + break; + case 'h': + /* Fall through */ + default: + usage(); + exit(1); + } + } + if (load_config()) + exit(1); +#ifndef __Darwin__ + if (open_mixer()) + exit(1); +#endif + if (connect_asterisk()) { +#ifndef __Darwin__ + close(mixfd); +#endif + exit(1); + } + if (login_asterisk()) { +#ifndef __Darwin__ + close(mixfd); +#endif + fclose(astf); + exit(1); + } + if (needfork) + daemon(0,0); + for(;;) { + if (wait_event()) { + fclose(astf); + while(connect_asterisk()) { + sleep(5); + } + if (login_asterisk()) { + fclose(astf); + exit(1); + } + } + } + exit(0); +} |