video chat on lan - scholarworks home

106
VIDEO CHAT ON LAN Payal Dalwadi B.E., Dharmsinh Desai University, Gujarat, India, 2006 PROJECT Submitted in partial satisfaction of the requirements for the degree of MASTER OF SCIENCE in COMPUTER SCIENCE at CALIFORNIA STATE UNIVERSITY, SACRAMENTO FALL 2010

Upload: others

Post on 03-Feb-2022

7 views

Category:

Documents


0 download

TRANSCRIPT

VIDEO CHAT ON LAN

Payal Dalwadi B.E., Dharmsinh Desai University, Gujarat, India, 2006

PROJECT

Submitted in partial satisfaction of the requirements for the degree of

MASTER OF SCIENCE

in

COMPUTER SCIENCE

at

CALIFORNIA STATE UNIVERSITY, SACRAMENTO

FALL 2010

ii

VIDEO CHAT ON LAN

A Project

by

Payal Dalwadi

Approved by: __________________________________, Committee Chair Chung-E Wang, Ph.D. __________________________________, Second Reader Isaac Ghansah, Ph.D. ____________________________ Date

iii

Student:

Payal Dalwadi

I certify that this student has met the requirements for format contained in the University

format manual, and that this project is suitable for shelving in the Library and credit is to

be awarded for the Project.

__________________________, Graduate Coordinator ________________ Nikrouz Faroughi, Ph.D. Date Department of Computer Science

iv

Abstract

of

VIDEO CHAT ON LAN

by

Payal Dalwadi

This project is an implementation of a software application to provide real-time video

chat experience for a user on a local area network (LAN). Generally, chat applications

require their users to create detailed profiles before starting to use the application. This

can be time consuming as well as a potential hazard to privacy. This application

overcomes these problems by significantly reducing the time needed to start using it, as

the only information needed from the users is the IP address of the recipient. Users can

send instant messages and share live web cam data with other users. The application also

provides a feature to add and remove people from their contact list. The present design

confines its operation within the limits of a local area network, but the possibilities are

open for operation in extended networks or the Internet.

The application is implemented by using VC++.NET. Communication between two

systems is established by windows socket API (WinSock2).

_______________________, Committee Chair Chung-E Wang, Ph.D. ______________________ Date

v

ACKNOWLEDGEMENT

It was a wonderful time I spent in Sacramento while getting my Master’s degree, and I

have many people to thank for it.

First and foremost, I would like to thank my project advisor Dr. Chunge-E Wang for

helping me and guiding me through the project. His dedication and energy have always

inspired me. In future also it will continue to inspire me. Thank you, Professor for

everything. Also, I would like to thank Dr. Isaac Ghansah for providing me his support in

completion of my project. I am thankful to former Graduate Coordinator, Dr. Cui Zhang

for her support and guidance throughout my masters. I am also thankful to Dr. Nikrouz

Faroughi for his support. I would like to express my honor to all the faculty members of

computer science, for adding to this experience.

I would like to thank all my friends including Kamlesh, Mantej, Mruga and Dhvani, for

making my entire study memorable. Finally, and most importantly, I would like to thank

my family for never giving up on me. Thanks a lot Mom and Dad, for always being there

for me.

vi

TABLE OF CONTENTS

Page

Acknowledgement………………………………………………………………………...v List of Tables…………………………………………………………………………...viii

List of Figures…………………………………………………….…………………….ix

Chapter

1. INTRODUCTION…………………………………………………………………….1

1.1 Project Objective………………………….…………..…………………………..2

1.2 Project Plan………………………………………………………………………..2

1.3 Future Work……………………………………………………….…………...….3

2. TECHNOLOGY USED FOR APPLICATION……………………………………….5

2.1 Introduction to .NET Framework……………………….………………………...5

2.2 Component of .NET………………………………………………….……………6

2.3 Microsoft Foundation Class Library…………………………….………………..6

2.4 Features of VC++.NET 2005………………………………………………..…….9

2.5 Socket…………………………………………………………………………….12

2.6 Windows Socket in MFC………………………………………………………...16

2.6.1 WinSock2 Architecture…………………………………………………….17

3. PROJECT IMPLEMENTATION………..………………………………………….21

3.1 Project Layout……………………………………………………………………21

3.1.1 Implementation of Features………………………………………………..21

vii

3.1.2 Establish Connection Using Socket………………………………………..31

3.1.3 Capturing Webcam Driver………………………….……………………..35

4. CONCLUSION AND FUTURE WORK……………………………………………39

Appendix…………………………………………………………………………………40

References………………………………………………………………………………..96

viii

LIST OF TABLES

Page

1. Table 3.1.1.1 Classes used by video chat on LAN…………………..………………30

2. Table 3.1.1.2 Functions used by video chat on LAN……………………….……….30

3. Table 3.1.3.1 Macros used by video chat on LAN…………………………………..36

ix

LIST OF FIGURES

Page

1. Figure 2.3.1 MFC document/view interface…………………………………………..7

2. Figure 2.5.1 Communication using socket.………………………………..………..13

3. Figure 2.6.1.1 WinSock2 architecture…………………………………………….…19

4. Figure 3.1.1.1 Main window of application………………………………………….22

5. Figure 3.1.1.2 Add contact in contact list……………………………………………23

6. Figure 3.1.1.3 Connection accepted by user…………………………………………24

7. Figure 3.1.1.4 Sending text data……………………………………………………..25

8. Figure 3.1.1.5 Initialization of webcam……………………………………………...26

9. Figure 3.1.1.6 Invitation to view webcam…………………………………………...27

10. Figure 3.1.1.7 Request to view webcam……………………………………………..28

11. Figure 3.1.1.8 Disconnection of webcam……………………………………………29

12. Figure 3.1.2.1 Communication between two system………………………………...33

13. Figure 3.1.2.2 Dialog data exchange………………………………………………...34

1

Chapter 1

INTRODUCTION

The Internet has enhanced the ways in which people communicate. Emails and instant

messaging have replaced traditional means of contact. Text and video conferencing have

gained popularity as they allow instantaneous human friendly communication. Save and

edit contacts, storage of conversations and other user information are some common

features in these applications. Many of these chat applications are based on server-client

architecture. A centralized server is used to maintain all the information necessary to

authenticate the user and relay data or connection information between users. Most of the

chat applications existing today require user created profiles containing personal

information before being able to chat. All this information is stored on a server. This

method of connecting users leads to the server being a store-house of personal

information. Such a system has many potential disadvantages. It creates a performance

bottle-neck as vast amounts of data must be processed by server. Connectivity issues

between the clients and the server can interrupt connections between users that could

otherwise be avoided. Thus, we need a chat application that overcomes these drawbacks;

one which can work without the complications of having a centralized server.

2

1.1 Project Objective

The objective of this project is to implement video chat on LAN using Microsoft

Foundation Class Library. MFC library wraps portion of Windows API in C++ classes. It

provides functionality that enables C++ classes to use a default application framework.

Once the frame work is able to do video chat on LAN, the project can be extended in

future for developing audio chat as well. Two users are able to chat by entering each

others’ IP addresses. Users can easily add and delete contacts from their contact list.

Users can accept and reject invitations or requests of video chat. Since the only form of

authentication is enabling the recipient to accept chat request, this application is not very

secure to use on the Internet. But, this application is intended to be used inside a LAN

where users are known and trusted.

1.2 Project Plan

The first step is to list out the features that define the application, as listed below, and

implement those features. This process is explained in more detail in chapter 3 of this

report.

• Simple connection interface using entered IP or one stored in a list.

• Easy to use webcam controls consisting of stop, start, invite, and request.

3

• Independent webcam and text chat controls.

The next step involves creating sockets which are used to establish connection. Three

types of sockets are created: DATA (text), VIDEO (video) and CONTROLMESGS (for

control messages like ‘stop webcam’, ‘request to view webcam’, and other webcam

functions).

To implement the webcam capture driver module, MFC library functions and macros are

used. Implemented functions includes connect, capture, stop, and disconnect webcam

driver.

1.3 Future Work

Chapter 4 gives the direction for further research and development for the project. Some

of the possible improvements are as follows:

1. Add IP discovery module.

• Right now this application needs to add IP address manually to initiate chat.

To solve this problem, a module can be added to the application which can

perform IP discovery and list IP address in a LAN with associated hostnames.

2. Add features such as audio and send file.

4

• This application only provides the feature to perform real-time streaming of

video and text. It does not have the features to send files or audio chat. To

make this application better, modules can be added which provide audio and

send file feature.

3. Use TCP instead of UDP as the underlying transport layer protocol.

• To improve video chat and to make connections reliable, create TCP

connections between the sender and the recipient.

5

Chapter 2

TECHNOLOGY USED FOR APPLICATION

In this chapter, the technology used to implement the project is discussed in detail. Video

chat on LAN is a Windows based application. The front-end and the back-end are

implemented using Visual Studio .NET 2005 (VC++). Visual Studio allows the usage of

MFC classes and macros, which are used to initialize, connect and disconnect the drivers

for the web-cam, and to capture the web-cam image. This application uses Windows

socket API (winsock) to establish a connection between two systems.

2.1 Introduction to .NET Framework

The .NET Framework is Microsoft's comprehensive and consistent programming model

for building applications that have visually stunning user experiences, seamless and

secure communication, and many more features. The .NET framework provides a large

library of classes. Framework supports multiple programming languages. It supports both

windows and web applications.

6

2.2 Components of .NET

.NET framework consists of two components: Common Language Runtime and .NET

class library.

Common Language Runtime (CLR) - The Common Language Runtime (CLR) is the

environment where all programs in .NET are run. Memory management and thread

management is done by CLR. Programs that run in the CLR need not manage memory, as

it is completely taken care of by the CLR. For example, when a program needs a block of

memory, CLR provides the block and releases the block when program is done.

.NET class library - .NET comes with thousands of classes to perform all important and

not-so-important operations. Library is completely object-oriented, providing more than

a thousand classes to utilize.

Video chat on LAN uses VC++.NET and MFC. Once the coding is done, building the

application with active solution configuration and active solution platform creates a

single executable.

2.3 Microsoft Foundation Class Library

MFC classes and multimedia macros are used for GUI elements and driver interface.

7

Microsoft Foundation Class Library (MFC) is a library that wraps a portion of the

Windows API in C++ classes. It also includes functionality that enables MFC to use a

default allocation framework. MFC application generates C++ source files, resource files,

header files, and a project files. The MFC Reference usually does not describe inherited

member functions or inherited operators.

A standard Visual C++ program based on the MFC Document/View interface is made up

of five main parts:

The Application Object — our Windows program itself

The Main Frame Window Object — our main window

The Document Object — handles our data

The View Object — handles data display

The Document Template

Figure 2.3.1 MFC document/view interface [13]

8

The application object is an instance of the CRealtorApp class. InitInstance()

method is called within the built-in and implicit WinMain() function and this

object runs first. Main window appears on the screen once this object is started

and it also starts passing Windows messages to main window.

The main window object displays the main tool bars for the application. It maps

the menu bar, the title bar of the window, and the tool bar. The main window

object is an instance of the class CMainFrame. This object deals with graphics

like drawing, text and other graphics on the window. The area on which the main

window object displays data is called the client area in a window; for example,

drawing a line in MS Paint appears in the MS paint’s client area. The client area is

handled by the view object [13].

The view object handles the client area. The formation and display of data take

