[asterisk-commits] oej: branch oej/pinequeue-trunk r363098 - in /team/oej/pinequeue-trunk: apps/...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Apr 23 08:02:40 CDT 2012
Author: oej
Date: Mon Apr 23 08:02:37 2012
New Revision: 363098
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=363098
Log:
Look ma, it compiles
Modified:
team/oej/pinequeue-trunk/apps/app_queue.c
team/oej/pinequeue-trunk/configs/queues.conf.sample
team/oej/pinequeue-trunk/include/asterisk/channel.h
team/oej/pinequeue-trunk/include/asterisk/file.h
team/oej/pinequeue-trunk/main/asterisk.dynamics
team/oej/pinequeue-trunk/main/channel.c
team/oej/pinequeue-trunk/main/features.c
team/oej/pinequeue-trunk/main/file.c
team/oej/pinequeue-trunk/main/say.c
Modified: team/oej/pinequeue-trunk/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinequeue-trunk/apps/app_queue.c?view=diff&rev=363098&r1=363097&r2=363098
==============================================================================
--- team/oej/pinequeue-trunk/apps/app_queue.c (original)
+++ team/oej/pinequeue-trunk/apps/app_queue.c Mon Apr 23 08:02:37 2012
@@ -968,7 +968,6 @@
{ QUEUE_AUTOPAUSE_ALL,"all" },
};
-
static struct ast_taskprocessor *devicestate_tps;
#define DEFAULT_RETRY 5
@@ -1016,6 +1015,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;
@@ -1288,6 +1290,7 @@
static void update_realtime_members(struct call_queue *q);
static struct member *interface_exists(struct call_queue *q, const char *interface);
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);
@@ -2696,6 +2699,8 @@
return res;
}
+void destroy_streamfile_info(struct ast_queue_streamfile_info *playdata);
+/* Uncommented by Old Olle patch
static int play_file(struct ast_channel *chan, const char *filename)
{
int res;
@@ -2717,7 +2722,7 @@
ast_stopstream(chan);
return res;
-}
+} */
/*!
* \brief Check for valid exit from queue via goto
@@ -2750,7 +2755,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;
}
@@ -2773,11 +2778,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 ||
@@ -2789,7 +2795,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
@@ -2797,7 +2803,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, ast_channel_language(qe->chan), NULL); /* Needs gender */
@@ -2805,7 +2811,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, ast_channel_language(qe->chan), NULL); /* Needs gender */
@@ -2814,11 +2820,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;
}
@@ -2842,7 +2848,7 @@
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);
+ res = play_file(qe->chan, qe->parent->sound_holdtime,ringing,NULL);
if (res)
goto playout;
@@ -2852,11 +2858,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;
}
@@ -2866,7 +2872,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;
}
@@ -2880,11 +2886,11 @@
ast_channel_name(qe->chan), 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 && !valid_exit(qe, res)) /* in other words, ignore any play_file problems... */
res = 0;
/* Set our last_pos indicators */
@@ -2892,13 +2898,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;
}
@@ -3492,12 +3503,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) {
@@ -3508,10 +3513,14 @@
}
/* 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 = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]),ringing, qe->moh);
+
+ /* if (res > 0 && !valid_exit(qe, res))
res = 0;
+ */
+ /* we no longer check for valid_exit(), as we simply
+ start the playback and let the autoservice thread
+ keep it going */
/* Resume Music on Hold if the caller is going to stay in the queue */
if (!res) {
@@ -3673,10 +3682,15 @@
#endif
while (*to && !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;
@@ -4003,6 +4017,9 @@
}
}
}
+ if (background_prompts) {
+ play_file(qe->chan, NULL, 0, qe->moh);
+ }
/* If we received an event from the caller, deal with it. */
if (winner == in) {
@@ -4391,6 +4408,7 @@
.chan_fixup = queue_transfer_fixup,
.destroy = queue_transfer_destroy,
};
+
/*! \brief Log an attended transfer when a queue caller channel is masqueraded
*
@@ -4849,29 +4867,36 @@
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 (!res2 && announce) {
- play_file(peer, announce);
- }
- 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, ast_channel_language(peer), NULL);
- play_file(peer, qe->parent->sound_minutes);
- }
- if (holdtimesecs > 1) {
- ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
- play_file(peer, qe->parent->sound_seconds);
- }
+
+ /* instead of starting autoservice and jacking this thread to push sound to the
+ peer channel, let's set up a background player to the peer channel and
+ get on with life in this thread. */
+
+ 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) {
+ play_file(peer, announce, ringing, qe->moh);;
+ }
+ 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) {
+ //int ast_say_number(struct ast_channel *chan, int num,
+ //const char *ints, const char *lang, const char *options);
+ ast_say_number(peer, holdtime, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
+ play_file(peer, qe->parent->sound_minutes, ringing, qe->moh);
+ }
+ if (holdtimesecs > 1) {
+ ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
+ play_file(peer, qe->parent->sound_seconds, ringing, qe->moh);
}
}
}
@@ -4904,10 +4929,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 (ast_channel_cdr(qe->chan)) {
ast_cdr_setdestchan(ast_channel_cdr(qe->chan), ast_channel_name(peer));
@@ -4926,7 +4952,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);
}
@@ -5100,7 +5126,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", ast_channel_name(qe->chan));
res = -1;
}
@@ -5343,8 +5369,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;
@@ -6105,6 +6132,310 @@
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", ast_channel_name(chan));
+ 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';
+ ast_channel_stream_set(state->chan, NULL);
+ state->stream = NULL;
+ state->aqsi->now_playing = 0; /* Important flag to indicate we are no longer playing on this channel */
+ //ast_log(LOG_DEBUG, "--- Restarting MOH --\n");
+ //if (state->aqsi->ringing) {
+ //ast_indicate(state->chan, AST_CONTROL_RINGING);
+ //} else if (state->aqsi->moh) {
+ //ast_moh_start(state->chan, state->aqsi->moh, NULL);
+ //}
+}
+
+/*! \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", ast_channel_name(state->chan));
+ } 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", ast_channel_name(state->chan));
+ return f;
+ }
+
+ if (!state->stream) {
+ if (!(state->stream = ast_openstream_full(state->chan, state->filename, ast_channel_language(state->chan), 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, ast_channel_name(chan));
+
+ 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;
+ }
+ /* Play prompts like before, with no interruption */
+ ast_stopstream(chan);
+ res = ast_streamfile(chan, filename, ast_channel_language(chan));
+ 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 */
+ 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", ast_channel_name(chan));
+ return 1; /* Why continue, if I can't access the datastore & list? */
+ }
+ ast_debug(2, "---- Aqsi now playing: %d\n", aqsi->now_playing);
+
+ 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));
+ ringing = aqsi->ringing;
+ moh = aqsi->moh;
+ 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(ast_channel_flags(chan), AST_FLAG_MOH)) {
+ ast_moh_start(chan, aqsi->qe->moh, NULL);
+ }
+ }
+ return -1;
+ }
+ } 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 -1;
+ }
+ }
+
+ 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);
+ ast_debug(3, " queued sound file %s for playing on chan %s\n", filename, ast_channel_name(chan));
+
+ /* 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", ast_channel_name(chan));
+ ast_indicate(chan,-1);
+ } else {
+ ast_debug(3, "Stopping MOH on chan %s\n", ast_channel_name(chan));
+ ast_moh_stop(chan);
+ }
+
+ ast_debug(3, "Stopping Streaming on chan %s\n", ast_channel_name(chan));
+ ast_stopstream(chan);
+
+ ast_debug(3, "Autoservice stop on chan %s\n", ast_channel_name(chan));
+ 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");
+ 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, ast_channel_name(chan));
+ /* 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
@@ -6128,6 +6459,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 = calloc(1,sizeof(struct ast_queue_streamfile_info));
+
/* whether to exit Queue application after the timeout hits */
int tries = 0;
int noption = 0;
@@ -6256,6 +6590,20 @@
S_OR(args.url, ""),
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
qe.opos);
+ /* Begin old Olle patch */
+ datastore = ast_datastore_alloc(ast_sound_ending(), NULL);
+
+ aqsi->qe = &qe;
+ aqsi->chan = chan;
+ aqsi->ringing = ringing;
+ aqsi->now_playing = 0;
+ strcpy(aqsi->moh, qe.moh);
+ AST_LIST_HEAD_INIT(&aqsi->flist);
+ datastore->data = aqsi;
+
+ ast_channel_datastore_add(chan, datastore);
+ /* End old Olle patch */
+
copy_rules(&qe, args.rule);
qe.pr = AST_LIST_FIRST(&qe.qe_rules);
check_turns:
@@ -6289,6 +6637,9 @@
break;
}
+ if (background_prompts) {
+ play_file(qe.chan, NULL, ringing, qe.moh); /* OEJ - Trigger next prompt */
+ }
if (makeannouncement) {
/* Make a position announcement, if enabled */
if (qe.parent->announcefrequency)
@@ -6371,6 +6722,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) {
@@ -6387,17 +6744,6 @@
ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "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);
@@ -6972,6 +7318,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"))) {
Modified: team/oej/pinequeue-trunk/configs/queues.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinequeue-trunk/configs/queues.conf.sample?view=diff&rev=363098&r1=363097&r2=363098
==============================================================================
--- team/oej/pinequeue-trunk/configs/queues.conf.sample (original)
+++ team/oej/pinequeue-trunk/configs/queues.conf.sample Mon Apr 23 08:02:37 2012
@@ -77,6 +77,14 @@
; set appropriately.
;
;check_state_unknown = no
+;
+; Prompts played to the caller by default is played in the foreground,
+; which means that even if a queue member becomes available, the
+; prompt will be played fully. Enabling 'background_prompts' will
+; make sure that prompts are interruptible. If a queue member becomes
+; available, the prompt will be interrupted.
+;
+background_prompts=no
;
;[markq]
;
Modified: team/oej/pinequeue-trunk/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinequeue-trunk/include/asterisk/channel.h?view=diff&rev=363098&r1=363097&r2=363098
==============================================================================
--- team/oej/pinequeue-trunk/include/asterisk/channel.h (original)
+++ team/oej/pinequeue-trunk/include/asterisk/channel.h Mon Apr 23 08:02:37 2012
@@ -3513,6 +3513,28 @@
* \param size The size of the buffer to write to
*/
int ast_channel_get_cc_agent_type(struct ast_channel *chan, char *agent_type, size_t size);
+
+/*! \brief Asynchronous filestream playing playlist
+ Used (at least at first) in app_queue - in the ast_queue_streamfile_info channel datastore
+*/
+struct ast_queue_streamfile_name {
+ char *filename;
+ AST_LIST_ENTRY(ast_queue_streamfile_name) list;
+};
+
+/*! \brief Information data about background playing of prompts */
+struct ast_queue_streamfile_info {
+ void (*digitHandler)(void *data, char digit); /* a func ptr to the handler that will do what needs doing when the streaming of a soundfile is finished */
+ struct queue_ent *qe;
+ AST_LIST_HEAD(,ast_queue_streamfile_name) flist; /* a list of other sound files that need to be played in sequence */
+ struct ast_channel *chan;
+ int ringing;
+ char moh[80];
+ int now_playing;
+ int valid_exit; /* if valid_exit() in app_queue is true */
+};
+
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Modified: team/oej/pinequeue-trunk/include/asterisk/file.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinequeue-trunk/include/asterisk/file.h?view=diff&rev=363098&r1=363097&r2=363098
==============================================================================
--- team/oej/pinequeue-trunk/include/asterisk/file.h (original)
+++ team/oej/pinequeue-trunk/include/asterisk/file.h Mon Apr 23 08:02:37 2012
@@ -39,6 +39,8 @@
struct ast_filestream;
struct ast_format;
+
+const struct ast_datastore_info *ast_sound_ending(void);
/*! The maximum number of formats we expect to see in a format string */
#define AST_MAX_FORMATS 10
@@ -338,6 +340,7 @@
*/
char *ast_format_str_reduce(char *fmts);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Modified: team/oej/pinequeue-trunk/main/asterisk.dynamics
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinequeue-trunk/main/asterisk.dynamics?view=diff&rev=363098&r1=363097&r2=363098
==============================================================================
--- team/oej/pinequeue-trunk/main/asterisk.dynamics (original)
+++ team/oej/pinequeue-trunk/main/asterisk.dynamics Mon Apr 23 08:02:37 2012
@@ -1,4 +1,5 @@
{
+ *ast_sound_*;
*ast_adsi_*;
*ast_agi_*;
*ast_pktccops_*;
Modified: team/oej/pinequeue-trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinequeue-trunk/main/channel.c?view=diff&rev=363098&r1=363097&r2=363098
==============================================================================
--- team/oej/pinequeue-trunk/main/channel.c (original)
+++ team/oej/pinequeue-trunk/main/channel.c Mon Apr 23 08:02:37 2012
@@ -2880,6 +2880,7 @@
ast_channel_generator(chan)->write_format_change(chan, ast_channel_generatordata(chan));
}
ast_channel_unlock(chan);
+ ast_debug(3, "ast_deactivate_generator() done on chan %s\n", ast_channel_name(chan));
}
static int generator_force(const void *data)
@@ -4050,6 +4051,7 @@
/* Run generator sitting on the line if timing device not available
* and synchronous generation of outgoing frames is necessary */
+ ast_debug(3, ">>>>>>>>> just another silly message. We are generating, man! \n");
ast_read_generator_actions(chan, f);
}
break;
Modified: team/oej/pinequeue-trunk/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinequeue-trunk/main/features.c?view=diff&rev=363098&r1=363097&r2=363098
==============================================================================
--- team/oej/pinequeue-trunk/main/features.c (original)
+++ team/oej/pinequeue-trunk/main/features.c Mon Apr 23 08:02:37 2012
@@ -1567,10 +1567,13 @@
ast_debug(4, "AMI ParkedCall Channel: %s\n", ast_channel_name(chan));
ast_debug(4, "AMI ParkedCall From: %s\n", event_from);
+/* OEJ */
+#ifdef HAVE_ADSI
if (peer && adsipark && ast_adsi_available(peer)) {
adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
ast_adsi_unload_session(peer);
}
+#endif
snprintf(app_data, sizeof(app_data), "%s,%s", pu->parkingexten,
pu->parkinglot->name);
Modified: team/oej/pinequeue-trunk/main/file.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinequeue-trunk/main/file.c?view=diff&rev=363098&r1=363097&r2=363098
==============================================================================
--- team/oej/pinequeue-trunk/main/file.c (original)
+++ team/oej/pinequeue-trunk/main/file.c Mon Apr 23 08:02:37 2012
@@ -44,6 +44,7 @@
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/linkedlists.h"
+#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
#include "asterisk/test.h"
@@ -771,6 +772,18 @@
return NULL;
}
+static const struct ast_datastore_info ast_sound_ending_obj = { /* this is here because it is referenced here
+ and the only other place it is used is in app_queue,
+ which is not always loaded. */
+ .type = "ast_sound_ending"
+};
+
+const struct ast_datastore_info *ast_sound_ending()
+{
+ return &ast_sound_ending_obj;
+}
+
+
static struct ast_frame *read_frame(struct ast_filestream *s, int *whennext)
{
struct ast_frame *fr, *new_fr;
@@ -829,6 +842,7 @@
ast_log(LOG_WARNING, "Failed to write frame\n");
ast_frfree(fr);
}
+ ast_log(LOG_DEBUG, "--- Giving up here now\n");
goto return_failure;
}
Modified: team/oej/pinequeue-trunk/main/say.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pinequeue-trunk/main/say.c?view=diff&rev=363098&r1=363097&r2=363098
==============================================================================
--- team/oej/pinequeue-trunk/main/say.c (original)
+++ team/oej/pinequeue-trunk/main/say.c Mon Apr 23 08:02:37 2012
@@ -50,11 +50,13 @@
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/utils.h"
+#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/test.h"
/* Forward declaration */
static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang);
+static int wait_file_full(struct ast_channel *chan, const char *ints, const char *file, const char *lang, int audiofd, int ctrlfd);
static int say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
@@ -124,14 +126,7 @@
}
if ((fn && ast_fileexists(fn, NULL, lang) > 0) ||
(snprintf(asciibuf + 13, sizeof(asciibuf) - 13, "%d", str[num]) > 0 && ast_fileexists(asciibuf, NULL, lang) > 0 && (fn = asciibuf))) {
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
+ res = wait_file_full(chan, ints, fn, lang, audiofd, ctrlfd);
}
num++;
}
@@ -204,14 +199,7 @@
fn = fnbuf;
}
if (fn && ast_fileexists(fn, NULL, lang) > 0) {
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
+ res = wait_file_full(chan, ints, fn, lang, audiofd, ctrlfd);
}
num++;
}
@@ -254,14 +242,7 @@
break;
}
if (fn && ast_fileexists(fn, NULL, lang) > 0) {
- res = ast_streamfile(chan, fn, lang);
- if (!res) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
+ res = wait_file_full(chan, ints, fn, lang, audiofd, ctrlfd);
}
num++;
}
@@ -422,12 +403,89 @@
static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang)
{
+ return wait_file_full(chan, ints, file, lang, -1, -1);
+}
+
+/*! wait_file_full: this routine to provide wait_file capability for those with audiofd, ctrlfd
+*/
+static int wait_file_full(struct ast_channel *chan, const char *ints, const char *file, const char *lang, int audiofd, int ctrlfd)
+{
int res;
- if ((res = ast_streamfile(chan, file, lang)))
- ast_log(LOG_WARNING, "Unable to play message %s\n", file);
- if (!res)
- res = ast_waitstream(chan, ints);
- return res;
+ struct ast_datastore *datastore;
+
+ /* if a datastore is present, we are in the queue app (perhaps others in time)
+ and don't want to wait around for the sounds to finish playing */
+
+ if ((datastore = ast_channel_datastore_find(chan, ast_sound_ending(), NULL))) { /* app_queue wants to schedule this instead of play & wait */
+ struct ast_queue_streamfile_info *aqsi = datastore->data;
+ if (aqsi) {
+ AST_LIST_LOCK(&aqsi->flist);
+ if (aqsi->now_playing) {
+ struct ast_queue_streamfile_name *fn = ast_calloc(1, sizeof(*fn));
+
+ fn->filename = ast_strdup(file);
+ ast_debug(3, "----> Adding file %s to playlist for %s\n", file, ast_channel_name(chan));
+
+ /* link the struct into the current ast_queue_streamfile_info struct */
+ AST_LIST_INSERT_TAIL(&aqsi->flist, fn, list);
+ } else {
+ /* if not playing, then start playing this file */
+ if (aqsi->ringing) {
+ ast_indicate(aqsi->chan,-1);
+ } else {
+ ast_moh_stop(aqsi->chan);
+ }
+
+ ast_stopstream(aqsi->chan);
+
+ ast_autoservice_stop(aqsi->chan);
+
+ ast_debug(3, "Starting to stream %s\n", file);
+ res = ast_streamfile(aqsi->chan, file, ast_channel_language(aqsi->chan)); /* begin the streaming */
+
+ while (res && !AST_LIST_EMPTY(&aqsi->flist)) {
+ /* really, how could this even be possible?
+ just in case.... */
+ struct ast_queue_streamfile_name *fn;
+
+ fn = AST_LIST_REMOVE_HEAD(&aqsi->flist, list);
+
+ ast_debug(3,"Start streaming file %s\n", fn->filename);
+ res = ast_streamfile(aqsi->chan, fn->filename, ast_channel_language(aqsi->chan));
+ }
+
+
+ if (res) {
+ /* oops, the current file has problems */
+ /* restore the moh */
+ if (aqsi->ringing) {
+ ast_indicate(aqsi->chan, AST_CONTROL_RINGING);
+ } else {
+ ast_moh_start(aqsi->chan, aqsi->moh, NULL);
+ }
+ AST_LIST_UNLOCK(&aqsi->flist);
+ return 1;
+ }
+ aqsi->now_playing = 1; /* We have begun playback */
+ ast_autoservice_start(aqsi->chan); /* this will let the sound file play in a different thread */
+ }
+ AST_LIST_UNLOCK(&aqsi->flist);
+ return 0;
+ }
+
+ } else {
+ /* otherwise, exactly business as usual */
+ if ((res = ast_streamfile(chan, file, lang))) {
+ ast_log(LOG_WARNING, "Unable to play message %s\n", file);
+ }
+ if ((audiofd > -1) && (ctrlfd > -1)) {
+ res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+ } else {
+ res = ast_waitstream(chan, ints);
+ }
+ return res;
+ }
+ return 0;
}
/*! \brief ast_say_number_full: call language-specific functions
@@ -563,13 +621,7 @@
}
}
if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
+ res = wait_file_full(chan, ints, fn, language, audiofd, ctrlfd);
}
}
return res;
@@ -686,14 +738,7 @@
num -= left * (exp10_int(length-1));
}
if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1)) {
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- } else {
- res = ast_waitstream(chan, ints);
- }
- }
- ast_stopstream(chan);
+ res = wait_file_full(chan, ints, fn, language, audiofd, ctrlfd);
}
}
return res;
@@ -795,13 +840,7 @@
}
}
if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
+ res = wait_file_full(chan, ints, fn, language, audiofd, ctrlfd);
}
}
return res;
@@ -925,19 +964,10 @@
res = -1;
}
if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
+ res = wait_file_full(chan, ints, fn, language, audiofd, ctrlfd);
if (!res) {
- if (strlen(fna) != 0 && !ast_streamfile(chan, fna, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
+ if (strlen(fna) != 0 ) {
+ res = wait_file_full(chan, ints, fn, language, audiofd, ctrlfd);
}
ast_stopstream(chan);
strcpy(fna, "");
@@ -1011,13 +1041,7 @@
}
if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
+ res = wait_file_full(chan, ints, fn, language, audiofd, ctrlfd);
}
}
return res;
@@ -1116,14 +1140,7 @@
}
if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
-
+ res = wait_file_full(chan, ints, fn, language, audiofd, ctrlfd);
}
}
@@ -1208,13 +1225,7 @@
res = -1;
}
if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1))
- res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
- else
- res = ast_waitstream(chan, ints);
- }
- ast_stopstream(chan);
+ res = wait_file_full(chan, ints, fn, language, audiofd, ctrlfd);
}
}
return res;
@@ -1379,14 +1390,7 @@
}
tmpnum = 0;
if (!res) {
- if (!ast_streamfile(chan, fn, language)) {
- if ((audiofd > -1) && (ctrlfd > -1)) {
[... 1053 lines stripped ...]
More information about the asterisk-commits
mailing list