view Renderer/Test/send_linda.cc @ 610:529188ae604d

change htonl to xdr_float (checked working on mac)
author kazz@kazzone.st.ie.u-ryukyu.ac.jp
date Sun, 08 Nov 2009 03:30:06 +0900
parents 8782cc4171b7
children 0eed1fa290c1
line wrap: on
line source

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include "SceneGraphRoot.h"
#include "lindaapi.h"
#include "send_linda.h"

#define HOSTNAME "localhost"
#define PORT_NUM 10000
#define LISTEN_PORT 1
#define MULTI_NUM 10
#define SEND_DATA_SIZE sizeof(float) * 6

void
send_position(SceneGraphPtr node)
{
	char *data;
	if ((data = (char *)psx_reply(node->seq)) == NULL) {
		//float send_data[6]; // xyz[3] and angle[3]
		int tapleid = node->id * 10 + 1;
		int fd = *(int*)node->propertyptr;

		// XDRの準備
		XDR xdrs;
		char send_data[SEND_DATA_SIZE];
		xdrmem_create(&xdrs, send_data, SEND_DATA_SIZE, XDR_ENCODE);
		
		for (int i = 0; i < 3; i ++) {
			xdr_float(&xdrs, &node->xyz[i]);
		}
		for (int i = 0; i < 3; i ++) {
			xdr_float(&xdrs, &node->angle[i]);
		}
		node->seq = psx_in(fd, tapleid);
		psx_out(fd, tapleid, (unsigned char *)send_data, SEND_DATA_SIZE);
		psx_free(data);
	}
}

void
root_move(SceneGraphPtr node, int w, int h)
{
    Pad *pad = sgroot->getController();
	int flag = 0;
    if (pad->right.isHold() || pad->left.isHold()) {
		if (pad->right.isHold()) {
			node->xyz[0] += 5.0f;
			flag = 1;
		} else if (pad->left.isHold()) {
			node->xyz[0] -= 5.0f;
			flag = 1;
		}
    }
    
    if (pad->down.isHold() || pad->up.isHold() ) {
		if (pad->down.isHold()) {
			node->xyz[1] += 5.0f;
			flag = 1;
		} else if (pad->up.isHold()) {
			node->xyz[1] -= 5.0f;
			flag = 1;
		}
    }

	/*
      ここでキー入力を向こうに送る
	*/
	if (flag) {
		send_position(node);
	}
}

void
root_collision(SceneGraphPtr node, int w, int h, SceneGraphPtr tree)
{
}

void
move(SceneGraphPtr node, int w, int h)
{
}

void
collision(SceneGraphPtr node, int w, int h, SceneGraphPtr tree)
{
}

void *
file_map(const char *filename, int *size) {
    int fd;
    void *addr;
    struct stat sb;

    if ((fd = open(filename, O_RDONLY)) == -1) {
		fprintf(stderr, "Can't open %s\n", filename);
		perror(NULL);
    }
    if (fstat(fd, &sb) == -1) {
		fprintf(stderr, "Can't fstat %s\n", filename);
		perror(NULL);
    }
    *size = sb.st_size;
    addr = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (addr == MAP_FAILED) {
		perror("mmap error\n");
		exit(EXIT_FAILURE);
    }
    close(fd);

    return addr;
}



int get_serial_id(int fd) {
    char *data;
    int serial;
    int seq;
    
    seq = psx_in(fd, 65535);
	do {
		psx_sync_n();
		data = (char *)psx_reply(seq);
	} while (data == 0);
    serial = atoi(data + LINDA_HEADER_SIZE);
    psx_free(data);
	printf("serial id = %d\n", serial);
    return serial;
}


void
send_xml(int tspace, int xml_id, void *addr, int size) {
    psx_out(tspace, xml_id, (unsigned char *)addr, size);
    psx_sync_n();
}

static char *xml;
static char *linda = HOSTNAME;

MainLoopPtr 
send_linda::init(Viewer *sgr, int screen_w, int screen_h)
{
    void *addr;
    int size;
    int tspace;
    int serial;
    int xml_id;

    SceneGraphPtr sgp;
    SceneGraphPtr root;

	// ここら辺長ったるいから、関数で分けるべきか...
	
	// root オブジェクト作成
    root = sgroot->createSceneGraph();
	// root_moveはコントローラーの入力で動き、座標をLinda Serverにout
    root->set_move_collision(root_move, root_collision);

	// XMLをメモリにmapして、オブジェクト生成
    addr = file_map(xml, &size);
	sgp = sgroot->createSceneGraph();
    sgroot->createFromXMLmemory(sgroot->tmanager, sgp, (char *)addr, size);
    sgp->set_move_collision(move, collision);

	// rootに接続
    root->addChild(sgp);

	// Linda Serverに接続
	tspace = open_linda_java(linda, PORT_NUM);
    // rootにLindaのfdを持たせる
	root->propertyptr = sgroot->tmanager->allocate(sizeof(int));
	root->property_size = sizeof(int);
	*(int *)root->propertyptr = tspace;

	// このclientのserial_idを取得
	serial = get_serial_id(tspace);
	root->id = serial;

	// ここから先の処理は、裏で何か動かせないかを考える
	// とりあえず、関数に分けようか
	
    // serial_idを十倍したところにXMLを送信
    xml_id = serial * 10;
    send_xml(tspace, xml_id, addr, size); // ここのpsx_sync_n()は仕方ない

	// XMLの送信が終了してから、serial_idをLindaに送信する
	int client_id = htonl(serial);
    psx_out(tspace, LISTEN_PORT, (unsigned char *)&client_id, sizeof(int));

	// serial_idを十倍して1足したところに座標データを送る
	// 初期化のout()
	int pos_id = serial * 10 + 1;
	char pos_data[SEND_DATA_SIZE] = {0};
//	float pos_data[6];
//	for (int i = 0; i < 6; i++) {
//		pos_data[i] = 0.0f;
//	}
    psx_out(tspace, pos_id, (unsigned char *)pos_data, SEND_DATA_SIZE);

	// 初期化のin()
	// send_position()でinの終了を確認する分岐が最初にあるため
	root->seq = psx_in(tspace, pos_id);
    sgroot->setSceneData(root);
	
    return sgr;
}

extern Application *
application() {
    return new send_linda();
}


const char *usr_help_str = "Usage: ./test_nogl [OPTION]\n";

extern int init(TaskManager *manager, int argc, char *argv[]);
extern void task_initialize();
static void TMend(TaskManager *manager);

int
TMmain(TaskManager *manager, int argc, char *argv[])
{
    task_initialize();
    manager->set_TMend(TMend);

    for(int i=0;i<argc;i++) {
		if (strcmp(argv[i],"-xml") == 0 && i+1<=argc) {
			xml = argv[i+1];
		} else if (strcmp(argv[i],"-linda") == 0 && i+1<=argc) {
			linda = argv[i+1];
		}
    }

    if (xml==0) {
	printf("-xml xml-file is required\n");
        exit(0);
    }

    return init(manager, argc, argv);

}

void
TMend(TaskManager *manager)
{
    printf("test_nogl end\n");
}

/* end */