[asterisk-commits] russell: branch russell/chan_console r49057 -
/team/russell/chan_console/chan...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Fri Dec 29 06:25:54 MST 2006
Author: russell
Date: Fri Dec 29 07:25:54 2006
New Revision: 49057
URL: http://svn.digium.com/view/asterisk?view=rev&rev=49057
Log:
Split the portaudio callback into a couple of different functions.
Modified:
team/russell/chan_console/channels/chan_console.c
Modified: team/russell/chan_console/channels/chan_console.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_console/channels/chan_console.c?view=diff&rev=49057&r1=49056&r2=49057
==============================================================================
--- team/russell/chan_console/channels/chan_console.c (original)
+++ team/russell/chan_console/channels/chan_console.c Fri Dec 29 07:25:54 2006
@@ -119,8 +119,11 @@
char write_buf[NUM_SAMPLES * 2];
/*! The index for the next write into write_buf */
unsigned int write_dst;
- /*! The current index into the sounds array */
- int cur_sound;
+ /*! The current index into the sounds array, -1 means none */
+ int cursound;
+ /*! The number of samples sent for the current sound, mod the total number
+ * of samples for the sound plus trailing silence. */
+ unsigned int sampsent;
/*! On-hook = 0, Off-hook = 1 */
unsigned int hookstate:1;
/*! Ignore context in the console dial CLI command */
@@ -137,7 +140,7 @@
} pvt = {
.name = "default",
.lock = AST_MUTEX_INIT_VALUE,
- .cur_sound = -1,
+ .cursound = -1,
};
/*! Global jitterbuffer configuration - by default, jb is disabled */
@@ -305,7 +308,7 @@
ast_verbose(" --- <(\"<) --- Hangup on Console --- (>\")> ---\n");
pvt.hookstate = 0;
- pvt.cur_sound = -1;
+ pvt.cursound = -1;
c->tech_pvt = NULL;
pvt.owner = NULL;
@@ -331,7 +334,7 @@
ast_mutex_lock(&pvt.lock);
ast_setstate(c, AST_STATE_UP);
- pvt.cur_sound = -1;
+ pvt.cursound = -1;
res = start_stream();
ast_mutex_unlock(&pvt.lock);
@@ -413,84 +416,96 @@
return 0;
}
+static int handle_output(void *output, unsigned long frame_count)
+{
+ unsigned int src = 0;
+ unsigned int num_samples;
+ struct ast_frame *fr;
+
+ ast_mutex_lock(&pvt.lock);
+ if (pvt.write_dst) {
+ num_samples = (pvt.write_dst * 2) > frame_count ? pvt.write_dst * 2 : frame_count;
+ memcpy(output, &pvt.write_buf, num_samples * 2);
+ pvt.write_dst -= num_samples * 2;
+ src += num_samples * 2;
+ frame_count -= num_samples;
+ }
+ while (frame_count) {
+ while (!(fr = AST_LIST_REMOVE_HEAD(&pvt.frames, frame_list))) {
+ ast_cond_wait(&pvt.cond, &pvt.lock);
+ if (!pvt.hookstate) {
+ if (fr)
+ ast_frfree(fr);
+ ast_mutex_unlock(&pvt.lock);
+ pvt.incallback = 0;
+ return paAbort;
+ }
+ }
+ num_samples = fr->samples > frame_count ? frame_count : fr->samples;
+ memcpy(output + src, fr->data, num_samples * 2);
+ frame_count -= num_samples;
+ if (num_samples != fr->samples) {
+ memcpy(&pvt.write_buf + pvt.write_dst, fr->data + num_samples * 2, (fr->samples - num_samples) * 2);
+ pvt.write_dst += (fr->samples - num_samples) * 2;
+ }
+ ast_frfree(fr);
+ }
+ ast_mutex_unlock(&pvt.lock);
+
+ return paContinue;
+}
+
+static int handle_input(const void *input, unsigned long frame_count)
+{
+ struct ast_frame *fr = &pvt.fr;
+ unsigned int count = 0;
+
+ memset(fr, 0, sizeof(*fr));
+ memset(pvt.read_buf, 0, NUM_SAMPLES * 2 + AST_FRIENDLY_OFFSET);
+ fr->data = pvt.read_buf + AST_FRIENDLY_OFFSET;
+ fr->offset = AST_FRIENDLY_OFFSET;
+ fr->frametype = AST_FRAME_VOICE;
+ fr->subclass = AST_FORMAT_SLINEAR;
+ fr->samples = NUM_SAMPLES;
+ fr->datalen = NUM_SAMPLES * 2;
+ memcpy(fr->data, input, NUM_SAMPLES * 2);
+
+ /* If the channel is in the process of being hung up, then it will be
+ * locked while calling the console_hangup callback, and that could be
+ * waiting to stop the audio stream, which will block until this
+ * function returns. Thus, locking the channel could result in a
+ * deadlock. So, we use the fact that the locks are recursive to test
+ * locking the channel before queueing the frame. */
+ while (ast_channel_trylock(pvt.owner)) {
+ if (++count == 100) {
+ ast_log(LOG_DEBUG, "Dropping frame\n");
+ pvt.incallback = 0;
+ return paContinue;
+ }
+ usleep(10);
+ }
+ ast_queue_frame(pvt.owner, fr);
+ ast_channel_unlock(pvt.owner);
+
+ return paContinue;
+}
+
static int console_callback(const void *input, void *output,
unsigned long frame_count, const PaStreamCallbackTimeInfo *time_info,
PaStreamCallbackFlags flags, void *userData)
{
+ int res = paContinue;
+
pvt.incallback = 1;
- if (output) {
- unsigned int src = 0;
- unsigned int num_samples;
- struct ast_frame *fr;
- ast_mutex_lock(&pvt.lock);
- if (pvt.write_dst) {
- num_samples = (pvt.write_dst * 2) > frame_count ? pvt.write_dst * 2 : frame_count;
- memcpy(output, &pvt.write_buf, num_samples * 2);
- pvt.write_dst -= num_samples * 2;
- src += num_samples * 2;
- frame_count -= num_samples;
- }
- while (frame_count) {
- while (!(fr = AST_LIST_REMOVE_HEAD(&pvt.frames, frame_list))) {
- ast_cond_wait(&pvt.cond, &pvt.lock);
- if (!pvt.hookstate) {
- if (fr)
- ast_frfree(fr);
- ast_mutex_unlock(&pvt.lock);
- pvt.incallback = 0;
- return paAbort;
- }
- }
- num_samples = fr->samples > frame_count ? frame_count : fr->samples;
- memcpy(output + src, fr->data, num_samples * 2);
- frame_count -= num_samples;
- if (num_samples != fr->samples) {
- memcpy(&pvt.write_buf + pvt.write_dst, fr->data + num_samples * 2, (fr->samples - num_samples) * 2);
- pvt.write_dst += (fr->samples - num_samples) * 2;
- }
- ast_frfree(fr);
- }
- ast_mutex_unlock(&pvt.lock);
-
- if (frame_count) {
- ast_log(LOG_WARNING, "console_callback didn't get %lu of the samples it wanted :(\n", frame_count);
- memset(output + src, 0, frame_count * 2);
- }
- }
-
- if (input) {
- struct ast_frame *fr = &pvt.fr;
- unsigned int count = 0;
- memset(fr, 0, sizeof(*fr));
- memset(pvt.read_buf, 0, NUM_SAMPLES * 2 + AST_FRIENDLY_OFFSET);
- fr->data = pvt.read_buf + AST_FRIENDLY_OFFSET;
- fr->offset = AST_FRIENDLY_OFFSET;
- fr->frametype = AST_FRAME_VOICE;
- fr->subclass = AST_FORMAT_SLINEAR;
- fr->samples = NUM_SAMPLES;
- fr->datalen = NUM_SAMPLES * 2;
- memcpy(fr->data, input, NUM_SAMPLES * 2);
- /* If the channel is in the process of being hung up, then it will be
- * locked while calling the console_hangup callback, and that could be
- * waiting to stop the audio stream, which will block until this
- * function returns. Thus, locking the channel could result in a
- * deadlock. So, we use the fact that the locks are recursive to test
- * locking the channel before queueing the frame. */
- while (ast_channel_trylock(pvt.owner)) {
- if (++count == 100) {
- ast_log(LOG_DEBUG, "Dropping frame\n");
- pvt.incallback = 0;
- return paContinue;
- }
- usleep(10);
- }
- ast_queue_frame(pvt.owner, fr);
- ast_channel_unlock(pvt.owner);
- }
+ if (output)
+ res = handle_output(output, frame_count);
+ if (res != paAbort && input)
+ res = handle_input(input, frame_count);
pvt.incallback = 0;
- return paContinue;
+
+ return res;
}
/*
@@ -594,7 +609,7 @@
return CLI_FAILURE;
}
pvt.hookstate = 0;
- pvt.cur_sound = -1;
+ pvt.cursound = -1;
if (pvt.owner)
ast_queue_hangup(pvt.owner);
More information about the asterisk-commits
mailing list