[asterisk-commits] russell: branch russell/chan_console r49017 -
/team/russell/chan_console/chan...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Dec 28 05:43:36 MST 2006
Author: russell
Date: Thu Dec 28 06:43:35 2006
New Revision: 49017
URL: http://svn.digium.com/view/asterisk?view=rev&rev=49017
Log:
- Place common code for starting and stopping the audio stream in functions
- Hackishly work around a couple of different deadlocks.
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=49017&r1=49016&r2=49017
==============================================================================
--- team/russell/chan_console/channels/chan_console.c (original)
+++ team/russell/chan_console/channels/chan_console.c Thu Dec 28 06:43:35 2006
@@ -65,12 +65,16 @@
ast_cond_t cond;
unsigned int hookstate:1;
unsigned int overridecontext:1;
+ unsigned int incallback:1;
AST_LIST_HEAD_NOLOCK(, ast_frame) frames;
} pvt = {
.name = "default",
};
AST_MUTEX_DEFINE_STATIC(console_lock);
+
+static int start_stream(void);
+static int stop_stream(void);
static struct ast_channel *console_request(const char *type, int format,
void *data, int *cause);
@@ -183,49 +187,37 @@
static int console_hangup(struct ast_channel *c)
{
- PaError err;
int res = 0;
ast_verbose(" -=- Hangup on Console -=-\n");
+
+ while (pvt.incallback) /* :( */
+ usleep(10);
ast_mutex_lock(&console_lock);
c->tech_pvt = NULL;
pvt.owner = NULL;
- if (pvt.hookstate) {
- err = Pa_StopStream(pvt.stream);
- if (err != paNoError) {
- ast_log(LOG_WARNING, "Error stopping stream!\n");
- res = -1;
- }
- pvt.hookstate = 0;
- }
+ if (pvt.hookstate)
+ stop_stream();
+ ast_mutex_unlock(&console_lock);
+
+ return res;
+}
+
+static int console_answer(struct ast_channel *c)
+{
+ int res = 0;
+
+ ast_verbose(" -=- Call from Console has been Answered -=-\n");
+
ast_mutex_lock(&console_lock);
+ ast_setstate(c, AST_STATE_UP);
+ res = start_stream();
+ ast_mutex_unlock(&console_lock);
return res;
}
-static int console_answer(struct ast_channel *c)
-{
- PaError err;
- int res = 0;
-
- ast_verbose(" -=- Call from Console has been Answered -=-\n");
-
- ast_mutex_lock(&console_lock);
-
- ast_setstate(c, AST_STATE_UP);
-
- err = Pa_StartStream(pvt.stream);
- if (err != paNoError) {
- ast_log(LOG_WARNING, "Error starting stream!\n");
- res = -1;
- }
-
- ast_mutex_unlock(&console_lock);
-
- return 0;
-}
-
static struct ast_frame *console_read(struct ast_channel *chan)
{
ast_log(LOG_WARNING, "This should never be called, mmkay?!\n");
@@ -236,7 +228,6 @@
static int console_call(struct ast_channel *c, char *dest, int timeout)
{
struct ast_frame f = { 0, };
- PaError err;
int res = 0;
ast_verbose(" << Call to device '%s' dnid '%s' rdnis '%s' on console "
@@ -248,11 +239,7 @@
f.subclass = AST_CONTROL_ANSWER;
ast_queue_frame(c, &f);
- err = Pa_StartStream(pvt.stream);
- if (err != paNoError) {
- ast_log(LOG_WARNING, "Error starting stream!\n");
- res = -1;
- }
+ res = start_stream();
return res;
}
@@ -260,8 +247,6 @@
static int console_write(struct ast_channel *chan, struct ast_frame *f)
{
struct ast_frame *fr = ast_frdup(f);
-
- //ast_log(LOG_NOTICE, "console_write...\n");
if (!fr)
return -1;
@@ -291,7 +276,7 @@
unsigned long frame_count, const PaStreamCallbackTimeInfo *time_info,
PaStreamCallbackFlags flags, void *userData)
{
- //ast_log(LOG_NOTICE, "console_callback, frame_count: %lu ...\n", frame_count);
+ pvt.incallback = 1;
if (output) {
unsigned int src = 0;
@@ -300,24 +285,28 @@
ast_mutex_lock(&console_lock);
if (pvt.write_dst) {
num_samples = (pvt.write_dst * 2) > frame_count ? pvt.write_dst * 2 : frame_count;
- //ast_log(LOG_NOTICE, "writing %d samples from write_buf\n", num_samples);
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)))
+ while (!(fr = AST_LIST_REMOVE_HEAD(&pvt.frames, frame_list))) {
ast_cond_wait(&pvt.cond, &console_lock);
+ if (!pvt.hookstate) {
+ if (fr)
+ ast_frfree(fr);
+ ast_mutex_unlock(&console_lock);
+ pvt.incallback = 0;
+ return paAbort;
+ }
+ }
num_samples = fr->samples > frame_count ? frame_count : fr->samples;
- //ast_log(LOG_NOTICE, "Writing %d samples from frame\n", num_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_log(LOG_NOTICE, "Saving %d bytes (%d samples) left over in frame\n",
- //(fr->samples - num_samples) * 2, (fr->samples - num_samples) * 2);
}
ast_frfree(fr);
}
@@ -331,6 +320,7 @@
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;
@@ -340,9 +330,19 @@
fr->samples = NUM_SAMPLES;
fr->datalen = NUM_SAMPLES * 2;
memcpy(fr->data, input, NUM_SAMPLES * 2);
+ 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);
+ }
+
+ pvt.incallback = 0;
return paContinue;
}
@@ -413,8 +413,7 @@
if (a->argc == e->args + 1) {
s = ast_ext_ctx(a->argv[e->args], &mye, &myc);
ast_log(LOG_NOTICE, "provided '%s', exten '%s' context '%s'\n", a->argv[e->args], mye, myc);
- } else
- ast_log(LOG_NOTICE, "No exten?\n");
+ }
/* supply default values if needed */
if (mye == NULL)
mye = "s";
@@ -459,21 +458,53 @@
NEW_CLI(cli_console_hangup, "Hangup a call on the console"),
};
+static int start_stream(void)
+{
+ PaError res;
+
+ res = Pa_OpenDefaultStream(&pvt.stream, INPUT_CHANNELS, OUTPUT_CHANNELS,
+ paInt16, SAMPLE_RATE, NUM_SAMPLES, console_callback, NULL);
+ if (res != paNoError) {
+ ast_log(LOG_WARNING, "Failed to open default audio device - (%d) %s\n",
+ res, Pa_GetErrorText(res));
+ return -1;
+ }
+
+ res = Pa_StartStream(pvt.stream);
+ if (res != paNoError) {
+ ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
+ res, Pa_GetErrorText(res));
+ return -1;
+ }
+
+ return 0;
+}
+
+/*!
+ * \note Called with console_lock locked
+ */
+static int stop_stream(void)
+{
+ if (pvt.hookstate) {
+ Pa_AbortStream(pvt.stream);
+ Pa_CloseStream(pvt.stream);
+ pvt.hookstate = 0;
+ ast_cond_signal(&pvt.cond);
+ }
+
+ return 0;
+}
+
static int unload_module(void)
{
- PaError res;
+ ast_mutex_lock(&console_lock);
+ stop_stream();
+ ast_mutex_unlock(&console_lock);
+ Pa_Terminate();
ast_channel_unregister(&console_tech);
ast_cli_unregister_multiple(cli_console, sizeof(cli_console) / sizeof(cli_console[0]));
- res = Pa_CloseStream(pvt.stream);
- if (res != paNoError) {
- ast_log(LOG_WARNING, "Failed to close default audio device - (%d) %s\n",
- res, Pa_GetErrorText(res));
- return -1;
- }
- Pa_Terminate();
-
ast_cond_destroy(&pvt.cond);
return 0;
@@ -482,6 +513,8 @@
static int load_module(void)
{
PaError res;
+
+ ast_cond_init(&pvt.cond, NULL);
res = Pa_Initialize();
if (res != paNoError) {
@@ -490,20 +523,8 @@
return AST_MODULE_LOAD_DECLINE;
}
- res = Pa_OpenDefaultStream(&pvt.stream, INPUT_CHANNELS, OUTPUT_CHANNELS,
- paInt16, SAMPLE_RATE, NUM_SAMPLES, console_callback, NULL);
- if (res != paNoError) {
- ast_log(LOG_WARNING, "Failed to open default audio device - (%d) %s\n",
- res, Pa_GetErrorText(res));
- return AST_MODULE_LOAD_DECLINE;
- }
-
- ast_cond_init(&pvt.cond, NULL);
-
if (ast_channel_register(&console_tech)) {
ast_log(LOG_ERROR, "Unable to register channel type 'Console'\n");
- Pa_CloseStream(pvt.stream);
- Pa_Terminate();
ast_cond_destroy(&pvt.cond);
return AST_MODULE_LOAD_DECLINE;
}
More information about the asterisk-commits
mailing list