mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-11-03 20:38:59 +00:00 
			
		
		
		
	muted: Remove deprecated application.
ASTERISK-29600 Change-Id: I0ae1c6a2996da43217126f094de90761314dcf82
This commit is contained in:
		
							
								
								
									
										6
									
								
								doc/UPGRADE-staging/muted_removal.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								doc/UPGRADE-staging/muted_removal.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
Subject: muted
 | 
			
		||||
Master-Only: True
 | 
			
		||||
 | 
			
		||||
This application was deprecated in Asterisk 16
 | 
			
		||||
and is now being removed in accordance with
 | 
			
		||||
the Asterisk Module Deprecation policy.
 | 
			
		||||
							
								
								
									
										1
									
								
								utils/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								utils/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -15,7 +15,6 @@ db1-ast/libdb1.a
 | 
			
		||||
hashtab.c
 | 
			
		||||
lock.c
 | 
			
		||||
md5.c
 | 
			
		||||
muted
 | 
			
		||||
pbx_ael.c
 | 
			
		||||
pval.c
 | 
			
		||||
smsq
 | 
			
		||||
 
 | 
			
		||||
@@ -38,15 +38,6 @@ include $(ASTTOPDIR)/Makefile.rules
 | 
			
		||||
 | 
			
		||||
ifeq ($(OSARCH),SunOS)
 | 
			
		||||
  LIBS+=-lsocket -lnsl
 | 
			
		||||
  UTILS:=$(filter-out muted,$(UTILS))
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(OSARCH),OpenBSD)
 | 
			
		||||
  UTILS:=$(filter-out muted,$(UTILS))
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(OSARCH),cygwin)
 | 
			
		||||
  UTILS:=$(filter-out muted,$(UTILS))
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(OSARCH),mingw32)
 | 
			
		||||
@@ -192,10 +183,6 @@ smsq: LIBS+=$(POPT_LIB)
 | 
			
		||||
 | 
			
		||||
streamplayer: streamplayer.o
 | 
			
		||||
 | 
			
		||||
muted: muted.o
 | 
			
		||||
muted: LIBS+=$(AUDIO_LIBS)
 | 
			
		||||
muted: _ASTCFLAGS:=$(filter-out -Werror,$(_ASTCFLAGS))
 | 
			
		||||
 | 
			
		||||
CHECK_SUBDIR:	# do nothing, just make sure that we recurse in the subdir/
 | 
			
		||||
db1-ast/libdb1.a: CHECK_SUBDIR
 | 
			
		||||
	_ASTCFLAGS="$(_ASTCFLAGS) -Wno-strict-aliasing" ASTCFLAGS="$(ASTCFLAGS)" $(MAKE) -C db1-ast libdb1.a
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										777
									
								
								utils/muted.c
									
									
									
									
									
								
							
							
						
						
									
										777
									
								
								utils/muted.c
									
									
									
									
									
								
							@@ -1,777 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*! \li \ref muted.c uses the configuration file \ref muted.conf
 | 
			
		||||
 * \addtogroup configuration_file Configuration Files
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \page muted.conf muted.conf
 | 
			
		||||
 * \verbinclude muted.conf.sample
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*** MODULEINFO
 | 
			
		||||
	<support_level>deprecated</support_level>
 | 
			
		||||
	<deprecated_in>16</deprecated_in>
 | 
			
		||||
	<removed_in>19</removed_in>
 | 
			
		||||
 ***/
 | 
			
		||||
 | 
			
		||||
#include "asterisk/autoconfig.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __Darwin__
 | 
			
		||||
#include <CoreAudio/AudioHardware.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <pwd.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__GLIBC__)
 | 
			
		||||
#include <sys/soundcard.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>
 | 
			
		||||
 | 
			
		||||
#define ast_strlen_zero(a)	(!(*(a)))
 | 
			
		||||
 | 
			
		||||
