Navigation
Home
gpl
danovitschwebcam
1.0
webcam.c








































webcam.c
   
   /*
    *
    * webcam.c - part of Danovitsch Webcam
    *
    * Copyright (C) 2001 by Daan Vreeken
    *
    * Published under the terms of the GNU Public License 2.0
    * (or any later version)
    *
    */
   
   
   
   
   #include <fcntl.h>
   #include <sys/socket.h>
   #include <netinet/in.h>
   #include <netinet/in_systm.h>
   #include <signal.h>
   #include <stdio.h>
   
   #include <math.h>
   
   #include "general.h"
   #include "io.h"
   #include "display.h"
   #include "capture.h"
   #include "overlay.h"
   #include "compress.h"
   #include "server.h"
   #include "http.h"
   #include "webcam.h"
    
   
   
   int			PleaseDie = 0;
   
   
   
   
   
   
   int TooOld(struct timeval *Object, long Sec, long USec)
   {
   	struct timeval		Temp = *Object;
   	struct timeval		Now;
   
   	Temp.tv_sec+=Sec;
   	Temp.tv_usec+=USec;
   	while (Temp.tv_usec>=1000*1000)
   	{
   		Temp.tv_usec-=1000*1000;
   		Temp.tv_sec++;
   	}
   
   	gettimeofday(&Now,NULL);
   
   	if (Temp.tv_sec<Now.tv_sec)
   		return 1;
   	if ((Temp.tv_sec==Now.tv_sec) && (Temp.tv_usec<Now.tv_usec))
   		return 1;
   	return 0;
   }
   
   
   
   void DeadHandler(int Sig)
   {
   	if (Sig==SIGPIPE)
   		if (Server_CurrentConnection!=NULL)
   		{
   			Debug(70,"Connection closed by foreign host. !!");
   			Server_CurrentConnection->Close=1;
   			return;
   		}
   		else
   			Error("EEEK! Fixme!! Received SIGPIPE!!");
   
   	PleaseDie=1;
   }
   
   
   
   void Translate(unsigned char *Dst, unsigned char *Src, int Bpp)
   {
   	int		X,Y;
   	unsigned char	*A = Dst;
   	unsigned char	*B = Src;
   	long		C;
   	int		Diff;
   	int		Plus;
   	unsigned char	Cnt;
   	unsigned char	Cnt2;
   
   	for (Y=0; Y<ImageHeight; Y++)
   		for (X=0; X<ImageWidth; X++)
   		{
   			*A++=*B++;
   			*A++=*B++;
   			*A++=*B++;
   			B++;
   			if (Bpp==4) A++;
   		}
   }
   
   
   
   void DrawOverlay(void)
   {
   	FILE			*OverlayTxt;
   	char			Buf[100];
   	char			Line[100];
   	int			Y = 0;
   	int			Len = 0;
   	int			Readed = 1;
   	int			Cnt;
   
   	
   	OverlayTxt=fopen("overlay.txt","r");
   	
   	if (!OverlayTxt) return;
   	
   	while (Readed>0)
   	{
   		Readed=fread(Buf,1,sizeof(Buf),OverlayTxt);
   		
   		for (Cnt=0; Cnt<Readed; Cnt++)
   		{
   			switch(Buf[Cnt])
   			{
   			case '\n':
   				Line[Len]=0;
   				Overlay_PrintF(7,14+Y*14,1,&White,&Black,Line);
   				Y++;
   
   				Len=0;
   				break;
   			default:
   				Line[Len++]=Buf[Cnt];
   			}
   		}
   		
   	}
   	Line[Len]=0;
   	if (Len!=0)
   		Overlay_PrintF(7,30+Y*14,1,&White,&Black,Line);
   	
   	fclose(OverlayTxt);
   }
   
   
   
   int main(void)
   {
   	XWnd			*Wnd;
   
   	char			ListenAddr[20];
   	struct sockaddr_in	Addr;
   	int			Len;
   	int			NewConn;
   	int			FDMax;
   	fd_set			ReadMask;
   	fd_set			WriteMask;
   	struct timeval		MaxWait;
   
   	unsigned char		Nop;
   	int			Cnt;
   
   	struct Connection	*C;
   	enum ConnState		State;
   
   	struct Capture_SettingsArr	*Arr = &Capture_Settings[0];
   
   	time_t			GMTime;
   	struct tm		*Time;
   	
   
   
   	signal(SIGTERM,&DeadHandler);
   	signal(SIGTSTP,&DeadHandler);
   	signal(SIGABRT,&DeadHandler);
   	signal(SIGQUIT,&DeadHandler);
   	signal(SIGHUP,&DeadHandler);
   	signal(SIGINT,&DeadHandler);
   
   	signal(SIGPIPE,&DeadHandler);
   
   
   	Display_Init();
   	IO_Init();
   	Server_Init();
   
   
   	Wnd=Display_CreateWindow();
   	if (Wnd==NULL)
   		ExitFatal("Could not create window!");
   	
   	Display_CreateImage(Wnd,ImageWidth,ImageHeight);
   	Display_ResizeWindow(Wnd,ImageWidth+10,ImageHeight+10);
   
   
   	pipe(&Capture_Fifo[0]);
   
   	MaxWait.tv_sec=0;
   	MaxWait.tv_usec=MainLoop_msec*1000;
   
   
   	Capture_Device=open("/devs/bktr0",O_RDONLY);
   	//Capture_Device=open("/dev/bktr1",O_RDONLY);
   	if (Capture_Device==-1)
   		ExitFatal("Could not open capture device!");
   
   
   	Capture_SetFormat();
   	Capture_SetSource();
   	Capture_Setup();
   	Capture_Single();
   
   
   	///Set all settings to default setting..
   	//
   	while (Arr->ID!=NoID)
   	{
   		Capture_Set(Arr,NULL,Arr->NumValue,Arr->OrgValue);
   		Arr++;
   	}
   
   
   	sprintf(ListenAddr,Server_ListenAddr);
   	memset(&(Addr.sin_zero),0,8);
   	Addr.sin_family=AF_INET;
   	Addr.sin_port=htons(Server_Port);
   	Addr.sin_addr.s_addr=inet_addr(ListenAddr);
   	Len=sizeof(Addr);
   
   	AcceptSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
   	Cnt=1;
   	setsockopt(AcceptSock,SOL_SOCKET,SO_REUSEADDR,(char *)&Cnt,sizeof(Cnt));
   
   	if (bind(AcceptSock,(struct sockaddr *)&Addr,Len)==-1)
   		ExitFatal("Could not bind socket!");
   
   	if (listen(AcceptSock,5)==-1)
   		ExitFatal("Socket error!");
   
   
   	while (!PleaseDie)
   	{
   		/// Check age of frame buffer
   		//
   		if (TooOld(&FrameTime,FrameTimeout))
   			Capture_Single();
   
   
   		/// Dump dead connections
   		//
   		for (Cnt=0; Cnt<Clients; Cnt++)
   			if (TooOld(&Client[Cnt].ConnectTime,ClientTimeout))
   			{
   				Debug(70,"Client timeout...");
   				Client[Cnt].Close=1;
   			}
   
   		for (Cnt=Clients-1; Cnt>=0; Cnt--)
   			if (Client[Cnt].Close)
   				Server_CloseConnection(Cnt);
   
   
   		FD_ZERO(&ReadMask);
   		FD_ZERO(&WriteMask);
   		FD_SET(AcceptSock,&ReadMask);
   		FD_SET(Capture_Fifo[1],&ReadMask);
   
   		FDMax=AcceptSock;
   		if (Capture_Fifo[1]>FDMax) FDMax=Capture_Fifo[1];
   
   		for (Cnt=0; Cnt<Clients; Cnt++)
   		{
   			State=Client[Cnt].State;
   
   			if ((State==GetRequest) || (State==GetHeader) ||
   				(State==GetData))
   			{
   				FD_SET(Client[Cnt].FD,&ReadMask);
   				if (Client[Cnt].FD>FDMax)
   					FDMax=Client[Cnt].FD;
   			}
   
   			if (State==Response)
   			{
   				FD_SET(Client[Cnt].FD,&WriteMask);
   				if (Client[Cnt].FD>FDMax)
   					FDMax=Client[Cnt].FD;
   			}
   		}
   
   
   		/// Wait for data to get available (anywhere)
   		//
   		if (select(FDMax+1,&ReadMask,&WriteMask,NULL,&MaxWait)<=0)
   		{
   			continue;
   		}
   
   
   		/// New connection?
   		//
   		if (FD_ISSET(AcceptSock,&ReadMask))
   		{
   			NewConn=accept(AcceptSock,NULL,NULL);
   			if (NewConn==-1)
   				ExitFatal("Hugh? accept returned an error!");
   
   			//fcntl(NewConn,F_SETFD,O_NONBLOCK);
   
   			if (Clients<MaxClients)
   			{
   				C=&Client[Clients];
   				C->FD=NewConn;
   				C->Close=0;
   				C->State=GetRequest;
   				C->Mode=LineMode;
   				C->Line=NULL;
   				C->Length=0;
   				C->Request=NULL;
   				C->PostData=NULL;
   				C->PostLength=0;
   				C->ContentLength=0;
   				C->Error=0;
   
   				gettimeofday(&C->ConnectTime,NULL);
   				Clients++;
   			}
   			else
   			{
   				Debug(80,"Server full... (dropping new connection)");
   				close(NewConn);
   			}
   		}
   
   		
   		/// Check client connections for activity...
   		//
   		for (Cnt=0; Cnt<Clients; Cnt++)
   		{
   			C=&Client[Cnt];
   
   			if (FD_ISSET(Client[Cnt].FD,&ReadMask))
   				Server_HandleData(Cnt);
   
   			if (FD_ISSET(Client[Cnt].FD,&WriteMask))
   			{
   				HTTP_Response(&Client[Cnt]);
   				Client[Cnt].State=Zombie;
   				Client[Cnt].Close=1;
   			}
   		}
   
   
   		/// Capture done?
   		//
   		if (FD_ISSET(Capture_Fifo[1],&ReadMask))
   		{
   			read(Capture_Fifo[1],&Nop,1);
   
   			memcpy(FrameBuffer,Frame,4*ImageWidth*ImageHeight);
   			Overlay_PrintF(7,0,1,&White,&Black,"%s",Server_String);
   			//Overlay_PrintF(7+(ImagesServed*10)%150,16,1,&White,&Black,"M o o ,    ] : 8 )");
   
   			Overlay_PrintF(7,ImageHeight-32,1,&White,&Black,"Images served: %d",ImagesServed);
   			Overlay_PrintF(7,ImageHeight-16,1,&White,&Black,"Viewpoint:%s",Capture_GetTextValue("InputF"));
   
   			//Overlay_PrintF(90,70,1,&Red,&White,"Webcam is off...");
   			//Overlay_PrintF(60,90,1,&Red,&White,"please come back later");
   			
   			//Overlay_PrintF(7,56,1,&White,&Black,"bliep");
   			
   			//Overlay_PrintF(7,40,1,&White,&Black,"ATV link test");
   			//Overlay_PrintF(7,70,1,&White,&Black,"Link frequency: 1255MHz power: 30mW");
   			//Overlay_PrintF(7,85,1,&White,&Black,"PA4DAN");
   			
   			DrawOverlay();
   			
   			time(&GMTime);
   			Time=localtime(&GMTime);
   			//Overlay_PrintF(7,ImageHeight-32,1,&White,&Black,"%02d:%02d.%02d (%s)",Time->tm_hour,Time->tm_min,Time->tm_sec,Time->tm_zone);
   			Overlay_PrintF(150,ImageHeight-16,1,&White,&Black,"%02d:%02d.%02d (%s)",Time->tm_hour,Time->tm_min,Time->tm_sec,Time->tm_zone);
   
   			Translate((unsigned char *)Wnd->Buffer,(unsigned char *)FrameBuffer,Wnd->Bpp);
   			//memcpy(Wnd->Buffer,FrameBuffer,4*ImageWidth*ImageHeight);
   			Display_UpdateImage(Wnd);
   			NewFrame=0;
   		}
   	}
   
   	Output("\n\nSomeone wants us to die!");
   
   	Server_Shutdown();
   	Capture_Shutdown();
   	
   	Output("\nMoo,\n]:8)");
   
   	return 0;
   }
   
   
   
   
   

syntax highlighted by Code2HTML, v. 0.9.1


Email me with questions/comments : Daan <Danovitsch @ Vitsch . net>