You are on page 1of 14

{ Capture 'Em! by Antti Kirjavainen akirjavainen@mail.htk.fi A small webcam software package with included HTTP-server.

There are almost no comments, sorry :) But the code is very simple. You can do anything you want with this code, except to release it as another program. } unit FilmStrip; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Menus, IdBaseComponent, IdComponent, IdHTTPServer, ShellAPI, IdTCPServer, VFW, INIFiles, IdIPWatch, Clipbrd, IdCustomHTTPServer; const WM_ICONTRAY = WM_USER + 1; ENTER = Chr(13) + Chr(10); type TfrmMain = class(TForm) pnlVideo: TPanel; MainMenu1: TMainMenu; File1: TMenuItem; mnuPort: TMenuItem; mnuSep: TMenuItem; mnuExit: TMenuItem; IdHTTPServer: TIdHTTPServer; mnuVideoSize: TMenuItem; mnuSetVideoSource: TMenuItem; mnuPopUp: TPopupMenu; mnuShow: TMenuItem; N1: TMenuItem; mnuQuit: TMenuItem; tmrUpdateTray: TTimer;

mnuHelp: TMenuItem; mnuAbout: TMenuItem; N3: TMenuItem; mnuAbout2: TMenuItem; stbStatus: TPanel; dlgSave: TSaveDialog; mnuCapture: TMenuItem; mnuSave: TMenuItem; mnuServer: TMenuItem; N2: TMenuItem; mnuActive: TMenuItem; N4: TMenuItem; mnuSaveTo: TMenuItem; mnuCapture2: TMenuItem; N5: TMenuItem; mnuHomepage: TMenuItem; mnuHomepage2: TMenuItem; mnuEmail: TMenuItem; tmrResetStatus: TTimer; mnuAutoCapture: TMenuItem; tmrCapture: TTimer; mnuLogging: TMenuItem; mnuLogEnabled: TMenuItem; N6: TMenuItem; mnuShowLog: TMenuItem; IdIPWatch: TIdIPWatch; mnuTest: TMenuItem; mnuIP: TMenuItem; procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormCreate(Sender: TObject); procedure WMSizing(var Message: TMessage); message WM_SIZING; procedure mnuPortClick(Sender: TObject); procedure mnuExitClick(Sender: TObject); procedure Status(const NewStatus: string); procedure IdHTTPServerCommandGet(AThread: TIdPeerThread; RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo); procedure mnuVideoSizeClick(Sender: TObject); procedure mnuSetVideoSourceClick(Sender: TObject); procedure mnuShowClick(Sender: TObject); procedure mnuQuitClick(Sender: TObject); procedure PrepareTray; procedure AppException(Sender: TObject; E: Exception); procedure AppMinimize(Sender: TObject); procedure tmrUpdateTrayTimer(Sender: TObject); procedure mnuAbout2Click(Sender: TObject); procedure mnuActiveClick(Sender: TObject);

procedure mnuSaveToClick(Sender: TObject); procedure mnuSaveClick(Sender: TObject); procedure mnuCapture2Click(Sender: TObject); procedure mnuAboutClick(Sender: TObject); procedure mnuHomepageClick(Sender: TObject); procedure mnuHomepage2Click(Sender: TObject); procedure mnuEmailClick(Sender: TObject); procedure tmrResetStatusTimer(Sender: TObject); procedure mnuAutoCaptureClick(Sender: TObject); procedure tmrCaptureTimer(Sender: TObject); procedure mnuLogEnabledClick(Sender: TObject); procedure mnuShowLogClick(Sender: TObject); procedure mnuTestClick(Sender: TObject); procedure mnuIPClick(Sender: TObject); private { Private declarations } a: NOTIFYICONDATA; public { Public declarations } procedure TrayMessage(var Msg: TMessage); message WM_ICONTRAY; end; var frmMain: TfrmMain; Video: TVideo; tmpFile: string; Port: Integer; AppPath: string; INIFile: TINIFile; INIFileName: string; SaveFileName: string; picCount: Integer; CaptureTime: Integer; Interval: Integer; function ReadFromINI(const Section: string; const Key: string; const Default: string): string; overload; function ReadFromINI(const Section: string; const Key: string; const Default: LongInt): LongInt; overload; function WriteToINI(const Section: string; const Key: string; const Value: string): Boolean; overload; function WriteToINI(const Section: string; const Key: string; const Value: LongInt): Boolean; overload; implementation

