muted.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2005, Digium, Inc.
  5. *
  6. * Mark Spencer <markster@digium.com>
  7. *
  8. * Updated for Mac OSX CoreAudio
  9. * by Josh Roberson <josh@asteriasgi.com>
  10. *
  11. * See http://www.asterisk.org for more information about
  12. * the Asterisk project. Please do not directly contact
  13. * any of the maintainers of this project for assistance;
  14. * the project provides a web site, mailing lists and IRC
  15. * channels for your use.
  16. *
  17. * This program is free software, distributed under the terms of
  18. * the GNU General Public License Version 2. See the LICENSE file
  19. * at the top of the source tree.
  20. */
  21. /*! \file
  22. *
  23. * \brief Mute Daemon
  24. *
  25. * \author Mark Spencer <markster@digium.com>
  26. *
  27. * Updated for Mac OSX CoreAudio
  28. * \arg Josh Roberson <josh@asteriasgi.com>
  29. *
  30. * \note Specially written for Malcolm Davenport, but I think I'll use it too
  31. * Connects to the Asterisk Manager Interface, AMI, and listens for events
  32. * on certain devices. If a phone call is connected to one of the devices (phones)
  33. * the local sound is muted to a lower volume during the call.
  34. *
  35. */
  36. /*** MODULEINFO
  37. <support_level>extended</support_level>
  38. ***/
  39. #include "asterisk/autoconfig.h"
  40. #ifdef __Darwin__
  41. #include <CoreAudio/AudioHardware.h>
  42. #include <sys/types.h>
  43. #include <pwd.h>
  44. #include <sys/stat.h>
  45. #elif defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__)
  46. #include <sys/soundcard.h>
  47. #endif
  48. #include <stdio.h>
  49. #include <errno.h>
  50. #include <stdlib.h>
  51. #include <unistd.h>
  52. #include <fcntl.h>
  53. #include <string.h>
  54. #include <netdb.h>
  55. #include <sys/socket.h>
  56. #include <sys/ioctl.h>
  57. #include <netinet/in.h>
  58. #include <arpa/inet.h>
  59. #define ast_strlen_zero(a) (!(*(a)))
  60. static char *config = "/etc/asterisk/muted.conf";
  61. static char host[256] = "";
  62. static char user[256] = "";
  63. static char pass[256] = "";
  64. static int smoothfade = 0;
  65. static int mutelevel = 20;
  66. static int muted = 0;
  67. static int needfork = 1;
  68. static int debug = 0;
  69. static int stepsize = 3;
  70. #ifndef __Darwin__
  71. static int mixchan = SOUND_MIXER_VOLUME;
  72. #endif
  73. struct subchannel {
  74. char *name;
  75. struct subchannel *next;
  76. };
  77. static struct channel {
  78. char *tech;
  79. char *location;
  80. struct channel *next;
  81. struct subchannel *subs;
  82. } *channels;
  83. static void add_channel(char *tech, char *location)
  84. {
  85. struct channel *chan;
  86. chan = malloc(sizeof(struct channel));
  87. if (chan) {
  88. memset(chan, 0, sizeof(struct channel));
  89. if (!(chan->tech = strdup(tech))) {
  90. free(chan);
  91. return;
  92. }
  93. if (!(chan->location = strdup(location))) {
  94. free(chan->tech);
  95. free(chan);
  96. return;
  97. }
  98. chan->next = channels;
  99. channels = chan;
  100. }
  101. }
  102. static int load_config(void)
  103. {
  104. FILE *f;
  105. char buf[1024];
  106. char *val;
  107. char *val2;
  108. int lineno=0;
  109. int x;
  110. f = fopen(config, "r");
  111. if (!f) {
  112. fprintf(stderr, "Unable to open config file '%s': %s\n", config, strerror(errno));
  113. return -1;
  114. }
  115. while(!feof(f)) {
  116. if (!fgets(buf, sizeof(buf), f)) {
  117. continue;
  118. }
  119. if (!feof(f)) {
  120. lineno++;
  121. val = strchr(buf, '#');
  122. if (val) *val = '\0';
  123. while(strlen(buf) && (buf[strlen(buf) - 1] < 33))
  124. buf[strlen(buf) - 1] = '\0';
  125. if (!strlen(buf))
  126. continue;
  127. val = buf;
  128. while(*val) {
  129. if (*val < 33)
  130. break;
  131. val++;
  132. }
  133. if (*val) {
  134. *val = '\0';
  135. val++;
  136. while(*val && (*val < 33)) val++;
  137. }
  138. if (!strcasecmp(buf, "host")) {
  139. if (val && strlen(val))
  140. strncpy(host, val, sizeof(host) - 1);
  141. else
  142. fprintf(stderr, "host needs an argument (the host) at line %d\n", lineno);
  143. } else if (!strcasecmp(buf, "user")) {
  144. if (val && strlen(val))
  145. strncpy(user, val, sizeof(user) - 1);
  146. else
  147. fprintf(stderr, "user needs an argument (the user) at line %d\n", lineno);
  148. } else if (!strcasecmp(buf, "pass")) {
  149. if (val && strlen(val))
  150. strncpy(pass, val, sizeof(pass) - 1);
  151. else
  152. fprintf(stderr, "pass needs an argument (the password) at line %d\n", lineno);
  153. } else if (!strcasecmp(buf, "smoothfade")) {
  154. smoothfade = 1;
  155. } else if (!strcasecmp(buf, "mutelevel")) {
  156. if (val && (sscanf(val, "%3d", &x) == 1) && (x > -1) && (x < 101)) {
  157. mutelevel = x;
  158. } else
  159. fprintf(stderr, "mutelevel must be a number from 0 (most muted) to 100 (no mute) at line %d\n", lineno);
  160. } else if (!strcasecmp(buf, "channel")) {
  161. if (val && strlen(val)) {
  162. val2 = strchr(val, '/');
  163. if (val2) {
  164. *val2 = '\0';
  165. val2++;
  166. add_channel(val, val2);
  167. } else
  168. fprintf(stderr, "channel needs to be of the format Tech/Location at line %d\n", lineno);
  169. } else
  170. fprintf(stderr, "channel needs an argument (the channel) at line %d\n", lineno);
  171. } else {
  172. fprintf(stderr, "ignoring unknown keyword '%s'\n", buf);
  173. }
  174. }
  175. }
  176. fclose(f);
  177. if (!strlen(host))
  178. fprintf(stderr, "no 'host' specification in config file\n");
  179. else if (!strlen(user))
  180. fprintf(stderr, "no 'user' specification in config file\n");
  181. else if (!channels)
  182. fprintf(stderr, "no 'channel' specifications in config file\n");
  183. else
  184. return 0;
  185. return -1;
  186. }
  187. static FILE *astf;
  188. #ifndef __Darwin__
  189. static int mixfd;
  190. static int open_mixer(void)
  191. {
  192. mixfd = open("/dev/mixer", O_RDWR);
  193. if (mixfd < 0) {
  194. fprintf(stderr, "Unable to open /dev/mixer: %s\n", strerror(errno));
  195. return -1;
  196. }
  197. return 0;
  198. }
  199. #endif /* !__Darwin */
  200. /*! Connect to the asterisk manager interface */
  201. static int connect_asterisk(void)
  202. {
  203. int sock;
  204. struct hostent *hp;
  205. char *ports;
  206. int port = 5038;
  207. struct sockaddr_in sin;
  208. ports = strchr(host, ':');
  209. if (ports) {
  210. *ports = '\0';
  211. ports++;
  212. if ((sscanf(ports, "%5d", &port) != 1) || (port < 1) || (port > 65535)) {
  213. fprintf(stderr, "'%s' is not a valid port number in the hostname\n", ports);
  214. return -1;
  215. }
  216. }
  217. hp = gethostbyname(host);
  218. if (!hp) {
  219. fprintf(stderr, "Can't find host '%s'\n", host);
  220. return -1;
  221. }
  222. sock = socket(AF_INET, SOCK_STREAM, 0);
  223. if (sock < 0) {
  224. fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
  225. return -1;
  226. }
  227. sin.sin_family = AF_INET;
  228. sin.sin_port = htons(port);
  229. memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
  230. if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) {
  231. fprintf(stderr, "Failed to connect to '%s' port '%d': %s\n", host, port, strerror(errno));
  232. close(sock);
  233. return -1;
  234. }
  235. astf = fdopen(sock, "r+");
  236. if (!astf) {
  237. fprintf(stderr, "fdopen failed: %s\n", strerror(errno));
  238. close(sock);
  239. return -1;
  240. }
  241. return 0;
  242. }
  243. static char *get_line(void)
  244. {
  245. static char buf[1024];
  246. if (fgets(buf, sizeof(buf), astf)) {
  247. while(strlen(buf) && (buf[strlen(buf) - 1] < 33))
  248. buf[strlen(buf) - 1] = '\0';
  249. return buf;
  250. } else
  251. return NULL;
  252. }
  253. /*! Login to the asterisk manager interface */
  254. static int login_asterisk(void)
  255. {
  256. char *welcome;
  257. char *resp;
  258. if (!(welcome = get_line())) {
  259. fprintf(stderr, "disconnected (1)\n");
  260. return -1;
  261. }
  262. fprintf(astf,
  263. "Action: Login\r\n"
  264. "Username: %s\r\n"
  265. "Secret: %s\r\n\r\n", user, pass);
  266. if (!(welcome = get_line())) {
  267. fprintf(stderr, "disconnected (2)\n");
  268. return -1;
  269. }
  270. if (strcasecmp(welcome, "Response: Success")) {
  271. fprintf(stderr, "login failed ('%s')\n", welcome);
  272. return -1;
  273. }
  274. /* Eat the rest of the event */
  275. while((resp = get_line()) && strlen(resp));
  276. if (!resp) {
  277. fprintf(stderr, "disconnected (3)\n");
  278. return -1;
  279. }
  280. fprintf(astf,
  281. "Action: Status\r\n\r\n");
  282. if (!(welcome = get_line())) {
  283. fprintf(stderr, "disconnected (4)\n");
  284. return -1;
  285. }
  286. if (strcasecmp(welcome, "Response: Success")) {
  287. fprintf(stderr, "status failed ('%s')\n", welcome);
  288. return -1;
  289. }
  290. /* Eat the rest of the event */
  291. while((resp = get_line()) && strlen(resp));
  292. if (!resp) {
  293. fprintf(stderr, "disconnected (5)\n");
  294. return -1;
  295. }
  296. return 0;
  297. }
  298. static struct channel *find_channel(char *channel)
  299. {
  300. char tmp[256] = "";
  301. char *s, *t;
  302. struct channel *chan;
  303. strncpy(tmp, channel, sizeof(tmp) - 1);
  304. s = strchr(tmp, '/');
  305. if (s) {
  306. *s = '\0';
  307. s++;
  308. t = strrchr(s, '-');
  309. if (t) {
  310. *t = '\0';
  311. }
  312. if (debug)
  313. printf("Searching for '%s' tech, '%s' location\n", tmp, s);
  314. chan = channels;
  315. while(chan) {
  316. if (!strcasecmp(chan->tech, tmp) && !strcasecmp(chan->location, s)) {
  317. if (debug)
  318. printf("Found '%s'/'%s'\n", chan->tech, chan->location);
  319. break;
  320. }
  321. chan = chan->next;
  322. }
  323. } else
  324. chan = NULL;
  325. return chan;
  326. }
  327. #ifndef __Darwin__
  328. static int getvol(void)
  329. {
  330. int vol;
  331. if (ioctl(mixfd, MIXER_READ(mixchan), &vol)) {
  332. #else
  333. static float getvol(void)
  334. {
  335. float volumeL, volumeR, vol;
  336. OSStatus err;
  337. AudioDeviceID device;
  338. UInt32 size;
  339. UInt32 channels[2];
  340. AudioObjectPropertyAddress OutputAddr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  341. AudioObjectPropertyAddress ChannelAddr = { kAudioDevicePropertyPreferredChannelsForStereo, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementWildcard };
  342. AudioObjectPropertyAddress VolumeAddr = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, };
  343. size = sizeof(device);
  344. err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &OutputAddr, 0, NULL, &size, &device);
  345. size = sizeof(channels);
  346. if (!err) {
  347. err = AudioObjectGetPropertyData(device, &ChannelAddr, 0, NULL, &size, &channels);
  348. }
  349. size = sizeof(vol);
  350. if (!err) {
  351. VolumeAddr.mElement = channels[0];
  352. err = AudioObjectGetPropertyData(device, &VolumeAddr, 0, NULL, &size, &volumeL);
  353. }
  354. if (!err) {
  355. VolumeAddr.mElement = channels[1];
  356. err = AudioObjectGetPropertyData(device, &VolumeAddr, 0, NULL, &size, &volumeR);
  357. }
  358. if (!err)
  359. vol = (volumeL < volumeR) ? volumeR : volumeL;
  360. else {
  361. #endif
  362. fprintf(stderr, "Unable to read mixer volume: %s\n", strerror(errno));
  363. return -1;
  364. }
  365. return vol;
  366. }
  367. #ifndef __Darwin__
  368. static int setvol(int vol)
  369. #else
  370. static int setvol(float vol)
  371. #endif
  372. {
  373. #ifndef __Darwin__
  374. if (ioctl(mixfd, MIXER_WRITE(mixchan), &vol)) {
  375. #else
  376. float volumeL = vol;
  377. float volumeR = vol;
  378. OSStatus err;
  379. AudioDeviceID device;
  380. UInt32 size;
  381. UInt32 channels[2];
  382. AudioObjectPropertyAddress OutputAddr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  383. AudioObjectPropertyAddress ChannelAddr = { kAudioDevicePropertyPreferredChannelsForStereo, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementWildcard };
  384. AudioObjectPropertyAddress VolumeAddr = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, };
  385. size = sizeof(device);
  386. err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &OutputAddr, 0, NULL, &size, &device);
  387. size = sizeof(channels);
  388. err = AudioObjectGetPropertyData(device, &ChannelAddr, 0, NULL, &size, &channels);
  389. size = sizeof(vol);
  390. if (!err) {
  391. VolumeAddr.mElement = channels[0];
  392. err = AudioObjectSetPropertyData(device, &VolumeAddr, 0, NULL, size, &volumeL);
  393. }
  394. if (!err) {
  395. VolumeAddr.mElement = channels[1];
  396. err = AudioObjectSetPropertyData(device, &VolumeAddr, 0, NULL, size, &volumeR);
  397. }
  398. if (err) {
  399. #endif
  400. fprintf(stderr, "Unable to write mixer volume: %s\n", strerror(errno));
  401. return -1;
  402. }
  403. return 0;
  404. }
  405. #ifndef __Darwin__
  406. static int oldvol = 0;
  407. static int mutevol = 0;
  408. #else
  409. static float oldvol = 0;
  410. static float mutevol = 0;
  411. #endif
  412. #ifndef __Darwin__
  413. static int mutedlevel(int orig, int level)
  414. {
  415. int l = orig >> 8;
  416. int r = orig & 0xff;
  417. l = (float)(level) * (float)(l) / 100.0;
  418. r = (float)(level) * (float)(r) / 100.0;
  419. return (l << 8) | r;
  420. #else
  421. static float mutedlevel(float orig, float level)
  422. {
  423. float master = orig;
  424. master = level * master / 100.0;
  425. return master;
  426. #endif
  427. }
  428. static void mute(void)
  429. {
  430. #ifndef __Darwin__
  431. int vol;
  432. int start;
  433. int x;
  434. #else
  435. float vol;
  436. float start = 1.0;
  437. float x;
  438. #endif
  439. vol = getvol();
  440. oldvol = vol;
  441. if (smoothfade)
  442. #ifdef __Darwin__
  443. start = mutelevel;
  444. #else
  445. start = 100;
  446. else
  447. start = mutelevel;
  448. #endif
  449. for (x=start;x>=mutelevel;x-=stepsize) {
  450. mutevol = mutedlevel(vol, x);
  451. setvol(mutevol);
  452. /* Wait 0.01 sec */
  453. usleep(10000);
  454. }
  455. mutevol = mutedlevel(vol, mutelevel);
  456. setvol(mutevol);
  457. if (debug)
  458. #ifdef __Darwin__
  459. printf("Mute from '%f' to '%f'!\n", oldvol, mutevol);
  460. #else
  461. printf("Mute from '%04x' to '%04x'!\n", oldvol, mutevol);
  462. #endif
  463. muted = 1;
  464. }
  465. static void unmute(void)
  466. {
  467. #ifdef __Darwin__
  468. float vol;
  469. float start;
  470. float x;
  471. #else
  472. int vol;
  473. int start;
  474. int x;
  475. #endif
  476. vol = getvol();
  477. if (debug)
  478. #ifdef __Darwin__
  479. printf("Unmute from '%f' (should be '%f') to '%f'!\n", vol, mutevol, oldvol);
  480. mutevol = vol;
  481. if (vol == mutevol) {
  482. #else
  483. printf("Unmute from '%04x' (should be '%04x') to '%04x'!\n", vol, mutevol, oldvol);
  484. if ((int)vol == mutevol) {
  485. #endif
  486. if (smoothfade)
  487. start = mutelevel;
  488. else
  489. #ifdef __Darwin__
  490. start = 1.0;
  491. #else
  492. start = 100;
  493. #endif
  494. for (x=start;x<100;x+=stepsize) {
  495. mutevol = mutedlevel(oldvol, x);
  496. setvol(mutevol);
  497. /* Wait 0.01 sec */
  498. usleep(10000);
  499. }
  500. setvol(oldvol);
  501. } else
  502. printf("Whoops, it's already been changed!\n");
  503. muted = 0;
  504. }
  505. static void check_mute(void)
  506. {
  507. int offhook = 0;
  508. struct channel *chan;
  509. chan = channels;
  510. while(chan) {
  511. if (chan->subs) {
  512. offhook++;
  513. break;
  514. }
  515. chan = chan->next;
  516. }
  517. if (offhook && !muted)
  518. mute();
  519. else if (!offhook && muted)
  520. unmute();
  521. }
  522. static void delete_sub(struct channel *chan, char *name)
  523. {
  524. struct subchannel *sub, *prev;
  525. prev = NULL;
  526. sub = chan->subs;
  527. while(sub) {
  528. if (!strcasecmp(sub->name, name)) {
  529. if (prev)
  530. prev->next = sub->next;
  531. else
  532. chan->subs = sub->next;
  533. free(sub->name);
  534. free(sub);
  535. return;
  536. }
  537. prev = sub;
  538. sub = sub->next;
  539. }
  540. }
  541. static void append_sub(struct channel *chan, char *name)
  542. {
  543. struct subchannel *sub;
  544. sub = chan->subs;
  545. while(sub) {
  546. if (!strcasecmp(sub->name, name))
  547. return;
  548. sub = sub->next;
  549. }
  550. sub = malloc(sizeof(struct subchannel));
  551. if (sub) {
  552. memset(sub, 0, sizeof(struct subchannel));
  553. if (!(sub->name = strdup(name))) {
  554. free(sub);
  555. return;
  556. }
  557. sub->next = chan->subs;
  558. chan->subs = sub;
  559. }
  560. }
  561. static void hangup_chan(char *channel)
  562. {
  563. struct channel *chan;
  564. if (debug)
  565. printf("Hangup '%s'\n", channel);
  566. chan = find_channel(channel);
  567. if (chan)
  568. delete_sub(chan, channel);
  569. check_mute();
  570. }
  571. static void offhook_chan(char *channel)
  572. {
  573. struct channel *chan;
  574. if (debug)
  575. printf("Offhook '%s'\n", channel);
  576. chan = find_channel(channel);
  577. if (chan)
  578. append_sub(chan, channel);
  579. check_mute();
  580. }
  581. static int wait_event(void)
  582. {
  583. char *resp;
  584. char event[120]="";
  585. char channel[120]="";
  586. char oldname[120]="";
  587. char newname[120]="";
  588. resp = get_line();
  589. if (!resp) {
  590. fprintf(stderr, "disconnected (6)\n");
  591. return -1;
  592. }
  593. if (!strncasecmp(resp, "Event: ", strlen("Event: "))) {
  594. strncpy(event, resp + strlen("Event: "), sizeof(event) - 1);
  595. /* Consume the rest of the non-event */
  596. while((resp = get_line()) && strlen(resp)) {
  597. if (!strncasecmp(resp, "Channel: ", strlen("Channel: ")))
  598. strncpy(channel, resp + strlen("Channel: "), sizeof(channel) - 1);
  599. if (!strncasecmp(resp, "Newname: ", strlen("Newname: ")))
  600. strncpy(newname, resp + strlen("Newname: "), sizeof(newname) - 1);
  601. if (!strncasecmp(resp, "Oldname: ", strlen("Oldname: ")))
  602. strncpy(oldname, resp + strlen("Oldname: "), sizeof(oldname) - 1);
  603. }
  604. if (strlen(channel)) {
  605. if (!strcasecmp(event, "Hangup"))
  606. hangup_chan(channel);
  607. else
  608. offhook_chan(channel);
  609. }
  610. if (strlen(newname) && strlen(oldname)) {
  611. if (!strcasecmp(event, "Rename")) {
  612. hangup_chan(oldname);
  613. offhook_chan(newname);
  614. }
  615. }
  616. } else {
  617. /* Consume the rest of the non-event */
  618. while((resp = get_line()) && strlen(resp));
  619. }
  620. if (!resp) {
  621. fprintf(stderr, "disconnected (7)\n");
  622. return -1;
  623. }
  624. return 0;
  625. }
  626. static void usage(void)
  627. {
  628. printf("Usage: muted [-f] [-d]\n"
  629. " -f : Do not fork\n"
  630. " -d : Debug (implies -f)\n");
  631. }
  632. int main(int argc, char *argv[])
  633. {
  634. int x;
  635. while((x = getopt(argc, argv, "fhd")) > 0) {
  636. switch(x) {
  637. case 'd':
  638. debug = 1;
  639. needfork = 0;
  640. break;
  641. case 'f':
  642. needfork = 0;
  643. break;
  644. case 'h':
  645. /* Fall through */
  646. default:
  647. usage();
  648. exit(1);
  649. }
  650. }
  651. if (load_config())
  652. exit(1);
  653. #ifndef __Darwin__
  654. if (open_mixer())
  655. exit(1);
  656. #endif
  657. if (connect_asterisk()) {
  658. #ifndef __Darwin__
  659. close(mixfd);
  660. #endif
  661. exit(1);
  662. }
  663. if (login_asterisk()) {
  664. #ifndef __Darwin__
  665. close(mixfd);
  666. #endif
  667. fclose(astf);
  668. exit(1);
  669. }
  670. #ifdef HAVE_WORKING_FORK
  671. if (needfork) {
  672. #ifndef HAVE_SBIN_LAUNCHD
  673. if (daemon(0,0) < 0) {
  674. fprintf(stderr, "daemon() failed: %s\n", strerror(errno));
  675. exit(1);
  676. }
  677. #else
  678. const char *found = NULL, *paths[] = {
  679. "/Library/LaunchAgents/org.asterisk.muted.plist",
  680. "/Library/LaunchDaemons/org.asterisk.muted.plist",
  681. "contrib/init.d/org.asterisk.muted.plist",
  682. "<path-to-asterisk-source>/contrib/init.d/org.asterisk.muted.plist" };
  683. char userpath[256];
  684. struct stat unused;
  685. struct passwd *pwd = getpwuid(getuid());
  686. int i;
  687. snprintf(userpath, sizeof(userpath), "%s%s", pwd->pw_dir, paths[0]);
  688. if (!stat(userpath, &unused)) {
  689. found = userpath;
  690. }
  691. if (!found) {
  692. for (i = 0; i < 3; i++) {
  693. if (!stat(paths[i], &unused)) {
  694. found = paths[i];
  695. break;
  696. }
  697. }
  698. }
  699. fprintf(stderr, "Mac OS X detected. Use 'launchctl load -w %s' to launch.\n", found ? found : paths[3]);
  700. exit(1);
  701. #endif /* !defined(HAVE_SBIN_LAUNCHD */
  702. }
  703. #endif
  704. for(;;) {
  705. if (wait_event()) {
  706. fclose(astf);
  707. while(connect_asterisk()) {
  708. sleep(5);
  709. }
  710. if (login_asterisk()) {
  711. fclose(astf);
  712. exit(1);
  713. }
  714. }
  715. }
  716. exit(0);
  717. }