chan_console.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2006 - 2008, Digium, Inc.
  5. *
  6. * Russell Bryant <russell@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*!
  19. * \file
  20. * \brief Cross-platform console channel driver
  21. *
  22. * \author Russell Bryant <russell@digium.com>
  23. *
  24. * \note Some of the code in this file came from chan_oss and chan_alsa.
  25. * chan_oss, Mark Spencer <markster@digium.com>
  26. * chan_oss, Luigi Rizzo
  27. * chan_alsa, Matthew Fredrickson <creslin@digium.com>
  28. *
  29. * \ingroup channel_drivers
  30. *
  31. * \extref Portaudio http://www.portaudio.com/
  32. *
  33. * To install portaudio v19 from svn, check it out using the following command:
  34. * - svn co https://www.portaudio.com/repos/portaudio/branches/v19-devel
  35. *
  36. * \note Since this works with any audio system that libportaudio supports,
  37. * including ALSA and OSS, this may someday deprecate chan_alsa and chan_oss.
  38. * However, before that can be done, it needs to *at least* have all of the
  39. * features that these other channel drivers have. The features implemented
  40. * in at least one of the other console channel drivers that are not yet
  41. * implemented here are:
  42. *
  43. * - Set Auto-answer from the dialplan
  44. * - transfer CLI command
  45. * - boost CLI command and .conf option
  46. * - console_video support
  47. */
  48. /*** MODULEINFO
  49. <depend>portaudio</depend>
  50. ***/
  51. #include "asterisk.h"
  52. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  53. #include <sys/signal.h> /* SIGURG */
  54. #include <portaudio.h>
  55. #include "asterisk/module.h"
  56. #include "asterisk/channel.h"
  57. #include "asterisk/pbx.h"
  58. #include "asterisk/causes.h"
  59. #include "asterisk/cli.h"
  60. #include "asterisk/musiconhold.h"
  61. #include "asterisk/callerid.h"
  62. #include "asterisk/astobj2.h"
  63. /*!
  64. * \brief The sample rate to request from PortAudio
  65. *
  66. * \todo Make this optional. If this is only going to talk to 8 kHz endpoints,
  67. * then it makes sense to use 8 kHz natively.
  68. */
  69. #define SAMPLE_RATE 16000
  70. /*!
  71. * \brief The number of samples to configure the portaudio stream for
  72. *
  73. * 320 samples (20 ms) is the most common frame size in Asterisk. So, the code
  74. * in this module reads 320 sample frames from the portaudio stream and queues
  75. * them up on the Asterisk channel. Frames of any size can be written to a
  76. * portaudio stream, but the portaudio documentation does say that for high
  77. * performance applications, the data should be written to Pa_WriteStream in
  78. * the same size as what is used to initialize the stream.
  79. */
  80. #define NUM_SAMPLES 320
  81. /*! \brief Mono Input */
  82. #define INPUT_CHANNELS 1
  83. /*! \brief Mono Output */
  84. #define OUTPUT_CHANNELS 1
  85. /*!
  86. * \brief Maximum text message length
  87. * \note This should be changed if there is a common definition somewhere
  88. * that defines the maximum length of a text message.
  89. */
  90. #define TEXT_SIZE 256
  91. /*! \brief Dance, Kirby, Dance! @{ */
  92. #define V_BEGIN " --- <(\"<) --- "
  93. #define V_END " --- (>\")> ---\n"
  94. /*! @} */
  95. static const char config_file[] = "console.conf";
  96. /*!
  97. * \brief Console pvt structure
  98. *
  99. * Currently, this is a singleton object. However, multiple instances will be
  100. * needed when this module is updated for multiple device support.
  101. */
  102. static struct console_pvt {
  103. AST_DECLARE_STRING_FIELDS(
  104. /*! Name of the device */
  105. AST_STRING_FIELD(name);
  106. AST_STRING_FIELD(input_device);
  107. AST_STRING_FIELD(output_device);
  108. /*! Default context for outgoing calls */
  109. AST_STRING_FIELD(context);
  110. /*! Default extension for outgoing calls */
  111. AST_STRING_FIELD(exten);
  112. /*! Default CallerID number */
  113. AST_STRING_FIELD(cid_num);
  114. /*! Default CallerID name */
  115. AST_STRING_FIELD(cid_name);
  116. /*! Default MOH class to listen to, if:
  117. * - No MOH class set on the channel
  118. * - Peer channel putting this device on hold did not suggest a class */
  119. AST_STRING_FIELD(mohinterpret);
  120. /*! Default language */
  121. AST_STRING_FIELD(language);
  122. );
  123. /*! Current channel for this device */
  124. struct ast_channel *owner;
  125. /*! Current PortAudio stream for this device */
  126. PaStream *stream;
  127. /*! A frame for preparing to queue on to the channel */
  128. struct ast_frame fr;
  129. /*! Running = 1, Not running = 0 */
  130. unsigned int streamstate:1;
  131. /*! On-hook = 0, Off-hook = 1 */
  132. unsigned int hookstate:1;
  133. /*! Unmuted = 0, Muted = 1 */
  134. unsigned int muted:1;
  135. /*! Automatically answer incoming calls */
  136. unsigned int autoanswer:1;
  137. /*! Ignore context in the console dial CLI command */
  138. unsigned int overridecontext:1;
  139. /*! Set during a reload so that we know to destroy this if it is no longer
  140. * in the configuration file. */
  141. unsigned int destroy:1;
  142. /*! ID for the stream monitor thread */
  143. pthread_t thread;
  144. } globals;
  145. AST_MUTEX_DEFINE_STATIC(globals_lock);
  146. static struct ao2_container *pvts;
  147. #define NUM_PVT_BUCKETS 7
  148. static struct console_pvt *active_pvt;
  149. AST_RWLOCK_DEFINE_STATIC(active_lock);
  150. /*!
  151. * \brief Global jitterbuffer configuration
  152. *
  153. * \note Disabled by default.
  154. */
  155. static struct ast_jb_conf default_jbconf = {
  156. .flags = 0,
  157. .max_size = -1,
  158. .resync_threshold = -1,
  159. .impl = "",
  160. .target_extra = -1,
  161. };
  162. static struct ast_jb_conf global_jbconf;
  163. /*! Channel Technology Callbacks @{ */
  164. static struct ast_channel *console_request(const char *type, int format,
  165. void *data, int *cause);
  166. static int console_digit_begin(struct ast_channel *c, char digit);
  167. static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration);
  168. static int console_text(struct ast_channel *c, const char *text);
  169. static int console_hangup(struct ast_channel *c);
  170. static int console_answer(struct ast_channel *c);
  171. static struct ast_frame *console_read(struct ast_channel *chan);
  172. static int console_call(struct ast_channel *c, char *dest, int timeout);
  173. static int console_write(struct ast_channel *chan, struct ast_frame *f);
  174. static int console_indicate(struct ast_channel *chan, int cond,
  175. const void *data, size_t datalen);
  176. static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
  177. /*! @} */
  178. /*!
  179. * \brief Formats natively supported by this module.
  180. */
  181. #define SUPPORTED_FORMATS ( AST_FORMAT_SLINEAR16 )
  182. static const struct ast_channel_tech console_tech = {
  183. .type = "Console",
  184. .description = "Console Channel Driver",
  185. .capabilities = SUPPORTED_FORMATS,
  186. .requester = console_request,
  187. .send_digit_begin = console_digit_begin,
  188. .send_digit_end = console_digit_end,
  189. .send_text = console_text,
  190. .hangup = console_hangup,
  191. .answer = console_answer,
  192. .read = console_read,
  193. .call = console_call,
  194. .write = console_write,
  195. .indicate = console_indicate,
  196. .fixup = console_fixup,
  197. };
  198. /*! \brief lock a console_pvt struct */
  199. #define console_pvt_lock(pvt) ao2_lock(pvt)
  200. /*! \brief unlock a console_pvt struct */
  201. #define console_pvt_unlock(pvt) ao2_unlock(pvt)
  202. static inline struct console_pvt *ref_pvt(struct console_pvt *pvt)
  203. {
  204. if (pvt)
  205. ao2_ref(pvt, +1);
  206. return pvt;
  207. }
  208. static inline struct console_pvt *unref_pvt(struct console_pvt *pvt)
  209. {
  210. ao2_ref(pvt, -1);
  211. return NULL;
  212. }
  213. static struct console_pvt *find_pvt(const char *name)
  214. {
  215. struct console_pvt tmp_pvt = {
  216. .name = name,
  217. };
  218. return ao2_find(pvts, &tmp_pvt, OBJ_POINTER);
  219. }
  220. /*!
  221. * \brief Stream monitor thread
  222. *
  223. * \arg data A pointer to the console_pvt structure that contains the portaudio
  224. * stream that needs to be monitored.
  225. *
  226. * This function runs in its own thread to monitor data coming in from a
  227. * portaudio stream. When enough data is available, it is queued up to
  228. * be read from the Asterisk channel.
  229. */
  230. static void *stream_monitor(void *data)
  231. {
  232. struct console_pvt *pvt = data;
  233. char buf[NUM_SAMPLES * sizeof(int16_t)];
  234. PaError res;
  235. struct ast_frame f = {
  236. .frametype = AST_FRAME_VOICE,
  237. .subclass = AST_FORMAT_SLINEAR16,
  238. .src = "console_stream_monitor",
  239. .data = buf,
  240. .datalen = sizeof(buf),
  241. .samples = sizeof(buf) / sizeof(int16_t),
  242. };
  243. for (;;) {
  244. pthread_testcancel();
  245. res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
  246. pthread_testcancel();
  247. if (!pvt->owner) {
  248. return NULL;
  249. }
  250. if (res == paNoError)
  251. ast_queue_frame(pvt->owner, &f);
  252. }
  253. return NULL;
  254. }
  255. static int open_stream(struct console_pvt *pvt)
  256. {
  257. int res = paInternalError;
  258. if (!strcasecmp(pvt->input_device, "default") &&
  259. !strcasecmp(pvt->output_device, "default")) {
  260. res = Pa_OpenDefaultStream(&pvt->stream, INPUT_CHANNELS, OUTPUT_CHANNELS,
  261. paInt16, SAMPLE_RATE, NUM_SAMPLES, NULL, NULL);
  262. } else {
  263. PaStreamParameters input_params = {
  264. .channelCount = 1,
  265. .sampleFormat = paInt16,
  266. .suggestedLatency = (1.0 / 50.0), /* 20 ms */
  267. .device = paNoDevice,
  268. };
  269. PaStreamParameters output_params = {
  270. .channelCount = 1,
  271. .sampleFormat = paInt16,
  272. .suggestedLatency = (1.0 / 50.0), /* 20 ms */
  273. .device = paNoDevice,
  274. };
  275. PaDeviceIndex index, num_devices, def_input, def_output;
  276. if (!(num_devices = Pa_GetDeviceCount()))
  277. return res;
  278. def_input = Pa_GetDefaultInputDevice();
  279. def_output = Pa_GetDefaultOutputDevice();
  280. for (index = 0;
  281. index < num_devices && (input_params.device == paNoDevice
  282. || output_params.device == paNoDevice);
  283. index++)
  284. {
  285. const PaDeviceInfo *dev = Pa_GetDeviceInfo(index);
  286. if (dev->maxInputChannels) {
  287. if ( (index == def_input && !strcasecmp(pvt->input_device, "default")) ||
  288. !strcasecmp(pvt->input_device, dev->name) )
  289. input_params.device = index;
  290. }
  291. if (dev->maxOutputChannels) {
  292. if ( (index == def_output && !strcasecmp(pvt->output_device, "default")) ||
  293. !strcasecmp(pvt->output_device, dev->name) )
  294. output_params.device = index;
  295. }
  296. }
  297. if (input_params.device == paNoDevice)
  298. ast_log(LOG_ERROR, "No input device found for console device '%s'\n", pvt->name);
  299. if (output_params.device == paNoDevice)
  300. ast_log(LOG_ERROR, "No output device found for console device '%s'\n", pvt->name);
  301. res = Pa_OpenStream(&pvt->stream, &input_params, &output_params,
  302. SAMPLE_RATE, NUM_SAMPLES, paNoFlag, NULL, NULL);
  303. }
  304. return res;
  305. }
  306. static int start_stream(struct console_pvt *pvt)
  307. {
  308. PaError res;
  309. int ret_val = 0;
  310. console_pvt_lock(pvt);
  311. /* It is possible for console_hangup to be called before the
  312. * stream is started, if this is the case pvt->owner will be NULL
  313. * and start_stream should be aborted. */
  314. if (pvt->streamstate || !pvt->owner)
  315. goto return_unlock;
  316. pvt->streamstate = 1;
  317. ast_debug(1, "Starting stream\n");
  318. res = open_stream(pvt);
  319. if (res != paNoError) {
  320. ast_log(LOG_WARNING, "Failed to open stream - (%d) %s\n",
  321. res, Pa_GetErrorText(res));
  322. ret_val = -1;
  323. goto return_unlock;
  324. }
  325. res = Pa_StartStream(pvt->stream);
  326. if (res != paNoError) {
  327. ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
  328. res, Pa_GetErrorText(res));
  329. ret_val = -1;
  330. goto return_unlock;
  331. }
  332. if (ast_pthread_create_background(&pvt->thread, NULL, stream_monitor, pvt)) {
  333. ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
  334. ret_val = -1;
  335. }
  336. return_unlock:
  337. console_pvt_unlock(pvt);
  338. return ret_val;
  339. }
  340. static int stop_stream(struct console_pvt *pvt)
  341. {
  342. if (!pvt->streamstate || pvt->thread == AST_PTHREADT_NULL)
  343. return 0;
  344. pthread_cancel(pvt->thread);
  345. pthread_kill(pvt->thread, SIGURG);
  346. pthread_join(pvt->thread, NULL);
  347. console_pvt_lock(pvt);
  348. Pa_AbortStream(pvt->stream);
  349. Pa_CloseStream(pvt->stream);
  350. pvt->stream = NULL;
  351. pvt->streamstate = 0;
  352. console_pvt_unlock(pvt);
  353. return 0;
  354. }
  355. /*!
  356. * \note Called with the pvt struct locked
  357. */
  358. static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state)
  359. {
  360. struct ast_channel *chan;
  361. if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL,
  362. ext, ctx, 0, "Console/%s", pvt->name))) {
  363. return NULL;
  364. }
  365. chan->tech = &console_tech;
  366. chan->nativeformats = AST_FORMAT_SLINEAR16;
  367. chan->readformat = AST_FORMAT_SLINEAR16;
  368. chan->writeformat = AST_FORMAT_SLINEAR16;
  369. chan->tech_pvt = ref_pvt(pvt);
  370. pvt->owner = chan;
  371. if (!ast_strlen_zero(pvt->language))
  372. ast_string_field_set(chan, language, pvt->language);
  373. ast_jb_configure(chan, &global_jbconf);
  374. if (state != AST_STATE_DOWN) {
  375. if (ast_pbx_start(chan)) {
  376. chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
  377. ast_hangup(chan);
  378. chan = NULL;
  379. } else
  380. start_stream(pvt);
  381. }
  382. return chan;
  383. }
  384. static struct ast_channel *console_request(const char *type, int format, void *data, int *cause)
  385. {
  386. int oldformat = format;
  387. struct ast_channel *chan = NULL;
  388. struct console_pvt *pvt;
  389. if (!(pvt = find_pvt(data))) {
  390. ast_log(LOG_ERROR, "Console device '%s' not found\n", (char *) data);
  391. return NULL;
  392. }
  393. format &= SUPPORTED_FORMATS;
  394. if (!format) {
  395. ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%d'\n", oldformat);
  396. goto return_unref;
  397. }
  398. if (pvt->owner) {
  399. ast_log(LOG_NOTICE, "Console channel already active!\n");
  400. *cause = AST_CAUSE_BUSY;
  401. goto return_unref;
  402. }
  403. console_pvt_lock(pvt);
  404. chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN);
  405. console_pvt_unlock(pvt);
  406. if (!chan)
  407. ast_log(LOG_WARNING, "Unable to create new Console channel!\n");
  408. return_unref:
  409. unref_pvt(pvt);
  410. return chan;
  411. }
  412. static int console_digit_begin(struct ast_channel *c, char digit)
  413. {
  414. ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);
  415. return -1; /* non-zero to request inband audio */
  416. }
  417. static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration)
  418. {
  419. ast_verb(1, V_BEGIN "Console Received End of Digit %c (duration %u)" V_END,
  420. digit, duration);
  421. return -1; /* non-zero to request inband audio */
  422. }
  423. static int console_text(struct ast_channel *c, const char *text)
  424. {
  425. ast_verb(1, V_BEGIN "Console Received Text '%s'" V_END, text);
  426. return 0;
  427. }
  428. static int console_hangup(struct ast_channel *c)
  429. {
  430. struct console_pvt *pvt = c->tech_pvt;
  431. ast_verb(1, V_BEGIN "Hangup on Console" V_END);
  432. pvt->hookstate = 0;
  433. pvt->owner = NULL;
  434. stop_stream(pvt);
  435. c->tech_pvt = unref_pvt(pvt);
  436. return 0;
  437. }
  438. static int console_answer(struct ast_channel *c)
  439. {
  440. struct console_pvt *pvt = c->tech_pvt;
  441. ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);
  442. ast_setstate(c, AST_STATE_UP);
  443. return start_stream(pvt);
  444. }
  445. /*
  446. * \brief Implementation of the ast_channel_tech read() callback
  447. *
  448. * Calling this function is harmless. However, if it does get called, it
  449. * is an indication that something weird happened that really shouldn't
  450. * have and is worth looking into.
  451. *
  452. * Why should this function not get called? Well, let me explain. There are
  453. * a couple of ways to pass on audio that has come from this channel. The way
  454. * that this channel driver uses is that once the audio is available, it is
  455. * wrapped in an ast_frame and queued onto the channel using ast_queue_frame().
  456. *
  457. * The other method would be signalling to the core that there is audio waiting,
  458. * and that it needs to call the channel's read() callback to get it. The way
  459. * the channel gets signalled is that one or more file descriptors are placed
  460. * in the fds array on the ast_channel which the core will poll() on. When the
  461. * fd indicates that input is available, the read() callback is called. This
  462. * is especially useful when there is a dedicated file descriptor where the
  463. * audio is read from. An example would be the socket for an RTP stream.
  464. */
  465. static struct ast_frame *console_read(struct ast_channel *chan)
  466. {
  467. ast_debug(1, "I should not be called ...\n");
  468. return &ast_null_frame;
  469. }
  470. static int console_call(struct ast_channel *c, char *dest, int timeout)
  471. {
  472. struct ast_frame f = { 0, };
  473. struct console_pvt *pvt = c->tech_pvt;
  474. ast_verb(1, V_BEGIN "Call to device '%s' on console from '%s' <%s>" V_END,
  475. dest, c->cid.cid_name, c->cid.cid_num);
  476. console_pvt_lock(pvt);
  477. if (pvt->autoanswer) {
  478. pvt->hookstate = 1;
  479. console_pvt_unlock(pvt);
  480. ast_verb(1, V_BEGIN "Auto-answered" V_END);
  481. f.frametype = AST_FRAME_CONTROL;
  482. f.subclass = AST_CONTROL_ANSWER;
  483. } else {
  484. console_pvt_unlock(pvt);
  485. ast_verb(1, V_BEGIN "Type 'console answer' to answer, or use the 'autoanswer' option "
  486. "for future calls" V_END);
  487. f.frametype = AST_FRAME_CONTROL;
  488. f.subclass = AST_CONTROL_RINGING;
  489. ast_indicate(c, AST_CONTROL_RINGING);
  490. }
  491. ast_queue_frame(c, &f);
  492. return start_stream(pvt);
  493. }
  494. static int console_write(struct ast_channel *chan, struct ast_frame *f)
  495. {
  496. struct console_pvt *pvt = chan->tech_pvt;
  497. Pa_WriteStream(pvt->stream, f->data, f->samples);
  498. return 0;
  499. }
  500. static int console_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
  501. {
  502. struct console_pvt *pvt = chan->tech_pvt;
  503. int res = 0;
  504. switch (cond) {
  505. case AST_CONTROL_BUSY:
  506. case AST_CONTROL_CONGESTION:
  507. case AST_CONTROL_RINGING:
  508. case -1:
  509. res = -1; /* Ask for inband indications */
  510. break;
  511. case AST_CONTROL_PROGRESS:
  512. case AST_CONTROL_PROCEEDING:
  513. case AST_CONTROL_VIDUPDATE:
  514. case AST_CONTROL_SRCUPDATE:
  515. break;
  516. case AST_CONTROL_HOLD:
  517. ast_verb(1, V_BEGIN "Console Has Been Placed on Hold" V_END);
  518. ast_moh_start(chan, data, pvt->mohinterpret);
  519. break;
  520. case AST_CONTROL_UNHOLD:
  521. ast_verb(1, V_BEGIN "Console Has Been Retrieved from Hold" V_END);
  522. ast_moh_stop(chan);
  523. break;
  524. default:
  525. ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n",
  526. cond, chan->name);
  527. /* The core will play inband indications for us if appropriate */
  528. res = -1;
  529. }
  530. return res;
  531. }
  532. static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
  533. {
  534. struct console_pvt *pvt = newchan->tech_pvt;
  535. pvt->owner = newchan;
  536. return 0;
  537. }
  538. /*!
  539. * split a string in extension-context, returns pointers to malloc'ed
  540. * strings.
  541. * If we do not have 'overridecontext' then the last @ is considered as
  542. * a context separator, and the context is overridden.
  543. * This is usually not very necessary as you can play with the dialplan,
  544. * and it is nice not to need it because you have '@' in SIP addresses.
  545. * Return value is the buffer address.
  546. *
  547. * \note came from chan_oss
  548. */
  549. static char *ast_ext_ctx(struct console_pvt *pvt, const char *src, char **ext, char **ctx)
  550. {
  551. if (ext == NULL || ctx == NULL)
  552. return NULL; /* error */
  553. *ext = *ctx = NULL;
  554. if (src && *src != '\0')
  555. *ext = ast_strdup(src);
  556. if (*ext == NULL)
  557. return NULL;
  558. if (!pvt->overridecontext) {
  559. /* parse from the right */
  560. *ctx = strrchr(*ext, '@');
  561. if (*ctx)
  562. *(*ctx)++ = '\0';
  563. }
  564. return *ext;
  565. }
  566. static struct console_pvt *get_active_pvt(void)
  567. {
  568. struct console_pvt *pvt;
  569. ast_rwlock_rdlock(&active_lock);
  570. pvt = ref_pvt(active_pvt);
  571. ast_rwlock_unlock(&active_lock);
  572. return pvt;
  573. }
  574. static char *cli_console_autoanswer(struct ast_cli_entry *e, int cmd,
  575. struct ast_cli_args *a)
  576. {
  577. struct console_pvt *pvt = get_active_pvt();
  578. char *res = CLI_SUCCESS;
  579. switch (cmd) {
  580. case CLI_INIT:
  581. e->command = "console set autoanswer [on|off]";
  582. e->usage =
  583. "Usage: console set autoanswer [on|off]\n"
  584. " Enables or disables autoanswer feature. If used without\n"
  585. " argument, displays the current on/off status of autoanswer.\n"
  586. " The default value of autoanswer is in 'oss.conf'.\n";
  587. return NULL;
  588. case CLI_GENERATE:
  589. return NULL;
  590. }
  591. if (!pvt) {
  592. ast_cli(a->fd, "No console device is set as active.\n");
  593. return CLI_FAILURE;
  594. }
  595. if (a->argc == e->args - 1) {
  596. ast_cli(a->fd, "Auto answer is %s.\n", pvt->autoanswer ? "on" : "off");
  597. unref_pvt(pvt);
  598. return CLI_SUCCESS;
  599. }
  600. if (a->argc != e->args) {
  601. unref_pvt(pvt);
  602. return CLI_SHOWUSAGE;
  603. }
  604. if (!strcasecmp(a->argv[e->args-1], "on"))
  605. pvt->autoanswer = 1;
  606. else if (!strcasecmp(a->argv[e->args - 1], "off"))
  607. pvt->autoanswer = 0;
  608. else
  609. res = CLI_SHOWUSAGE;
  610. unref_pvt(pvt);
  611. return CLI_SUCCESS;
  612. }
  613. static char *cli_console_flash(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  614. {
  615. struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH };
  616. struct console_pvt *pvt = get_active_pvt();
  617. if (cmd == CLI_INIT) {
  618. e->command = "console flash";
  619. e->usage =
  620. "Usage: console flash\n"
  621. " Flashes the call currently placed on the console.\n";
  622. return NULL;
  623. } else if (cmd == CLI_GENERATE)
  624. return NULL;
  625. if (!pvt) {
  626. ast_cli(a->fd, "No console device is set as active\n");
  627. return CLI_FAILURE;
  628. }
  629. if (a->argc != e->args)
  630. return CLI_SHOWUSAGE;
  631. if (!pvt->owner) {
  632. ast_cli(a->fd, "No call to flash\n");
  633. unref_pvt(pvt);
  634. return CLI_FAILURE;
  635. }
  636. pvt->hookstate = 0;
  637. ast_queue_frame(pvt->owner, &f);
  638. unref_pvt(pvt);
  639. return CLI_SUCCESS;
  640. }
  641. static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  642. {
  643. char *s = NULL;
  644. const char *mye = NULL, *myc = NULL;
  645. struct console_pvt *pvt = get_active_pvt();
  646. if (cmd == CLI_INIT) {
  647. e->command = "console dial";
  648. e->usage =
  649. "Usage: console dial [extension[@context]]\n"
  650. " Dials a given extension (and context if specified)\n";
  651. return NULL;
  652. } else if (cmd == CLI_GENERATE)
  653. return NULL;
  654. if (!pvt) {
  655. ast_cli(a->fd, "No console device is currently set as active\n");
  656. return CLI_FAILURE;
  657. }
  658. if (a->argc > e->args + 1)
  659. return CLI_SHOWUSAGE;
  660. if (pvt->owner) { /* already in a call */
  661. int i;
  662. struct ast_frame f = { AST_FRAME_DTMF, 0 };
  663. if (a->argc == e->args) { /* argument is mandatory here */
  664. ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
  665. unref_pvt(pvt);
  666. return CLI_FAILURE;
  667. }
  668. s = a->argv[e->args];
  669. /* send the string one char at a time */
  670. for (i = 0; i < strlen(s); i++) {
  671. f.subclass = s[i];
  672. ast_queue_frame(pvt->owner, &f);
  673. }
  674. unref_pvt(pvt);
  675. return CLI_SUCCESS;
  676. }
  677. /* if we have an argument split it into extension and context */
  678. if (a->argc == e->args + 1) {
  679. char *ext = NULL, *con = NULL;
  680. s = ast_ext_ctx(pvt, a->argv[e->args], &ext, &con);
  681. ast_debug(1, "provided '%s', exten '%s' context '%s'\n",
  682. a->argv[e->args], mye, myc);
  683. mye = ext;
  684. myc = con;
  685. }
  686. /* supply default values if needed */
  687. if (ast_strlen_zero(mye))
  688. mye = pvt->exten;
  689. if (ast_strlen_zero(myc))
  690. myc = pvt->context;
  691. if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
  692. console_pvt_lock(pvt);
  693. pvt->hookstate = 1;
  694. console_new(pvt, mye, myc, AST_STATE_RINGING);
  695. console_pvt_unlock(pvt);
  696. } else
  697. ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
  698. if (s)
  699. free(s);
  700. unref_pvt(pvt);
  701. return CLI_SUCCESS;
  702. }
  703. static char *cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  704. {
  705. struct console_pvt *pvt = get_active_pvt();
  706. if (cmd == CLI_INIT) {
  707. e->command = "console hangup";
  708. e->usage =
  709. "Usage: console hangup\n"
  710. " Hangs up any call currently placed on the console.\n";
  711. return NULL;
  712. } else if (cmd == CLI_GENERATE)
  713. return NULL;
  714. if (!pvt) {
  715. ast_cli(a->fd, "No console device is set as active\n");
  716. return CLI_FAILURE;
  717. }
  718. if (a->argc != e->args)
  719. return CLI_SHOWUSAGE;
  720. if (!pvt->owner && !pvt->hookstate) {
  721. ast_cli(a->fd, "No call to hang up\n");
  722. unref_pvt(pvt);
  723. return CLI_FAILURE;
  724. }
  725. pvt->hookstate = 0;
  726. if (pvt->owner)
  727. ast_queue_hangup(pvt->owner);
  728. unref_pvt(pvt);
  729. return CLI_SUCCESS;
  730. }
  731. static char *cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  732. {
  733. char *s;
  734. struct console_pvt *pvt = get_active_pvt();
  735. char *res = CLI_SUCCESS;
  736. if (cmd == CLI_INIT) {
  737. e->command = "console {mute|unmute}";
  738. e->usage =
  739. "Usage: console {mute|unmute}\n"
  740. " Mute/unmute the microphone.\n";
  741. return NULL;
  742. } else if (cmd == CLI_GENERATE)
  743. return NULL;
  744. if (!pvt) {
  745. ast_cli(a->fd, "No console device is set as active\n");
  746. return CLI_FAILURE;
  747. }
  748. if (a->argc != e->args)
  749. return CLI_SHOWUSAGE;
  750. s = a->argv[e->args-1];
  751. if (!strcasecmp(s, "mute"))
  752. pvt->muted = 1;
  753. else if (!strcasecmp(s, "unmute"))
  754. pvt->muted = 0;
  755. else
  756. res = CLI_SHOWUSAGE;
  757. ast_verb(1, V_BEGIN "The Console is now %s" V_END,
  758. pvt->muted ? "Muted" : "Unmuted");
  759. unref_pvt(pvt);
  760. return res;
  761. }
  762. static char *cli_list_available(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  763. {
  764. PaDeviceIndex index, num, def_input, def_output;
  765. if (cmd == CLI_INIT) {
  766. e->command = "console list available";
  767. e->usage =
  768. "Usage: console list available\n"
  769. " List all available devices.\n";
  770. return NULL;
  771. } else if (cmd == CLI_GENERATE)
  772. return NULL;
  773. if (a->argc != e->args)
  774. return CLI_SHOWUSAGE;
  775. ast_cli(a->fd, "\n"
  776. "=============================================================\n"
  777. "=== Available Devices =======================================\n"
  778. "=============================================================\n"
  779. "===\n");
  780. num = Pa_GetDeviceCount();
  781. if (!num) {
  782. ast_cli(a->fd, "(None)\n");
  783. return CLI_SUCCESS;
  784. }
  785. def_input = Pa_GetDefaultInputDevice();
  786. def_output = Pa_GetDefaultOutputDevice();
  787. for (index = 0; index < num; index++) {
  788. const PaDeviceInfo *dev = Pa_GetDeviceInfo(index);
  789. if (!dev)
  790. continue;
  791. ast_cli(a->fd, "=== ---------------------------------------------------------\n"
  792. "=== Device Name: %s\n", dev->name);
  793. if (dev->maxInputChannels)
  794. ast_cli(a->fd, "=== ---> %sInput Device\n", (index == def_input) ? "Default " : "");
  795. if (dev->maxOutputChannels)
  796. ast_cli(a->fd, "=== ---> %sOutput Device\n", (index == def_output) ? "Default " : "");
  797. ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n");
  798. }
  799. ast_cli(a->fd, "=============================================================\n\n");
  800. return CLI_SUCCESS;
  801. }
  802. static char *cli_list_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  803. {
  804. struct ao2_iterator i;
  805. struct console_pvt *pvt;
  806. if (cmd == CLI_INIT) {
  807. e->command = "console list devices";
  808. e->usage =
  809. "Usage: console list devices\n"
  810. " List all configured devices.\n";
  811. return NULL;
  812. } else if (cmd == CLI_GENERATE)
  813. return NULL;
  814. if (a->argc != e->args)
  815. return CLI_SHOWUSAGE;
  816. ast_cli(a->fd, "\n"
  817. "=============================================================\n"
  818. "=== Configured Devices ======================================\n"
  819. "=============================================================\n"
  820. "===\n");
  821. i = ao2_iterator_init(pvts, 0);
  822. while ((pvt = ao2_iterator_next(&i))) {
  823. console_pvt_lock(pvt);
  824. ast_cli(a->fd, "=== ---------------------------------------------------------\n"
  825. "=== Device Name: %s\n"
  826. "=== ---> Active: %s\n"
  827. "=== ---> Input Device: %s\n"
  828. "=== ---> Output Device: %s\n"
  829. "=== ---> Context: %s\n"
  830. "=== ---> Extension: %s\n"
  831. "=== ---> CallerID Num: %s\n"
  832. "=== ---> CallerID Name: %s\n"
  833. "=== ---> MOH Interpret: %s\n"
  834. "=== ---> Language: %s\n"
  835. "=== ---> Muted: %s\n"
  836. "=== ---> Auto-Answer: %s\n"
  837. "=== ---> Override Context: %s\n"
  838. "=== ---------------------------------------------------------\n===\n",
  839. pvt->name, (pvt == active_pvt) ? "Yes" : "No",
  840. pvt->input_device, pvt->output_device, pvt->context,
  841. pvt->exten, pvt->cid_num, pvt->cid_name, pvt->mohinterpret,
  842. pvt->language, pvt->muted ? "Yes" : "No", pvt->autoanswer ? "Yes" : "No",
  843. pvt->overridecontext ? "Yes" : "No");
  844. console_pvt_unlock(pvt);
  845. unref_pvt(pvt);
  846. }
  847. ao2_iterator_destroy(&i);
  848. ast_cli(a->fd, "=============================================================\n\n");
  849. return CLI_SUCCESS;
  850. }
  851. /*!
  852. * \brief answer command from the console
  853. */
  854. static char *cli_console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  855. {
  856. struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
  857. struct console_pvt *pvt = get_active_pvt();
  858. switch (cmd) {
  859. case CLI_INIT:
  860. e->command = "console answer";
  861. e->usage =
  862. "Usage: console answer\n"
  863. " Answers an incoming call on the console channel.\n";
  864. return NULL;
  865. case CLI_GENERATE:
  866. return NULL; /* no completion */
  867. }
  868. if (!pvt) {
  869. ast_cli(a->fd, "No console device is set as active\n");
  870. return CLI_FAILURE;
  871. }
  872. if (a->argc != e->args) {
  873. unref_pvt(pvt);
  874. return CLI_SHOWUSAGE;
  875. }
  876. if (!pvt->owner) {
  877. ast_cli(a->fd, "No one is calling us\n");
  878. unref_pvt(pvt);
  879. return CLI_FAILURE;
  880. }
  881. pvt->hookstate = 1;
  882. ast_indicate(pvt->owner, -1);
  883. ast_queue_frame(pvt->owner, &f);
  884. unref_pvt(pvt);
  885. return CLI_SUCCESS;
  886. }
  887. /*!
  888. * \brief Console send text CLI command
  889. *
  890. * \note concatenate all arguments into a single string. argv is NULL-terminated
  891. * so we can use it right away
  892. */
  893. static char *cli_console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  894. {
  895. char buf[TEXT_SIZE];
  896. struct console_pvt *pvt = get_active_pvt();
  897. struct ast_frame f = {
  898. .frametype = AST_FRAME_TEXT,
  899. .data = buf,
  900. .src = "console_send_text",
  901. };
  902. int len;
  903. if (cmd == CLI_INIT) {
  904. e->command = "console send text";
  905. e->usage =
  906. "Usage: console send text <message>\n"
  907. " Sends a text message for display on the remote terminal.\n";
  908. return NULL;
  909. } else if (cmd == CLI_GENERATE)
  910. return NULL;
  911. if (!pvt) {
  912. ast_cli(a->fd, "No console device is set as active\n");
  913. return CLI_FAILURE;
  914. }
  915. if (a->argc < e->args + 1) {
  916. unref_pvt(pvt);
  917. return CLI_SHOWUSAGE;
  918. }
  919. if (!pvt->owner) {
  920. ast_cli(a->fd, "Not in a call\n");
  921. unref_pvt(pvt);
  922. return CLI_FAILURE;
  923. }
  924. ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
  925. if (ast_strlen_zero(buf)) {
  926. unref_pvt(pvt);
  927. return CLI_SHOWUSAGE;
  928. }
  929. len = strlen(buf);
  930. buf[len] = '\n';
  931. f.datalen = len + 1;
  932. ast_queue_frame(pvt->owner, &f);
  933. unref_pvt(pvt);
  934. return CLI_SUCCESS;
  935. }
  936. static void set_active(struct console_pvt *pvt, const char *value)
  937. {
  938. if (pvt == &globals) {
  939. ast_log(LOG_ERROR, "active is only valid as a per-device setting\n");
  940. return;
  941. }
  942. if (!ast_true(value))
  943. return;
  944. ast_rwlock_wrlock(&active_lock);
  945. if (active_pvt)
  946. unref_pvt(active_pvt);
  947. active_pvt = ref_pvt(pvt);
  948. ast_rwlock_unlock(&active_lock);
  949. }
  950. static char *cli_console_active(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  951. {
  952. struct console_pvt *pvt;
  953. switch (cmd) {
  954. case CLI_INIT:
  955. e->command = "console active";
  956. e->usage =
  957. "Usage: console active [device]\n"
  958. " If no device is specified. The active console device will be shown.\n"
  959. "Otherwise, the specified device will become the console device active for\n"
  960. "the Asterisk CLI.\n";
  961. return NULL;
  962. case CLI_GENERATE:
  963. if (a->pos == e->args) {
  964. struct ao2_iterator i;
  965. int x = 0;
  966. char *res = NULL;
  967. i = ao2_iterator_init(pvts, 0);
  968. while ((pvt = ao2_iterator_next(&i))) {
  969. if (++x > a->n && !strncasecmp(pvt->name, a->word, strlen(a->word)))
  970. res = ast_strdup(pvt->name);
  971. unref_pvt(pvt);
  972. if (res) {
  973. ao2_iterator_destroy(&i);
  974. return res;
  975. }
  976. }
  977. ao2_iterator_destroy(&i);
  978. }
  979. return NULL;
  980. }
  981. if (a->argc < e->args)
  982. return CLI_SHOWUSAGE;
  983. if (a->argc == e->args) {
  984. pvt = get_active_pvt();
  985. if (!pvt)
  986. ast_cli(a->fd, "No device is currently set as the active console device.\n");
  987. else {
  988. console_pvt_lock(pvt);
  989. ast_cli(a->fd, "The active console device is '%s'.\n", pvt->name);
  990. console_pvt_unlock(pvt);
  991. pvt = unref_pvt(pvt);
  992. }
  993. return CLI_SUCCESS;
  994. }
  995. if (!(pvt = find_pvt(a->argv[e->args]))) {
  996. ast_cli(a->fd, "Could not find a device called '%s'.\n", a->argv[e->args]);
  997. return CLI_FAILURE;
  998. }
  999. set_active(pvt, "yes");
  1000. console_pvt_lock(pvt);
  1001. ast_cli(a->fd, "The active console device has been set to '%s'\n", pvt->name);
  1002. console_pvt_unlock(pvt);
  1003. unref_pvt(pvt);
  1004. return CLI_SUCCESS;
  1005. }
  1006. static struct ast_cli_entry cli_console[] = {
  1007. AST_CLI_DEFINE(cli_console_dial, "Dial an extension from the console"),
  1008. AST_CLI_DEFINE(cli_console_hangup, "Hangup a call on the console"),
  1009. AST_CLI_DEFINE(cli_console_mute, "Disable/Enable mic input"),
  1010. AST_CLI_DEFINE(cli_console_answer, "Answer an incoming console call"),
  1011. AST_CLI_DEFINE(cli_console_sendtext, "Send text to a connected party"),
  1012. AST_CLI_DEFINE(cli_console_flash, "Send a flash to the connected party"),
  1013. AST_CLI_DEFINE(cli_console_autoanswer, "Turn autoanswer on or off"),
  1014. AST_CLI_DEFINE(cli_list_available, "List available devices"),
  1015. AST_CLI_DEFINE(cli_list_devices, "List configured devices"),
  1016. AST_CLI_DEFINE(cli_console_active, "View or Set the active console device"),
  1017. };
  1018. /*!
  1019. * \brief Set default values for a pvt struct
  1020. *
  1021. * \note This function expects the pvt lock to be held.
  1022. */
  1023. static void set_pvt_defaults(struct console_pvt *pvt)
  1024. {
  1025. if (pvt == &globals) {
  1026. ast_string_field_set(pvt, mohinterpret, "default");
  1027. ast_string_field_set(pvt, context, "default");
  1028. ast_string_field_set(pvt, exten, "s");
  1029. ast_string_field_set(pvt, language, "");
  1030. ast_string_field_set(pvt, cid_num, "");
  1031. ast_string_field_set(pvt, cid_name, "");
  1032. pvt->overridecontext = 0;
  1033. pvt->autoanswer = 0;
  1034. } else {
  1035. ast_mutex_lock(&globals_lock);
  1036. ast_string_field_set(pvt, mohinterpret, globals.mohinterpret);
  1037. ast_string_field_set(pvt, context, globals.context);
  1038. ast_string_field_set(pvt, exten, globals.exten);
  1039. ast_string_field_set(pvt, language, globals.language);
  1040. ast_string_field_set(pvt, cid_num, globals.cid_num);
  1041. ast_string_field_set(pvt, cid_name, globals.cid_name);
  1042. pvt->overridecontext = globals.overridecontext;
  1043. pvt->autoanswer = globals.autoanswer;
  1044. ast_mutex_unlock(&globals_lock);
  1045. }
  1046. }
  1047. static void store_callerid(struct console_pvt *pvt, const char *value)
  1048. {
  1049. char cid_name[256];
  1050. char cid_num[256];
  1051. ast_callerid_split(value, cid_name, sizeof(cid_name),
  1052. cid_num, sizeof(cid_num));
  1053. ast_string_field_set(pvt, cid_name, cid_name);
  1054. ast_string_field_set(pvt, cid_num, cid_num);
  1055. }
  1056. /*!
  1057. * \brief Store a configuration parameter in a pvt struct
  1058. *
  1059. * \note This function expects the pvt lock to be held.
  1060. */
  1061. static void store_config_core(struct console_pvt *pvt, const char *var, const char *value)
  1062. {
  1063. if (pvt == &globals && !ast_jb_read_conf(&global_jbconf, var, value))
  1064. return;
  1065. CV_START(var, value);
  1066. CV_STRFIELD("context", pvt, context);
  1067. CV_STRFIELD("extension", pvt, exten);
  1068. CV_STRFIELD("mohinterpret", pvt, mohinterpret);
  1069. CV_STRFIELD("language", pvt, language);
  1070. CV_F("callerid", store_callerid(pvt, value));
  1071. CV_BOOL("overridecontext", pvt->overridecontext);
  1072. CV_BOOL("autoanswer", pvt->autoanswer);
  1073. if (pvt != &globals) {
  1074. CV_F("active", set_active(pvt, value))
  1075. CV_STRFIELD("input_device", pvt, input_device);
  1076. CV_STRFIELD("output_device", pvt, output_device);
  1077. }
  1078. ast_log(LOG_WARNING, "Unknown option '%s'\n", var);
  1079. CV_END;
  1080. }
  1081. static void pvt_destructor(void *obj)
  1082. {
  1083. struct console_pvt *pvt = obj;
  1084. ast_string_field_free_memory(pvt);
  1085. }
  1086. static int init_pvt(struct console_pvt *pvt, const char *name)
  1087. {
  1088. pvt->thread = AST_PTHREADT_NULL;
  1089. if (ast_string_field_init(pvt, 32))
  1090. return -1;
  1091. ast_string_field_set(pvt, name, S_OR(name, ""));
  1092. return 0;
  1093. }
  1094. static void build_device(struct ast_config *cfg, const char *name)
  1095. {
  1096. struct ast_variable *v;
  1097. struct console_pvt *pvt;
  1098. int new = 0;
  1099. if ((pvt = find_pvt(name))) {
  1100. console_pvt_lock(pvt);
  1101. set_pvt_defaults(pvt);
  1102. pvt->destroy = 0;
  1103. } else {
  1104. if (!(pvt = ao2_alloc(sizeof(*pvt), pvt_destructor)))
  1105. return;
  1106. init_pvt(pvt, name);
  1107. set_pvt_defaults(pvt);
  1108. new = 1;
  1109. }
  1110. for (v = ast_variable_browse(cfg, name); v; v = v->next)
  1111. store_config_core(pvt, v->name, v->value);
  1112. if (new)
  1113. ao2_link(pvts, pvt);
  1114. else
  1115. console_pvt_unlock(pvt);
  1116. unref_pvt(pvt);
  1117. }
  1118. static int pvt_mark_destroy_cb(void *obj, void *arg, int flags)
  1119. {
  1120. struct console_pvt *pvt = obj;
  1121. pvt->destroy = 1;
  1122. return 0;
  1123. }
  1124. static void destroy_pvts(void)
  1125. {
  1126. struct ao2_iterator i;
  1127. struct console_pvt *pvt;
  1128. i = ao2_iterator_init(pvts, 0);
  1129. while ((pvt = ao2_iterator_next(&i))) {
  1130. if (pvt->destroy) {
  1131. ao2_unlink(pvts, pvt);
  1132. ast_rwlock_wrlock(&active_lock);
  1133. if (active_pvt == pvt)
  1134. active_pvt = unref_pvt(pvt);
  1135. ast_rwlock_unlock(&active_lock);
  1136. }
  1137. unref_pvt(pvt);
  1138. }
  1139. ao2_iterator_destroy(&i);
  1140. }
  1141. /*!
  1142. * \brief Load the configuration
  1143. * \param reload if this was called due to a reload
  1144. * \retval 0 success
  1145. * \retval -1 failure
  1146. */
  1147. static int load_config(int reload)
  1148. {
  1149. struct ast_config *cfg;
  1150. struct ast_variable *v;
  1151. struct ast_flags config_flags = { 0 };
  1152. char *context = NULL;
  1153. /* default values */
  1154. memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
  1155. ast_mutex_lock(&globals_lock);
  1156. set_pvt_defaults(&globals);
  1157. ast_mutex_unlock(&globals_lock);
  1158. if (!(cfg = ast_config_load(config_file, config_flags))) {
  1159. ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
  1160. return -1;
  1161. }
  1162. ao2_callback(pvts, OBJ_NODATA, pvt_mark_destroy_cb, NULL);
  1163. ast_mutex_lock(&globals_lock);
  1164. for (v = ast_variable_browse(cfg, "general"); v; v = v->next)
  1165. store_config_core(&globals, v->name, v->value);
  1166. ast_mutex_unlock(&globals_lock);
  1167. while ((context = ast_category_browse(cfg, context))) {
  1168. if (strcasecmp(context, "general"))
  1169. build_device(cfg, context);
  1170. }
  1171. ast_config_destroy(cfg);
  1172. destroy_pvts();
  1173. return 0;
  1174. }
  1175. static int pvt_hash_cb(const void *obj, const int flags)
  1176. {
  1177. const struct console_pvt *pvt = obj;
  1178. return ast_str_hash(pvt->name);
  1179. }
  1180. static int pvt_cmp_cb(void *obj, void *arg, int flags)
  1181. {
  1182. struct console_pvt *pvt = obj, *pvt2 = arg;
  1183. return !strcasecmp(pvt->name, pvt2->name) ? CMP_MATCH : 0;
  1184. }
  1185. static void stop_streams(void)
  1186. {
  1187. struct console_pvt *pvt;
  1188. struct ao2_iterator i;
  1189. i = ao2_iterator_init(pvts, 0);
  1190. while ((pvt = ao2_iterator_next(&i))) {
  1191. if (pvt->hookstate)
  1192. stop_stream(pvt);
  1193. unref_pvt(pvt);
  1194. }
  1195. ao2_iterator_destroy(&i);
  1196. }
  1197. static int unload_module(void)
  1198. {
  1199. ast_channel_unregister(&console_tech);
  1200. ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
  1201. stop_streams();
  1202. Pa_Terminate();
  1203. /* Will unref all the pvts so they will get destroyed, too */
  1204. ao2_ref(pvts, -1);
  1205. pvt_destructor(&globals);
  1206. return 0;
  1207. }
  1208. static int load_module(void)
  1209. {
  1210. PaError res;
  1211. init_pvt(&globals, NULL);
  1212. if (!(pvts = ao2_container_alloc(NUM_PVT_BUCKETS, pvt_hash_cb, pvt_cmp_cb)))
  1213. goto return_error;
  1214. if (load_config(0))
  1215. goto return_error;
  1216. res = Pa_Initialize();
  1217. if (res != paNoError) {
  1218. ast_log(LOG_WARNING, "Failed to initialize audio system - (%d) %s\n",
  1219. res, Pa_GetErrorText(res));
  1220. goto return_error_pa_init;
  1221. }
  1222. if (ast_channel_register(&console_tech)) {
  1223. ast_log(LOG_ERROR, "Unable to register channel type 'Console'\n");
  1224. goto return_error_chan_reg;
  1225. }
  1226. if (ast_cli_register_multiple(cli_console, ARRAY_LEN(cli_console)))
  1227. goto return_error_cli_reg;
  1228. return AST_MODULE_LOAD_SUCCESS;
  1229. return_error_cli_reg:
  1230. ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
  1231. return_error_chan_reg:
  1232. ast_channel_unregister(&console_tech);
  1233. return_error_pa_init:
  1234. Pa_Terminate();
  1235. return_error:
  1236. if (pvts)
  1237. ao2_ref(pvts, -1);
  1238. pvts = NULL;
  1239. pvt_destructor(&globals);
  1240. return AST_MODULE_LOAD_DECLINE;
  1241. }
  1242. static int reload(void)
  1243. {
  1244. return load_config(1);
  1245. }
  1246. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Console Channel Driver",
  1247. .load = load_module,
  1248. .unload = unload_module,
  1249. .reload = reload,
  1250. );