Index: apps/app_meetme.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_meetme.c,v retrieving revision 1.70 diff -u -r1.70 app_meetme.c --- apps/app_meetme.c 14 Jan 2005 05:10:00 -0000 1.70 +++ apps/app_meetme.c 21 Jan 2005 13:43:32 -0000 @@ -74,6 +74,9 @@ " 'M' -- enable music on hold when the conference has a single caller\n" " 'x' -- close the conference when last marked user exits\n" " 'w' -- wait until the marked user enters the conference\n" +" 'r' -- Record conference (records as ${MEETME_RECORDINGFILE}\n" +" using format ${MEETME_RECORDINGFORMAT}). Default filename is\n" +" meetme-conf-rec-$CONFNO-$UNIQUEID and default format is wav\n" " 'b' -- run AGI script specified in ${MEETME_AGI_BACKGROUND}\n" " Default: conf-background.agi\n" " (Note: This does not work with non-Zap channels in the same conference)\n" @@ -116,6 +119,10 @@ time_t start; /* Start time (s) */ int isdynamic; /* Created on the fly? */ int locked; /* Is the conference locked? */ + int recording; + pthread_t recordthread; + char *recordingfilename; + char *recordingformat; char pin[AST_MAX_EXTENSION]; /* If protected by a PIN */ struct ast_conference *next; } *confs; @@ -139,10 +146,15 @@ AST_MUTEX_DEFINE_STATIC(conflock); static int admin_exec(struct ast_channel *chan, void *data); +void *recordthread(void *args); #include "enter.h" #include "leave.h" +#define MEETME_RECORD_OFF 0 +#define MEETME_RECORD_ACTIVE 1 +#define MEETME_RECORD_TERMINATE 2 + #define ENTER 0 #define LEAVE 1 @@ -162,6 +174,7 @@ #define CONFFLAG_EXIT_CONTEXT (1 << 12) /* If set, the MeetMe will exit to the specified context */ #define CONFFLAG_MARKEDUSER (1 << 13) /* If set, the user will be marked */ #define CONFFLAG_INTROUSER (1 << 14) /* If set, user will be ask record name on entry of conference */ +#define CONFFLAG_RECORDCONF (1 << 15) /* If set, the conference will be recorded */ static int careful_write(int fd, unsigned char *data, int len) { @@ -227,6 +240,7 @@ strncpy(cnf->confno, confno, sizeof(cnf->confno) - 1); strncpy(cnf->pin, pin, sizeof(cnf->pin) - 1); cnf->markedusers = 0; + cnf->recording = MEETME_RECORD_OFF; cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL); if (cnf->chan) { cnf->fd = cnf->chan->fds[0]; /* for use by conf_play() */ @@ -244,7 +258,7 @@ /* Setup a new zap conference */ ztc.chan = 0; ztc.confno = -1; - ztc.confmode = ZT_CONF_CONFANN; + ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON; if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) { ast_log(LOG_WARNING, "Error setting conference\n"); if (cnf->chan) @@ -528,6 +542,7 @@ char *agifiledefault = "conf-background.agi"; char meetmesecs[30] = ""; char exitcontext[AST_MAX_EXTENSION] = ""; + char recordingtmp[AST_MAX_EXTENSION] = ""; int dtmf; ZT_BUFFERINFO bi; @@ -540,6 +555,20 @@ } memset(user, 0, sizeof(struct ast_conf_user)); + if (confflags & CONFFLAG_RECORDCONF && conf->recording != MEETME_RECORD_ACTIVE) { + conf->recordingfilename = pbx_builtin_getvar_helper(chan,"MEETME_RECORDINGFILE"); + conf->recordingformat = pbx_builtin_getvar_helper(chan,"MEETME_RECORDINGFORMAT"); + if (!conf->recordingfilename) { + snprintf(recordingtmp,sizeof(recordingtmp),"meetme-conf-rec-%s-%s",conf->confno,chan->uniqueid); + conf->recordingfilename = ast_strdupa(recordingtmp); + } + if (!conf->recordingformat) { + snprintf(recordingtmp,sizeof(recordingtmp), "wav"); + conf->recordingformat = ast_strdupa(recordingtmp); + } + pthread_create (&conf->recordthread, NULL, recordthread, conf); + } + user->user_no = 0; /* User number 0 means starting up user! (dead - not in the list!) */ time(&user->jointime); @@ -1070,6 +1099,17 @@ } if (!cur) ast_log(LOG_WARNING, "Conference not found\n"); + + if (conf->recording == MEETME_RECORD_ACTIVE) { + conf->recording = MEETME_RECORD_TERMINATE; + ast_mutex_unlock(&conflock); + while (1) { + ast_mutex_lock(&conflock); + if (conf->recording == MEETME_RECORD_OFF) + break; + ast_mutex_unlock(&conflock); + } + } if (conf->chan) ast_hangup(conf->chan); else @@ -1263,6 +1303,8 @@ if (inflags) { if (strchr(inflags, 'a')) confflags |= CONFFLAG_ADMIN; + if (strchr(inflags, 'r')) + confflags |= CONFFLAG_RECORDCONF; if (strchr(inflags, 'i')) confflags |= CONFFLAG_INTROUSER; if (strchr(inflags, 'm')) @@ -1612,6 +1654,49 @@ ast_mutex_unlock(&conflock); return 0; } + +void *recordthread(void *args) { + struct ast_conference *cnf; + struct ast_frame *f=NULL; + int flags; + struct ast_filestream *s; + int res=0; + + cnf = (struct ast_conference *) args; + ast_stopstream(cnf->chan); + flags = O_CREAT|O_TRUNC|O_WRONLY; + s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags , 0, 0644); + + if (s) { + cnf->recording = MEETME_RECORD_ACTIVE; + while (ast_waitfor(cnf->chan, -1) > -1) { + f = ast_read(cnf->chan); + if (!f) { + res = -1; + break; + } + if (f->frametype == AST_FRAME_VOICE) { + res = ast_writestream(s, f); + if (res) { + break; + } + } + ast_frfree(f); + if (cnf->recording == MEETME_RECORD_TERMINATE) { + ast_mutex_lock(&conflock); + ast_mutex_unlock(&conflock); + break; + + } + + } + cnf->recording = MEETME_RECORD_OFF; + ast_closestream(s); + } + + pthread_exit(0); +} + int unload_module(void) {