#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

#include <dos/dos.h>
#include <exec/exec.h>
#include <devices/serial.h>
#include <jpeg/jpeg.h>
#include <cybergraphics/cybergraphics.h>
#include <intuition/intuition.h>
#include <libraries/asl.h>

//#include <clib/exec_protos.h>		// TetiSoft
//#include <clib/dos_protos.h>		// TetiSoft
//#include <clib/intuition_protos.h>	// TetiSoft
//#include <clib/asl_protos.h>		// TetiSoft

#include <proto/exec.h>			// TetiSoft
#include <proto/dos.h>			// TetiSoft
#include <proto/intuition.h>		// TetiSoft
#include <proto/asl.h>			// TetiSoft

#include <clib/alib_protos.h>
#include <clib/jpeg_protos.h>
#include <clib/cybergraphics_protos.h>

//#include <pragma/exec_lib.h>		// TetiSoft
//#include <pragma/dos_lib.h>		// TetiSoft
//#include <pragma/intuition_lib.h>	// TetiSoft
//#include <pragma/asl_lib.h>		// TetiSoft

#include <pragma/jpeg_lib.h>
#include <pragma/cybergraphics_lib.h>

#include "Camedia.h"

// Added by TetiSoft (Since 01-Mar-2000, __AMIGADATE__ is one day in the future):
char VerString[]="$VER: Camedia " VERSION " " __AMIGADATE__;

struct Library *JpegBase, *CyberGfxBase;

void info_f(enum Camera_Speed cs, char* error_msg);
void preview_f(enum Camera_Speed cs, char* error_msg);
void do_f(int user_min, int user_max, char *name, long speed, enum Camera_Speed cs, int action, char* error_msg);	// TetiSoft: Added enum

#ifdef __SASC
void __regargs __chkabort(void)
{
}
#endif