place here. For example, the text editing for a word processing program is

handled by the view object. In fact, the view object is really a window itself that

appears on top of the client area. The document object stores the data which is

displayed in the view object.

The document object is used by program to store the data. Visual C++ makes it

easier by allowing all that data in the document object to store and then handle the

display of the data that fits into the client area in the view object. That implies,

several different views can be open in the same document at once like MDI

application.

9

The document template is created in the InitInstance() function of the application

object and this is how the program connects the other three classes — the

document, main frame window, and view classes — to the program itself.

The CSingleDocTemplate object is found if it is SDI application or the

CMultiDocTemplate object found if it is MDI application.

2.4 Features of VC++.NET 2005

This section gives a brief overview of main features of VC++.NET as listed below:

• Powerful Windows-based Applications

Visual C++ .NET comes with features such as a powerful new forms designer, an in-

place menu editor, and automatic control anchoring and docking. Visual C++.NET

delivers new productivity features for building more robust applications easily and

quickly. With an improved integrated development environment (IDE) and a significantly

reduced startup time, Visual C++ .NET offers fast, automatic formatting of code,

improved IntelliSense, an enhanced object browser and XML designer, and much more.

10

• Powerful, Flexible, Simplified Data Access

The data access can be tackled easily with SQL server data reader and SQL connection.

The flexibility of SQL connection enables data binding to any database, as well as

classes, collections, and arrays, and provides true XML representation of data. Seamless

access to SQL enables simple data access for connected data binding scenarios. Using

SQL connection, any .NET programming language can gain high-speed access to MS

SQL Server, Oracle, DB2, Microsoft Access, and more.

• Direct Access to the Platform

Visual C++ developers can have full access to the capabilities available in .NET

Framework 1.1. Developers can easily program system services including the event log,

performance counters and file system. The new Windows Service project template

enables to build real Microsoft Windows NT Services [10].

• ISO/ANSI C++ Standard Compliance

It provides most standards-compliant C++ compiler which can run on any platform today.

Also, it provides new features including Partial Template Specialization, Partial

Ordering, Member Template Definitions, and much more [9].

11

• Performance Optimizations

Microsoft has significantly enhanced optimization performance with two new compiler

options,

The first complier options is the /G7 flag. Code optimization is done by

complier for the Intel Pentium 4 and AMD Athlon processors using this flag. The

numbers can vary when recompilation of the code is done with /G7. Recompiling

with this flag will not produce code that only executes on the Intel Pentium 4 or

AMD Athlon, but the code produced may have a minor performance penalty on

older generations of these processors [9][12].

The second complier option is /arch: [argument], where the argument is

either SSE or SSE2. Streaming SIMD Extensions (SSE) and Streaming SIMD

Extensions 2 (SSE2_) instructions, as well as other instructions that support SSE

or SSE2 are used by the complier using this option[9][12].

• Security Enhancements

There are well known problems for C and C++ programs and they are Buffer overruns. It

occurs due to unmanaged code which does not perform array bounds checking or type-

safety checking. C++ gives an advantage for certain classes of applications. The

downside is that buffer overruns become security holes and opportunities for several

12

kinds of security attacks. To overcome this problem, Microsoft has added

the /GS compiler option [9].

• Managed C++ Windows Forms Designer

Last, but certainly not least, it also provides support for creating Windows forms in the

managed C++ language. The main benefit is of drag-and-drop placement and layout

capabilities using different tools. Users do not have to write code for each small tool, it is

generated by .NET.

2.5 Socket

Socket functionality, and an overview of WinSock2 are discussed in this section. Sockets

are a protocol independent method of creating a connection between processes.

A socket is an interface between the transport layer and the application layer.

13

Figure 2.5.1 Communication using socket

To use a socket, a program has to provide socket type and address domain. Any two

processes can communicate with each other if their sockets are in the same domain and of

the same type [11].

• Socket domain

There are two widely used address domains. Each of these domains has its own address

format.

UNIX domain - Two processes which share a common file system can

communicate. UNIX domain provides network transparency. With UNIX domain

sockets, the credential of the process can be retrieved that creates the remote

Application

Transport

Network

Data Link

Physical

Application

Transport

Network

Data Link

Physical

Sockets

14

socket, and use that for access control also, which can be quite convenient on

multi-user systems. The address of a socket in the UNIX domain is a character

string which is basically an entry in the file system. UNIX domain sockets have

explicit knowledge that they are being executed on the same system. They avoid

the extra context switch through the software interrupt ‘NETISR’ [11], and a

sending thread writes the traffic stream or the datagrams directly into the

receiving socket buffer. No checksums are calculated, no headers are inserted, no

routing is performed, etc. Because they have access to the remote socket buffer,

they can also directly provide feedback to the sender when it is filling, or more

importantly, emptying, rather than having the added overhead of explicit

acknowledgement and window changes. The one piece of functionality that

UNIX domain sockets don't provide that TCP does is out-of-band data [10].

Internet domain – Two processes running on two different hosts on the

Internet can communicate. It uses TCP/IP Internet protocol suit. The address of a

socket in the Internet domain consists of the Internet address of the host machine.

In addition, each socket needs a port number on that host. Port numbers are 16 bit

unsigned integers.

• Socket Types Socket types define the communication properties visible to the application. Processes

communicate only between sockets of the same type. There are different types of socket.

15

However, there are two socket types are widely used – stream sockets, and datagram

sockets.

A stream socket - Stream sockets treat communications as a continuous

stream of characters. It uses Transmission Control Protocol (TCP). It provides

two-way, sequenced, reliable, and unduplicated flow of data with no record

boundaries. A stream operates much like a telephone conversation [11]. The

socket type is SOCK_STREAM.

A datagram socket - Datagram sockets reads entire messages at once. It uses

User Datagram Protocol (UDP). It provides a two-way flow of messages.

Datagram socket may receive messages in a different order from the sequence in

which the messages were sent [11]. Record boundaries in the data are preserved.

The socket type is SOCK_DGRAM.

A sequential packet socket – It provides a two-way, sequenced, reliable,

connection, for datagrams of a fixed maximum length. The socket type is

SOCK_SEQPACKET. No protocol for this type has been implemented for any

protocol family [11].

A raw socket - provides access to the underlying communication protocols

[11].

16

2.6 Windows Socket in MFC Windows Sockets 2 is designed for use by C/C++ programmers. Windows Sockets 2 can

be used on all Windows platforms.WinSock2 provides a powerful and flexible API for

creating universal TCP/IP applications. Windows Sockets version 2.0 (WinSock 2)

formalizes the API for a number of other protocol suites like ATM, IPX/SPX, and

DECnet and it allows them to coexist simultaneously [9].

Here is a list of the new features that WinSock 2 provides [9].

Multiple Protocol support: WOSA architecture enable service providers to

offer "plug-in" and "pile-on" features.

Transport Protocol Independence: Choose the transport protocol depending on

the services provided.

Multiple Namespaces: Allows used to select the protocol to resolve

hostnames, or locate services.

Scatter and Gather: Provided features like receive and send, to and from

multiple buffers.

Overlapped I/O and Event Objects: Enhanced throughput can be achieved by

utilizing Win32 paradigms.

Quality of Service: It helps to negotiate and keep track of bandwidth per

socket.

17

Multipoint and Multicast: This feature is Protocol independent APIs and

protocol specific APIs.

Conditional Acceptance: Before connection is made it can reject or defer a

connect request.

Connect and Disconnect data: This feature supports for transport protocols.

Socket Sharing: Socket handler can be shared by two or more processes

Vendor IDs and a mechanism for vendor extensions: This feature allows

adding Vendor specific APIs.

Layered Service Providers: Service can be added to existing transport

providers using this feature.

2.6.1 WinSock 2 Architecture

WinSock2 API is used to implement socket in the application. This section gives brief

overview of WinSock2.

WinSock 2 has an all-new architecture that provides much more flexibility. The WinSock

2 architecture allows for simultaneous support of multiple protocol stacks, interfaces, and

service providers. Flexibility is added because there is a one DLL on the top and another

layer below, and standard service provider interface. WinSock 2 adopts the Windows

Open Systems Architecture (WOSA) model, which separates the API from the protocol

18

service provider. In this model the WinSock DLL provides the standard API, and each

vendor installs its own service provider layer underneath. The API layer "talks" to a

service provider via a standardized Service Provider Interface (SPI), and it is capable of

multiplexing between multiple service providers simultaneously [9].

WinSock 2 specification has two distinct parts: the API for application developers and

the SPI for protocol stack and namespace service providers. There is also an intermediate

DLL layers which are independent of both the application developers and service

providers. These DLLs are provided and maintained by Microsoft and Intel. Layered

Service Provider comes on the top of a transport service provider [9].

19

The following figure illustrates the WinSock 2 architecture.

+---------------+ +-----------------++-----------------+ | WinSock 2 | | 16-bit WinSock || 32-bit WinSock | | Application | | 1.1 Application || 1.1 Application | +---------------+ +-----------------++-----------------+ | | | | +-----------------++-----------------+ <-- WinSock | | WINSOCK.DLL || WSSOCK32.DLL | 1.1 API | | (16-bit) || (32-bit) | | +-----------------++-----------------+ | | +-------------------------------------------------------+ <-- WinSock | WS2-32.DLL (32-bit) | 2.0 API +-------------------------------------------------------+ | +-------------------------------------------------------+ <--- WinSock |+-----------++--------------++------------++----------+| 2.0 SPI || TCP/IP || TCP/IP-based || additional ||Layered SP|| / || transport || namespace || service |+----------+| / || service || service pro- || providers |+----------+| <-- || provider || vider (DNS) || (SPX, etc.)|| Any TSP || |+-----------++--------------++------------++----------+| +-------------------------------------------------------+

Figure 2.6.1.1 WinSock2 Architecture [9]

MFC Provides two models for Windows socket programming.

CAsyncSocket – Encapsulation of the Windows sockets API is done by this class.

This class converts notification of network events messages in to callback

functions.

CSocket – It is derived form class CAsyncSocket. This class inherits many

member functions from CAsyncSocket that encapsulate Windows sockets APIs.

20

Synchronous operation is important so bloking is done by CSocket. It manages

aspects of communication using either API or class CAsyncSocket.

21

Chapter 3

PROJECT IMPLEMENTATION

This chapter is aimed to provide users with guidance on how the features provided by the

application are implemented, and to describe many details of the framework of video on

LAN application. Video chat on LAN is an application that is used for chatting within a

LAN. The following subjects are addressed in this chapter:

• The overall architecture of application.

• List of classes and macros.

3.1 Project Layout

Project is divided into three main parts

• List out features provided by application and implement those features.

• Make connection between two system using sockets.

• Implement module for webcam driver capture using MFC macros.

3.1.1 Implementation of Features

This section gives details of implementation of features. Detail includes functions

implemented to make these features functional as described in chapter 1.

22

Detail description of functionality.

• Map all the buttons and menu items corresponding to the function.

EnableMenuItem() and (CButton*)GetDlgItem(button) functions are implemented to

map menu options and buttons. EnableMenuItem() take menu item to be enabled and

action to take as parameters. Action includes enable, disable, grayed and other.

(CButton*)GetDlgItem(button) takes pointer to child window as parameter. To set and

get the window for the host and guest webcam SetWindowPos() and GetWindowRect()

functions are used.

Figure 3.1.1.1 Main window of application

23

• Add Contact and Delete Contact

