54 #include <CoreAudio/AudioHardware.h> 55 #include <sys/types.h> 58 #elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__GLIBC__) 59 #include <sys/soundcard.h> 68 #include <sys/socket.h> 69 #include <sys/ioctl.h> 70 #include <netinet/in.h> 71 #include <arpa/inet.h> 73 #define ast_strlen_zero(a) (!(*(a))) 75 static char *
config =
"/etc/asterisk/muted.conf";
77 static char host[256] =
"";
78 static char user[256] =
"";
79 static char pass[256] =
"";
107 memset(chan, 0,
sizeof(
struct channel));
133 fprintf(stderr,
"Unable to open config file '%s': %s\n",
config, strerror(
errno));
137 if (!fgets(buf,
sizeof(buf), f)) {
142 val = strchr(buf,
'#');
143 if (val) *val =
'\0';
144 while(strlen(buf) && (buf[strlen(buf) - 1] < 33))
145 buf[strlen(buf) - 1] =
'\0';
157 while(*val && (*val < 33)) val++;
159 if (!strcasecmp(buf,
"host")) {
160 if (val && strlen(val))
161 strncpy(
host, val,
sizeof(
host) - 1);
163 fprintf(stderr,
"host needs an argument (the host) at line %d\n", lineno);
164 }
else if (!strcasecmp(buf,
"user")) {
165 if (val && strlen(val))
166 snprintf(
user,
sizeof(
user),
"%s", val);
168 fprintf(stderr,
"user needs an argument (the user) at line %d\n", lineno);
169 }
else if (!strcasecmp(buf,
"pass")) {
170 if (val && strlen(val))
171 snprintf(
pass,
sizeof(
pass),
"%s", val);
173 fprintf(stderr,
"pass needs an argument (the password) at line %d\n", lineno);
174 }
else if (!strcasecmp(buf,
"smoothfade")) {
176 }
else if (!strcasecmp(buf,
"mutelevel")) {
177 if (val && (sscanf(val,
"%3d", &x) == 1) && (x > -1) && (x < 101)) {
180 fprintf(stderr,
"mutelevel must be a number from 0 (most muted) to 100 (no mute) at line %d\n", lineno);
181 }
else if (!strcasecmp(buf,
"channel")) {
182 if (val && strlen(val)) {
183 val2 = strchr(val,
'/');
189 fprintf(stderr,
"channel needs to be of the format Tech/Location at line %d\n", lineno);
191 fprintf(stderr,
"channel needs an argument (the channel) at line %d\n", lineno);
193 fprintf(stderr,
"ignoring unknown keyword '%s'\n", buf);
199 fprintf(stderr,
"no 'host' specification in config file\n");
200 else if (!strlen(
user))
201 fprintf(stderr,
"no 'user' specification in config file\n");
203 fprintf(stderr,
"no 'channel' specifications in config file\n");
215 mixfd = open(
"/dev/mixer", O_RDWR);
217 fprintf(stderr,
"Unable to open /dev/mixer: %s\n", strerror(
errno));
231 struct sockaddr_in sin;
233 ports = strchr(
host,
':');
237 if ((sscanf(ports,
"%5d", &port) != 1) || (port < 1) || (port > 65535)) {
238 fprintf(stderr,
"'%s' is not a valid port number in the hostname\n", ports);
244 fprintf(stderr,
"Can't find host '%s'\n",
host);
247 sock = socket(AF_INET, SOCK_STREAM, 0);
249 fprintf(stderr,
"Failed to create socket: %s\n", strerror(
errno));
252 sin.sin_family = AF_INET;
253 sin.sin_port = htons(port);
254 memcpy(&sin.sin_addr, hp->h_addr,
sizeof(sin.sin_addr));
255 if (connect(sock, (
struct sockaddr *)&sin,
sizeof(sin))) {
256 fprintf(stderr,
"Failed to connect to '%s' port '%d': %s\n",
host, port, strerror(
errno));
260 astf = fdopen(sock,
"r+");
262 fprintf(stderr,
"fdopen failed: %s\n", strerror(
errno));
271 static char buf[1024];
272 if (fgets(buf,
sizeof(buf),
astf)) {
273 while(strlen(buf) && (buf[strlen(buf) - 1] < 33))
274 buf[strlen(buf) - 1] =
'\0';
286 fprintf(stderr,
"disconnected (1)\n");
294 fprintf(stderr,
"disconnected (2)\n");
297 if (strcasecmp(welcome,
"Response: Success")) {
298 fprintf(stderr,
"login failed ('%s')\n", welcome);
302 while((resp =
get_line()) && strlen(resp));
304 fprintf(stderr,
"disconnected (3)\n");
308 "Action: Status\r\n\r\n");
310 fprintf(stderr,
"disconnected (4)\n");
313 if (strcasecmp(welcome,
"Response: Success")) {
314 fprintf(stderr,
"status failed ('%s')\n", welcome);
318 while((resp =
get_line()) && strlen(resp));
320 fprintf(stderr,
"disconnected (5)\n");
330 struct channel *chan;
331 strncpy(tmp, channel,
sizeof(tmp) - 1);
332 s = strchr(tmp,
'/');
341 printf(
"Searching for '%s' tech, '%s' location\n", tmp, s);
344 if (!strcasecmp(chan->
tech, tmp) && !strcasecmp(chan->
location, s)) {
346 printf(
"Found '%s'/'%s'\n", chan->
tech, chan->
location);
365 float volumeL, volumeR, vol;
367 AudioDeviceID device;
370 AudioObjectPropertyAddress OutputAddr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
371 AudioObjectPropertyAddress ChannelAddr = { kAudioDevicePropertyPreferredChannelsForStereo, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementWildcard };
372 AudioObjectPropertyAddress VolumeAddr = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, };
374 size =
sizeof(device);
375 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &OutputAddr, 0,
NULL, &size, &device);
378 err = AudioObjectGetPropertyData(device, &ChannelAddr, 0,
NULL, &size, &channels);
382 VolumeAddr.mElement = channels[0];
383 err = AudioObjectGetPropertyData(device, &VolumeAddr, 0,
NULL, &size, &volumeL);
386 VolumeAddr.mElement = channels[1];
387 err = AudioObjectGetPropertyData(device, &VolumeAddr, 0,
NULL, &size, &volumeR);
390 vol = (volumeL < volumeR) ? volumeR : volumeL;
393 fprintf(stderr,
"Unable to read mixer volume: %s\n", strerror(
errno));
402 static int setvol(
float vol)
411 AudioDeviceID device;
414 AudioObjectPropertyAddress OutputAddr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
415 AudioObjectPropertyAddress ChannelAddr = { kAudioDevicePropertyPreferredChannelsForStereo, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementWildcard };
416 AudioObjectPropertyAddress VolumeAddr = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, };
418 size =
sizeof(device);
419 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &OutputAddr, 0,
NULL, &size, &device);
421 err = AudioObjectGetPropertyData(device, &ChannelAddr, 0,
NULL, &size, &channels);
424 VolumeAddr.mElement = channels[0];
425 err = AudioObjectSetPropertyData(device, &VolumeAddr, 0,
NULL, size, &volumeL);
428 VolumeAddr.mElement = channels[1];
429 err = AudioObjectSetPropertyData(device, &VolumeAddr, 0,
NULL, size, &volumeR);
434 fprintf(stderr,
"Unable to write mixer volume: %s\n", strerror(
errno));
445 static float oldvol = 0;
446 static float mutevol = 0;
454 l = (float)(level) * (float)(l) / 100.0;
455 r = (float)(level) * (float)(r) / 100.0;
459 static float mutedlevel(
float orig,
float level)
462 master = level * master / 100.0;
499 printf(
"Mute from '%f' to '%f'!\n", oldvol, mutevol);
501 printf(
"Mute from '%04x' to '%04x'!\n", oldvol, mutevol);
520 printf(
"Unmute from '%f' (should be '%f') to '%f'!\n", vol, mutevol, oldvol);
522 if (vol == mutevol) {
524 printf(
"Unmute from '%04x' (should be '%04x') to '%04x'!\n", vol, mutevol, oldvol);
525 if ((
int)vol == mutevol) {
543 printf(
"Whoops, it's already been changed!\n");
559 if (offhook && !
muted)
561 else if (!offhook &&
muted)
571 if (!strcasecmp(sub->
name, name)) {
590 if (!strcasecmp(sub->
name, name))
608 struct channel *chan;
610 printf(
"Hangup '%s'\n", channel);
619 struct channel *chan;
621 printf(
"Offhook '%s'\n", channel);
633 char oldname[120]=
"";
634 char newname[120]=
"";
638 fprintf(stderr,
"disconnected (6)\n");
641 if (!strncasecmp(resp,
"Event: ", strlen(
"Event: "))) {
643 int channel_len = -1;
644 int newname_len = -1;
645 int oldname_len = -1;
647 event_len = snprintf(
event,
sizeof(
event),
"%s", resp + strlen(
"Event: "));
649 while((resp =
get_line()) && strlen(resp)) {
650 if (!strncasecmp(resp,
"Channel: ", strlen(
"Channel: ")))
651 channel_len = snprintf(channel,
sizeof(channel),
"%s", resp + strlen(
"Channel: "));
652 if (!strncasecmp(resp,
"Newname: ", strlen(
"Newname: ")))
653 newname_len = snprintf(newname,
sizeof(newname),
"%s", resp + strlen(
"Newname: "));
654 if (!strncasecmp(resp,
"Oldname: ", strlen(
"Oldname: ")))
655 oldname_len = snprintf(oldname,
sizeof(oldname),
"%s", resp + strlen(
"Oldname: "));
657 if (channel_len == strlen(channel)) {
658 if (event_len == strlen(
event) && !strcasecmp(
event,
"Hangup"))
663 if (newname_len == strlen(newname) && oldname_len == strlen(oldname)) {
664 if (event_len == strlen(
event) && !strcasecmp(
event,
"Rename")) {
671 while((resp =
get_line()) && strlen(resp));
674 fprintf(stderr,
"disconnected (7)\n");
682 printf(
"Usage: muted [-f] [-d]\n" 683 " -f : Do not fork\n" 684 " -d : Debug (implies -f)\n");
687 int main(
int argc,
char *argv[])
690 while((x = getopt(argc, argv,
"fhd")) > 0) {
725 #ifdef HAVE_WORKING_FORK 727 #ifndef HAVE_SBIN_LAUNCHD 728 if (daemon(0,0) < 0) {
729 fprintf(stderr,
"daemon() failed: %s\n", strerror(
errno));
733 const char *found =
NULL, *paths[] = {
734 "/Library/LaunchAgents/org.asterisk.muted.plist",
735 "/Library/LaunchDaemons/org.asterisk.muted.plist",
736 "contrib/init.d/org.asterisk.muted.plist",
737 "<path-to-asterisk-source>/contrib/init.d/org.asterisk.muted.plist" };
740 struct passwd *pwd = getpwuid(getuid());
743 snprintf(userpath,
sizeof(userpath),
"%s%s", pwd->pw_dir, paths[0]);
744 if (!stat(userpath, &unused)) {
749 for (i = 0; i < 3; i++) {
750 if (!stat(paths[i], &unused)) {
757 fprintf(stderr,
"Mac OS X detected. Use 'launchctl load -w %s' to launch.\n", found ? found : paths[3]);
static void check_mute(void)
static int wait_event(void)
static int mutedlevel(int orig, int level)
static void delete_sub(struct channel *chan, char *name)
static void offhook_chan(char *channel)
static int connect_asterisk(void)
static void append_sub(struct channel *chan, char *name)
static int login_asterisk(void)
static struct channel * channels
static int open_mixer(void)
static void hangup_chan(char *channel)
static int load_config(void)
static char * get_line(void)
structure to hold users read from users.conf
static struct channel * find_channel(char *channel)
static int setvol(int vol)
struct stasis_forward * sub
static void add_channel(char *tech, char *location)
static struct hostent * hp
int main(int argc, char *argv[])