Release s3d 0.2.2
[s3d.git] / server / process.c
blobb817b607787ac1958def1aac67dcfd0eb9bf62bb
1 /*
2 * process.c
4 * Copyright (C) 2004-2011 Simon Wunderlich <dotslash@packetmixer.de>
6 * This file is part of s3d, a 3d network display server.
7 * See http://s3d.berlios.de/ for more updates.
9 * s3d is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * s3d is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with s3d; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "global.h"
25 #include <stdlib.h> /* for malloc, free */
26 #include <string.h> /* strncmp(), strncpy() */
27 /* this piece of code handles processes */
29 #define mcp_p (&procs_p[0])
30 struct t_process *procs_p = NULL; /* pointer to the processes */
31 int procs_n; /* number of processes */
32 static int p_del(struct t_process *p); /* local prototype */
33 static int process_list_rm(int pid);
34 static int process_sys_init(struct t_process *p);
36 /* protocol request for process initialization */
37 struct t_process *process_protinit(struct t_process *p, const char *name)
39 int con_type;
40 int32_t mcp_oid;
41 if ((strncmp(name, "sys_", 4) == 0)) { /* we don't like "sys_"-apps, kicking this */
42 errds(VHIGH, "process_protinit()", "appnames starting with 'sys_' not allowed.");
43 return NULL;
45 if ((p->id != MCP) && (strncmp(name, "mcp", 3) == 0)) {
46 if (procs_p[MCP].con_type == CON_NULL) {
47 s3dprintf(MED, "free mcp place, pid %d becoming mcp!", p->id);
48 con_type = p->con_type; /* move connection data */
49 #ifdef TCP
50 procs_p[MCP].sockid = p->sockid; /* don't save contype yet,
51 or p_del will notify mcp about a deleted
52 mcp-object (which is itselfs, actually) */
53 #endif
54 #ifdef SHM
55 memcpy(&procs_p[MCP].shmsock, &p->shmsock, sizeof(struct t_shmcb));
56 #endif
57 p_del(p); /* deleting data/mcp object */
58 procs_p[MCP].con_type = con_type;
59 mcp_init();
60 process_list_rm(p->id); /* remove old process, but don't kill connection */
61 return &procs_p[MCP];
62 } else {
63 s3dprintf(LOW, "the place for the mcp is already taken ...");
64 return NULL;
66 } else {
67 strncpy(p->name, name, S3D_NAME_MAX);
68 process_sys_init(p);
70 /* register the new process in the mcp */
71 if (-1 != (mcp_oid = obj_new(&procs_p[MCP]))) {
72 mcp_p->object[mcp_oid]->oflags |= OF_VIRTUAL | OF_VISIBLE | OF_SELECTABLE;
73 mcp_p->object[mcp_oid]->virtual_pid = p->id;
75 /* mcp_p->object[mcp_oid]->p_mat=(struct t_material *)new_p; */
76 /* dirty, but it's just a pointer after all ... */
77 p->mcp_oid = mcp_oid;
78 s3dprintf(LOW, "process %d now has mcp_oid %d", p->id, mcp_oid);
79 mcp_rep_object(mcp_oid);
80 if (mcp_p->con_type == CON_NULL) { /* there is no mcp connected! setting focus to the new program: */
81 mcp_focus(mcp_oid);
83 } else {
84 s3dprintf(LOW, "couldn't add object to mcp ...");
87 return p;
90 /* adds system objects to the app, like camera, pointers etc ... */
91 static int process_sys_init(struct t_process *p)
93 int cam, ptr;
94 struct t_obj *o;
95 cam = obj_new(p);
96 ptr = obj_new(p);
97 if (p->id == MCP) {
98 /* this is only called once within process_init, later mcp's are
99 will be registered as "real" apps first */
100 p->object[cam]->translate.z = 5;
101 p->object[cam]->oflags = OF_CAM;
102 p->object[ptr]->translate.z = -1;
103 p->object[ptr]->oflags = OF_POINTER;
104 link_insert(p, ptr, cam);
105 } else {
106 /* TODO: ... get the cam and ptr position of the mcp, somehow */
107 p->object[cam]->oflags = OF_CAM;
109 if (OBJ_VALID(mcp_p, get_pointer(mcp_p), o)) { /* get parent pointer, copy parent */
110 p->object[ptr]->rotate.x = o->rotate.x;
111 p->object[ptr]->rotate.y = o->rotate.y;
112 p->object[ptr]->rotate.z = o->rotate.z;
113 p->object[ptr]->translate.x = o->translate.x;
114 p->object[ptr]->translate.y = o->translate.y;
115 p->object[ptr]->translate.z = o->translate.z;
117 p->object[ptr]->oflags = OF_POINTER;
118 link_insert(p, ptr, cam);
120 s3dprintf(MED, "process_sys_init(): added object cam0 %d", cam);
121 s3dprintf(MED, "process_sys_init(): added object ptr0 %d", ptr);
122 obj_pos_update(get_proc_by_pid(MCP), cam, cam);
123 obj_pos_update(get_proc_by_pid(MCP), ptr, ptr);
124 event_obj_info(p, 0); /* tell the new program about the thing */
126 return 0;
129 /* this is to be called when a new connection appears. a pointer to the added process will be returned */
130 struct t_process *process_add(void)
132 struct t_process *new_p;
133 procs_n++;
134 procs_p = (struct t_process *)realloc(procs_p, sizeof(struct t_process) * procs_n); /* increase the block */
135 new_p = &procs_p[procs_n - 1];
137 new_p->id = procs_n - 1;
138 new_p->object = NULL;
139 new_p->n_obj = 0;
140 new_p->mcp_oid = -1;
141 new_p->biggest_obj = -1;
142 new_p->con_type = CON_NULL; /* this is to be changed by the caller */
143 new_p->name[0] = '\0';
144 return new_p;
147 /* deletes the process with pid */
148 int process_del(int pid)
150 if (pid == MCP) {
151 n_remove(&procs_p[pid]);
152 p_del(&procs_p[pid]);
153 return 0;
155 if ((pid > 0) && (pid < procs_n)) {
156 n_remove(&procs_p[pid]);
157 p_del(&procs_p[pid]);
158 process_list_rm(pid);
159 return 0;
161 return -1;
164 /* just kick process out of the process list, no network/mcp-oid cleanup */
165 static int process_list_rm(int pid)
167 if (pid != (procs_n - 1)) { /* copy last block, swap pid */
168 memcpy(&procs_p[pid], &procs_p[procs_n - 1], sizeof(struct t_process));
169 procs_p[pid].id = pid; /* change the pid of the new procs_p */
170 if (procs_p[pid].mcp_oid != -1) /* the last process could just appear without initializing yet ... */
171 procs_p[0].object[procs_p[pid].mcp_oid]->virtual_pid = pid;
172 /* change the mcp-objects pid-pointer to the right position! */
173 /* this is kind of pointer madness */
175 procs_n--;
176 procs_p = (struct t_process *)realloc(procs_p, sizeof(struct t_process) * procs_n); /* decrease the block,
177 wipe the last one */
178 return 0;
181 struct t_process *get_proc_by_pid(int pid)
183 if ((pid >= 0) && (pid < procs_n))
184 return &procs_p[pid];
185 return NULL;
188 /* this actually deleted the process with all it's parts */
189 /* it's quite the same as the original version, but without free() */
190 static int p_del(struct t_process *p)
192 int j, i = p->n_obj;
193 if (p->id != MCP) {
194 if (p->mcp_oid != -1) {
195 for (j = 0; j < mcp_p->n_obj; j++) /* remove clones and links pointing on this app-object ... */
196 if (mcp_p->object[j] != NULL) {
197 if ((mcp_p->object[j]->oflags & OF_CLONE) && (mcp_p->object[j]->clone_ooid == p->mcp_oid)) { /* it's linking to our object! */
198 mcp_p->object[j]->oflags &= ~OF_CLONE; /* disable clone flag */
199 mcp_p->object[j]->clone_ooid = 0; /* and "clone reference" to 0 */
200 mcp_p->object[j]->r = 0.0F; /* empty object, so radius is zero! */
203 obj_free(mcp_p, p->mcp_oid); /* free the mcp-app-object. */
204 mcp_del_object(p->mcp_oid); /* tell MCP that it's object is beeing deleted. */
206 if (i > 0) {
207 for (i = 0; i < p->n_obj; i++)
208 if (p->object[i])
209 obj_free(p, i);
210 free(p->object);
212 } else {
213 /* the mcp keeps in our memory ... */
214 /* so we just delete the objects added */
215 /* by the last mcp */
216 s3dprintf(MED, "clean up mcp's junk ...");
217 for (i = 0; i < p->n_obj; i++) {
218 if (p->object[i] != NULL)
219 if (!(p->object[i]->oflags & (OF_SYSTEM | OF_VIRTUAL)))
220 obj_free(p, i);
223 return 0; /* successfully deleted */
226 int process_init(void)
228 procs_n = 0;
229 procs_p = NULL;
230 process_add();
231 /* set up mcp */
232 strncpy(mcp_p->name, "mcp", S3D_NAME_MAX);
233 mcp_p->con_type = CON_NULL;
234 process_sys_init(mcp_p);
235 return 0;
238 int process_quit(void)
240 int i;
241 s3dprintf(HIGH, "telling %d processes to go away", procs_n);
242 for (i = (procs_n - 1); i >= 0; i--) {
243 s3dprintf(HIGH, "[QUIT] for %d", i);
244 event_quit(&procs_p[i]);
246 free(procs_p);
247 return 0;