![]() |
![]() |
||||||
![]() |
|||||||
|
/*
*
* 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> |