[asterisk-commits] branch 1.2 r33724 - in /branches/1.2: ./ apps/ include/asterisk/

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Mon Jun 12 14:34:39 MST 2006


Author: file
Date: Mon Jun 12 16:34:38 2006
New Revision: 33724

URL: http://svn.digium.com/view/asterisk?rev=33724&view=rev
Log:
Greatly simply the mixmonitor thread, and move channel reference directly to spy structure so that the core can modify it.

Modified:
    branches/1.2/apps/app_mixmonitor.c
    branches/1.2/channel.c
    branches/1.2/include/asterisk/chanspy.h

Modified: branches/1.2/apps/app_mixmonitor.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/apps/app_mixmonitor.c?rev=33724&r1=33723&r2=33724&view=diff
==============================================================================
--- branches/1.2/apps/app_mixmonitor.c (original)
+++ branches/1.2/apps/app_mixmonitor.c Mon Jun 12 16:34:38 2006
@@ -79,12 +79,11 @@
 static const char *mixmonitor_spy_type = "MixMonitor";
 
 struct mixmonitor {
-	struct ast_channel *chan;
-	char *filename;
+	struct ast_channel_spy *spy;
+	struct ast_filestream *fs;
 	char *post_process;
+	char *name;
 	unsigned int flags;
-	int readvol;
-	int writevol;
 };
 
 enum {
@@ -110,18 +109,20 @@
 	AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
 });
 
-static void stopmon(struct ast_channel *chan, struct ast_channel_spy *spy) 
-{
+static void stopmon(struct ast_channel_spy *spy) 
+{
+	struct ast_channel *chan = spy->chan;
+
 	/* If our status has changed to DONE, then the channel we're spying on is gone....
 	   DON'T TOUCH IT!!!  RUN AWAY!!! */
 	if (spy->status == CHANSPY_DONE)
 		return;
-
+  
 	if (!chan)
 		return;
 
 	ast_mutex_lock(&chan->lock);
-	ast_channel_spy_remove(chan, spy);
+	ast_channel_spy_remove(spy->chan, spy);
 	ast_mutex_unlock(&chan->lock);
 }
 
@@ -136,7 +137,7 @@
 	ast_mutex_lock(&chan->lock);
 	res = ast_channel_spy_add(chan, spy);
 	ast_mutex_unlock(&chan->lock);
-		
+
 	if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan)))
 		ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);	
 
