| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * Copyright (C) 1999 - 2005, Digium, Inc. | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  |  * Updated for Mac OSX CoreAudio | 
					
						
							| 
									
										
										
										
											2005-07-18 04:30:33 +00:00
										 |  |  |  * by Josh Roberson <josh@asteriasgi.com> | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \brief Mute Daemon | 
					
						
							| 
									
										
										
										
											2005-09-15 15:44:26 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * \author Mark Spencer <markster@digium.com> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  |  * Updated for Mac OSX CoreAudio | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * \arg Josh Roberson <josh@asteriasgi.com> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-11-14 19:00:38 +00:00
										 |  |  |  * \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. | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2005-04-22 13:11:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-14 21:57:42 +00:00
										 |  |  | /*! \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 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-14 20:28:54 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							| 
									
										
										
										
											2018-07-17 10:24:02 +00:00
										 |  |  | 	<support_level>deprecated</support_level> | 
					
						
							| 
									
										
											  
											
												policy: Add deprecation and removal versions to modules.
app_meetme is deprecated in 19, to be removed in 21.
app_osplookup is deprecated in 19, to be removed in 21.
chan_alsa is deprecated in 19, to be removed in 21.
chan_mgcp is deprecated in 19, to be removed in 21.
chan_skinny is deprecated in 19, to be removed in 21.
res_pktccops is deprecated in 19, to be removed in 21.
cdr_mysql was deprecated in 1.8, to be removed in 19.
app_mysql was deprecated in 1.8, to be removed in 19.
app_ices was deprecated in 16, to be removed in 19.
app_macro was deprecated in 16, to be removed in 21.
app_fax was deprecated in 16, to be removed in 19.
app_url was deprecated in 16, to be removed in 19.
app_image was deprecated in 16, to be removed in 19.
app_nbscat was deprecated in 16, to be removed in 19.
app_dahdiras was deprecated in 16, to be removed in 19.
cdr_syslog was deprecated in 16, to be removed in 19.
chan_oss was deprecated in 16, to be removed in 19.
chan_phone was deprecated in 16, to be removed in 19.
chan_sip was deprecated in 17, to be removed in 21.
chan_nbs was deprecated in 16, to be removed in 19.
chan_misdn was deprecated in 16, to be removed in 19.
chan_vpb was deprecated in 16, to be removed in 19.
res_config_sqlite was deprecated in 16, to be removed in 19.
res_monitor was deprecated in 16, to be removed in 21.
conf2ael was deprecated in 16, to be removed in 19.
muted was deprecated in 16, to be removed in 19.
ASTERISK-29548
ASTERISK-29549
ASTERISK-29550
ASTERISK-29551
ASTERISK-29552
ASTERISK-29553
ASTERISK-29554
ASTERISK-29555
ASTERISK-29557
ASTERISK-29558
ASTERISK-29559
ASTERISK-29560
ASTERISK-29561
ASTERISK-29562
ASTERISK-29563
ASTERISK-29564
ASTERISK-29565
ASTERISK-29566
ASTERISK-29567
ASTERISK-29568
ASTERISK-29569
ASTERISK-29570
ASTERISK-29571
ASTERISK-29572
ASTERISK-29573
ASTERISK-29574
Change-Id: Ic3bee31a10d42c4b3bbc913d893f7b2a28a27131
											
										 
											2021-08-11 08:15:16 -03:00
										 |  |  | 	<deprecated_in>16</deprecated_in> | 
					
						
							|  |  |  | 	<removed_in>19</removed_in> | 
					
						
							| 
									
										
										
										
											2011-07-14 20:28:54 +00:00
										 |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-05 22:11:30 +00:00
										 |  |  | #include "asterisk/autoconfig.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-18 22:35:40 +00:00
										 |  |  | #ifdef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | #include <CoreAudio/AudioHardware.h>
 | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <pwd.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							| 
									
										
										
										
											2018-04-20 12:50:03 +02:00
										 |  |  | #elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__GLIBC__)
 | 
					
						
							| 
									
										
										
										
											2006-09-18 22:35:40 +00:00
										 |  |  | #include <sys/soundcard.h>
 | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | #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>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | #define ast_strlen_zero(a)	(!(*(a)))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *config = "/etc/asterisk/muted.conf"; | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-14 07:44:19 +00:00
										 |  |  | static char host[256] = ""; | 
					
						
							|  |  |  | static char user[256] = ""; | 
					
						
							|  |  |  | static char pass[256] = ""; | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | static int smoothfade = 0; | 
					
						
							|  |  |  | static int mutelevel = 20; | 
					
						
							|  |  |  | static int muted = 0; | 
					
						
							|  |  |  | static int needfork = 1; | 
					
						
							|  |  |  | static int debug = 0; | 
					
						
							|  |  |  | static int stepsize = 3; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | static int mixchan = SOUND_MIXER_VOLUME; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 07:00:21 +00:00
										 |  |  | struct subchannel { | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 	struct subchannel *next; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | static struct channel { | 
					
						
							|  |  |  | 	char *tech; | 
					
						
							|  |  |  | 	char *location; | 
					
						
							|  |  |  | 	struct channel *next; | 
					
						
							| 
									
										
										
										
											2004-05-17 07:00:21 +00:00
										 |  |  | 	struct subchannel *subs; | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | } *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)); | 
					
						
							| 
									
										
										
										
											2006-10-24 01:28:45 +00:00
										 |  |  | 		if (!(chan->tech = strdup(tech))) { | 
					
						
							|  |  |  | 			free(chan); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!(chan->location = strdup(location))) { | 
					
						
							|  |  |  | 			free(chan->tech); | 
					
						
							|  |  |  | 			free(chan); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		chan->next = channels; | 
					
						
							|  |  |  | 		channels = chan; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int load_config(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	FILE *f; | 
					
						
							| 
									
										
										
										
											2020-10-29 14:59:48 +01:00
										 |  |  | 	char buf[256]; | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	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)) { | 
					
						
							| 
									
										
										
										
											2008-11-02 18:52:13 +00:00
										 |  |  | 		if (!fgets(buf, sizeof(buf), f)) { | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		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)) | 
					
						
							| 
									
										
										
										
											2004-07-14 07:44:19 +00:00
										 |  |  | 					strncpy(host, val, sizeof(host) - 1); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 				else | 
					
						
							|  |  |  | 					fprintf(stderr, "host needs an argument (the host) at line %d\n", lineno); | 
					
						
							|  |  |  | 			} else if (!strcasecmp(buf, "user")) { | 
					
						
							|  |  |  | 				if (val && strlen(val)) | 
					
						
							| 
									
										
										
										
											2020-06-01 18:25:48 -05:00
										 |  |  | 					snprintf(user, sizeof(user), "%s", val); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 				else | 
					
						
							|  |  |  | 					fprintf(stderr, "user needs an argument (the user) at line %d\n", lineno); | 
					
						
							|  |  |  | 			} else if (!strcasecmp(buf, "pass")) { | 
					
						
							|  |  |  | 				if (val && strlen(val)) | 
					
						
							| 
									
										
										
										
											2020-06-01 18:25:48 -05:00
										 |  |  | 					snprintf(pass, sizeof(pass), "%s", val); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 				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")) { | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 				if (val && (sscanf(val, "%3d", &x) == 1) && (x > -1) && (x < 101)) { | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 					mutelevel = x; | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | 				} else | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 					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"); | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | 	else if (!channels) | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		fprintf(stderr, "no 'channel' specifications in config file\n"); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static FILE *astf; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #endif /* !__Darwin */
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-14 19:00:38 +00:00
										 |  |  | /*! Connect to the asterisk manager interface */ | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | static int connect_asterisk(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int sock; | 
					
						
							|  |  |  | 	struct hostent *hp; | 
					
						
							|  |  |  | 	char *ports; | 
					
						
							|  |  |  | 	int port = 5038; | 
					
						
							|  |  |  | 	struct sockaddr_in sin; | 
					
						
							| 
									
										
										
										
											2005-11-14 19:00:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	ports = strchr(host, ':'); | 
					
						
							|  |  |  | 	if (ports) { | 
					
						
							|  |  |  | 		*ports = '\0'; | 
					
						
							|  |  |  | 		ports++; | 
					
						
							| 
									
										
										
										
											2009-08-10 19:20:57 +00:00
										 |  |  | 		if ((sscanf(ports, "%5d", &port) != 1) || (port < 1) || (port > 65535)) { | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 			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)); | 
					
						
							| 
									
										
										
										
											2006-08-22 02:30:38 +00:00
										 |  |  | 	if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) { | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-14 19:00:38 +00:00
										 |  |  | /*! Login to the asterisk manager interface */ | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | static int login_asterisk(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *welcome; | 
					
						
							|  |  |  | 	char *resp; | 
					
						
							|  |  |  | 	if (!(welcome = get_line())) { | 
					
						
							|  |  |  | 		fprintf(stderr, "disconnected (1)\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | 	fprintf(astf, | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		"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; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | 	fprintf(astf, | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		"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; | 
					
						
							| 
									
										
										
										
											2004-07-14 07:44:19 +00:00
										 |  |  | 	strncpy(tmp, channel, sizeof(tmp) - 1); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | static int getvol(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int vol; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	if (ioctl(mixfd, MIXER_READ(mixchan), &vol)) { | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | static float getvol(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float volumeL, volumeR, vol; | 
					
						
							|  |  |  | 	OSStatus err; | 
					
						
							|  |  |  | 	AudioDeviceID device; | 
					
						
							|  |  |  | 	UInt32 size; | 
					
						
							|  |  |  | 	UInt32 channels[2]; | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | 	AudioObjectPropertyAddress OutputAddr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; | 
					
						
							|  |  |  | 	AudioObjectPropertyAddress ChannelAddr = { kAudioDevicePropertyPreferredChannelsForStereo, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementWildcard }; | 
					
						
							|  |  |  | 	AudioObjectPropertyAddress VolumeAddr = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, }; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	size = sizeof(device); | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | 	err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &OutputAddr, 0, NULL, &size, &device); | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 	size = sizeof(channels); | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | 	if (!err) { | 
					
						
							|  |  |  | 		err = AudioObjectGetPropertyData(device, &ChannelAddr, 0, NULL, &size, &channels); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 	size = sizeof(vol); | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 	if (!err) | 
					
						
							|  |  |  | 		vol = (volumeL < volumeR) ? volumeR : volumeL; | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		fprintf(stderr, "Unable to read mixer volume: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return vol; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | static int setvol(int vol) | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | static int setvol(float vol) | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	if (ioctl(mixfd, MIXER_WRITE(mixchan), &vol)) { | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 	float volumeL = vol; | 
					
						
							|  |  |  | 	float volumeR = vol; | 
					
						
							|  |  |  | 	OSStatus err; | 
					
						
							|  |  |  | 	AudioDeviceID device; | 
					
						
							|  |  |  | 	UInt32 size; | 
					
						
							|  |  |  | 	UInt32 channels[2]; | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | 	AudioObjectPropertyAddress OutputAddr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; | 
					
						
							|  |  |  | 	AudioObjectPropertyAddress ChannelAddr = { kAudioDevicePropertyPreferredChannelsForStereo, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementWildcard }; | 
					
						
							|  |  |  | 	AudioObjectPropertyAddress VolumeAddr = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, }; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	size = sizeof(device); | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | 	err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &OutputAddr, 0, NULL, &size, &device); | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 	size = sizeof(channels); | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | 	err = AudioObjectGetPropertyData(device, &ChannelAddr, 0, NULL, &size, &channels); | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 	size = sizeof(vol); | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 	if (err) { | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		fprintf(stderr, "Unable to write mixer volume: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | static int oldvol = 0; | 
					
						
							|  |  |  | static int mutevol = 0; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | static float oldvol = 0; | 
					
						
							|  |  |  | static float mutevol = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2008-08-07 15:16:48 +00:00
										 |  |  | static int mutedlevel(int orig, int level) | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int l = orig >> 8; | 
					
						
							|  |  |  | 	int r = orig & 0xff; | 
					
						
							| 
									
										
										
										
											2008-08-07 15:16:48 +00:00
										 |  |  | 	l = (float)(level) * (float)(l) / 100.0; | 
					
						
							|  |  |  | 	r = (float)(level) * (float)(r) / 100.0; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	return (l << 8) | r; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-08-07 15:16:48 +00:00
										 |  |  | static float mutedlevel(float orig, float level) | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float master = orig; | 
					
						
							| 
									
										
										
										
											2008-08-07 15:16:48 +00:00
										 |  |  | 	master = level * master / 100.0; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | 	return master; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void mute(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	int vol; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | 	int start; | 
					
						
							|  |  |  | 	int x; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 	float vol; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | 	float start = 1.0; | 
					
						
							|  |  |  | 	float x; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	vol = getvol(); | 
					
						
							|  |  |  | 	oldvol = vol; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | 	if (smoothfade) | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | #ifdef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | 		start = mutelevel; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		start = 100; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		start = mutelevel; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifdef __Darwin__
 | 
					
						
							|  |  |  | 		printf("Mute from '%f' to '%f'!\n", oldvol, mutevol); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		printf("Mute from '%04x' to '%04x'!\n", oldvol, mutevol); | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	muted = 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void unmute(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifdef __Darwin__
 | 
					
						
							|  |  |  | 	float vol; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | 	float start; | 
					
						
							|  |  |  | 	float x; | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	int vol; | 
					
						
							|  |  |  | 	int start; | 
					
						
							|  |  |  | 	int x; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	vol = getvol(); | 
					
						
							|  |  |  | 	if (debug) | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifdef __Darwin__
 | 
					
						
							|  |  |  | 		printf("Unmute from '%f' (should be '%f') to '%f'!\n", vol, mutevol, oldvol); | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | 	mutevol = vol; | 
					
						
							|  |  |  | 	if (vol == mutevol) { | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		printf("Unmute from '%04x' (should be '%04x') to '%04x'!\n", vol, mutevol, oldvol); | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | 	if ((int)vol == mutevol) { | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		if (smoothfade) | 
					
						
							|  |  |  | 			start = mutelevel; | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | #ifdef __Darwin__
 | 
					
						
							|  |  |  | 			start = 1.0; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 			start = 100; | 
					
						
							| 
									
										
										
										
											2005-07-18 15:51:09 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		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) { | 
					
						
							| 
									
										
										
										
											2004-05-17 07:00:21 +00:00
										 |  |  | 		if (chan->subs) { | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 			offhook++; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		chan = chan->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (offhook && !muted) | 
					
						
							|  |  |  | 		mute(); | 
					
						
							|  |  |  | 	else if (!offhook && muted) | 
					
						
							|  |  |  | 		unmute(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 07:00:21 +00:00
										 |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | 		if (!strcasecmp(sub->name, name)) | 
					
						
							| 
									
										
										
										
											2004-05-17 07:00:21 +00:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		sub = sub->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sub = malloc(sizeof(struct subchannel)); | 
					
						
							|  |  |  | 	if (sub) { | 
					
						
							|  |  |  | 		memset(sub, 0, sizeof(struct subchannel)); | 
					
						
							| 
									
										
										
										
											2006-10-24 01:28:45 +00:00
										 |  |  | 		if (!(sub->name = strdup(name))) { | 
					
						
							|  |  |  | 			free(sub); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-05-17 07:00:21 +00:00
										 |  |  | 		sub->next = chan->subs; | 
					
						
							|  |  |  | 		chan->subs = sub; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | static void hangup_chan(char *channel) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct channel *chan; | 
					
						
							| 
									
										
										
										
											2004-05-19 03:16:59 +00:00
										 |  |  | 	if (debug) | 
					
						
							|  |  |  | 		printf("Hangup '%s'\n", channel); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	chan = find_channel(channel); | 
					
						
							|  |  |  | 	if (chan) | 
					
						
							| 
									
										
										
										
											2004-05-17 07:00:21 +00:00
										 |  |  | 		delete_sub(chan, channel); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	check_mute(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void offhook_chan(char *channel) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct channel *chan; | 
					
						
							| 
									
										
										
										
											2004-05-19 03:16:59 +00:00
										 |  |  | 	if (debug) | 
					
						
							|  |  |  | 		printf("Offhook '%s'\n", channel); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	chan = find_channel(channel); | 
					
						
							|  |  |  | 	if (chan) | 
					
						
							| 
									
										
										
										
											2004-05-17 07:00:21 +00:00
										 |  |  | 		append_sub(chan, channel); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	check_mute(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int wait_event(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *resp; | 
					
						
							| 
									
										
										
										
											2004-05-19 03:16:59 +00:00
										 |  |  | 	char event[120]=""; | 
					
						
							|  |  |  | 	char channel[120]=""; | 
					
						
							|  |  |  | 	char oldname[120]=""; | 
					
						
							|  |  |  | 	char newname[120]=""; | 
					
						
							| 
									
										
										
										
											2005-11-14 19:00:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	resp = get_line(); | 
					
						
							|  |  |  | 	if (!resp) { | 
					
						
							|  |  |  | 		fprintf(stderr, "disconnected (6)\n"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!strncasecmp(resp, "Event: ", strlen("Event: "))) { | 
					
						
							| 
									
										
										
										
											2020-06-01 18:25:48 -05:00
										 |  |  | 		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: ")); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		/* Consume the rest of the non-event */ | 
					
						
							|  |  |  | 		while((resp = get_line()) && strlen(resp)) { | 
					
						
							|  |  |  | 			if (!strncasecmp(resp, "Channel: ", strlen("Channel: "))) | 
					
						
							| 
									
										
										
										
											2020-06-01 18:25:48 -05:00
										 |  |  | 				channel_len = snprintf(channel, sizeof(channel), "%s", resp + strlen("Channel: ")); | 
					
						
							| 
									
										
										
										
											2004-05-19 03:16:59 +00:00
										 |  |  | 			if (!strncasecmp(resp, "Newname: ", strlen("Newname: "))) | 
					
						
							| 
									
										
										
										
											2020-06-01 18:25:48 -05:00
										 |  |  | 				newname_len = snprintf(newname, sizeof(newname), "%s", resp + strlen("Newname: ")); | 
					
						
							| 
									
										
										
										
											2004-05-19 03:16:59 +00:00
										 |  |  | 			if (!strncasecmp(resp, "Oldname: ", strlen("Oldname: "))) | 
					
						
							| 
									
										
										
										
											2020-06-01 18:25:48 -05:00
										 |  |  | 				oldname_len = snprintf(oldname, sizeof(oldname), "%s", resp + strlen("Oldname: ")); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-01 18:25:48 -05:00
										 |  |  | 		if (channel_len == strlen(channel)) { | 
					
						
							|  |  |  | 			if (event_len == strlen(event) && !strcasecmp(event, "Hangup")) | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 				hangup_chan(channel); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				offhook_chan(channel); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-06-01 18:25:48 -05:00
										 |  |  | 		if (newname_len == strlen(newname) && oldname_len == strlen(oldname)) { | 
					
						
							|  |  |  | 			if (event_len == strlen(event) && !strcasecmp(event, "Rename")) { | 
					
						
							| 
									
										
										
										
											2004-05-19 03:16:59 +00:00
										 |  |  | 				hangup_chan(oldname); | 
					
						
							|  |  |  | 				offhook_chan(newname); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	} 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" | 
					
						
							| 
									
										
										
										
											2005-11-14 19:00:38 +00:00
										 |  |  | 	       "        -d : Debug (implies -f)\n"); | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	if (open_mixer()) | 
					
						
							|  |  |  | 		exit(1); | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	if (connect_asterisk()) { | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		close(mixfd); | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		exit(1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (login_asterisk()) { | 
					
						
							| 
									
										
										
										
											2015-05-03 05:09:57 -04:00
										 |  |  | #ifndef __Darwin__
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		close(mixfd); | 
					
						
							| 
									
										
										
										
											2005-07-18 04:22:08 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 		fclose(astf); | 
					
						
							|  |  |  | 		exit(1); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-07-08 16:43:12 +00:00
										 |  |  | #ifdef HAVE_WORKING_FORK
 | 
					
						
							| 
									
										
										
										
											2008-02-04 21:15:18 +00:00
										 |  |  | 	if (needfork) { | 
					
						
							|  |  |  | #ifndef HAVE_SBIN_LAUNCHD
 | 
					
						
							| 
									
										
										
										
											2008-11-02 18:52:13 +00:00
										 |  |  | 		if (daemon(0,0) < 0) { | 
					
						
							|  |  |  | 			fprintf(stderr, "daemon() failed: %s\n", strerror(errno)); | 
					
						
							|  |  |  | 			exit(1); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-02-04 21:15:18 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | 		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]); | 
					
						
							| 
									
										
										
										
											2008-02-04 21:15:18 +00:00
										 |  |  | 		exit(1); | 
					
						
							| 
									
										
										
										
											2010-12-07 22:54:00 +00:00
										 |  |  | #endif /* !defined(HAVE_SBIN_LAUNCHD */
 | 
					
						
							| 
									
										
										
										
											2008-02-04 21:15:18 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-04-21 15:54:16 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	for(;;) { | 
					
						
							| 
									
										
										
										
											2004-08-03 06:31:20 +00:00
										 |  |  | 		if (wait_event()) { | 
					
						
							|  |  |  | 			fclose(astf); | 
					
						
							|  |  |  | 			while(connect_asterisk()) { | 
					
						
							|  |  |  | 				sleep(5); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (login_asterisk()) { | 
					
						
							|  |  |  | 				fclose(astf); | 
					
						
							|  |  |  | 				exit(1); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-05-17 06:31:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	exit(0); | 
					
						
							|  |  |  | } |