Newer
Older
Kevin P. Fleming
committed
spy->write_queue.samples = 0;
}
ast_clear_flag(spy, CHANSPY_TRIGGER_FLUSH);
return result;
Kevin P. Fleming
committed
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
}
if ((spy->read_queue.samples < samples) || (spy->write_queue.samples < samples))
return NULL;
/* short-circuit if both head frames have exactly what we want */
if ((spy->read_queue.head->samples == samples) &&
(spy->write_queue.head->samples == samples)) {
read_frame = spy->read_queue.head;
spy->read_queue.head = read_frame->next;
read_frame->next = NULL;
write_frame = spy->write_queue.head;
spy->write_queue.head = write_frame->next;
write_frame->next = NULL;
spy->read_queue.samples -= samples;
spy->write_queue.samples -= samples;
need_dup = 0;
} else {
copy_data_from_queue(&spy->read_queue, read_buf, samples);
copy_data_from_queue(&spy->write_queue, write_buf, samples);
read_frame = &stack_read_frame;
write_frame = &stack_write_frame;
need_dup = 1;
}
if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST))
ast_frame_adjust_volume(read_frame, spy->read_vol_adjustment);
if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST))
ast_frame_adjust_volume(write_frame, spy->write_vol_adjustment);
if (ast_test_flag(spy, CHANSPY_MIXAUDIO)) {
ast_frame_slinear_sum(read_frame, write_frame);
if (need_dup)
result = ast_frdup(read_frame);
Kevin P. Fleming
committed
else {
Kevin P. Fleming
committed
result = read_frame;
Kevin P. Fleming
committed
ast_frfree(write_frame);
}
Kevin P. Fleming
committed
} else {
if (need_dup) {
result = ast_frdup(read_frame);
result->next = ast_frdup(write_frame);
} else {
result = read_frame;
result->next = write_frame;
}
}
return result;
}
static void *silence_generator_alloc(struct ast_channel *chan, void *data)
{
/* just store the data pointer in the channel structure */
return data;
}
static void silence_generator_release(struct ast_channel *chan, void *data)
{
/* nothing to do */
}
static int silence_generator_generate(struct ast_channel *chan, void *data, int len, int samples)
short buf[samples];
struct ast_frame frame = {
.frametype = AST_FRAME_VOICE,
.subclass = AST_FORMAT_SLINEAR,
.data = buf,
.samples = samples,
.datalen = sizeof(buf),
};
if (ast_write(chan, &frame))
return -1;
return 0;
}
static struct ast_generator silence_generator = {
.alloc = silence_generator_alloc,
.release = silence_generator_release,
.generate = silence_generator_generate,
};
struct ast_silence_generator {
int old_write_format;
};
struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_channel *chan)
{
struct ast_silence_generator *state;
if (!(state = ast_calloc(1, sizeof(*state)))) {
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
return NULL;
}
state->old_write_format = chan->writeformat;
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
ast_log(LOG_ERROR, "Could not set write format to SLINEAR\n");
free(state);
return NULL;
}
ast_activate_generator(chan, &silence_generator, state);
if (option_debug)
ast_log(LOG_DEBUG, "Started silence generator on '%s'\n", chan->name);
return state;
}
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
{
if (!state)
return;
ast_deactivate_generator(chan);
if (option_debug)
ast_log(LOG_DEBUG, "Stopped silence generator on '%s'\n", chan->name);
if (ast_set_write_format(chan, state->old_write_format) < 0)
ast_log(LOG_ERROR, "Could not return write format to its original state\n");
free(state);
}
/*! \ brief Convert channel reloadreason (ENUM) to text string for manager event */
const char *channelreloadreason2txt(enum channelreloadreason reason)
{
switch (reason) {
case CHANNEL_MODULE_LOAD:
return "LOAD (Channel module load)";
case CHANNEL_MODULE_RELOAD:
return "RELOAD (Channel module reload)";
case CHANNEL_CLI_RELOAD:
return "CLIRELOAD (Channel module reload by CLI command)";
default:
return "MANAGERRELOAD (Channel module reload by manager)";
}
};
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
#ifdef DEBUG_CHANNEL_LOCKS
/*! \brief Unlock AST channel (and print debugging output)
\note You need to enable DEBUG_CHANNEL_LOCKS for this function
*/
int ast_channel_unlock(struct ast_channel *chan)
{
int res = 0;
if (option_debug > 2)
ast_log(LOG_DEBUG, "::::==== Unlocking AST channel %s\n", chan->name);
if (!chan) {
ast_log(LOG_DEBUG, "::::==== Unlocking non-existing channel \n");
return 0;
}
res = ast_mutex_unlock(&chan->lock);
if (option_debug > 2) {
/* Try to find counter if possible on your platform
I've only found out how to do this on Linux
DEBUG_THREADS changes the lock structure
*/
#ifdef __linux__
int count = 0;
#ifdef DEBUG_THREADS
if ((count = chan->lock.mutex.__m_count))
#else
if ((count = chan->lock.__m_count))
#endif
ast_log(LOG_DEBUG, ":::=== Still have %d locks (recursive)\n", count);
#endif
if (!res)
ast_log(LOG_DEBUG, "::::==== Channel %s was unlocked\n", chan->name);
if (res == EINVAL) {
ast_log(LOG_DEBUG, "::::==== Channel %s had no lock by this thread. Failed unlocking\n", chan->name);
}
}
if (res == EPERM) {
/* We had no lock, so okay any way*/
if (option_debug > 3)
ast_log(LOG_DEBUG, "::::==== Channel %s was not locked at all \n", chan->name);
res = 0;
}
return res;
}
/*! \brief Lock AST channel (and print debugging output)
\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
int ast_channel_lock(struct ast_channel *chan)
{
int res;
if (option_debug > 3)
ast_log(LOG_DEBUG, "====:::: Locking AST channel %s\n", chan->name);
res = ast_mutex_lock(&chan->lock);
if (option_debug > 3) {
#ifdef __linux__
int count = 0;
#ifdef DEBUG_THREADS
if ((count = chan->lock.mutex.__m_count))
#else
if ((count = chan->lock.__m_count))
#endif
ast_log(LOG_DEBUG, ":::=== Now have %d locks (recursive)\n", count);
#endif
if (!res)
ast_log(LOG_DEBUG, "::::==== Channel %s was locked\n", chan->name);
if (res == EDEADLK) {
/* We had no lock, so okey any way */
if (option_debug > 3)
ast_log(LOG_DEBUG, "::::==== Channel %s was not locked by us. Lock would cause deadlock.\n", chan->name);
}
if (res == EINVAL) {
if (option_debug > 3)
ast_log(LOG_DEBUG, "::::==== Channel %s lock failed. No mutex.\n", chan->name);
}
}
return res;
}
/*! \brief Lock AST channel (and print debugging output)
\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
int ast_channel_trylock(struct ast_channel *chan)
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
{
int res;
if (option_debug > 2)
ast_log(LOG_DEBUG, "====:::: Trying to lock AST channel %s\n", chan->name);
res = ast_mutex_trylock(&chan->lock);
if (option_debug > 2) {
#ifdef __linux__
int count = 0;
#ifdef DEBUG_THREADS
if ((count = chan->lock.mutex.__m_count))
#else
if ((count = chan->lock.__m_count))
#endif
ast_log(LOG_DEBUG, ":::=== Now have %d locks (recursive)\n", count);
#endif
if (!res)
ast_log(LOG_DEBUG, "::::==== Channel %s was locked\n", chan->name);
if (res == EBUSY) {
/* We failed to lock */
if (option_debug > 2)
ast_log(LOG_DEBUG, "::::==== Channel %s failed to lock. Not waiting around...\n", chan->name);
}
if (res == EDEADLK) {
/* We had no lock, so okey any way*/
if (option_debug > 2)
ast_log(LOG_DEBUG, "::::==== Channel %s was not locked. Lock would cause deadlock.\n", chan->name);
}
if (res == EINVAL && option_debug > 2)
ast_log(LOG_DEBUG, "::::==== Channel %s lock failed. No mutex.\n", chan->name);
}
return res;
}
#endif
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
/*
* Wrappers for various ast_say_*() functions that call the full version
* of the same functions.
* The proper place would be say.c, but that file is optional and one
* must be able to build asterisk even without it (using a loadable 'say'
* implementation that only supplies the 'full' version of the functions.
*/
int ast_say_number(struct ast_channel *chan, int num,
const char *ints, const char *language, const char *options)
{
return ast_say_number_full(chan, num, ints, language, options, -1, -1);
}
int ast_say_enumeration(struct ast_channel *chan, int num,
const char *ints, const char *language, const char *options)
{
return ast_say_enumeration_full(chan, num, ints, language, options, -1, -1);
}
int ast_say_digits(struct ast_channel *chan, int num,
const char *ints, const char *lang)
{
return ast_say_digits_full(chan, num, ints, lang, -1, -1);
}
int ast_say_digit_str(struct ast_channel *chan, const char *str,
const char *ints, const char *lang)
{
return ast_say_digit_str_full(chan, str, ints, lang, -1, -1);
}
int ast_say_character_str(struct ast_channel *chan, const char *str,
const char *ints, const char *lang)
{
return ast_say_character_str_full(chan, str, ints, lang, -1, -1);
}
int ast_say_phonetic_str(struct ast_channel *chan, const char *str,
const char *ints, const char *lang)
{
return ast_say_phonetic_str_full(chan, str, ints, lang, -1, -1);
}
int ast_say_digits_full(struct ast_channel *chan, int num,
const char *ints, const char *lang, int audiofd, int ctrlfd)
{
char buf[256];
snprintf(buf, sizeof(buf), "%d", num);
return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd);
}
/* end of file */