diff --git a/Makefile b/Makefile index dfc53df..0d59931 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ SHAREDOS=chan_capi.so OBJECTS=chan_capi.o chan_capi_utils.o chan_capi_rtp.o chan_capi_command.o xlaw.o dlist.o \ chan_capi_qsig_core.o chan_capi_qsig_ecma.o chan_capi_qsig_asn197ade.o \ chan_capi_qsig_asn197no.o chan_capi_supplementary.o chan_capi_chat.o \ - chan_capi_mwi.o chan_capi_cli.o + chan_capi_mwi.o chan_capi_cli.o chan_capi_ami.o ifeq (${USE_OWN_LIBCAPI},yes) OBJECTS += libcapi20/convert.o libcapi20/capi20.o libcapi20/capifunc.o diff --git a/chan_capi.c b/chan_capi.c index 534ceab..726632f 100644 --- a/chan_capi.c +++ b/chan_capi.c @@ -56,6 +56,7 @@ struct _diva_streaming_vector* vind; #endif #include "chan_capi_mwi.h" #include "chan_capi_cli.h" +#include "chan_capi_ami.h" /* #define CC_VERSION "x.y.z" */ #define CC_VERSION "$Revision$" @@ -7283,7 +7284,11 @@ static int pbx_capicommand_exec(struct ast_channel *chan, void *data) int pbx_capi_cli_exec_capicommand(struct ast_channel *chan, const char *data) { +#ifdef CC_AST_HAS_CONST_CHAR_IN_REGAPPL return (pbx_capicommand_exec(chan, data)); +#else + return (pbx_capicommand_exec(chan, (void*)data)); +#endif } /* @@ -8528,6 +8533,7 @@ int unload_module(void) ast_unregister_application(commandapp); + pbx_capi_ami_unregister(); pbx_capi_cli_unregister(); #ifdef CC_AST_HAS_VERSION_1_4 @@ -8642,6 +8648,7 @@ int load_module(void) } pbx_capi_cli_register(); + pbx_capi_ami_register(); ast_register_application(commandapp, pbx_capicommand_exec, commandsynopsis, commandtdesc); diff --git a/chan_capi_ami.c b/chan_capi_ami.c new file mode 100644 index 0000000..1d22d3c --- /dev/null +++ b/chan_capi_ami.c @@ -0,0 +1,175 @@ +/* + * + Copyright (c) Dialogic (R) 2009 - 2010 + * + This source file is supplied for the use with + Eicon Networks range of DIVA Server Adapters. + * + Dialogic (R) File Revision : 1.9 + * + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + * + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + * + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Based on apps/app_meetme.c + * + */ +#ifdef CC_AST_HAS_VERSION_1_6 +#include "chan_capi_platform.h" +#include "chan_capi20.h" +#include "chan_capi.h" +#include "chan_capi_qsig.h" +#include "chan_capi_utils.h" +#include "chan_capi_chat.h" +#include "asterisk/manager.h" + + +#define CC_AMI_ACTION_NAME_CHATLIST "CapichatList" + +/* + LOCALS + */ +static int pbx_capi_ami_capichat_list(struct mansession *s, const struct message *m); +static int capiChatListRegistered; + +static char mandescr_capichatlist[] = +"Description: Lists all users in a particular CapiChat conference.\n" +"CapichatList will follow as separate events, followed by a final event called\n" +"CapichatListComplete.\n" +"Variables:\n" +" *ActionId: \n" +" *Conference: \n"; + + +void pbx_capi_ami_register(void) +{ + capiChatListRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATLIST, + EVENT_FLAG_REPORTING, + pbx_capi_ami_capichat_list, + "List participants in a conference", + mandescr_capichatlist) == 0; +} + +void pbx_capi_ami_unregister(void) +{ + if (capiChatListRegistered != 0) + ast_manager_unregister(CC_AMI_ACTION_NAME_CHATLIST); +} + +static int pbx_capi_ami_capichat_list(struct mansession *s, const struct message *m) { + const char *actionid = astman_get_header(m, "ActionID"); + const char *conference = astman_get_header(m, "Conference"); + char idText[80] = ""; + int total = 0; + const struct capichat_s *capiChatRoom; + + if (!ast_strlen_zero(actionid)) + snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); + + if (pbx_capi_chat_get_room_c(NULL) == NULL) { + astman_send_error(s, m, "No active conferences."); + return 0; + } + + astman_send_listack(s, m, CC_AMI_ACTION_NAME_CHATLIST" user list will follow", "start"); + + /* Find the right conference */ + pbx_capi_lock_chat_rooms(); + + for (capiChatRoom = pbx_capi_chat_get_room_c(NULL), total = 0; + capiChatRoom != NULL; + capiChatRoom = pbx_capi_chat_get_room_c(capiChatRoom)) { + const char* roomName = pbx_capi_chat_get_room_name(capiChatRoom); + /* If we ask for one particular, and this isn't it, skip it */ + if (!ast_strlen_zero(conference) && strcmp(roomName, conference)) + continue; + + { + unsigned int roomNumber = pbx_capi_chat_get_room_number(capiChatRoom); + struct ast_channel *c = pbx_capi_chat_get_room_channel(capiChatRoom); + int isMemberOperator = pbx_capi_chat_is_member_operator(capiChatRoom); + int isCapiChatRoomMuted = pbx_capi_chat_is_room_muted(capiChatRoom); + int isCapiChatMemberMuted = pbx_capi_chat_is_member_muted(capiChatRoom); + int isCapiChatMemberListener = pbx_capi_chat_is_member_listener(capiChatRoom); + int isCapiChatMostRecentMember = pbx_capi_chat_is_most_recent_user(capiChatRoom); + const char* mutedVisualName = "No"; + char* cidVisual; + char* callerNameVisual; + + ast_channel_lock(c); + cidVisual = ast_strdup(pbx_capi_get_cid (c, "")); + callerNameVisual = ast_strdup(pbx_capi_get_callername (c, "")); + ast_channel_unlock(c); + + if (isCapiChatMemberListener || isCapiChatRoomMuted || isCapiChatMemberMuted) { + if (isMemberOperator) { + if (isCapiChatMemberMuted) + mutedVisualName = "By self"; + } else if (isCapiChatMemberListener || isCapiChatRoomMuted) { + mutedVisualName = "By admin"; + } else { + mutedVisualName = "By self"; + } + } + + total++; + astman_append(s, + "Event: "CC_AMI_ACTION_NAME_CHATLIST"\r\n" + "%s" + "Conference: %s/%u\r\n" + "UserNumber: %d\r\n" + "CallerIDNum: %s\r\n" + "CallerIDName: %s\r\n" + "Channel: %s\r\n" + "Admin: %s\r\n" + "Role: %s\r\n" + "MarkedUser: %s\r\n" + "Muted: %s\r\n" + "Talking: %s\r\n" + "\r\n", + idText, + roomName, + roomNumber, + total, + (cidVisual != 0) ? cidVisual : "?", + (callerNameVisual != 0) ? callerNameVisual : "?", + c->name, + (isMemberOperator != 0) ? "Yes" : "No", + (isCapiChatMemberListener != 0) ? "Listen only" : "Talk and listen" /* "Talk only" */, + (isCapiChatMostRecentMember != 0) ? "Yes" : "No", + mutedVisualName, + /* "Yes" "No" */ "Not monitored"); + + ast_free (cidVisual); + ast_free (callerNameVisual); + } + } + pbx_capi_unlock_chat_rooms(); + /* Send final confirmation */ + astman_append(s, + "Event: "CC_AMI_ACTION_NAME_CHATLIST"Complete\r\n" + "EventList: Complete\r\n" + "ListItems: %d\r\n" + "%s" + "\r\n", total, idText); + return 0; +} +#else +void pbx_capi_ami_register(void) +{ +} +void pbx_capi_ami_unregister(void) +{ +} +#endif diff --git a/chan_capi_ami.h b/chan_capi_ami.h new file mode 100644 index 0000000..04ffb66 --- /dev/null +++ b/chan_capi_ami.h @@ -0,0 +1,9 @@ +#ifndef __CC_AMI_INTERFACE_H__ +#define __CC_AMI_INTERFACE_H__ + +void pbx_capi_ami_register(void); +void pbx_capi_ami_unregister(void); + + +#endif + diff --git a/chan_capi_chat.c b/chan_capi_chat.c index 479ade6..6619a2e 100644 --- a/chan_capi_chat.c +++ b/chan_capi_chat.c @@ -1036,7 +1036,7 @@ int pbxcli_capi_chatinfo(int fd, int argc, char *argv[]) ast_channel_lock(c); ast_cli(fd, "%3d %-12s%-30s\"%s\" <%s>\n", room->number, room->name, c->name, - pbx_capi_get_callername (c), pbx_capi_get_cid (c)); + pbx_capi_get_callername (c, ""), pbx_capi_get_cid (c, "")); ast_channel_unlock(c); } room = room->next; @@ -1156,4 +1156,140 @@ int pbx_capi_chat_remove_user(const char* roomName, const char* memberName) return ret; } +/*! + * \brief Chat Room enumerator + * + * \note called unter protection of chat_lock + */ +const struct capichat_s *pbx_capi_chat_get_room_c(const struct capichat_s * room) +{ + if (room == 0) + return chat_list; + + return room->next; +} + +/*! + * \brief Get room name + * + * \note called unter protection of chat_lock + */ +const char* pbx_capi_chat_get_room_name(const struct capichat_s * room) +{ + return room->name; +} + +/*! + * \brief Get room number + * + * \note called unter protection of chat_lock + */ +unsigned int pbx_capi_chat_get_room_number(const struct capichat_s * room) +{ + return room->number; +} + +/*! + * \brief Get number of members in room + * + * \note called unter protection of chat_lock + */ +unsigned int pbx_capi_chat_get_room_members(const struct capichat_s * room) +{ + return room->active; +} + +/*! + * \brief Is entire room muted + * + * \note called unter protection of chat_lock + */ +int pbx_capi_chat_is_room_muted(const struct capichat_s * room) +{ + return (room->room_mode == RoomModeMuted); +} + +/*! + * \brief Get room channel + * + * \note called unter protection of chat_lock + */ +struct ast_channel *pbx_capi_chat_get_room_channel(const struct capichat_s * room) +{ + struct ast_channel *c = NULL; + + if ((room != NULL) && (room->i != NULL)) { + c = (room->i->owner != 0) ? room->i->owner : room->i->used; + } + + return (c); +} + +/*! + * \brief Is user operator + * + * \note called unter protection of chat_lock + */ +int pbx_capi_chat_is_member_operator(const struct capichat_s * room) +{ + return (room->room_member_type == RoomMemberOperator); +} + +/*! + * \brief Is member muted + * + * \note called unter protection of chat_lock + */ +int pbx_capi_chat_is_member_muted(const struct capichat_s * room) +{ + int isMuted = 0; + + isMuted |= ((room->i != 0) && + (room->i->divaDigitalTxGain == 0x100)); + isMuted |= ((room->i != 0 ) && + (room->i->line_plci != 0) && + (room->i->line_plci->divaDigitalTxGain == 0x100)); + isMuted |= ((room->i != 0 ) && + (room->i->data_plci != 0) && + (room->i->data_plci->divaDigitalTxGain == 0x100)); + + return (isMuted); +} + +/*! + * \brief Is user listener + * + * \note called unter protection of chat_lock + */ +int pbx_capi_chat_is_member_listener(const struct capichat_s * room) +{ + return (room->room_member_type == RoomMemberListener); +} + +/*! + * \brief Is most recent user + * + * \note called unter protection of chat_lock + */ +int pbx_capi_chat_is_most_recent_user(const struct capichat_s * room) +{ + return ((room->info & PBX_CHAT_MEMBER_INFO_RECENT) != 0); +} + + +/*! + * \brief Lock chat list + */ +void pbx_capi_lock_chat_rooms(void) +{ + cc_mutex_lock(&chat_lock); +} + +/*! + * \brief Unlock chat list + */ +void pbx_capi_unlock_chat_rooms(void) +{ + cc_mutex_unlock(&chat_lock); +} diff --git a/chan_capi_chat.h b/chan_capi_chat.h index 6106919..10502d3 100644 --- a/chan_capi_chat.h +++ b/chan_capi_chat.h @@ -28,4 +28,19 @@ extern int pbx_capi_chat_mute(struct ast_channel *c, char *param); extern int pbx_capi_chat_play(struct ast_channel *c, char *param); int pbx_capi_chat_remove_user(const char* room, const char* name); +struct capichat_s; +const struct capichat_s *pbx_capi_chat_get_room_c(const struct capichat_s * room); +const char* pbx_capi_chat_get_room_name(const struct capichat_s * room); +unsigned int pbx_capi_chat_get_room_number(const struct capichat_s * room); +unsigned int pbx_capi_chat_get_room_members(const struct capichat_s * room); +struct ast_channel *pbx_capi_chat_get_room_channel(const struct capichat_s * room); +int pbx_capi_chat_is_member_operator(const struct capichat_s * room); +int pbx_capi_chat_is_room_muted(const struct capichat_s * room); +int pbx_capi_chat_is_member_muted(const struct capichat_s * room); +int pbx_capi_chat_is_member_listener(const struct capichat_s * room); +int pbx_capi_chat_is_most_recent_user(const struct capichat_s * room); + +void pbx_capi_lock_chat_rooms(void); +void pbx_capi_unlock_chat_rooms(void); + #endif diff --git a/chan_capi_qsig_core.c b/chan_capi_qsig_core.c index a276043..e0e41b6 100644 --- a/chan_capi_qsig_core.c +++ b/chan_capi_qsig_core.c @@ -1003,7 +1003,7 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i } cc_qsig_build_facility_struct(data, &dataidx, protocolvar, APDUINTERPRETATION_IGNORE, &nfe); - cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0, pbx_capi_get_connectedname (i->owner)); + cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0, pbx_capi_get_connectedname (i->owner, "")); cc_qsig_add_invoke(data, &dataidx, &invoke, i); if (add_externalinfo) { diff --git a/chan_capi_utils.c b/chan_capi_utils.c index 9a14e7e..cf7ccd7 100644 --- a/chan_capi_utils.c +++ b/chan_capi_utils.c @@ -1584,12 +1584,12 @@ int capi_write_frame(struct capi_pvt *i, struct ast_frame *f) ast_channel_lock(chan) to be held while while accessing returned pointer */ -const char* pbx_capi_get_cid(struct ast_channel* c) +const char* pbx_capi_get_cid(const struct ast_channel* c, const char* notAvailableVisual) { const char* cid; #ifdef CC_AST_HAS_VERSION_1_8 - cid = S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""); + cid = S_COR(c->caller.id.number.valid, c->caller.id.number.str, notAvailableVisual); #else cid = c->cid.cid_num; #endif @@ -1601,14 +1601,14 @@ const char* pbx_capi_get_cid(struct ast_channel* c) ast_channel_lock(chan) to be held while while accessing returned pointer */ -const char* pbx_capi_get_callername(struct ast_channel* c) +const char* pbx_capi_get_callername(const struct ast_channel* c, const char* notAvailableVisual) { const char* name; #ifdef CC_AST_HAS_VERSION_1_8 - name = S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""); + name = S_COR(c->caller.id.name.valid, c->caller.id.name.str, notAvailableVisual); #else - name = (c->cid.cid_name) ? c->cid.cid_name : ""; + name = (c->cid.cid_name) ? c->cid.cid_name : notAvailableVisual; #endif return (name); @@ -1618,14 +1618,14 @@ const char* pbx_capi_get_callername(struct ast_channel* c) ast_channel_lock(chan) to be held while while accessing returned pointer */ -const char* pbx_capi_get_connectedname(struct ast_channel* c) +const char* pbx_capi_get_connectedname(const struct ast_channel* c, const char* notAvailableVisual) { const char* name; #ifdef CC_AST_HAS_VERSION_1_8 - name = S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""); + name = S_COR(c->connected.id.name.valid, c->connected.id.name.str, notAvailableVisual); #else - name = (c->cid.cid_name) ? c->cid.cid_name : ""; + name = (c->cid.cid_name) ? c->cid.cid_name : notAvailableVisual; #endif return (name); diff --git a/chan_capi_utils.h b/chan_capi_utils.h index 910194f..fc0fa62 100644 --- a/chan_capi_utils.h +++ b/chan_capi_utils.h @@ -59,9 +59,9 @@ extern int capi_create_reader_writer_pipe(struct capi_pvt *i); extern struct ast_frame *capi_read_pipeframe(struct capi_pvt *i); extern int capi_write_frame(struct capi_pvt *i, struct ast_frame *f); extern int capi_verify_resource_plci(const struct capi_pvt *i); -extern const char* pbx_capi_get_cid (struct ast_channel* c); -extern const char* pbx_capi_get_callername (struct ast_channel* c); -const char* pbx_capi_get_connectedname (struct ast_channel* c); +extern const char* pbx_capi_get_cid (const struct ast_channel* c, const char *notAvailableVisual); +extern const char* pbx_capi_get_callername (const struct ast_channel* c, const char *notAvailableVisual); +const char* pbx_capi_get_connectedname (const struct ast_channel* c, const char *notAvailableVisual); #define capi_number(data, strip) \ capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))