As, this application work on LAN, it adds IP address as contact. To get IP address and

host name GetAddress() and gethostname() functions are used. This function updates

contact list as well as contact.log file. OnDeleteCintact() function implemented to delete

contact from the contact list. This function executes methods GetcaretIndex, GetText,

DeleteString to delete contact form contact list. This will also update “contact.log” file.

Figure 3.1.1.2 Add contact in contact list

24

• Connect to a Remote System

CAsyncSocket model is used to create socket in order to establish connection. Methods

SendTo() and OnReceive() are used to make connection to remote system. Depending on

the message type three sockets are created: DATA, VIDEO and CONTROLMSGS.

Figure 3.1.1.3 Connection accepted by user

• Send Text Data

Once connection is establised and the socketType is defined as TEXTDATA, then it

calls function StartTextChat().The function textSocket.SendTextData is implemented to

25

send the text data over the network. This function updates chat Windows on both the

systems.

Figure 3.1.1.4 Sending text data

• Start Host CAM

When the web cam is initialized, it calls the below functions:

Create a capture window using the function capCreateCaptureWindow.

Set the callback fuction by capSetCallbackOnFrame.

Connect to the CAM Driver using capDriverConnect.

26

Capturing of frames starts once the initialization is being done. To capture frames

created, a thread created by AfxBeginThread. capGrabFrame() function is used to capture

frames. Once a frame is captured, it is stored in BMP format by using capFileSaveDIB().

Then the BMP file is converted to JPEG format by using CImage::Load and

CImage::Save functions. Once the function capGrabFrame is executed it calls the

callback function to execute SendNDisplayVideo() function which displays the captured

frame using CImage::Draw and sends it to the remote host.

Figure 3.1.1.5 Initialization of webcam

• Stop the Host CAM

27

Video chat has to be stopped on this function call. The methods capCaptureStop(),

capCaptureAbort(), and capDriverDisconnect() stop the capturing and disconnect the

driver.

• Invite to View My CAM

CConnectCAMInvitation() function is called when this feature is executed. Depenging

upon the control messages, this function calls two methods -

CConnectCAMInvitation::OnConnectionAccept(), and

CConnectCAMInvitation::OnConnectionReject()

Figure 3.1.1.6 Inivitation to view webcam

28

• Request to View Guest CAM

CConnectCAMRequest() function is called when this feature is executed. Depenging

upon the control messages, this function calls two methods -

CConnectCAMInvitation::OnConnectionAccept(), and

CConnectCAMInvitation::OnConnectionReject().

Figure 3.1.1.7 Request to view webcam

• Stop Viewing Guest CAM

To implement this feature, the function capCaptureStop() is called. This function sends

control messages to the connected system.

29

• Disconnect From Remote System

A sequence of methods are called to stop video and text chat. capCaptureStop(),

capCaptureAbort(), capDriverDisconnect() ,Close() executes sequentially.

Figure 3.1.1.8 Disconnection of webcam

• Exit the Application

On exit , application closes all the open sockets. That includes it killing the thread to stop

the image-capturing process. OnExitApplication() calls the Shell_NotifyIcon()

function. It takes the arguments NIM_DELETE (0x00000002) and the pointer to the

thread-capturing structure.

30

The given tables give an overview of classes, functions and macros used by the

application.

CLASS DESCRIPTION REQUIREMENT USE IN APPLICATION

CAsyncSocket

encapsulates the Windows Socket Functions API

afxsock.h To create socket DATA,VIDEO AND CONTROLMSGS

CDialog The base class used for displaying dialog boxes on the screen.

afxwin.h To create dialog box for chat window

Table 3.1.1.1 Classes used by video chat on LAN

FUNCTION DESCRIPTION REQUIREMENT USE IN APPLICATION

DoDataExchange

Called by the framework to exchange and validate dialog data.

-

To exchange text and video data

GetDlgItem Retrieves a handle to a control in the specified dialog box.

-

To handle video and text controls

CapCreateCaptureWindow

Capture window is created by this function

Vfw.h, Vfw32.lib To create host and guest capture window for text data.

Table 3.1.1.2 Functions used by video chat on LAN

31

3.1.2 Establish Connection Using Socket

Sockets are used to make connection between two systems. A class named DataSocket

was created, which is a subclass of CSocket. The DataSocket class contains a

datamember named SocketType and the PortNumber. The sockets created are the objects

of the class DataSocket. Three types of UDP sockets were created, and port numbers used

for those sockets were defined.

// Type of UDP socket #define TYPE_CONTROLMESG 11 // for control messages #define TYPE_VIDEODATA 12 //for video data #define TYPE_TEXTDATA 13 // for text data // Port Numbers used for different UDP sockets #define PORT_CONTROLMESG 6000 // for control messages #define PORT_VIDEODATA 6002 // for video data #define PORT_TEXTDATA 6004 // for text data

To create Winsock application, the build environment should be linked to the library

wininet.lib. #pragma comment indicates to the linker that the wininet.lib file is needed.

Winsock 2 header files are included to use Winsock API. The Winsock2.h header file

contains most of the Winsock functions, structures, and definitions. The Ws2tcpip.h

header file contains definitions introduced in the WinSock 2 Protocol-Specific Annex

document for TCP/IP that includes newer functions and structures used to retrieve IP

addresses.

32

• Below text describes how text chat works on the system.

Function CreateSocket(PORT_TEXTDATA,TYPE_TEXTDATA) creates the socket for

text data. ReceiveFrom ( textData , textLength , address , portNumber ) reads the data

from given address and portnumber and reads textData for length of textLength.

SendTo(data,n+2,PORT_CONTROLMESG,remoteaddress) sends the data of buffer size

n+2 to the given remoteaddress. OnAccept() function returns the value zero for success or

returns an error on network failure. OnConnect() function returns the value zero for

success or returns an error on network failure. OnReceive() returns the value zero if the

function is executed successfully or returns an error if socket implementation detects that

the network subsystem failed. OnSend() returns the value zero if the function is executed

successfully or returns an error if socket implementation detects that the network

subsystem failed. Function Close() closes the socket and releases the socket descriptor so

that no other references can use it.

33

The below figure is an example of communication between two systems.

Check SocketType = TYPE_TEXTDATA/ TYPE_VIDEODATA/ TYPE_CONTROLMSGS Check textData[0] = different CONTROLMESGS

Figure 3.1.2.1 Communication between two systems

In this example, User2 is added in the contact list of User 1. This is done by executing

function OnAddContact(). This function adds User2 in the contact list of User1. Once

User 1 192.168.1.11

User 2 192.168.1.12

Accept connection request

Add IP in contact log

GetAddress()

WebCAM Started

OnAddContact()

CAsyscSocket::SendTo()

StartTextChat()

CONTROLMESG_VIEWCAMREQ

CONTROLMESG_ACCEPTCAMREQ

34

User2 has accepted the connection request, User1 can initiate chat with User2. This is

done by executing StartOnChat() function. Here, User2 is sending request to User1 to

view User1’s webcam. The request is being accepted by User1. Once it is accepted,

User2 can view User1’s webcam. This example use all three sockets DATA for text chat,

VIDEO for video data and CONTROLMESGS for control messages like request to view

webcam and user1 has accepted webcam view request from user2.

• Data exchange mechanism

The Dialog data exchange (DDX) mechanism is used to send and receive data. It is an

easy way to initialize the controls in a dialog box and to gather data input by the user.

Figure 3.1.2.2 Dialog data exchange

35

The initial values of the dialog object’s member variables are set in OnInitDialog handler.

DDX transfers the values of the member variables to the controls in the dialog box, where

they appear when the dialog box itself appears in response to DoModal. The same

mechanism transfers the values from the controls to the member variables when user

clicks the send button. If the user cancels a modal dialog box, the OnCancel member

function terminates the dialog box and DoModal returns the value IDCANCEL. In that

case, no data is exchanged between the dialog box and the dialog object.

3.1.3 Capturing Webcam Driver

This section describes how the webcam driver capture is done by MFC macros. Details

about capturing process of video frames and sending to other user are discussed here.

Following are the functions used to implement the webcam functionality:

void StartMyCAM(); //Start the webcam void StopMyCAM(); //Stop the webcam void InviteToViewCAM(); //Invite to view webcam void ReqToViewCAM(); //Request to view webcam void CAMDisconnected(); //Disconnect the webcam void StopViewGuestCAM (); //Stop viewing webcam To use MFC API’s for capturing webcam driver, “vfw32” library is used. #pragma

comment indicates to the linker that vfc32.lib file is needed. Also library “winmm” is

included so audio module can be implemented in future.

36

Given table lists the macros used by video chat on LAN:

MACRO DESCRIPTION REQUIREMENT USE IN APPLICATION

CapDriverConnect Connects a capture window to a capture driver

Vfw.h To connect capture window to a webcam driver

CapDriverDisconnect Disconnects a capture driver from a capture window.

Vfw.h To disconnect webcam driver from the capture window

CapSetCallbckOnFrame Sets a preview callback function in the application. AVICap calls this procedure when the capture window captures preview frames.

Vfw.h Preview captured frames. Returns TURE on successful or FALSE if frame capture session is in progress.

CapCaptureStop Stops the capture operation.

Vfw.h Stop capturing frames.

CapCaptureSetSetup Sets the configuration parameters used with streaming capture

Vfw.h To set streaming parameter with capture window.

CapCaptureGetSetup Retrieves the current settings of the streaming capture parameters.

Vfw.h To get streaming parameter for capture window

CapSetVideoFormat Sets the format of captured video data.

Vfw.h To save frames as bmp file.

Table 3.1.3.1 Macro used by video chat on LAN

37

Video data is captured in frames and stored in an image file, which is overwritten, every

hundred milliseconds by a new frame. To capture the frames, the structure

THREADSTRUCT was created. Function StartVideoCapture is called using

AfxBeginThread function. This function creates an object of THREAD STRUCT and sets

volatile bool threadRun data type to TRUE. It calls capGrabFrame to capture the frame.

Once frame is captured it is saved as an image using capFileSaveDIB. Every 100ms, a

new frame is captured and old image is deleted. To send saved images to receiver

SendDisplayVideo() function is called. fread() function reads the RecivedImageObj which

is a pointer to CImage.

• Below text describes how the webcam features work in the application:

Function capCreateCaptureWindow() creates the capture window. The function

capCreateCaptureWindow("Capture", WS_POPUP, 0, 0, 1, 1, 0, 0) takes the name used

for the capture window, style used for window, x-coordinate of the upper left corner of

the capture window, y-coordinate of the upper left corner of the capture window, Width

of the capture window, Height of the capture window, handle to the parent window and

the window identifier as arguments. The function capSetUserData(captureWindow, this)

captures user window. The function capSetCallbackOnFrame(captureWindow,

OnCaptureVideo) macro points to the preview callback function of type Video Stream

Callback. AVICap calls this procedure when captureWiindow captures preview frames.

capDriverConnect(captureWindow, index) macro connects captureWindow to capture

38

driver with index. Used index=0 for webcam driver. When capDriverConnect function is

called, it connects the capture window to the webcam driver. The application captures the

image and stores it as a bmp file. It converts it into the jpeg file and sends it to the

destination. After converting bmp file to jpeg file it deletes the bmp file. Capturing of

frame happens at every 100ms. To capture frames, a thread is implemented using the