// void main(int argc, char *argv[]) {	// TetiSoft: Why not return result code to the shell?
int main(void) {	// TetiSoft: We return result and don't need params
	enum arg {
		NONE = -2,
		WRONG_MODE = -1,
		DEVICE = 0, 
		UNIT, 
		SPEED, 
		INFO,
		PREVIEW,
		TAKE_PICTURE,
		RETR,
		THUMBNAILS,
		DEL,
		FROM,
		TO,
		NAME};
		
	char *input_mask = "DEVICE/K,UNIT/N,SPEED/N,INFO/S,PREVIEW/S,TAKE_PICTURE/S,RETR/S,THUMBNAILS/S,DEL/S,FROM/N,TO/N,NAME/K";
	enum Camera_Speed cs;
	long speed/*=0*/;	// TetiSoft: No init necessary
	int from=0, to=0, i, unit, modus = NONE;	// TetiSoft: from and to now initialized
	LONG array[12];
	struct RDArgs *rdargs;
	char devicename[256], picture_name[256], error_msg[256];
	
	error_msg[0]='\0';

	for (i=0; i<12; i++) array[i]=0;
	rdargs=ReadArgs(input_mask, array, NULL);
	if (rdargs==NULL) {
		printf("An error occured in ReadArgs(%s, array, NULL);\n", input_mask);
//		exit(0);		// TetiSoft: No return code
		return RETURN_FAIL;	// Added by TetiSoft
	}
	
	/* DEVICE/K */
	if (array[DEVICE]==0) strcpy(devicename, "serial.device");
	else strcpy(devicename, (char *) array[DEVICE]);
	
	/* UNIT/N */
	if (array[UNIT]!=0) unit=*((long *) array[UNIT]);
	else unit=0;
	
	/* SPEED/N */
	if (array[SPEED]==0) {
		speed=19200;
		cs=CAMERA_SPEED_19200;
	} else {
		speed=*((long *) array[SPEED]);
	
		switch (speed) {
			case 9600:
				cs=CAMERA_SPEED_9600;
				break;
			case 19200:
				cs=CAMERA_SPEED_19200;
				break;
			case 38400:
				cs=CAMERA_SPEED_38400;
				break;			
			case 57600:
				cs=CAMERA_SPEED_57600;
				break;
			case 115200:
				cs=CAMERA_SPEED_115200;
				break;
			case 230400:			// Added by TetiSoft
				cs=CAMERA_SPEED_230400;	// Added by TetiSoft
				break;			// Added by TetiSoft
			default:
				// cs=CAMERA_SPEED_Unknown;
				printf("Unknown speed, must be either 9600, 19200, 38400, 57600, 115200 or 230400\n");	// TetiSoft: Added 230400
//				exit(0);		// TetiSoft: No return code
				FreeArgs(rdargs);	// Added by TetiSoft
				return RETURN_ERROR;	// Added by TetiSoft
		}
	}
		
	/* INFO/S */ 
	if ((int) array[INFO]) modus=INFO;
	
	/* PREVIEW/S */
	if ((int) array[PREVIEW]) {
		if (modus!=NONE) {
			printf("Choose exactly one mode!\n");
			modus=WRONG_MODE;
		} else
			modus=PREVIEW;
	}
	
	/* TAKE_PICTURE/S */
	if ((int) array[TAKE_PICTURE]) {
		if (modus!=NONE) {
			printf("Choose exactly one mode!\n");
			modus=WRONG_MODE;
		} else 
			modus=TAKE_PICTURE;
	}
	
	/* RETR/S */
	if ((int) array[RETR]) {
		if (modus!=NONE) {
			printf("Choose exactly one mode!\n");
			modus=WRONG_MODE;
		} else {
			modus=RETR;
		}
	}
	
	/* THUMBNAILS/S */
	if ((int) array[THUMBNAILS]) {
		if (modus!=NONE) {
			printf("Choose exactly one mode!\n");
			modus=WRONG_MODE;
		} else {
			modus=THUMBNAILS;
		}
	}
	
	/* DEL/S */
	if ((int) array[DEL]) {
		if (modus!=NONE) {
			printf("Choose exactly one mode!\n");
			modus=WRONG_MODE;
		} else {
			modus=DEL;
		}
	}
	
	if ((modus==RETR) || (modus==THUMBNAILS) || (modus==DEL)) {
		/* FROM/N */
		if (array[FROM]!=0) from=(int) *((long *) array[FROM]);
//		else from=0;	// TetiSoft: No longer necessary
	
		/* TO/N */
		if (array[TO]!=0) to=(int) *((long *) array[TO]);
//		else to=0;	// TetiSoft: No longer necessary
	
		/* NAME/K */
		if (array[NAME]==0) strcpy(picture_name, "Picture");
		else strcpy(picture_name, (char *) array[NAME]);
	}
	
	FreeArgs(rdargs);
	
	if (modus==NONE) {
		printf("Choose one mode, which is Either INFO, PREVIEW, RETR, THUMBNAILS or DEL\n");
//		exit(0);		// TetiSoft: No return code
		return RETURN_ERROR;	// Added by TetiSoft
	}
	
	bootstrap(devicename, unit, error_msg);
	if (*error_msg!=0) {
		printf("There was an error in bootstrap: %s\n", error_msg);
//		exit(0);		// TetiSoft: No return code
		return RETURN_ERROR;	// Added by TetiSoft
	}
	
	switch (modus){
		
		case THUMBNAILS:
			if (from==0) from=1;
			if (to==0) to=255;
			do_f(from, to, picture_name, speed, cs, 0, error_msg);
			break;
		
		case RETR:
			if (from==0) from=1;
			if (to==0) to=255;
			do_f(from, to, picture_name, speed, cs, 1, error_msg);
			break;
		
		case DEL:
			if (from==0) from=1;
			if (to==0) to=255;
			do_f(from, to, picture_name, speed, cs, 2, error_msg);
			break;
			
		case TAKE_PICTURE:
			// for this short code, I don't define a seperate function:)
			init(cs, error_msg);
			if (*error_msg==0) {
				TakeAction(AC_Take_Picture, 0, error_msg);
				// overwrite timeout_error, which is ok in this single case
				*error_msg=0;
			}				
			break;
		
		case PREVIEW:
			preview_f(cs, error_msg);
			break;
			
		case INFO:
			info_f(cs, error_msg);
			break;
			
		default:
			printf("ops, there is somthing wrong with the mode\n");
	}
	clean(100);
	if (*error_msg!=0) {
		printf("There was an error: %s\n", error_msg);
		return RETURN_ERROR;
	} else {
		printf("Well, all done\n");
		return RETURN_OK;
	}
}


