From 39c9ac14750c537695e089ba969b1abe5050fdf0 Mon Sep 17 00:00:00 2001 From: MelwareDE Date: Thu, 14 May 2009 21:57:35 +0000 Subject: [PATCH] Add chat_play --- chan_capi.c | 1 + chan_capi_chat.c | 158 ++++++++++++++++++++++++++++++++++++++++++++--- chan_capi_chat.h | 1 + 3 files changed, 150 insertions(+), 10 deletions(-) diff --git a/chan_capi.c b/chan_capi.c index 231d921..5c2d014 100644 --- a/chan_capi.c +++ b/chan_capi.c @@ -6102,6 +6102,7 @@ static struct capicommands_s { { "ccpartybusy", pbx_capi_ccpartybusy, 0, 0 }, { "chat", pbx_capi_chat, 0, 0 }, { "chat_mute", pbx_capi_chat_mute, 0, 0 }, + { "chat_play", pbx_capi_chat_play, 0, 0 }, { "resource", pbx_capi_chat_associate_resource_plci, 0, 0 }, { "hangup", pbx_capi_realhangup, 0, 0 }, { "qsig_ssct", pbx_capi_qsig_ssct, 1, 0 }, diff --git a/chan_capi_chat.c b/chan_capi_chat.c index dddf333..c7c6c76 100644 --- a/chan_capi_chat.c +++ b/chan_capi_chat.c @@ -408,7 +408,7 @@ static struct capichat_s *add_chat_member(char *roomname, struct capi_pvt *i, ro * loop during chat */ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, - struct capichat_s *room, unsigned int flags) + struct capichat_s *room, unsigned int flags, FILE* voice_message) { struct ast_frame *f; int ms; @@ -418,24 +418,33 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, int nfds = 0; struct ast_channel *rchan; struct ast_channel *chan = c; - int moh_active = 0; + int moh_active = 0, voice_message_moh_active = 0; + int write_block_nr = 2; - ast_indicate(chan, -1); + if (voice_message == NULL) { + ast_indicate(chan, -1); + } waitfd = i->readerfd; if (i->channeltype == CAPI_CHANNELTYPE_NULL) { nfds = 1; - ast_set_read_format(chan, capi_capability); - ast_set_write_format(chan, capi_capability); + if (voice_message == NULL) { + ast_set_read_format(chan, capi_capability); + ast_set_write_format(chan, capi_capability); + } } - if ((flags & CHAT_FLAG_MOH) && (room->active < 2)) { + if ((flags & CHAT_FLAG_MOH) && ((room->active < 2) || (voice_message != 0))) { #if defined(CC_AST_HAS_VERSION_1_6) || defined(CC_AST_HAS_VERSION_1_4) ast_moh_start(chan, NULL, NULL); #else ast_moh_start(chan, NULL); #endif - moh_active = 1; + if (voice_message == 0) { + moh_active = 1; + } else { + voice_message_moh_active = 1; + } } while (1) { @@ -461,7 +470,7 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, } else if (f->frametype == AST_FRAME_VOICE) { cc_verbose(5, 1, VERBOSE_PREFIX_3 "%s: chat: voice frame.\n", i->vname); - if (i->channeltype == CAPI_CHANNELTYPE_NULL) { + if ((voice_message == 0) && (i->channeltype == CAPI_CHANNELTYPE_NULL)) { capi_write_frame(i, f); } } else if (f->frametype == AST_FRAME_NULL) { @@ -481,7 +490,28 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, } f = capi_read_pipeframe(i); if (f->frametype == AST_FRAME_VOICE) { - ast_write(chan, f); + if (voice_message == 0) { + ast_write(chan, f); + } else { + char* p = f->FRAME_DATA_PTR; + int len; + + do { + if ((len = fread(p, 1, f->datalen, voice_message)) > 0) { + if (len < f->datalen) { + memset (&p[len], 0x00, f->datalen-len); + len = 0; + } + capi_write_frame(i, f); + } + } while ((write_block_nr-- != 0) && (len > 0)); + + if (len <= 0) { + break; + } + + write_block_nr = 0; + } } /* ignore other nullplci frames */ } else { @@ -498,6 +528,9 @@ static void chat_handle_events(struct ast_channel *c, struct capi_pvt *i, moh_active = 0; } } + if (voice_message_moh_active != 0) { + ast_moh_stop(chan); + } } /* @@ -581,11 +614,12 @@ int pbx_capi_chat(struct ast_channel *c, char *param) room = add_chat_member(roomname, i, room_member_type); if (!room) { cc_log(LOG_WARNING, "Unable to open " CC_MESSAGE_NAME " chat room.\n"); + capi_remove_nullif(i); return -1; } /* main loop */ - chat_handle_events(c, i, room, flags); + chat_handle_events(c, i, room, flags, 0); del_chat_member(room); @@ -595,6 +629,110 @@ out: return 0; } +int pbx_capi_chat_play(struct ast_channel *c, char *param) +{ + struct capi_pvt *i = NULL; + char *roomname, *controller, *file_name; + char *p; + struct capichat_s *room; + ast_group_t tmpcntr; + unsigned long long contr = 0; + room_member_type_t room_member_type = RoomMemberOperator; + FILE* f; + + roomname = strsep(¶m, "|"); + file_name = strsep(¶m, "|"); + controller = param; + + if (!roomname) { + cc_log(LOG_WARNING, CC_MESSAGE_NAME " chat_play requires room name.\n"); + return -1; + } + if (!file_name || !*file_name) { + cc_log(LOG_WARNING, CC_MESSAGE_NAME " chat_play requires file name.\n"); + return -1; + } + + { + int chat_members; + + cc_mutex_lock(&chat_lock); + for (room = chat_list, chat_members = 0; room != 0 && chat_members == 0; room = room->next) { + chat_members += (strcmp(room->name, roomname) == 0); + } + cc_mutex_unlock(&chat_lock); + + if (chat_members == 0) { + return 0; + } + } + + f = fopen(file_name, "rb"); + if (f == NULL) { + cc_log(LOG_WARNING, "can't open voice file (%s)\n", strerror(errno)); + return -1; + } + + { + unsigned char tmp[2] = { 0, 0 }; + + if (fread(tmp, 1, 2, f) != 2) { + cc_log(LOG_WARNING, "can't read voice file (%s)\n", strerror(errno)); + fclose(f); + return -1; + } + } + + rewind(f); + + if (controller) { + for (p = controller; p && *p; p++) { + if (*p == '|') *p = ','; + } + tmpcntr = ast_get_group(controller); + contr = (unsigned long long)(tmpcntr >> 1); + } + + cc_verbose(3, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME " chat_play: %s: roomname=%s " + "message=%s controller=%s (0x%llx)\n", + c->name, roomname, file_name, controller, contr); + + i = capi_mknullif(c, contr); + if (i == NULL) { + fclose (f); + cc_log(LOG_WARNING, "Unable to play %s to chat room %s", file_name, roomname); + return (-1); + } + + if (c->_state != AST_STATE_UP) { + ast_answer(c); + } + + capi_wait_for_answered(i); + if (!(capi_wait_for_b3_up(i))) { + goto out; + } + + room = add_chat_member(roomname, i, room_member_type); + if (!room) { + capi_remove_nullif(i); + fclose (f); + cc_log(LOG_WARNING, "Unable to open " CC_MESSAGE_NAME " chat room.\n"); + return -1; + } + + /* main loop */ + chat_handle_events(c, i, room, CHAT_FLAG_MOH, f); + + del_chat_member(room); + +out: + fclose (f); + capi_remove_nullif(i); + + return 0; +} + struct capi_pvt* pbx_check_resource_plci(struct ast_channel *c) { struct capi_pvt *i = NULL; diff --git a/chan_capi_chat.h b/chan_capi_chat.h index ab39e92..85f602e 100644 --- a/chan_capi_chat.h +++ b/chan_capi_chat.h @@ -24,5 +24,6 @@ extern char *pbxcli_capi_chatinfo(struct ast_cli_entry *e, int cmd, struct ast_c extern int pbxcli_capi_chatinfo(int fd, int argc, char *argv[]); #endif extern int pbx_capi_chat_mute(struct ast_channel *c, char *param); +extern int pbx_capi_chat_play(struct ast_channel *c, char *param); #endif