macro AfxBeginThread. The thread AfxBeginThread (StartVideoCapture,

ThreadParameter) creates a new thread to capture images till the driver is connected.

capCaptureSetSetup (captureWindow,&CapParms,sizeof(CapParms) ) macro sets

configuration parameter used with streaming capture. capCaptureGetSetup

(captureWindow, &CapParms, sizeof(CapParms)) macro retrieves the current settings of

the streaming capture parameters. The macro

capSetVideoFormat(captureWindow,&VidCap_bmpinfo,sizeof(VidCap_bmpinfo)) is

called to set the format of capture video data. capGetVideoFormat

(captureWindow,&m_bmpinfo,sizeof(m_bmpinfo)) macro is called to retrieve a copy of

the video format used. When the user stops to view the webcam, the macro

capCaptureStop(captureWindow) is called. This macro stops the capture operation for

captureWindow. Once the function capCaptureStop is executed,

capDriverDisconnect(captureWindow) will be executed and it disconnects the capture

driver for captureWindow.

39

Chapter 4

CONCLUSION AND FUTURE WORK

The primary goal of this project is to create a Video Chat on LAN application. Video is

generally used in these applications in order to provide a richer sense of presence [5],

help coordination of communication [4] and facilitate emotional expression. However,

delivering high-quality video remains technically challenging for this application as it

uses UDP connections. To make video quality better, TCP connections can be used

instead of UDP. Also, by adding modules for send file and audio features, the application

can be made more versatile.

This application has been successfully implemented using VC++.NET and MFC library. I

have learned a lot about MFC library during implementation of different functionalities

for the application, and how they can be integrated with .NET framework to make a user-

friendly application.

To summarize, I would like to make a note that this Video chat on LAN Application is an

efficient and cost-effective application.

40

APPENDIX

VideoOverLanDlg.h #pragma once #define WM_TRAY_MESSAGE (WM_USER + 3) // CVideoOverLanDlg dialog class CVideoOverLanDlg : public CDialog { public: CVideoOverLanDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data enum { IDD = IDD_VIDEOOVERLAN_DIALOG }; NOTIFYICONDATA m_TrayData; CMenu m_menu; afx_msg void OnBnClickedOk(); afx_msg void OnBnClickedButton1(); HICON m_hIcon; virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); void OnTrayRButtonDown(CPoint pt); void OnExit(); LRESULT OnTrayNotify(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support private: CBitmapButton btnBmpENTER , btnBmpEXIT; };

41

VideoOverLanDlg.cpp #include "stdafx.h" #include "VideoOverLan.h" #include "VideoOverLanDlg.h" #include "ChatBox.h" #ifdef _DEBUG #define new DEBUG_NEW #endif CChatBox * chatObj; // CVideoOverLanDlg dialog CVideoOverLanDlg::CVideoOverLanDlg(CWnd* pParent /*=NULL*/) : CDialog(CVideoOverLanDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); btnBmpENTER.LoadBitmaps(IDB_BITMAP2); btnBmpEXIT.LoadBitmaps(IDB_BITMAP3); } void CVideoOverLanDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } // Maping the Buttons with user defined functions. BEGIN_MESSAGE_MAP(CVideoOverLanDlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDOK, &CVideoOverLanDlg::OnBnClickedOk) ON_MESSAGE(WM_TRAY_MESSAGE,OnTrayNotify) ON_COMMAND(ID_EXIT, OnExit) END_MESSAGE_MAP() // CVideoOverLanDlg message handlers BOOL CVideoOverLanDlg::OnInitDialog() { CDialog::OnInitDialog();

42

// IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

} } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here CButton *btnENTER , *btnEXIT ; //Load Bitmap images on Buttons. btnENTER = reinterpret_cast<CButton *>(GetDlgItem(IDOK));

LONG GWLENTER = GetWindowLong(btnENTER->m_hWnd, GWL_STYLE); SetWindowLong(btnENTER->m_hWnd, GWL_STYLE, GWLENTER | BS_OWNERDRAW) ;

btnBmpENTER.SubclassDlgItem(IDOK, this); btnEXIT = reinterpret_cast<CButton *>(GetDlgItem(IDCANCEL)); LONG GWLEXIT = GetWindowLong(btnEXIT->m_hWnd, GWL_STYLE);

SetWindowLong(btnEXIT->m_hWnd, GWL_STYLE, GWLEXIT | BS_OWNERDRAW) ;

btnBmpEXIT.SubclassDlgItem(IDCANCEL, this);

43

return TRUE; // return TRUE unless you set the focus to a control } void CVideoOverLanDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CVideoOverLanDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } // When ENTER Pressed void CVideoOverLanDlg::OnBnClickedOk() { chatObj = new CChatBox; chatObj->SetParent(this); //Create the System-tray Icon. m_TrayData.cbSize = sizeof(NOTIFYICONDATA); m_TrayData.hWnd = this->m_hWnd; m_TrayData.uID = 1;

44

m_TrayData.uCallbackMessage = WM_TRAY_MESSAGE; m_TrayData.hIcon = this->m_hIcon; strcpy(m_TrayData.szTip,"My Icon"); m_TrayData.uFlags = NIF_ICON|NIF_MESSAGE; //Load the Menu on the tray icon. BOOL BSus = FALSE; BSus = m_menu.LoadMenu(IDR_MENU2); if(!(BSus)) MessageBox("Unabled to Load menu"); BOOL bSuccess = FALSE; bSuccess = Shell_NotifyIcon(NIM_ADD,&m_TrayData); if(!(bSuccess)) MessageBox("Unable to Set Tary Icon"); else { this->ShowWindow(SW_MINIMIZE); this->ShowWindow(SW_HIDE); } chatObj->DoModal(); // Draw the Next window ( Chat Box window ). } //Tray Icon notify Function. LRESULT CVideoOverLanDlg::OnTrayNotify(WPARAM wParam, LPARAM lParam) { UINT uID; UINT uMsg; uID = (UINT) wParam; uMsg = (UINT) lParam; if (uID != 1) return 0; CPoint pt; switch (uMsg ) { case WM_LBUTTONDOWN: GetCursorPos(&pt); ClientToScreen(&pt); OnTrayRButtonDown(pt); break;

45

case WM_RBUTTONDOWN: case WM_CONTEXTMENU: GetCursorPos(&pt); OnTrayRButtonDown(pt); break; } return 1; } //On Right Button Pressed void CVideoOverLanDlg::OnTrayRButtonDown(CPoint pt) { m_menu.GetSubMenu(0)-> TrackPopupMenu(TPM_BOTTOMALIGN| TPM_LEFTBUTTON| TPM_RIGHTBUTTON,pt.x,pt.y,this); } //On EXIT. void CVideoOverLanDlg::OnExit() { Shell_NotifyIcon(NIM_DELETE,&m_TrayData); DestroyWindow(); }

46

VideoOverLan.h #pragma once #ifndef __AFXWIN_H__ #error "include 'stdafx.h' before including this file for PCH" #endif #include "resource.h" // CVideoOverLanApp: class CVideoOverLanApp : public CWinApp { public: CVideoOverLanApp(); public: virtual BOOL InitInstance();

DECLARE_MESSAGE_MAP() }; extern CVideoOverLanApp theApp;

47

VideoOverLan.cpp #include "stdafx.h" #include "VideoOverLan.h" #include "VideoOverLanDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CVideoOverLanApp BEGIN_MESSAGE_MAP(CVideoOverLanApp, CWinApp) ON_COMMAND(ID_HELP, &CWinApp::OnHelp) END_MESSAGE_MAP() // CVideoOverLanApp construction CVideoOverLanApp::CVideoOverLanApp() { } // The one and only CVideoOverLanApp object CVideoOverLanApp theApp; // CVideoOverLanApp initialization BOOL CVideoOverLanApp::InitInstance() { // InitCommonControlsEx() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable // visual styles. Otherwise, any window creation will fail. INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); // Set this to include all the common control classes you want to use // in your application. InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls);

48

CWinApp::InitInstance(); AfxEnableControlContainer(); SetRegistryKey(_T("Local AppWizard-Generated Applications")); CVideoOverLanDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { } else if (nResponse == IDCANCEL) { } return FALSE; }

49

stdafx.h

// stdafx.h : include file for standard system include files, or project specific include files that are used frequently, but are changed infrequently #pragma once #ifndef _SECURE_ATL #define _SECURE_ATL 1 #endif #ifndef VC_EXTRALEAN #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #endif // Modify the following defines if you have to target a platform prior to the ones specified below. // Refer to MSDN for the latest info on corresponding values for different platforms. #ifndef WINVER // Allow use of features specific to Windows XP or later. #define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. #endif #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or

//later. #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target

//other versions of Windows. #endif #ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or

//later. #define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target //Windows Me or later. #endif #ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. #define _WIN32_IE 0x0600 // Change this to the appropriate value to target other

// versions of IE. #endif #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors

//will be explicit

50

// turns off MFC's hiding of some common and often safely ignored warning messages #define _AFX_ALL_WARNINGS #include <afxwin.h> // MFC core and standard components #include <afxext.h> // MFC extensions #include <afxdisp.h> // MFC Automation classes #ifndef _AFX_NO_OLE_SUPPORT #include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls #endif #ifndef _AFX_NO_AFXCMN_SUPPORT #include <afxcmn.h> // MFC support for Windows Common Controls #endif // _AFX_NO_AFXCMN_SUPPORT #include <afxsock.h> // MFC socket extensions #include "atlimage.h" #ifdef _UNICODE #if defined _M_IX86 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") #elif defined _M_IA64 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") #elif defined _M_X64 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") #else #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") #endif #endif

51

stdafx.cpp // stdafx.cpp : source file that includes just the standard includes // VideoOverLan.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h"

52

Resource.h

//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by VideoOverLan.rc // #define IDM_ABOUTBOX 0x0010 #define IDD_ABOUTBOX 100 #define IDS_ABOUTBOX 101 #define IDD_VIDEOOVERLAN_DIALOG 102 #define IDR_MAINFRAME 128 #define IDD_DIALOG1 129 #define IDD_CHATBOX 129 #define IDR_MENU1 130 #define IDD_DIALOG2 131 #define IDD_DIALOG3 132 #define IDR_MENU2 133 #define IDB_BITMAP1 134 #define IDB_BITMAP2 135 #define IDB_BITMAP3 136 #define IDB_BITMAP4 137 #define IDB_BITMAP5 138 #define IDB_BITMAP6 139 #define IDD_DIALOG4 140 #define IDD_DIALOG5 142 #define IDB_BITMAP7 143 #define IDB_BITMAP8 144 #define IDC_IPADDRESS1 1000 #define IDC_LOCALVIDEO 1001 #define IDC_LOCALBORDER 1002 #define IDC_REMOTEBORDER 1003 #define IDC_REMOTEVIDEO 1004 #define IDC_LIST1 1005 #define IDC_EDIT1 1006 #define IDC_BUTTON1 1009 #define IDREJECT 1010 #define IDC_MESG 1011 #define IDC_EDIT2 1012 #define IDC_BUTTON2 1013 #define IDC_LIST2 1015 #define IDC_BUTTON3 1016

53

