Only log a failure to get read/write samples from factories if it didn't happen
[asterisk/asterisk.git] / main / audiohook.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2007, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@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  *
21  * \brief Audiohooks Architecture
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include <signal.h>
31
32 #include "asterisk/channel.h"
33 #include "asterisk/utils.h"
34 #include "asterisk/lock.h"
35 #include "asterisk/linkedlists.h"
36 #include "asterisk/audiohook.h"
37 #include "asterisk/slinfactory.h"
38 #include "asterisk/frame.h"
39 #include "asterisk/translate.h"
40
41 #define AST_AUDIOHOOK_SYNC_TOLERANCE 100 /*!< Tolerance in milliseconds for audiohooks synchronization */
42 #define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE 100 /*!< When small queue is enabled, this is the maximum amount of audio that can remain queued at a time. */
43
44 struct ast_audiohook_translate {
45         struct ast_trans_pvt *trans_pvt;
46         struct ast_format format;
47 };
48
49 struct ast_audiohook_list {
50         /* If all the audiohooks in this list are capable
51          * of processing slinear at any sample rate, this
52          * variable will be set and the sample rate will
53          * be preserved during ast_audiohook_write_list()*/
54         int native_slin_compatible;
55         int list_internal_samp_rate;/*!< Internal sample rate used when writing to the audiohook list */
56
57         struct ast_audiohook_translate in_translate[2];
58         struct ast_audiohook_translate out_translate[2];
59         AST_LIST_HEAD_NOLOCK(, ast_audiohook) spy_list;
60         AST_LIST_HEAD_NOLOCK(, ast_audiohook) whisper_list;
61         AST_LIST_HEAD_NOLOCK(, ast_audiohook) manipulate_list;
62 };
63
64 static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int rate, int reset)
65 {
66         struct ast_format slin;
67
68         if (audiohook->hook_internal_samp_rate == rate) {
69                 return 0;
70         }
71
72         audiohook->hook_internal_samp_rate = rate;
73
74         ast_format_set(&slin, ast_format_slin_by_rate(rate), 0);
75         /* Setup the factories that are needed for this audiohook type */
76         switch (audiohook->type) {
77         case AST_AUDIOHOOK_TYPE_SPY:
78                 if (reset) {
79                         ast_slinfactory_destroy(&audiohook->read_factory);
80                 }
81                 ast_slinfactory_init_with_format(&audiohook->read_factory, &slin);
82                 /* fall through */
83         case AST_AUDIOHOOK_TYPE_WHISPER:
84                 if (reset) {
85                         ast_slinfactory_destroy(&audiohook->write_factory);
86                 }
87                 ast_slinfactory_init_with_format(&audiohook->write_factory, &slin);
88                 break;
89         default:
90                 break;
91         }
92         return 0;
93 }
94
95 /*! \brief Initialize an audiohook structure
96  * \param audiohook Audiohook structure
97  * \param type
98  * \param source
99  * \return Returns 0 on success, -1 on failure
100  */
101 int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags init_flags)
102 {
103         /* Need to keep the type and source */
104         audiohook->type = type;
105         audiohook->source = source;
106
107         /* Initialize lock that protects our audiohook */
108         ast_mutex_init(&audiohook->lock);
109         ast_cond_init(&audiohook->trigger, NULL);
110
111         audiohook->init_flags = init_flags;
112
113         /* initialize internal rate at 8khz, this will adjust if necessary */
114         audiohook_set_internal_rate(audiohook, 8000, 0);
115
116         /* Since we are just starting out... this audiohook is new */
117         ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_NEW);
118
119         return 0;
120 }
121
122 /*! \brief Destroys an audiohook structure
123  * \param audiohook Audiohook structure
124  * \return Returns 0 on success, -1 on failure
125  */
126 int ast_audiohook_destroy(struct ast_audiohook *audiohook)
127 {
128         /* Drop the factories used by this audiohook type */
129         switch (audiohook->type) {
130         case AST_AUDIOHOOK_TYPE_SPY:
131                 ast_slinfactory_destroy(&audiohook->read_factory);
132         case AST_AUDIOHOOK_TYPE_WHISPER:
133                 ast_slinfactory_destroy(&audiohook->write_factory);
134                 break;
135         default:
136                 break;
137         }
138
139         /* Destroy translation path if present */
140         if (audiohook->trans_pvt)
141                 ast_translator_free_path(audiohook->trans_pvt);
142
143         /* Lock and trigger be gone! */
144         ast_cond_destroy(&audiohook->trigger);
145         ast_mutex_destroy(&audiohook->lock);
146
147         return 0;
148 }
149
150 /*! \brief Writes a frame into the audiohook structure
151  * \param audiohook Audiohook structure
152  * \param direction Direction the audio frame came from
153  * \param frame Frame to write in
154  * \return Returns 0 on success, -1 on failure
155  */
156 int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, struct ast_frame *frame)
157 {
158         struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
159         struct ast_slinfactory *other_factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->write_factory : &audiohook->read_factory);
160         struct timeval *rwtime = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_time : &audiohook->write_time), previous_time = *rwtime;
161         int our_factory_samples;
162         int our_factory_ms;
163         int other_factory_samples;
164         int other_factory_ms;
165         int muteme = 0;
166
167         /* Update last feeding time to be current */
168         *rwtime = ast_tvnow();
169
170         our_factory_samples = ast_slinfactory_available(factory);
171         our_factory_ms = ast_tvdiff_ms(*rwtime, previous_time) + (our_factory_samples / (audiohook->hook_internal_samp_rate / 1000));
172         other_factory_samples = ast_slinfactory_available(other_factory);
173         other_factory_ms = other_factory_samples / (audiohook->hook_internal_samp_rate / 1000);
174
175         if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC) && other_factory_samples && (our_factory_ms - other_factory_ms > AST_AUDIOHOOK_SYNC_TOLERANCE)) {
176                 ast_debug(1, "Flushing audiohook %p so it remains in sync\n", audiohook);
177                 ast_slinfactory_flush(factory);
178                 ast_slinfactory_flush(other_factory);
179         }
180
181         if (ast_test_flag(audiohook, AST_AUDIOHOOK_SMALL_QUEUE) && ((our_factory_ms > AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE) || (other_factory_ms > AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE))) {
182                 ast_debug(1, "Audiohook %p has stale audio in its factories. Flushing them both\n", audiohook);
183                 ast_slinfactory_flush(factory);
184                 ast_slinfactory_flush(other_factory);
185         }
186
187         /* swap frame data for zeros if mute is required */
188         if ((ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) ||
189                 (ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) ||
190                 (ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_READ | AST_AUDIOHOOK_MUTE_WRITE) == (AST_AUDIOHOOK_MUTE_READ | AST_AUDIOHOOK_MUTE_WRITE))) {
191                         muteme = 1;
192         }
193
194         if (muteme && frame->datalen > 0) {
195                 ast_frame_clear(frame);
196         }
197
198         /* Write frame out to respective factory */
199         ast_slinfactory_feed(factory, frame);
200
201         /* If we need to notify the respective handler of this audiohook, do so */
202         if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) {
203                 ast_cond_signal(&audiohook->trigger);
204         } else if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) {
205                 ast_cond_signal(&audiohook->trigger);
206         } else if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC)) {
207                 ast_cond_signal(&audiohook->trigger);
208         }
209
210         return 0;
211 }
212
213 static struct ast_frame *audiohook_read_frame_single(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction)
214 {
215         struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
216         int vol = (direction == AST_AUDIOHOOK_DIRECTION_READ ? audiohook->options.read_volume : audiohook->options.write_volume);
217         short buf[samples];
218         struct ast_frame frame = {
219                 .frametype = AST_FRAME_VOICE,
220                 .data.ptr = buf,
221                 .datalen = sizeof(buf),
222                 .samples = samples,
223         };
224         ast_format_set(&frame.subclass.format, ast_format_slin_by_rate(audiohook->hook_internal_samp_rate), 0);
225
226         /* Ensure the factory is able to give us the samples we want */
227         if (samples > ast_slinfactory_available(factory))
228                 return NULL;
229
230         /* Read data in from factory */
231         if (!ast_slinfactory_read(factory, buf, samples))
232                 return NULL;
233
234         /* If a volume adjustment needs to be applied apply it */
235         if (vol)
236                 ast_frame_adjust_volume(&frame, vol);
237
238         return ast_frdup(&frame);
239 }
240
241 static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audiohook, size_t samples, struct ast_frame **read_reference, struct ast_frame **write_reference)
242 {
243         int i = 0, usable_read, usable_write;
244         short buf1[samples], buf2[samples], *read_buf = NULL, *write_buf = NULL, *final_buf = NULL, *data1 = NULL, *data2 = NULL;
245         struct ast_frame frame = {
246                 .frametype = AST_FRAME_VOICE,
247                 .data.ptr = NULL,
248                 .datalen = sizeof(buf1),
249                 .samples = samples,
250         };
251         ast_format_set(&frame.subclass.format, ast_format_slin_by_rate(audiohook->hook_internal_samp_rate), 0);
252
253         /* Make sure both factories have the required samples */
254         usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
255         usable_write = (ast_slinfactory_available(&audiohook->write_factory) >= samples ? 1 : 0);
256
257         if (!usable_read && !usable_write) {
258                 /* If both factories are unusable bail out */
259                 ast_debug(1, "Read factory %p and write factory %p both fail to provide %zd samples\n", &audiohook->read_factory, &audiohook->write_factory, samples);
260                 return NULL;
261         }
262
263         /* If we want to provide only a read factory make sure we aren't waiting for other audio */
264         if (usable_read && !usable_write && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)) {
265                 ast_debug(3, "Write factory %p was pretty quick last time, waiting for them.\n", &audiohook->write_factory);
266                 return NULL;
267         }
268
269         /* If we want to provide only a write factory make sure we aren't waiting for other audio */
270         if (usable_write && !usable_read && (ast_tvdiff_ms(ast_tvnow(), audiohook->read_time) < (samples/8)*2)) {
271                 ast_debug(3, "Read factory %p was pretty quick last time, waiting for them.\n", &audiohook->read_factory);
272                 return NULL;
273         }
274
275         /* Start with the read factory... if there are enough samples, read them in */
276         if (usable_read) {
277                 if (ast_slinfactory_read(&audiohook->read_factory, buf1, samples)) {
278                         read_buf = buf1;
279                         /* Adjust read volume if need be */
280                         if (audiohook->options.read_volume) {
281                                 int count = 0;
282                                 short adjust_value = abs(audiohook->options.read_volume);
283                                 for (count = 0; count < samples; count++) {
284                                         if (audiohook->options.read_volume > 0)
285                                                 ast_slinear_saturated_multiply(&buf1[count], &adjust_value);
286                                         else if (audiohook->options.read_volume < 0)
287                                                 ast_slinear_saturated_divide(&buf1[count], &adjust_value);
288                                 }
289                         }
290                 }
291         } else {
292                 ast_debug(1, "Failed to get %d samples from read factory %p\n", (int)samples, &audiohook->read_factory);
293         }
294
295         /* Move on to the write factory... if there are enough samples, read them in */
296         if (usable_write) {
297                 if (ast_slinfactory_read(&audiohook->write_factory, buf2, samples)) {
298                         write_buf = buf2;
299                         /* Adjust write volume if need be */
300                         if (audiohook->options.write_volume) {
301                                 int count = 0;
302                                 short adjust_value = abs(audiohook->options.write_volume);
303                                 for (count = 0; count < samples; count++) {
304                                         if (audiohook->options.write_volume > 0)
305                                                 ast_slinear_saturated_multiply(&buf2[count], &adjust_value);
306                                         else if (audiohook->options.write_volume < 0)
307                                                 ast_slinear_saturated_divide(&buf2[count], &adjust_value);
308                                 }
309                         }
310                 }
311         } else {
312                 ast_debug(1, "Failed to get %d samples from write factory %p\n", (int)samples, &audiohook->write_factory);
313         }
314
315         /* Basically we figure out which buffer to use... and if mixing can be done here */
316         if (read_buf && read_reference) {
317                 frame.data.ptr = buf1;
318                 *read_reference = ast_frdup(&frame);
319         }
320         if (write_buf && write_reference) {
321                 frame.data.ptr = buf2;
322                 *write_reference = ast_frdup(&frame);
323         }
324
325         if (read_buf && write_buf) {
326                 for (i = 0, data1 = read_buf, data2 = write_buf; i < samples; i++, data1++, data2++) {
327                         ast_slinear_saturated_add(data1, data2);
328                 }
329                 final_buf = buf1;
330         } else if (read_buf) {
331                 final_buf = buf1;
332         } else if (write_buf) {
333                 final_buf = buf2;
334         } else {
335                 return NULL;
336         }
337
338         /* Make the final buffer part of the frame, so it gets duplicated fine */
339         frame.data.ptr = final_buf;
340
341         /* Yahoo, a combined copy of the audio! */
342         return ast_frdup(&frame);
343 }
344
345 static struct ast_frame *audiohook_read_frame_helper(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format, struct ast_frame **read_reference, struct ast_frame **write_reference)
346 {
347         struct ast_frame *read_frame = NULL, *final_frame = NULL;
348         struct ast_format tmp_fmt;
349         int samples_converted;
350
351         /* the number of samples requested is based on the format they are requesting.  Inorder
352          * to process this correctly samples must be converted to our internal sample rate */
353         if (audiohook->hook_internal_samp_rate == ast_format_rate(format)) {
354                 samples_converted = samples;
355         } else if (audiohook->hook_internal_samp_rate > ast_format_rate(format)) {
356                 samples_converted = samples * (audiohook->hook_internal_samp_rate / (float) ast_format_rate(format));
357         } else {
358                 samples_converted = samples * (ast_format_rate(format) / (float) audiohook->hook_internal_samp_rate);
359         }
360
361         if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ?
362                 audiohook_read_frame_both(audiohook, samples_converted, read_reference, write_reference) :
363                 audiohook_read_frame_single(audiohook, samples_converted, direction)))) {
364                 return NULL;
365         }
366
367         /* If they don't want signed linear back out, we'll have to send it through the translation path */
368         if (format->id != ast_format_slin_by_rate(audiohook->hook_internal_samp_rate)) {
369                 /* Rebuild translation path if different format then previously */
370                 if (ast_format_cmp(format, &audiohook->format) == AST_FORMAT_CMP_NOT_EQUAL) {
371                         if (audiohook->trans_pvt) {
372                                 ast_translator_free_path(audiohook->trans_pvt);
373                                 audiohook->trans_pvt = NULL;
374                         }
375
376                         /* Setup new translation path for this format... if we fail we can't very well return signed linear so free the frame and return nothing */
377                         if (!(audiohook->trans_pvt = ast_translator_build_path(format, ast_format_set(&tmp_fmt, ast_format_slin_by_rate(audiohook->hook_internal_samp_rate), 0)))) {
378                                 ast_frfree(read_frame);
379                                 return NULL;
380                         }
381                         ast_format_copy(&audiohook->format, format);
382                 }
383                 /* Convert to requested format, and allow the read in frame to be freed */
384                 final_frame = ast_translate(audiohook->trans_pvt, read_frame, 1);
385         } else {
386                 final_frame = read_frame;
387         }
388
389         return final_frame;
390 }
391
392 /*! \brief Reads a frame in from the audiohook structure
393  * \param audiohook Audiohook structure
394  * \param samples Number of samples wanted in requested output format
395  * \param direction Direction the audio frame came from
396  * \param format Format of frame remote side wants back
397  * \return Returns frame on success, NULL on failure
398  */
399 struct ast_frame *ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format)
400 {
401         return audiohook_read_frame_helper(audiohook, samples, direction, format, NULL, NULL);
402 }
403
404 /*! \brief Reads a frame in from the audiohook structure
405  * \param audiohook Audiohook structure
406  * \param samples Number of samples wanted
407  * \param direction Direction the audio frame came from
408  * \param format Format of frame remote side wants back
409  * \param read_frame frame pointer for copying read frame data
410  * \param write_frame frame pointer for copying write frame data
411  * \return Returns frame on success, NULL on failure
412  */
413 struct ast_frame *ast_audiohook_read_frame_all(struct ast_audiohook *audiohook, size_t samples, struct ast_format *format, struct ast_frame **read_frame, struct ast_frame **write_frame)
414 {
415         return audiohook_read_frame_helper(audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, format, read_frame, write_frame);
416 }
417
418 static void audiohook_list_set_samplerate_compatibility(struct ast_audiohook_list *audiohook_list)
419 {
420         struct ast_audiohook *ah = NULL;
421         audiohook_list->native_slin_compatible = 1;
422         AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, ah, list) {
423                 if (!(ah->init_flags & AST_AUDIOHOOK_MANIPULATE_ALL_RATES)) {
424                         audiohook_list->native_slin_compatible = 0;
425                         return;
426                 }
427         }
428 }
429
430 /*! \brief Attach audiohook to channel
431  * \param chan Channel
432  * \param audiohook Audiohook structure
433  * \return Returns 0 on success, -1 on failure
434  */
435 int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
436 {
437         ast_channel_lock(chan);
438
439         if (!ast_channel_audiohooks(chan)) {
440                 struct ast_audiohook_list *ahlist;
441                 /* Whoops... allocate a new structure */
442                 if (!(ahlist = ast_calloc(1, sizeof(*ahlist)))) {
443                         ast_channel_unlock(chan);
444                         return -1;
445                 }
446                 ast_channel_audiohooks_set(chan, ahlist);
447                 AST_LIST_HEAD_INIT_NOLOCK(&ast_channel_audiohooks(chan)->spy_list);
448                 AST_LIST_HEAD_INIT_NOLOCK(&ast_channel_audiohooks(chan)->whisper_list);
449                 AST_LIST_HEAD_INIT_NOLOCK(&ast_channel_audiohooks(chan)->manipulate_list);
450                 /* This sample rate will adjust as necessary when writing to the list. */
451                 ast_channel_audiohooks(chan)->list_internal_samp_rate = 8000;
452         }
453
454         /* Drop into respective list */
455         if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY)
456                 AST_LIST_INSERT_TAIL(&ast_channel_audiohooks(chan)->spy_list, audiohook, list);
457         else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER)
458                 AST_LIST_INSERT_TAIL(&ast_channel_audiohooks(chan)->whisper_list, audiohook, list);
459         else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE)
460                 AST_LIST_INSERT_TAIL(&ast_channel_audiohooks(chan)->manipulate_list, audiohook, list);
461
462
463         audiohook_set_internal_rate(audiohook, ast_channel_audiohooks(chan)->list_internal_samp_rate, 1);
464         audiohook_list_set_samplerate_compatibility(ast_channel_audiohooks(chan));
465
466         /* Change status over to running since it is now attached */
467         ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_RUNNING);
468
469         ast_channel_unlock(chan);
470
471         return 0;
472 }
473
474 /*! \brief Update audiohook's status
475  * \param audiohook Audiohook structure
476  * \param status Audiohook status enum
477  *
478  * \note once status is updated to DONE, this function can not be used to set the
479  * status back to any other setting.  Setting DONE effectively locks the status as such.
480  */
481
482 void ast_audiohook_update_status(struct ast_audiohook *audiohook, enum ast_audiohook_status status)
483 {
484         ast_audiohook_lock(audiohook);
485         if (audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
486                 audiohook->status = status;
487                 ast_cond_signal(&audiohook->trigger);
488         }
489         ast_audiohook_unlock(audiohook);
490 }
491
492 /*! \brief Detach audiohook from channel
493  * \param audiohook Audiohook structure
494  * \return Returns 0 on success, -1 on failure
495  */
496 int ast_audiohook_detach(struct ast_audiohook *audiohook)
497 {
498         if (audiohook->status == AST_AUDIOHOOK_STATUS_NEW || audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
499                 return 0;
500
501         ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_SHUTDOWN);
502
503         while (audiohook->status != AST_AUDIOHOOK_STATUS_DONE)
504                 ast_audiohook_trigger_wait(audiohook);
505
506         return 0;
507 }
508
509 /*! \brief Detach audiohooks from list and destroy said list
510  * \param audiohook_list List of audiohooks
511  * \return Returns 0 on success, -1 on failure
512  */
513 int ast_audiohook_detach_list(struct ast_audiohook_list *audiohook_list)
514 {
515         int i = 0;
516         struct ast_audiohook *audiohook = NULL;
517
518         /* Drop any spies */
519         while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->spy_list, list))) {
520                 ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
521         }
522
523         /* Drop any whispering sources */
524         while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->whisper_list, list))) {
525                 ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
526         }
527
528         /* Drop any manipulaters */
529         while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->manipulate_list, list))) {
530                 ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
531                 audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
532         }
533
534         /* Drop translation paths if present */
535         for (i = 0; i < 2; i++) {
536                 if (audiohook_list->in_translate[i].trans_pvt)
537                         ast_translator_free_path(audiohook_list->in_translate[i].trans_pvt);
538                 if (audiohook_list->out_translate[i].trans_pvt)
539                         ast_translator_free_path(audiohook_list->out_translate[i].trans_pvt);
540         }
541
542         /* Free ourselves */
543         ast_free(audiohook_list);
544
545         return 0;
546 }
547
548 /*! \brief find an audiohook based on its source
549  * \param audiohook_list The list of audiohooks to search in
550  * \param source The source of the audiohook we wish to find
551  * \return Return the corresponding audiohook or NULL if it cannot be found.
552  */
553 static struct ast_audiohook *find_audiohook_by_source(struct ast_audiohook_list *audiohook_list, const char *source)
554 {
555         struct ast_audiohook *audiohook = NULL;
556
557         AST_LIST_TRAVERSE(&audiohook_list->spy_list, audiohook, list) {
558                 if (!strcasecmp(audiohook->source, source))
559                         return audiohook;
560         }
561
562         AST_LIST_TRAVERSE(&audiohook_list->whisper_list, audiohook, list) {
563                 if (!strcasecmp(audiohook->source, source))
564                         return audiohook;
565         }
566
567         AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, audiohook, list) {
568                 if (!strcasecmp(audiohook->source, source))
569                         return audiohook;
570         }
571
572         return NULL;
573 }
574
575 void ast_audiohook_move_by_source(struct ast_channel *old_chan, struct ast_channel *new_chan, const char *source)
576 {
577         struct ast_audiohook *audiohook;
578         enum ast_audiohook_status oldstatus;
579
580         if (!ast_channel_audiohooks(old_chan) || !(audiohook = find_audiohook_by_source(ast_channel_audiohooks(old_chan), source))) {
581                 return;
582         }
583
584         /* By locking both channels and the audiohook, we can assure that
585          * another thread will not have a chance to read the audiohook's status
586          * as done, even though ast_audiohook_remove signals the trigger
587          * condition.
588          */
589         ast_audiohook_lock(audiohook);
590         oldstatus = audiohook->status;
591
592         ast_audiohook_remove(old_chan, audiohook);
593         ast_audiohook_attach(new_chan, audiohook);
594
595         audiohook->status = oldstatus;
596         ast_audiohook_unlock(audiohook);
597 }
598
599 /*! \brief Detach specified source audiohook from channel
600  * \param chan Channel to detach from
601  * \param source Name of source to detach
602  * \return Returns 0 on success, -1 on failure
603  */
604 int ast_audiohook_detach_source(struct ast_channel *chan, const char *source)
605 {
606         struct ast_audiohook *audiohook = NULL;
607
608         ast_channel_lock(chan);
609
610         /* Ensure the channel has audiohooks on it */
611         if (!ast_channel_audiohooks(chan)) {
612                 ast_channel_unlock(chan);
613                 return -1;
614         }
615
616         audiohook = find_audiohook_by_source(ast_channel_audiohooks(chan), source);
617
618         ast_channel_unlock(chan);
619
620         if (audiohook && audiohook->status != AST_AUDIOHOOK_STATUS_DONE)
621                 ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_SHUTDOWN);
622
623         return (audiohook ? 0 : -1);
624 }
625
626 /*!
627  * \brief Remove an audiohook from a specified channel
628  *
629  * \param chan Channel to remove from
630  * \param audiohook Audiohook to remove
631  *
632  * \return Returns 0 on success, -1 on failure
633  *
634  * \note The channel does not need to be locked before calling this function
635  */
636 int ast_audiohook_remove(struct ast_channel *chan, struct ast_audiohook *audiohook)
637 {
638         ast_channel_lock(chan);
639
640         if (!ast_channel_audiohooks(chan)) {
641                 ast_channel_unlock(chan);
642                 return -1;
643         }
644
645         if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY)
646                 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->spy_list, audiohook, list);
647         else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER)
648                 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->whisper_list, audiohook, list);
649         else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE)
650                 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->manipulate_list, audiohook, list);
651
652         audiohook_list_set_samplerate_compatibility(ast_channel_audiohooks(chan));
653         ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
654
655         ast_channel_unlock(chan);
656
657         return 0;
658 }
659
660 /*! \brief Pass a DTMF frame off to be handled by the audiohook core
661  * \param chan Channel that the list is coming off of
662  * \param audiohook_list List of audiohooks
663  * \param direction Direction frame is coming in from
664  * \param frame The frame itself
665  * \return Return frame on success, NULL on failure
666  */
667 static struct ast_frame *dtmf_audiohook_write_list(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
668 {
669         struct ast_audiohook *audiohook = NULL;
670         int removed = 0;
671
672         AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
673                 ast_audiohook_lock(audiohook);
674                 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
675                         AST_LIST_REMOVE_CURRENT(list);
676                         removed = 1;
677                         ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
678                         ast_audiohook_unlock(audiohook);
679                         audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
680                         continue;
681                 }
682                 if (ast_test_flag(audiohook, AST_AUDIOHOOK_WANTS_DTMF))
683                         audiohook->manipulate_callback(audiohook, chan, frame, direction);
684                 ast_audiohook_unlock(audiohook);
685         }
686         AST_LIST_TRAVERSE_SAFE_END;
687
688         /* if an audiohook got removed, reset samplerate compatibility */
689         if (removed) {
690                 audiohook_list_set_samplerate_compatibility(audiohook_list);
691         }
692         return frame;
693 }
694
695 static struct ast_frame *audiohook_list_translate_to_slin(struct ast_audiohook_list *audiohook_list,
696         enum ast_audiohook_direction direction, struct ast_frame *frame)
697 {
698         struct ast_audiohook_translate *in_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ?
699                 &audiohook_list->in_translate[0] : &audiohook_list->in_translate[1]);
700         struct ast_frame *new_frame = frame;
701         struct ast_format tmp_fmt;
702         enum ast_format_id slin_id;
703
704         /* If we are capable of maintaining doing samplerates other that 8khz, update
705          * the internal audiohook_list's rate and higher samplerate audio arrives. By
706          * updating the list's rate, all the audiohooks in the list will be updated as well
707          * as the are written and read from. */
708         if (audiohook_list->native_slin_compatible) {
709                 audiohook_list->list_internal_samp_rate =
710                         MAX(ast_format_rate(&frame->subclass.format), audiohook_list->list_internal_samp_rate);
711         }
712
713         slin_id = ast_format_slin_by_rate(audiohook_list->list_internal_samp_rate);
714
715         if (frame->subclass.format.id == slin_id) {
716                 return new_frame;
717         }
718
719         if (ast_format_cmp(&frame->subclass.format, &in_translate->format) == AST_FORMAT_CMP_NOT_EQUAL) {
720                 if (in_translate->trans_pvt) {
721                         ast_translator_free_path(in_translate->trans_pvt);
722                 }
723                 if (!(in_translate->trans_pvt = ast_translator_build_path(ast_format_set(&tmp_fmt, slin_id, 0), &frame->subclass.format))) {
724                         return NULL;
725                 }
726                 ast_format_copy(&in_translate->format, &frame->subclass.format);
727         }
728         if (!(new_frame = ast_translate(in_translate->trans_pvt, frame, 0))) {
729                 return NULL;
730         }
731
732         return new_frame;
733 }
734
735 static struct ast_frame *audiohook_list_translate_to_native(struct ast_audiohook_list *audiohook_list,
736         enum ast_audiohook_direction direction, struct ast_frame *slin_frame, struct ast_format *outformat)
737 {
738         struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
739         struct ast_frame *outframe = NULL;
740         if (ast_format_cmp(&slin_frame->subclass.format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
741                 /* rebuild translators if necessary */
742                 if (ast_format_cmp(&out_translate->format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
743                         if (out_translate->trans_pvt) {
744                                 ast_translator_free_path(out_translate->trans_pvt);
745                         }
746                         if (!(out_translate->trans_pvt = ast_translator_build_path(outformat, &slin_frame->subclass.format))) {
747                                 return NULL;
748                         }
749                         ast_format_copy(&out_translate->format, outformat);
750                 }
751                 /* translate back to the format the frame came in as. */
752                 if (!(outframe = ast_translate(out_translate->trans_pvt, slin_frame, 0))) {
753                         return NULL;
754                 }
755         }
756         return outframe;
757 }
758
759 /*!
760  * \brief Pass an AUDIO frame off to be handled by the audiohook core
761  *
762  * \details
763  * This function has 3 ast_frames and 3 parts to handle each.  At the beginning of this
764  * function all 3 frames, start_frame, middle_frame, and end_frame point to the initial
765  * input frame.
766  *
767  * Part_1: Translate the start_frame into SLINEAR audio if it is not already in that
768  *         format.  The result of this part is middle_frame is guaranteed to be in
769  *         SLINEAR format for Part_2.
770  * Part_2: Send middle_frame off to spies and manipulators.  At this point middle_frame is
771  *         either a new frame as result of the translation, or points directly to the start_frame
772  *         because no translation to SLINEAR audio was required.
773  * Part_3: Translate end_frame's audio back into the format of start frame if necessary.  This
774  *         is only necessary if manipulation of middle_frame occurred.
775  *
776  * \param chan Channel that the list is coming off of
777  * \param audiohook_list List of audiohooks
778  * \param direction Direction frame is coming in from
779  * \param frame The frame itself
780  * \return Return frame on success, NULL on failure
781  */
782 static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
783 {
784         struct ast_frame *start_frame = frame, *middle_frame = frame, *end_frame = frame;
785         struct ast_audiohook *audiohook = NULL;
786         int samples;
787         int middle_frame_manipulated = 0;
788         int removed = 0;
789
790         /* ---Part_1. translate start_frame to SLINEAR if necessary. */
791         if (!(middle_frame = audiohook_list_translate_to_slin(audiohook_list, direction, start_frame))) {
792                 return frame;
793         }
794         samples = middle_frame->samples;
795
796         /* ---Part_2: Send middle_frame to spy and manipulator lists.  middle_frame is guaranteed to be SLINEAR here.*/
797         /* Queue up signed linear frame to each spy */
798         AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
799                 ast_audiohook_lock(audiohook);
800                 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
801                         AST_LIST_REMOVE_CURRENT(list);
802                         removed = 1;
803                         ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
804                         ast_audiohook_unlock(audiohook);
805                         continue;
806                 }
807                 audiohook_set_internal_rate(audiohook, audiohook_list->list_internal_samp_rate, 1);
808                 ast_audiohook_write_frame(audiohook, direction, middle_frame);
809                 ast_audiohook_unlock(audiohook);
810         }
811         AST_LIST_TRAVERSE_SAFE_END;
812
813         /* If this frame is being written out to the channel then we need to use whisper sources */
814         if (direction == AST_AUDIOHOOK_DIRECTION_WRITE && !AST_LIST_EMPTY(&audiohook_list->whisper_list)) {
815                 int i = 0;
816                 short read_buf[samples], combine_buf[samples], *data1 = NULL, *data2 = NULL;
817                 memset(&combine_buf, 0, sizeof(combine_buf));
818                 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
819                         ast_audiohook_lock(audiohook);
820                         if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
821                                 AST_LIST_REMOVE_CURRENT(list);
822                                 removed = 1;
823                                 ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
824                                 ast_audiohook_unlock(audiohook);
825                                 continue;
826                         }
827                         audiohook_set_internal_rate(audiohook, audiohook_list->list_internal_samp_rate, 1);
828                         if (ast_slinfactory_available(&audiohook->write_factory) >= samples && ast_slinfactory_read(&audiohook->write_factory, read_buf, samples)) {
829                                 /* Take audio from this whisper source and combine it into our main buffer */
830                                 for (i = 0, data1 = combine_buf, data2 = read_buf; i < samples; i++, data1++, data2++)
831                                         ast_slinear_saturated_add(data1, data2);
832                         }
833                         ast_audiohook_unlock(audiohook);
834                 }
835                 AST_LIST_TRAVERSE_SAFE_END;
836                 /* We take all of the combined whisper sources and combine them into the audio being written out */
837                 for (i = 0, data1 = middle_frame->data.ptr, data2 = combine_buf; i < samples; i++, data1++, data2++) {
838                         ast_slinear_saturated_add(data1, data2);
839                 }
840                 middle_frame_manipulated = 1;
841         }
842
843         /* Pass off frame to manipulate audiohooks */
844         if (!AST_LIST_EMPTY(&audiohook_list->manipulate_list)) {
845                 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
846                         ast_audiohook_lock(audiohook);
847                         if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
848                                 AST_LIST_REMOVE_CURRENT(list);
849                                 removed = 1;
850                                 ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
851                                 ast_audiohook_unlock(audiohook);
852                                 /* We basically drop all of our links to the manipulate audiohook and prod it to do it's own destructive things */
853                                 audiohook->manipulate_callback(audiohook, chan, NULL, direction);
854                                 continue;
855                         }
856                         audiohook_set_internal_rate(audiohook, audiohook_list->list_internal_samp_rate, 1);
857                         /* Feed in frame to manipulation. */
858                         if (audiohook->manipulate_callback(audiohook, chan, middle_frame, direction)) {
859                                 /* XXX IGNORE FAILURE */
860
861                                 /* If the manipulation fails then the frame will be returned in its original state.
862                                  * Since there are potentially more manipulator callbacks in the list, no action should
863                                  * be taken here to exit early. */
864                         }
865                         ast_audiohook_unlock(audiohook);
866                 }
867                 AST_LIST_TRAVERSE_SAFE_END;
868                 middle_frame_manipulated = 1;
869         }
870
871         /* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */
872         if (middle_frame_manipulated) {
873                 if (!(end_frame = audiohook_list_translate_to_native(audiohook_list, direction, middle_frame, &start_frame->subclass.format))) {
874                         /* translation failed, so just pass back the input frame */
875                         end_frame = start_frame;
876                 }
877         } else {
878                 end_frame = start_frame;
879         }
880         /* clean up our middle_frame if required */
881         if (middle_frame != end_frame) {
882                 ast_frfree(middle_frame);
883                 middle_frame = NULL;
884         }
885
886         /* Before returning, if an audiohook got removed, reset samplerate compatibility */
887         if (removed) {
888                 audiohook_list_set_samplerate_compatibility(audiohook_list);
889         }
890
891         return end_frame;
892 }
893
894 int ast_audiohook_write_list_empty(struct ast_audiohook_list *audiohook_list)
895 {
896         if (AST_LIST_EMPTY(&audiohook_list->spy_list) &&
897                 AST_LIST_EMPTY(&audiohook_list->whisper_list) &&
898                 AST_LIST_EMPTY(&audiohook_list->manipulate_list)) {
899
900                 return 1;
901         }
902         return 0;
903 }
904
905 /*! \brief Pass a frame off to be handled by the audiohook core
906  * \param chan Channel that the list is coming off of
907  * \param audiohook_list List of audiohooks
908  * \param direction Direction frame is coming in from
909  * \param frame The frame itself
910  * \return Return frame on success, NULL on failure
911  */
912 struct ast_frame *ast_audiohook_write_list(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
913 {
914         /* Pass off frame to it's respective list write function */
915         if (frame->frametype == AST_FRAME_VOICE)
916                 return audio_audiohook_write_list(chan, audiohook_list, direction, frame);
917         else if (frame->frametype == AST_FRAME_DTMF)
918                 return dtmf_audiohook_write_list(chan, audiohook_list, direction, frame);
919         else
920                 return frame;
921 }
922
923 /*! \brief Wait for audiohook trigger to be triggered
924  * \param audiohook Audiohook to wait on
925  */
926 void ast_audiohook_trigger_wait(struct ast_audiohook *audiohook)
927 {
928         struct timeval wait;
929         struct timespec ts;
930
931         wait = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000));
932         ts.tv_sec = wait.tv_sec;
933         ts.tv_nsec = wait.tv_usec * 1000;
934
935         ast_cond_timedwait(&audiohook->trigger, &audiohook->lock, &ts);
936
937         return;
938 }
939
940 /* Count number of channel audiohooks by type, regardless of type */
941 int ast_channel_audiohook_count_by_source(struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
942 {
943         int count = 0;
944         struct ast_audiohook *ah = NULL;
945
946         if (!ast_channel_audiohooks(chan))
947                 return -1;
948
949         switch (type) {
950                 case AST_AUDIOHOOK_TYPE_SPY:
951                         AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, ah, list) {
952                                 if (!strcmp(ah->source, source)) {
953                                         count++;
954                                 }
955                         }
956                         break;
957                 case AST_AUDIOHOOK_TYPE_WHISPER:
958                         AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->whisper_list, ah, list) {
959                                 if (!strcmp(ah->source, source)) {
960                                         count++;
961                                 }
962                         }
963                         break;
964                 case AST_AUDIOHOOK_TYPE_MANIPULATE:
965                         AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->manipulate_list, ah, list) {
966                                 if (!strcmp(ah->source, source)) {
967                                         count++;
968                                 }
969                         }
970                         break;
971                 default:
972                         ast_debug(1, "Invalid audiohook type supplied, (%d)\n", type);
973                         return -1;
974         }
975
976         return count;
977 }
978
979 /* Count number of channel audiohooks by type that are running */
980 int ast_channel_audiohook_count_by_source_running(struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
981 {
982         int count = 0;
983         struct ast_audiohook *ah = NULL;
984         if (!ast_channel_audiohooks(chan))
985                 return -1;
986
987         switch (type) {
988                 case AST_AUDIOHOOK_TYPE_SPY:
989                         AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, ah, list) {
990                                 if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
991                                         count++;
992                         }
993                         break;
994                 case AST_AUDIOHOOK_TYPE_WHISPER:
995                         AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->whisper_list, ah, list) {
996                                 if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
997                                         count++;
998                         }
999                         break;
1000                 case AST_AUDIOHOOK_TYPE_MANIPULATE:
1001                         AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->manipulate_list, ah, list) {
1002                                 if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
1003                                         count++;
1004                         }
1005                         break;
1006                 default:
1007                         ast_debug(1, "Invalid audiohook type supplied, (%d)\n", type);
1008                         return -1;
1009         }
1010         return count;
1011 }
1012
1013 /*! \brief Audiohook volume adjustment structure */
1014 struct audiohook_volume {
1015         struct ast_audiohook audiohook; /*!< Audiohook attached to the channel */
1016         int read_adjustment;            /*!< Value to adjust frames read from the channel by */
1017         int write_adjustment;           /*!< Value to adjust frames written to the channel by */
1018 };
1019
1020 /*! \brief Callback used to destroy the audiohook volume datastore
1021  * \param data Volume information structure
1022  * \return Returns nothing
1023  */
1024 static void audiohook_volume_destroy(void *data)
1025 {
1026         struct audiohook_volume *audiohook_volume = data;
1027
1028         /* Destroy the audiohook as it is no longer in use */
1029         ast_audiohook_destroy(&audiohook_volume->audiohook);
1030
1031         /* Finally free ourselves, we are of no more use */
1032         ast_free(audiohook_volume);
1033
1034         return;
1035 }
1036
1037 /*! \brief Datastore used to store audiohook volume information */
1038 static const struct ast_datastore_info audiohook_volume_datastore = {
1039         .type = "Volume",
1040         .destroy = audiohook_volume_destroy,
1041 };
1042
1043 /*! \brief Helper function which actually gets called by audiohooks to perform the adjustment
1044  * \param audiohook Audiohook attached to the channel
1045  * \param chan Channel we are attached to
1046  * \param frame Frame of audio we want to manipulate
1047  * \param direction Direction the audio came in from
1048  * \return Returns 0 on success, -1 on failure
1049  */
1050 static int audiohook_volume_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
1051 {
1052         struct ast_datastore *datastore = NULL;
1053         struct audiohook_volume *audiohook_volume = NULL;
1054         int *gain = NULL;
1055
1056         /* If the audiohook is shutting down don't even bother */
1057         if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
1058                 return 0;
1059         }
1060
1061         /* Try to find the datastore containg adjustment information, if we can't just bail out */
1062         if (!(datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
1063                 return 0;
1064         }
1065
1066         audiohook_volume = datastore->data;
1067
1068         /* Based on direction grab the appropriate adjustment value */
1069         if (direction == AST_AUDIOHOOK_DIRECTION_READ) {
1070                 gain = &audiohook_volume->read_adjustment;
1071         } else if (direction == AST_AUDIOHOOK_DIRECTION_WRITE) {
1072                 gain = &audiohook_volume->write_adjustment;
1073         }
1074
1075         /* If an adjustment value is present modify the frame */
1076         if (gain && *gain) {
1077                 ast_frame_adjust_volume(frame, *gain);
1078         }
1079
1080         return 0;
1081 }
1082
1083 /*! \brief Helper function which finds and optionally creates an audiohook_volume_datastore datastore on a channel
1084  * \param chan Channel to look on
1085  * \param create Whether to create the datastore if not found
1086  * \return Returns audiohook_volume structure on success, NULL on failure
1087  */
1088 static struct audiohook_volume *audiohook_volume_get(struct ast_channel *chan, int create)
1089 {
1090         struct ast_datastore *datastore = NULL;
1091         struct audiohook_volume *audiohook_volume = NULL;
1092
1093         /* If we are able to find the datastore return the contents (which is actually an audiohook_volume structure) */
1094         if ((datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
1095                 return datastore->data;
1096         }
1097
1098         /* If we are not allowed to create a datastore or if we fail to create a datastore, bail out now as we have nothing for them */
1099         if (!create || !(datastore = ast_datastore_alloc(&audiohook_volume_datastore, NULL))) {
1100                 return NULL;
1101         }
1102
1103         /* Create a new audiohook_volume structure to contain our adjustments and audiohook */
1104         if (!(audiohook_volume = ast_calloc(1, sizeof(*audiohook_volume)))) {
1105                 ast_datastore_free(datastore);
1106                 return NULL;
1107         }
1108
1109         /* Setup our audiohook structure so we can manipulate the audio */
1110         ast_audiohook_init(&audiohook_volume->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume", AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
1111         audiohook_volume->audiohook.manipulate_callback = audiohook_volume_callback;
1112
1113         /* Attach the audiohook_volume blob to the datastore and attach to the channel */
1114         datastore->data = audiohook_volume;
1115         ast_channel_datastore_add(chan, datastore);
1116
1117         /* All is well... put the audiohook into motion */
1118         ast_audiohook_attach(chan, &audiohook_volume->audiohook);
1119
1120         return audiohook_volume;
1121 }
1122
1123 /*! \brief Adjust the volume on frames read from or written to a channel
1124  * \param chan Channel to muck with
1125  * \param direction Direction to set on
1126  * \param volume Value to adjust the volume by
1127  * \return Returns 0 on success, -1 on failure
1128  */
1129 int ast_audiohook_volume_set(struct ast_channel *chan, enum ast_audiohook_direction direction, int volume)
1130 {
1131         struct audiohook_volume *audiohook_volume = NULL;
1132
1133         /* Attempt to find the audiohook volume information, but only create it if we are not setting the adjustment value to zero */
1134         if (!(audiohook_volume = audiohook_volume_get(chan, (volume ? 1 : 0)))) {
1135                 return -1;
1136         }
1137
1138         /* Now based on the direction set the proper value */
1139         if (direction == AST_AUDIOHOOK_DIRECTION_READ || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
1140                 audiohook_volume->read_adjustment = volume;
1141         }
1142         if (direction == AST_AUDIOHOOK_DIRECTION_WRITE || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
1143                 audiohook_volume->write_adjustment = volume;
1144         }
1145
1146         return 0;
1147 }
1148
1149 /*! \brief Retrieve the volume adjustment value on frames read from or written to a channel
1150  * \param chan Channel to retrieve volume adjustment from
1151  * \param direction Direction to retrieve
1152  * \return Returns adjustment value
1153  */
1154 int ast_audiohook_volume_get(struct ast_channel *chan, enum ast_audiohook_direction direction)
1155 {
1156         struct audiohook_volume *audiohook_volume = NULL;
1157         int adjustment = 0;
1158
1159         /* Attempt to find the audiohook volume information, but do not create it as we only want to look at the values */
1160         if (!(audiohook_volume = audiohook_volume_get(chan, 0))) {
1161                 return 0;
1162         }
1163
1164         /* Grab the adjustment value based on direction given */
1165         if (direction == AST_AUDIOHOOK_DIRECTION_READ) {
1166                 adjustment = audiohook_volume->read_adjustment;
1167         } else if (direction == AST_AUDIOHOOK_DIRECTION_WRITE) {
1168                 adjustment = audiohook_volume->write_adjustment;
1169         }
1170
1171         return adjustment;
1172 }
1173
1174 /*! \brief Adjust the volume on frames read from or written to a channel
1175  * \param chan Channel to muck with
1176  * \param direction Direction to increase
1177  * \param volume Value to adjust the adjustment by
1178  * \return Returns 0 on success, -1 on failure
1179  */
1180 int ast_audiohook_volume_adjust(struct ast_channel *chan, enum ast_audiohook_direction direction, int volume)
1181 {
1182         struct audiohook_volume *audiohook_volume = NULL;
1183
1184         /* Attempt to find the audiohook volume information, and create an audiohook if none exists */
1185         if (!(audiohook_volume = audiohook_volume_get(chan, 1))) {
1186                 return -1;
1187         }
1188
1189         /* Based on the direction change the specific adjustment value */
1190         if (direction == AST_AUDIOHOOK_DIRECTION_READ || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
1191                 audiohook_volume->read_adjustment += volume;
1192         }
1193         if (direction == AST_AUDIOHOOK_DIRECTION_WRITE || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
1194                 audiohook_volume->write_adjustment += volume;
1195         }
1196
1197         return 0;
1198 }
1199
1200 /*! \brief Mute frames read from or written to a channel
1201  * \param chan Channel to muck with
1202  * \param source Type of audiohook
1203  * \param flag which flag to set / clear
1204  * \param clear set or clear
1205  * \return Returns 0 on success, -1 on failure
1206  */
1207 int ast_audiohook_set_mute(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clear)
1208 {
1209         struct ast_audiohook *audiohook = NULL;
1210
1211         ast_channel_lock(chan);
1212
1213         /* Ensure the channel has audiohooks on it */
1214         if (!ast_channel_audiohooks(chan)) {
1215                 ast_channel_unlock(chan);
1216                 return -1;
1217         }
1218
1219         audiohook = find_audiohook_by_source(ast_channel_audiohooks(chan), source);
1220
1221         if (audiohook) {
1222                 if (clear) {
1223                         ast_clear_flag(audiohook, flag);
1224                 } else {
1225                         ast_set_flag(audiohook, flag);
1226                 }
1227         }
1228
1229         ast_channel_unlock(chan);
1230
1231         return (audiohook ? 0 : -1);
1232 }