view Renderer/Test/dynamic_create.cc @ 575:0f13810d4492

Linda API worked. (slightly unreliable)
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 23 Oct 2009 15:53:24 +0900
parents 6289230fe821
children cc989924f469
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 "SceneGraphRoot.h"
#include "lindaapi.h"
#include "dynamic_create.h"

#define PORT 10000

#define SERIAL_REGIST_TUPLE_NO 1

/*
  typedef struct {
  caddr_t file_mmap;
  off_t size;
  } st_mmap_t;
*/

typedef struct client_ {
    int id;
    SceneGraphPtr sgp;
    struct client_ *next;
} client_t;

typedef struct {
    int tid;
    int sid;
    int read_id;
    SceneGraphPtr node;
    TaskManager *manager;
    client_t *clist;
} callback_arg;


void
client_list_init(TaskManager* manager, client_t *clist)
{
    clist->id = -1;
    clist->next = clist;
}

void
client_list_update(TaskManager *manager, client_t *clist, int id, SceneGraphPtr sgp)
{
    //client_t *c;
    // for (c = clist->next; c != clist; c = c->next) {
    // 	if (c->id == id) {
    // 		c->sgp = sgp;
    // 		return;
    // 	}
    // }
	
    // c->next = (client_t *)manager->allocate(sizeof(client_t));
    // c->next->id = id;
    // c->next->sgp = sgp;
    // c->next->next = clist;
}

void
client_list_delete(TaskManager *manager, client_t *clist, int id)
{
    client_t *c, *prev;
    for (c = clist->next, prev = clist; c->next != clist; c = c->next) {
	if (c->id == id) {
	    prev->next = c->next;
	    return;
	}
	prev = clist;
    }
    if (c->id == id) {
	prev->next = c->next;
	return;
    }
}

int
fix_byte(int size,int fix_byte_size)
{
    size = (size/fix_byte_size)*fix_byte_size  + ((size%fix_byte_size)!= 0)*fix_byte_size;
    
    return size;
}

st_mmap_t
my_mmap(char *filename)
{
    int fd = -1;
    int map = MAP_PRIVATE;
    st_mmap_t st_mmap;
    struct stat sb;

    if ((fd = open(filename, O_RDONLY, 0666)) == 0 ) {
	fprintf(stderr, "Can't open %s\n", filename);
    }

    if (fstat(fd, &sb)) {
	fprintf(stderr, "Can't fstat %s\n", filename);
    }

    printf("file size %d\n", (int)sb.st_size);
	
    st_mmap.size = fix_byte(sb.st_size, 4096);

    printf("fix 4096byte file size %d\n", (int)st_mmap.size);

    st_mmap.file_mmap = (char *)mmap(NULL, st_mmap.size, PROT_READ, map, fd, (off_t)0);
    if (st_mmap.file_mmap == (caddr_t)-1) {
	fprintf(stderr, "Can't mmap file\n");
	perror(NULL);
	exit(0);
    }

    return st_mmap;	
}

static void
earth_collision(SceneGraphPtr node, int screen_w, int screen_h,
		SceneGraphPtr tree)
{    
}

static void
moon_collision(SceneGraphPtr node, int screen_w, int screen_h,
	       SceneGraphPtr tree)
{
}

static void
moon_move(SceneGraphPtr node, int screen_w, int screen_h)
{
    //node->angle[0] += 3.0f;
    node->xyz[1] += 1.0f;
}


static void
earth_move(SceneGraphPtr node, int screen_w, int screen_h)
{
    // psx_sync_n();  in viewer::MainLoop
}

SceneGraphPtr
create_sg(TaskManager *manager, SceneGraphPtr node, unsigned char *data, int len, int serial_id)
{
    SceneGraphPtr object;

    sgroot->createFromXMLmemory(sgroot->tmanager, (char *)data, len);
    object = sgroot->createSceneGraph(sgroot->getLast());
    object->id = serial_id;
    object->set_move_collision(moon_move, moon_collision);
    node->addChild(object);

    return object;
}

// void
// del_callback(unsigned char *data, void *arg)
// {
//     free(data);
// }

// void
// psx_del(int t, int id)
// {
//     psx_callback_in(t, id, del_callback, NULL);
// }

static void
callback_get_xml(unsigned char *xml_tuple, void *arg) {
    int xml_len = psx_get_datalength(xml_tuple);
    callback_arg *carg = (callback_arg *)arg;
    unsigned char *xml_data = xml_tuple+LINDA_HEADER_SIZE;
    SceneGraphPtr sgp;
    // ここで create
	fwrite(xml_data, 1, 10, stdout);
    sgp = create_sg(carg->manager, carg->node, xml_data, xml_len, carg->sid);
    client_list_update(carg->manager, carg->clist, carg->sid, sgp);
    free(arg);
    free(xml_tuple);
}

static void
callbacker(unsigned char *tuple, void *arg) {
    int serial_id, xml_id;
	
    unsigned char *data;
    callback_arg *carg = (callback_arg *)arg;
	
    // 最初の4byteデータは使わない
    data = tuple+LINDA_HEADER_SIZE;
    // clientのSerialIDを取得
    serial_id = ntohl(*(int *)data);

	printf("serial id = %d\n", serial_id);
    // タプルを解放
    //psx_del(carg->tid, SERIAL_REGIST_TUPLE_NO);
    
    // xml fileを取得する もうすでにxml fileが送信済みである事を期待
    // つまり、送信者がserial_idを送る前にxml fileを送信していなくてはならない
    xml_id = serial_id * 10;
    callback_arg *copy_arg = (callback_arg *)carg->manager->allocate(sizeof(callback_arg));
    *copy_arg = *carg;
    copy_arg->sid = serial_id;
    psx_callback_in(carg->tid, xml_id, callback_get_xml, (void *)copy_arg);
    
    /* dataは'\0'で終わっている事を期待     (writerで保証する)  */
    //printf("get data[%d]: `%s'\n", len, data);
    free(tuple);
    
    psx_callback_in(carg->tid, carg->read_id, callbacker, arg);
}

void
linda_init(TaskManager *manager, client_t *clist, SceneGraphPtr node)
{
    init_linda();
    callback_arg *carg = (callback_arg *)manager->allocate(sizeof(callback_arg));

    carg->tid = open_linda_java("localhost", PORT);
    carg->read_id = SERIAL_REGIST_TUPLE_NO;    
    carg->node = node;
    carg->manager = manager;
    carg->clist = clist;
    psx_callback_in(carg->tid, carg->read_id, callbacker, carg);
}

MainLoopPtr 
dynamic_create::init(Viewer *sgroot, int screen_w, int screen_h)
{
    //SceneGraphPtr earth;
    client_t *clist;
    clist = (client_t *)sgroot->manager->allocate(sizeof(client_t));
	
    client_list_init(sgroot->manager, clist);

    SceneGraphPtr parent;
    parent = sgroot->createSceneGraph();
    parent->set_move_collision(earth_move, earth_collision);
    parent->xyz[0] += 300;

    linda_init(sgroot->manager, clist,  parent);
    
    // SceneGraphRoot に、使用する SceneGraph を設定する
    // このとき、ユーザーが記述した SceneGraph の root を渡す。
    sgroot->setSceneData(parent);
    return sgroot;
}

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

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);
    return init(manager, argc, argv);

}

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

/* end */