muted.c 17 KB

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