summaryrefslogtreecommitdiff
path: root/main/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c138
1 files changed, 74 insertions, 64 deletions
diff --git a/main/channel.c b/main/channel.c
index 23ea4b7c0..94b0e8b1c 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -2943,12 +2943,13 @@ int ast_channel_get_up_time(struct ast_channel *chan)
return (ast_tvdiff_ms(ast_tvnow(), ast_channel_answertime(chan)) / 1000);
}
-void ast_deactivate_generator(struct ast_channel *chan)
+static void deactivate_generator_nolock(struct ast_channel *chan)
{
- ast_channel_lock(chan);
if (ast_channel_generatordata(chan)) {
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->release) {
- ast_channel_generator(chan)->release(chan, ast_channel_generatordata(chan));
+ struct ast_generator *generator = ast_channel_generator(chan);
+
+ if (generator && generator->release) {
+ generator->release(chan, ast_channel_generatordata(chan));
}
ast_channel_generatordata_set(chan, NULL);
ast_channel_generator_set(chan, NULL);
@@ -2956,14 +2957,23 @@ void ast_deactivate_generator(struct ast_channel *chan)
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
ast_settimeout(chan, 0, NULL, NULL);
}
+}
+
+void ast_deactivate_generator(struct ast_channel *chan)
+{
+ ast_channel_lock(chan);
+ deactivate_generator_nolock(chan);
ast_channel_unlock(chan);
}
static void generator_write_format_change(struct ast_channel *chan)
{
+ struct ast_generator *generator;
+
ast_channel_lock(chan);
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->write_format_change) {
- ast_channel_generator(chan)->write_format_change(chan, ast_channel_generatordata(chan));
+ generator = ast_channel_generator(chan);
+ if (generator && generator->write_format_change) {
+ generator->write_format_change(chan, ast_channel_generatordata(chan));
}
ast_channel_unlock(chan);
}
@@ -3009,8 +3019,10 @@ int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen,
ast_channel_lock(chan);
if (ast_channel_generatordata(chan)) {
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->release) {
- ast_channel_generator(chan)->release(chan, ast_channel_generatordata(chan));
+ struct ast_generator *generator_old = ast_channel_generator(chan);
+
+ if (generator_old && generator_old->release) {
+ generator_old->release(chan, ast_channel_generatordata(chan));
}
}
if (gen->alloc && !(generatordata = gen->alloc(chan, params))) {
@@ -3642,49 +3654,57 @@ static void send_dtmf_end_event(struct ast_channel *chan,
static void ast_read_generator_actions(struct ast_channel *chan, struct ast_frame *f)
{
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->generate && ast_channel_generatordata(chan) && !ast_internal_timing_enabled(chan)) {
- void *tmp = ast_channel_generatordata(chan);
- int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples) = ast_channel_generator(chan)->generate;
- int res;
- int samples;
+ struct ast_generator *generator;
+ void *gendata;
+ int res;
+ int samples;
+
+ generator = ast_channel_generator(chan);
+ if (!generator
+ || !generator->generate
+ || f->frametype != AST_FRAME_VOICE
+ || !ast_channel_generatordata(chan)
+ || ast_channel_timingfunc(chan)) {
+ return;
+ }
- if (ast_channel_timingfunc(chan)) {
- ast_debug(1, "Generator got voice, switching to phase locked mode\n");
- ast_settimeout(chan, 0, NULL, NULL);
- }
+ /*
+ * We must generate frames in phase locked mode since
+ * we have no internal timer available.
+ */
- ast_channel_generatordata_set(chan, NULL); /* reset, to let writes go through */
+ if (ast_format_cmp(&f->subclass.format, ast_channel_writeformat(chan)) == AST_FORMAT_CMP_NOT_EQUAL) {
+ float factor;
- if (ast_format_cmp(&f->subclass.format, ast_channel_writeformat(chan)) == AST_FORMAT_CMP_NOT_EQUAL) {
- float factor;
- factor = ((float) ast_format_rate(ast_channel_writeformat(chan))) / ((float) ast_format_rate(&f->subclass.format));
- samples = (int) ( ((float) f->samples) * factor );
- } else {
- samples = f->samples;
- }
+ factor = ((float) ast_format_rate(ast_channel_writeformat(chan))) / ((float) ast_format_rate(&f->subclass.format));
+ samples = (int) (((float) f->samples) * factor);
+ } else {
+ samples = f->samples;
+ }
- /* This unlock is here based on two assumptions that hold true at this point in the
- * code. 1) this function is only called from within __ast_read() and 2) all generators
- * call ast_write() in their generate callback.
- *
- * The reason this is added is so that when ast_write is called, the lock that occurs
- * there will not recursively lock the channel. Doing this will cause intended deadlock
- * avoidance not to work in deeper functions
- */
- ast_channel_unlock(chan);
- res = generate(chan, tmp, f->datalen, samples);
- ast_channel_lock(chan);
- ast_channel_generatordata_set(chan, tmp);
+ gendata = ast_channel_generatordata(chan);
+ ast_channel_generatordata_set(chan, NULL); /* reset, to let writes go through */
+
+ /*
+ * This unlock is here based on two assumptions that hold true at
+ * this point in the code. 1) this function is only called from
+ * within __ast_read() and 2) all generators call ast_write() in
+ * their generate callback.
+ *
+ * The reason this is added is so that when ast_write is called,
+ * the lock that occurs there will not recursively lock the
+ * channel. Doing this will allow deadlock avoidance to work in
+ * deeper functions.
+ */
+ ast_channel_unlock(chan);
+ res = generator->generate(chan, gendata, f->datalen, samples);
+ ast_channel_lock(chan);
+ if (generator == ast_channel_generator(chan)) {
+ ast_channel_generatordata_set(chan, gendata);
if (res) {
ast_debug(1, "Auto-deactivating generator\n");
ast_deactivate_generator(chan);
}
-
- } else if (f->frametype == AST_FRAME_CNG) {
- if (ast_channel_generator(chan) && !ast_channel_timingfunc(chan) && (ast_channel_timingfd(chan) > -1)) {
- ast_debug(1, "Generator got CNG, switching to timed mode\n");
- ast_settimeout(chan, 50, generator_force, chan);
- }
}
}
@@ -4265,11 +4285,6 @@ done:
return f;
}
-int ast_internal_timing_enabled(struct ast_channel *chan)
-{
- return (ast_opt_internal_timing && ast_channel_timingfd(chan) > -1);
-}
-
struct ast_frame *ast_read(struct ast_channel *chan)
{
return __ast_read(chan, 0);
@@ -7693,30 +7708,24 @@ struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_cha
return state;
}
-static int internal_deactivate_generator(struct ast_channel *chan, void* generator)
+static int deactivate_silence_generator(struct ast_channel *chan)
{
ast_channel_lock(chan);
if (!ast_channel_generatordata(chan)) {
- ast_debug(1, "Trying to stop silence generator when there is no "
- "generator on '%s'\n", ast_channel_name(chan));
+ ast_debug(1, "Trying to stop silence generator when there is no generator on '%s'\n",
+ ast_channel_name(chan));
ast_channel_unlock(chan);
return 0;
}
- if (ast_channel_generator(chan) != generator) {
- ast_debug(1, "Trying to stop silence generator when it is not the current "
- "generator on '%s'\n", ast_channel_name(chan));
+ if (ast_channel_generator(chan) != &silence_generator) {
+ ast_debug(1, "Trying to stop silence generator when it is not the current generator on '%s'\n",
+ ast_channel_name(chan));
ast_channel_unlock(chan);
return 0;
}
- if (ast_channel_generator(chan) && ast_channel_generator(chan)->release) {
- ast_channel_generator(chan)->release(chan, ast_channel_generatordata(chan));
- }
- ast_channel_generatordata_set(chan, NULL);
- ast_channel_generator_set(chan, NULL);
- ast_channel_set_fd(chan, AST_GENERATOR_FD, -1);
- ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
- ast_settimeout(chan, 0, NULL, NULL);
+ deactivate_generator_nolock(chan);
+
ast_channel_unlock(chan);
return 1;
@@ -7724,10 +7733,11 @@ static int internal_deactivate_generator(struct ast_channel *chan, void* generat
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
{
- if (!state)
+ if (!state) {
return;
+ }
- if (internal_deactivate_generator(chan, &silence_generator)) {
+ if (deactivate_silence_generator(chan)) {
ast_debug(1, "Stopped silence generator on '%s'\n", ast_channel_name(chan));
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");