loader: Correct overly strict startup checks.
[asterisk/asterisk.git] / main / channel.c
index 1134d01..7eb40d1 100644 (file)
@@ -3160,7 +3160,7 @@ int ast_waitfor(struct ast_channel *c, int ms)
 
 int ast_waitfordigit(struct ast_channel *c, int ms)
 {
-       return ast_waitfordigit_full(c, ms, -1, -1);
+       return ast_waitfordigit_full(c, ms, NULL, -1, -1);
 }
 
 int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data)
@@ -3222,7 +3222,7 @@ int ast_settimeout_full(struct ast_channel *c, unsigned int rate, int (*func)(co
        return res;
 }
 
-int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, int audiofd, int cmdfd)
+int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, const char *breakon, int audiofd, int cmdfd)
 {
        struct timeval start = ast_tvnow();
        int ms;
@@ -3261,17 +3261,24 @@ int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, int audiofd, in
                } else if (rchan) {
                        int res;
                        struct ast_frame *f = ast_read(c);
-                       if (!f)
+
+                       if (!f) {
+                               ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
+
                                return -1;
+                       }
 
                        switch (f->frametype) {
                        case AST_FRAME_DTMF_BEGIN:
                                break;
                        case AST_FRAME_DTMF_END:
                                res = f->subclass.integer;
-                               ast_frfree(f);
-                               ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
-                               return res;
+                               if (!breakon || strchr(breakon, res)) {
+                                       ast_frfree(f);
+                                       ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
+                                       return res;
+                               }
+                               break;
                        case AST_FRAME_CONTROL:
                                switch (f->subclass.integer) {
                                case AST_CONTROL_HANGUP:
@@ -4053,7 +4060,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio, int
                                }
 #else
                                int jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),
-                                       ast_format_get_sample_rate(f->subclass.codec),
+                                       ast_format_get_sample_rate(f->subclass.format),
                                        ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
                                if (jump - MONITOR_DELAY >= 0) {
                                        if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) {
@@ -4176,6 +4183,11 @@ struct ast_frame *ast_read_noaudio(struct ast_channel *chan)
        return __ast_read(chan, 1, 1);
 }
 
+struct ast_frame *ast_read_stream_noaudio(struct ast_channel *chan)
+{
+       return __ast_read(chan, 1, 0);
+}
+
 int ast_indicate(struct ast_channel *chan, int condition)
 {
        return ast_indicate_data(chan, condition, NULL, 0);
@@ -4216,6 +4228,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
        case AST_CONTROL_MASQUERADE_NOTIFY:
        case AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE:
        case AST_CONTROL_STREAM_TOPOLOGY_CHANGED:
+       case AST_CONTROL_STREAM_TOPOLOGY_SOURCE_CHANGED:
        case AST_CONTROL_STREAM_STOP:
        case AST_CONTROL_STREAM_SUSPEND:
        case AST_CONTROL_STREAM_REVERSE:
@@ -4516,6 +4529,7 @@ static int indicate_data_internal(struct ast_channel *chan, int _condition, cons
        case AST_CONTROL_UPDATE_RTP_PEER:
        case AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE:
        case AST_CONTROL_STREAM_TOPOLOGY_CHANGED:
+       case AST_CONTROL_STREAM_TOPOLOGY_SOURCE_CHANGED:
        case AST_CONTROL_STREAM_STOP:
        case AST_CONTROL_STREAM_SUSPEND:
        case AST_CONTROL_STREAM_REVERSE:
@@ -5040,7 +5054,11 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame
        case AST_FRAME_VIDEO:
                /* XXX Handle translation of video codecs one day XXX */
                if (ast_channel_tech(chan)->write_stream) {
-                       res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);
+                       if (stream) {
+                               res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);
+                       } else {
+                               res = 0;
+                       }
                } else if ((stream == default_stream) && ast_channel_tech(chan)->write_video) {
                        res = ast_channel_tech(chan)->write_video(chan, fr);
                } else {
@@ -5049,7 +5067,11 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame
                break;
        case AST_FRAME_MODEM:
                if (ast_channel_tech(chan)->write_stream) {
-                       res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);
+                       if (stream) {
+                               res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);
+                       } else {
+                               res = 0;
+                       }
                } else if ((stream == default_stream) && ast_channel_tech(chan)->write) {
                        res = ast_channel_tech(chan)->write(chan, fr);
                } else {
@@ -5189,7 +5211,7 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame
                                }
 #else
                                int jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)),
