This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/blenkernel/intern/verse_method.c
Chris Want 5d0a207ecb Patch from GSR that a) fixes a whole bunch of GPL/BL license
blocks that were previously missed; and b) greatly increase my
ohloh stats!
2008-04-16 22:40:48 +00:00

521 lines
14 KiB
C

/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Contributor(s): Nathan Letwory.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifdef WITH_VERSE
#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_listBase.h"
#include "DNA_userdef_types.h"
#include "DNA_text_types.h"
#include "BLI_dynamiclist.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BIF_verse.h"
#include "BKE_bad_level_calls.h"
#include "BKE_library.h"
#include "BKE_text.h"
#include "BKE_verse.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "verse.h"
/* helper struct for creating method descriptions */
typedef struct VMethodInfo {
const char *name;
uint8 param_count;
const VNOParamType param_type[4];
const char *param_name[4];
uint16 id;
} VMethodInfo;
#ifdef VERSECHAT
/* array with methods for verse chat */
static VMethodInfo vmethod_info[] = {
{ "join", 1, { VN_O_METHOD_PTYPE_STRING }, { "channel"}},
{ "leave", 1, { VN_O_METHOD_PTYPE_STRING }, { "channel"}},
{ "hear", 3, { VN_O_METHOD_PTYPE_STRING, VN_O_METHOD_PTYPE_STRING, VN_O_METHOD_PTYPE_STRING }, { "channel", "from", "msg"}}
};
#endif
/* lookup a method group based on its name */
struct VMethodGroup *lookup_vmethodgroup_name(ListBase *lb, const char *name) {
struct VMethodGroup *vmg;
for(vmg= lb->first; vmg; vmg= vmg->next)
if(strcmp(vmg->name,name)==0) break;
return vmg;
}
/* lookup a method group based on its group_id */
struct VMethodGroup *lookup_vmethodgroup(ListBase *lb, uint16 group_id) {
struct VMethodGroup *vmg;
for(vmg= lb->first; vmg; vmg= vmg->next)
if(vmg->group_id==group_id) break;
return vmg;
}
/* lookup a method based on its name */
struct VMethod *lookup_vmethod_name(ListBase *lb, const char *name) {
struct VMethod *vm;
for(vm= lb->first; vm; vm= vm->next)
if(strcmp(vm->name,name)==0) break;
return vm;
}
/* lookup a method based on its method_id */
struct VMethod *lookup_vmethod(ListBase *lb, uint8 method_id) {
struct VMethod *vm;
for(vm= lb->first; vm; vm= vm->next)
if(vm->id==method_id) break;
return vm;
}
#ifdef VERSECHAT
/*
* send say command
*/
void send_say(const char *chan, const char *utter)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VMethodGroup *vmg;
struct VMethod *vm;
VNOPackedParams *utterpack;
VNOParam args[2];
vnode= (VNode *)(session->nodes.lb.first);
for( ; vnode; vnode= vnode->next) {
if(strcmp(vnode->name, "tawksrv")==0) {
vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
if(!vmg) break;
vm= lookup_vmethod_name(&(vmg->methods), "say");
if(!vm) break;
args[0].vstring= (char *)chan;
args[1].vstring= (char *)utter;
if((utterpack= verse_method_call_pack(vm->param_count, vm->param_type, args))!=NULL) {
verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, utterpack);
}
break;
}
}
}
/*
* send logout command
*/
void send_logout(VNode *vnode)
{
struct VMethodGroup *vmg;
struct VMethod *vm;
VNOPackedParams *pack;
vnode->chat_flag = CHAT_LOGGED;
vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
if(!vmg) return;
vm= lookup_vmethod_name(&(vmg->methods), "logout");
if(!vm) return;
if((pack= verse_method_call_pack(vm->param_count, vm->param_type, NULL))!=NULL) {
verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, pack);
}
vnode->chat_flag = CHAT_NOTLOGGED;
}
/*
* send join command
*/
void send_join(VNode *vnode, const char *chan)
{
struct VMethodGroup *vmg;
struct VMethod *vm;
VNOPackedParams *join;
VNOParam channel[1];
vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
if(!vmg) return;
vm= lookup_vmethod_name(&(vmg->methods), "join");
if(!vm) return;
channel[0].vstring= (char *)chan;
if((join= verse_method_call_pack(vm->param_count, vm->param_type, channel))!=NULL) {
verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, join);
}
}
/*
* send leave command
*/
void send_leave(VNode *vnode, const char *chan)
{
struct VMethodGroup *vmg;
struct VMethod *vm;
VNOPackedParams *leave;
VNOParam channel[1];
vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
if(!vmg) return;
vm= lookup_vmethod_name(&(vmg->methods), "leave");
if(!vm) return;
channel[0].vstring= (char *)chan;
if((leave= verse_method_call_pack(vm->param_count, vm->param_type, channel))!=NULL) {
verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, leave);
}
}
/*
* send login command
*/
void send_login(VNode *vnode)
{
struct VMethodGroup *vmg;
struct VMethod *vm;
VNOPackedParams *login;
VNOParam param[1];
vnode->chat_flag = CHAT_LOGGED;
vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk");
if(!vmg) return;
vm= lookup_vmethod_name(&(vmg->methods), "login");
if(!vm) return;
param[0].vstring= U.verseuser;
if((login= verse_method_call_pack(vm->param_count, vm->param_type, param))!=NULL) {
verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, login);
}
vnode->chat_flag = CHAT_LOGGED;
vnode= lookup_vnode(vnode->session, vnode->session->avatar);
vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk-client");
if(!vmg)
verse_send_o_method_group_create(vnode->session->avatar, ~0, "tawk-client");
}
#endif
/*
* Free a VMethod
*/
void free_verse_method(VMethod *vm) {
if(!vm) return;
MEM_freeN(vm->param_type);
}
/*
* Free methods for VMethodGroup
*/
void free_verse_methodgroup(VMethodGroup *vmg)
{
struct VMethod *vm, *tmpvm;
if(!vmg) return;
vm= vmg->methods.first;
while(vm) {
tmpvm=vm->next;
free_verse_method(vm);
vm= tmpvm;
}
BLI_freelistN(&(vmg->methods));
}
/* callback for method group creation */
static void cb_o_method_group_create(
void *user_data,
VNodeID node_id,
uint16 group_id,
const char *name)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VMethodGroup *vmg;
if(!session) return;
vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
vmg = lookup_vmethodgroup(&(vnode->methodgroups), group_id);
/* create method group holder in node node_id */
if(!vmg) {
vmg= MEM_mallocN(sizeof(VMethodGroup), "VMethodGroup");
vmg->group_id = group_id;
vmg->methods.first = vmg->methods.last = NULL;
BLI_addtail(&(vnode->methodgroups), vmg);
printf("new method group with name %s (group_id %d) for node %u created\n", name, group_id, node_id);
}
/* this ensures name of an existing group gets updated, in case it is changed */
BLI_strncpy(vmg->name, (char *)name, 16);
/* subscribe to method group */
verse_send_o_method_group_subscribe(node_id, group_id);
#ifdef VERSECHAT
/* if this is our own method group, register our methods */
if(node_id==session->avatar) {
verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[0].name,
vmethod_info[0].param_count,
(VNOParamType *)vmethod_info[0].param_type,
(const char **)vmethod_info[0].param_name);
b_verse_update();
verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[1].name,
vmethod_info[1].param_count,
(VNOParamType *)vmethod_info[1].param_type,
(const char **)vmethod_info[1].param_name);
b_verse_update();
verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[2].name,
vmethod_info[2].param_count,
(VNOParamType *)vmethod_info[2].param_type,
(const char **)vmethod_info[2].param_name);
b_verse_update();
}
#endif
}
/* callback for method group destruction */
static void cb_o_method_group_destroy(
void *user_data,
VNodeID node_id,
uint16 group_id,
const char *name)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VMethodGroup *vmg;
struct VMethod *vm;
printf("method group %d destroyed\n", group_id);
if(!session) return;
vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
for(vmg= vnode->methodgroups.first; vmg; vmg= vmg->next)
if(vmg->group_id==group_id) break;
if(!vmg) return; /* method group doesn't exist? */
vmg->group_id = 0;
vmg->name[0] = '\0';
vm= vmg->methods.first;
while(vm) {
/* free vm */
}
/* TODO: unsubscribe from method group */
BLI_remlink(&(vnode->methodgroups),vmg);
MEM_freeN(vmg);
}
/* callback for method creation */
static void cb_o_method_create(
void *user_data,
VNodeID node_id,
uint16 group_id,
uint16 method_id,
const char *name,
uint8 param_count,
const VNOParamType *param_type,
const char *param_name[])
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VMethodGroup *vmg;
struct VMethod *vm;
unsigned int size;
unsigned int i;
char *put;
if(!session) return;
vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
vmg= lookup_vmethodgroup((&vnode->methodgroups), group_id);
if(!vmg) return;
vm= lookup_vmethod((&vmg->methods), method_id);
if(!vm) {
vm= MEM_mallocN(sizeof(VMethod), "VMethod");
vm->id= method_id;
vm->param_count= param_count;
size= param_count* (sizeof(*vm->param_type) + sizeof(*vm->param_name));
for(i= 0; i <param_count; i++) {
size+=strlen(param_name[i])+1;
}
vm->param_type= MEM_mallocN(size, "param_type and param_name");
memcpy(vm->param_type, param_type, sizeof(VNOParamType)*param_count);
vm->param_name= (char **)(vm->param_type + param_count);
put= (char *)(vm->param_name + param_count);
for(i= 0; i < param_count; i++) {
vm->param_name[i]= put;
strcpy(put, param_name[i]);
put += strlen(param_name[i]) + 1;
}
BLI_addtail(&(vmg->methods), vm);
#ifdef VERSECHAT
if(strcmp(vmethod_info[0].name, name)==0) {
vmethod_info[0].id = method_id;
}
#endif
printf("method %s in group %d of node %u created\n", name, group_id, node_id);
}
BLI_strncpy(vm->name, (char *)name, 500);
}
/* callback for method destruction */
static void cb_o_method_destroy(
void *user_data,
VNodeID node_id,
uint16 group_id,
uint16 method_id,
const char *name,
uint8 param_count,
const VNOParamType *param_type,
const char *param_name[])
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VMethodGroup *vmg;
struct VMethod *vm;
if(!session) return;
vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
for(vmg= vnode->methodgroups.first; vmg; vmg= vmg->next)
if(vmg->group_id==group_id) break;
if(!vmg) return; /* method group doesn't exist? */
for(vm= vmg->methods.first; vm; vm= vm->next)
if(vm->id==method_id) break;
if(!vm) return;
BLI_remlink(&(vmg->methods), vm);
MEM_freeN(vm->param_type);
MEM_freeN(vm);
}
/* callback for method calls */
static void cb_o_method_call(void *user_data, VNodeID node_id, uint8 group_id, uint8 method_id, VNodeID sender, VNOPackedParams *params)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VMethodGroup *vmg;
struct VMethod *vm;
Text *text;
int method_idx= -1;
VNOParam arg[3];
if(!session) return;
if(session->avatar!=node_id) return;
vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
vmg= lookup_vmethodgroup(&(vnode->methodgroups), group_id);
if(!vmg) return;
vm= lookup_vmethod(&(vmg->methods), method_id);
if(!vm) return;
#ifdef VERSECHAT
if(strcmp(vm->name, "join")==0) method_idx=0;
if(strcmp(vm->name, "leave")==0) method_idx=1;
if(strcmp(vm->name, "hear")==0) method_idx=2;
if(method_idx>-1)
verse_method_call_unpack(params, vmethod_info[method_idx].param_count, vmethod_info[method_idx].param_type, arg);
switch(method_idx) {
case 0:
printf("Joining channel %s\n",arg[0].vstring);
text=add_empty_text();
text->flags |= TXT_ISCHAT;
rename_id(&(text->id), arg[0].vstring);
break;
case 1:
printf("Leaving channel %s\n",arg[0].vstring);
break;
case 2:
{
ListBase lb = G.main->text;
ID *id= (ID *)lb.first;
char showstr[1024];
showstr[0]='\0';
text = NULL;
sprintf(showstr, "%s: %s\n", arg[1].vstring, arg[2].vstring);
for(; id; id= id->next) {
if(strcmp(id->name+2, arg[0].vstring)==0 && strcmp(arg[0].vstring, "#server")!=0) {
text = (Text *)id;
break;
}
}
if(text) {
txt_insert_buf(text, showstr);
txt_move_eof(text, 0);
allqueue(REDRAWCHAT, 0);
} else {
printf("%s> %s: %s\n",arg[0].vstring, arg[1].vstring, arg[2].vstring);
}
}
break;
}
#endif
}
void set_method_callbacks(void)
{
/* create and destroy method groups */
verse_callback_set(verse_send_o_method_group_create, cb_o_method_group_create, NULL);
verse_callback_set(verse_send_o_method_group_destroy, cb_o_method_group_destroy, NULL);
/* create and destroy methods */
verse_callback_set(verse_send_o_method_create, cb_o_method_create, NULL);
verse_callback_set(verse_send_o_method_destroy, cb_o_method_destroy, NULL);
/* call methods */
verse_callback_set(verse_send_o_method_call, cb_o_method_call, NULL);
}
#endif