comparison rlgwebd.js @ 164:3a97e4ee50f0

rlgwebd.js: read ttyrecs created by dgamelaunch. TTYREC files created by dgamelaunch are tracked by DglSession objects, as a first step toward making them watchable.
author John "Elwin" Edwards
date Tue, 06 Jan 2015 16:59:12 -0500
parents 0f6da35b27a0
children 59e62710cbb5
comparison
equal deleted inserted replaced
163:0f6da35b27a0 164:3a97e4ee50f0
189 this.term.kill('SIGHUP'); 189 this.term.kill('SIGHUP');
190 }; 190 };
191 } 191 }
192 TermSession.prototype = new events.EventEmitter(); 192 TermSession.prototype = new events.EventEmitter();
193 193
194 function DglSession(filename) {
195 var ss = this;
196 events.EventEmitter.call(this);
197 var pathcoms = filename.split('/');
198 this.gname = pathcoms[pathcoms.length - 2];
199 if (!(this.gname in games)) {
200 ss.emit('open', false);
201 return;
202 }
203 var basename = pathcoms[pathcoms.length - 1];
204 var firstsep = basename.indexOf(':');
205 this.pname = basename.slice(0, firstsep);
206 var fname = basename.slice(firstsep + 1);
207 this.ttyrec = path.join("/dgldir/ttyrec", this.pname, this.gname, fname);
208 this.framebuf = new Buffer(1024);
209 this.frameoff = 0;
210 this.framepush = function(chunk) {
211 /* If this chunk resets the screen, discard what preceded it. */
212 var cgame = games[this.gname];
213 if (bufncmp(chunk, cgame.clear, cgame.clear.length)) {
214 tslog("DGL %s: clearing frame", ss.tag());
215 this.framebuf = new Buffer(1024);
216 this.frameoff = 0;
217 }
218 /* Make sure there's space. */
219 while (this.framebuf.length < chunk.length + this.frameoff) {
220 var nbuf = new Buffer(this.framebuf.length * 2);
221 this.framebuf.copy(nbuf, 0, 0, this.frameoff);
222 this.framebuf = nbuf;
223 if (this.framebuf.length > 65536) {
224 tslog("Warning: DGL %s frame buffer at %d bytes", this.tag(),
225 this.framebuf.length);
226 }
227 }
228 chunk.copy(this.framebuf, this.frameoff);
229 this.frameoff += chunk.length;
230 };
231 this.readchunk = function () {
232 var header = new Buffer(12);
233 fs.read(ss.fd, header, 0, 12, null, function (err, n, buf) {
234 /* Stop recursion if end of file has been reached. */
235 if (err || n < 12)
236 return;
237 var datalen = buf.readUInt32LE(8);
238 //tslog("Allocating %d bytes", datalen);
239 var databuf = new Buffer(datalen);
240 fs.read(ss.fd, databuf, 0, datalen, null, function (err, n, buf) {
241 if (err || n < datalen)
242 return;
243 /* Process the data */
244 ss.framepush(buf);
245 ss.emit("data", buf);
246 tslog("DGL %s: %d bytes", ss.tag(), buf.length);
247 /* Recurse. */
248 ss.readchunk();
249 });
250 });
251 };
252 fs.readFile(filename, {encoding: "utf8"}, function (err, data) {
253 if (err) {
254 ss.emit('open', false);
255 return;
256 }
257 var lines = data.split('\n');
258 ss.h = Number(lines[1]);
259 ss.w = Number(lines[2]);
260 fs.open(ss.ttyrec, "r", function(err, fd) {
261 if (err) {
262 ss.emit('open', false);
263 }
264 else {
265 ss.fd = fd;
266 ss.emit('open', true);
267 tslog("DGL %s: open", ss.tag());
268 ss.readchunk();
269 ss.watcher = fs.watch(ss.ttyrec, function (ev, finame) {
270 if (ev == "change")
271 ss.readchunk();
272 });
273 }
274 });
275 });
276 this.tag = function () {
277 return this.gname + "/" + this.pname;
278 };
279 this.close = function () {
280 this.watcher.close()
281 fs.close(this.fd);
282 this.emit("close");
283 tslog("DGL %s: closed", ss.tag());
284 };
285 }
286 DglSession.prototype = new events.EventEmitter();
287
194 // Also known as WebSocketAndTermSessionClosureGlueFactory 288 // Also known as WebSocketAndTermSessionClosureGlueFactory
195 function wsWatcher(conn, session) { 289 function wsWatcher(conn, session) {
196 var ss = this; // is this even needed? 290 var ss = this; // is this even needed?
197 var dataH = function(buf) { 291 var dataH = function(buf) {
198 conn.sendUTF(JSON.stringify({"t": "d", "d": buf.toString("hex")})); 292 conn.sendUTF(JSON.stringify({"t": "d", "d": buf.toString("hex")}));
629 var gname = matchresult[1]; 723 var gname = matchresult[1];
630 var pname = matchresult[2]; 724 var pname = matchresult[2];
631 var tag = gname + "/" + pname; 725 var tag = gname + "/" + pname;
632 if (chunk[0] == "E") { 726 if (chunk[0] == "E") {
633 tslog("DGL: %s is playing %s: %s", pname, gname, fname) 727 tslog("DGL: %s is playing %s: %s", pname, gname, fname)
634 dglgames[tag] = fname; 728 dglgames[tag] = new DglSession(fname);
635 } 729 }
636 else if (chunk[0] == "C") { 730 else if (chunk[0] == "C") {
637 tslog("DGL: %s started playing %s: %s", pname, gname, fname) 731 tslog("DGL: %s started playing %s: %s", pname, gname, fname)
638 dglgames[tag] = fname; 732 dglgames[tag] = new DglSession(fname);
639 } 733 }
640 else if (chunk[0] == "D") { 734 else if (chunk[0] == "D") {
641 tslog("DGL: %s finished playing %s: %s", pname, gname, fname) 735 tslog("DGL: %s finished playing %s: %s", pname, gname, fname)
736 dglgames[tag].close();
642 delete dglgames[tag]; 737 delete dglgames[tag];
643 } 738 }
644 else { 739 else {
645 tslog("Watcher says: %s", chunk) 740 tslog("Watcher says: %s", chunk)
646 } 741 }