#define IDC_BUTTON4 1017 #define IDC_BUTTON5 1018 #define IDC_CAMREQ 1019 #define IDC_CAMINV 1021 #define IDB_STATIC 1022 #define ID_CHAT_CONNECT 32771 #define ID_CHAT_DISCONNECT 32772 #define ID_CHAT_EXIT 32773 #define ID_VIEW_LOCALVIDEOSCREEN 32774 #define ID_VIEW_REMOTEVIDEOSCREEN 32775 #define ID_HELP_ABOUT 32778 #define VIDEO_SEND 32784 #define VIDEO_RECEIVE 32785 #define HELP_ABOUT 32786 #define ID_EXIT_EXIT 32787 #define ID_EXIT 32788 #define CHAT_DISCONNECT 32789 #define CHAT_EXIT 32790 #define VIEW_MYCAM 32791 #define START_MYCAM 32792 #define STOP_MYCAM 32793 #define ID_VIEWCAM_STOPSENDINGVIDEO 32794 #define ID_VIEWCAM_STOPRECEIVINGVIDEO 32795 #define INVITE_CAM 32798 #define REQ_CAM 32799 #define STOP_GUESTCAM 32800 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 145 #define _APS_NEXT_COMMAND_VALUE 32801 #define _APS_NEXT_CONTROL_VALUE 1023 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif

54

DataSocket.h

#if !defined(AFX_DATASOCKET_H__B098630F_5F44_11D6_8897_000B2B0F84B6__INCLUDED_) #define AFX_DATASOCKET_H__B098630F_5F44_11D6_8897_000B2B0F84B6__INCLUDED_ // Type of UDP socket #define TYPE_CONTROLMESG 11 #define TYPE_VIDEODATA 12 #define TYPE_TEXTDATA 13 // Port Numbers used for different UDP sockets #define PORT_CONTROLMESG 6000 #define PORT_VIDEODATA 6002 #define PORT_TEXTDATA 6004 // Control Message types. #define CONTROLMESG_CONNECT 101 #define CONTROLMESG_DISCONNECT 102 #define CONTROLMESG_ACCEPT 103 #define CONTROLMESG_REJECT 104 #define CONTROLMESG_VIEWCAMERAREQ 105 #define CONTROLMESG_ACCEPTCAMREQ 106 #define CONTROLMESG_REJECTCAMREQ 107 #define CONTROLMESG_VIEWCAMERAINV 108 #define CONTROLMESG_ACCEPTCAMINV 109 #define CONTROLMESG_REJECTCAMINV 110 #define CONTROLMESG_CAMDISCONNECT 111 #define CONTROLMESG_STOPVIEWCAM 112 #define CONTROLMESG_NOCAM 113

55

class DataSocket : public CSocket { public: CDialog *parentDlg; char localname[200]; static char remotename[500]; static char remoteaddress[500]; int SocketType; static unsigned char textData[2000] , videoData[30000]; static unsigned int textLength , videoLength; DataSocket(); virtual ~DataSocket(); void CreateSocket(int port,int type); void SetParent(CDialog *dlg); void OnReceive(int errcode); void SendControlMessage(int type,char *address); void SendVideoData(unsigned char *data,int length); void SendTextData(unsigned char *data,short length); void CloseSocket(); }; #endif

56

DataSocket.cpp

#pragma comment(lib, "wininet.lib") #include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #include <windows.h> #include "stdafx.h" #include "VideoOverLan.h" #include "DataSocket.h" #include "VideoOverLanDlg.h" #include "ChatBox.h" #include "ConnectionRequestDlg.h" #include "ConnectCAMRequest.h" #include "ConnectCAMInvitation.h" char DataSocket::remoteaddress[500]=""; char DataSocket::remotename[500]=""; unsigned char DataSocket::textData[2000]; unsigned char DataSocket::videoData[30000]; unsigned int DataSocket::textLength=2000; unsigned int DataSocket::videoLength=30000; DataSocket::DataSocket() { } DataSocket::~DataSocket() { } // Create the Socket with particular type and port number. void DataSocket::CreateSocket(int port,int DataType) { WORD wVersionRequested; WSADATA wsaData; int err;

57

CString ERR; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { ERR.Format("WSAStartup failed with error: %d\n", err); AfxMessageBox(ERR); return ; } this->Create(port,SOCK_DGRAM); SocketType=DataType; gethostname(localname,300); } void DataSocket::SetParent(CDialog *dlg) { parentDlg=dlg; } //Called by the framework when message/data is received on the socket. void DataSocket::OnReceive(int errcode) { CString address; char hname[400],str[1000],mesg[500]; unsigned int portNumber , retvalue; int n,len; ConnectionRequestDlg requestDlg(NULL); CConnectCAMRequest CAMRequestDlg(NULL); CConnectCAMInvitation CAMInviteDlg(NULL); // Checking for the DATA Type. if(SocketType==TYPE_CONTROLMESG) {

retvalue = this->ReceiveFrom ( textData , textLength , address , portNumber ); // Read the DATA.

if(retvalue==SOCKET_ERROR) return; int i = 0; for ( i=0 ; i<textData[1] ; i++ ) hname[i] = textData[i+2];

58

hname[i] = 0; strcpy ( remotename , hname ); strcpy ( remoteaddress , (LPCTSTR) address); //Checking for Particular Message. if ( textData[0] == CONTROLMESG_CONNECT ) // Connect Request { requestDlg.SetParameter(remotename,remoteaddress,parentDlg); requestDlg.DoModal(); return; }

else if ( textData[0] == CONTROLMESG_DISCONNECT ) { ( (CChatBox*)parentDlg)->StopTextChat(); sprintf(str,"User %s has disconnected",hname); AfxMessageBox(str); return; } else if ( textData[0] == CONTROLMESG_CAMDISCONNECT ) { ( (CChatBox*)parentDlg)->CAMDisconnected(); sprintf ( str , "USER %s has Disconnected the CAM" , hname ); AfxMessageBox ( str ); } else if ( textData[0] == CONTROLMESG_ACCEPT ) { AfxMessageBox("User has accepted the connection"); ( (CChatBox*)parentDlg)->StartTextChat(); return; } else if ( textData[0] == CONTROLMESG_REJECT ) //Connection Rejected. { sprintf(str,"User %s has rejected your invitation",hname); AfxMessageBox(str); return; } else if ( textData[0] == CONTROLMESG_VIEWCAMERAREQ ) { if ( ( ( CChatBox * ) parentDlg )->MyCAMStarted ) {

59

CAMRequestDlg.SetParameter(remotename,remoteaddress,parentDlg); CAMRequestDlg.DoModal(); return; } else

((CChatBox*)parentDlg)-> controlMSGSocket.SendControlMessage (CONTROLMESG_NOCAM,NULL);

} else if ( textData[0] == CONTROLMESG_ACCEPTCAMREQ ) { AfxMessageBox("User has Accepted Your Request");

( ( CChatBox * ) parentDlg )->menu->EnableMenuItem ( REQ_CAM , MF_GRAYED );

( ( CChatBox * ) parentDlg )->menu->EnableMenuItem ( STOP_GUESTCAM , MF_ENABLED );

if ( ( ( CChatBox * ) parentDlg )->MyCAMStarted ) ( ( CChatBox * ) parentDlg )->menu->EnableMenuItem (

INVITE_CAM , MF_ENABLED ); ( ( CChatBox * ) parentDlg )->ReceiveCAM = TRUE; ( ( CChatBox * ) parentDlg )->StopGuestCAM = FALSE; return; } else if ( textData[0] == CONTROLMESG_REJECTCAMREQ ) //Reject the Request to view the CAM {

sprintf(str,"User %s has rejected your Request to View the CAM",hname);

AfxMessageBox(str); return; } else if ( textData[0] == CONTROLMESG_VIEWCAMERAINV ) { CAMInviteDlg.SetParameter(remotename,remoteaddress,parentDlg); CAMInviteDlg.DoModal(); return; } else if ( textData[0] == CONTROLMESG_ACCEPTCAMINV ) { AfxMessageBox("User has accepted Your Invitation");

60

( ( CChatBox * ) parentDlg )->menu->EnableMenuItem ( INVITE_CAM , MF_GRAYED );

( ( CChatBox * ) parentDlg )->SendMyCAM = TRUE; return; } else if ( textData[0] == CONTROLMESG_REJECTCAMINV ) //Reject the invitation. {

sprintf(str,"User %s has rejected your Invitation to View the CAM",hname);

AfxMessageBox(str); return; } else if ( textData[0] == CONTROLMESG_STOPVIEWCAM ) {

( ( CChatBox * ) parentDlg )->menu->EnableMenuItem ( INVITE_CAM , MF_ENABLED );

sprintf ( str , "USER %s has Stoppped Viewing Your CAM" , hname );

AfxMessageBox ( str ); return ; } else if ( textData[0] == CONTROLMESG_NOCAM ) {

sprintf ( str , "Either USER %s Didn't Have a CAM or didn't START CAM" , hname );

AfxMessageBox ( str ); return ; } return; } if ( SocketType == TYPE_VIDEODATA ) // Type Video. {

retvalue = this->ReceiveFrom ( videoData , videoLength , address , portNumber );

if ( retvalue == SOCKET_ERROR ) return;

( ( CChatBox * ) parentDlg )->DisplayReceivedFrame ( videoData , retvalue );

return; } if ( SocketType == TYPE_TEXTDATA ) //Type Text Data.

61

{ retvalue = this->ReceiveFrom ( textData , textLength , address ,

portNumber ); if ( retvalue == SOCKET_ERROR ) return; // Get host name from the data. // Length of username n = textData[1]; int i = 0; for ( i = 0 ; i < n ; i++) hname[i] = textData[i+2]; hname[i] = 0; len = textData[n+2] | ( textData[n+3] << 8 ); memcpy(mesg,&textData[n+4],len); mesg[len]=0; sprintf(str,"%s >> %s ",hname,mesg); // Display message in list box ((CChatBox *)parentDlg)->DisplayMesg(str); return; } } // Send the control message to remote host void DataSocket::SendControlMessage(int type,char *address) { char data[1000]; int n; // Prepare the message DATA // Type of the Message data[0]=type; // Length of hostname n=strlen(localname); data[1]=n; // Name of the sender host

62

memcpy(&data[2],localname,n); if(address==NULL) SendTo(data,n+2,PORT_CONTROLMESG,remoteaddress); else SendTo(data,n+2,PORT_CONTROLMESG,address); } //Send the VIDEO data to remote host void DataSocket::SendVideoData(unsigned char *data,int length) { SendTo(data,length,PORT_VIDEODATA,remoteaddress); } //Send the TEXT data to remote host void DataSocket::SendTextData(unsigned char *data,short length) { unsigned char *packet=new unsigned char[length+500]; int n; // Create the Packet to Send // Set the Type Text message packet[0]=TYPE_TEXTDATA; // Length of hostname n=strlen(localname); packet[1]=n; // Hostname memcpy(&packet[2],localname,n); // Data length packet[n+2]=(unsigned char) length; packet[n+3]=(unsigned char) (length>>8); // Data memcpy(&packet[n+4],data,length); SendTo(packet,n+4+length,PORT_TEXTDATA,remoteaddress); }

63

//Closes the socket created by the createsocket method void DataSocket::CloseSocket() { DataSocket::Close(); }

64

Chatbox.h

