#include <Carbon/Carbon.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <IOKit/IOReturn.h>
#include "DVFamily.h"
typedef struct DVFuncsStruct {
UInt32 (*fDVCountDevices)( void );
OSErr (*fDVGetIndDevice)( DVDeviceID * pDVDevice, UInt32 index );
OSErr (*fDVSetDeviceName)( DVDeviceID deviceID, char * str );
OSErr (*fDVGetDeviceName)( DVDeviceID deviceID, char * str );
OSErr (*fDVOpenDriver)( DVDeviceID deviceID, DVDeviceRefNum *pRefNum );
OSErr (*fDVCloseDriver)( DVDeviceRefNum refNum );
OSErr (*fDVDoAVCTransaction)( DVDeviceRefNum refNum, AVCTransactionParamsPtr pParams );
OSErr (*fDVIsEnabled)( DVDeviceRefNum refNum, Boolean *isEnabled);
OSErr (*fDVGetDeviceStandard)( DVDeviceRefNum refNum, UInt32 * pStandard );
OSErr (*fDVEnableRead)( DVDeviceRefNum refNum );
OSErr (*fDVDisableRead)( DVDeviceRefNum refNum );
OSErr (*fDVReadFrame)( DVDeviceRefNum refNum, Ptr *ppReadBuffer, UInt32 * pSize );
OSErr (*fDVReleaseFrame)( DVDeviceRefNum refNum, Ptr pReadBuffer );
OSErr (*fDVEnableWrite)( DVDeviceRefNum refNum );
OSErr (*fDVDisableWrite)( DVDeviceRefNum refNum );
OSErr (*fDVGetEmptyFrame)( DVDeviceRefNum refNum, Ptr *ppEmptyFrameBuffer, UInt32 * pSize );
OSErr (*fDVWriteFrame)( DVDeviceRefNum refNum, Ptr pWriteBuffer );
OSErr (*fDVSetWriteSignalMode)( DVDeviceRefNum refNum, UInt8 mode);
OSErr (*fDVNewNotification)( DVDeviceRefNum refNum, DVNotifyProc notifyProc,
void *userData, DVNotificationID *pNotifyID );
OSErr (*fDVNotifyMeWhen)( DVDeviceRefNum refNum, DVNotificationID notifyID, UInt32 events);
OSErr (*fDVCancelNotification)( DVDeviceRefNum refNum, DVNotificationID notifyID );
OSErr (*fDVDisposeNotification)( DVDeviceRefNum refNum, DVNotificationID notifyID );
} DVFuncs, *DVFuncsPtr;
static DVFuncs sDVFuncs;
static char *sFile = "/tmp/dump.dv";
static int sWrite = 0;
static int sLoop = 0;
static int sSDL;
static int sDVCPro;
static int sNotifyTest;
static CFBundleRef findMe()
{
CFURLRef bundleURL;
CFBundleRef myBundle;
Boolean didLoad = false;
bundleURL = CFURLCreateWithFileSystemPath(
kCFAllocatorDefault,
CFSTR("DVFamily.bundle"),
kCFURLPOSIXPathStyle,
true );
myBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
if(!myBundle) {
bundleURL = CFURLCreateWithFileSystemPath(
kCFAllocatorDefault,
CFSTR("/System/Library/Extensions/DVFamily.bundle"),
kCFURLPOSIXPathStyle,
true );
myBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
}
printf("Bundle: %p\n", myBundle);
didLoad = CFBundleLoadExecutable( myBundle );
printf("loaded? %d\n", didLoad);
sDVFuncs.fDVCountDevices = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVCountDevices") );
sDVFuncs.fDVGetIndDevice = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVGetIndDevice") );
sDVFuncs.fDVSetDeviceName = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVSetDeviceName") );
sDVFuncs.fDVGetDeviceName = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVGetDeviceName") );
sDVFuncs.fDVOpenDriver = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVOpenDriver") );
sDVFuncs.fDVCloseDriver = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVCloseDriver") );
sDVFuncs.fDVDoAVCTransaction = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVDoAVCTransaction") );
sDVFuncs.fDVIsEnabled = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVIsEnabled") );
sDVFuncs.fDVGetDeviceStandard = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVGetDeviceStandard") );
sDVFuncs.fDVEnableRead = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVEnableRead") );
sDVFuncs.fDVDisableRead = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVDisableRead") );
sDVFuncs.fDVReadFrame = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVReadFrame") );
sDVFuncs.fDVReleaseFrame = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVReleaseFrame") );
sDVFuncs.fDVEnableWrite = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVEnableWrite") );
sDVFuncs.fDVDisableWrite = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVDisableWrite") );
sDVFuncs.fDVGetEmptyFrame = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVGetEmptyFrame") );
sDVFuncs.fDVWriteFrame = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVWriteFrame") );
sDVFuncs.fDVSetWriteSignalMode = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVSetWriteSignalMode") );
sDVFuncs.fDVNewNotification = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVNewNotification") );
sDVFuncs.fDVNotifyMeWhen = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVNotifyMeWhen") );
sDVFuncs.fDVCancelNotification = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVCancelNotification") );
sDVFuncs.fDVDisposeNotification = CFBundleGetFunctionPointerForName(
myBundle, CFSTR("DVDisposeNotification") );
CFRelease( bundleURL );
return myBundle;
}
static OSErr doControlTest(DVDeviceRefNum refNum, UInt8 op1, UInt8 op2)
{
AVCTransactionParams avcParams;
char in[4], out[16];
OSErr err;
in[0] = kAVCControlCommand;
in[1] = 0x20; in[2] = op1;
in[3] = op2;
avcParams.commandBufferPtr = in;
avcParams.commandLength = sizeof(in);
avcParams.responseBufferPtr = out;
avcParams.responseBufferSize = sizeof(out);
avcParams.responseHandler = NULL;
err = sDVFuncs.fDVDoAVCTransaction(refNum, &avcParams );
if(err)
printf("Error %d calling DVDoAVCTransaction(%ld)\n", err, refNum);
return err;
}
static void readFrames(DVDeviceRefNum refNum, int file, int numFrames)
{
OSErr err, wait;
Ptr pReadBuffer;
UInt32 size;
int i;
err = sDVFuncs.fDVEnableRead(refNum);
for(i=0; i<numFrames; i++) {
wait = sDVFuncs.fDVReadFrame( refNum, &pReadBuffer, &size );
while(wait == -1) {
usleep(10000); wait = sDVFuncs.fDVReadFrame( refNum, &pReadBuffer, &size );
}
if(file)
write(file, pReadBuffer, size);
err = sDVFuncs.fDVReleaseFrame( refNum, pReadBuffer );
}
err = sDVFuncs.fDVDisableRead( refNum );
}
static void destructoRead(DVDeviceRefNum refNum)
{
OSErr err, wait;
Ptr pReadBuffer;
UInt32 size;
int i;
do {
err = sDVFuncs.fDVEnableRead(refNum);
for(i=0; i<100; i++) {
wait = sDVFuncs.fDVReadFrame( refNum, &pReadBuffer, &size );
while(wait == -1) {
wait = sDVFuncs.fDVReadFrame( refNum, &pReadBuffer, &size );
}
err = sDVFuncs.fDVReleaseFrame( refNum, pReadBuffer );
}
err = sDVFuncs.fDVDisableRead( refNum );
} while(1);
}
static void writeFrames(DVDeviceRefNum refNum, int file)
{
OSErr err, wait;
Ptr pReadBuffer;
UInt32 size, len;
err = sDVFuncs.fDVEnableWrite(refNum);
if(err)
return;
do {
wait = sDVFuncs.fDVGetEmptyFrame( refNum, &pReadBuffer, &size );
while(wait == -1) {
usleep(10000); wait = sDVFuncs.fDVGetEmptyFrame( refNum, &pReadBuffer, &size );
}
if(wait)
break;
if(file) {
len = read(file, pReadBuffer, size);
if(len < size) {
if(sLoop) {
int res;
res = lseek(file, 0, SEEK_SET);
printf("lseek res %d\n", res);
}
else
break;
}
}
err = sDVFuncs.fDVWriteFrame( refNum, pReadBuffer );
} while (1);
err = sDVFuncs.fDVDisableWrite( refNum );
}
static void destructoWrite(DVDeviceID device, DVDeviceRefNum refNum, int file)
{
OSErr err, wait;
Ptr pReadBuffer;
UInt32 size, len;
int i;
do {
err = sDVFuncs.fDVEnableWrite(refNum);
if(err) {
sleep(1);
continue;
}
for(i=0; i<100; i++) {
wait = sDVFuncs.fDVGetEmptyFrame( refNum, &pReadBuffer, &size );
while(wait == -1) {
usleep(10000); wait = sDVFuncs.fDVGetEmptyFrame( refNum, &pReadBuffer, &size );
}
if(file) {
len = read(file, pReadBuffer, size);
if(len < size) {
int res;
res = lseek(file, 0, SEEK_SET);
printf("lseek res %d\n", res);
}
}
err = sDVFuncs.fDVWriteFrame( refNum, pReadBuffer );
};
err = sDVFuncs.fDVDisableWrite( refNum );
#if 1
err = sDVFuncs.fDVCloseDriver(refNum );
err = sDVFuncs.fDVOpenDriver( device, &refNum );
if(err) {
if(err == (OSErr)kIOReturnExclusiveAccess) {
do {
sleep(1);
err = sDVFuncs.fDVOpenDriver( device, &refNum );
}
while (err == (OSErr)kIOReturnExclusiveAccess);
}
printf("Error %d calling DVOpenDriver(%ld)\n", err, device);
}
#endif
} while (err == noErr);
}
static OSStatus myNotifyProc(DVEventRecordPtr event, void *userData )
{
printf("event for device %d, event %d, userdata %p\n",
event->eventHeader.deviceID, event->eventHeader.theEvent, userData);
return noErr;
}
int main(int argc, char **argv)
{
CFBundleRef myBundle;
UInt32 numDevs, i;
UInt32 standard;
Boolean isEnabled;
OSErr err;
DVDeviceID device;
DVNotificationID notifyID;
char name[256];
int file;
int pos = 1;
int destruct = 0;
while(argc > pos) {
if(strcmp(argv[pos], "-w") == 0)
sWrite = 1;
else if(strcmp(argv[pos], "-r") == 0)
sWrite = 0;
else if(strcmp(argv[pos], "-d") == 0)
destruct = 1;
else if(strcmp(argv[pos], "-l") == 0)
sLoop = 1;
else if(strcmp(argv[pos], "-sdl") == 0)
sSDL = 1;
else if(strcmp(argv[pos], "-DVCPro") == 0)
sDVCPro = 1;
else if(strcmp(argv[pos], "-n") == 0)
sNotifyTest = 1;
else if(strcmp(argv[pos], "-h") == 0) {
printf("%s [-w/-r] [-l(oop)] [-d(estructoTest)] [-sdl/-DVCPro] [-n(otify test] [filename]\n", argv[0]);
exit(0);
}
else
sFile = argv[pos];
pos++;
}
myBundle = findMe();
printf("sLoop = %d\n", sLoop);
numDevs = sDVFuncs.fDVCountDevices();
printf("Number of devices: %ld\n", numDevs);
if(numDevs == 0) {
err = sDVFuncs.fDVNewNotification( kEveryDVDeviceRefNum, myNotifyProc,
0x1234, ¬ifyID );
if(err)
printf("Error %d calling DVNewNotification(, %ld)\n", err, kEveryDVDeviceRefNum);
err = sDVFuncs.fDVNotifyMeWhen( kEveryDVDeviceRefNum, notifyID,
kDVDeviceAdded | kDVDeviceRemoved);
if(err)
printf("Error %d calling NotifyMeWhen(%ld, %ld)\n", err, kEveryDVDeviceRefNum, notifyID);
while (numDevs == 0 || sNotifyTest) {
printf("Waiting for devices: %ld\n", numDevs);
usleep(1000000); numDevs = sDVFuncs.fDVCountDevices();
}
}
for(i=1; i<=numDevs; i++) {
DVDeviceRefNum refNum;
err = sDVFuncs.fDVGetIndDevice(&device, i);
if(err)
printf("Error %d calling DVGetIndDevice(, %ld)\n", err, i);
err = sDVFuncs.fDVGetDeviceName(device, name);
if(err)
printf("Error %d calling DVGetDeviceName(%ld)\n", err, device);
else
printf("Device %ld name is %s\n", device, name);
err = sDVFuncs.fDVOpenDriver( device, &refNum );
if(err) {
if(err == (OSErr)kIOReturnExclusiveAccess) {
do {
sleep(1);
err = sDVFuncs.fDVOpenDriver( device, &refNum );
}
while (err == (OSErr)kIOReturnExclusiveAccess);
}
printf("Error %d calling DVOpenDriver(%ld)\n", err, device);
}
err = sDVFuncs.fDVGetDeviceStandard(refNum, &standard);
if(err)
printf("Error %d calling DVGetDeviceStandard(%ld)\n", err, device);
else if(standard == kNTSCStandard)
printf("Device %ld video standard is NTSC\n", device);
else if(standard == kPALStandard)
printf("Device %ld video standard is PAL\n", device);
else
printf("Device %ld, unknown video standard %ld\n", device, standard);
err = sDVFuncs.fDVIsEnabled(refNum, &isEnabled);
if(err)
printf("Error %d calling DVIsEnabled(%ld)\n", err, device);
else
printf("Device %ld isEnabled: %d\n", device, isEnabled);
if(sWrite) {
if(sSDL) {
err = sDVFuncs.fDVSetWriteSignalMode(refNum, kAVCSignalModeSDL525_60);
}
file = open(sFile, O_RDONLY, 0666);
printf("opened file, %d\n", file);
if(destruct)
destructoWrite(device, refNum, file);
else
writeFrames(refNum, file);
}
else {
file = open(sFile, O_CREAT | O_WRONLY | O_TRUNC, 0666);
err = doControlTest(refNum, kAVCPlayOpcode, kAVCPlayForward);
if(destruct)
destructoRead(refNum);
else
readFrames(refNum, file, 300);
err = doControlTest(refNum, kAVCWindOpcode, kAVCWindStop);
err = sDVFuncs.fDVCloseDriver( refNum );
if(err)
printf("Error %d calling DVCloseDriver(%ld)\n", err, device);
while(sLoop) {
readFrames(refNum, 0, 300);
}
}
err = sDVFuncs.fDVCloseDriver(refNum );
}
sleep(10);
return 0;
}