uses About, Log; {$R *.dfm} {$R click.res} function ReadFromINI(const Section: string; const Key: string; const Default: string): string; var ReadINI: TIniFile; begin try ReadINI := TIniFile.Create(INIFileName); ReadFromINI := ReadINI.ReadString(Section, Key, Default); finally ReadINI.Free; end; end; function ReadFromINI(const Section: string; const Key: string; const Default: LongInt): LongInt; var ReadINI: TIniFile; begin try ReadINI := TIniFile.Create(INIFileName); ReadFromINI := ReadINI.ReadInteger(Section, Key, Default); finally ReadINI.Free; end; end; function WriteToINI(const Section: string; const Key: string; const Value: string): Boolean; var WriteINI: TIniFile; begin try WriteINI := TIniFile.Create(INIFileName);

WriteINI.WriteString(Section, Key, Value); WriteToINI := True; finally WriteINI.Free; end; end; function WriteToINI(const Section: string; const Key: string; const Value: LongInt): Boolean; var WriteINI: TIniFile; begin try WriteINI := TIniFile.Create(INIFileName); WriteINI.WriteInteger(Section, Key, Value); WriteToINI := True; finally WriteINI.Free; end; end; procedure TfrmMain.PrepareTray; begin Application.OnException := AppException; Application.OnMinimize := AppMinimize; // Create the icon to the systray: a.cbSize := sizeof(a); a.Wnd := Handle; a.uID := 0; a.szTip := 'Webcam Server'; a.uCallbackMessage := WM_USER + 1; a.hIcon := Application.Icon.Handle; a.uFlags := NIF_ICON + NIF_MESSAGE + NIF_TIP; Shell_NotifyIcon(NIM_ADD, @a); end; procedure TfrmMain.TrayMessage(var Msg: TMessage); var curPos: TPoint; begin

case Msg.lParam of WM_RBUTTONUP: begin // popup menu if (Self.Visible) then mnuShow.Caption := '&Hide' else mnuShow.Caption := '&Show'; GetCursorPos(curPos); mnuPopUp.Popup(curPos.x, curPos.y); end; WM_LBUTTONDBLCLK: begin Self.Show; Application.Restore; Application.BringToFront; end; {WM_LBUTTONDOWN: begin end;} end; end; procedure TfrmMain.AppException(Sender: TObject; E: Exception); begin // Nothing end; procedure TfrmMain.AppMinimize(Sender: TObject); begin Self.Hide; end; procedure TfrmMain.tmrUpdateTrayTimer(Sender: TObject); // Explorer crashes quite often, so make sure the icon stays in the tray (refresh): begin Shell_NotifyIcon(NIM_ADD, @a); end; procedure TfrmMain.FormCreate(Sender: TObject); begin // Command line parameters:

if (Pos('/T', UpperCase(CMDLine)) > 0) or (Pos('/M', UpperCase(CMDLine)) > 0) then begin Self.WindowState := wsMinimized; Application.Restore; Self.Hide; end; if (Pos('/?', UpperCase(CMDLine)) > 0) or (Pos('/H', UpperCase(CMDLine)) > 0) or (Pos('-H', UpperCase(CMDLine)) > 0) or (Pos('-?', UpperCase(CMDLine)) > 0) then begin Self.WindowState := wsMinimized; MessageDlg('Command line parameters for Capture ''Em!: ' + ENTER + ENTER + '/? = This help screen' + ENTER + '/T = Start the program minimized', mtInformation, [mbOK], 0); Application.Terminate; exit; end; AppPath := ExtractFilePath(Application.ExeName); INIFileName := AppPath + 'WebCam.INI'; PrepareTray; Port := ReadFromINI('Options', 'Port', 80); Video := TVideo.Create(pnlVideo); IdHTTPServer.DefaultPort := Port; //Status('Idle.'); if (ReadFromINI('Options', 'Active', 0) = 1) then begin mnuActive.Checked := True; idHTTPServer.Active := True; end else begin mnuActive.Checked := False; idHTTPServer.Active := False; end; if (ReadFromINI('Options', 'Logging', 1) = 1) then mnuLogEnabled.Checked := True else mnuLogEnabled.Checked := False; dlgSave.InitialDir := ReadFromINI('Options', 'LastDir',

ExtractFilePath(Application.ExeName)); end; procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction); begin Shell_NotifyIcon(NIM_DELETE, @a); FreeAndNil(Video); end; procedure TfrmMain.WMSizing(var Message: TMessage); var lprc: PRect; TitleBarHeight: Integer; begin lprc := PRect(Message.LParam); TitleBarHeight := Height - ClientHeight; lprc^.Bottom := lprc^.Top + Round(ClientWidth * 0.75) + TitlebarHeight + stbStatus.Height; end; procedure TfrmMain.mnuPortClick(Sender: TObject); var msgPort: string; begin msgPort := InputBox('Port to use', 'Change port to:', IntToStr(Port)); if (StrToInt(msgPort) <= 0) then exit; if (StrToInt(msgPort) <> Port) then begin Port := StrToInt(msgPort); WriteToINI('Options', 'Port', Port); ShowMessage('Restart the program to activate the port change.'); end; end; procedure TfrmMain.mnuExitClick(Sender: TObject); begin Self.Close; end; procedure TfrmMain.Status(const NewStatus: string);

var strTime: string; TheTime: TDateTime; begin TheTime := Time; stbStatus.Caption := NewStatus; stbStatus.Refresh; if mnuLogEnabled.Checked then frmLog.txtLog.Text := frmLog.txtLog.Text + '[' + TimeToStr(Time) + '] ' + NewStatus + ENTER; tmrResetStatus.Enabled := True; end; procedure TfrmMain.IdHTTPServerCommandGet(AThread: TIdPeerThread; RequestInfo: TIdHTTPRequestInfo; ResponseInfo: TIdHTTPResponseInfo); begin tmpFile := AppPath + 'tmp.jpg'; if Video.TakePicture(tmpFile) then begin Status('Picture sent to ' + RequestInfo.RemoteIP + '.'); IdHTTPServer.ServeFile(AThread, ResponseInfo, tmpFile); end else begin Status('Error!'); end; end; procedure TfrmMain.mnuVideoSizeClick(Sender: TObject); begin //try Video.SetSize; //except // MessageDlg('Failed to open settings. Is the webcam connected to the computer?', mtError, [mbOK], 0); //end; end; procedure TfrmMain.mnuSetVideoSourceClick(Sender: TObject);

begin Video.SetSource; end; procedure TfrmMain.mnuShowClick(Sender: TObject); begin if (Self.Visible) then Self.Hide else Self.Show; end; procedure TfrmMain.mnuQuitClick(Sender: TObject); begin Shell_NotifyIcon(NIM_DELETE, @a); FreeAndNil(Video); Application.Terminate; end; procedure TfrmMain.mnuAbout2Click(Sender: TObject); begin mnuAbout.Click; end; procedure TfrmMain.mnuActiveClick(Sender: TObject); begin if mnuActive.Checked then mnuActive.Checked := False else mnuActive.Checked := True; if (mnuActive.Checked) then WriteToINI('Options', 'Active', 1) else WriteToINI('Options', 'Active', 0); idHTTPServer.Active := mnuActive.Checked; end; procedure TfrmMain.mnuSaveToClick(Sender: TObject); begin dlgSave.Execute; if (Length(dlgSave.FileName) = 0) then exit; SaveFilename := dlgSave.FileName; WriteToINI('Options', 'LastDir', ExtractFilePath(SaveFileName)); dlgSave.FileName := '';

