[asterisk-commits] oej: branch oej/pinetestedition-1.8 r383028 - in /team/oej/pinetestedition-1....
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Mar 13 10:45:51 CDT 2013
Author: oej
Date: Wed Mar 13 10:45:46 2013
New Revision: 383028
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=383028
Log:
A soup of patches to give testers a good preview of what's coming to an Asterisk near them.
Added:
team/oej/pinetestedition-1.8/patches/
team/oej/pinetestedition-1.8/patches/README.darjeeling (with props)
team/oej/pinetestedition-1.8/patches/README.oolong-path-support (with props)
team/oej/pinetestedition-1.8/patches/README.pinequeue (with props)
team/oej/pinetestedition-1.8/patches/README.rana-dtmf-rtp-duration (with props)
team/oej/pinetestedition-1.8/patches/README.roibos-cng.txt (with props)
team/oej/pinetestedition-1.8/patches/oolong-path-support-1.8.diff (with props)
team/oej/pinetestedition-1.8/patches/pinequeue-1.8.diff (with props)
team/oej/pinetestedition-1.8/patches/rana-dtmf-duration-1.8.diff (with props)
team/oej/pinetestedition-1.8/patches/roibos-cng-support-1.8.diff (with props)
team/oej/pinetestedition-1.8/patches/set-tone-zone-sip.diff (with props)
team/oej/pinetestedition-1.8/res/res_noise.c (with props)
Modified:
team/oej/pinetestedition-1.8/apps/app_queue.c
team/oej/pinetestedition-1.8/apps/app_senddtmf.c
team/oej/pinetestedition-1.8/channels/chan_iax2.c
team/oej/pinetestedition-1.8/channels/chan_local.c
team/oej/pinetestedition-1.8/channels/chan_mgcp.c
team/oej/pinetestedition-1.8/channels/chan_sip.c
team/oej/pinetestedition-1.8/channels/sip/include/sip.h
team/oej/pinetestedition-1.8/configs/queues.conf.sample
team/oej/pinetestedition-1.8/configs/sip.conf.sample
team/oej/pinetestedition-1.8/funcs/func_frame_trace.c
team/oej/pinetestedition-1.8/include/asterisk/channel.h
team/oej/pinetestedition-1.8/include/asterisk/file.h
team/oej/pinetestedition-1.8/include/asterisk/frame.h
team/oej/pinetestedition-1.8/include/asterisk/indications.h
team/oej/pinetestedition-1.8/include/asterisk/rtp_engine.h
team/oej/pinetestedition-1.8/main/asterisk.dynamics
team/oej/pinetestedition-1.8/main/channel.c
team/oej/pinetestedition-1.8/main/features.c
team/oej/pinetestedition-1.8/main/file.c
team/oej/pinetestedition-1.8/main/frame.c
team/oej/pinetestedition-1.8/main/rtp_engine.c
team/oej/pinetestedition-1.8/main/say.c
team/oej/pinetestedition-1.8/res/res_rtp_asterisk.c
Modified: team/oej/pinetestedition-1.8/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/apps/app_queue.c?view=diff&rev=383028&r1=383027&r2=383028
==============================================================================
--- team/oej/pinetestedition-1.8/apps/app_queue.c (original)
+++ team/oej/pinetestedition-1.8/apps/app_queue.c Wed Mar 13 10:45:46 2013
@@ -881,7 +881,6 @@
{ QUEUE_AUTOPAUSE_ALL,"all" },
};
-
static struct ast_taskprocessor *devicestate_tps;
#define DEFAULT_RETRY 5
@@ -927,6 +926,9 @@
/*! \brief queues.conf [general] option */
static int shared_lastcall = 1;
+
+/*! \brief Play prompts without interrupts (foreground) */
+static int background_prompts = 0;
/*! \brief Subscription to device state change events */
static struct ast_event_sub *device_state_sub;
@@ -1190,6 +1192,7 @@
static void update_realtime_members(struct call_queue *q);
static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
+static int play_file(struct ast_channel *chan, const char *filename, int ringing, char *moh);
static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
/*! \brief sets the QUEUESTATUS channel variable */
@@ -2627,28 +2630,7 @@
return res;
}
-static int play_file(struct ast_channel *chan, const char *filename)
-{
- int res;
-
- if (ast_strlen_zero(filename)) {
- return 0;
- }
-
- if (!ast_fileexists(filename, NULL, chan->language)) {
- return 0;
- }
-
- ast_stopstream(chan);
-
- res = ast_streamfile(chan, filename, chan->language);
- if (!res)
- res = ast_waitstream(chan, AST_DIGIT_ANY);
-
- ast_stopstream(chan);
-
- return res;
-}
+void destroy_streamfile_info(struct ast_queue_streamfile_info *playdata);
/*!
* \brief Check for valid exit from queue via goto
@@ -2681,7 +2663,7 @@
/* We have an exact match */
if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
- qe->valid_digits = 1;
+ qe->valid_digits = 1; /* there it is, the only indication */
/* Return 1 on a successful goto */
return 1;
}
@@ -2704,11 +2686,12 @@
if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency))
return 0;
- if (ringing) {
- ast_indicate(qe->chan,-1);
- } else {
- ast_moh_stop(qe->chan);
- }
+ /* Commented out by old Olle patch */
+ /* if (ringing) { */
+ /* ast_indicate(qe->chan,-1); */
+ /* } else { */
+ /* ast_moh_stop(qe->chan); */
+ /* } */
if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
@@ -2720,7 +2703,7 @@
if (announceposition == 1) {
/* Say we're next, if we are */
if (qe->pos == 1) {
- res = play_file(qe->chan, qe->parent->sound_next);
+ res = play_file(qe->chan, qe->parent->sound_next, ringing, NULL);
if (res)
goto playout;
else
@@ -2728,7 +2711,7 @@
} else {
if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
/* More than Case*/
- res = play_file(qe->chan, qe->parent->queue_quantity1);
+ res = play_file(qe->chan, qe->parent->queue_quantity1, ringing, NULL);
if (res)
goto playout;
res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
@@ -2736,7 +2719,7 @@
goto playout;
} else {
/* Normal Case */
- res = play_file(qe->chan, qe->parent->sound_thereare);
+ res = play_file(qe->chan, qe->parent->sound_thereare, ringing, NULL);
if (res)
goto playout;
res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language, NULL); /* Needs gender */
@@ -2745,11 +2728,11 @@
}
if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
/* More than Case*/
- res = play_file(qe->chan, qe->parent->queue_quantity2);
+ res = play_file(qe->chan, qe->parent->queue_quantity2, ringing, NULL);
if (res)
goto playout;
} else {
- res = play_file(qe->chan, qe->parent->sound_calls);
+ res = play_file(qe->chan, qe->parent->sound_calls, ringing, NULL);
if (res)
goto playout;
}
@@ -2770,10 +2753,10 @@
/* If the hold time is >1 min, if it's enabled, and if it's not
supposed to be only once and we have already said it, say it */
- if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
- ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
- !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
- res = play_file(qe->chan, qe->parent->sound_holdtime);
+ if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
+ ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
+ !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
+ res = play_file(qe->chan, qe->parent->sound_holdtime,ringing,NULL);
if (res)
goto playout;
@@ -2783,11 +2766,11 @@
goto playout;
if (avgholdmins == 1) {
- res = play_file(qe->chan, qe->parent->sound_minute);
+ res = play_file(qe->chan, qe->parent->sound_minute, ringing, NULL);
if (res)
goto playout;
} else {
- res = play_file(qe->chan, qe->parent->sound_minutes);
+ res = play_file(qe->chan, qe->parent->sound_minutes, ringing, NULL);
if (res)
goto playout;
}
@@ -2797,7 +2780,7 @@
if (res)
goto playout;
- res = play_file(qe->chan, qe->parent->sound_seconds);
+ res = play_file(qe->chan, qe->parent->sound_seconds, ringing, NULL);
if (res)
goto playout;
}
@@ -2811,11 +2794,11 @@
qe->chan->name, qe->parent->name, qe->pos);
}
if (say_thanks) {
- res = play_file(qe->chan, qe->parent->sound_thanks);
+ res = play_file(qe->chan, qe->parent->sound_thanks, ringing, NULL);
}
playout:
- if ((res > 0 && !valid_exit(qe, res)))
+ if (res > 0) /* in other words, ignore any play_file problems... */
res = 0;
/* Set our last_pos indicators */
@@ -2823,13 +2806,18 @@
qe->last_pos_said = qe->pos;
/* Don't restart music on hold if we're about to exit the caller from the queue */
- if (!res) {
+ /* Next section commented out by old Olle patch */
+ /* if (!res) {
if (ringing) {
ast_indicate(qe->chan, AST_CONTROL_RINGING);
} else {
ast_moh_start(qe->chan, qe->moh, NULL);
}
- }
+ } */
+ /* it used to be, that we'd fire up the MOH/Indication at this point;
+ now, play_file handles those details; it no longer waits for any
+ user input... so no questions about valid_exit().
+ */
return res;
}
@@ -3480,12 +3468,6 @@
if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency)
return 0;
- /* Stop the music on hold so we can play our own file */
- if (ringing)
- ast_indicate(qe->chan,-1);
- else
- ast_moh_stop(qe->chan);
-
ast_verb(3, "Playing periodic announcement\n");
if (qe->parent->randomperiodicannounce && qe->parent->numperiodicannounce) {
@@ -3496,18 +3478,11 @@
}
/* play the announcement */
- res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]));
-
- if (res > 0 && !valid_exit(qe, res))
- res = 0;
-
- /* Resume Music on Hold if the caller is going to stay in the queue */
- if (!res) {
- if (ringing)
- ast_indicate(qe->chan, AST_CONTROL_RINGING);
- else
- ast_moh_start(qe->chan, qe->moh, NULL);
- }
+ res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]), ringing, qe->moh);
+
+ /* we no longer check for valid_exit(), as we simply
+ start the playback and let the autoservice thread
+ keep it going */
/* update last_periodic_announce_time */
if (qe->parent->relativeperiodicannounce)
@@ -3646,10 +3621,15 @@
#endif
while ((*to = ast_remaining_ms(start_time_tv, orig)) && !peer) {
+
int numlines, retry, pos = 1;
struct ast_channel *watchers[AST_MAX_WATCHERS];
watchers[0] = in;
start = NULL;
+
+ if (background_prompts) {
+ play_file(qe->chan, NULL, 0, qe->moh);
+ }
for (retry = 0; retry < 2; retry++) {
numlines = 0;
@@ -4196,6 +4176,10 @@
/* This is the holding pen for callers 2 through maxlen */
for (;;) {
+ if (background_prompts) {
+ play_file(qe->chan, NULL, 0, qe->moh);
+ }
+
if (is_our_turn(qe))
break;
@@ -4217,9 +4201,9 @@
}
/* Make a position announcement, if enabled */
- if (qe->parent->announcefrequency &&
- (res = say_position(qe,ringing)))
+ if (qe->parent->announcefrequency && (res = say_position(qe,ringing))) {
break;
+ }
/* If we have timed out, break out */
if (qe->expire && (time(NULL) >= qe->expire)) {
@@ -4446,6 +4430,7 @@
.chan_fixup = queue_transfer_fixup,
.destroy = queue_transfer_destroy,
};
+
/*! \brief Log an attended transfer when a queue caller channel is masqueraded
*
@@ -4903,39 +4888,41 @@
int res2;
res2 = ast_autoservice_start(qe->chan);
- if (!res2) {
- if (qe->parent->memberdelay) {
- ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
- res2 = ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
+ if (qe->parent->memberdelay) {
+ ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
+ res2 |= ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
+ }
+ if (!res2 && announce) {
+ if (play_file(peer, announce, ringing, qe->moh) < 0) {
+ ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", announce, peer->name);
}
- if (!res2 && announce) {
- if (play_file(peer, announce) < 0) {
- ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", announce, peer->name);
+ }
+ if (!res2 && qe->parent->reportholdtime) {
+ int res3;
+ res3 = play_file(peer, qe->parent->sound_reporthold, ringing, qe->moh);
+ if (!res3) {
+ int holdtime, holdtimesecs;
+
+ time(&now);
+ holdtime = abs((now - qe->start) / 60);
+ holdtimesecs = abs((now - qe->start) % 60);
+ if (holdtime > 0) {
+ ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
+ if (play_file(peer, qe->parent->sound_minutes, ringing, qe->moh) < 0) {
+ ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_minutes, peer->name);
+ }
}
- }
- if (!res2 && qe->parent->reportholdtime) {
- if (!play_file(peer, qe->parent->sound_reporthold)) {
- int holdtime, holdtimesecs;
-
- time(&now);
- holdtime = abs((now - qe->start) / 60);
- holdtimesecs = abs((now - qe->start) % 60);
- if (holdtime > 0) {
- ast_say_number(peer, holdtime, AST_DIGIT_ANY, peer->language, NULL);
- if (play_file(peer, qe->parent->sound_minutes) < 0) {
- ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_minutes, peer->name);
- }
- }
- if (holdtimesecs > 1) {
- ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, peer->language, NULL);
- if (play_file(peer, qe->parent->sound_seconds) < 0) {
- ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_seconds, peer->name);
- }
+ if (holdtimesecs > 1) {
+ ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, peer->language, NULL);
+ if (play_file(peer, qe->parent->sound_seconds, ringing, qe->moh) < 0) {
+ ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_seconds, peer->name);
}
}
}
ast_autoservice_stop(qe->chan);
}
+
+
if (ast_check_hangup(peer)) {
/* Agent must have hung up */
ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", peer->name);
@@ -4964,10 +4951,11 @@
}
}
/* Stop music on hold */
- if (ringing)
+ if (ringing) {
ast_indicate(qe->chan,-1);
- else
+ } else {
ast_moh_stop(qe->chan);
+ }
/* If appropriate, log that we have a destination channel */
if (qe->chan->cdr)
ast_cdr_setdestchan(qe->chan->cdr, peer->name);
@@ -4985,7 +4973,7 @@
/* Play announcement to the caller telling it's his turn if defined */
if (!ast_strlen_zero(qe->parent->sound_callerannounce)) {
- if (play_file(qe->chan, qe->parent->sound_callerannounce))
+ if (play_file(qe->chan, qe->parent->sound_callerannounce,ringing,qe->moh))
ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", qe->parent->sound_callerannounce);
}
@@ -5152,7 +5140,7 @@
res = ast_autoservice_start(qe->chan);
if (res) {
- ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
+ ast_log(LOG_ERROR, "Unable to start autoservice on calling channel %s\n", qe->chan->name);
res = -1;
}
@@ -5373,8 +5361,9 @@
{
/* Don't need to hold the lock while we setup the outgoing calls */
int retrywait = qe->parent->retry * 1000;
-
- int res = ast_waitfordigit(qe->chan, retrywait);
+ int res;
+
+ res = ast_waitfordigit(qe->chan, retrywait);
if (res > 0 && !valid_exit(qe, res))
res = 0;
@@ -6064,6 +6053,326 @@
AST_LIST_UNLOCK(&rule_lists);
}
+/*! \brief Data structure for \ref play_file() channel frame generator */
+struct gen_state {
+ struct ast_channel *chan;
+ struct ast_filestream *stream;
+ int sample_queue;
+ char filename[512];
+ struct ast_queue_streamfile_info *aqsi;
+};
+
+
+/*! \brief Allocate generator data structures if needed
+
+We don't really do anything here since we get the needed data as params.
+*/
+static void *gen_alloc(struct ast_channel *chan, void *params)
+{
+ struct gen_state *state = params;
+
+ ast_debug(3, "--- Allocating generator for %s\n", chan->name);
+ return state;
+}
+
+/*! \brief Close file stream used by generator */
+static void gen_closestream(struct gen_state *state)
+{
+ if (!state->stream) {
+ ast_debug(3, "--- No active stream to close.\n");
+ return;
+ }
+
+ ast_closestream(state->stream);
+ state->filename[0] = '\0';
+ state->chan->stream = NULL;
+ state->stream = NULL;
+ state->aqsi->now_playing = 0; /* Important flag to indicate we are no longer playing on this channel */
+}
+
+/*! \brief Release generator on channel */
+static void gen_release(struct ast_channel *chan, void *data)
+{
+ struct gen_state *state = data;
+ ast_debug(3, "--- releasing stream \n");
+ if (!data) {
+ ast_debug(3, "--- No state??? \n");
+ return;
+ }
+ gen_closestream(state);
+ ast_free(state);
+}
+
+
+/*! \brief Read frames from file stream and return them to the generator \ref gen_generate() */
+static struct ast_frame *gen_readframe(struct gen_state *state)
+{
+ struct ast_frame *f = NULL;
+ if (state && state->chan) {
+ ast_debug(3, "... Generating frames for %s\n", state->chan->name);
+ } else {
+ ast_log(LOG_ERROR, "... no channel to generate frames for!\n");
+ return f;
+ }
+ if (ast_strlen_zero(state->filename)) {
+ ast_log(LOG_ERROR, ".... no file to read from?? Generator for %s\n", state->chan->name);
+ return f;
+ }
+
+ if (!state->stream) {
+ if (!(state->stream = ast_openstream_full(state->chan, state->filename, state->chan->language, 1))) {
+ ast_log(LOG_WARNING, "File '%s' could not be opened: %s\n", state->filename, strerror(errno));
+ return f;
+ }
+
+ }
+ f = ast_readframe(state->stream);
+
+ return f;
+}
+
+/*! \brief The actual generator that reads frames and sends them to the channel
+ While letting the queue app do it's thing.
+ */
+static int gen_generate(struct ast_channel *chan, void *data, int len, int samples)
+{
+ struct gen_state *state = data;
+ struct ast_frame *f = NULL;
+ int res = 0;
+
+ ast_debug(2, "***** Generating good old prompts for your benefit. Did I hear a thank you?\n");
+
+ if (!state) {
+ ast_log(LOG_ERROR, "---- Do not have a current state data structure\n");
+ return -1;
+ }
+ if (!state->chan) {
+ ast_log(LOG_ERROR, "... no channel to generate frames for!\n");
+ return -1;
+ }
+
+ state->sample_queue += samples;
+ ast_debug(3, "--------->>>>> Generating %d samples - sample queue now %d channel %s\n", samples, state->sample_queue, chan->name);
+
+ while (state->sample_queue > 0) {
+ if (!(f = gen_readframe(state))) {
+ ast_debug(3, "---- :-( Could not get more frames\n");
+ return -1;
+ }
+
+ res = ast_write(chan, f);
+ state->sample_queue -= f->samples;
+ ast_frfree(f);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Failed to write frame: %s\n", strerror(errno));
+ return -1;
+ }
+ }
+
+ return res;
+}
+
+/*! \brief Generator initialization structure for play_file */
+static struct ast_generator play_file_gen =
+{
+ alloc: gen_alloc, /*! \ref gen_alloc() */
+ release: gen_release, /*! \ref gen_release() */
+ generate: gen_generate, /*! \ref gen_generate() */
+};
+
+/*! \brief Play queue updates in the background, being able to interrupt if an
+ agent becomes available.
+
+ To enable playing of a string of files, one after the other, and not have to wait
+ around for each one to finish before playing the next, instead we put them into
+ a list, which we insert at the tail.
+
+ Make sure to get things rolling with a plain play_file(), then use this
+ to queue up the others in sequence
+
+ When called without a filename, we check if we have a list of files in the
+ playlist. If so we start playing again.
+*/
+static int play_file(struct ast_channel *chan, const char *filename, int ringing, char *moh)
+{
+ int res = 0;
+ struct ast_datastore *datastore;
+ struct ast_queue_streamfile_info *aqsi = NULL;
+ struct gen_state *generatordata;
+ struct ast_queue_streamfile_name *sfn = NULL;
+ char playfilename[512];
+
+
+ if (!background_prompts) {
+ if (ast_strlen_zero(filename)) {
+ return 0;
+ }
+
+ if (!ast_fileexists(filename, NULL, chan->language)) {
+ return 0;
+ }
+
+ ast_stopstream(chan);
+
+ res = ast_streamfile(chan, filename, chan->language);
+ if (!res) {
+ res = ast_waitstream(chan, AST_DIGIT_ANY);
+ }
+
+ ast_stopstream(chan);
+ if (ringing) {
+ ast_indicate(chan, AST_CONTROL_RINGING);
+ } else {
+ ast_moh_start(chan, moh, NULL);
+ }
+
+ return res;
+ }
+
+ /* look up the datastore and the play_finished struct, and set appropriate values */
+
+ ast_channel_lock(chan);
+ if ((datastore = ast_channel_datastore_find(chan, ast_sound_ending(), NULL))) {
+ aqsi = datastore->data;
+ if (aqsi) { /* copy this stuff into place */
+ aqsi->ringing = ringing;
+ if (moh) {
+ strcpy(aqsi->moh, moh);
+ }
+ }
+ } else {
+ ast_log(LOG_ERROR, "Can't find the ast_sound_ending datastore! on chan %s\n", chan->name);
+ ast_channel_unlock(chan);
+ return 1; /* Why continue, if I can't access the datastore & list? */
+ }
+ ast_channel_unlock(chan);
+ if (option_debug && !ast_strlen_zero(filename)) {
+ ast_debug(2, "---- Aqsi now playing: %s\n", aqsi->now_playing ? "true" : "false");
+ }
+
+ if (aqsi->now_playing == 0) {
+ playfilename[0] = '\0';
+ if (ast_strlen_zero(filename)) {
+ /* take the first one if we have a playlist */
+ if (!AST_LIST_EMPTY(&aqsi->flist)) {
+ sfn = AST_LIST_REMOVE_HEAD(&aqsi->flist, list);
+ ast_copy_string(playfilename, sfn->filename, sizeof(playfilename));
+ ast_free(sfn);
+ ast_debug(3, "--- No filename and not playing - selecting next file in playlist - %s\n", playfilename);
+ }
+ if (ast_strlen_zero(playfilename)) {
+ ast_debug(3, "--- empty queue... No filename and not currently playing\n");
+ if (ringing) {
+ ast_indicate(chan, AST_CONTROL_RINGING);
+ } else {
+ if (!ast_test_flag(chan, AST_FLAG_MOH)) {
+ ast_moh_start(chan, aqsi->qe->moh ? aqsi->qe->moh : NULL, NULL);
+ }
+ }
+ return 0;
+ }
+ } else {
+ ast_copy_string(playfilename, filename, sizeof(playfilename));
+ }
+ } else {
+ if (ast_strlen_zero(filename)) {
+ ast_debug(3, "--- just checking... No filename and currently playing\n");
+ return 0;
+ }
+ }
+
+ /* If the filename doesn't exist, do not queue it up */
+ if (!ast_strlen_zero(filename)) {
+ if (!ast_fileexists(filename, NULL, chan->language)) {
+ ast_log(LOG_ERROR, "Filename %s does not exist, not queued for playing out on chan %s\n", filename, chan->name);
+ return 0;
+ }
+ }
+
+ AST_LIST_LOCK(&aqsi->flist);
+
+ if (aqsi->now_playing) {
+ struct ast_queue_streamfile_name *fn = ast_calloc(1, sizeof(*fn));
+ fn->filename = ast_strdup(filename);
+ if (!fn || ! fn->filename) {
+ ast_log(LOG_ERROR, "Error allocating memory.\n");
+ AST_LIST_UNLOCK(&aqsi->flist);
+ return 1;
+ }
+ ast_debug(3, " queued sound file %s for playing on chan %s\n", filename, chan->name);
+
+ /* link the struct into the current ast_queue_streamfile_info struct */
+ AST_LIST_INSERT_TAIL(&aqsi->flist, fn, list);
+ /* in this case, nothing else to do, just insert the new file at the end of the list */
+ } else {
+ /* Start playing */
+
+ /* Stop the music on hold so we can play our own file */
+ if (ringing) {
+ ast_debug(3, "Stopping Indication on %s\n", chan->name);
+ ast_indicate(chan,-1);
+ } else {
+ ast_debug(3, "Stopping MOH on chan %s\n", chan->name);
+ ast_moh_stop(chan);
+ }
+
+ ast_debug(3, "Stopping Streaming on chan %s\n", chan->name);
+ ast_stopstream(chan);
+
+ ast_debug(3, "Autoservice stop on chan %s\n", chan->name);
+ ast_autoservice_stop(chan);
+
+ /* Create generator to start playing audio without waiting */
+ generatordata = ast_calloc(1, sizeof(struct gen_state));
+ if (!generatordata) {
+ ast_log(LOG_ERROR, "Can't allocate generator input\n");
+ AST_LIST_UNLOCK(&aqsi->flist);
+ return 1;
+ }
+ ast_copy_string(generatordata->filename, playfilename, sizeof(generatordata->filename));
+ generatordata->chan = chan;
+ generatordata->aqsi = aqsi;
+
+ /* Starting new generator on channel. */
+ if (ast_activate_generator(chan, &play_file_gen, generatordata)) {
+ ast_log(LOG_ERROR, "Not playing requested prompt %s. Generator failed on %s.\n", playfilename, chan->name);
+ /* oops, the current file has problems */
+ /* restore the moh */
+ if (ringing) {
+ ast_indicate(chan, AST_CONTROL_RINGING);
+ } else {
+ ast_moh_start(chan, aqsi->qe->moh, NULL);
+ }
+ AST_LIST_UNLOCK(&aqsi->flist);
+ return 1;
+ } else {
+ ast_debug(3, "--- Generator Starting to play file %s \n", playfilename);
+ }
+ aqsi->now_playing = 1; /* We have begun playback */
+ }
+
+ AST_LIST_UNLOCK(&aqsi->flist);
+ ast_waitfor(chan, 1);
+
+ return 0; /* non-zero most likely means the file doesn't exist */
+}
+
+/*! \brief This routine propably will only need to be called at module unload time */
+void destroy_streamfile_info(struct ast_queue_streamfile_info *playdata)
+{
+ struct ast_queue_streamfile_name *fn;
+ AST_LIST_LOCK(&playdata->flist);
+ while (!AST_LIST_EMPTY(&playdata->flist)) {
+ fn = AST_LIST_REMOVE_HEAD(&playdata->flist, list);
+ ast_free(fn->filename);
+
+ ast_free(fn);
+ }
+ AST_LIST_UNLOCK(&playdata->flist);
+ AST_LIST_HEAD_DESTROY(&playdata->flist);
+ ast_free(playdata);
+}
+
/*!\brief The starting point for all queue calls
*
* The process involved here is to
@@ -6087,6 +6396,9 @@
int qcontinue = 0;
int max_penalty, min_penalty;
enum queue_result reason = QUEUE_UNKNOWN;
+ struct ast_datastore *datastore = NULL;
+ struct ast_queue_streamfile_info *aqsi = ast_calloc(1, sizeof(struct ast_queue_streamfile_info));
+
/* whether to exit Queue application after the timeout hits */
int tries = 0;
int noption = 0;
@@ -6209,6 +6521,24 @@
S_OR(args.url, ""),
S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
qe.opos);
+
+ /* Add the background music datastore for this channel */
+ if (background_prompts) {
+ datastore = ast_datastore_alloc(ast_sound_ending(), NULL);
+ if (datastore && aqsi) {
+ /* If memory allocation worked out */
+ aqsi->qe = &qe;
+ aqsi->chan = chan;
+ aqsi->ringing = ringing;
+ aqsi->now_playing = 0;
+ ast_copy_string(aqsi->moh, qe.moh, sizeof(aqsi->moh));
+ AST_LIST_HEAD_INIT(&aqsi->flist);
+ datastore->data = aqsi;
+
+ ast_channel_datastore_add(chan, datastore);
+ }
+ }
+
copy_rules(&qe, args.rule);
qe.pr = AST_LIST_FIRST(&qe.qe_rules);
check_turns:
@@ -6242,6 +6572,9 @@
break;
}
+ if (background_prompts) {
+ play_file(qe.chan, NULL, ringing, qe.moh);
+ }
if (makeannouncement) {
/* Make a position announcement, if enabled */
if (qe.parent->announcefrequency)
@@ -6324,6 +6657,12 @@
}
stop:
+ /* remove the playdata datastore */
+ ast_channel_datastore_remove(chan, datastore);
+
+ /* get rid of the datastore for non-wait sound playing */
+ destroy_streamfile_info(aqsi);
+
if (res) {
if (res < 0) {
if (!qe.handled) {
@@ -6340,17 +6679,6 @@
ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITWITHKEY",
"%s|%d", qe.digits, qe.pos);
}
- }
-
- /* Don't allow return code > 0 */
- if (res >= 0) {
- res = 0;
- if (ringing) {
- ast_indicate(chan, -1);
- } else {
- ast_moh_stop(chan);
- }
- ast_stopstream(chan);
}
set_queue_variables(qe.parent, qe.chan);
@@ -6816,6 +7144,10 @@
update_cdr = 0;
if ((general_val = ast_variable_retrieve(cfg, "general", "updatecdr")))
update_cdr = ast_true(general_val);
+ background_prompts = 0;
+ if ((general_val = ast_variable_retrieve(cfg, "general", "background_prompts"))) {
+ background_prompts = ast_true(general_val);
+ }
shared_lastcall = 0;
if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall")))
shared_lastcall = ast_true(general_val);
Modified: team/oej/pinetestedition-1.8/apps/app_senddtmf.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/apps/app_senddtmf.c?view=diff&rev=383028&r1=383027&r2=383028
==============================================================================
--- team/oej/pinetestedition-1.8/apps/app_senddtmf.c (original)
+++ team/oej/pinetestedition-1.8/apps/app_senddtmf.c Wed Mar 13 10:45:46 2013
@@ -79,6 +79,9 @@
<parameter name="Digit" required="true">
<para>The DTMF digit to play.</para>
</parameter>
+ <parameter name="Duration" required="false">
+ <para>The duration in ms for the digit to play.</para>
+ </parameter>
</syntax>
<description>
<para>Plays a dtmf digit on the specified channel.</para>
@@ -145,7 +148,9 @@
{
const char *channel = astman_get_header(m, "Channel");
const char *digit = astman_get_header(m, "Digit");
+ const char *duration = astman_get_header(m, "Duration");
struct ast_channel *chan;
+ int dtmfduration = 0;
if (!(chan = ast_channel_get_by_name(channel))) {
astman_send_error(s, m, "Channel not found");
@@ -157,8 +162,11 @@
chan = ast_channel_unref(chan);
return 0;
}
+ if (!ast_strlen_zero(duration)) {
+ dtmfduration = atoi(duration);
+ }
- ast_senddigit(chan, *digit, 0);
+ ast_senddigit(chan, *digit, dtmfduration);
chan = ast_channel_unref(chan);
Modified: team/oej/pinetestedition-1.8/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/channels/chan_iax2.c?view=diff&rev=383028&r1=383027&r2=383028
==============================================================================
--- team/oej/pinetestedition-1.8/channels/chan_iax2.c (original)
+++ team/oej/pinetestedition-1.8/channels/chan_iax2.c Wed Mar 13 10:45:46 2013
@@ -1170,6 +1170,7 @@
static int iax2_call(struct ast_channel *c, char *dest, int timeout);
static int iax2_devicestate(void *data);
static int iax2_digit_begin(struct ast_channel *c, char digit);
+static int iax2_digit_continue(struct ast_channel *c, char digit, unsigned int duration);
static int iax2_digit_end(struct ast_channel *c, char digit, unsigned int duration);
static int iax2_do_register(struct iax2_registry *reg);
static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan);
@@ -1221,6 +1222,7 @@
.requester = iax2_request,
.devicestate = iax2_devicestate,
.send_digit_begin = iax2_digit_begin,
+ .send_digit_continue = iax2_digit_continue,
.send_digit_end = iax2_digit_end,
.send_text = iax2_sendtext,
.send_image = iax2_sendimage,
@@ -4293,8 +4295,15 @@
return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
}
+static int iax2_digit_continue(struct ast_channel *c, char digit, unsigned int duration)
+{
+ /* We propably should find a way to send duration here. */
+ return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_CONTINUE, digit, 0, NULL, 0, -1);
+}
+
static int iax2_digit_end(struct ast_channel *c, char digit, unsigned int duration)
{
+ /* We propably should find a way to send duration here. */
return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
}
Modified: team/oej/pinetestedition-1.8/channels/chan_local.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/channels/chan_local.c?view=diff&rev=383028&r1=383027&r2=383028
==============================================================================
--- team/oej/pinetestedition-1.8/channels/chan_local.c (original)
+++ team/oej/pinetestedition-1.8/channels/chan_local.c Wed Mar 13 10:45:46 2013
@@ -96,6 +96,7 @@
static struct ast_channel *local_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
static int local_digit_begin(struct ast_channel *ast, char digit);
+static int local_digit_continue(struct ast_channel *ast, char digit, unsigned int duration);
static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
static int local_call(struct ast_channel *ast, char *dest, int timeout);
static int local_hangup(struct ast_channel *ast);
@@ -118,6 +119,7 @@
.capabilities = -1,
.requester = local_request,
.send_digit_begin = local_digit_begin,
+ .send_digit_continue = local_digit_continue,
.send_digit_end = local_digit_end,
.call = local_call,
.hangup = local_hangup,
@@ -804,6 +806,29 @@
return res;
}
+static int local_digit_continue(struct ast_channel *ast, char digit, unsigned int duration)
+{
+ struct local_pvt *p = ast->tech_pvt;
+ int res = -1;
+ struct ast_frame f = { AST_FRAME_DTMF_CONTINUE, };
+ int isoutbound;
+
+ if (!p) {
+ return -1;
+ }
+
+ ao2_ref(p, 1); /* ref for local_queue_frame */
+ ao2_lock(p);
+ isoutbound = IS_OUTBOUND(ast, p);
+ f.subclass.integer = digit;
+ f.len = duration;
+ res = local_queue_frame(p, isoutbound, &f, ast, 0);
+ ao2_unlock(p);
+ ao2_ref(p, -1);
+
+ return res;
+}
+
static int local_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
{
struct local_pvt *p = ast->tech_pvt;
Modified: team/oej/pinetestedition-1.8/channels/chan_mgcp.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/channels/chan_mgcp.c?view=diff&rev=383028&r1=383027&r2=383028
==============================================================================
--- team/oej/pinetestedition-1.8/channels/chan_mgcp.c (original)
+++ team/oej/pinetestedition-1.8/channels/chan_mgcp.c Wed Mar 13 10:45:46 2013
@@ -450,6 +450,7 @@
static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
+static int mgcp_senddigit_continue(struct ast_channel *ast, char digit, unsigned int duration);
static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
static int mgcp_devicestate(void *data);
static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone);
@@ -475,6 +476,7 @@
.indicate = mgcp_indicate,
.fixup = mgcp_fixup,
.send_digit_begin = mgcp_senddigit_begin,
+ .send_digit_continue = mgcp_senddigit_continue,
.send_digit_end = mgcp_senddigit_end,
.bridge = ast_rtp_instance_bridge,
.func_channel_read = acf_channel_read,
@@ -1317,6 +1319,21 @@
return res;
}
+static int mgcp_senddigit_continue(struct ast_channel *ast, char digit, unsigned int duration)
+{
+ struct mgcp_subchannel *sub = ast->tech_pvt;
+ struct mgcp_endpoint *p = sub->parent;
+
+ ast_mutex_lock(&sub->lock);
+
+ if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+ ast_debug(4, "DTMF continue using RFC2833\n");
+ ast_rtp_instance_dtmf_continue(sub->rtp, digit, duration);
+ }
+ ast_mutex_unlock(&sub->lock);
+
+ return 0;
+}
static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
{
struct mgcp_subchannel *sub = ast->tech_pvt;
Modified: team/oej/pinetestedition-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinetestedition-1.8/channels/chan_sip.c?view=diff&rev=383028&r1=383027&r2=383028
==============================================================================
--- team/oej/pinetestedition-1.8/channels/chan_sip.c (original)
+++ team/oej/pinetestedition-1.8/channels/chan_sip.c Wed Mar 13 10:45:46 2013
@@ -264,6 +264,7 @@
#include "asterisk/cel.h"
#include "asterisk/data.h"
#include "asterisk/aoc.h"
+#include "asterisk/indications.h"
#include "sip/include/sip.h"
#include "sip/include/globals.h"
#include "sip/include/config_parser.h"
@@ -691,6 +692,7 @@
static char default_engine[256]; /*!< Default RTP engine */
static int default_maxcallbitrate; /*!< Maximum bitrate for call */
static struct ast_codec_pref default_prefs; /*!< Default codec prefs */
+static char default_zone[MAX_TONEZONE_COUNTRY]; /*!< Default tone zone for channels created from the SIP driver */
static unsigned int default_transports; /*!< Default Transports (enum sip_transport) that are acceptable */
static unsigned int default_primary_transport; /*!< Default primary Transport (enum sip_transport) for outbound connections to devices */
/*@}*/
@@ -1224,6 +1226,7 @@
static int sip_transfer(struct ast_channel *ast, const char *dest);
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int sip_senddigit_begin(struct ast_channel *ast, char digit);
+static int sip_senddigit_continue(struct ast_channel *ast, char digit, unsigned int duration);
static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
static int sip_setoption(struct ast_channel *chan, int option, void *data, int datalen);
static int sip_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
@@ -1281,6 +1284,8 @@
static void free_old_route(struct sip_route *route);
static void list_route(struct sip_route *route);
static void build_route(struct sip_pvt *p, struct sip_request *req, int backwards, int resp);
+static void build_path(struct sip_pvt *p, struct sip_peer *peer, struct sip_request *req, char *pathbuf);
+static void copy_route(struct sip_route **d, struct sip_route *s);
static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sockaddr *addr,
struct sip_request *req, const char *uri);
static struct sip_pvt *get_sip_pvt_byid_locked(const char *callid, const char *totag, const char *fromtag);
@@ -1446,7 +1451,7 @@
static void set_socket_transport(struct sip_socket *socket, int transport);
/* Realtime device support */
-static void realtime_update_peer(const char *peername, struct ast_sockaddr *addr, const char *username, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms);
+static void realtime_update_peer(const char *peername, struct ast_sockaddr *addr, const char *username, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms, const char *path);
static void update_peer(struct sip_peer *p, int expire);
static struct ast_variable *get_insecure_variable_from_config(struct ast_config *config);
static const char *get_name_from_variable(const struct ast_variable *var);
@@ -1528,6 +1533,7 @@
static int add_rpid(struct sip_request *req, struct sip_pvt *p);
static int add_vidupdate(struct sip_request *req);
static void add_route(struct sip_request *req, struct sip_route *route);
+static void make_route_list(struct sip_route *route, char *r, int rem);
static int copy_header(struct sip_request *req, const struct sip_request *orig, const char *field);
static int copy_all_header(struct sip_request *req, const struct sip_request *orig, const char *field);
static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, const struct sip_request *orig, const char *field);
@@ -1614,6 +1620,7 @@
.transfer = sip_transfer, /* called with chan locked */
.fixup = sip_fixup, /* called with chan locked */
.send_digit_begin = sip_senddigit_begin, /* called with chan unlocked */
+ .send_digit_continue = sip_senddigit_continue, /* called with chan unlocked */
.send_digit_end = sip_senddigit_end,
.bridge = ast_rtp_instance_bridge, /* XXX chan unlocked ? */
.early_bridge = ast_rtp_instance_early_bridge,
@@ -4757,6 +4764,10 @@
* implied else case here
*/
break;
+ case AST_OPTION_CNG_SUPPORT:
+ /* Check if the current dialog has agreed on Comfort Noise support */
+ res = (p->noncodeccapability & AST_RTP_CN);
+ break;
default:
break;
}
@@ -4858,7 +4869,7 @@
that name and store that in the "regserver" field in the sippeers
table to facilitate multi-server setups.
*/
[... 9423 lines stripped ...]
More information about the asterisk-commits
mailing list