You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3195 lines
92 KiB
3195 lines
92 KiB
This patch is derived from the difference between appconference-2.0.1 |
|
from http://appconference.sourceforge.net/ and the version included in |
|
http://download.fedora.redhat.com/pub/fedora/linux/development/source/SRPMS/asterisk-1.6.0-0.4.beta5.fc9.src.rpm |
|
|
|
Index: Flags.txt |
|
--- Flags.txt.orig 2008-02-26 17:05:57 +0100 |
|
+++ Flags.txt 2008-03-19 09:18:57 +0100 |
|
@@ -21,6 +21,10 @@ |
|
Moderator/video switch options: |
|
'M' : member is a "moderator". When a moderator quits, all members are kicked and the conference is disabled. |
|
'S' : member accepts VAD controlled video switching. Do not use with 'X'. |
|
+'z' : member can "linger". When the member is currently transmitting video and becomes silent and nobody else is speaking, we stay on it. |
|
+'o' : enable special behavior when in 1 and 2 member situation (one on one video). The conference observes the 'o' status of the last |
|
+ member to join it |
|
+'F' : force switch mode: if the member is talking, force a switch to it even when there is no video |
|
|
|
Miscellaneous: |
|
't' : member accepts text based control messages. The messages are described in a separate document |
|
Index: Makefile |
|
--- Makefile.orig 2008-02-26 17:05:57 +0100 |
|
+++ Makefile 2008-03-19 09:18:57 +0100 |
|
@@ -18,11 +18,11 @@ |
|
# |
|
|
|
INSTALL_PREFIX := |
|
-INSTALL_MODULES_DIR := $(INSTALL_PREFIX)/usr/lib/asterisk/modules |
|
+INSTALL_MODULES_DIR := $(INSTALL_PREFIX)/lib/asterisk/modules |
|
|
|
-ASTERISK_INCLUDE_DIR ?= ../asterisk/include |
|
+ASTERISK_INCLUDE_DIR ?= $(INSTALL_PREFIX)/include |
|
|
|
-REVISION = $(shell svnversion -n .) |
|
+REVISION = 2.0.1 |
|
|
|
# turn app_conference debugging on or off ( 0 == OFF, 1 == ON ) |
|
APP_CONFERENCE_DEBUG ?= 0 |
|
Index: app_conference.c |
|
--- app_conference.c.orig 2008-02-26 17:05:57 +0100 |
|
+++ app_conference.c 2008-03-19 09:18:57 +0100 |
|
@@ -27,14 +27,7 @@ |
|
|
|
#include "asterisk.h" |
|
|
|
-// SVN revision number, provided by make |
|
-#ifndef REVISION |
|
-#define REVISION "unknown" |
|
-#endif |
|
- |
|
-static char *revision = REVISION; |
|
- |
|
-ASTERISK_FILE_VERSION(__FILE__, REVISION) |
|
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.1 $") |
|
|
|
#include "app_conference.h" |
|
#include "common.h" |
|
@@ -84,7 +77,7 @@ |
|
|
|
static int load_module( void ) |
|
{ |
|
- ast_log( LOG_NOTICE, "Loading app_conference module, revision=%s\n", revision) ; |
|
+ ast_log( LOG_NOTICE, "Loading app_conference module\n") ; |
|
|
|
init_conference() ; |
|
|
|
Index: app_conference.h |
|
--- app_conference.h.orig 2008-02-26 17:05:57 +0100 |
|
+++ app_conference.h 2008-03-19 09:18:57 +0100 |
|
@@ -31,6 +31,7 @@ |
|
#ifndef _ASTERISK_CONF_H |
|
#define _ASTERISK_CONF_H |
|
|
|
+#include "asterisk.h" |
|
|
|
/* standard includes */ |
|
#include <stdlib.h> |
|
@@ -40,27 +41,27 @@ |
|
#include <math.h> |
|
#include <stdio.h> |
|
|
|
- |
|
#include <pthread.h> |
|
|
|
/* asterisk includes */ |
|
-#include <asterisk/utils.h> |
|
-#include <asterisk/pbx.h> |
|
-#include <asterisk/module.h> |
|
-#include <asterisk/logger.h> |
|
-#include <asterisk/lock.h> |
|
-#include <asterisk/frame.h> |
|
-#include <asterisk/manager.h> |
|
-#include <asterisk/dsp.h> |
|
-#include <asterisk/translate.h> |
|
-#include <asterisk/channel.h> |
|
-#include <asterisk/file.h> |
|
-//#include <asterisk/channel_pvt.h> |
|
-#include <asterisk/cli.h> |
|
+#include "asterisk/channel.h" |
|
+#include "asterisk/utils.h" |
|
+#include "asterisk/pbx.h" |
|
+#include "asterisk/module.h" |
|
+#include "asterisk/logger.h" |
|
+#include "asterisk/lock.h" |
|
+#include "asterisk/frame.h" |
|
+#include "asterisk/manager.h" |
|
+#include "asterisk/dsp.h" |
|
+#include "asterisk/translate.h" |
|
+#include "asterisk/channel.h" |
|
+#include "asterisk/file.h" |
|
+//#include "asterisk/channel_pvt.h" |
|
+#include "asterisk/cli.h" |
|
|
|
|
|
#if (SILDET == 2) |
|
-#include "libspeex/speex_preprocess.h" |
|
+#include "speex_preprocess.h" |
|
#endif |
|
|
|
// |
|
@@ -226,6 +227,10 @@ |
|
// Amount of audio required before we decide somebody started talking |
|
#define AST_CONF_VIDEO_START_TIMEOUT 2000 |
|
|
|
+// Amount of time we wait for a video frame until we decide that |
|
+// the member has stopped broadcasting video |
|
+#define AST_CONF_VIDEO_STOP_BROADCAST_TIMEOUT 200 |
|
+ |
|
// |
|
// Text frame control protocol |
|
// |
|
Index: cli.c |
|
--- cli.c.orig 2008-02-26 17:05:57 +0100 |
|
+++ cli.c 2008-03-19 09:27:50 +0100 |
|
@@ -28,125 +28,121 @@ |
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
*/ |
|
|
|
-#include "asterisk/autoconfig.h" |
|
-#include "cli.h" |
|
+#include "asterisk.h" |
|
|
|
-static char conference_restart_usage[] = |
|
- "usage: conference restart\n" |
|
- " kick all users in all conferences\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_restart = { |
|
- { "conference", "restart", NULL }, |
|
- conference_restart, |
|
- "restart a conference", |
|
- conference_restart_usage |
|
-} ; |
|
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.1 $") |
|
|
|
+#include "asterisk/autoconfig.h" |
|
+#include "cli.h" |
|
|
|
-int conference_restart( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
- if ( argc < 2 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference restart"; |
|
+ e->usage = "usage: conference restart\n" |
|
+ " restart a conference\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
|
|
+ if ( a->argc < 2 ) |
|
+ return CLI_SHOWUSAGE; |
|
+ |
|
kick_all(); |
|
- return RESULT_SUCCESS ; |
|
+ |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
+static char *handle_cli_app_conference_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
+{ |
|
|
|
-// |
|
-// debug functions |
|
-// |
|
- |
|
-static char conference_debug_usage[] = |
|
- "usage: conference debug <conference_name> [ on | off ]\n" |
|
- " enable debugging for a conference\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_debug = { |
|
- { "conference", "debug", NULL }, |
|
- conference_debug, |
|
- "enable debugging for a conference", |
|
- conference_debug_usage |
|
-} ; |
|
- |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference debug"; |
|
+ e->usage = "usage: conference debug <conference_name> [ on | off ]\n" |
|
+ " enable debugging for a conference\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
|
|
-int conference_debug( int fd, int argc, char *argv[] ) |
|
-{ |
|
- if ( argc < 3 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ if ( a->argc < 3) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
// get the conference name |
|
- const char* name = argv[2] ; |
|
+ const char* name = a->argv[2] ; |
|
|
|
// get the new state |
|
int state = 0 ; |
|
|
|
- if ( argc == 3 ) |
|
+ if ( a->argc == 3 ) |
|
{ |
|
// no state specified, so toggle it |
|
state = -1 ; |
|
} |
|
else |
|
{ |
|
- if ( strncasecmp( argv[3], "on", 4 ) == 0 ) |
|
+ if ( strncasecmp( a->argv[3], "on", 4 ) == 0 ) |
|
state = 1 ; |
|
- else if ( strncasecmp( argv[3], "off", 3 ) == 0 ) |
|
+ else if ( strncasecmp( a->argv[3], "off", 3 ) == 0 ) |
|
state = 0 ; |
|
else |
|
- return RESULT_SHOWUSAGE ; |
|
+ return CLI_SHOWUSAGE ; |
|
} |
|
|
|
int new_state = set_conference_debugging( name, state ) ; |
|
|
|
if ( new_state == 1 ) |
|
{ |
|
- ast_cli( fd, "enabled conference debugging, name => %s, new_state => %d\n", |
|
- name, new_state ) ; |
|
+ ast_cli( a->fd, "enabled conference debugging, name => %s, new_state => %d\n", |
|
+ name, new_state ) ; |
|
} |
|
else if ( new_state == 0 ) |
|
{ |
|
- ast_cli( fd, "disabled conference debugging, name => %s, new_state => %d\n", |
|
+ ast_cli( a->fd, "disabled conference debugging, name => %s, new_state => %d\n", |
|
name, new_state ) ; |
|
} |
|
else |
|
{ |
|
// error setting state |
|
- ast_cli( fd, "\nunable to set debugging state, name => %s\n\n", name ) ; |
|
+ ast_cli( a->fd, "\nunable to set debugging state, name => %s\n\n", name ) ; |
|
} |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-// |
|
-// stats functions |
|
-// |
|
- |
|
-static char conference_show_stats_usage[] = |
|
- "usage: conference show stats\n" |
|
- " display stats for active conferences.\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_show_stats = { |
|
- { "conference", "show", "stats", NULL }, |
|
- conference_show_stats, |
|
- "show conference stats", |
|
- conference_show_stats_usage |
|
-} ; |
|
+static char *conference_show_stats_name( int fd, const char* name ) |
|
+{ |
|
+ // not implemented yet |
|
+ return CLI_SUCCESS ; |
|
+} |
|
|
|
-int conference_show_stats( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
- if ( argc < 3 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference show stats"; |
|
+ e->usage = "usage: conference show stats\n" |
|
+ " display stats for active conferences.\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
+ if ( a->argc < 3 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
// get count of active conferences |
|
int count = get_conference_count() ; |
|
|
|
- ast_cli( fd, "\n\nCONFERENCE STATS, ACTIVE( %d )\n\n", count ) ; |
|
+ ast_cli( a->fd, "\n\nCONFERENCE STATS, ACTIVE( %d )\n\n", count ) ; |
|
|
|
// if zero, go no further |
|
if ( count <= 0 ) |
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
|
|
// |
|
// get the conference stats |
|
@@ -161,8 +157,8 @@ |
|
// make sure we were able to fetch some |
|
if ( count <= 0 ) |
|
{ |
|
- ast_cli( fd, "!!! error fetching conference stats, available => %d !!!\n", count ) ; |
|
- return RESULT_SUCCESS ; |
|
+ ast_cli( a->fd, "!!! error fetching conference stats, available => %d !!!\n", count ) ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
// |
|
@@ -170,8 +166,8 @@ |
|
// |
|
|
|
// output header |
|
- ast_cli( fd, "%-20.20s %-40.40s\n", "Name", "Stats") ; |
|
- ast_cli( fd, "%-20.20s %-40.40s\n", "----", "-----") ; |
|
+ ast_cli( a->fd, "%-20.20s %-40.40s\n", "Name", "Stats") ; |
|
+ ast_cli( a->fd, "%-20.20s %-40.40s\n", "----", "-----") ; |
|
|
|
ast_conference_stats* s = NULL ; |
|
|
|
@@ -182,1008 +178,931 @@ |
|
s = &(stats[i]) ; |
|
|
|
// output this conferences stats |
|
- ast_cli( fd, "%-20.20s\n", (char*)( &(s->name) )) ; |
|
+ ast_cli( a->fd, "%-20.20s\n", (char*)( &(s->name) )) ; |
|
} |
|
|
|
- ast_cli( fd, "\n" ) ; |
|
+ ast_cli( a->fd, "\n" ) ; |
|
|
|
// |
|
// drill down to specific stats |
|
// |
|
|
|
- if ( argc == 4 ) |
|
+ if ( a->argc == 4 ) |
|
{ |
|
// show stats for a particular conference |
|
- conference_show_stats_name( fd, argv[3] ) ; |
|
+ conference_show_stats_name( a->fd, a->argv[3] ) ; |
|
} |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-int conference_show_stats_name( int fd, const char* name ) |
|
+static char *handle_cli_app_conference_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
- // not implemented yet |
|
- return RESULT_SUCCESS ; |
|
-} |
|
- |
|
-static char conference_list_usage[] = |
|
- "usage: conference list {<conference_name>}\n" |
|
- " list members of a conference\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_list = { |
|
- { "conference", "list", NULL }, |
|
- conference_list, |
|
- "list members of a conference", |
|
- conference_list_usage |
|
-} ; |
|
- |
|
- |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference list"; |
|
+ e->usage = "usage: conference list {<conference_name>}\n" |
|
+ " list members of a conference\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
|
|
-int conference_list( int fd, int argc, char *argv[] ) |
|
-{ |
|
int index; |
|
|
|
- if ( argc < 2 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ if ( a->argc < 2 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
- if (argc >= 3) |
|
+ if (a->argc >= 3) |
|
{ |
|
- for (index = 2; index < argc; index++) |
|
+ for (index = 2; index < a->argc; index++) |
|
{ |
|
// get the conference name |
|
- const char* name = argv[index] ; |
|
- show_conference_list( fd, name ); |
|
+ const char* name = a->argv[index] ; |
|
+ show_conference_list( a->fd, name ); |
|
} |
|
} |
|
else |
|
{ |
|
- show_conference_stats(fd); |
|
+ show_conference_stats(a->fd); |
|
} |
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
|
|
-int conference_kick( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference kick"; |
|
+ e->usage = "usage: conference kick <conference> <member id>\n" |
|
+ " kick member <member id> from conference <conference>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
// get the conference name |
|
- const char* name = argv[2] ; |
|
+ const char* name = a->argv[2] ; |
|
|
|
int member_id; |
|
- sscanf(argv[3], "%d", &member_id); |
|
+ sscanf(a->argv[3], "%d", &member_id); |
|
|
|
int res = kick_member( name, member_id ); |
|
|
|
- if (res) ast_cli( fd, "User #: %d kicked\n", member_id) ; |
|
+ if (res) ast_cli( a->fd, "User #: %d kicked\n", member_id) ; |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-static char conference_kick_usage[] = |
|
- "usage: conference kick <conference> <member id>\n" |
|
- " kick member <member id> from conference <conference>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_kick = { |
|
- { "conference", "kick", NULL }, |
|
- conference_kick, |
|
- "kick member from a conference", |
|
- conference_kick_usage |
|
-} ; |
|
- |
|
-int conference_kickchannel( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_kickchannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference kickchannel"; |
|
+ e->usage = "usage: conference kickchannel <conference_name> <channel>\n" |
|
+ " kick channel from conference\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
- const char *name = argv[2] ; |
|
- const char *channel = argv[3]; |
|
+ const char *name = a->argv[2] ; |
|
+ const char *channel = a->argv[3]; |
|
|
|
int res = kick_channel( name, channel ); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli( fd, "Cannot kick channel %s in conference %s\n", channel, name); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Cannot kick channel %s in conference %s\n", channel, name); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-static char conference_kickchannel_usage[] = |
|
- "usage: conference kickchannel <conference_name> <channel>\n" |
|
- " kick channel from conference\n" |
|
-; |
|
+static char *handle_cli_app_conference_exit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
+{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference exit"; |
|
+ e->usage = "usage: conference exit <channel>\n" |
|
+ " exit channel from any conference where it in\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
+ if ( a->argc < 3 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
-static struct ast_cli_entry cli_kickchannel = { |
|
- { "conference", "kickchannel", NULL }, |
|
- conference_kickchannel, |
|
- "kick channel from conference", |
|
- conference_kickchannel_usage |
|
-} ; |
|
+ const char *channel = a->argv[2]; |
|
+ |
|
+ struct ast_conf_member *member = find_member(channel, 1); |
|
+ if(!member) |
|
+ { |
|
+ ast_cli( a->fd, "Member %s not found\n", channel); |
|
+ return CLI_FAILURE; |
|
+ } |
|
+ const char * name = member->conf_name; |
|
+ int res = kick_channel( name, channel ); |
|
+ |
|
+ if ( !res ) |
|
+ { |
|
+ ast_cli( a->fd, "Cannot exit channel %s from conference %s\n", channel, name); |
|
+ ast_mutex_unlock(&member->lock); |
|
+ return CLI_FAILURE; |
|
+ } |
|
|
|
-int conference_mute( int fd, int argc, char *argv[] ) |
|
+ ast_mutex_unlock( &member->lock ) ; |
|
+ return CLI_SUCCESS ; |
|
+} |
|
+ |
|
+static char *handle_cli_app_conference_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference mute"; |
|
+ e->usage = "usage: conference mute <conference_name> <member id>\n" |
|
+ " mute member in a conference\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
// get the conference name |
|
- const char* name = argv[2] ; |
|
+ const char* name = a->argv[2] ; |
|
|
|
int member_id; |
|
- sscanf(argv[3], "%d", &member_id); |
|
+ sscanf(a->argv[3], "%d", &member_id); |
|
|
|
int res = mute_member( name, member_id ); |
|
|
|
- if (res) ast_cli( fd, "User #: %d muted\n", member_id) ; |
|
+ if (res) ast_cli( a->fd, "User #: %d muted\n", member_id) ; |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-static char conference_mute_usage[] = |
|
- "usage: conference mute <conference_name> <member id>\n" |
|
- " mute member in a conference\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_mute = { |
|
- { "conference", "mute", NULL }, |
|
- conference_mute, |
|
- "mute member in a conference", |
|
- conference_mute_usage |
|
-} ; |
|
- |
|
-int conference_mutechannel( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_mutechannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference mutechannel"; |
|
+ e->usage = "usage: conference mutechannel <channel>\n" |
|
+ " mute channel in a conference\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
struct ast_conf_member *member; |
|
char *channel; |
|
|
|
- if ( argc < 3 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ if ( a->argc < 3 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
- channel = argv[2]; |
|
+ channel = a->argv[2]; |
|
|
|
member = find_member(channel, 1); |
|
if(!member) { |
|
- ast_cli(fd, "Member %s not found\n", channel); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Member %s not found\n", channel); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
member->mute_audio = 1; |
|
ast_mutex_unlock( &member->lock ) ; |
|
|
|
- ast_cli( fd, "Channel #: %s muted\n", argv[2]) ; |
|
+ ast_cli( a->fd, "Channel #: %s muted\n", a->argv[2]) ; |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-static char conference_mutechannel_usage[] = |
|
- "usage: conference mutechannel <channel>\n" |
|
- " mute channel in a conference\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_mutechannel = { |
|
- { "conference", "mutechannel", NULL }, |
|
- conference_mutechannel, |
|
- "mute channel in a conference", |
|
- conference_mutechannel_usage |
|
-} ; |
|
- |
|
-int conference_viewstream( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_viewstream(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference viewstream"; |
|
+ e->usage = "usage: conference viewstream <conference_name> <member id> <stream no>\n" |
|
+ " member <member id> will receive video stream <stream no>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
int res; |
|
|
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
// get the conference name |
|
- const char* switch_name = argv[2] ; |
|
+ const char* switch_name = a->argv[2] ; |
|
|
|
int member_id, viewstream_id; |
|
- sscanf(argv[3], "%d", &member_id); |
|
- sscanf(argv[4], "%d", &viewstream_id); |
|
+ sscanf(a->argv[3], "%d", &member_id); |
|
+ sscanf(a->argv[4], "%d", &viewstream_id); |
|
|
|
res = viewstream_switch( switch_name, member_id, viewstream_id ); |
|
|
|
- if (res) ast_cli( fd, "User #: %d viewing %d\n", member_id, viewstream_id) ; |
|
+ if (res) ast_cli( a->fd, "User #: %d viewing %d\n", member_id, viewstream_id) ; |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-static char conference_viewstream_usage[] = |
|
- "usage: conference viewstream <conference_name> <member id> <stream no>\n" |
|
- " member <member id> will receive video stream <stream no>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_viewstream = { |
|
- { "conference", "viewstream", NULL }, |
|
- conference_viewstream, |
|
- "switch view in a conference", |
|
- conference_viewstream_usage |
|
-} ; |
|
- |
|
-int conference_viewchannel( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_viewchannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference viewchannel"; |
|
+ e->usage = "usage: conference viewchannel <conference_name> <dest channel> <src channel>\n" |
|
+ " channel <dest channel> will receive video stream <src channel>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
int res; |
|
|
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
// get the conference name |
|
- const char* switch_name = argv[2] ; |
|
+ const char* switch_name = a->argv[2] ; |
|
|
|
- res = viewchannel_switch( switch_name, argv[3], argv[4] ); |
|
+ res = viewchannel_switch( switch_name, a->argv[3], a->argv[4] ); |
|
|
|
- if (res) ast_cli( fd, "Channel #: %s viewing %s\n", argv[3], argv[4]) ; |
|
+ if (res) ast_cli( a->fd, "Channel #: %s viewing %s\n", a->argv[3], a->argv[4]) ; |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-static char conference_viewchannel_usage[] = |
|
- "usage: conference viewchannel <conference_name> <dest channel> <src channel>\n" |
|
- " channel <dest channel> will receive video stream <src channel>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_viewchannel = { |
|
- { "conference", "viewchannel", NULL }, |
|
- conference_viewchannel, |
|
- "switch channel in a conference", |
|
- conference_viewchannel_usage |
|
-} ; |
|
- |
|
-int conference_unmute( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_unmute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference unmute"; |
|
+ e->usage = "usage: conference unmute <conference_name> <member id>\n" |
|
+ " unmute member in a conference\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
// get the conference name |
|
- const char* name = argv[2] ; |
|
+ const char* name = a->argv[2] ; |
|
|
|
int member_id; |
|
- sscanf(argv[3], "%d", &member_id); |
|
+ sscanf(a->argv[3], "%d", &member_id); |
|
|
|
int res = unmute_member( name, member_id ); |
|
|
|
- if (res) ast_cli( fd, "User #: %d unmuted\n", member_id) ; |
|
+ if (res) ast_cli( a->fd, "User #: %d unmuted\n", member_id) ; |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-static char conference_unmute_usage[] = |
|
- "usage: conference unmute <conference_name> <member id>\n" |
|
- " unmute member in a conference\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_unmute = { |
|
- { "conference", "unmute", NULL }, |
|
- conference_unmute, |
|
- "unmute member in a conference", |
|
- conference_unmute_usage |
|
-} ; |
|
- |
|
-int conference_unmutechannel( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_unmutechannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference unmutechannel"; |
|
+ e->usage = "usage: conference unmutechannel <channel>\n" |
|
+ " unmute channel in a conference\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
struct ast_conf_member *member; |
|
char *channel; |
|
|
|
- if ( argc < 3 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ if ( a->argc < 3 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
- channel = argv[2]; |
|
+ channel = a->argv[2]; |
|
|
|
member = find_member(channel, 1); |
|
if(!member) { |
|
- ast_cli(fd, "Member %s not found\n", channel); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Member %s not found\n", channel); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
member->mute_audio = 0; |
|
ast_mutex_unlock( &member->lock ) ; |
|
|
|
- ast_cli( fd, "Channel #: %s unmuted\n", argv[2]) ; |
|
+ ast_cli( a->fd, "Channel #: %s unmuted\n", a->argv[2]) ; |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-static char conference_unmutechannel_usage[] = |
|
- "usage: conference unmutechannel <channel>\n" |
|
- " unmute channel in a conference\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_unmutechannel = { |
|
- { "conference", "unmutechannel", NULL }, |
|
- conference_unmutechannel, |
|
- "unmute channel in a conference", |
|
- conference_unmutechannel_usage |
|
-} ; |
|
- |
|
-// |
|
-// play sound |
|
-// |
|
-static char conference_play_sound_usage[] = |
|
- "usage: conference play sound <channel-id> <sound-file> [mute]\n" |
|
- " play sound <sound-file> to conference member <channel-id>.\n" |
|
- " If mute is specified, all other audio is muted while the sound is played back.\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_play_sound = { |
|
- { "conference", "play", "sound", NULL }, |
|
- conference_play_sound, |
|
- "play a sound to a conference member", |
|
- conference_play_sound_usage |
|
-} ; |
|
- |
|
-int conference_play_sound( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_play_sound(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference play sound"; |
|
+ e->usage = "usage: conference play sound <channel-id> <sound-file> [mute]\n" |
|
+ " play sound <sound-file> to conference member <channel-id>.\n" |
|
+ " If mute is specified, all other audio is muted while the sound is played back.\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
char *channel, *file; |
|
int mute = 0; |
|
|
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
- channel = argv[3]; |
|
- file = argv[4]; |
|
+ channel = a->argv[3]; |
|
+ file = a->argv[4]; |
|
|
|
- if(argc > 5 && !strcmp(argv[5], "mute")) |
|
+ if(a->argc > 5 && !strcmp(a->argv[5], "mute")) |
|
mute = 1; |
|
|
|
- int res = play_sound_channel(fd, channel, file, mute); |
|
+ int res = play_sound_channel(a->fd, channel, file, mute); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Sound playback failed failed\n"); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Sound playback failed failed\n"); |
|
+ return CLI_FAILURE; |
|
} |
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-// |
|
-// stop sounds |
|
-// |
|
- |
|
-static char conference_stop_sounds_usage[] = |
|
- "usage: conference stop sounds <channel-id>\n" |
|
- " stop sounds for conference member <channel-id>.\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_stop_sounds = { |
|
- { "conference", "stop", "sounds", NULL }, |
|
- conference_stop_sounds, |
|
- "stop sounds for a conference member", |
|
- conference_stop_sounds_usage |
|
-} ; |
|
- |
|
-int conference_stop_sounds( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_stop_sounds(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference play sound"; |
|
+ e->usage = "usage: conference stop sounds <channel-id>\n" |
|
+ " stop sounds for conference member <channel-id>.\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
char *channel; |
|
|
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
- channel = argv[3]; |
|
+ channel = a->argv[3]; |
|
|
|
- int res = stop_sound_channel(fd, channel); |
|
+ int res = stop_sound_channel( a->fd, channel); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Sound stop failed failed\n"); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Sound stop failed failed\n"); |
|
+ return CLI_FAILURE; |
|
} |
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-// |
|
-// end conference |
|
-// |
|
- |
|
-static char conference_end_usage[] = |
|
- "usage: conference end <conference name>\n" |
|
- " ends a conference.\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_end = { |
|
- { "conference", "end", NULL }, |
|
- conference_end, |
|
- "stops a conference", |
|
- conference_end_usage |
|
-} ; |
|
- |
|
-int conference_end( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_end(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference end"; |
|
+ e->usage = "usage: conference end <conference name>\n" |
|
+ " ends a conference.\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check the args length |
|
- if ( argc < 3 ) |
|
- return RESULT_SHOWUSAGE ; |
|
+ if ( a->argc < 3 ) |
|
+ return CLI_SHOWUSAGE ; |
|
|
|
// conference name |
|
- const char* name = argv[2] ; |
|
+ const char* name = a->argv[2] ; |
|
|
|
// get the conference |
|
if ( end_conference( name, 1 ) != 0 ) |
|
{ |
|
- ast_cli( fd, "unable to end the conference, name => %s\n", name ) ; |
|
- return RESULT_SHOWUSAGE ; |
|
+ ast_cli( a->fd, "unable to end the conference, name => %s\n", name ) ; |
|
+ return CLI_SHOWUSAGE ; |
|
} |
|
|
|
- return RESULT_SUCCESS ; |
|
+ return CLI_SUCCESS ; |
|
} |
|
|
|
-// |
|
-// E.BUU - Manager conference end. Additional option to just kick everybody out |
|
-// without hangin up channels |
|
-// |
|
-int manager_conference_end(struct mansession *s, const struct message *m) |
|
+static char *handle_cli_app_conference_lock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
- const char *confname = astman_get_header(m,"Conference"); |
|
- int hangup = 1; |
|
- |
|
- const char * h = astman_get_header(m, "Hangup"); |
|
- if (h) |
|
- { |
|
- hangup = atoi(h); |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference lock"; |
|
+ e->usage = "usage: conference lock <conference name> <member id>\n" |
|
+ " locks incoming video stream for conference <conference name> to member <member id>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
} |
|
|
|
- ast_log( LOG_NOTICE, "Terminating conference %s on manager's request. Hangup: %s.\n", confname, hangup?"YES":"NO" ); |
|
- if ( end_conference( confname, hangup ) != 0 ) |
|
- { |
|
- ast_log( LOG_ERROR, "manager end conf: unable to terminate conference %s.\n", confname ); |
|
- astman_send_error(s, m, "Failed to terminate\r\n"); |
|
- return RESULT_FAILURE; |
|
- } |
|
- |
|
- astman_send_ack(s, m, "Conference terminated"); |
|
- return RESULT_SUCCESS; |
|
-} |
|
-// |
|
-// lock conference to a video source |
|
-// |
|
-static char conference_lock_usage[] = |
|
- "usage: conference lock <conference name> <member id>\n" |
|
- " locks incoming video stream for conference <conference name> to member <member id>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_lock = { |
|
- { "conference", "lock", NULL }, |
|
- conference_lock, |
|
- "locks incoming video to a member", |
|
- conference_lock_usage |
|
-} ; |
|
- |
|
-int conference_lock( int fd, int argc, char *argv[] ) |
|
-{ |
|
// check args |
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[2]; |
|
+ const char *conference = a->argv[2]; |
|
int member; |
|
- sscanf(argv[3], "%d", &member); |
|
+ sscanf(a->argv[3], "%d", &member); |
|
|
|
int res = lock_conference(conference, member); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Locking failed\n"); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Locking failed\n"); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// lock conference to a video source channel |
|
-// |
|
-static char conference_lockchannel_usage[] = |
|
- "usage: conference lockchannel <conference name> <channel>\n" |
|
- " locks incoming video stream for conference <conference name> to channel <channel>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_lockchannel = { |
|
- { "conference", "lockchannel", NULL }, |
|
- conference_lockchannel, |
|
- "locks incoming video to a channel", |
|
- conference_lockchannel_usage |
|
-} ; |
|
- |
|
-int conference_lockchannel( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_lockchannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference lockchannel"; |
|
+ e->usage = "usage: conference lockchannel <conference name> <channel>\n" |
|
+ " locks incoming video stream for conference <conference name> to channel <channel>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[2]; |
|
- const char *channel = argv[3]; |
|
+ const char *conference = a->argv[2]; |
|
+ const char *channel = a->argv[3]; |
|
|
|
int res = lock_conference_channel(conference, channel); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Locking failed\n"); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Locking failed\n"); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// unlock conference |
|
-// |
|
-static char conference_unlock_usage[] = |
|
- "usage: conference unlock <conference name>\n" |
|
- " unlocks conference <conference name>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_unlock = { |
|
- { "conference", "unlock", NULL }, |
|
- conference_unlock, |
|
- "unlocks conference", |
|
- conference_unlock_usage |
|
-} ; |
|
- |
|
-int conference_unlock( int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_unlock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference unlock"; |
|
+ e->usage = "usage: conference unlock <conference name>\n" |
|
+ " unlocks conference <conference name>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 3 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 3 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
|
|
- const char *conference = argv[2]; |
|
+ const char *conference = a->argv[2]; |
|
|
|
int res = unlock_conference(conference); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Unlocking failed\n"); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Unlocking failed\n"); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Set conference default video source |
|
-// |
|
-static char conference_set_default_usage[] = |
|
- "usage: conference set default <conference name> <member id>\n" |
|
- " sets the default video source for conference <conference name> to member <member id>\n" |
|
- " Use a negative value for member if you want to clear the default\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_set_default = { |
|
- { "conference", "set", "default", NULL }, |
|
- conference_set_default, |
|
- "sets default video source", |
|
- conference_set_default_usage |
|
-} ; |
|
- |
|
-int conference_set_default(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_set_default(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference set default"; |
|
+ e->usage = "usage: conference set default <conference name> <member id>\n" |
|
+ " sets the default video source for conference <conference name> to member <member id>\n" |
|
+ " Use a negative value for member if you want to clear the default\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[3]; |
|
+ const char *conference = a->argv[3]; |
|
int member; |
|
- sscanf(argv[4], "%d", &member); |
|
+ sscanf(a->argv[4], "%d", &member); |
|
|
|
int res = set_default_id(conference, member); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Setting default video id failed\n"); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Setting default video id failed\n"); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Set conference default video source channel |
|
-// |
|
-static char conference_set_defaultchannel_usage[] = |
|
- "usage: conference set defaultchannel <conference name> <channel>\n" |
|
- " sets the default video source channel for conference <conference name> to channel <channel>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_set_defaultchannel = { |
|
- { "conference", "set", "defaultchannel", NULL }, |
|
- conference_set_defaultchannel, |
|
- "sets default video source channel", |
|
- conference_set_defaultchannel_usage |
|
-} ; |
|
- |
|
-int conference_set_defaultchannel(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_set_defaultchannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference set defaultchannel"; |
|
+ e->usage = "usage: conference set defaultchannel <conference name> <channel>\n" |
|
+ " sets the default video source channel for conference <conference name> to channel <channel>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[3]; |
|
- const char *channel = argv[4]; |
|
+ const char *conference = a->argv[3]; |
|
+ const char *channel = a->argv[4]; |
|
|
|
int res = set_default_channel(conference, channel); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Setting default video id failed\n"); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Setting default video id failed\n"); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Mute video from a member |
|
-// |
|
-static char conference_video_mute_usage[] = |
|
- "usage: conference video mute <conference name> <member id>\n" |
|
- " mutes video from member <member id> in conference <conference name>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_video_mute = { |
|
- { "conference", "video", "mute", NULL }, |
|
- conference_video_mute, |
|
- "mutes video from a member", |
|
- conference_video_mute_usage |
|
-} ; |
|
- |
|
-int conference_video_mute(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_video_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference video mute"; |
|
+ e->usage = "usage: conference video mute <conference name> <member id>\n" |
|
+ " mutes video from member <member id> in conference <conference name>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[3]; |
|
+ const char *conference = a->argv[3]; |
|
int member; |
|
- sscanf(argv[4], "%d", &member); |
|
+ sscanf(a->argv[4], "%d", &member); |
|
|
|
int res = video_mute_member(conference, member); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Muting video from member %d failed\n", member); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Muting video from member %d failed\n", member); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Unmute video from a member |
|
-// |
|
-static char conference_video_unmute_usage[] = |
|
- "usage: conference video unmute <conference name> <member id>\n" |
|
- " unmutes video from member <member id> in conference <conference name>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_video_unmute = { |
|
- { "conference", "video", "unmute", NULL }, |
|
- conference_video_unmute, |
|
- "unmutes video from a member", |
|
- conference_video_unmute_usage |
|
-} ; |
|
- |
|
-int conference_video_unmute(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_video_unmute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference video unmute"; |
|
+ e->usage = "usage: conference video unmute <conference name> <member id>\n" |
|
+ " unmutes video from member <member id> in conference <conference name>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[3]; |
|
+ const char *conference = a->argv[3]; |
|
int member; |
|
- sscanf(argv[4], "%d", &member); |
|
+ sscanf(a->argv[4], "%d", &member); |
|
|
|
int res = video_unmute_member(conference, member); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Unmuting video from member %d failed\n", member); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Unmuting video from member %d failed\n", member); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Mute video from a channel |
|
-// |
|
-static char conference_video_mutechannel_usage[] = |
|
- "usage: conference video mutechannel <conference name> <channel>\n" |
|
- " mutes video from channel <channel> in conference <conference name>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_video_mutechannel = { |
|
- { "conference", "video", "mutechannel", NULL }, |
|
- conference_video_mutechannel, |
|
- "mutes video from a channel", |
|
- conference_video_mutechannel_usage |
|
-} ; |
|
- |
|
-int conference_video_mutechannel(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_video_mutechannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference video mutechannel"; |
|
+ e->usage = "usage: conference video mutechannel <conference name> <channel>\n" |
|
+ " mutes video from channel <channel> in conference <conference name>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[3]; |
|
- const char *channel = argv[4]; |
|
+ const char *conference = a->argv[3]; |
|
+ const char *channel = a->argv[4]; |
|
|
|
int res = video_mute_channel(conference, channel); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Muting video from channel %s failed\n", channel); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Muting video from channel %s failed\n", channel); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Unmute video from a channel |
|
-// |
|
-static char conference_video_unmutechannel_usage[] = |
|
- "usage: conference video unmutechannel <conference name> <channel>\n" |
|
- " unmutes video from channel <channel> in conference <conference name>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_video_unmutechannel = { |
|
- { "conference", "video", "unmutechannel", NULL }, |
|
- conference_video_unmutechannel, |
|
- "unmutes video from a channel", |
|
- conference_video_unmutechannel_usage |
|
-} ; |
|
- |
|
-int conference_video_unmutechannel(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_video_unmutechannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference video unmutechannel"; |
|
+ e->usage = "usage: conference video unmutechannel <conference name> <channel>\n" |
|
+ " unmutes video from channel <channel> in conference <conference name>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[3]; |
|
- const char *channel = argv[4]; |
|
+ const char *conference = a->argv[3]; |
|
+ const char *channel = a->argv[4]; |
|
|
|
int res = video_unmute_channel(conference, channel); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Unmuting video from channel %s failed\n", channel); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Unmuting video from channel %s failed\n", channel); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
- |
|
-// |
|
-// Text message functions |
|
-// Send a text message to a member |
|
-// |
|
-static char conference_text_usage[] = |
|
- "usage: conference text <conference name> <member id> <text>\n" |
|
- " Sends text message <text> to member <member id> in conference <conference name>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_text = { |
|
- { "conference", "text", NULL }, |
|
- conference_text, |
|
- "sends a text message to a member", |
|
- conference_text_usage |
|
-} ; |
|
- |
|
-int conference_text(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_text(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference text"; |
|
+ e->usage = "usage: conference text <conference name> <member id> <text>\n" |
|
+ " Sends text message <text> to member <member id> in conference <conference name>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[2]; |
|
+ const char *conference = a->argv[2]; |
|
int member; |
|
- sscanf(argv[3], "%d", &member); |
|
- const char *text = argv[4]; |
|
+ sscanf(a->argv[3], "%d", &member); |
|
+ const char *text = a->argv[4]; |
|
|
|
int res = send_text(conference, member, text); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Sending a text message to member %d failed\n", member); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Sending a text message to member %d failed\n", member); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Send a text message to a channel |
|
-// |
|
-static char conference_textchannel_usage[] = |
|
- "usage: conference textchannel <conference name> <channel> <text>\n" |
|
- " Sends text message <text> to channel <channel> in conference <conference name>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_textchannel = { |
|
- { "conference", "textchannel", NULL }, |
|
- conference_textchannel, |
|
- "sends a text message to a channel", |
|
- conference_textchannel_usage |
|
-} ; |
|
- |
|
-int conference_textchannel(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_textchannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference textchannel"; |
|
+ e->usage = "usage: conference textchannel <conference name> <channel> <text>\n" |
|
+ " Sends text message <text> to channel <channel> in conference <conference name>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 5 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 5 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[2]; |
|
- const char *channel = argv[3]; |
|
- const char *text = argv[4]; |
|
+ const char *conference = a->argv[2]; |
|
+ const char *channel = a->argv[3]; |
|
+ const char *text = a->argv[4]; |
|
|
|
int res = send_text_channel(conference, channel, text); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Sending a text message to channel %s failed\n", channel); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Sending a text message to channel %s failed\n", channel); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Send a text message to all members in a conference |
|
-// |
|
-static char conference_textbroadcast_usage[] = |
|
- "usage: conference textbroadcast <conference name> <text>\n" |
|
- " Sends text message <text> to all members in conference <conference name>\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_textbroadcast = { |
|
- { "conference", "textbroadcast", NULL }, |
|
- conference_textbroadcast, |
|
- "sends a text message to all members in a conference", |
|
- conference_textbroadcast_usage |
|
-} ; |
|
- |
|
-int conference_textbroadcast(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_textbroadcast(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference textbroadcast"; |
|
+ e->usage = "usage: conference textbroadcast <conference name> <text>\n" |
|
+ " Sends text message <text> to all members in conference <conference name>\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[2]; |
|
- const char *text = argv[3]; |
|
+ const char *conference = a->argv[2]; |
|
+ const char *text = a->argv[3]; |
|
|
|
int res = send_text_broadcast(conference, text); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Sending a text broadcast to conference %s failed\n", conference); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Sending a text broadcast to conference %s failed\n", conference); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Associate two members |
|
-// Audio from the source member will drive VAD based video switching for the destination member |
|
-// If the destination member is missing or negative, break any existing association |
|
-// |
|
-static char conference_drive_usage[] = |
|
- "usage: conference drive <conference name> <source member> [destination member]\n" |
|
- " Drives VAD video switching of <destination member> using audio from <source member> in conference <conference name>\n" |
|
- " If destination is missing or negative, break existing association\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_drive = { |
|
- { "conference", "drive", NULL }, |
|
- conference_drive, |
|
- "pairs two members to drive VAD-based video switching", |
|
- conference_drive_usage |
|
-} ; |
|
- |
|
-int conference_drive(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_drive(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference drive"; |
|
+ e->usage = "usage: conference drive <conference name> <source member> [destination member]\n" |
|
+ " Drives VAD video switching of <destination member> using audio from <source member> in conference <conference name>\n" |
|
+ " If destination is missing or negative, break existing association\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[2]; |
|
+ const char *conference = a->argv[2]; |
|
int src_member = -1; |
|
int dst_member = -1; |
|
- sscanf(argv[3], "%d", &src_member); |
|
- if ( argc > 4 ) |
|
- sscanf(argv[4], "%d", &dst_member); |
|
+ sscanf(a->argv[3], "%d", &src_member); |
|
+ if ( a->argc > 4 ) |
|
+ sscanf(a->argv[4], "%d", &dst_member); |
|
|
|
int res = drive(conference, src_member, dst_member); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Pairing members %d and %d failed\n", src_member, dst_member); |
|
- return RESULT_FAILURE; |
|
+ ast_cli( a->fd, "Pairing members %d and %d failed\n", src_member, dst_member); |
|
+ return CLI_FAILURE; |
|
} |
|
|
|
- return RESULT_SUCCESS; |
|
+ return CLI_SUCCESS; |
|
} |
|
|
|
-// |
|
-// Associate two channels |
|
-// Audio from the source channel will drive VAD based video switching for the destination channel |
|
-// If the destination channel is missing, break any existing association |
|
-// |
|
-static char conference_drivechannel_usage[] = |
|
- "usage: conference drive <conference name> <source channel> [destination channel]\n" |
|
- " Drives VAD video switching of <destination member> using audio from <source channel> in conference <conference channel>\n" |
|
- " If destination is missing, break existing association\n" |
|
-; |
|
- |
|
-static struct ast_cli_entry cli_drivechannel = { |
|
- { "conference", "drivechannel", NULL }, |
|
- conference_drivechannel, |
|
- "pairs two channels to drive VAD-based video switching", |
|
- conference_drivechannel_usage |
|
-} ; |
|
- |
|
-int conference_drivechannel(int fd, int argc, char *argv[] ) |
|
+static char *handle_cli_app_conference_drivechannel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
|
{ |
|
+ switch ( cmd ) { |
|
+ case CLI_INIT: |
|
+ e->command = "conference drivechannel"; |
|
+ e->usage = "usage: conference drive <conference name> <source channel> [destination channel]\n" |
|
+ " Drives VAD video switching of <destination member> using audio from <source channel> in conference <conference channel>\n" |
|
+ " If destination is missing, break existing association\n"; |
|
+ return NULL; |
|
+ case CLI_GENERATE: |
|
+ return NULL; |
|
+ } |
|
+ |
|
// check args |
|
- if ( argc < 4 ) |
|
- return RESULT_SHOWUSAGE; |
|
+ if ( a->argc < 4 ) |
|
+ return CLI_SHOWUSAGE; |
|
|
|
- const char *conference = argv[2]; |
|
- const char *src_channel = argv[3]; |
|
+ const char *conference = a->argv[2]; |
|
+ const char *src_channel = a->argv[3]; |
|
const char *dst_channel = NULL; |
|
- if ( argc > 4 ) |
|
- dst_channel = argv[4]; |
|
+ if ( a->argc > 4 ) |
|
+ dst_channel = a->argv[4]; |
|
|
|
int res = drive_channel(conference, src_channel, dst_channel); |
|
|
|
if ( !res ) |
|
{ |
|
- ast_cli(fd, "Pairing channels %s and %s failed\n", src_channel, dst_channel); |
|
+ ast_cli( a->fd, "Pairing channels %s and %s failed\n", src_channel, dst_channel); |
|
+ return CLI_FAILURE; |
|
+ } |
|
+ |
|
+ return CLI_SUCCESS; |
|
+} |
|
+ |
|
+static struct ast_cli_entry app_conference_clis[] = { |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_restart, "Restart a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_debug, "Enable debugging for a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_show_stats, "Display stats for active conferences"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_list, "List members of a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_kick, "Kick member from a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_kickchannel, "Kick channel from conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_exit, "Exit channel from any conference where it in"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_mute, "Mute member in a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_mutechannel, "Mute channel in a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_viewstream, "Switch view in a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_viewchannel, "Switch channel in a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_unmute, "Unmute member in a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_unmutechannel, "Unmute channel in a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_play_sound, "Play a sound to a conference member"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_stop_sounds, "Stop sounds for a conference member"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_end, "Stops a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_lock, "Locks incoming video to a member"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_lockchannel, "Locks incoming video to a channel"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_unlock, "Unlocks conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_set_default, "Sets default video sourcee"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_set_defaultchannel, "Sets default video source channel"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_video_mute, "Mutes video from a member"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_video_unmute, "Unmutes video from a member"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_video_mutechannel, "Mutes video from a channel"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_video_unmutechannel, "Unmutes video from a channel"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_text, "Sends a text message to a member"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_textchannel, "Sends a text message to a channel"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_textbroadcast, "Sends a text message to all members in a conference"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_drive, "Pairs two members to drive VAD-based video switching"), |
|
+ AST_CLI_DEFINE(handle_cli_app_conference_drivechannel, "Pairs two channels to drive VAD-based video switching"), |
|
+}; |
|
+ |
|
+// |
|
+// E.BUU - Manager conference end. Additional option to just kick everybody out |
|
+// without hangin up channels |
|
+// |
|
+int manager_conference_end(struct mansession *s, const struct message *m) |
|
+{ |
|
+ const char *confname = astman_get_header(m,"Conference"); |
|
+ int hangup = 1; |
|
+ |
|
+ const char * h = astman_get_header(m, "Hangup"); |
|
+ if (h) |
|
+ { |
|
+ hangup = atoi(h); |
|
+ } |
|
+ |
|
+ ast_log( LOG_NOTICE, "Terminating conference %s on manager's request. Hangup: %s.\n", confname, hangup?"YES":"NO" ); |
|
+ if ( end_conference( confname, hangup ) != 0 ) |
|
+ { |
|
+ ast_log( LOG_ERROR, "manager end conf: unable to terminate conference %s.\n", confname ); |
|
+ astman_send_error(s, m, "Failed to terminate\r\n"); |
|
return RESULT_FAILURE; |
|
} |
|
|
|
+ astman_send_ack(s, m, "Conference terminated"); |
|
return RESULT_SUCCESS; |
|
} |
|
|
|
- |
|
// |
|
// cli initialization function |
|
// |
|
|
|
void register_conference_cli( void ) |
|
{ |
|
- ast_cli_register( &cli_restart ); |
|
- ast_cli_register( &cli_debug ) ; |
|
- ast_cli_register( &cli_show_stats ) ; |
|
- ast_cli_register( &cli_list ); |
|
- ast_cli_register( &cli_kick ); |
|
- ast_cli_register( &cli_kickchannel ); |
|
- ast_cli_register( &cli_mute ); |
|
- ast_cli_register( &cli_mutechannel ); |
|
- ast_cli_register( &cli_viewstream ); |
|
- ast_cli_register( &cli_viewchannel ); |
|
- ast_cli_register( &cli_unmute ); |
|
- ast_cli_register( &cli_unmutechannel ); |
|
- ast_cli_register( &cli_play_sound ) ; |
|
- ast_cli_register( &cli_stop_sounds ) ; |
|
- ast_cli_register( &cli_end ); |
|
- ast_cli_register( &cli_lock ); |
|
- ast_cli_register( &cli_lockchannel ); |
|
- ast_cli_register( &cli_unlock ); |
|
- ast_cli_register( &cli_set_default ); |
|
- ast_cli_register( &cli_set_defaultchannel ); |
|
- ast_cli_register( &cli_video_mute ) ; |
|
- ast_cli_register( &cli_video_unmute ) ; |
|
- ast_cli_register( &cli_video_mutechannel ) ; |
|
- ast_cli_register( &cli_video_unmutechannel ) ; |
|
- ast_cli_register( &cli_text ); |
|
- ast_cli_register( &cli_textchannel ); |
|
- ast_cli_register( &cli_textbroadcast ); |
|
- ast_cli_register( &cli_drive ); |
|
- ast_cli_register( &cli_drivechannel ); |
|
+ ast_cli_register_multiple(app_conference_clis, sizeof(app_conference_clis) / sizeof(struct ast_cli_entry)); |
|
ast_manager_register( "ConferenceList", 0, manager_conference_list, "Conference List" ); |
|
ast_manager_register( "ConferenceEnd", EVENT_FLAG_CALL, manager_conference_end, "Terminate a conference" ); |
|
|
|
@@ -1191,35 +1110,7 @@ |
|
|
|
void unregister_conference_cli( void ) |
|
{ |
|
- ast_cli_unregister( &cli_restart ); |
|
- ast_cli_unregister( &cli_debug ) ; |
|
- ast_cli_unregister( &cli_show_stats ) ; |
|
- ast_cli_unregister( &cli_list ); |
|
- ast_cli_unregister( &cli_kick ); |
|
- ast_cli_unregister( &cli_kickchannel ); |
|
- ast_cli_unregister( &cli_mute ); |
|
- ast_cli_unregister( &cli_mutechannel ); |
|
- ast_cli_unregister( &cli_viewstream ); |
|
- ast_cli_unregister( &cli_viewchannel ); |
|
- ast_cli_unregister( &cli_unmute ); |
|
- ast_cli_unregister( &cli_unmutechannel ); |
|
- ast_cli_unregister( &cli_play_sound ) ; |
|
- ast_cli_unregister( &cli_stop_sounds ) ; |
|
- ast_cli_unregister( &cli_end ); |
|
- ast_cli_unregister( &cli_lock ); |
|
- ast_cli_unregister( &cli_lockchannel ); |
|
- ast_cli_unregister( &cli_unlock ); |
|
- ast_cli_unregister( &cli_set_default ); |
|
- ast_cli_unregister( &cli_set_defaultchannel ); |
|
- ast_cli_unregister( &cli_video_mute ) ; |
|
- ast_cli_unregister( &cli_video_unmute ) ; |
|
- ast_cli_unregister( &cli_video_mutechannel ) ; |
|
- ast_cli_unregister( &cli_video_unmutechannel ) ; |
|
- ast_cli_unregister( &cli_text ); |
|
- ast_cli_unregister( &cli_textchannel ); |
|
- ast_cli_unregister( &cli_textbroadcast ); |
|
- ast_cli_unregister( &cli_drive ); |
|
- ast_cli_unregister( &cli_drivechannel ); |
|
+ ast_cli_unregister_multiple(app_conference_clis, sizeof(app_conference_clis) / sizeof(struct ast_cli_entry)); |
|
ast_manager_unregister( "ConferenceList" ); |
|
ast_manager_unregister( "ConferenceEnd" ); |
|
} |
|
Index: cli.h |
|
--- cli.h.orig 2008-02-26 17:05:57 +0100 |
|
+++ cli.h 2008-03-19 09:18:57 +0100 |
|
@@ -42,52 +42,6 @@ |
|
// function declarations |
|
// |
|
|
|
-int conference_show_stats( int fd, int argc, char *argv[] ) ; |
|
-int conference_show_stats_name( int fd, const char* name ) ; |
|
- |
|
-int conference_restart( int fd, int argc, char *argv[] ); |
|
- |
|
-int conference_debug( int fd, int argc, char *argv[] ) ; |
|
-int conference_no_debug( int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_list( int fd, int argc, char *argv[] ) ; |
|
-int conference_kick( int fd, int argc, char *argv[] ) ; |
|
-int conference_kickchannel( int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_mute( int fd, int argc, char *argv[] ) ; |
|
-int conference_unmute( int fd, int argc, char *argv[] ) ; |
|
-int conference_mutechannel( int fd, int argc, char *argv[] ) ; |
|
-int conference_unmutechannel( int fd, int argc, char *argv[] ) ; |
|
-int conference_viewstream( int fd, int argc, char *argv[] ) ; |
|
-int conference_viewchannel( int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_play_sound( int fd, int argc, char *argv[] ) ; |
|
-int conference_stop_sounds( int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_play_video( int fd, int argc, char *argv[] ) ; |
|
-int conference_stop_videos( int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_end( int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_lock( int fd, int argc, char *argv[] ) ; |
|
-int conference_lockchannel( int fd, int argc, char *argv[] ) ; |
|
-int conference_unlock( int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_set_default(int fd, int argc, char *argv[] ) ; |
|
-int conference_set_defaultchannel(int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_video_mute(int fd, int argc, char *argv[] ) ; |
|
-int conference_video_mutechannel(int fd, int argc, char *argv[] ) ; |
|
-int conference_video_unmute(int fd, int argc, char *argv[] ) ; |
|
-int conference_video_unmutechannel(int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_text( int fd, int argc, char *argv[] ) ; |
|
-int conference_textchannel( int fd, int argc, char *argv[] ) ; |
|
-int conference_textbroadcast( int fd, int argc, char *argv[] ) ; |
|
- |
|
-int conference_drive( int fd, int argc, char *argv[] ) ; |
|
-int conference_drivechannel(int fd, int argc, char *argv[] ); |
|
- |
|
int manager_conference_end(struct mansession *s, const struct message *m); |
|
|
|
void register_conference_cli( void ) ; |
|
Index: conference.c |
|
--- conference.c.orig 2008-02-26 17:05:57 +0100 |
|
+++ conference.c 2008-03-19 09:18:57 +0100 |
|
@@ -28,6 +28,9 @@ |
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
*/ |
|
|
|
+#include "asterisk.h" |
|
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.1 $") |
|
+ |
|
#include "asterisk/autoconfig.h" |
|
#include "conference.h" |
|
#include "asterisk/utils.h" |
|
@@ -45,12 +48,21 @@ |
|
|
|
static int conference_count = 0 ; |
|
|
|
+// Forward funtcion declarations |
|
+static void do_VAD_switching(struct ast_conference *conf); |
|
+static void do_video_switching(struct ast_conference *conf, int new_id, int lock); |
|
+static struct ast_conference* find_conf(const char* name); |
|
+static struct ast_conference* create_conf(char* name, struct ast_conf_member* member); |
|
+static void remove_conf(struct ast_conference* conf); |
|
+static void add_member(struct ast_conf_member* member, struct ast_conference* conf); |
|
+static int get_new_id(struct ast_conference *conf); |
|
+static int update_member_broadcasting(struct ast_conference *conf, struct ast_conf_member *member, struct conf_frame *cfr, struct timeval time); |
|
|
|
// |
|
// main conference function |
|
// |
|
|
|
-void conference_exec( struct ast_conference *conf ) |
|
+static void conference_exec( struct ast_conference *conf ) |
|
{ |
|
|
|
struct ast_conf_member *next_member; |
|
@@ -302,54 +314,126 @@ |
|
// VIDEO // |
|
//-------// |
|
|
|
- // loop over the incoming frames and send to all outgoing |
|
- // TODO: this is an O(n^2) algorithm. Can we speed it up without sacrificing per-member switching? |
|
- for (video_source_member = conf->memberlist; |
|
- video_source_member != NULL; |
|
- video_source_member = video_source_member->next) |
|
+ curr = ast_tvnow(); |
|
+ |
|
+ // Chat mode handling |
|
+ // If there's only one member, then video gets reflected back to it |
|
+ // If there are two members, then each sees the other's video |
|
+ if ( conf->does_chat_mode && |
|
+ conf->membercount > 0 && |
|
+ conf->membercount <= 2 |
|
+ ) |
|
+ { |
|
+ struct ast_conf_member *m1, *m2; |
|
+ |
|
+ m1 = conf->memberlist; |
|
+ m2 = conf->memberlist->next; |
|
+ |
|
+ if ( !conf->chat_mode_on ) |
|
+ conf->chat_mode_on = 1; |
|
+ |
|
+ start_video(m1); |
|
+ if ( m2 != NULL ) |
|
+ start_video(m2); |
|
+ |
|
+ if ( conf->membercount == 1 ) |
|
+ { |
|
+ cfr = get_incoming_video_frame(m1); |
|
+ update_member_broadcasting(conf, m1, cfr, curr); |
|
+ while ( cfr ) |
|
+ { |
|
+ queue_outgoing_video_frame(m1, cfr->fr, conf->delivery_time); |
|
+ delete_conf_frame(cfr); |
|
+ cfr = get_incoming_video_frame(m1); |
|
+ } |
|
+ } else if ( conf->membercount == 2 ) |
|
+ { |
|
+ cfr = get_incoming_video_frame(m1); |
|
+ update_member_broadcasting(conf, m1, cfr, curr); |
|
+ while ( cfr ) |
|
+ { |
|
+ queue_outgoing_video_frame(m2, cfr->fr, conf->delivery_time); |
|
+ delete_conf_frame(cfr); |
|
+ cfr = get_incoming_video_frame(m1); |
|
+ } |
|
+ |
|
+ cfr = get_incoming_video_frame(m2); |
|
+ update_member_broadcasting(conf, m2, cfr, curr); |
|
+ while ( cfr ) |
|
+ { |
|
+ queue_outgoing_video_frame(m1, cfr->fr, conf->delivery_time); |
|
+ delete_conf_frame(cfr); |
|
+ cfr = get_incoming_video_frame(m2); |
|
+ } |
|
+ } |
|
+ } else |
|
{ |
|
- while ((cfr = get_incoming_video_frame( video_source_member ))) |
|
+ // Generic conference handling (chat mode disabled or more than 2 members) |
|
+ // If we were previously in chat mode, turn it off and stop video from members |
|
+ if ( conf->chat_mode_on ) |
|
{ |
|
+ // Send STOPVIDEO commands to everybody except the current source, if any |
|
+ conf->chat_mode_on = 0; |
|
for (member = conf->memberlist; member != NULL; member = member->next) |
|
{ |
|
- // skip members that are not ready or are not supposed to receive video |
|
- if ( !member->ready_for_outgoing || member->norecv_video ) |
|
- continue ; |
|
- |
|
- if ( conf->video_locked ) |
|
- { |
|
- // Always send video from the locked source |
|
- if ( conf->current_video_source_id == video_source_member->id ) |
|
- queue_outgoing_video_frame(member, cfr->fr, conf->delivery_time); |
|
- } else |
|
+ if ( member->id != conf->current_video_source_id ) |
|
+ stop_video(member); |
|
+ } |
|
+ } |
|
+ |
|
+ // loop over the incoming frames and send to all outgoing |
|
+ // TODO: this is an O(n^2) algorithm. Can we speed it up without sacrificing per-member switching? |
|
+ for (video_source_member = conf->memberlist; |
|
+ video_source_member != NULL; |
|
+ video_source_member = video_source_member->next |
|
+ ) |
|
+ { |
|
+ cfr = get_incoming_video_frame(video_source_member); |
|
+ update_member_broadcasting(conf, video_source_member, cfr, curr); |
|
+ while ( cfr ) |
|
+ { |
|
+ for (member = conf->memberlist; member != NULL; member = member->next) |
|
{ |
|
- // If the member has vad switching disabled and dtmf switching enabled, use that |
|
- if ( member->dtmf_switch && |
|
- !member->vad_switch && |
|
- member->req_id == video_source_member->id |
|
- ) |
|
+ // skip members that are not ready or are not supposed to receive video |
|
+ if ( !member->ready_for_outgoing || member->norecv_video ) |
|
+ continue ; |
|
+ |
|
+ if ( conf->video_locked ) |
|
{ |
|
- queue_outgoing_video_frame(member, cfr->fr, conf->delivery_time); |
|
+ // Always send video from the locked source |
|
+ if ( conf->current_video_source_id == video_source_member->id ) |
|
+ queue_outgoing_video_frame(member, cfr->fr, conf->delivery_time); |
|
} else |
|
{ |
|
- // If no dtmf switching, then do VAD switching |
|
- // The VAD switching decision code should make sure that our video source |
|
- // is legit |
|
- if ( (conf->current_video_source_id == video_source_member->id) || |
|
- (conf->current_video_source_id < 0 && |
|
- conf->default_video_source_id == video_source_member->id |
|
- ) |
|
+ // If the member has vad switching disabled and dtmf switching enabled, use that |
|
+ if ( member->dtmf_switch && |
|
+ !member->vad_switch && |
|
+ member->req_id == video_source_member->id |
|
) |
|
{ |
|
queue_outgoing_video_frame(member, cfr->fr, conf->delivery_time); |
|
+ } else |
|
+ { |
|
+ // If no dtmf switching, then do VAD switching |
|
+ // The VAD switching decision code should make sure that our video source |
|
+ // is legit |
|
+ if ( (conf->current_video_source_id == video_source_member->id) || |
|
+ (conf->current_video_source_id < 0 && |
|
+ conf->default_video_source_id == video_source_member->id |
|
+ ) |
|
+ ) |
|
+ { |
|
+ queue_outgoing_video_frame(member, cfr->fr, conf->delivery_time); |
|
+ } |
|
} |
|
- } |
|
|
|
|
|
+ } |
|
} |
|
+ // Garbage collection |
|
+ delete_conf_frame(cfr); |
|
+ cfr = get_incoming_video_frame(video_source_member); |
|
} |
|
- // Garbage collection |
|
- delete_conf_frame(cfr); |
|
} |
|
} |
|
|
|
@@ -448,7 +532,7 @@ |
|
ast_mutex_init( &conflist_lock ) ; |
|
} |
|
|
|
-struct ast_conference* start_conference( struct ast_conf_member* member ) |
|
+struct ast_conference* join_conference( struct ast_conf_member* member ) |
|
{ |
|
// check input |
|
if ( member == NULL ) |
|
@@ -499,7 +583,7 @@ |
|
} |
|
|
|
// This function should be called with conflist_lock mutex being held |
|
-struct ast_conference* find_conf( const char* name ) |
|
+static struct ast_conference* find_conf( const char* name ) |
|
{ |
|
// no conferences exist |
|
if ( conflist == NULL ) |
|
@@ -527,7 +611,7 @@ |
|
} |
|
|
|
// This function should be called with conflist_lock held |
|
-struct ast_conference* create_conf( char* name, struct ast_conf_member* member ) |
|
+static struct ast_conference* create_conf( char* name, struct ast_conf_member* member ) |
|
{ |
|
ast_log( AST_CONF_DEBUG, "entered create_conf, name => %s\n", name ) ; |
|
|
|
@@ -551,7 +635,7 @@ |
|
conf->memberlist = NULL ; |
|
|
|
conf->membercount = 0 ; |
|
- conf->conference_thread = -1 ; |
|
+ conf->conference_thread = 0 ; |
|
|
|
conf->debug_flag = 0 ; |
|
|
|
@@ -562,6 +646,9 @@ |
|
//conf->current_video_source_timestamp = ast_tvnow(); |
|
conf->video_locked = 0; |
|
|
|
+ conf->chat_mode_on = 0; |
|
+ conf->does_chat_mode = 0; |
|
+ |
|
// zero stats |
|
memset( &conf->stats, 0x0, sizeof( ast_conference_stats ) ) ; |
|
|
|
@@ -614,7 +701,7 @@ |
|
{ |
|
ast_log( LOG_ERROR, "unable to start conference thread for conference %s\n", conf->name ) ; |
|
|
|
- conf->conference_thread = -1 ; |
|
+ conf->conference_thread = 0 ; |
|
|
|
// release conference mutexes |
|
ast_mutex_unlock( &conf->lock ) ; |
|
@@ -632,7 +719,7 @@ |
|
} |
|
|
|
//This function should be called with conflist_lock and conf->lock held |
|
-void remove_conf( struct ast_conference *conf ) |
|
+static void remove_conf( struct ast_conference *conf ) |
|
{ |
|
int c; |
|
|
|
@@ -709,7 +796,7 @@ |
|
return ; |
|
} |
|
|
|
-int get_new_id( struct ast_conference *conf ) |
|
+static int get_new_id( struct ast_conference *conf ) |
|
{ |
|
// must have the conf lock when calling this |
|
int newid; |
|
@@ -788,11 +875,10 @@ |
|
// |
|
|
|
// This function should be called with conflist_lock held |
|
-void add_member( struct ast_conf_member *member, struct ast_conference *conf ) |
|
+static void add_member( struct ast_conf_member *member, struct ast_conference *conf ) |
|
{ |
|
int newid, last_id; |
|
struct ast_conf_member *othermember; |
|
- int count; |
|
|
|
if ( conf == NULL ) |
|
{ |
|
@@ -820,11 +906,22 @@ |
|
} |
|
} |
|
|
|
- if ( member->mute_video ) |
|
+ // update conference stats |
|
+ conf->membercount++; |
|
+ |
|
+ // The conference sets chat mode according to the latest member chat flag |
|
+ conf->does_chat_mode = member->does_chat_mode; |
|
+ |
|
+ // check if we're supposed to do chat_mode, and if so, start video on the client |
|
+ if ( conf->does_chat_mode && conf->membercount <= 2 ) |
|
{ |
|
- send_text_message_to_member(member, AST_CONF_CONTROL_STOP_VIDEO); |
|
+ start_video(member); |
|
+ conf->chat_mode_on = 1; |
|
} |
|
|
|
+ if ( member->mute_video ) |
|
+ stop_video(member); |
|
+ |
|
// set a long term id |
|
int new_initial_id = 0; |
|
othermember = conf->memberlist; |
|
@@ -853,9 +950,6 @@ |
|
member->next = conf->memberlist ; // next is now list |
|
conf->memberlist = member ; // member is now at head of list |
|
|
|
- // update conference stats |
|
- count = count_member( member, conf, 1 ) ; |
|
- |
|
ast_log( AST_CONF_DEBUG, "member added to conference, name => %s\n", conf->name ) ; |
|
|
|
// release the conference lock |
|
@@ -957,7 +1051,7 @@ |
|
member_temp->next = member->next ; |
|
|
|
// update conference stats |
|
- count = count_member( member, conf, 0 ) ; |
|
+ count = --conf->membercount; |
|
|
|
// Check if member is the default or current video source |
|
if ( conf->current_video_source_id == member->id ) |
|
@@ -970,6 +1064,17 @@ |
|
conf->default_video_source_id = -1; |
|
} |
|
|
|
+ // If the member is broadcasting, we notify that it is no longer the case |
|
+ if ( member->video_broadcast_active ) |
|
+ { |
|
+ manager_event(EVENT_FLAG_CALL, |
|
+ "ConferenceVideoBroadcastOff", |
|
+ "ConferenceName: %s\r\nChannel: %s\r\n", |
|
+ conf->name, |
|
+ member->channel_name |
|
+ ); |
|
+ } |
|
+ |
|
// output to manager... |
|
manager_event( |
|
EVENT_FLAG_CALL, |
|
@@ -997,6 +1102,32 @@ |
|
// it already points to the previous (or NULL). |
|
// it will still be the previous after member is deleted |
|
|
|
+ // notify others about leave |
|
+ char * leave_snd = member->leave_snd; |
|
+ if (conf->membercount && strcmp(leave_snd, "-")>1) |
|
+ { |
|
+ struct ast_conf_member *membertest = conf->memberlist; |
|
+ while (membertest != NULL) |
|
+ { |
|
+ if (membertest != member) |
|
+ { |
|
+ // lock member for basic_play_sound |
|
+ ast_mutex_lock(&membertest->lock); |
|
+ |
|
+ // basic_play_sound unlock member automatically. do not mute on enter message |
|
+ if (!basic_play_sound (membertest, leave_snd, 0)) |
|
+ { |
|
+ ast_log(LOG_ERROR, "playing conference[%d] leave message <%s> FAILED on <%s>\n", conf->membercount, leave_snd, membertest->channel_name) ; |
|
+ } |
|
+ else |
|
+ { |
|
+ ast_log(LOG_NOTICE, "playing conference[%d] leave message <%s> on <%s>\n", conf->membercount, leave_snd, membertest->channel_name); |
|
+ } |
|
+ membertest = membertest->next; |
|
+ } |
|
+ } |
|
+ } |
|
+ |
|
// delete the member |
|
delete_member( member ) ; |
|
|
|
@@ -1028,33 +1159,6 @@ |
|
return count ; |
|
} |
|
|
|
-int count_member( struct ast_conf_member* member, struct ast_conference* conf, short add_member ) |
|
-{ |
|
- if ( member == NULL || conf == NULL ) |
|
- { |
|
- ast_log( LOG_WARNING, "unable to count member\n" ) ; |
|
- return -1 ; |
|
- } |
|
- |
|
- short delta = ( add_member == 1 ) ? 1 : -1 ; |
|
- |
|
- // increment member count |
|
- conf->membercount += delta ; |
|
- |
|
- return conf->membercount ; |
|
-} |
|
- |
|
-// |
|
-// queue incoming frame functions |
|
-// |
|
- |
|
- |
|
- |
|
- |
|
-// |
|
-// get conference stats |
|
-// |
|
- |
|
// |
|
// returns: -1 => error, 0 => debugging off, 1 => debugging on |
|
// state: on => 1, off => 0, toggle => -1 |
|
@@ -1160,6 +1264,8 @@ |
|
// acquire conference mutex |
|
ast_mutex_lock(&conf->lock); |
|
|
|
+ ast_cli(fd, "Chat mode is %s\n", conf->chat_mode_on ? "ON" : "OFF"); |
|
+ |
|
// do the biz |
|
member = conf->memberlist ; |
|
while ( member != NULL ) |
|
@@ -1182,6 +1288,9 @@ |
|
if ( member->no_camera ) ast_cli( fd, "N"); |
|
if ( member->does_text ) ast_cli( fd, "t"); |
|
if ( member->via_telephone ) ast_cli( fd, "T"); |
|
+ if ( member->vad_linger ) ast_cli( fd, "z"); |
|
+ if ( member->does_chat_mode ) ast_cli( fd, "o" ); |
|
+ if ( member->force_vad_switch ) ast_cli( fd, "F" ); |
|
ast_cli( fd, " " ); |
|
|
|
if ( member->id == conf->default_video_source_id ) |
|
@@ -1871,16 +1980,18 @@ |
|
// All the VAD-based video switching magic happens here |
|
// This function should be called inside conference_exec |
|
// The conference mutex should be locked, we don't have to do it here |
|
-void do_VAD_switching(struct ast_conference *conf) |
|
+static void do_VAD_switching(struct ast_conference *conf) |
|
{ |
|
struct ast_conf_member *member; |
|
- struct timeval current_time; |
|
- long longest_speaking; |
|
- struct ast_conf_member *longest_speaking_member; |
|
- int current_silent, current_no_camera, current_video_mute; |
|
- int default_no_camera, default_video_mute; |
|
- |
|
- current_time = ast_tvnow(); |
|
+ struct timeval current_time = ast_tvnow(); |
|
+ long longest_speaking = 0; |
|
+ struct ast_conf_member *longest_speaking_member = NULL; |
|
+ int current_silent = 0; |
|
+ int current_linger = 0; |
|
+ int current_no_video = 0; |
|
+ int current_force_switch = 0; |
|
+ int default_no_video = 0; |
|
+ int default_force_switch = 0; |
|
|
|
// Scan the member list looking for the longest speaking member |
|
// We also check if the currently speaking member has been silent for a while |
|
@@ -1889,27 +2000,10 @@ |
|
// at least AST_CONF_VIDEO_START_TIMEOUT ms |
|
// We say that a member is silent after his speaking state has been off for |
|
// at least AST_CONF_VIDEO_STOP_TIMEOUT ms |
|
- longest_speaking = 0; |
|
- longest_speaking_member = NULL; |
|
- current_silent = 0; |
|
- current_no_camera = 0; |
|
- current_video_mute = 0; |
|
- default_no_camera = 0; |
|
- default_video_mute = 0; |
|
for ( member = conf->memberlist ; |
|
member != NULL ; |
|
member = member->next ) |
|
{ |
|
- // Has the state changed since last time through this loop? Notify! |
|
- if ( member->speaking_state_notify ) |
|
- { |
|
-/* fprintf(stderr, "Mihai: member %d, channel %s has changed state to %s\n", |
|
- member->id, |
|
- member->channel_name, |
|
- ((member->speaking_state == 1 ) ? "speaking" : "silent") |
|
- ); */ |
|
- } |
|
- |
|
// If a member connects via telephone, they don't have video |
|
if ( member->via_telephone ) |
|
continue; |
|
@@ -1920,29 +2014,30 @@ |
|
if ( !member->vad_switch ) |
|
continue; |
|
|
|
- if ( member->mute_video ) |
|
+ // Extract the linger and force switch flags of the current video source |
|
+ if ( member->id == conf->current_video_source_id ) |
|
{ |
|
- if ( member->id == conf->default_video_source_id ) |
|
- default_video_mute = 1; |
|
- if ( member->id == conf->current_video_source_id ) |
|
- current_video_mute = 1; |
|
- else |
|
- continue; |
|
+ current_linger = member->vad_linger; |
|
+ current_force_switch = member->force_vad_switch; |
|
} |
|
+ |
|
+ if ( member->id == conf->default_video_source_id ) |
|
+ default_force_switch = member->force_vad_switch; |
|
|
|
- if ( member->no_camera ) |
|
+ if ( member->no_camera || member->mute_video ) |
|
{ |
|
if ( member->id == conf->default_video_source_id ) |
|
- default_no_camera = 1; |
|
+ default_no_video = 1; |
|
+ |
|
if ( member->id == conf->current_video_source_id ) |
|
- current_no_camera = 1; |
|
- else |
|
+ current_no_video = 1; |
|
+ else if ( !member->force_vad_switch ) |
|
continue; |
|
} |
|
|
|
// Check if current speaker has been silent for a while |
|
if ( member->id == conf->current_video_source_id && |
|
- member->speaking_state == 0 && |
|
+ !member->speaking_state && |
|
ast_tvdiff_ms(current_time, member->last_state_change) > AST_CONF_VIDEO_STOP_TIMEOUT ) |
|
{ |
|
current_silent = 1; |
|
@@ -1963,27 +2058,33 @@ |
|
|
|
// We got our results, now let's make a decision |
|
// If the currently speaking member has been marked as silent, then we take the longest |
|
- // speaking member. If no member is speaking, we go to default |
|
+ // speaking member. If no member is speaking, but the current member has the vad_linger |
|
+ // flag set, we stay put, otherwise we go to default. If there's no default, we blank. |
|
// As a policy we don't want to switch away from a member that is speaking |
|
// however, we might need to refine this to avoid a situation when a member has a |
|
// low noise threshold or its VAD is simply stuck |
|
- if ( current_silent || current_no_camera || current_video_mute || conf->current_video_source_id < 0 ) |
|
- { |
|
- if ( longest_speaking_member != NULL ) |
|
- { |
|
- do_video_switching(conf, longest_speaking_member->id, 0); |
|
- } else |
|
- { |
|
- // If there's nobody speaking and we have a default that can send video, switch to it |
|
- // If not, then switch to empty (-1) |
|
- if ( conf->default_video_source_id >= 0 && |
|
- !default_no_camera && |
|
- !default_video_mute |
|
- ) |
|
- do_video_switching(conf, conf->default_video_source_id, 0); |
|
- else |
|
- do_video_switching(conf, -1, 0); |
|
- } |
|
+ if ( |
|
+ (conf->current_video_source_id < 0) || |
|
+ (current_silent && !current_linger) || |
|
+ (current_silent && longest_speaking_member != NULL ) || |
|
+ (current_no_video && !current_force_switch) |
|
+ ) |
|
+ { |
|
+ int new_id; |
|
+ |
|
+ if ( longest_speaking_member ) |
|
+ // Somebody is talking, switch to that member |
|
+ new_id = longest_speaking_member->id; |
|
+ else if ( conf->default_video_source_id && |
|
+ (!default_no_video || default_force_switch) |
|
+ ) |
|
+ // No talking, but we have a default that can send video |
|
+ new_id = conf->default_video_source_id; |
|
+ else |
|
+ // No default, switch to empty (-1) |
|
+ new_id = -1; |
|
+ |
|
+ do_video_switching(conf, new_id, 0); |
|
} |
|
} |
|
|
|
@@ -2752,80 +2853,62 @@ |
|
// a text message notifying members of a video switch |
|
// The notification is sent to the current member and to the new member |
|
// The function locks the conference mutex as required |
|
-void do_video_switching(struct ast_conference *conf, int new_id, int lock) |
|
+static void do_video_switching(struct ast_conference *conf, int new_id, int lock) |
|
{ |
|
- struct ast_conf_member *member; |
|
- struct ast_conf_member *new_member = NULL; |
|
- |
|
if ( conf == NULL ) return; |
|
|
|
if ( lock ) |
|
- { |
|
- // acquire conference mutex |
|
ast_mutex_lock( &conf->lock ); |
|
- } |
|
- |
|
- //fprintf(stderr, "Mihai: video switch from %d to %d\n", conf->current_video_source_id, new_id); |
|
|
|
// No need to do anything if the current member is the same as the new member |
|
if ( new_id != conf->current_video_source_id ) |
|
{ |
|
+ // During chat mode, we don't actually switch members |
|
+ // however, we keep track of who's supposed to be current speaker |
|
+ // so we can switch to it once we get out of chat mode. |
|
+ // We also send VideoSwitch events so anybody monitoring the AMI |
|
+ // can keep track of this |
|
+ struct ast_conf_member *member; |
|
+ struct ast_conf_member *new_member = NULL; |
|
+ |
|
for ( member = conf->memberlist ; member != NULL ; member = member->next ) |
|
{ |
|
if ( member->id == conf->current_video_source_id ) |
|
{ |
|
- send_text_message_to_member(member, AST_CONF_CONTROL_STOP_VIDEO); |
|
+ if ( !conf->chat_mode_on ) |
|
+ stop_video(member); |
|
} |
|
if ( member->id == new_id ) |
|
{ |
|
- send_text_message_to_member(member, AST_CONF_CONTROL_START_VIDEO); |
|
+ if ( !conf->chat_mode_on ) |
|
+ start_video(member); |
|
new_member = member; |
|
} |
|
} |
|
|
|
- conf->current_video_source_id = new_id; |
|
+ manager_event(EVENT_FLAG_CALL, |
|
+ "ConferenceVideoSwitch", |
|
+ "ConferenceName: %s\r\nChannel: %s\r\n", |
|
+ conf->name, |
|
+ new_member == NULL ? "empty" : new_member->channel_name |
|
+ ); |
|
|
|
- if ( new_member != NULL ) |
|
- { |
|
- manager_event(EVENT_FLAG_CALL, |
|
- "ConferenceVideoSwitch", |
|
- "ConferenceName: %s\r\nChannel: %s\r\n", |
|
- conf->name, |
|
- new_member->channel_name); |
|
- } else |
|
- { |
|
- manager_event(EVENT_FLAG_CALL, |
|
- "ConferenceVideoSwitch", |
|
- "ConferenceName: %s\r\nChannel: empty\r\n", |
|
- conf->name); |
|
- } |
|
+ conf->current_video_source_id = new_id; |
|
} |
|
|
|
if ( lock ) |
|
- { |
|
- // release conference mutex |
|
ast_mutex_unlock( &conf->lock ); |
|
- } |
|
} |
|
|
|
-int play_sound_channel(int fd, const char *channel, const char *file, int mute) |
|
+int basic_play_sound(struct ast_conf_member *member, const char *file, int mute) |
|
{ |
|
- struct ast_conf_member *member; |
|
struct ast_conf_soundq *newsound; |
|
struct ast_conf_soundq **q; |
|
|
|
- member = find_member(channel, 1); |
|
- if( !member ) |
|
- { |
|
- ast_cli(fd, "Member %s not found\n", channel); |
|
- return 0; |
|
- } |
|
- |
|
newsound = calloc(1, sizeof(struct ast_conf_soundq)); |
|
newsound->stream = ast_openstream(member->chan, file, NULL); |
|
- if( !newsound->stream ) |
|
+ if( !newsound->stream ) |
|
{ |
|
- ast_cli(fd, "Sound %s not found\n", file); |
|
free(newsound); |
|
ast_mutex_unlock(&member->lock); |
|
return 0; |
|
@@ -2841,6 +2924,26 @@ |
|
|
|
ast_mutex_unlock(&member->lock); |
|
|
|
+ return 1 ; |
|
+} |
|
+ |
|
+int play_sound_channel(int fd, const char *channel, const char *file, int mute) |
|
+{ |
|
+ struct ast_conf_member *member; |
|
+ |
|
+ member = find_member(channel, 1); |
|
+ if( !member ) |
|
+ { |
|
+ ast_cli(fd, "Member %s not found\n", channel); |
|
+ return 0; |
|
+ } |
|
+ |
|
+ if (! basic_play_sound(member, file, mute)) |
|
+ { |
|
+ ast_cli(fd, "Sound %s not found\n", file); |
|
+ return 0; |
|
+ } |
|
+ |
|
ast_cli(fd, "Playing sound %s to member %s %s\n", |
|
file, channel, mute ? "with mute" : ""); |
|
|
|
@@ -2884,3 +2987,38 @@ |
|
ast_cli( fd, "Stopped sounds to member %s\n", channel); |
|
return 1; |
|
} |
|
+ |
|
+static int update_member_broadcasting(struct ast_conference *conf, struct ast_conf_member *member, struct conf_frame *cfr, struct timeval now) |
|
+{ |
|
+ if ( conf == NULL || member == NULL ) |
|
+ return 0; |
|
+ |
|
+ if ( cfr == NULL && |
|
+ member->video_broadcast_active && |
|
+ (ast_tvdiff_ms(now, member->last_video_frame_time)) > AST_CONF_VIDEO_STOP_BROADCAST_TIMEOUT |
|
+ ) |
|
+ { |
|
+ member->video_broadcast_active = 0; |
|
+ manager_event(EVENT_FLAG_CALL, |
|
+ "ConferenceVideoBroadcastOff", |
|
+ "ConferenceName: %s\r\nChannel: %s\r\n", |
|
+ conf->name, |
|
+ member->channel_name |
|
+ ); |
|
+ } else if ( cfr != NULL ) |
|
+ { |
|
+ member->last_video_frame_time = now; |
|
+ if ( !member->video_broadcast_active ) |
|
+ { |
|
+ member->video_broadcast_active = 1; |
|
+ manager_event(EVENT_FLAG_CALL, |
|
+ "ConferenceVideoBroadcastOn", |
|
+ "ConferenceName: %s\r\nChannel: %s\r\n", |
|
+ conf->name, |
|
+ member->channel_name |
|
+ ); |
|
+ } |
|
+ } |
|
+ |
|
+ return member->video_broadcast_active; |
|
+} |
|
Index: conference.h |
|
--- conference.h.orig 2008-02-26 17:05:57 +0100 |
|
+++ conference.h 2008-03-19 09:18:57 +0100 |
|
@@ -109,6 +109,12 @@ |
|
// keep track of current delivery time |
|
struct timeval delivery_time ; |
|
|
|
+ // the conference does chat mode: special treatment for situations with 1 and 2 members |
|
+ short does_chat_mode; |
|
+ |
|
+ // chat mode is on; |
|
+ short chat_mode_on; |
|
+ |
|
// 1 => on, 0 => off |
|
short debug_flag ; |
|
} ; |
|
@@ -120,13 +126,8 @@ |
|
// function declarations |
|
// |
|
|
|
-struct ast_conference* start_conference( struct ast_conf_member* member ) ; |
|
- |
|
-void conference_exec( struct ast_conference* conf ) ; |
|
+struct ast_conference* join_conference( struct ast_conf_member* member ) ; |
|
|
|
-struct ast_conference* find_conf( const char* name ) ; |
|
-struct ast_conference* create_conf( char* name, struct ast_conf_member* member ) ; |
|
-void remove_conf( struct ast_conference* conf ) ; |
|
int end_conference( const char *name, int hangup ) ; |
|
|
|
// find a particular member, locking if requested. |
|
@@ -136,14 +137,9 @@ |
|
int queue_frame_for_speaker( struct ast_conference* conf, struct ast_conf_member* member, conf_frame* frame ) ; |
|
int queue_silent_frame( struct ast_conference* conf, struct ast_conf_member* member ) ; |
|
|
|
-int get_new_id( struct ast_conference *conf ); |
|
-void add_member( struct ast_conf_member* member, struct ast_conference* conf ) ; |
|
int remove_member( struct ast_conf_member* member, struct ast_conference* conf ) ; |
|
-int count_member( struct ast_conf_member* member, struct ast_conference* conf, short add_member ) ; |
|
|
|
-void do_VAD_switching(struct ast_conference *conf); |
|
int send_text_message_to_member(struct ast_conf_member *member, const char *text); |
|
-void do_video_switching(struct ast_conference *conf, int new_id, int lock); |
|
|
|
// called by app_confernce.c:load_module() |
|
void init_conference( void ) ; |
|
@@ -185,6 +181,7 @@ |
|
int drive(const char *conference, int src_member_id, int dst_member_id); |
|
int drive_channel(const char *conference, const char *src_channel, const char *dst_channel); |
|
|
|
+int basic_play_sound(struct ast_conf_member *member, const char *file, int mute); |
|
int play_sound_channel(int fd, const char *channel, const char *file, int mute); |
|
int stop_sound_channel(int fd, const char *channel); |
|
|
|
Index: frame.c |
|
--- frame.c.orig 2008-02-26 17:05:57 +0100 |
|
+++ frame.c 2008-03-19 09:18:57 +0100 |
|
@@ -28,6 +28,10 @@ |
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
*/ |
|
|
|
+#include "asterisk.h" |
|
+ |
|
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.1 $") |
|
+ |
|
#include "asterisk/autoconfig.h" |
|
#include "frame.h" |
|
|
|
Index: member.c |
|
--- member.c.orig 2008-02-26 17:05:57 +0100 |
|
+++ member.c 2008-03-19 09:18:57 +0100 |
|
@@ -28,7 +28,13 @@ |
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
*/ |
|
|
|
+#include "asterisk.h" |
|
+ |
|
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.1 $") |
|
+ |
|
#include <stdio.h> |
|
+#include "asterisk/channel.h" |
|
+#include "asterisk/app.h" |
|
#include "asterisk/autoconfig.h" |
|
#include "member.h" |
|
|
|
@@ -635,7 +641,7 @@ |
|
// setup a conference for the new member |
|
// |
|
|
|
- conf = start_conference( member ) ; |
|
+ conf = join_conference( member ) ; |
|
|
|
if ( conf == NULL ) |
|
{ |
|
@@ -690,6 +696,42 @@ |
|
|
|
// tell conference_exec we're ready for frames |
|
member->ready_for_outgoing = 1 ; |
|
+ |
|
+ // notify others about enter |
|
+ char * enter_snd = member->enter_snd; |
|
+ if (strcmp(enter_snd, "-")!=0) |
|
+ { |
|
+ // lock conference |
|
+ ast_mutex_lock( &conf->lock ); |
|
+ |
|
+ /*if (conf->membercount < 2) |
|
+ { |
|
+ enter_snd = "conf-onlyperson"; |
|
+ }*/ |
|
+ |
|
+ struct ast_conf_member *membertest = conf->memberlist; |
|
+ while (membertest != NULL) |
|
+ { |
|
+ // lock member for basic_play_sound |
|
+ ast_mutex_lock(&membertest->lock); |
|
+ |
|
+ // basic_play_sound unlock member automatically. do not mute on enter message |
|
+ if (!basic_play_sound ( membertest, enter_snd, 0 )) |
|
+ { |
|
+ ast_log(LOG_ERROR, "playing conference[%d] entry message <%s> FAILED on <%s>\n", conf->membercount, enter_snd, membertest->channel_name); |
|
+ } |
|
+ else |
|
+ { |
|
+ ast_log(LOG_NOTICE, "playing conference[%d] entry message <%s> on <%s>\n", conf->membercount, enter_snd, membertest->channel_name); |
|
+ } |
|
+ |
|
+ membertest = membertest->next; |
|
+ } |
|
+ |
|
+ // unlock conference |
|
+ ast_mutex_unlock( &conf->lock ); |
|
+ } |
|
+ |
|
while ( 42 == 42 ) |
|
{ |
|
// make sure we have a channel to process |
|
@@ -812,6 +854,17 @@ |
|
|
|
struct ast_conf_member* create_member( struct ast_channel *chan, const char* data ) |
|
{ |
|
+ char *parse; |
|
+ AST_DECLARE_APP_ARGS(args, |
|
+ AST_APP_ARG(conf_name); |
|
+ AST_APP_ARG(flags); |
|
+ AST_APP_ARG(enter_snd); |
|
+ AST_APP_ARG(leave_snd); |
|
+ AST_APP_ARG(priority); |
|
+ AST_APP_ARG(vad_prob_start); |
|
+ AST_APP_ARG(vad_prob_continue); |
|
+ ); |
|
+ |
|
// |
|
// check input |
|
// |
|
@@ -828,6 +881,11 @@ |
|
return NULL ; |
|
} |
|
|
|
+ if (ast_strlen_zero(data)) { |
|
+ ast_log(LOG_ERROR, "Conference requires an argument (conf_name[|flags[|enter_snd[|leave_snd[|priority[vad_prob_start[|vad_prob_continue]]]]]]))\n"); |
|
+ return NULL; |
|
+ } |
|
+ |
|
// |
|
// allocate memory for new conference member |
|
// |
|
@@ -846,61 +904,54 @@ |
|
// |
|
// initialize member with passed data values |
|
// |
|
+ |
|
+ parse = ast_strdupa(data); |
|
|
|
- char argstr[80] ; |
|
- char *stringp, *token ; |
|
- |
|
- // copy the passed data |
|
- strncpy( argstr, data, sizeof(argstr) - 1 ) ; |
|
- |
|
- // point to the copied data |
|
- stringp = argstr ; |
|
- |
|
- ast_log( AST_CONF_DEBUG, "attempting to parse passed params, stringp => %s\n", stringp ) ; |
|
+ AST_STANDARD_APP_ARGS(args, parse); |
|
|
|
// parse the id |
|
- if ( ( token = strsep( &stringp, "/" ) ) != NULL ) |
|
- { |
|
- member->conf_name = malloc( strlen( token ) + 1 ) ; |
|
- strcpy( member->conf_name, token ) ; |
|
- } |
|
- else |
|
+ if (ast_strlen_zero(args.conf_name)) |
|
{ |
|
ast_log( LOG_ERROR, "unable to parse member id\n" ) ; |
|
free( member ) ; |
|
return NULL ; |
|
} |
|
+ else |
|
+ member->conf_name = ast_strdup(args.conf_name); |
|
|
|
// parse the flags |
|
- if ( ( token = strsep( &stringp, "/" ) ) != NULL ) |
|
- { |
|
- member->flags = malloc( strlen( token ) + 1 ) ; |
|
- strcpy( member->flags, token ) ; |
|
- } |
|
+ if (!ast_strlen_zero(args.flags)) |
|
+ member->flags = ast_strdup(args.flags); |
|
else |
|
- { |
|
- // make member->flags something |
|
- member->flags = malloc( sizeof( char ) ) ; |
|
- memset( member->flags, 0x0, sizeof( char ) ) ; |
|
- } |
|
+ member->flags = ast_strdup(""); |
|
+ |
|
+ // parse enter sound |
|
+ if (!ast_strlen_zero(args.enter_snd)) |
|
+ member->enter_snd = ast_strdup(args.enter_snd); |
|
+ else |
|
+ member->enter_snd = ast_strdup("enter"); |
|
|
|
+ // parse leave sound |
|
+ if (!ast_strlen_zero(args.leave_snd)) |
|
+ member->leave_snd = ast_strdup(args.leave_snd); |
|
+ else |
|
+ member->leave_snd = ast_strdup("leave"); |
|
+ |
|
+ if (!ast_strlen_zero(args.priority)) |
|
// parse the priority |
|
- member->priority = ( token = strsep( &stringp, "/" ) ) != NULL |
|
- ? atoi( token ) |
|
- : 0 |
|
- ; |
|
- |
|
- // parse the vad_prob_start |
|
- member->vad_prob_start = ( token = strsep( &stringp, "/" ) ) != NULL |
|
- ? atof( token ) |
|
- : AST_CONF_PROB_START |
|
- ; |
|
- |
|
- // parse the vad_prob_continue |
|
- member->vad_prob_continue = ( token = strsep( &stringp, "/" ) ) != NULL |
|
- ? atof( token ) |
|
- : AST_CONF_PROB_CONTINUE |
|
- ; |
|
+ member->priority = atoi(args.priority); |
|
+ else |
|
+ member->priority = 0; |
|
+ |
|
+ if (!ast_strlen_zero(args.vad_prob_start)) |
|
+ member->vad_prob_start = atof(args.vad_prob_start); |
|
+ else |
|
+ member->vad_prob_start = AST_CONF_PROB_START; |
|
+ |
|
+ if (!ast_strlen_zero(args.vad_prob_continue)) |
|
+ member->vad_prob_continue = atof(args.vad_prob_continue); |
|
+ else |
|
+ member->vad_prob_continue = AST_CONF_PROB_CONTINUE; |
|
|
|
// debugging |
|
ast_log( |
|
@@ -991,9 +1042,15 @@ |
|
member->speaking_state_notify = 0 ; |
|
member->speaking_state = 0 ; |
|
member->local_speaking_state = 0; |
|
+ member->last_state_change = (struct timeval){0, 0}; |
|
member->speaker_count = 0; |
|
member->driven_member = NULL; |
|
|
|
+ member->video_broadcast_active = 0; |
|
+ member->last_video_frame_time = (struct timeval){0, 0}; |
|
+ |
|
+ member->video_started = 0; |
|
+ |
|
// linked-list pointer |
|
member->next = NULL ; |
|
|
|
@@ -1067,7 +1124,7 @@ |
|
} |
|
else |
|
{ |
|
- // allowed flags are C, c, L, l, V, D, A, C, X, R, T, t, M, S |
|
+ // allowed flags are C, c, L, l, V, D, A, C, X, R, T, t, M, S, z, o, F |
|
// mute/no_recv options |
|
switch ( flags[i] ) |
|
{ |
|
@@ -1105,6 +1162,9 @@ |
|
case 'S': |
|
member->vad_switch = 1; |
|
break; |
|
+ case 'F': |
|
+ member->force_vad_switch = 1; |
|
+ break; |
|
case 'M': |
|
member->ismoderator = 1; |
|
break; |
|
@@ -1114,6 +1174,12 @@ |
|
case 't': |
|
member->does_text = 1; |
|
break; |
|
+ case 'z': |
|
+ member->vad_linger = 1; |
|
+ break; |
|
+ case 'o': |
|
+ member->does_chat_mode = 1; |
|
+ break; |
|
|
|
//Telephone connection |
|
case 'T': |
|
@@ -1162,8 +1228,11 @@ |
|
speex_preprocess_ctl( member->dsp, SPEEX_PREPROCESS_SET_PROB_START, &member->vad_prob_start ) ; |
|
speex_preprocess_ctl( member->dsp, SPEEX_PREPROCESS_SET_PROB_CONTINUE, &member->vad_prob_continue ) ; |
|
|
|
+ speex_preprocess_ctl( member->dsp, SPEEX_PREPROCESS_GET_PROB_START, &member->vad_prob_start ) ; |
|
+ speex_preprocess_ctl( member->dsp, SPEEX_PREPROCESS_GET_PROB_CONTINUE, &member->vad_prob_continue ) ; |
|
+ |
|
ast_log( AST_CONF_DEBUG, "speech_prob_start => %f, speech_prob_continue => %f\n", |
|
- member->dsp->speech_prob_start, member->dsp->speech_prob_continue ) ; |
|
+ member->vad_prob_start, member->vad_prob_continue ) ; |
|
} |
|
} |
|
#endif |
|
@@ -1446,6 +1515,10 @@ |
|
free(member->callerid); |
|
free(member->callername); |
|
|
|
+ // free enter/leave sounds |
|
+ free(member->enter_snd); |
|
+ free(member->leave_snd); |
|
+ |
|
free( member ) ; |
|
member = NULL ; |
|
|
|
@@ -3276,3 +3349,31 @@ |
|
|
|
return; |
|
} |
|
+ |
|
+int is_video_eligible(struct ast_conf_member *member) |
|
+{ |
|
+ if ( member == NULL ) |
|
+ return 0; |
|
+ |
|
+ return !member->no_camera && !member->mute_video && !member->via_telephone; |
|
+} |
|
+ |
|
+// Member start and stop video methods |
|
+void start_video(struct ast_conf_member *member) |
|
+{ |
|
+ if ( member == NULL || member->video_started || !is_video_eligible(member)) |
|
+ return; |
|
+ |
|
+ send_text_message_to_member(member, AST_CONF_CONTROL_START_VIDEO); |
|
+ member->video_started = 1; |
|
+} |
|
+ |
|
+void stop_video(struct ast_conf_member *member) |
|
+{ |
|
+ if ( member == NULL || !member->video_started ) |
|
+ return; |
|
+ |
|
+ send_text_message_to_member(member, AST_CONF_CONTROL_STOP_VIDEO); |
|
+ member->video_started = 0; |
|
+ |
|
+} |
|
Index: member.h |
|
--- member.h.orig 2008-02-26 17:05:57 +0100 |
|
+++ member.h 2008-03-19 09:18:57 +0100 |
|
@@ -151,6 +151,10 @@ |
|
|
|
// switch video by VAD? |
|
short vad_switch; |
|
+ // do a VAD switch even if video is not enabled? |
|
+ short force_vad_switch; |
|
+ // if member is current speaker, video will stay on it when it becomes silent |
|
+ short vad_linger; |
|
// switch by dtmf? |
|
short dtmf_switch; |
|
// relay dtmf to manager? |
|
@@ -159,6 +163,8 @@ |
|
short first_frame_received; |
|
// does text messages? |
|
short does_text; |
|
+ // conference does chat mode (1 on 1 video when two members in conference) |
|
+ short does_chat_mode; |
|
|
|
|
|
// time we last dropped a frame |
|
@@ -177,6 +183,15 @@ |
|
struct timeval last_state_change; |
|
int speaker_count; // Number of drivers (including this member) that are speaking |
|
|
|
+ // Stuff used to determine video broadcast state |
|
+ // This member's video is sent out to at least one member of the conference |
|
+ short video_broadcast_active; |
|
+ // Time when we last sent out a video frame from this member |
|
+ struct timeval last_video_frame_time; |
|
+ |
|
+ // Is the member supposed to be transmitting video? |
|
+ short video_started; |
|
+ |
|
// pointer to next member in single-linked list |
|
struct ast_conf_member* next ; |
|
|
|
@@ -237,6 +252,10 @@ |
|
// For playing sounds |
|
struct ast_conf_soundq *soundq; |
|
struct ast_conf_soundq *videoq; |
|
+ |
|
+ // Enter/leave sounds |
|
+ char * enter_snd; |
|
+ char * leave_snd; |
|
|
|
// Pointer to another member that will be driven from this member's audio |
|
struct ast_conf_member *driven_member; |
|
@@ -295,6 +314,12 @@ |
|
struct ast_conf_member *member, |
|
struct conf_frame *send_frames); |
|
|
|
+int is_video_eligible(struct ast_conf_member *member); |
|
+ |
|
+// Member start and stop video methods |
|
+void start_video(struct ast_conf_member *member); |
|
+void stop_video(struct ast_conf_member *member); |
|
+ |
|
// |
|
// packer functions |
|
//
|
|
|