// You may freely copy, distribute and reuse the code in this example.
// The author disclaims any warranty of any kind, expressed or implied,
// as to its fitness for any particular use.

// Grab20 and Capture written by Peter Eisch.

/* Generated by Interface Builder */

#import "Grab20.h"
#import "other.h"
#import <appkit/Application.h>
#import <appkit/Button.h>
#import <appkit/Listener.h>
#import <appkit/Speaker.h>
#import <appkit/SavePanel.h>
#import <appkit/Slider.h>
#import <appkit/graphics.h>
#import <appkit/nextstd.h>
#import <dpsclient/wraps.h>
#import <objc/List.h>
#import <streams/streams.h>
#import <sys/timeb.h>
#import <appkit/Panel.h>
#import <defaults/defaults.h>

@implementation Grab20

- drawSelf:(const NXRect *)rects :(int)count
{
	[super drawSelf:rects :count];
	NXSetColor(NX_COLORRED);
	PSrectstroke(grabRect.origin.x,
			grabRect.origin.y,
			grabRect.size.width,
			grabRect.size.height);
	return self;
}

- setCount:sender
{
	[field setIntValue:[frameSlider intValue]];
	return self;
}

- begin:sender
{
	int i;
	NXRect region, area;
	time_t myTime;
	id list, spanel;
	char tmp[255];

	int count = [frameSlider intValue];
	int imageWidth = [width intValue];
	int imageHeight = [height intValue];
	int originx = [x intValue];
	int originy = [y intValue];

	[startGrab setStringValue:""];
	[stopGrab setStringValue:""];
	[startWrite setStringValue:""];
	[stopWrite setStringValue:""];
	
	if ((imageWidth <= 0) || (imageHeight <= 0)) {
		NXRunAlertPanel("No Region",
				"You need to select a region to grab.",
				NULL,NULL,NULL);
		return self;
	}
	
	list = [[List alloc] initCount:count];
	
	region.size.width = imageWidth;
	region.size.height = imageHeight;
	region.origin.x = 0.0;
	region.origin.y = 0.0;

	area.size.width = region.size.width;
	area.size.height = region.size.height;
	area.origin.x = originx;
	area.origin.y = originy;
	
	for (i = 0; i < count; i++) {
		[list addObject:[[NXImage alloc] initSize:&region.size]];
	}
	
	[startGrab setStringValue:"Building Speed Cache"];

	for (i = 0; i < count; i++) {
		id image = [list objectAt:i];
		if ([image lockFocus])
			[image unlockFocus];
		else NXLogError("problem locking focus on %i\n", i);
	}
	
	myTime = time(0);
	sprintf(tmp, "%s", ctime(&myTime));
	[startGrab setStringValue:tmp];

	for (i = 0; i < count; i++) {
		[self grabIn:[list objectAt:i] fromRect:&area toRect:&region];
	}

	myTime = time(0);
	sprintf(tmp, "%s", ctime(&myTime));
	[stopGrab setStringValue:tmp];

	spanel = [SavePanel new];
	[spanel setRequiredFileType:"anim"];
	if ([spanel runModal]) {
		char * path;
		char dir[255];
		char file[255];
		char tmpdir[255];
		char tmpname[255];
		
		path = (char *)[spanel filename];		
		sprintf(tmpdir,"/bin/mkdir %s\n", path);
		system(tmpdir);

		parsePath(path, dir, file);
		sprintf(tmpdir, "%s/%s", path, file);

		myTime = time(0);
		sprintf(tmp, "%s", ctime(&myTime));
		[startWrite setStringValue:tmp];

		for (i = 0; i < count; i++) {
			NXStream * data;
			
			data = NXOpenMemory(NULL, 0, NX_READWRITE);
			sprintf(tmpname, "%s.%d.tiff", tmpdir, (i+1));
			[[list objectAt:i] writeTIFF:data];			
			NXSeek(data, 0, NX_FROMSTART);
			NXSaveToFile(data, tmpname);
			NXCloseMemory(data, NX_FREEBUFFER);
		}
		myTime = time(0);
		sprintf(tmp, "%s", ctime(&myTime));
		[stopWrite setStringValue:tmp];

		if ([open state]) {
			int ok;
			
			[[NXApp appSpeaker] setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
			[[NXApp appSpeaker] openFile:[spanel filename] ok:&ok];
    
			if (!ok) {
					NXRunAlertPanel(NULL, "Couldn't open %s", NULL, NULL, NULL, [spanel filename]);
			}
		}
	
	}
		
	[list freeObjects];
	[list free];
	
	return self;
}

- appDidInit:sender
{
	[self start:self];
	[self display];
	return self;
}

- appDidBecomeActive:sender
{
	[self start:self];
	[self display];
	return self;
}

+ initialize /* save compile and test it.  make sure the NXReadDefault() stuff is correct.  document the code */
{
	const NXDefaultsVector CaptureDefaults = {
			{ MAX_X, "590" },
			{ MAX_Y, "492" },
			{ MAX_WIDTH, "640"},
			{ MAX_HEIGHT, "480" },
			{ NULL, NULL }
	};

	NXRegisterDefaults([NXApp appName], CaptureDefaults);

	return self;
}

- update:sender
{
	int maxX = atoi(NXReadDefault([NXApp appName], MAX_X));
	int maxY = atoi(NXReadDefault([NXApp appName], MAX_Y));
	int maxWid = atoi(NXReadDefault([NXApp appName], MAX_WIDTH));
	int maxHei = atoi(NXReadDefault([NXApp appName], MAX_HEIGHT));
	int val = [sender intValue];
	int tg = [sender tag];

	switch(tg) {
		case 0:
			if (val > maxWid) val = maxWid;
			if (val < 0) val = 0;
			break;
		case 1:
			if (val > maxHei) val = maxHei;
			if (val < 0) val = 0;
			break;
		case 2:
			if (val > maxX) val = maxX;
			if (val < 0) val = 0;
			break;
		case 3:
			if (val > maxY) val = maxY;
			if (val < 0) val = 0;
			break;
	}
	[sender setIntValue:val];
	if ([x intValue] < 0) [x setIntValue:0];
	if ([x intValue] > maxWid) [x setIntValue:maxWid];
	if ([y intValue] < 0) [y setIntValue:0];
	if ([y intValue] > maxHei) [y setIntValue:maxHei];
	if ([width intValue] > (maxWid - [x intValue])) 
		[width setIntValue:(maxWid - [x intValue])];
	if ([height intValue] > (maxHei - [y intValue])) 
		[height setIntValue:(maxHei - [y intValue])];
	
	[horiSlide setIntValue:[y intValue]];
	[vertSlide setIntValue:[x intValue]];
	[widSlide setIntValue:[width intValue]];
	[heiSlide setIntValue:[height intValue]];
	
	NXSetRect(&grabRect,
		[x floatValue], [y floatValue],
		[width floatValue], [height floatValue]);
		
	[self display];
	return self;
}

- mouseDown:(NXEvent *)theEvent
{
  NXEvent anEvent = *theEvent;
  NXPoint point1 = theEvent->location,point2;
  int oldMask;
  BOOL dragged = NO;
  
	[self convertPoint:&point1 fromView:nil];
  oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
	while(anEvent.type != NX_MOUSEUP) {
		NXGetOrPeekEvent(DPSGetCurrentContext(),
			&anEvent, NX_MOUSEUPMASK|NX_LMOUSEDRAGGEDMASK,NX_FOREVER,10,0);
		if (anEvent.type == NX_MOUSEDRAGGED) {
			dragged = YES;
			point2 = anEvent.location;
			[self convertPoint:&point2 fromView:nil];
			if (point1.x < point2.x) {
				grabRect.origin.x = point1.x;
				grabRect.size.width = point2.x - point1.x;
			} else {
				grabRect.origin.x = point2.x;
				grabRect.size.width = point1.x - point2.x;
			}
			if (point1.y < point2.y) {
				grabRect.origin.y = point1.y;
				grabRect.size.height = point2.y - point1.y;
			} else {
				grabRect.origin.y = point2.y;
				grabRect.size.height = point1.y - point2.y;
			}

			NXIntersectionRect(&bounds, &grabRect);
			[x setIntValue:(int)grabRect.origin.x];
			[y setIntValue:(int)grabRect.origin.y];
			[width setIntValue:(int)grabRect.size.width];
			[height setIntValue:(int)grabRect.size.height];
			[self display];
		}
	}
	if(!dragged) NXSetRect(&grabRect,0.0,0.0,0.0,0.0);
	[horiSlide setIntValue:(int)grabRect.origin.x];
	[vertSlide setIntValue:(int)grabRect.origin.y];
	[widSlide setIntValue:(int)grabRect.size.width];
	[heiSlide setIntValue:(int)grabRect.size.height];
	[x setIntValue:[horiSlide intValue]];
	[y setIntValue:[vertSlide intValue]];
	[width setIntValue:[widSlide intValue]];
	[height setIntValue:[heiSlide intValue]];
	[self display];

  [window setEventMask:oldMask];
  return self;
}

- updateHori:sender
{
	[x setIntValue:[sender intValue]];
	grabRect.origin.x = [sender floatValue];
	[self display];
	return self;
}

- updateVert:sender
{
	[y setIntValue:[sender intValue]];
	grabRect.origin.y = [sender floatValue];
	[self display];
	return self;
}

- updateWid:sender
{
	[width setIntValue:[sender intValue]];
	grabRect.size.width = [sender floatValue];
	[self display];
	return self;
}

- updateHei:sender
{
	[height setIntValue:[sender intValue]];
	grabRect.size.height = [sender floatValue];
	[self display];
	return self;
}

- windowWillResize:sender toSize:(NXSize *)frameSize
{
	if (frameSize->width > 661) frameSize->width = 661;
	if (frameSize->height > 531) frameSize->height = 531;	
	return self;
}

- changeIn:sender
/* 
 *  to set the video in
 */
{
	[self selectInput:([[in selectedCell] tag] + 1)];
	return self;
}

- initFrame:(const NXRect *)dRect
{
	[super initFrame:dRect];
	NXSetRect(&grabRect, 296.0, 216.0, 48.0, 48.0);
	return self;
}

@end
