shithub: treason

ref: 3f03592d6961c9f33b681b3269803739766b0c4b
dir: treason/main.c

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <mouse.h>
#include <keyboard.h>
#include <thread.h>
#include "frame.h"
#include "misc.h"
#include "stream.h"
#include "decoder.h"

int mainstacksize = 128*1024;

static Image *curim;
static uvlong lastframe;

static void
drawframe(Frame *f)
{
	uvlong x, end, left;
	static uvlong delay;
	Rectangle r;

	lockdisplay(display);

	if(curim != nil && (Dx(curim->r) != f->w || Dy(curim->r) != f->h)){
		freeimage(curim);
		curim = nil;
	}
	r = Rect(0,0,f->w,f->h);
	if(curim == nil)
		curim = allocimage(display, r, RGB24, 0, DNofill);
	loadimage(curim, r, f->rgb, f->w*f->h*3);

	if(lastframe == 0)
		lastframe = nanosec();

	end = lastframe + f->dt - delay;
	while(1){
		x = nanosec();
		if(x >= end)
			break;
		left = end - x;
		if(left > 750000000ULL)
			sleep(70);
		else if(left > 250000000ULL)
			sleep(20);
		else if(left > 100000000ULL)
			sleep(1);
	}

	x = nanosec();
	if(Dx(r) < Dx(screen->r) && Dy(r) < Dy(screen->r))
		r = rectsubpt(screen->r, divpt(Pt(Dx(r)-Dx(screen->r), Dy(r)-Dy(screen->r)), 2));
	else
		r = screen->r;
	draw(screen, r, curim, nil, ZP);
	flushimage(display, 1);
	unlockdisplay(display);

	delay = nanosec() - x;
	lastframe += f->dt;

	free(f);
}

void
threadmain(int argc, char **argv)
{
	enum {
		Cframe,
		Cplayerdone,
		Cmouse,
		Ckeyboard,
		Cresize,
		Cnum,
	};
	Frame *frame;
	Mousectl *mctl;
	Keyboardctl *kctl;
	Rune key;
	Mouse m;
	char *s;
	Stream *stream;
	Decoder *d;
	int i, end, done, res, nstreams;
	Alt a[Cnum+1] =
	{
		[Cframe] = { nil, &frame, CHANRCV },
		[Cplayerdone] = { nil, nil, CHANRCV },
		[Cmouse] = { nil, &m, CHANRCV },
		[Ckeyboard] = { nil, &key, CHANRCV },
		[Cresize] =  { nil, nil, CHANRCV },
		[Cnum] = { nil, nil, CHANEND },
	};

	ARGBEGIN{
	}ARGEND

	if(argc < 1)
		sysfatal("usage");

	nproc = atoi((s = getenv("NPROC")) != nil ? s : "1");

	srand(nanosec());
	if(initdraw(nil, nil, "treason") < 0)
		sysfatal("initdraw: %r");
	flushimage(display, 1);
	display->locking = 1;
	unlockdisplay(display);
	if((mctl = initmouse(nil, screen)) == nil)
		sysfatal("initmouse: %r");
	if((kctl = initkeyboard(nil)) == nil)
		sysfatal("initkeyboard: %r");

	a[Cmouse].c = mctl->c;
	a[Cresize].c = mctl->resizec;
	a[Ckeyboard].c = kctl->c;

	for(end = i = 0; !end && i < argc; i++){
		draw(screen, screen->r, display->black, nil, ZP);
		if((stream = Sopen(argv[i], &nstreams)) == nil)
			sysfatal("%r");
		if((d = Dopen(stream)) == nil)
			sysfatal("%r");

		a[Cframe].c = d->frames;
		a[Cplayerdone].c = d->finished;
		lastframe = 0;

		for(done = 0; !done && !end;){
			res = alt(a);
			switch(res){
			case Cframe:
				drawframe(frame);
				break;

			case Cplayerdone:
				done = 1;
				break;

			case Cmouse:
				break;

			case Ckeyboard:
				end = key == 'q' || key == Kdel;
				done = key == '\n';
				break;

			case Cresize:
				lockdisplay(display);
				if(getwindow(display, Refnone) < 0)
					sysfatal("getwindow: %r");
				freeimage(curim);
				curim = nil;
				draw(screen, screen->r, display->black, nil, ZP);
				flushimage(display, 1);
				unlockdisplay(display);
				break;
			}
		}

		Dclose(d);
		for(i = 0; i < nstreams; i++)
			Sclose(stream+i);
	}

	threadexitsall(nil);
}