@@ -148,91 +149,31 @@
 static void *mixmonitor_thread(void *obj) 
 {
 	struct mixmonitor *mixmonitor = obj;
-	struct ast_channel_spy spy;
-	struct ast_filestream *fs = NULL;
-	char *ext, *name;
-	unsigned int oflags;
-	struct ast_frame *f;
-	char post_process[1024] = "";
+	struct ast_frame *f = NULL;
 	
 	STANDARD_INCREMENT_USECOUNT;
-
-	name = ast_strdupa(mixmonitor->chan->name);
-
-	oflags = O_CREAT|O_WRONLY;
-	oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
+	
+	if (option_verbose > 1)
+		ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", mixmonitor->name);
+	
+	ast_mutex_lock(&mixmonitor->spy->lock);
+
+	while (mixmonitor->spy->chan) {
+		struct ast_frame *next = NULL;
+		int write;
+
+		ast_channel_spy_trigger_wait(mixmonitor->spy);
 		
-	if ((ext = strrchr(mixmonitor->filename, '.'))) {
-		*(ext++) = '\0';
-	} else {
-		ext = "raw";
-	}
-
-	fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0644);
-	if (!fs) {
-		ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
-		goto out;
-	}
-
-	if (ast_test_flag(mixmonitor, MUXFLAG_APPEND))
-		ast_seekstream(fs, 0, SEEK_END);
-	
-	memset(&spy, 0, sizeof(spy));
-	ast_set_flag(&spy, CHANSPY_FORMAT_AUDIO);
-	ast_set_flag(&spy, CHANSPY_MIXAUDIO);
-	spy.type = mixmonitor_spy_type;
-	spy.status = CHANSPY_RUNNING;
-	spy.read_queue.format = AST_FORMAT_SLINEAR;
-	spy.write_queue.format = AST_FORMAT_SLINEAR;
-	if (mixmonitor->readvol) {
-		ast_set_flag(&spy, CHANSPY_READ_VOLADJUST);
-		spy.read_vol_adjustment = mixmonitor->readvol;
-	}
-	if (mixmonitor->writevol) {
-		ast_set_flag(&spy, CHANSPY_WRITE_VOLADJUST);
-		spy.write_vol_adjustment = mixmonitor->writevol;
-	}
-	ast_mutex_init(&spy.lock);
-
-	if (startmon(mixmonitor->chan, &spy)) {
-		ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
-			spy.type, mixmonitor->chan->name);
-		goto out2;
-	}
-
-	if (option_verbose > 1)
-		ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", name);
-	
-	if (mixmonitor->post_process) {
-		char *p;
-
-		for (p = mixmonitor->post_process; *p ; p++) {
-			if (*p == '^' && *(p+1) == '{') {
-				*p = '$';
-			}
-		}
-		pbx_substitute_variables_helper(mixmonitor->chan, mixmonitor->post_process, post_process, sizeof(post_process) - 1);
-	}
-
-	while (1) {
-		struct ast_frame *next;
-		int write;
-
-		ast_mutex_lock(&spy.lock);
-
-		ast_channel_spy_trigger_wait(&spy);
-		
-		if (ast_check_hangup(mixmonitor->chan) || spy.status != CHANSPY_RUNNING) {
-			ast_mutex_unlock(&spy.lock);
+		if (!mixmonitor->spy->chan || mixmonitor->spy->status != CHANSPY_RUNNING) {
 			break;
 		}
 		
 		while (1) {
-			if (!(f = ast_channel_spy_read_frame(&spy, SAMPLES_PER_FRAME)))
+			if (!(f = ast_channel_spy_read_frame(mixmonitor->spy, SAMPLES_PER_FRAME)))
 				break;
 
 			write = (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) ||
-				 ast_bridged_channel(mixmonitor->chan));
+				 ast_bridged_channel(mixmonitor->spy->chan));
 
 			/* it is possible for ast_channel_spy_read_frame() to return a chain
 			   of frames if a queue flush was necessary, so process them
@@ -240,32 +181,33 @@
 			for (; f; f = next) {
 				next = f->next;
 				if (write)
-					ast_writestream(fs, f);
+					ast_writestream(mixmonitor->fs, f);
 				ast_frfree(f);
 			}
 		}
-
-		ast_mutex_unlock(&spy.lock);
-	}
-	
-	stopmon(mixmonitor->chan, &spy);
+	}
+
+	ast_mutex_unlock(&mixmonitor->spy->lock);
+	
+	stopmon(mixmonitor->spy);
 
 	if (option_verbose > 1)
-		ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", name);
-
-	if (!ast_strlen_zero(post_process)) {
+		ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", mixmonitor->name);
+
+	if (!ast_strlen_zero(mixmonitor->post_process)) {
 		if (option_verbose > 2)
-			ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", post_process);
-		ast_safe_system(post_process);
-	}
-
-out2:
-	ast_mutex_destroy(&spy.lock);
-
-	if (fs)
-		ast_closestream(fs);
-
-out:
+			ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", mixmonitor->post_process);
+		ast_safe_system(mixmonitor->post_process);
+	}
+
+	ast_mutex_destroy(&mixmonitor->spy->lock);
+		
+	ast_closestream(mixmonitor->fs);
+
+	/* Deallocate everything */
+	free(mixmonitor->spy);
+	free(mixmonitor->post_process);
+	free(mixmonitor->name);
 	free(mixmonitor);
 
 	STANDARD_DECREMENT_USECOUNT;
@@ -279,32 +221,93 @@
 	pthread_attr_t attr;
 	pthread_t thread;
 	struct mixmonitor *mixmonitor;
-	int len;
-
-	len = sizeof(*mixmonitor) + strlen(filename) + 1;
-	if (!ast_strlen_zero(post_process))
-		len += strlen(post_process) + 1;
-
-	if (!(mixmonitor = calloc(1, len))) {
+	char *file_name, *postprocess, *ext, postprocess2[1024] = "";
+	unsigned int oflags;
+
+	/* Pre-allocate mixmonitor structure and spy */
+	if (!(mixmonitor = calloc(1, sizeof(*mixmonitor)))) {
 		ast_log(LOG_ERROR, "Memory Error!\n");
 		return;
 	}
 
-	mixmonitor->chan = chan;
-	mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor);
-	strcpy(mixmonitor->filename, filename);
+	if (!(mixmonitor->spy = calloc(1, sizeof(*mixmonitor->spy)))) {
+                ast_log(LOG_ERROR, "Memory Error!\n");
+		free(mixmonitor);
+                return;
+        }
+
+	/* Copy over flags and channel name */
+	mixmonitor->flags = flags;
+	mixmonitor->name = strdup(chan->name);
+
+	/* Determine creation flags and filename plus extension for filestream */
+	oflags = O_CREAT | O_WRONLY;
+	oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
+	file_name = ast_strdupa(filename);
+	if ((ext = strrchr(file_name, '.'))) {
+		*(ext++) = '\0';
+	} else {
+		ext = "raw";
+	}
+
+	/* Move onto actually creating the filestream */
+	mixmonitor->fs = ast_writefile(file_name, ext, NULL, oflags, 0, 0644);
+	if (!mixmonitor->fs) {
+		ast_log(LOG_ERROR, "Cannot open %s.%s\n", file_name, ext);
+		free(mixmonitor->name);
+		free(mixmonitor->spy);
+		free(mixmonitor);
+		return;
+	}
+
+	/* If a post process system command is given attach it to the structure */
 	if (!ast_strlen_zero(post_process)) {
-		mixmonitor->post_process = mixmonitor->filename + strlen(filename) + 1;
-		strcpy(mixmonitor->post_process, post_process);
-	}
-	mixmonitor->readvol = readvol;
-	mixmonitor->writevol = writevol;
-	mixmonitor->flags = flags;
+		char *p = NULL;
+		postprocess = ast_strdupa(post_process);
+		for (p = postprocess; *p ; p++) {
+			if (*p == '^' && *(p+1) == '{') {
+				*p = '$';
+			}
+		}
+		pbx_substitute_variables_helper(chan, postprocess, postprocess2, sizeof(postprocess2) - 1);
+		mixmonitor->post_process = strdup(postprocess2);
+	}
+
+	/* Setup the actual spy before creating our thread */
+	ast_set_flag(mixmonitor->spy, CHANSPY_FORMAT_AUDIO);
+	ast_set_flag(mixmonitor->spy, CHANSPY_MIXAUDIO);
+	mixmonitor->spy->type = mixmonitor_spy_type;
+	mixmonitor->spy->status = CHANSPY_RUNNING;
+	mixmonitor->spy->read_queue.format = AST_FORMAT_SLINEAR;
+	mixmonitor->spy->write_queue.format = AST_FORMAT_SLINEAR;
+	if (readvol) {
+		ast_set_flag(mixmonitor->spy, CHANSPY_READ_VOLADJUST);
+		mixmonitor->spy->read_vol_adjustment = readvol;
+	}
+	if (writevol) {
+		ast_set_flag(mixmonitor->spy, CHANSPY_WRITE_VOLADJUST);
+		mixmonitor->spy->write_vol_adjustment = writevol;
+	}
+	ast_mutex_init(&mixmonitor->spy->lock);
+
+	if (startmon(chan, mixmonitor->spy)) {
+		ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
+			mixmonitor->spy->type, chan->name);
+		/* Since we couldn't add ourselves - bail out! */
+		ast_mutex_destroy(&mixmonitor->spy->lock);
+		free(mixmonitor->post_process);
+		ast_closestream(mixmonitor->fs);
+		free(mixmonitor->name);
+		free(mixmonitor->spy);
+		free(mixmonitor);
+		return;
+	}
 
 	pthread_attr_init(&attr);
 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 	ast_pthread_create(&thread, &attr, mixmonitor_thread, mixmonitor);
 	pthread_attr_destroy(&attr);