static char *config = "/etc/asterisk/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));
 | 
			
		||||
		if (!(chan->tech = strdup(tech))) {
 | 
			
		||||
			free(chan);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(chan->location = strdup(location))) {
 | 
			
		||||
			free(chan->tech);
 | 
			
		||||
			free(chan);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		chan->next = channels;
 | 
			
		||||
		channels = chan;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int load_config(void)
 | 
			
		||||
{
 | 
			
		||||
	FILE *f;
 | 
			
		||||
	char buf[256];
 | 
			
		||||
	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)) {
 | 
			
		||||
		if (!fgets(buf, sizeof(buf), f)) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		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))
 | 
			
		||||
					snprintf(user, sizeof(user), "%s", val);
 | 
			
		||||
				else
 | 
			
		||||
					fprintf(stderr, "user needs an argument (the user) at line %d\n", lineno);
 | 
			
		||||
			} else if (!strcasecmp(buf, "pass")) {
 | 
			
		||||
				if (val && strlen(val))
 | 
			
		||||
					snprintf(pass, sizeof(pass), "%s", val);
 | 
			
		||||
				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, "%3d", &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, "%5d", &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, (struct sockaddr *)&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];
 | 
			
		||||
	AudioObjectPropertyAddress OutputAddr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
 | 
			
		||||
	AudioObjectPropertyAddress ChannelAddr = { kAudioDevicePropertyPreferredChannelsForStereo, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementWildcard };
 | 
			
		||||
	AudioObjectPropertyAddress VolumeAddr = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, };
 | 
			
		||||
 | 
			
		||||
	size = sizeof(device);
 | 
			
		||||
	err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &OutputAddr, 0, NULL, &size, &device);
 | 
			
		||||
	size = sizeof(channels);
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		err = AudioObjectGetPropertyData(device, &ChannelAddr, 0, NULL, &size, &channels);
 | 
			
		||||
	}
 | 
			
		||||
	size = sizeof(vol);
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		VolumeAddr.mElement = channels[0];
 | 
			
		||||
		err = AudioObjectGetPropertyData(device, &VolumeAddr, 0, NULL, &size, &volumeL);
 | 
			
		||||
	}
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		VolumeAddr.mElement = channels[1];
 | 
			
		||||
		err = AudioObjectGetPropertyData(device, &VolumeAddr, 0, NULL, &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];
 | 
			
		||||
	AudioObjectPropertyAddress OutputAddr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
 | 
			
		||||
	AudioObjectPropertyAddress ChannelAddr = { kAudioDevicePropertyPreferredChannelsForStereo, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementWildcard };
 | 
			
		||||
	AudioObjectPropertyAddress VolumeAddr = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, };
 | 
			
		||||
 | 
			
		||||
	size = sizeof(device);
 | 
			
		||||
	err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &OutputAddr, 0, NULL, &size, &device);
 | 
			
		||||
	size = sizeof(channels);
 | 
			
		||||
	err = AudioObjectGetPropertyData(device, &ChannelAddr, 0, NULL, &size, &channels);
 | 
			
		||||
	size = sizeof(vol);
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		VolumeAddr.mElement = channels[0];
 | 
			
		||||
		err = AudioObjectSetPropertyData(device, &VolumeAddr, 0, NULL, size, &volumeL);
 | 
			
		||||
	}
 | 
			
		||||
	if (!err) {
 | 
			
		||||
		VolumeAddr.mElement = channels[1];
 | 
			
		||||
		err = AudioObjectSetPropertyData(device, &VolumeAddr, 0, NULL, 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 level)
 | 
			
		||||
{
 | 
			
		||||
	int l = orig >> 8;
 | 
			
		||||
	int r = orig & 0xff;
 | 
			
		||||
	l = (float)(level) * (float)(l) / 100.0;
 | 
			
		||||
	r = (float)(level) * (float)(r) / 100.0;
 | 
			
		||||
 | 
			
		||||
	return (l << 8) | r;
 | 
			
		||||
#else
 | 
			
		||||
static float mutedlevel(float orig, float level)
 | 
			
		||||
{
 | 
			
		||||
	float master = orig;
 | 
			
		||||
	master = level * 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));
 | 
			
		||||
		if (!(sub->name = strdup(name))) {
 | 
			
		||||
			free(sub);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		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: "))) {
 | 
			
		||||
		int event_len = -1;
 | 
			
		||||
		int channel_len = -1;
 | 
			
		||||
		int newname_len = -1;
 | 
			
		||||
		int oldname_len = -1;
 | 
			
		||||
 | 
			
		||||
		event_len = snprintf(event, sizeof(event), "%s", resp + strlen("Event: "));
 | 
			
		||||
		/* Consume the rest of the non-event */
 | 
			
		||||
		while((resp = get_line()) && strlen(resp)) {
 | 
			
		||||
			if (!strncasecmp(resp, "Channel: ", strlen("Channel: ")))
 | 
			
		||||
				channel_len = snprintf(channel, sizeof(channel), "%s", resp + strlen("Channel: "));
 | 
			
		||||
			if (!strncasecmp(resp, "Newname: ", strlen("Newname: ")))
 | 
			
		||||
				newname_len = snprintf(newname, sizeof(newname), "%s", resp + strlen("Newname: "));
 | 
			
		||||
			if (!strncasecmp(resp, "Oldname: ", strlen("Oldname: ")))
 | 
			
		||||
				oldname_len = snprintf(oldname, sizeof(oldname), "%s", resp + strlen("Oldname: "));
 | 
			
		||||
		}
 | 
			
		||||
		if (channel_len == strlen(channel)) {
 | 
			
		||||
			if (event_len == strlen(event) && !strcasecmp(event, "Hangup"))
 | 
			
		||||
				hangup_chan(channel);
 | 
			
		||||
			else
 | 
			
		||||
				offhook_chan(channel);
 | 
			
		||||
		}
 | 
			
		||||
		if (newname_len == strlen(newname) && oldname_len == strlen(oldname)) {
 | 
			
		||||
			if (event_len == strlen(event) && !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);
 | 
			
		||||
	}
 | 
			
		||||
#ifdef HAVE_WORKING_FORK
 | 
			
		||||
	if (needfork) {
 | 
			
		||||
#ifndef HAVE_SBIN_LAUNCHD
 | 
			
		||||
		if (daemon(0,0) < 0) {
 | 
			
		||||
			fprintf(stderr, "daemon() failed: %s\n", strerror(errno));
 | 
			
		||||
			exit(1);
 | 
			
		||||
		}
 | 
			
		||||
#else
 | 
			
		||||
		const char *found = NULL, *paths[] = {
 | 
			
		||||
			"/Library/LaunchAgents/org.asterisk.muted.plist",
 | 
			
		||||
			"/Library/LaunchDaemons/org.asterisk.muted.plist",
 | 
			
		||||
			"contrib/init.d/org.asterisk.muted.plist",
 | 
			
		||||
			"<path-to-asterisk-source>/contrib/init.d/org.asterisk.muted.plist" };
 | 
			
		||||
		char userpath[256];
 | 
			
		||||
		struct stat unused;
 | 
			
		||||
		struct passwd *pwd = getpwuid(getuid());
 | 
			
		||||
		int i;
 | 
			
		||||
 | 
			
		||||
		snprintf(userpath, sizeof(userpath), "%s%s", pwd->pw_dir, paths[0]);
 | 
			
		||||
		if (!stat(userpath, &unused)) {
 | 
			
		||||
			found = userpath;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!found) {
 | 
			
		||||
			for (i = 0; i < 3; i++) {
 | 
			
		||||
				if (!stat(paths[i], &unused)) {
 | 
			
		||||
					found = paths[i];
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fprintf(stderr, "Mac OS X detected.  Use 'launchctl load -w %s' to launch.\n", found ? found : paths[3]);
 | 
			
		||||
		exit(1);
 | 
			
		||||
#endif /* !defined(HAVE_SBIN_LAUNCHD */
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	for(;;) {
 | 
			
		||||
		if (wait_event()) {
 | 
			
		||||
			fclose(astf);
 | 
			
		||||
			while(connect_asterisk()) {
 | 
			
		||||
				sleep(5);
 | 
			
		||||
			}
 | 
			
		||||
			if (login_asterisk()) {
 | 
			
		||||
				fclose(astf);
 | 
			
		||||
				exit(1);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	exit(0);
 | 
			
		||||
}
 | 
			
		||||
@@ -28,10 +28,6 @@
 | 
			
		||||
	<defaultenabled>no</defaultenabled>
 | 
			
		||||
	<support_level>extended</support_level>
 | 
			
		||||
  </member>
 | 
			
		||||
  <member name="muted">
 | 
			
		||||
	<defaultenabled>no</defaultenabled>
 | 
			
		||||
	<support_level>deprecated</support_level>
 | 
			
		||||
  </member>
 | 
			
		||||
  <member name="smsq">
 | 
			
		||||
	<defaultenabled>no</defaultenabled>
 | 
			
		||||
	<depend>popt</depend>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user