diff --git a/apps/app_meetme.c b/apps/app_meetme.c index 81b1cabbe7910f9506327f8f3ad0474eabdc595b..cb7778d62bcd4297fcb4c1c4d33de3dea0a26464 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -63,6 +63,120 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/translate.h" #include "asterisk/ulaw.h" +#include "enter.h" +#include "leave.h" + +LOCAL_USER_DECL; + +#define CONFIG_FILE_NAME "meetme.conf" + +/*! each buffer is 20ms, so this is 640ms total */ +#define DEFAULT_AUDIO_BUFFERS 32 + +enum { + ADMINFLAG_MUTED = (1 << 1), /*!< User is muted */ + ADMINFLAG_KICKME = (1 << 2) /*!< User has been kicked */ +}; + +#define MEETME_DELAYDETECTTALK 300 +#define MEETME_DELAYDETECTENDTALK 1000 + +#define AST_FRAME_BITS 32 + +enum volume_action { + VOL_UP, + VOL_DOWN +}; + +enum entrance_sound { + ENTER, + LEAVE +}; + +enum recording_state { + MEETME_RECORD_OFF, + MEETME_RECORD_STARTED, + MEETME_RECORD_ACTIVE, + MEETME_RECORD_TERMINATE +}; + +#define CONF_SIZE 320 + +enum { + /*! user has admin access on the conference */ + CONFFLAG_ADMIN = (1 << 0), + /*! If set the user can only receive audio from the conference */ + CONFFLAG_MONITOR = (1 << 1), + /*! If set asterisk will exit conference when '#' is pressed */ + CONFFLAG_POUNDEXIT = (1 << 2), + /*! If set asterisk will provide a menu to the user when '*' is pressed */ + CONFFLAG_STARMENU = (1 << 3), + /*! If set the use can only send audio to the conference */ + CONFFLAG_TALKER = (1 << 4), + /*! If set there will be no enter or leave sounds */ + CONFFLAG_QUIET = (1 << 5), + /*! If set, when user joins the conference, they will be told the number + * of users that are already in */ + CONFFLAG_ANNOUNCEUSERCOUNT = (1 << 6), + /*! Set to run AGI Script in Background */ + CONFFLAG_AGI = (1 << 7), + /*! Set to have music on hold when user is alone in conference */ + CONFFLAG_MOH = (1 << 8), + /*! If set the MeetMe will return if all marked with this flag left */ + CONFFLAG_MARKEDEXIT = (1 << 9), + /*! If set, the MeetMe will wait until a marked user enters */ + CONFFLAG_WAITMARKED = (1 << 10), + /*! If set, the MeetMe will exit to the specified context */ + CONFFLAG_EXIT_CONTEXT = (1 << 11), + /*! If set, the user will be marked */ + CONFFLAG_MARKEDUSER = (1 << 12), + /*! If set, user will be ask record name on entry of conference */ + CONFFLAG_INTROUSER = (1 << 13), + /*! If set, the MeetMe will be recorded */ + CONFFLAG_RECORDCONF = (1<< 14), + /*! If set, the user will be monitored if the user is talking or not */ + CONFFLAG_MONITORTALKER = (1 << 15), + CONFFLAG_DYNAMIC = (1 << 16), + CONFFLAG_DYNAMICPIN = (1 << 17), + CONFFLAG_EMPTY = (1 << 18), + CONFFLAG_EMPTYNOPIN = (1 << 19), + CONFFLAG_ALWAYSPROMPT = (1 << 20), + /*! If set, treats talking users as muted users */ + CONFFLAG_OPTIMIZETALKER = (1 << 21), + /*! If set, won't speak the extra prompt when the first person + * enters the conference */ + CONFFLAG_NOONLYPERSON = (1 << 22), + CONFFLAG_INTROUSERNOREVIEW = (1 << 23) + /*! If set, user will be asked to record name on entry of conference + * without review */ +}; + +AST_APP_OPTIONS(meetme_opts, { + AST_APP_OPTION('A', CONFFLAG_MARKEDUSER ), + AST_APP_OPTION('a', CONFFLAG_ADMIN ), + AST_APP_OPTION('b', CONFFLAG_AGI ), + AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT ), + AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN ), + AST_APP_OPTION('d', CONFFLAG_DYNAMIC ), + AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN ), + AST_APP_OPTION('e', CONFFLAG_EMPTY ), + AST_APP_OPTION('i', CONFFLAG_INTROUSER ), + AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW ), + AST_APP_OPTION('M', CONFFLAG_MOH ), + AST_APP_OPTION('m', CONFFLAG_MONITOR ), + AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER ), + AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT ), + AST_APP_OPTION('p', CONFFLAG_POUNDEXIT ), + AST_APP_OPTION('q', CONFFLAG_QUIET ), + AST_APP_OPTION('r', CONFFLAG_RECORDCONF ), + AST_APP_OPTION('s', CONFFLAG_STARMENU ), + AST_APP_OPTION('T', CONFFLAG_MONITORTALKER ), + AST_APP_OPTION('t', CONFFLAG_TALKER ), + AST_APP_OPTION('w', CONFFLAG_WAITMARKED ), + AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ), + AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT ), + AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON ), +}); static const char *app = "MeetMe"; static const char *app2 = "MeetMeCount"; @@ -137,31 +251,27 @@ static const char *descrip3 = " 'N' -- Mute entire conference (except admin)\n" ""; -#define CONFIG_FILE_NAME "meetme.conf" - -LOCAL_USER_DECL; - struct ast_conference { - ast_mutex_t playlock; /* Conference specific lock (players) */ - ast_mutex_t listenlock; /* Conference specific lock (listeners) */ - char confno[AST_MAX_EXTENSION]; /* Conference */ - struct ast_channel *chan; /* Announcements channel */ - struct ast_channel *lchan; /* Listen/Record channel */ - int fd; /* Announcements fd */ - int zapconf; /* Zaptel Conf # */ - int users; /* Number of active users */ - int markedusers; /* Number of marked users */ - time_t start; /* Start time (s) */ - int refcount; /* reference count of usage */ - unsigned int recording:2; /* recording status */ - unsigned int isdynamic:1; /* Created on the fly? */ - unsigned int locked:1; /* Is the conference locked? */ - pthread_t recordthread; /* thread for recording */ - pthread_attr_t attr; /* thread attribute */ - const char *recordingfilename; /* Filename to record the Conference into */ - const char *recordingformat; /* Format to record the Conference in */ - char pin[AST_MAX_EXTENSION]; /* If protected by a PIN */ - char pinadmin[AST_MAX_EXTENSION]; /* If protected by a admin PIN */ + ast_mutex_t playlock; /*!< Conference specific lock (players) */ + ast_mutex_t listenlock; /*!< Conference specific lock (listeners) */ + char confno[AST_MAX_EXTENSION]; /*!< Conference */ + struct ast_channel *chan; /*!< Announcements channel */ + struct ast_channel *lchan; /*!< Listen/Record channel */ + int fd; /*!< Announcements fd */ + int zapconf; /*!< Zaptel Conf # */ + int users; /*!< Number of active users */ + int markedusers; /*!< Number of marked users */ + time_t start; /*!< Start time (s) */ + int refcount; /*!< reference count of usage */ + enum recording_state recording:2; /*!< recording status */ + unsigned int isdynamic:1; /*!< Created on the fly? */ + unsigned int locked:1; /*!< Is the conference locked? */ + pthread_t recordthread; /*!< thread for recording */ + pthread_attr_t attr; /*!< thread attribute */ + const char *recordingfilename; /*!< Filename to record the Conference into */ + const char *recordingformat; /*!< Format to record the Conference in */ + char pin[AST_MAX_EXTENSION]; /*!< If protected by a PIN */ + char pinadmin[AST_MAX_EXTENSION]; /*!< If protected by a admin PIN */ struct ast_frame *transframe[32]; struct ast_frame *origframe; struct ast_trans_pvt *transpath[32]; @@ -172,112 +282,53 @@ struct ast_conference { static AST_LIST_HEAD_STATIC(confs, ast_conference); struct volume { - int desired; /* Desired volume adjustment */ - int actual; /* Actual volume adjustment (for channels that can't adjust) */ + int desired; /*!< Desired volume adjustment */ + int actual; /*!< Actual volume adjustment (for channels that can't adjust) */ }; struct ast_conf_user { - int user_no; /* User Number */ - int userflags; /* Flags as set in the conference */ - int adminflags; /* Flags set by the Admin */ - struct ast_channel *chan; /* Connected channel */ - int talking; /* Is user talking */ - int zapchannel; /* Is a Zaptel channel */ - char usrvalue[50]; /* Custom User Value */ - char namerecloc[AST_MAX_EXTENSION]; /* Name Recorded file Location */ - time_t jointime; /* Time the user joined the conference */ + int user_no; /*!< User Number */ + int userflags; /*!< Flags as set in the conference */ + int adminflags; /*!< Flags set by the Admin */ + struct ast_channel *chan; /*!< Connected channel */ + int talking; /*!< Is user talking */ + int zapchannel; /*!< Is a Zaptel channel */ + char usrvalue[50]; /*!< Custom User Value */ + char namerecloc[AST_MAX_EXTENSION]; /*!< Name Recorded file Location */ + time_t jointime; /*!< Time the user joined the conference */ struct volume talk; struct volume listen; AST_LIST_ENTRY(ast_conf_user) list; }; -static int audio_buffers; /* The number of audio buffers to be allocated on pseudo channels - when in a conference - */ - -#define DEFAULT_AUDIO_BUFFERS 32 /* each buffer is 20ms, so this is 640ms total */ - -#define ADMINFLAG_MUTED (1 << 1) /* User is muted */ -#define ADMINFLAG_KICKME (1 << 2) /* User is kicked */ -#define MEETME_DELAYDETECTTALK 300 -#define MEETME_DELAYDETECTENDTALK 1000 - -#define AST_FRAME_BITS 32 +/*! The number of audio buffers to be allocated on pseudo channels + * when in a conference */ +static int audio_buffers; -enum volume_action { - VOL_UP, - VOL_DOWN, +/*! Map 'volume' levels from -5 through +5 into + * decibel (dB) settings for channel drivers + * Note: these are not a straight linear-to-dB + * conversion... the numbers have been modified + * to give the user a better level of adjustability + */ +static signed char gain_map[] = { + -15, + -13, + -10, + -6, + 0, + 0, + 0, + 6, + 10, + 13, + 15, }; -static int admin_exec(struct ast_channel *chan, void *data); +static int admin_exec(struct ast_channel *chan, void *data); static void *recordthread(void *args); -#include "enter.h" -#include "leave.h" - -#define ENTER 0 -#define LEAVE 1 - -#define MEETME_RECORD_OFF 0 -#define MEETME_RECORD_STARTED 1 -#define MEETME_RECORD_ACTIVE 2 -#define MEETME_RECORD_TERMINATE 3 - -#define CONF_SIZE 320 - -#define CONFFLAG_ADMIN (1 << 1) /* If set the user has admin access on the conference */ -#define CONFFLAG_MONITOR (1 << 2) /* If set the user can only receive audio from the conference */ -#define CONFFLAG_POUNDEXIT (1 << 3) /* If set asterisk will exit conference when '#' is pressed */ -#define CONFFLAG_STARMENU (1 << 4) /* If set asterisk will provide a menu to the user when '*' is pressed */ -#define CONFFLAG_TALKER (1 << 5) /* If set the use can only send audio to the conference */ -#define CONFFLAG_QUIET (1 << 6) /* If set there will be no enter or leave sounds */ -#define CONFFLAG_ANNOUNCEUSERCOUNT (1 << 7) /* If set, when user joins the conference, they will be told the number of users that are already in */ -#define CONFFLAG_AGI (1 << 8) /* Set to run AGI Script in Background */ -#define CONFFLAG_MOH (1 << 9) /* Set to have music on hold when user is alone in conference */ -#define CONFFLAG_MARKEDEXIT (1 << 10) /* If set the MeetMe will return if all marked with this flag left */ -#define CONFFLAG_WAITMARKED (1 << 11) /* If set, the MeetMe will wait until a marked user enters */ -#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 MeetMe will be recorded */ -#define CONFFLAG_MONITORTALKER (1 << 16) /* If set, the user will be monitored if the user is talking or not */ -#define CONFFLAG_DYNAMIC (1 << 17) -#define CONFFLAG_DYNAMICPIN (1 << 18) -#define CONFFLAG_EMPTY (1 << 19) -#define CONFFLAG_EMPTYNOPIN (1 << 20) -#define CONFFLAG_ALWAYSPROMPT (1 << 21) -#define CONFFLAG_OPTIMIZETALKER (1 << 22) /* If set, treats talking users as muted users */ -#define CONFFLAG_NOONLYPERSON (1 << 23) /* If set, won't speak the extra prompt when the first person enters the conference */ -#define CONFFLAG_INTROUSERNOREVIEW (1 << 24) /* If set, user will be asked to record name on entry of conference without review */ - -AST_APP_OPTIONS(meetme_opts, { - AST_APP_OPTION('A', CONFFLAG_MARKEDUSER ), - AST_APP_OPTION('a', CONFFLAG_ADMIN ), - AST_APP_OPTION('b', CONFFLAG_AGI ), - AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT ), - AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN ), - AST_APP_OPTION('d', CONFFLAG_DYNAMIC ), - AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN ), - AST_APP_OPTION('e', CONFFLAG_EMPTY ), - AST_APP_OPTION('i', CONFFLAG_INTROUSER ), - AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW ), - AST_APP_OPTION('M', CONFFLAG_MOH ), - AST_APP_OPTION('m', CONFFLAG_MONITOR ), - AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER ), - AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT ), - AST_APP_OPTION('p', CONFFLAG_POUNDEXIT ), - AST_APP_OPTION('q', CONFFLAG_QUIET ), - AST_APP_OPTION('r', CONFFLAG_RECORDCONF ), - AST_APP_OPTION('s', CONFFLAG_STARMENU ), - AST_APP_OPTION('T', CONFFLAG_MONITORTALKER ), - AST_APP_OPTION('t', CONFFLAG_TALKER ), - AST_APP_OPTION('w', CONFFLAG_WAITMARKED ), - AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ), - AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT ), - AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON ), -}); - static char *istalking(int x) { if (x > 0) @@ -315,26 +366,6 @@ static int careful_write(int fd, unsigned char *data, int len, int block) return 0; } -/* Map 'volume' levels from -5 through +5 into - decibel (dB) settings for channel drivers - Note: these are not a straight linear-to-dB - conversion... the numbers have been modified - to give the user a better level of adjustability -*/ -static signed char gain_map[] = { - -15, - -13, - -10, - -6, - 0, - 0, - 0, - 6, - 10, - 13, - 15, -}; - static int set_talk_volume(struct ast_conf_user *user, int volume) { signed char gain_adjust; @@ -426,7 +457,7 @@ static void reset_volumes(struct ast_conf_user *user) ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); } -static void conf_play(struct ast_channel *chan, struct ast_conference *conf, int sound) +static void conf_play(struct ast_channel *chan, struct ast_conference *conf, enum entrance_sound sound) { unsigned char *data; int len;