picCount := 0; end; procedure TfrmMain.mnuSaveClick(Sender: TObject); begin if (Length(SaveFileName) = 0) then SaveFileName := AppPath + 'pic'; if DirectoryExists(SaveFileName) then SaveFileName := SaveFileName + 'pic'; if (FileExists(SaveFileName + IntToStr(picCount) + '.jpg')) then begin picCount := picCount + 1; mnuSave.Click; exit; end; if not Video.TakePicture(SaveFileName + IntToStr(picCount) + '.jpg') then begin Status('Error!'); MessageDlg('Failed to capture!', mtError, [mbOK], 0); end else begin Status('Captured ' + SaveFileName + IntToStr(picCount) + '.jpg.'); end; end; procedure TfrmMain.mnuCapture2Click(Sender: TObject); begin mnuSave.Click; end; procedure TfrmMain.mnuAboutClick(Sender: TObject); begin frmAbout.Show; end; procedure TfrmMain.mnuHomepageClick(Sender: TObject); begin ShellExecute(Handle, 'open', 'http://www.htk.fi/public/akirjavainen', '', '', SW_SHOWDEFAULT); end; procedure TfrmMain.mnuHomepage2Click(Sender: TObject);

begin mnuHomepage.Click; end; procedure TfrmMain.mnuEmailClick(Sender: TObject); begin ShellExecute(Handle, 'open', 'mailto:akirjavainen@mail.htk.fi', '', '', SW_SHOWDEFAULT); end; procedure TfrmMain.tmrResetStatusTimer(Sender: TObject); begin tmrResetStatus.Enabled := False; stbStatus.Caption := 'Idle.'; stbStatus.Refresh; end; procedure TfrmMain.mnuAutoCaptureClick(Sender: TObject); var msgCapture: string; begin if mnuAutoCapture.Checked then begin mnuAutoCapture.Checked := False; tmrCapture.Enabled := False; CaptureTime := 0; end else begin msgCapture := InputBox('Enter time in minutes', 'Auto-Capture', IntToStr(Interval)); if (StrToInt(msgCapture) <= 0) then exit; Interval := StrToInt(msgCapture); CaptureTime := 0; mnuAutoCapture.Checked := True; tmrCapture.Enabled := True; end; end; procedure TfrmMain.tmrCaptureTimer(Sender: TObject); begin

CaptureTime := CaptureTime + 1; Status(IntToStr(Interval - CaptureTime) + ' minutes to capture...'); if (CaptureTime >= Interval) then begin CaptureTime := 0; mnuCapture.Click; end; end; procedure TfrmMain.mnuLogEnabledClick(Sender: TObject); begin if mnuLogEnabled.Checked then mnuLogEnabled.Checked := False else mnuLogEnabled.Checked := True; if (mnuLogEnabled.Checked) then WriteToINI('Options', 'Logging', 1) else WriteToINI('Options', 'Logging', 0); end; procedure TfrmMain.mnuShowLogClick(Sender: TObject); begin frmLog.Show; end; procedure TfrmMain.mnuTestClick(Sender: TObject); var LocalAddr: string; LocalAddr2: PChar; begin LocalAddr := 'http://localhost'; if (Port <> 80) then LocalAddr := LocalAddr + ':' + IntToStr(Port); LocalAddr2 := StrPCopy(LocalAddr2, LocalAddr); ShellExecute(Handle, 'open', LocalAddr2, '', '', SW_SHOWDEFAULT); end; procedure TfrmMain.mnuIPClick(Sender: TObject); begin Clipboard.AsText := idIPWatch.LocalIP; MessageDlg('Your IP, ' + idIPWatch.LocalIP + ' copied to clipboard.',

mtInformation, [mbOK], 0); end; end.