void info_f(enum Camera_Speed cs, char* error_msg) {
	int ResVal=Unknown_Resolution;		// Added by TetiSoft
	enum Resolution *re=&ResVal;		// TetiSoft: Added enum, fixed NULL init
	time_t cVal=0;				// Added by TetiSoft
	time_t *c=&cVal;			// TetiSoft: Fixed NULL init
	time_t TDVal=0;				// Added by TetiSoft
	time_t *TimeDate=&TDVal;		// TetiSoft: Fixed NULL init
	long ssVal=0;				// Added by TetiSoft
	long *ss=&ssVal;			// TetiSoft: Fixed NULL init
	int aVal=Unknown_Aperture;		// Added by TetiSoft
	enum Aperture *a=&aVal;			// TetiSoft: Added enum, fixed NULL init
	int cmVal=Unknown_Color_Mode;		// Added by TetiSoft
	enum Color_Mode *cm=&cmVal;		// TetiSoft: Added enum, fixed NULL init
	int fmVal=Unknown_Flash_Mode;		// Added by TetiSoft
	enum Flash_Mode *fm=&fmVal;		// TetiSoft: Added enum, fixed NULL init
	int noftVal=0;				// Added by TetiSoft
	int *noft=&noftVal;			// TetiSoft: Fixed NULL init
	int noflVal=0;				// Added by TetiSoft
	int *nofl=&noflVal;			// TetiSoft: Fixed NULL init
	int bcVal=0;				// Added by TetiSoft
	int *bc=&bcVal;				// TetiSoft: Fixed NULL init
	int aohtVal=0;				// Added by TetiSoft
	int *aoht=&aohtVal;			// TetiSoft: Fixed NULL init
	int aosoftVal=0;			// Added by TetiSoft
	int *asoft=&aosoftVal;			// TetiSoft: Fixed NULL init
	int lbVal=0;				// Added by TetiSoft
	int *lb=&lbVal;				// TetiSoft: Fixed NULL init
	int latVal=0;				// Added by TetiSoft
	int *lat=&latVal;			// TetiSoft: Fixed NULL init
//	int AELVal=0;				// Added by TetiSoft
//	int *AEL_WBL=&AELVal;			// TetiSoft: Fixed NULL init
//	int FEVal=0;				// Added by TetiSoft
//	int *Fisheye=&FEVal;			// TetiSoft: Fixed NULL init
//	int WideVal=0;				// Added by TetiSoft
//	int *Wide=&WideVal;			// TetiSoft: Fixed NULL init
//	int ZoomVal=0;				// Added by TetiSoft
//	int *Digital_Zoom=&ZoomVal;		// TetiSoft: Fixed NULL init
//	int BAWVal=0;				// Added by TetiSoft
//	int *BAW=&BAWVal;			// TetiSoft: Fixed NULL init
//	int LCDBVal=0;				// Added by TetiSoft
//	int *LCD_Brightness=&LCDBVal;		// TetiSoft: Fixed NULL init
//	int FTVal=0;				// Added by TetiSoft
//	int *Frames_Taken=&FTVal;		// TetiSoft: Fixed NULL init
//	int PSVal=0;				// Added by TetiSoft
//	int *ProtectionState=&PSVal;		// TetiSoft: Fixed NULL init
	int psofVal=0;				// Added by TetiSoft
	int *psof=&psofVal;			// TetiSoft: Fixed NULL init
//	int ccsVal=CAMERA_SPEED_Unknown;	// Added by TetiSoft
//	enum Camera_Speed *ccs=&ccsVal;		// TetiSoft: Added enum, fixed NULL init
//	int brcVal=Unknown_Bright_Contrast;	// Added by TetiSoft
//	enum Bright_Contrast *brc=&brcVal;	// TetiSoft: Added enum, fixed NULL init
	int wbVal=Unknown_White_Balance;	// Added by TetiSoft
	enum White_Balance *wb=&wbVal;		// TetiSoft: Added enum, fixed NULL init
	int dfVal=Unknown_Date_Format;		// Added by TetiSoft
	enum Date_Format *df=&dfVal;		// TetiSoft: Added enum, fixed NULL init
	int emVal=Unknown_Exp_Meter;		// Added by TetiSoft
	enum Exp_Meter *em=&emVal;		// TetiSoft: Added enum, fixed NULL init
	long amlVal=0;				// Added by TetiSoft
	long *aml=&amlVal;			// TetiSoft: Fixed NULL init
	long locfVal=0;				// Added by TetiSoft
	long *locf=&locfVal;			// TetiSoft: Fixed NULL init
	long loctVal=0;				// Added by TetiSoft
	long *loct=&loctVal;			// TetiSoft: Fixed NULL init
	long adl=0;				// Added by TetiSoft
	long *AudioDataLength=&adl;		// TetiSoft: Fixed NULL init
	int lmVal=Unknown_Lens_Mode;		// Added by TetiSoft
	enum Lens_Mode *lm=&lmVal;		// TetiSoft: Added enum, fixed NULL init
	int i, max;
	char buf[1024];
	long buflen;				// Added by TetiSoft

	init(cs, error_msg);
	if (*error_msg!=0) return;

	Get_Resolution(re, error_msg);
	if (*error_msg!=0) return;
	printf("Resolution=%s\n", dump_Resolution(*re));

	Get_Clock(c, error_msg);
	if (*error_msg!=0) return;
	printf("Clock=%s", asctime(localtime(c)));	// TetiSoft: stripped \n
		
	Get_Shutter_Speed(ss, error_msg);
	if (*error_msg!=0) return;
	printf("Shutter_Speed=%d\n", *ss);

	Get_Aperture(a, error_msg);
	if (*error_msg!=0) return;
	printf("Aperture=%s\n", dump_Aperture(*a));

	Get_Color_Mode(cm, error_msg);
	if (*error_msg!=0) return;
	printf("Color_Mode=%s\n", dump_Color_Mode(*cm));
		
	Get_Flash_Mode(fm, error_msg);
	if (*error_msg!=0) return;
	printf("Flash_Mode=%s\n", dump_Flash_Mode(*fm));

	Get_Num_of_Frames_Taken(noft, error_msg);
	if (*error_msg!=0) return;
	printf("Number of Frames Taken=%d\n", *noft);
	max=*noft;
		
	Get_Num_of_Frames_Left(nofl, error_msg);
	if (*error_msg!=0) return;
	printf("Number of Frames Left=%d\n", *nofl);
		
	Get_Battery_Capacity(bc, error_msg);
	if (*error_msg!=0) return;
	printf("Battery Capacity=%d\n", *bc);
/*
	Get_Comm_Speed(ccs, error_msg);
  	if (*error_msg!=0) return;
 	printf("Comm Speed=%s\n", dump_Camera_Speed(*ccs));

	Get_Bright_And_Contrast(brc, error_msg);
 	if (*error_msg!=0) return;
	printf("Bright and Contrast=%s\n", dump_Bright_Contrast(*brc));
*/
	Get_White_Balance(wb, error_msg);
	if (*error_msg!=0) return;
	printf("White Balance=%s\n", dump_White_Balance(*wb));
	
	Get_Autoshut_on_Host_Timer(aoht, error_msg);
	if (*error_msg!=0) return;
	printf("Autoshut on Host Timer=%d\n", *aoht);
		
	Get_Autoshut_on_Field_Timer(asoft, error_msg);
	if (*error_msg!=0) return;
	printf("Autoshut on Field Timer=%d\n", *asoft);
	
	Get_Available_Memory_Left(aml, error_msg);
	if (*error_msg!=0) return;
	printf("Available Memory Left=%d [Bytes]\n", *aml);
		
	Get_Lens_Mode(lm, error_msg);
	if (*error_msg!=0) return;
	printf("Lens Mode=%s\n", dump_Lens_Mode(*lm));
		
	Get_LCD_Brightness(lb, error_msg);
	if (*error_msg!=0) return;
	printf("LCD Brightness=%d\n", *lb);
		
	Get_LCD_Autoshut_Timer(lat, error_msg);
	if (*error_msg!=0) return;
	printf("LCD Autoshut Timer=%d\n", *lat);
		
	Get_Date_Format(df, error_msg);
	if (*error_msg!=0) return;
	printf("Date Format=%s\n", dump_Date_Format(*df));
	
	Get_Exp_Meter(em, error_msg);
	if (*error_msg!=0) return;
	printf("Exp Meter=%s\n", dump_Exp_Meter(*em));
/*
	Get_Optical_Mode(AEL_WBL, Fisheye, Wide, Digital_Zoom, BAW, error_msg);
	if (*error_msg!=0) return;
	printf("AEL_WB=%dL, Fisheye=%d, Wide=%d, Digital_Zoom=%d, BAW=%d\n", *AEL_WBL, *Fisheye, *Wide, *Digital_Zoom, *BAW);
*/
	Get_Camera_ID(buf, &buflen, error_msg);			// TetiSoft: Fixed NULL pointer
	if (*error_msg!=0) return;
	printf("Camera ID=%s\n", (char *) buf);
		
	Get_Serial_Number(buf, &buflen, error_msg);		// TetiSoft: Fixed NULL pointer
	if (*error_msg!=0) return;
	printf("Serial Number=%s\n", buf);
		
	Get_Version(buf, &buflen, error_msg);			// TetiSoft: Fixed NULL pointer
	if (*error_msg!=0) return;
	printf("Version=%s\n", buf);
		
	Get_Model((char *) buf, &buflen, error_msg);		// TetiSoft: Fixed NULL pointer
	if (*error_msg!=0) return;
	printf("Model=%s\n", buf);
/*
	Get_Camera_Summery_Data(re, LCD_Brightness, Frames_Taken, error_msg);
	if (*error_msg!=0) return;
	printf("Resolution=%s, LCD Brightness=%d, Frames Taken=%d\n", dump_Resolution(*re), *LCD_Brightness, *Frames_Taken);
*/
	Get_Manufacturer((char *) buf, &buflen, error_msg);	// TetiSoft: Fixed NULL pointer
	if (*error_msg!=0) return;
	printf("Manufacturer=%s\n", buf);

	if (max>0) {
		i=1;
		printf("There are %d frames taken\n", max);
		while (i<=max && i<255) {
			printf("Frame[%d]:\n", i);
			Get_Length_of_Frame(i, locf, error_msg);
			if (*error_msg!=0) return;
			printf("   Length=%d\n", *locf);
		
			Get_Length_of_Thumbnail(i, loct, error_msg);
			if (*error_msg!=0) return;
			printf("   Length of Thumbnail=%d\n", *loct);
				Get_Protect_State_of_Frame(i, psof, error_msg);
			if (*error_msg!=0) return;
			printf("   Protection=%d\n", *psof);
			
			Get_Picture_Summery_Data(i, AudioDataLength, re, psof, TimeDate, error_msg);	// TetiSoft: Fixed three NULL pointers
			if (*error_msg!=0) return;
//			printf("   time stamp=%s\n", asctime(localtime(TimeDate)));	// TetiSoft: disabled
			printf("   Resolution=%s\n   time stamp=%s\n", dump_Resolution(*re), asctime(localtime(TimeDate)));	// TetiSoft: Also show resolution
			i++;
		}
	} else printf("There are no pictures in the camera\n");
/*
	{
		// Added by TetiSoft: Reset serial speed of camera to default for next prg call, doesn't seem to work :-(
		L1 r, initbyte=Computer_Initialization_Byte;
		if (!error_msg[0]) send(&initbyte, 1, error_msg);
		if (!error_msg[0]) read(&r, 1, error_msg);
		if (!error_msg[0]) {
			if (r==Camera_Signature) Set_Comm_Speed(CAMERA_SPEED_INIT, error_msg);
			else printf("unexpected answer %d\n", r);
		}
		if (error_msg[0]) printf("%s\n", error_msg);
	}
*/
}


