home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
videotlk.zip
/
SAMPLES
/
DIVEOLD
/
DIVELIB.C
< prev
next >
Wrap
Text File
|
1998-12-24
|
19KB
|
532 lines
// #define DEBUG
#define VCAI_ENABLED
#define DIVE_ENABLED
#define VCAI_MONITOR
#define INCL_DOS
#define INCL_DOSERRORS
#define INCL_GPI
#define INCL_WIN
#define INCL_32
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _MEERROR_H_
#include <mmioos2.h> /* It is from MMPM toolkit */
#include <dive.h>
#include <fourcc.h>
#include <vcadd.h>
#include <vcai.h>
#include "dive.h"
#include "pmtv2rem.h"
#define WIDTH (300)
#define HEIGHT (240)
HWND HwndNBFrame; // Notebook frame handle
BOOL NotebookOpen = FALSE; // Notebook not open
void remote_open (MOUSEPOS mousepos);
PWINDATA DiveSetup (char *name, USHORT instance, USHORT connector);
int DiveRegister (HAB hab);
int DiveStop (void);
static void msg_box (UCHAR *txt, UCHAR *title, ULONG options);
static WINDATA WTV_data;
static DIVE_CAPS DiveCaps = {0}; // DIVE capabilities of system
static FOURCC fccFormats[100] = {0}; // Color format code
static SETUP_BLITTER SetupBlitter; // structure for blitter ops.
/* This function will display a TV in the window using DIVE. The basic *
* theory is that the WinCast board will be continually capturing into the *
* buffer and DIVE will blit the image onto the screen. The blitter is *
* setup in the main thread of the program where window details are known. */
VOID APIENTRY DiveTV (ULONG data_addr)
{
PWINDATA win_data = NULL; /* Structure holding window information */
UCHAR *tv_image = NULL; /* Capture buffer for TV image */
size_t tv_size = 0; /* Size of capture buffer */
ULONG rc = 0; /* DIVE error return code */
ULONG dive_srcbuf_no = 0; /* DIVE source buffer number */
ULONG line_len = 0;
ULONG scanline_bytes = 0;
ULONG scanlines = 0;
PBYTE dive_buf_addr = 0;
RECTL dive_rect;
/* Set the window information and check it's valid. */
if ((win_data = (PWINDATA)data_addr) == NULL)
{
DosExit (EXIT_PROCESS, 1);
return;
}
/* Wait until we are permitted to proceed */
while (win_data->win_blit_halt)
DosSleep (100);
/* Allocate a capture buffer for the image and declare it to DIVE */
tv_size = (size_t)(win_data->win_dive_width * win_data->win_dive_height * 4);
rc = DosAllocMem ((PPVOID)&tv_image, tv_size, (PAG_COMMIT | PAG_WRITE));
if (rc != NO_ERROR)
{
DosExit (EXIT_PROCESS, 1);
return;
}
#ifdef DIVE_ENABLED
line_len = (win_data->win_dive_width << 1);
line_len = (line_len - (line_len % 4));
rc = DiveAllocImageBuffer (win_data->win_dive_handle,
&dive_srcbuf_no, FOURCC_Y422,
win_data->win_dive_width,
win_data->win_dive_height,
0, // DIVE sets line len
(PBYTE)tv_image);
if (rc)
{
DosExit (EXIT_PROCESS, 1);
return;
}
dive_rect.xLeft = 0;
dive_rect.yTop = 0;
dive_rect.xRight = win_data->win_dive_width;
dive_rect.yBottom = win_data->win_dive_height;
#endif
#ifdef VCAI_ENABLED
// Connect to the capture board and start the capture.
VcaiVideoRectValidate (0, 0,
win_data->win_dive_width, win_data->win_dive_height,
0, 0,
win_data->win_dive_width, win_data->win_dive_height);
#ifdef VCAI_MONITOR
VcaiWCastMonitor (win_data->win_dive_width, win_data->win_dive_height,
(ULONG)tv_image);
// VcaiVideoRectValidate (0, 0,
// win_data->win_dive_width, win_data->win_dive_height,
// 0, 0,
// win_data->win_dive_width, win_data->win_dive_height);
VcaiOverlay (TRUE);
#endif
#endif
win_data->win_bliting = TRUE;
while (!win_data->win_blit_halt)
{
#ifdef DIVE_ENABLED
DosSleep (30);
/* Blit the image to the screen. There may be a need for the DIVE *
* buffer (dive_srcbuf_no) to be DiveBeginImageBufferAccess'ed *
* before the blit is made. */
DiveBlitImage (win_data->win_dive_handle,
dive_srcbuf_no, DIVE_BUFFER_SCREEN);
#endif
}
#ifdef VCAI_ENABLED
#ifdef VCAI_MONITOR
VcaiOverlay (FALSE);
// This call will stop displaying the image and free the memory that is
// stuck in the PC RAM
VcaiWCastMonitor (0, 0, 0L);
#endif
VcaiVideoInputSet (4);
VcaiDeviceClose (win_data->win_vcai_handle);
#endif
/* Free any buffers and undeclare any of the DIVE buffers used */
#ifdef DIVE_ENABLED
DiveFreeImageBuffer (win_data->win_dive_handle, dive_srcbuf_no);
#endif
DosFreeMem (tv_image);
/* Inform the main thread that all has finished okay. */
win_data->win_bliting = FALSE;
}
MRESULT EXPENTRY TVWindowProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
static PWINDATA win_data = NULL; /* Pointer to window data */
HPS hps; /* Presentation Space handle */
HRGN hrgn; /* Region handle */
RGNRECT rgnCtl; /* Processing control structure */
RECTL rcl; /* Current widow rectangle */
POINTL pointl; /* Point to offset from Desktop */
ULONG rc;
ULONG width; /* Width of the current rectangle */
MOUSEPOS mousepos; /* Position of mouse in window */
/* Get the pointer to window data */
if (win_data == NULL)
{
if ((win_data = (PWINDATA)WinQueryWindowULong (hwnd, 0)) == NULL)
return WinDefWindowProc (hwnd, msg, mp1, mp2);
}
/* Handle messages to this window */
switch (msg)
{
case WM_COMMAND:
switch (SHORT1FROMMP (mp1))
{
case ID_FILE_EXIT:
win_data->win_blit_halt = TRUE;
DiveSetupBlitter (win_data->win_dive_handle, 0);
WinPostMsg (hwnd, WM_QUIT, 0L, 0L);
break;
case ID_TV_SETUP:
if (NotebookOpen)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
(PSZ)"Settings notebook already open",
(PSZ)WTV_NAME, 0, MB_OK | MB_INFORMATION);
break;
}
HwndNBFrame = WinLoadSecondaryWindow (HWND_DESKTOP, HWND_DESKTOP,
(PFNWP)NotebookDlgProc,
(HMODULE)NULLHANDLE,
IDD_NOTE,
NULL);
break;
case ID_TV_CON1:
case ID_TV_CON2:
case ID_TV_RF:
case ID_TV_SVHS:
case ID_TV_TEST:
if (win_data->win_vcai_handle == 0)
{
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
(PSZ)"Connector not initialised",
(PSZ)WTV_NAME, 0, MB_OK | MB_INFORMATION);
break;
}
#ifdef VCAI_ENABLED
/* Now, alter the connector to the appropriate one */
VcaiVideoInputSet (SHORT1FROMMP(mp1)-BASE_CONNECTOR);
#endif
break;
default:
/* Let PM handle this message. */
return WinDefWindowProc (hwnd, msg, mp1, mp2);
}
break;
case WM_BUTTON1CLICK :
WinQueryWindowRect (hwnd, &rcl);
WinMapWindowPoints (hwnd, HWND_DESKTOP, (PPOINTL)&rcl, 2);
mousepos.mp_x = MOUSEMSG (&msg)->x + rcl.xLeft;
mousepos.mp_y = MOUSEMSG (&msg)->y + rcl.yBottom;
remote_open (mousepos);
break;
case WM_VRNDISABLED:
#ifdef DIVE_ENABLED
/* Stop the blitter */
DiveSetupBlitter (win_data->win_dive_handle, 0);
#endif
break;
case WM_VRNENABLED:
if ((hps = WinGetPS (hwnd)) == 0)
break;
if ((hrgn = GpiCreateRegion (hps, 0L, NULL)) == RGN_ERROR)
{
WinReleasePS( hps );
break;
}
/* NOTE: If mp1 is zero, then this was just a move message. *
* Illustrate the visible region on a WM_VRNENABLE. */
WinQueryVisibleRegion (hwnd, hrgn);
rgnCtl.ircStart = 0;
rgnCtl.crc = 50;
rgnCtl.ulDirection = RECTDIR_LFRT_TOPBOT;
/* Get the all ORed rectangles */
rc = (ULONG)GpiQueryRegionRects (hps, hrgn, NULL,
&rgnCtl, win_data->win_rcls);
if (rc == FALSE)
{
#ifdef DIVE_ENABLED
/* Reset the blitter and close */
DiveSetupBlitter (win_data->win_dive_handle, 0);
#endif
GpiDestroyRegion (hps, hrgn);
WinReleasePS (hps);
break;
}
win_data->win_rcl_cnt = rgnCtl.crcReturned;
/* Now find the window position and size, relative 2 parent *
* Convert the point to offset from desktop lower left. */
WinQueryWindowPos (win_data->win_hwnd_client, &win_data->win_swp);
pointl.x = win_data->win_swp.x;
pointl.y = win_data->win_swp.y;
WinMapWindowPoints (win_data->win_hwnd_frame,
HWND_DESKTOP, &pointl, 1);
/* Tell DIVE about the new settings. */
SetupBlitter.lScreenPosX = pointl.x;
SetupBlitter.lScreenPosY = pointl.y;
SetupBlitter.ulDstWidth = win_data->win_swp.cx;
SetupBlitter.ulDstHeight = win_data->win_swp.cy;
SetupBlitter.ulNumDstRects = win_data->win_rcl_cnt;
SetupBlitter.pVisDstRects = win_data->win_rcls;
#ifdef DIVE_ENABLED
DiveSetupBlitter (win_data->win_dive_handle, &SetupBlitter);
#endif
win_data->win_blit_halt = FALSE;
GpiDestroyRegion (hps, hrgn);
WinReleasePS (hps);
break;
case WM_REALIZEPALETTE:
#ifdef DIVE_ENABLED
/* This tells DIVE that the physical palette may have changed. */
DiveSetDestinationPalette (win_data->win_dive_handle, 0, 0, 0);
#endif
break;
case WM_CLOSE:
/* Post to quit the dispatch message loop. */
win_data->win_blit_halt = TRUE;
DiveSetupBlitter (win_data->win_dive_handle, 0);
WinPostMsg (hwnd, WM_QUIT, 0L, 0L);
break;
default:
/* Let PM handle this message. */
return WinDefWindowProc (hwnd, msg, mp1, mp2);
}
return ( FALSE );
}
PWINDATA DiveSetup (char *name, USHORT instance, USHORT connector)
{
DRIVERHANDLE vhandle;
char txt[400];
WTV_data.win_vcai_connector = connector;
strcpy (WTV_data.win_vcai_name, name);
WTV_data.win_vcai_no = instance;
vhandle = VcaiDeviceOpen (name, instance);
if (vhandle <= 0)
{
sprintf (txt, "Cannot Open Device %s %u !", name, instance);
WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
txt,
(PSZ)WTV_NAME,
0, MB_OK | MB_INFORMATION);
return FALSE;
}
WTV_data.win_vcai_handle = vhandle;
VcaiDeviceConnect (vhandle);
VcaiVideoInputSet (connector);
#ifdef DIVE_ENABLED
// Get the DIVE capabilities and if the system is 16 coloured then exit
DiveCaps.pFormatData = fccFormats;
DiveCaps.ulFormatLength = 120;
DiveCaps.ulStructLen = sizeof (DIVE_CAPS);
if (DiveQueryCaps (&DiveCaps, DIVE_BUFFER_SCREEN))
{
msg_box ("Unable to query the Dive environment",
"Error", MB_OK | MB_ERROR);
return FALSE;
}
if (DiveCaps.ulDepth < 8)
{
msg_box ("Unable to execute in a 16-colour environment",
"Error", MB_OK | MB_ERROR);
return FALSE;
}
// Calculate the bytes per pixel
WTV_data.win_sizebytes = DiveCaps.ulScanLineBytes /
DiveCaps.ulHorizontalResolution;
// Open the DIVE device and the VCAI capture device
if (DiveOpen (&(WTV_data.win_dive_handle), FALSE, 0))
{
msg_box ("Unable to open the DIVE device",
"Error", MB_OK | MB_ERROR);
return FALSE;
}
#endif
// Set the window size
WTV_data.win_width = WIDTH; // 640 400
WTV_data.win_height = HEIGHT; // 320 300
#if 0
WTV_data.win_dive_width = WTV_data.win_width - 4;
WTV_data.win_dive_height = (3 * WTV_data.win_height) >> 2;
#else
WTV_data.win_dive_width = WIDTH; // 636
WTV_data.win_dive_height = HEIGHT; // 320
#endif
return &WTV_data;
}
int DiveRegister (HAB hab)
{
ULONG flCreate; // Window creation control flags
ULONG rc;
// Register a window class, and create a standard window.
WinRegisterClass (hab, (PSZ)"WTVWindow", TVWindowProc, 0, sizeof (ULONG));
flCreate = FCF_TASKLIST | FCF_SYSMENU |
FCF_TITLEBAR | FCF_ICON |
FCF_SIZEBORDER | FCF_MINMAX | FCF_MENU | FCF_SHELLPOSITION;
// Window
WTV_data.win_hwnd_frame = WinCreateStdWindow (HWND_DESKTOP,
WS_VISIBLE, &flCreate,
(PSZ)"WTVWindow",
(PSZ)"DIVE Window",
WS_SYNCPAINT | WS_VISIBLE,
0, ID_MAINWND,
&(WTV_data.win_hwnd_client));
WinSetWindowULong (WTV_data.win_hwnd_client, 0, (ULONG)&WTV_data);
// Query some information about the window, i.e. size and position
WTV_data.win_cxWidthBorder =
(LONG)WinQuerySysValue (HWND_DESKTOP, SV_CXSIZEBORDER);
WTV_data.win_cyWidthBorder =
(LONG)WinQuerySysValue (HWND_DESKTOP, SV_CYSIZEBORDER);
WTV_data.win_cyTitleBar =
(LONG)WinQuerySysValue (HWND_DESKTOP, SV_CYTITLEBAR);
WTV_data.win_cyMenu =
(LONG)WinQuerySysValue (HWND_DESKTOP, SV_CYMENU);
// WTV_data.win_cxWidthWindow = (WTV_data.win_width / 2) +
WTV_data.win_cxWidthWindow = WTV_data.win_width +
(WTV_data.win_cxWidthBorder * 2);
WTV_data.win_cyHeightWindow = (WTV_data.win_cyWidthBorder * 2) +
WTV_data.win_cyTitleBar +
WTV_data.win_cyMenu +
WTV_data.win_height;
WTV_data.win_cxWindowPos =
((LONG)WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN)
- WTV_data.win_cxWidthWindow ) / 2;
WTV_data.win_cyWindowPos =
((LONG)WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN)
- WTV_data.win_cyHeightWindow ) / 2;
// Set the window position and size.
WinSetWindowPos (WTV_data.win_hwnd_frame, HWND_TOP,
WTV_data.win_cxWindowPos, WTV_data.win_cyWindowPos,
WTV_data.win_cxWidthWindow, WTV_data.win_cyHeightWindow,
SWP_SIZE | SWP_MOVE | SWP_SHOW | SWP_ACTIVATE);
// Turn on visible region notification.
WinSetVisibleRegionNotify (WTV_data.win_hwnd_client, TRUE);
// Send an invlaidation message to the client.
SetupBlitter.ulStructLen = sizeof (SETUP_BLITTER);
SetupBlitter.fccSrcColorFormat = FOURCC_Y422;
// SetupBlitter.ulSrcWidth = (WTV_data.win_dive_width / 2);
SetupBlitter.ulSrcWidth = WTV_data.win_dive_width;
SetupBlitter.ulSrcHeight = WTV_data.win_dive_height;
SetupBlitter.ulSrcPosX = 0;
SetupBlitter.ulSrcPosY = 0;
SetupBlitter.ulDitherType = 1; // Dither please!
SetupBlitter.fInvert = FALSE;
SetupBlitter.lDstPosX = 0;
SetupBlitter.lDstPosY = 0;
SetupBlitter.fccDstColorFormat = FOURCC_SCRN;
WinPostMsg (WTV_data.win_hwnd_frame, WM_VRNENABLED, 0L, 0L);
// Start up the blitting thread.
WTV_data.win_bliting = FALSE;
WTV_data.win_blit_halt = TRUE;
rc = DosCreateThread (&(WTV_data.win_blit_tid),
(PFNTHREAD)DiveTV,
(ULONG)&WTV_data, 0L, 8192L);
if (rc)
{
WinSetVisibleRegionNotify (WTV_data.win_hwnd_client, FALSE);
#ifdef DIVE_ENABLED
DiveClose (WTV_data.win_dive_handle);
#endif
WinDestroyWindow (WTV_data.win_hwnd_frame);
return FALSE;
}
// Set the proiroty of the blitting thread
DosSetPriority (PRTYS_THREAD, PRTYC_IDLETIME, 0, WTV_data.win_blit_tid);
WTV_data.win_blit_halt = FALSE;
return TRUE;
}
int DiveStop ()
{
#ifdef DIVE_ENABLED
// Set the variable to end the running thread, and wait for it to end.
WTV_data.win_blit_halt = TRUE;
DosWaitThread (&(WTV_data.win_blit_tid), DCWW_WAIT);
#endif
#ifdef DEBUG
msg_box ("DiveTV thread has been closed okay",
"Info", MB_OK | MB_INFORMATION);
#endif
// Turn off visible region notificationm tidy up, and terminate DIVE
WinSetVisibleRegionNotify (WTV_data.win_hwnd_client, FALSE);
#ifdef DIVE_ENABLED
DiveClose (WTV_data.win_dive_handle);
#endif
// Process for termination
WinDestroyWindow (WTV_data.win_hwnd_frame);
return TRUE;
}
static void msg_box (UCHAR *txt, UCHAR *title, ULONG options)
{
WinMessageBox (HWND_DESKTOP,
HWND_DESKTOP,
txt,
title,
0,
options);
}