#include<vfw.h> #include<afxmt.h> #include<afxole.h> #include "DataSocket.h" #include "AddContactDlg.h" #include "afxwin.h" #define CAM_WIDTH 176 #define CAM_HEIGHT 144 #define IMAGE_WIDTH CAM_WIDTH #define IMAGE_HEIGHT CAM_HEIGHT // CChatBox dialog class CChatBox : public CDialog { DECLARE_DYNAMIC(CChatBox) public: CDialog *mdlg; HWND captureWindow; CAPDRIVERCAPS caps; BOOL TextChatStarted ; BOOL MyCAMStarted , StopGuestCAM , InviteCAMEnable; BOOL SendMyCAM ,ReceiveCAM; PBITMAPINFO m_bmpinfo; BITMAPINFO compbmp , VidCap_bmpinfo; BITMAPINFOHEADER m_bmpheader; BOOL CAMInitialize(); BOOL SetCaptureParameters(); void CAMDestroy(); void GetDriverCaps(); BOOL StartCapture(); BOOL StopCapture();

65

friend LRESULT CALLBACK OnCaptureVideo(HWND hWnd, LPVIDEOHDR lpheader) ;

static UINT StartVideoCapture (LPVOID param); typedef struct THREADSTRUCT { CChatBox * _this; } THREADSTRUCT; HDC m_hdc; CMenu *menu; CButton *SendButton; CButton *ConnectButton; CButton *CancelConnectButton; CListBox *ChatListBox; CListBox ContactListBox; CStdioFile ContactListFile; CChatBox * chatObj; HICON m_hIcon; HWND hwnd; CAddContactDlg *addContactdlg; DataSocket controlMSGSocket , videoSocket , textSocket; HDRAWDIB hdib; int local_wnd_x , local_wnd_y; int remote_wnd_x , remote_wnd_y; CChatBox(CWnd* pParent = NULL); virtual ~CChatBox(); void SetParent(CDialog *dlg); enum { IDD = IDD_CHATBOX }; virtual void DoDataExchange(CDataExchange* pDX); virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnCancel ();

66

afx_msg void OnContactSelect(); virtual void OnExitApplication(); void OnDisconnect(); void StartMyCAM(); void StopMyCAM(); void InviteToViewCAM(); void ReqToViewCAM(); void CAMDisconnected(); void StopViewGuestCAM (); void OnAbout(); void StartTextChat(); void StopTextChat(); void OnSendMesg(); void OnConnect(); void OnCancelConnect(); void OnDeleteContct(); void OnAddContact(); void DisplayMesg(char *str); void SendNDisplayVideo(); void DisplayReceivedFrame(unsigned char *data,int size); DECLARE_MESSAGE_MAP() };

67

ChatBox.cpp #include "stdafx.h" #include "VideoOverLan.h" #include "VideoOverLanDlg.h" #include "ChatBox.h" #pragma comment(lib,"vfw32") #pragma comment(lib,"winmm") int lengthOfFile = 0; bool JpegCreated = false; volatile bool threadRun = TRUE; unsigned char sendData[10000]; class CAboutDlg : public CDialog { public: CAboutDlg(); enum { IDD = IDD_ABOUTBOX }; // ClassWizard generated virtual function overrides protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); }

68

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // CChatBox dialog IMPLEMENT_DYNAMIC(CChatBox, CDialog) CChatBox::CChatBox(CWnd* pParent /*=NULL*/) : CDialog(CChatBox::IDD, pParent) { } CChatBox::~CChatBox() { } void CChatBox::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST2, ContactListBox); } void CChatBox::SetParent(CDialog *dlg) { mdlg=dlg; } BEGIN_MESSAGE_MAP(CChatBox, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() // Chat menu handlers ON_COMMAND(CHAT_DISCONNECT,OnDisconnect) ON_COMMAND(CHAT_EXIT,OnExitApplication) // Display CAM menu handlers ON_COMMAND(START_MYCAM,StartMyCAM) ON_COMMAND(STOP_MYCAM,StopMyCAM)

69

// View CAM menu handlers ON_COMMAND(INVITE_CAM,InviteToViewCAM) ON_COMMAND(REQ_CAM,ReqToViewCAM) ON_COMMAND ( STOP_GUESTCAM , StopViewGuestCAM ) // ABOUT menu handlers ON_COMMAND(HELP_ABOUT,OnAbout) ON_COMMAND(IDOK,OnSendMesg) ON_COMMAND(IDC_BUTTON1, OnConnect) ON_COMMAND(IDC_BUTTON2, OnCancelConnect) ON_COMMAND(IDC_BUTTON4, OnAddContact) ON_COMMAND(IDC_BUTTON5, OnDeleteContct) //Notification Handler for Contact List. ON_LBN_SELCHANGE(IDC_LIST2, OnContactSelect) END_MESSAGE_MAP() // Init Dialog for ChatBox Dialog BOOL CChatBox::OnInitDialog() { CDialog::OnInitDialog(); ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

} } SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon

70

// Open ContactListFile

ContactListFile.Open("ContactFile.log",CFile::modeCreate | CFile::modeNoTruncate | CFile::modeRead);

// Disable/Enable the menu items menu=this->GetMenu();

menu->EnableMenuItem(CHAT_DISCONNECT,MF_DISABLED | MF_GRAYED);

menu->EnableMenuItem(INVITE_CAM,MF_GRAYED); menu->EnableMenuItem(REQ_CAM,MF_GRAYED); menu->EnableMenuItem(STOP_GUESTCAM,MF_GRAYED); menu->EnableMenuItem(STOP_MYCAM,MF_GRAYED); menu->EnableMenuItem(START_MYCAM,MF_ENABLED); ChatListBox = (CListBox*)GetDlgItem(IDC_LIST1); //Initialize ChatListBox SendButton = (CButton*)GetDlgItem(IDOK); ConnectButton = (CButton*)GetDlgItem(IDC_BUTTON1); CancelConnectButton = (CButton*)GetDlgItem(IDC_BUTTON2); // Disable the send button SendButton->EnableWindow(FALSE); MyCAMStarted = FALSE; StopGuestCAM = FALSE; SendMyCAM=FALSE; ReceiveCAM=FALSE; TextChatStarted = FALSE; CWnd *wnd,*bwnd; CRect rect,brect; // Initialize the Window for viewing MY CAM wnd=this->GetDlgItem(IDC_LOCALVIDEO); bwnd=this->GetDlgItem(IDC_LOCALBORDER); bwnd->GetWindowRect(brect);

71

ScreenToClient(brect); local_wnd_x=brect.TopLeft().x+(brect.Width()-IMAGE_WIDTH)/2; local_wnd_y=brect.TopLeft().y+(brect.Height()-IMAGE_HEIGHT)/2;

wnd->SetWindowPos(&wndTop,local_wnd_x-4,local_wnd_y-4, IMAGE_WIDTH+9,IMAGE_HEIGHT+9,SWP_SHOWWINDOW | SWP_DRAWFRAME);

// Initialize the Window for viewing Guest's CAM wnd=this->GetDlgItem(IDC_REMOTEVIDEO); // Video display window bwnd=this->GetDlgItem(IDC_REMOTEBORDER); // Border window... bwnd->GetWindowRect(brect); ScreenToClient(brect); remote_wnd_x=brect.TopLeft().x+(brect.Width()-IMAGE_WIDTH)/2; remote_wnd_y=brect.TopLeft().y+(brect.Height()-IMAGE_HEIGHT)/2;

wnd->SetWindowPos(&wndTop,remote_wnd_x-4,remote_wnd_y-4, IMAGE_WIDTH+9,IMAGE_HEIGHT+9,SWP_SHOWWINDOW | SWP_DRAWFRAME);

// Get Dialog DC m_hdc=this->GetDC()->m_hDC; // Setup the connect dialog box addContactdlg=new CAddContactDlg(NULL); addContactdlg->SetParent(this); // Setup the parent for differnt UDP sockets controlMSGSocket.SetParent(this); videoSocket.SetParent(this); textSocket.SetParent(this); // Create UDP socket for Transmitting and receiving Control messages

controlMSGSocket.CreateSocket(PORT_CONTROLMESG,TYPE_CONTROLMESG);

//Read the contents of Contact list file and display on the contact list window. lengthOfFile = ContactListFile.GetLength();

72

if ( lengthOfFile ) { int i = 0 , j = 0; char * Buffer = NULL; char contact[300] = ""; Buffer = new char [lengthOfFile]; ContactListFile.Read ( Buffer , lengthOfFile ); for ( i = 0 ; i < lengthOfFile ; i++ , j++ ) { if ( Buffer[i] != '\n' ) contact[j] = Buffer[i]; else { contact[j] = '\0'; j = 0; ContactListBox.AddString ( contact ); } } } ContactListFile.Close (); return TRUE; // return TRUE unless you set the focus to a control } void CChatBox::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } void CChatBox::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting

73

SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } HCURSOR CChatBox::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } void CChatBox::OnCancel() { OnExitApplication(); } void CChatBox::OnExitApplication() { //Stop the Thread threadRun = FALSE; // If the not disconnected from the remote system then disconnect if(TextChatStarted) StopTextChat(); //If Cam is not stopped, stop the CAM if ( MyCAMStarted ) StopMyCAM(); // Close the control message Socket controlMSGSocket.CloseSocket();

74

// Close the video capture device CAMDestroy(); // Close graphics.... if(hdib!=NULL) { ::DrawDibEnd(hdib); ::DrawDibClose(hdib); } CDialog::OnCancel(); //Close the Parent Window. ( ( CVideoOverLanDlg * )mdlg)->OnExit(); } void CChatBox::OnDisconnect() { // Send notification to the remote host... controlMSGSocket.SendControlMessage(CONTROLMESG_DISCONNECT,NULL); StopTextChat(); } void CChatBox::StartMyCAM() { CMenu *menu=this->GetMenu(); if( MyCAMStarted == FALSE ) { if ( CAMInitialize () ) { m_bmpinfo=&VidCap_bmpinfo;

menu-> EnableMenuItem(START_MYCAM,MF_DISABLED | MF_GRAYED);

menu->EnableMenuItem(STOP_MYCAM,MF_ENABLED); if ( TextChatStarted == TRUE ) { menu->EnableMenuItem(INVITE_CAM,MF_ENABLED); InviteCAMEnable = TRUE; } MyCAMStarted=TRUE;

75

if ( StartCapture () == FALSE ) { MessageBox("Unable to start the capture"); } } } } void CChatBox::StopMyCAM() { CMenu *menu=this->GetMenu(); if ( MyCAMStarted ) { StopCapture (); CAMDestroy (); CWnd *wnd=(CWnd*)this->GetDlgItem(IDC_LOCALVIDEO); wnd->Invalidate(TRUE); menu->EnableMenuItem(START_MYCAM,MF_ENABLED); menu->EnableMenuItem(STOP_MYCAM,MF_GRAYED); if ( InviteCAMEnable == TRUE ) { if ( SendMyCAM == TRUE )

controlMSGSocket.SendControlMessage(CONTROLMESG_CAMDISCONNECT,NULL);

menu->EnableMenuItem(INVITE_CAM,MF_GRAYED); InviteCAMEnable = FALSE; } MyCAMStarted = FALSE; } } void CChatBox::InviteToViewCAM() { controlMSGSocket.SendControlMessage(CONTROLMESG_VIEWCAMERAINV,NULL); } void CChatBox::ReqToViewCAM() { controlMSGSocket.SendControlMessage(CONTROLMESG_VIEWCAMERAREQ,NULL); }

76