void do_f(int user_min, int user_max, char *picture_name, long speed, enum Camera_Speed cs, int action, char* error_msg) {
	time_t t;
	time_t time1, time2;
	char name[255], comment[80];
	int i, max, passedtime, NoFT;
	long size=0;
	struct tm *tm_s;
	long adl;	// Added by TetiSoft
	int res;	// Added by TetiSoft
	int prot;	// Added by TetiSoft
	
	if ((user_min<1) || (user_max<1) || (user_min>user_max)) {
		printf("Can't accept such ranges\n");
		return;
	}
	
	init(cs, error_msg);
	if (*error_msg!=0) return;

	Get_Num_of_Frames_Taken(&NoFT, error_msg);
	if (*error_msg!=0) return;
	
	max=(int) NoFT;
	if (max==0) {
		printf("No pictures are stored in the camera.\n");
		return;
	}

	if (max<user_min) {
		printf("There are %d pictures in the camera, not one more.\n", max);
		printf("user_min=%d\n", user_min);
		return;
	}

	if (max<user_max) user_max=max;
	
	switch(action) {
		case 0:
			printf("Will get thumbnails %d to %d\n", user_min, user_max);
			break;
		case 1: 
			printf("Will get pictures %d to %d\n", user_min, user_max);
			break;
		case 2: 
			printf("Will delete pictures %d to %d\n", user_min, user_max);
			break;
		default:
			printf("action has a wrong value %d\n", action);
	}
	
	for(i=user_min; i<=user_max; i++) {
	
		if (action==0) {
			sprintf(name, "%s_%d.jpeg", picture_name, i);
			Get_Length_of_Thumbnail(i, &size, error_msg);
			if (*error_msg!=0) return;
			printf("Get thumbnail %d, size %d bytes, transfer time: about %d s\n", i, size, (int) 3+size/(speed/10));
		}
	
		if (action==1) {
			sprintf(name, "%s_%d.jpeg", picture_name, i);		
			Get_Length_of_Frame(i, &size, error_msg);
			if (*error_msg!=0) return;
			printf("Get picture %d, size %d bytes, transfer time: about %d s\n", i, size, (int) 3+size/(speed/10));
		}

		Get_Picture_Summery_Data(i, &adl, &res, &prot, &t, error_msg);	// TetiSoft: Fixed three NULL pointers
		if (*error_msg!=0) return;
			
		tm_s = localtime(&t);
		if (((tm_s->tm_year)<95) && ((tm_s->tm_year)>105)) strcpy(comment, "no date set");
		else strftime(comment, 80, "%d-%b-%Y %H:%M:%S", tm_s );
	
		time(&time1);
		switch (action) {
			case 0:
				save_Thumbnail(i, name, comment, error_msg);
				if (*error_msg!=0) return;
				break;
			case 1:
				save_Frame(i, name, comment, error_msg);
				if (*error_msg!=0) return;
				break;
			case 2:
				SetIntegerRegister(Cmd_Set_Current_Frame_Number, (L1) i, error_msg);
				if (*error_msg!=0) return;
				TakeAction(AC_Erase_Current_Frame, 0, error_msg);
				if (*error_msg!=0) return;
				break;
			default:
				printf("action has a wrong value %d\n", action);
		}				
		time(&time2);
		passedtime=(int) time2-time1;
		if (passedtime==0) passedtime=1;
//		if ((action==0) || (action==1)) printf("%s, size %d, transfered in %d s, %5.0f cps\n", name, size, passedtime, ((float) size) / ((float) passedtime) );	// TetiSoft: Why float?
		if ((action==0) || (action==1)) printf("%s, size %d, transfered in %d s, %d cps\n", name, size, passedtime, size/passedtime);				// TetiSoft: int should do it
	} // end for
}