-                                                            ast_format_get_sample_rate(f->subclass.codec),
+                                                            ast_format_get_sample_rate(f->subclass.format),
                                                             ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
                                if (jump - MONITOR_DELAY >= 0) {
                                        if (ast_seekstream(ast_channel_monitor(chan)->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1) {
@@ -5237,7 +5259,11 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame
                        f = NULL;
                } else {
                        if (ast_channel_tech(chan)->write_stream) {
-                               res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), f);
+                               if (stream) {
+                                       res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), f);
+                               } else {
+                                       res = 0;
+                               }
                        } else if ((stream == default_stream) && ast_channel_tech(chan)->write) {
                                res = ast_channel_tech(chan)->write(chan, f);
                        } else {
@@ -6010,7 +6036,7 @@ static struct ast_channel *request_channel(const char *type, struct ast_format_c
        const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
 {
        struct chanlist *chan;
-       struct ast_channel *c;
+       struct ast_channel *c = NULL;
        int res;
        int foo;
 
@@ -6051,9 +6077,6 @@ static struct ast_channel *request_channel(const char *type, struct ast_format_c
                c = chan->tech->requester_with_stream_topology(type, topology, assignedids, requestor, addr, cause);
 
                ast_stream_topology_free(tmp_converted_topology);
-               if (!c) {
-                       return NULL;
-               }
        } else if (chan->tech->requester) {
                struct ast_format_cap *tmp_converted_cap = NULL;
                struct ast_format_cap *tmp_cap;
@@ -6104,12 +6127,10 @@ static struct ast_channel *request_channel(const char *type, struct ast_format_c
                ao2_cleanup(tmp_converted_cap);
 
                c = chan->tech->requester(type, joint_cap, assignedids, requestor, addr, cause);
+               ao2_ref(joint_cap, -1);
+       }
 
-               if (!c) {
-                       ao2_ref(joint_cap, -1);
-                       return NULL;
-               }
-       } else {
+       if (!c) {
                return NULL;
        }
 
@@ -6347,11 +6368,11 @@ int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, in
                                silgen = ast_channel_start_silence_generator(c);
                        usleep(1000);
                        if (!d)
-                               d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
+                               d = ast_waitfordigit_full(c, to, NULL, audiofd, ctrlfd);
                } else {
                        if (!silgen && ast_opt_transmit_silence)
                                silgen = ast_channel_start_silence_generator(c);
-                       d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);
+                       d = ast_waitfordigit_full(c, to, NULL, audiofd, ctrlfd);
                }
                if (d < 0) {
                        ast_channel_stop_silence_generator(c, silgen);
@@ -10836,22 +10857,29 @@ enum ast_channel_error ast_channel_errno(void)
 int ast_channel_request_stream_topology_change(struct ast_channel *chan,
                struct ast_stream_topology *topology, void *change_source)
 {
+       int res;
+
        ast_assert(chan != NULL);
        ast_assert(topology != NULL);
 
+       ast_channel_lock(chan);
        if (!ast_channel_is_multistream(chan) || !ast_channel_tech(chan)->indicate) {
+               ast_channel_unlock(chan);
                return -1;
        }
 
        if (ast_stream_topology_equal(ast_channel_get_stream_topology(chan), topology)) {
                ast_debug(3, "Topology of %s already matches what is requested so ignoring topology change request\n",
                                ast_channel_name(chan));
+               ast_channel_unlock(chan);
                return 0;
        }
 
        ast_channel_internal_set_stream_topology_change_source(chan, change_source);
 
-       return ast_channel_tech(chan)->indicate(chan, AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE, topology, sizeof(topology));
+       res = ast_channel_tech(chan)->indicate(chan, AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE, topology, sizeof(topology));
+       ast_channel_unlock(chan);
+       return res;
 }
 
 int ast_channel_stream_topology_changed(struct ast_channel *chan, struct ast_stream_topology *topology)