void CChatBox::OnAbout() { CAboutDlg dlgAbout; dlgAbout.DoModal(); } void CChatBox::OnSendMesg() { unsigned char data[500]; char msg[500]; //Get the Message from Edit Box. GetDlgItemText(IDC_EDIT1,(char*)data,500); if(strlen((const char*)data)>0) // Checking if any Message is there or Not. { //Call the function to send the data to Remote Host. textSocket.SendTextData(data,strlen((const char*)data)); //Clean the Edit Box. SetDlgItemText(IDC_EDIT1,""); //Call the function to Display the Message on the List Box. sprintf ( msg , "%s >> %s" , "ME" , data ); DisplayMesg ( msg ); } } void CChatBox::DisplayMesg(char *mesg) { //The Message is Displaying On the List Box. ChatListBox->AddString(mesg); } void CChatBox::DisplayReceivedFrame(unsigned char *data1,int size) { // If remote view disabled then return... if(StopGuestCAM == TRUE) return; // If video reception disabled..then return..

77

if(ReceiveCAM == FALSE) return; FILE * JpegFileWrite = NULL ; JpegFileWrite = fopen ( "RecivedFrame.jpg" , "wb+" ); fwrite ( data1 , sizeof ( unsigned char ) , size , JpegFileWrite ); fclose ( JpegFileWrite); CImage * RecivedImageObj = new CImage; ; CString ReciveFramePath = _T("RecivedFrame.jpg"); HRESULT hResult = RecivedImageObj->Load(ReciveFramePath); RecivedImageObj->Draw (m_hdc,remote_wnd_x,remote_wnd_y,IMAGE_WIDTH,IMAGE_HEIGHT,0,0,IMAGE_WIDTH,IMAGE_HEIGHT); } void CChatBox::SendNDisplayVideo() { CRect wndrect; // Display the captured frame... if(MyCAMStarted) { CImage * RecivedImageObj = new CImage; ; CString ReciveFramePath = _T("CaptureFrame.bmp"); HRESULT hResult = RecivedImageObj->Load(ReciveFramePath);

RecivedImageObj->Draw (m_hdc,local_wnd_x,local_wnd_y, IMAGE_WIDTH,IMAGE_HEIGHT,0,0,IMAGE_WIDTH,IMAGE_HEIGHT);

} if(SendMyCAM == TRUE) { if ( JpegCreated == true ) { int i = 0 , len = 0; FILE * JpegFileRead; unsigned char A[2];

if ( ( JpegFileRead = fopen ( "CaptureFrame.jpg" , "rb+") ) == NULL )

{

78

AfxMessageBox ( "File CaptureFrame.jpg can't open" ); return; } while(!feof(JpegFileRead)) { fread(A , sizeof(unsigned char) , 1 , JpegFileRead) ; sendData[i] = A[0]; i++; } fclose ( JpegFileRead) ; videoSocket.SendVideoData ( sendData , i ); } } } void CChatBox::StartTextChat() { if(TextChatStarted) return; TextChatStarted=TRUE; // Enable / Disable menu items... menu->EnableMenuItem(CHAT_DISCONNECT,MF_ENABLED); menu->EnableMenuItem(REQ_CAM,MF_ENABLED); if ( MyCAMStarted ) { menu->EnableMenuItem(INVITE_CAM,MF_ENABLED); InviteCAMEnable = TRUE ; } // Create Socket for text data transfer. textSocket.CreateSocket(PORT_TEXTDATA,TYPE_TEXTDATA); // Enable the send button SendButton->EnableWindow(TRUE); // Create Socket for video data transfer. videoSocket.CreateSocket(PORT_VIDEODATA,TYPE_VIDEODATA);

79

ConnectButton->EnableWindow(FALSE); CancelConnectButton->EnableWindow(FALSE); } void CChatBox::StopTextChat() { if(TextChatStarted==FALSE) return; TextChatStarted=FALSE; // Enable/disable menu items

menu->EnableMenuItem(CHAT_DISCONNECT,MF_DISABLED | MF_GRAYED);

// Close the Text tranfsfer textSocket.CloseSocket(); // Disable the send button. SendButton->EnableWindow(FALSE); // Clear the contents of text chat windows SetDlgItemText(IDC_EDIT1,""); ChatListBox->ResetContent(); //Close the Video Transfer videoSocket.CloseSocket(); // Update local and remote sytem CAM viewing Windows. CWnd * wnd=(CWnd*)this->GetDlgItem(IDC_REMOTEVIDEO); wnd->Invalidate(TRUE); SendMyCAM=FALSE; ReceiveCAM=FALSE; menu->EnableMenuItem(INVITE_CAM,MF_GRAYED); menu->EnableMenuItem(REQ_CAM,MF_GRAYED); menu->EnableMenuItem(STOP_GUESTCAM,MF_GRAYED); ConnectButton->EnableWindow ( TRUE ); CancelConnectButton->EnableWindow ( TRUE );

80

} // When CONNECT Button Pressed. void CChatBox::OnConnect() { char hostname[200]; this->GetDlgItemText(IDC_EDIT2,hostname,200); //Get the data from the Box. SetDlgItemText(IDC_EDIT2,""); // Clear the Box controlMSGSocket.SendControlMessage(CONTROLMESG_CONNECT,hostname); //Send the Connection Request to Remote system. } //When CANCEL Button Pressed. void CChatBox::OnCancelConnect() { SetDlgItemText(IDC_EDIT2,""); // Clear the Box. } // When Add Contact Button Pressed void CChatBox::OnAddContact() { addContactdlg->DoModal(); // Call the Contact Dialogue. } //Delete A Contact From the Contact List void CChatBox::OnDeleteContct() { int index = 100; CString DeleteData , CompareData; //Get the Selected Contact and Delete it. index = ContactListBox.GetCaretIndex(); ContactListBox.GetText ( index ,DeleteData ); ContactListBox.DeleteString ( index ); SetDlgItemText(IDC_EDIT2,""); //Update the ContactFile Entries.

ContactListFile.Open("ContactFile.log",CFile::modeCreate | CFile::modeNoTruncate | CFile::modeRead);

lengthOfFile = ContactListFile.GetLength(); if ( lengthOfFile ) { int i = 0 , j = 0;

81

char * Buffer = NULL; char contact[300] = ""; Buffer = new char [lengthOfFile]; ContactListFile.SeekToBegin(); ContactListFile.Read ( Buffer , lengthOfFile ); ContactListFile.Close();

ContactListFile.Open ( "ContactFile.log" , CFile::modeCreate | CFile::modeWrite );

for ( i = 0 ; i < lengthOfFile ; i++ , j++ ) { if ( Buffer[i] != '\n' ) contact[j] = Buffer[i]; else { contact[j] = '\0'; j = 0; if ( DeleteData.Compare ( contact ) ) { ContactListFile.SeekToEnd(); ContactListFile.Write ( contact , strlen ( contact ) ); ContactListFile.Write ( "\n" , 1 ); } } } ContactListFile.Close (); } } //Contact List notify function. void CChatBox::OnContactSelect() { int index = 0; int curPos= 0; CString ContactListIP, ConnectBoxIP; index = ContactListBox.GetCaretIndex(); ContactListBox.GetText ( index , ContactListIP ); ContactListIP.MakeReverse(); ConnectBoxIP = ContactListIP.Tokenize(" ",curPos);

82

ConnectBoxIP.MakeReverse(); SetDlgItemText(IDC_EDIT2,ConnectBoxIP); } // Initializing the CAM BOOL CChatBox::CAMInitialize() { int index=0; captureWindow = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0); //Create Capture Window if(captureWindow==NULL) return FALSE; capSetUserData(captureWindow,this); capSetCallbackOnFrame(captureWindow,OnCaptureVideo);//Set the Callback Function. // Connect to webcam driver if( ! capDriverConnect(captureWindow,index) ) { // Device may be open already or it may not have been closed properly last time. AfxMessageBox("Unable to open Video Capture Device"); captureWindow=NULL; return FALSE; } // Set the capture parameters if(SetCaptureParameters()==FALSE) { capDriverDisconnect(captureWindow); return FALSE; } return TRUE; } //Thread to perforn the Capturing. UINT CChatBox::StartVideoCapture (LPVOID ThreadParameter) { THREADSTRUCT * ThreadStructObj = (THREADSTRUCT*) ThreadParameter; CImage * CaptureImage = new CImage; threadRun = TRUE;

83

// Start the Capturing while ( threadRun == TRUE ) {

capGrabFrame ( ThreadStructObj->_this->captureWindow ); if ( capFileSaveDIB ( ThreadStructObj->_this->captureWindow ,

"CaptureFrame.bmp" ) ) //Save as BMP file. { // Convert to JPEG image. CString CaptureFramePath = _T("CaptureFrame.bmp"); HRESULT hResult = CaptureImage->Load(CaptureFramePath); hResult = CaptureImage->Save(_T("CaptureFrame.jpg")); JpegCreated = true; } Sleep(100); } delete CaptureImage; return 1; } BOOL CChatBox::StartCapture() { THREADSTRUCT * ThreadParameter = new THREADSTRUCT; ThreadParameter->_this = this; AfxBeginThread (StartVideoCapture, ThreadParameter); //Creating the thread. return TRUE; } BOOL CChatBox::StopCapture() { capCaptureStop(captureWindow); capCaptureAbort(captureWindow); threadRun = FALSE; Sleep(2000); return TRUE; } void CChatBox::CAMDestroy() { if(captureWindow==NULL) return;

84

// Stop the capturing process capCaptureAbort(captureWindow); // Disable the callback function.. capSetCallbackOnVideoStream(captureWindow, NULL); Sleep(300); // This delay is important... // Disconnect the CAM driver capDriverDisconnect(captureWindow); } BOOL CChatBox::SetCaptureParameters() { CAPTUREPARMS CapParms={0}; capCaptureGetSetup(captureWindow,&CapParms,sizeof(CapParms)); CapParms.fAbortLeftMouse = FALSE; CapParms.fAbortRightMouse = FALSE; CapParms.fYield = TRUE; CapParms.wPercentDropForError = 50; if(capCaptureSetSetup(captureWindow,&CapParms,sizeof(CapParms))==FALSE) return FALSE; // Set Video Format capGetVideoFormat(captureWindow,&m_bmpinfo,sizeof(m_bmpinfo)); VidCap_bmpinfo.bmiHeader.biWidth=IMAGE_WIDTH; VidCap_bmpinfo.bmiHeader.biHeight=IMAGE_HEIGHT; BOOL ret=capSetVideoFormat(captureWindow,&VidCap_bmpinfo,sizeof(VidCap_bmpinfo)); return TRUE; } LRESULT CALLBACK OnCaptureVideo(HWND mwnd,LPVIDEOHDR lphdr) { CChatBox * vidcapObj = ( CChatBox * ) capGetUserData ( mwnd ) ; if(vidcapObj!=NULL ) {

85

vidcapObj->SendNDisplayVideo(); } return TRUE; } // Disconnect the CAM void CChatBox::CAMDisconnected() { ReceiveCAM = FALSE; menu->EnableMenuItem ( REQ_CAM , MF_ENABLED ); menu->EnableMenuItem(STOP_GUESTCAM,MF_GRAYED); CWnd * wnd=(CWnd*)this->GetDlgItem(IDC_REMOTEVIDEO); wnd->Invalidate(TRUE); } //Stop Viewing the Guest CAM void CChatBox::StopViewGuestCAM () { StopGuestCAM = TRUE; controlMSGSocket.SendControlMessage(CONTROLMESG_STOPVIEWCAM,NULL); menu->EnableMenuItem ( STOP_GUESTCAM , MF_GRAYED ); menu->EnableMenuItem ( REQ_CAM , MF_ENABLED ); }