void preview_f(enum Camera_Speed cs, char* error_msg) {
	struct JPEGDecHandle *jph;
	struct Screen *scr;
	struct Window *win;
	struct Message *msg;
	UBYTE *buffer/*=NULL*/;
	UBYTE *frame_buffer/*=NULL*/;
	ULONG DisplayID;
	UWORD DisplayDepth;
	struct ScreenModeRequester *smr;

	int err;
	ULONG x, y, /*count,*/ bpp;
	UBYTE colorspace;
	long sizeVal;		// Added by TetiSoft
	long *size=&sizeVal;	// TetiSoft: Fixed NULL init
	BOOL r;
		

	/* Open Libraries */
	
	JpegBase = OpenLibrary( "jpeg.library", NULL );
	if (JpegBase==NULL) {
		printf("Couldn't open jpeg.library\n");
		return;
	}
	
	CyberGfxBase = OpenLibrary( "cybergraphics.library", NULL );
	if (JpegBase==NULL) {
		printf("Couldn't open cybergraphics.library\n");
		goto end5;
	}
	
	/* Open ASL and ask user about screen */
	
	smr = (struct ScreenModeRequester* ) AllocAslRequestTags(ASL_ScreenModeRequest,
		ASLSM_MinDepth, (ULONG) 15,
		TAG_DONE);
		
	if (smr==NULL) {
		printf("Couldn't do an AllocAslRequestTags()\n");
		goto end4;
	}
	
	r = AslRequest(smr, TAG_DONE);
	if (!r) {
		FreeAslRequest(smr);
		printf("User did nothing?\n");
		goto end4;
	}
	
	DisplayID=smr->sm_DisplayID;
	DisplayDepth=smr->sm_DisplayDepth;
	FreeAslRequest(smr);
	
	/* Open Screen and Window */
	
	scr = OpenScreenTags( NULL,
								SA_Title, "Camedia_Snapshot",
								//SA_DisplayID, 0x40120051,
								SA_DisplayID, DisplayID,
								//SA_Depth, GetCyberIDAttr( CYBRIDATTR_DEPTH, 0x40120051),
								SA_Depth, DisplayDepth,
								TAG_DONE );
	if (scr==NULL) {
		printf("Couln't open screen\n");
		goto end4;
	}
	
	win = OpenWindowTags( NULL,
								WA_Title, "Preview",								
								WA_Flags, WFLG_ACTIVATE | WFLG_SIMPLE_REFRESH |
								WFLG_SIZEGADGET | WFLG_RMBTRAP | WFLG_DRAGBAR |
								WFLG_DEPTHGADGET | WFLG_CLOSEGADGET,
								WA_IDCMP, IDCMP_CLOSEWINDOW,
								WA_Left, 0,
								WA_Top, 0,
								WA_Width, 500,
								WA_Height, 380,
								WA_MinWidth, 100,
								WA_MinHeight, 70,
								WA_MaxWidth, scr->Width,
								WA_MaxHeight, scr->Height,
								WA_AutoAdjust, 1,
								WA_CustomScreen, scr,
								TAG_DONE );

	if ( win == NULL ) {
		printf("Couldn't open window\n");
		goto end3;
	}
	
	buffer=(UBYTE *) AllocMem(256000+6000, MEMF_CLEAR);
	if (buffer==NULL) {
		printf("No memory\n");
		goto end2;
	}
	frame_buffer=buffer+256000;
	
	/* retrieve previews */
	
	init(cs, error_msg);
	if (*error_msg!=0) {
		printf("Error in init() %s\n", error_msg);
		goto end2;
	}
	
	for (;;) {
		msg=GetMsg( win->UserPort );
		if (msg!=NULL) {
			ReplyMsg(msg);
			while ( ( msg = GetMsg( win->UserPort ) ) != NULL ) ReplyMsg( msg );
			goto end1;
		}
		
		Get_Preview((UBYTE *) frame_buffer, size, error_msg);
		if (*error_msg!=0) {
			printf("Error in Get_Preview() %s\n", error_msg);
			goto end1;
		}

		/* Decode picture */
		
		err = AllocJPEGDecompress( &jph,
				JPG_SrcMemStream, frame_buffer,
				JPG_SrcMemStreamSize, *size,
				TAG_DONE );

		if (err!=0) {
			printf("error in AllocJPEGDecompress\n");
			goto end1;
		}
		err = GetJPEGInfo( jph,
								JPG_Width, &x, JPG_Height, &y,
								JPG_ColourSpace, &colorspace, 
								JPG_BytesPerPixel, &bpp,
								JPG_ScaleNum, 1, JPG_ScaleDenom, 1,
								TAG_DONE );
		
		if (err!=0) {
			printf("error in GetJPEGInfo\n");
			FreeJPEGDecompress(jph);
			goto end1;
		}

		err = DecompressJPEG( jph,
									JPG_DestRGBBuffer, buffer,
									JPG_ScaleNum, 1, JPG_ScaleDenom, 1,
									TAG_DONE );
		if (err!=0) {
			printf("error in DecompressJPEG(...)\n");
			FreeJPEGDecompress(jph);
			goto end1;
		}
	
		/* Display picture */
		/*count=*/ (ULONG) ScalePixelArray(buffer, x, y, (bpp*x), win->RPort, win->BorderLeft, win->BorderTop, win->GZZWidth, win->GZZHeight, RECTFMT_RGB);

		FreeJPEGDecompress(jph);
	}
	
	/* Close Windows and Screen*/

end1:
	FreeMem(buffer, 256000+6000);
end2:
	CloseWindow(win);
end3:
	CloseScreen(scr);
end4:
	/* Close Libraries */
	CloseLibrary(CyberGfxBase);
end5:
	CloseLibrary(JpegBase);
}