Newer
Older
Kevin P. Fleming
committed
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
.subclass = spy->write_queue.format,
.data = write_buf,
.samples = samples,
.datalen = ast_codec_get_len(spy->write_queue.format, samples),
};
/* if a flush has been requested, dump everything in whichever queue is larger */
if (ast_test_flag(spy, CHANSPY_TRIGGER_FLUSH)) {
if (spy->read_queue.samples > spy->write_queue.samples) {
if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST)) {
for (result = spy->read_queue.head; result; result = result->next)
ast_frame_adjust_volume(result, spy->read_vol_adjustment);
}
result = spy->read_queue.head;
spy->read_queue.head = NULL;
spy->read_queue.samples = 0;
} else {
if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST)) {
for (result = spy->write_queue.head; result; result = result->next)
ast_frame_adjust_volume(result, spy->write_vol_adjustment);
}
result = spy->write_queue.head;
spy->write_queue.head = NULL;
spy->write_queue.samples = 0;
}
ast_clear_flag(spy, CHANSPY_TRIGGER_FLUSH);
return result;
Kevin P. Fleming
committed
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
}
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)))) {
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
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)";
}
};
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
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
#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)
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
{
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
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
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
/*
* 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 */