86

AddContactDlg.h

#pragma once #include "afxcmn.h" // CAddContactDlg dialog class CAddContactDlg : public CDialog { DECLARE_DYNAMIC(CAddContactDlg) // Attributes public: CDialog *mdlg; CAddContactDlg(CWnd* pParent = NULL); // standard constructor virtual ~CAddContactDlg(); CIPAddressCtrl ConnectIP; void SetParent(CDialog *dlg); afx_msg void OnAddContct(); afx_msg void OnClose(); afx_msg void OnBnClickedButton1(); afx_msg void OnBnClickedCancel(); DECLARE_MESSAGE_MAP() // Dialog Data enum { IDD = IDD_DIALOG2 }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support };

87

ConnectCAMInvitation..h

#if !defined(AFX_CONNECTCAMINVITATION_H__5FB1D083_5F66_11D6_8897_000B2B0F84B6__INCLUDED_) #define AFX_CONNECTCAMINVITATION_H__5FB1D083_5F66_11D6_8897_000B2B0F84B6__INCLUDED_ #pragma once // CConnectCAMInvitation dialog class CConnectCAMInvitation : public CDialog { DECLARE_DYNAMIC(CConnectCAMInvitation) public: char remoteName[500]; char remoteAddress[500]; CDialog *pdlg; CConnectCAMInvitation(CWnd* pParent = NULL); // standard constructor virtual ~CConnectCAMInvitation(); afx_msg BOOL OnInitDialog(); afx_msg void OnConnectionAccept(); afx_msg void OnConnectionReject(); void SetParameter(char *hostname,char *hostaddress,CDialog *dlg) ; DECLARE_MESSAGE_MAP() // Dialog Data enum { IDD = IDD_DIALOG5 }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support }; #endif

88

ConnectCAMInvitation.cpp

#include "stdafx.h" #include "VideoOverLan.h" #include "ConnectCAMInvitation.h" #include "ChatBox.h" // CConnectCAMInvitation dialog IMPLEMENT_DYNAMIC(CConnectCAMInvitation, CDialog) CConnectCAMInvitation::CConnectCAMInvitation(CWnd* pParent /*=NULL*/) : CDialog(CConnectCAMInvitation::IDD, pParent) { } CConnectCAMInvitation::~CConnectCAMInvitation() { } void CConnectCAMInvitation::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CConnectCAMInvitation, CDialog) ON_BN_CLICKED(IDOK, OnConnectionAccept) ON_BN_CLICKED(IDCANCEL, OnConnectionReject) END_MESSAGE_MAP() // CConnectCAMInvitation message handlers BOOL CConnectCAMInvitation::OnInitDialog() { CDialog::OnInitDialog(); char str[600];

89

sprintf(str,"Invitation to View %s CAM",remoteName); this->SetDlgItemText(IDC_CAMINV,str); return TRUE; } void CConnectCAMInvitation::SetParameter(char *hostname,char *hostaddress,CDialog *dlg) { strcpy(remoteName,hostname); strcpy(remoteAddress,hostaddress); pdlg=dlg; } // When Accept button Pressed. void CConnectCAMInvitation::OnConnectionAccept() { this->OnCancel(); // Send notification to remote user ( ( CChatBox * ) pdlg )->controlMSGSocket.SendControlMessage ( CONTROLMESG_ACCEPTCAMINV , NULL ); // Start the Receiving of Video ( ( CChatBox * ) pdlg )->menu->EnableMenuItem ( REQ_CAM , MF_GRAYED ); ( ( CChatBox * ) pdlg )->ReceiveCAM = TRUE; ( ( CChatBox * ) pdlg )->StopGuestCAM = FALSE; } // When Connection is Rejected. void CConnectCAMInvitation::OnConnectionReject() { // Send notification to remote user ( ( CChatBox * ) pdlg )->controlMSGSocket.SendControlMessage ( CONTROLMESG_REJECTCAMINV , NULL ); CDialog::OnCancel(); }

90

ConnectCAMRequest.h #if !defined(AFX_CONNECTCAMREQUEST_H__5FB1D083_5F66_11D6_8897_000B2B0F84B6__INCLUDED_) #define AFX_CONNECTCAMREQUEST_H__5FB1D083_5F66_11D6_8897_000B2B0F84B6__INCLUDED_ #pragma once // CConnectCAMRequest dialog class CConnectCAMRequest : public CDialog { DECLARE_DYNAMIC(CConnectCAMRequest) public: char remoteName[500]; char remoteAddress[500]; CDialog *pdlg; CConnectCAMRequest(CWnd* pParent = NULL); // standard constructor virtual ~CConnectCAMRequest(); afx_msg BOOL OnInitDialog(); afx_msg void OnConnectionAccept(); afx_msg void OnConnectionReject(); void SetParameter(char *hostname,char *hostaddress,CDialog *dlg) ; DECLARE_MESSAGE_MAP() // Dialog Data enum { IDD = IDD_DIALOG4 }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support }; #endif

91

ConnectCAMRequest.cpp #include "stdafx.h" #include "VideoOverLan.h" #include "ConnectCAMRequest.h" #include "ChatBox.h" // CConnectCAMRequest dialog IMPLEMENT_DYNAMIC(CConnectCAMRequest, CDialog) CConnectCAMRequest::CConnectCAMRequest(CWnd* pParent /*=NULL*/) : CDialog(CConnectCAMRequest::IDD, pParent) { } CConnectCAMRequest::~CConnectCAMRequest() { } void CConnectCAMRequest::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CConnectCAMRequest, CDialog) ON_BN_CLICKED(IDOK, OnConnectionAccept) ON_BN_CLICKED(IDCANCEL, OnConnectionReject) END_MESSAGE_MAP() // CConnectCAMRequest message handlers BOOL CConnectCAMRequest::OnInitDialog() { CDialog::OnInitDialog();

92

char str[600]; sprintf(str,"Request to View Your CAM from user %s ",remoteName); this->SetDlgItemText(IDC_CAMREQ,str); return TRUE; } /** * Set remote user name and address */ void CConnectCAMRequest::SetParameter(char *hostname,char *hostaddress,CDialog *dlg) { strcpy(remoteName,hostname); strcpy(remoteAddress,hostaddress); pdlg=dlg; } void CConnectCAMRequest::OnConnectionAccept() { this->OnCancel(); // Send notification to remote user ((CChatBox*)pdlg)->controlMSGSocket.SendControlMessage(CONTROLMESG_ACCEPTCAMREQ,NULL); // Start the Sending of Video ((CChatBox*)pdlg)->menu->EnableMenuItem ( INVITE_CAM , MF_GRAYED ); ((CChatBox*)pdlg)->SendMyCAM = TRUE; } void CConnectCAMRequest::OnConnectionReject() { // Send notification to remote user ((CChatBox*)pdlg)->controlMSGSocket.SendControlMessage(CONTROLMESG_REJECTCAMREQ,NULL);

93

CDialog::OnCancel(); }

ConnectionRequestDlg.h #if !defined(AFX_CONNECTIONREQUESTDLG_H__5FB1D083_5F66_11D6_8897_000B2B0F84B6__INCLUDED_) #define AFX_CONNECTIONREQUESTDLG_H__5FB1D083_5F66_11D6_8897_000B2B0F84B6__INCLUDED_ class ConnectionRequestDlg : public CDialog { public: char rname[500]; char raddress[500]; CDialog *pdlg; ConnectionRequestDlg(CWnd* pParent = NULL); // standard constructor afx_msg BOOL OnInitDialog(); afx_msg void OnConnectionAccept(); afx_msg void OnConnectionReject(); void SetParameter(char *hostname,char *hostaddress,CDialog *dlg) ; DECLARE_MESSAGE_MAP() // Dialog Data enum { IDD = IDD_DIALOG3 }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support }; #endif

94

ConnectionRequestDlg.cpp #include "stdafx.h" #include "VideoOverLan.h" #include "ConnectionRequestDlg.h" #include "VideoOverLanDlg.h" #include "ChatBox.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ConnectionRequestDlg::ConnectionRequestDlg(CWnd* pParent /*=NULL*/) : CDialog(ConnectionRequestDlg::IDD, pParent) { } void ConnectionRequestDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(ConnectionRequestDlg, CDialog) ON_BN_CLICKED(IDOK, OnConnectionAccept) ON_BN_CLICKED(IDREJECT, OnConnectionReject) END_MESSAGE_MAP() BOOL ConnectionRequestDlg::OnInitDialog() { CDialog::OnInitDialog(); char str[600]; sprintf(str,"Connection request from user %s ",rname);

95

this->SetDlgItemText(IDC_MESG,str); return TRUE; } /** * Set remote user name and IP address */ void ConnectionRequestDlg::SetParameter(char *hostname,char *hostaddress,CDialog *dlg) { strcpy(rname,hostname); strcpy(raddress,hostaddress); pdlg=dlg; } // If User Accept the Connection. void ConnectionRequestDlg::OnConnectionAccept() { this->OnCancel(); // Send notification to remote user ((CChatBox*)pdlg)->controlMSGSocket.SendControlMessage(CONTROLMESG_ACCEPT,NULL); // Initialize the Connection ((CChatBox*)pdlg)->StartTextChat(); } // If user Reject the Request. void ConnectionRequestDlg::OnConnectionReject() { // Send notification to remote user ((CChatBox*)pdlg)->controlMSGSocket.SendControlMessage(CONTROLMESG_REJECT,NULL); CDialog::OnCancel(); }

96

REFERENCES

[1] Shepherd, George (1996). MFC Internals. Addison-Wesley.

[2] Heremiah Scholl, John D. McCarthy, Angela Sasse, Peter Parnes: Designing a

Large-Scale Video Chat Application.

http://portal.acm.org.proxy.lib.csus.edu/results.cfm?h=1&cfid=114120636&cftoken=

62364332

[3] Daly-Jones, O., Monk, A. & Watts, L. (1998). Some advantages of video

conferencing over high-quality audio conferencing: Fluency and awareness of

attentional focus, International Journal of Human Computer Studies, 49, 1 (1998), 21-

58.

[4] Nardi, B.A., Whittaker, S., Bradner, E., Interaction and outeraction: instant

messaging in action. In Proc. CSCW 2000, ACM Press (2000)

[5] MSDN Library http://msdn.microsoft.com/en-us/library/ms123401.aspx

[6] Visual C++ Libraries

http://msdn.microsoft.com/en-us/library/52cs05fz(VS.71).aspx

[7] Niranjan Babu Kalla. (2004, January), “What is the .NET Framework?” [Online],

Available: http://www.aspfree.com/c/a/.NET/What-is-the-NET-Framework/

[8] http://ondotnet.com/pub/a/dotnet/2002/11/18/everettcpp.html

[9] http://www.sockets.com/winsock2.htm#Architecture

97

[10] http://lists.freebsd.org/pipermail/freebsd-performance/2005-

February/001143.html

[11] http://www.cs.cf.ac.uk/Dave/C/node28.html

[12] http://software.intel.com/en-us/articles/use-the-microsoft-c-compiler-for-the-

pentium-m-processor/

[13] MFC Document/View architecture

http://www.sethi.org/classes/comp270/lab_notes/lab_11_mfc_doc_view_wizards.htm

l