+
 }
 
 static int mixmonitor_exec(struct ast_channel *chan, void *data)

Modified: branches/1.2/channel.c
URL: http://svn.digium.com/view/asterisk/branches/1.2/channel.c?rev=33724&r1=33723&r2=33724&view=diff
==============================================================================
--- branches/1.2/channel.c (original)
+++ branches/1.2/channel.c Mon Jun 12 16:34:38 2006
@@ -964,6 +964,9 @@
 
 int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy)
 {
+	/* Link the owner channel to the spy */
+	spy->chan = chan;
+
 	if (!ast_test_flag(spy, CHANSPY_FORMAT_AUDIO)) {
 		ast_log(LOG_WARNING, "Could not add channel spy '%s' to channel '%s', only audio format spies are supported.\n",
 			spy->type, chan->name);
@@ -1034,7 +1037,14 @@
 
 void ast_channel_spy_trigger_wait(struct ast_channel_spy *spy)
 {
-	ast_cond_wait(&spy->trigger, &spy->lock);
+	struct timeval tv;
+	struct timespec ts;
+
+	tv = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000));
+	ts.tv_sec = tv.tv_sec;
+	ts.tv_nsec = tv.tv_usec * 1000;
+
+	ast_cond_timedwait(&spy->trigger, &spy->lock, &ts);
 }
 
 void ast_channel_spy_remove(struct ast_channel *chan, struct ast_channel_spy *spy)
@@ -1047,6 +1057,8 @@
 	AST_LIST_REMOVE(&chan->spies->list, spy, list);
 
 	ast_mutex_lock(&spy->lock);
+
+	spy->chan = NULL;
 
 	for (f = spy->read_queue.head; f; f = spy->read_queue.head) {
 		spy->read_queue.head = f->next;
@@ -1085,6 +1097,7 @@
 	/* Marking the spies as done is sufficient.  Chanspy or spy users will get the picture. */
 	AST_LIST_TRAVERSE(&chan->spies->list, spy, list) {
 		ast_mutex_lock(&spy->lock);
+		spy->chan = NULL;
 		if (spy->status == CHANSPY_RUNNING)
 			spy->status = CHANSPY_DONE;
 		if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE)

Modified: branches/1.2/include/asterisk/chanspy.h
URL: http://svn.digium.com/view/asterisk/branches/1.2/include/asterisk/chanspy.h?rev=33724&r1=33723&r2=33724&view=diff
==============================================================================
--- branches/1.2/include/asterisk/chanspy.h (original)
+++ branches/1.2/include/asterisk/chanspy.h Mon Jun 12 16:34:38 2006
@@ -58,6 +58,7 @@
 	AST_LIST_ENTRY(ast_channel_spy) list;
 	ast_mutex_t lock;
 	ast_cond_t trigger;
+	struct ast_channel *chan;
 	struct ast_channel_spy_queue read_queue;
 	struct ast_channel_spy_queue write_queue;
 	unsigned int flags;



More information about the asterisk-commits mailing list