IsochComponentsRef [plain text]
Copyright 2001 Apple Computer, Inc. All Rights Reserved.
ISOCHRONOUS COMPONENTS REFERENCE v1.0 3/16/2001
(INITIAL DOCUMENTATION - SUBJECT TO CHANGE)
Header Files: IsochronousDataHandler.h, DeviceControl.h
Framework: DVComponentGlue
Component Types for Isoch Components
------------------------------------
#define kIDHComponentType 'ihlr' /* Component type*/
#define kIDHSubtypeDV 'dv ' /* Subtype for DV (over FireWire)*/
Data Types for Isoch Components
-------------------------------
The callback function prototype:
typedef OSStatus (*IDHNotificationProc)(IDHGenericEvent *event, void *userData);
FieldDecriptions:
event - a IDHGenericEvent that is returned from the Isoch component. If this is an IDHRead() or
IDHWrite() notification function, then 'event' is the address of the IDHParameterBlock
that was passed to the IDHRead()/IDHWrite() call.
userData - If this is an IDHRead() or IDHWrite() notification function, the userData returned will
be the 'refCon' field of the IDHParameterBlock. Otherwise, it will be the value specified
in the IDHNewNotification() function.
The parameter block passed to IDHRead() and IDHWrite():
struct IDHParameterBlock {
UInt32 reserved1; /* reserved by Apple */
UInt16 reserved2; /* reserved by Apple */
void * buffer; /* buffer used in read/write operation */
ByteCount requestedCount; /* bytes required to read/write */
ByteCount actualCount; /* actual bytes read/written */
IDHNotificationProc completionProc; /* called after read/write complete */
void * refCon; /* user specified data */
OSErr result; /* result of read/write */
};
Field Descriptions
reserved1, reserved2 - reserved by Apple
buffer - can contain an address of a user supplied buffer or 'nil'.
In reads: if 'buffer' is supplied, the data is read into the buffer
if 'buffer' is 'nil', a buffer address is returned in the completion proc
and the client has control of the buffer until it is released by
the IDHReleaseBuffer() function. NOTE: The buffer will remain valid for
an indeterminate amount of time. The client should USE the buffer ASAP to
guarantee data integrity
In writes: If 'buffer' is supplied, the data from the buffer is written to the
isoch device.
If 'buffer' is 'nil', a buffer address is supplied to the client on
callback. The client then writes his data into the buffer and returns
control to the IDH component. The data is then written to the device.
requestedCount - contains the number of bytes requested to read or write.
actualCount - the actual number of bytes read or written from/to the device.
completionProc - the routine that is called after read or write completion. If the completionProc
parameter is set to 'nil', the function becomes synchronous and does not return
until the read/write is complete. It is NOT possible to have a synchronous write/ 'nil'
buffer operation.
refCon - user data that is returned to the completion proc.
result - result of IDHRead()/IDHWrite() operation.
Error Codes (see functions for actual meanings)
-----------------------------------------------
#define kIDHErrDeviceDisconnected -14101
#define kIDHErrInvalidDeviceID -14102
#define kIDHErrDeviceInUse -14104
#define kIDHErrDeviceNotOpened -14105
#define kIDHErrDeviceReadError -14107
#define kIDHErrDeviceWriteError -14108
#define kIDHErrDeviceNotConfigured -14109
#define kIDHErrDeviceList -14110
#define kIDHErrCompletionPending -14111
#define kIDHErrDeviceTimeout -14112
#define kIDHErrInvalidIndex -14113
#define kIDHErrDeviceCantRead -14114
#define kIDHErrDeviceCantWrite -14115
Isochronous Component Atoms
---------------------------
#define kIDHDeviceAtomType 'devc' /* QTAtom - contains the description for a device */
#define kIDHDeviceIDType 'dvid' /* UInt32 - contains the device ID referenced in notification events */
#define kIDHIsochServiceAtomType 'isoc' /* QTAtom - contains the isoch configs for a device */
#define kIDHIsochModeAtomType 'mode' /* QTAtom - contains isoch configuration atoms */
#define kIDHIsochVersionAtomType 'iver' /* UInt32 - contains the version of the isoch component */
#define kIDHUseCMPAtomType 'ucmp' /* UInt32 - true when using CMP */
#define kIDHUniqueIDType 'unid' /* variable size - contains a unique ID associated with device */
#define kIDHNameAtomType 'name' /* Str255 - contains the name of the device */
#define kIDHIsochMediaType 'av ' /* OSType - kIDHSoundMediaAtomType or kIDHVideoMediaAtomType */
#define kIDHDataTypeAtomType 'dtyp' /* OSType - a configuration identifier */
#define kIDHDefaultIOType 'dfio' /* UInt32 - set for default read or write config */
#define kIDHDataSizeAtomType 'dsiz' /* UInt32 - the size of a frame of data */
#define kIDHDataBufferSizeAtomType 'dbuf' /* UInt32 - the size of a packet of data*/
#define kIDHDataIntervalAtomType 'intv' /* float - frame rate i.e. 29.97fps */
#define kIDHDataIODirectionAtomType 'ddir' /* long - I/O direction associated with the device
kIDHDataTypeIsInput is 1
kIDHDataTypeIsOutput is 2
kIDHDataTypeIsInputAndOutput is 4 */
#define kIDHSoundChannelCountAtomType 'ccnt' /* long - number of audio channels */
#define kIDHSoundSampleSizeAtomType 'ssiz' /* long - number of bytes per sample of audio */
#define kIDHSoundSampleRateAtomType 'srat' /* Fixed - audio sample rate */
#define kIDHVideoDimensionsAtomType 'dimn' /* IDHDimension - pixel dimension of video */
#define kIDHVideoResolutionAtomType 'resl' /* IDHResolution - DPI resolution */
#define kIDHVideoRefreshRateAtomType 'refr' /* Fixed - video refresh rate */
#define kIDHVideoPixelTypeAtomType 'pixl' /* OSType - Quicktime pixel type */
#define kIDHVideoDecompressorTypeAtomType 'dety' /* OSType - Quicktime decompressor type */
#define kIDHVideoDecompressorComponentAtomType 'cmpt' /* Component - Quicktime decompressor */
Atom Layout
-----------
deviceList - QTAtomContainer
kIDHIsochVersionAtomType (r)
kIDHUseCMPAtomType (r/w)
kIDHDeviceAtomType (r)
kIDHDeviceIDType (r)
kIDHUniqueIDType (r)
kIDHNameAtomType (r/w)
kIDHDefaultIOType (r/w)
kIDHIsochServiceAtomType (r)
kIDHIsochModeAtomType (r)
kIDHDataTypeAtomType (r)
kIDHDataSizeAtomType (r)
kIDHDataBufferSizeAtomType (r)
kIDHDataBufferSizeAtomType (r)
kIDHDataIntervalAtomType (r)
kIDHDataIODirectionAtomType (r)
kIDHSoundChannelCountAtomType (r)
kIDHSoundSampleSizeAtomType (r)
kIDHSoundSampleRateAtomType (r)
kIDHIsochModeAtomType (r)
kIDHDataTypeAtomType (r)
kIDHDataSizeAtomType (r)
kIDHDataBufferSizeAtomType (r)
kIDHDataBufferSizeAtomType (r)
kIDHDataIntervalAtomType (r)
kIDHDataIODirectionAtomType (r)
kIDHVideoDimensionsAtomType (r)
kIDHVideoResolutionAtomType (r)
kIDHVideoRefreshRateAtomType (r)
kIDHVideoPixelTypeAtomType (r)
kIDHVideoDecompressorTypeAtomType (r)
kIDHVideoDecompressorComponentAtomType (r)
kIDHDeviceAtomType
...
Note: (r) - read only, (r/w) - read/write
Device Status Structure
struct IDHDeviceStatus {
UInt32 version; /* version of structure */
Boolean physicallyConnected; /* device is connected and active */
Boolean readEnabled; /* device has been enabled for read */
Boolean writeEnabled; /* device has been enabled for writing */
Boolean exclusiveAccess; /* a client has opened device for exclusive access */
UInt32 currentBandwidth; /* ??? */
UInt32 currentChannel; /* ??? */
PsuedoID localNodeID; /* the ID associated with this device */
SInt16 inputStandard; /* ntscIn is 0 or palIn is 1 */
Boolean deviceActive; /* device is being used by another client */
};
Notification Structures
struct IDHEventHeader {
IDHDeviceID deviceID; /* a unique device ID */
IDHNotificationID notificationID; /* notification ID associated this callback */
IDHEvent event; /* The event */
};
struct IDHGenericEvent {
IDHEventHeader eventHeader; /* as described above */
UInt32 pad[4];
};
struct IDHDeviceConnectionEvent {
IDHEventHeader eventHeader;
};
struct IDHDeviceIOEnableEvent {
IDHEventHeader eventHeader;
};
Notification Events
#define kIDHEventInvalid 0,
#define kIDHEventDeviceAdded 1L << 0 /* Uses IDHDeviceConnectionEvent*/
#define kIDHEventDeviceRemoved 1L << 1 /* Uses IDHDeviceConnectionEvent*/
#define kIDHEventDeviceChanged 1L << 2 /* Uses ????*/
#define kIDHEventReadEnabled 1L << 3 /* Uses IDHDeviceIOEnableEvent*/
#define kIDHEventReserved1 1L << 4 /* Reserved for future use*/
#define kIDHEventReadDisabled 1L << 5 /* Uses IDHDeviceIOEnableEvent*/
#define kIDHEventWriteEnabled 1L << 6 /* Uses IDHDeviceIOEnableEvent*/
#define kIDHEventReserved2 1L << 7 /* Reserved for future use*/
#define kIDHEventWriteDisabled 1L << 8 /* Uses IDHDeviceIOEnableEvent*/
#define kIDHEventEveryEvent (long)0xFFFFFFFF
Isochronous Component Functions
===============================
Getting device information and choosing a device
IDHGetDeviceList
----------------
The IDHGetDeviceList function returns an atom list of the devices that are currently active.
pascal ComponentResult IDHGetDeviceList( ComponentInstance idh, QTAtomContainer *deviceList)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
deviceList - An atom container that describes each of the devices that support this isoch component.
The atom structure is defined above. The user must free this atom container using
QTRemoveChildren() and QTDisposeAtomContainer() when finished.
Result Codes:
Quicktime error codes
IDHUpdateDeviceList
-------------------
The IDHUpdateDeviceList function allows the client to change certain atoms within the internal atom list.
pascal ComponentResult IDHUpdateDeviceList( ComponentInstance idh, QTAtomContainer *deviceList)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
deviceList - An atom container that was returned from IDHGetDeviceList(). The client has modified one
or more atoms identified as (r/w).
Result Codes:
kIDHErrDeviceList The device list is either stale or corrupt. Please IDHGetDeviceList().
Quicktime error codes
IDHSetDeviceConfiguration
-------------------------
The IDHSetDeviceConfiguration function allows the user to choose a specific configuration of a device
for reads or writes. The configuration structure is defined in the atom description above.
pascal ComponentResult IDHSetDeviceConfiguration( ComponentInstance idh, const QTAtomSpec *configurationID)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
configurationID - Specifies the requested configuration. The user passes an QTAtomSpec which is
an atom container/ kIDHIsochModeAtomType atom pair. NOTE: The user must NOT dispose
of the device list (requested by IDHGetDeviceList()) until he is through with this
configuration.
Result Codes:
kIDHErrDeviceInUse Another device has already been opened. Please IDHCloseDevice().
kIDHErrDeviceList The device list is either stale or corrupt. Please IDHGetDeviceList().
kIDHErrInvalidDeviceID Internal Error
kAlreadyEnabledErr Device control has already been enabled on this device
kNotEnabledErr Device control is not enabled
IDHGetDeviceConfiguration
-------------------------
The IDHGetDeviceConfiguration function returns the configuration that the client set using the
IDHSetDeviceConfiguration() call.
pascal ComponentResult IDHGetDeviceConfiguration( ComponentInstance idh, QTAtomSpec *configurationID)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
configurationID - Contains the previously specified configuration. The function returns an QTAtomSpec
which is an atom container/ kIDHIsochModeAtomType atom pair. NOTE: The user must NOT
dispose the device list (requested by IDHGetDeviceList()) until he is through with this
configuration.
Result Codes:
kIDHErrDeviceNotConfigured A device has not already been selected using IDHSetDeviceConfiguration()
Opening and closing a device
IDHOpenDevice
-------------
The IDHOpenDevice function opens the currently configured device.
pascal ComponentResult IDHOpenDevice( ComponentInstance idh, UInt32 permissions)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
permissions - The user specifies a combination of the following flags when opening a device.
kIDHOpenForReadTransactions - Indicates that the device will be opened for reads. The value of
this flag is 1. One or more clients can open a device for reads unless a client specifies
the kIDHOpenWithExclusiveAccess flag.
kIDHOpenForWriteTransactions - Indicates that the device will be opened for writes. The value of
this flag is 0x2. Note: Only one client can open a device for writes.
kIDHOpenWithExclusiveAccess - Indicates that the device cannot be opened by another client. The
value of this flag is 0x4.
Result Codes:
kIDHErrDeviceNotConfigured A device has not already been selected using IDHSetDeviceConfiguration()
kIDHErrInvalidDeviceID Internal Error
kIDHErrDeviceInUse Device has been exclusively opened by another client. Or it has already been
in another state.
kIDHErrInvalidIndex Internal Error
IDHCloseDevice
--------------
The IDHCloseDevice function closes the previously opened IDH device.
pascal ComponentResult IDHCloseDevice( ComponentInstance idh)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
Result Codes:
kIDHErrDeviceNotConfigured A device has not already been selected using IDHSetDeviceConfiguration()
kIDHErrInvalidDeviceID Internal Error
kIDHErrDeviceNotOpened A device has not been opened
Device I/O
IDHRead
-------
The IDHRead function reads data from the currently opened device configuration.
pascal ComponentResult IDHRead( ComponentInstance idh, IDHParameterBlock *pb)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
pb - Specifies the address of a IDHParameterBlock structure. Each of the fields are described in detail
in a previous section. The user should keep the IDHParameterBlock around until the completion routine
is called. NOTE: On a 'nil' buffer read, the buffer will remain valid for an indeterminate
amount of time. The client should USE the buffer ASAP to guarantee data integrity.
Result Codes:
kIDHErrDeviceNotConfigured A device has not already been selected using IDHSetDeviceConfiguration()
kIDHErrInvalidDeviceID Internal Error
kIDHErrDeviceTimeout Timeout on synchronous read
IDHWrite
--------
The IDHWrite function writes data to the currently opened device configuration.
pascal ComponentResult IDHWrite( ComponentInstance idh, IDHParameterBlock *pb)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
pb - Specifies the address of a IDHParameterBlock structure. Each of the fields are described in detail
in a previous section. The user should keep the IDHParameterBlock around until the completion routine
is called.
Result Codes:
kIDHErrDeviceNotConfigured A device has not already been selected using IDHSetDeviceConfiguration()
kIDHErrInvalidDeviceID Internal Error
kIDHErrDeviceTimeout Timeout on synchronous read
IDHReleaseBuffer
----------------
The IDHReleaseBuffer function releases a buffer returned from an IDHRead() request where
the client specified a 'nil' buffer.
pascal ComponentResult IDHReleaseBuffer( ComponentInstance idh, IDHParameterBlock *pb)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
pb - Specifies the address of the IDHParameterBlock structure that was originally passed into
IDHRead() function. NOTE: The buffer will remain valid for an indeterminate amount of time.
The client should USE the buffer ASAP to guarantee data integrity.
Result Codes:
kIDHErrDeviceNotConfigured A device has not already been selected using IDHSetDeviceConfiguration()
kIDHErrInvalidDeviceID Internal Error
IDHCancelPendingIO
------------------
The IDHCancelPendingIO function cancels any outstanding IDHRead() or IDHWrite() requests. This
should be called prior to closing a device.
pascal ComponentResult IDHCancelPendingIO( ComponentInstance idh, IDHParameterBlock *pb)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
pb - Specifies the address of the IDHParameterBlock structure that was originally passed into
IDHRead() or IDHWrite() function.
Result Codes:
Macintosh errors
Getting device status
IDHGetDeviceStatus
------------------
The IDHGetDeviceStatus function gets the device status from the specified device configuration.
pascal ComponentResult IDHGetDeviceStatus( ComponentInstance idh, const QTAtomSpec *configurationID,
IDHDeviceStatus *status)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
configurationID - The user passes an QTAtomSpec which is an atom container/ kIDHIsochModeAtomType atom
pair. NOTE: The user must NOT dispose of the device list (requested by IDHGetDeviceList())
until he is through with this configuration.
status - The address of a IDHDeviceStatus structure. The specified device status will be returned. Each
of the status fields are described in detail above.
Result Codes:
kIDHErrDeviceList The device list is either stale or corrupt. Please IDHGetDeviceList().
kIDHErrInvalidDeviceID Internal Error
Device Notification
IDHNewNotification
------------------
The IDHNewNotification function creates a notification ID which is used to initiate client notification
based on device events.
pascal ComponentResult IDHNewNotification( ComponentInstance idh, IDHDeviceID deviceID,
IDHNotificationProc notificationProc, void *userData,
IDHNotificationID *notificationID)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
deviceID - the value of a devices kIDHDeviceIDType atom or kIDHDeviceIDEveryDevice.
notificationProc - the client function that is called when a particular event has taken place
userData - the client specified data returned to the client notificationProc.
notificationID - this parameter is returned to the client and used in other IDH functions.
Result Codes:
Macintosh errors
IDHNotifyMeWhen
---------------
The IDHNotifyMeWhen function actually enables the notification process. When one of the client specified
events occur, the client will be notified through his notification function. NOTE: This function is
a one shot. The function must be called again after the event(s) have occured to re-enable the
notification.
pascal ComponentResult IDHNotifyMeWhen( ComponentInstance idh, IDHNotificationID notificationID,
IDHEvent events)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
notificationID - this parameter is obtained by calling IDHNewNotification.
events - one or more flags that the client uses to specify the device events of interest
kIDHEventDeviceAdded - Indicates that a new device has been added to the computer. The value of this
flag is 1.
kIDHEventDeviceRemoved - Indicates that a device has been removed from the computer. The value of this
flag is 2.
kIDHEventDeviceChanged - Indicates that a device is ???. The value of this flag is 4.
kIDHEventReadEnabled - Indicates that a device has been enabled for read. The value of this flag
is 8.
kIDHEventReadDisabled - Indicates that a device has been disabled for read. The value of this flag
is 32.
kIDHEventWriteEnabled - Indicates that a device has been enabled for write. The value of this flag
is 64.
kIDHEventWriteDisabled - Indicates that a device has been disabled for write. The value of this flag
is 256.
Result Codes:
Macintosh Errors
IDHCancelNotification
---------------------
The IDHCancelNotification function cancels an outstanding IDHNotifyMeWhen() request. This function
should be called prior to exiting to avoid spurious calls to the client callback.
pascal ComponentResult IDHCancelNotification( ComponentInstance idh, IDHNotificationID notificationID)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
notificationID - this parameter is obtained by calling IDHNewNotification() and used in IDHNotifyMeWhen().
Result Codes:
Macintosh Errors
IDHDisposeNotification
----------------------
The IDHDisposeNotification function releases the resources associated with the IDHNotificationID. This
function should be called before closing the isoch component.
pascal ComponentResult IDHDisposeNotification( ComponentInstance idh, IDHNotificationID notificationID)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
notificationID - this parameter is obtained by calling IDHNewNotification().
Result Codes:
Macintosh Errors
Other functions
IDHGetDeviceClock
-----------------
The IDHGetDeviceClock function returns a bus specific clock component used in audio/video
synchronization. The client should read the Quicktime documentation for information about
a Clock Component. The Clock component is used in other Quicktime functions such as video out.
pascal ComponentResult IDHGetDeviceClock( ComponentInstance idh, Component *clock)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
clock - returns the Clock component associated with this IDH component.
Result Codes:
kIDHErrDeviceNotConfigured A device has not already been selected using IDHSetDeviceConfiguration()
IDHGetDeviceControl
-------------------
The IDHGetDeviceControl function returns an instance to a device control component associated with
the device that was most recently set with IDHSetDeviceConfiguration. See the device control component
documentation for more details.
pascal ComponentResult IDHGetDeviceControl( ComponentInstance idh, ComponentInstance *deviceControl)
idh - Specifies the IDH component for operation. You can obtain this identifier from the
ComponentManager's OpenComponent() function.
deviceControl - returns an instance of a device control component.
Result Codes:
kIDHErrDeviceNotConfigured A device has not already been selected using IDHSetDeviceConfiguration()
kIDHErrInvalidDeviceID Internal Error
Device Control Component Reference
==================================
Component Types for Device Control Components
------------------------------------
#define kDVCComponentType 'devc' /* Component type*/
#define kDVCSubtypeDV 'fwdv' /* Subtype for DV (over FireWire)*/
Data Types for Device Control Components
-------------------------------
The parameter block passed to DeviceControlDoAVCTransaction():
typedef UInt32 DCResponseHandler(UInt32 fwCommandObjectID, Ptr responseBuffer, UInt32 responseLength);
struct DVCTransactionParams {
Ptr commandBufferPtr; /* pointer to AVC command bytes */
UInt32 commandLength; /* command length in bytes */
Ptr responseBufferPtr; /* pointer to buffer to store AVC response */
UInt32 responseBufferSize; /* response buffer size in bytes */
DCResponseHandler * responseHandler; /* Function to call when device sends response - IGNORED in X 1.0 */
};
typedef struct DVCTransactionParams DVCTransactionParams;
Device Control Component Functions
===============================
DeviceControlDoAVCTransaction
-----------------------------
The DeviceControlDoAVCTransaction transaction sends an AV/C command to the device and returns the response sent by the device. Documentation on AV/C command and response formats is available from the 1394 Trade Association (www.1394TA.org)
ComponentResult DeviceControlDoAVCTransaction(ComponentInstance instance, DVCTransactionParams * params)
instance - specifies the device control component for operation. Obtained from IDHGetDeviceControl().
params - parameter block for call.
SAMPLE CODE
===========
NOTE - The isoch component requires QT 4.0 headers and libraries.
Opening a DV isoch component
----------------------------
ComponentDescription compDesc;
Component isochComponent;
ComponentInstance isochInstance;
compDesc.componentType = kIDHComponentType;
compDesc.componentSubType = kIDHSubtypeDV;
compDesc.componentManufacturer = 0;
compDesc.componentFlags = 0;
compDesc.componentFlagsMask = kAnyComponentFlagsMask;
isochComponent = FindNextComponent( nil, &compDesc);
if( isochComponent == nil)
goto error;
isochInstance = OpenComponent( isochComponent);
if( isochInstance == nil)
goto error;
Finding the first video device in the list
------------------------------------------
QTAtomContainer deviceList;
short nDVDevices, i, j, nConfigs;
QTAtom deviceAtom, isochAtom;
QTAtomSpec currentIsochConfig;
err = IDHGetDeviceList( isochInstance, &deviceList);
if( err != noErr)
goto err;
nDVDevices = QTCountChildrenOfType( deviceList, kParentAtomIsContainer, kIDHDeviceAtomType);
for( i=0; i<nDVDevices; ++i)
{
QTAtom deviceAtom, isochAtom;
int nConfigs;
// get the atom to this device
deviceAtom = QTFindChildByIndex( deviceList, kParentAtomIsContainer, kIDHDeviceAtomType, i + 1, nil);
if( deviceAtom == nil)
goto error;
// find the isoch characteristics for this device
isochAtom = QTFindChildByIndex( deviceList, deviceAtom, kIDHIsochServiceAtomType, 1, nil);
if( isochAtom == nil)
goto error;
// how many configs exist for this device
nConfigs = QTCountChildrenOfType( deviceList, isochAtom, kIDHIsochModeAtomType);
currentIsochConfig.atom = nil; // start with no selected config
// process each config
for( j=0; j<nConfigs; ++j)
{
OSType mediaType;
long size;
QTAtom configAtom, mediaAtom;
// get this configs atom
configAtom = QTFindChildByIndex( deviceList, isochAtom, kIDHIsochModeAtomType, j + 1, nil);
if( configAtom == nil)
goto error;
// find the media type atom
mediaAtom = QTFindChildByIndex( deviceList, configAtom, kIDHIsochMediaType, 1, nil);
if( mediaAtom == nil)
goto error;
QTLockContainer( deviceList);
// get the value of the mediaType atom
QTCopyAtomDataToPtr( deviceList, mediaAtom, true, sizeof( mediaType), &mediaType, &size);
QTUnlockContainer( deviceList);
// is this config an video config?
if( mediaType == kIDHVideoMediaAtomType) // found video device
{
currentIsochConfig.container = deviceList; // save this config
currentIsochConfig.atom = configAtom;
break;
}
}
if( currentIsochConfig.atom != nil) // did we find a video config?
break;
}
if( currentIsochConfig.atom == nil) // no good configs found
goto error;
Setting a configuration and opening a device for reading
--------------------------------------------------------
// set isoch to use this config
err = IDHSetDeviceConfiguration( isochInstance, ¤tIsochConfig);
if( err != noErr)
goto error;
// open the DV device
err = IDHOpenDevice( isochInstance, kIDHOpenForReadTransactions);
if( err != noErr)
goto Exit);
Reading from a device (client supplies buffer)
----------------------------------------------
// we are doing isoch reads with only one buffer at a time
isochParamBlock.buffer = myBuffer;
isochParamBlock.requestedCount = 120000; // NTSC buffer size
isochParamBlock.actualCount = 0;
isochParamBlock.completionProc = DVIsochComponentReadCallback;
isochParamBlock.refCon = iGlobals;
err = IDHRead( isochInstance, &isochParamBlock);
if( err != noErr)
goto error;
Callback from read request (client supplies buffer)
---------------------------------------------------
// called when a new isoch read is received
OSStatus DVIsochComponentReadCallback( IDHGenericEvent *eventRecord, void *userData)
{
OSErr result = noErr;
ComponentInstancePtr iGlobals = userData;
IDHParameterBlock *pb = (IDHParameterBlock *) eventRecord;
// fill out structure
pb->buffer = myBuffer;
pb->requestedCount = 120000;
pb->actualCount = 0;
pb->completionProc = DVIsochComponentReadCallback;
pb->refCon = iGlobals;
// do another read
result = IDHRead( isochInstance, pb);
if( result != noErr)
goto error;
error:
return result;
}
Reading from a device (isoch component supplies buffer)
-------------------------------------------------------
// we are doing isoch reads with only one buffer at a time
isochParamBlock.buffer = nil;
isochParamBlock.requestedCount = 120000; // NTSC buffer size
isochParamBlock.actualCount = 0;
isochParamBlock.completionProc = DVIsochComponentReadCallback;
isochParamBlock.refCon = iGlobals;
err = IDHRead( isochInstance, &isochParamBlock);
if( err != noErr)
goto error;
Callback from read request (isoch component supplies buffer)
------------------------------------------------------------
// called when a new isoch read is received
OSStatus DVIsochComponentReadCallback( IDHGenericEvent *eventRecord, void *userData)
{
OSErr result = noErr;
ComponentInstancePtr iGlobals = userData;
IDHParameterBlock *pb = (IDHParameterBlock *) eventRecord;
WorkOnData( pb->buffer, pb->actualCount);
result = IDHReleaseBuffer( isochInstance, pb);
if( result != noErr)
goto error;
// fill out structure
pb->buffer = nil;
pb->requestedCount = 120000;
pb->actualCount = 0;
pb->completionProc = DVIsochComponentReadCallback;
pb->refCon = iGlobals;
// do another read
result = IDHRead( isochInstance, pb);
if( result != noErr)
goto error;
error:
return result;
}
Writing to device (client supplies the buffer)
----------------------------------------------
// we are doing isoch reads with only one buffer at a time
isochParamBlock.buffer = myBuffer;
isochParamBlock.requestedCount = 120000; // NTSC buffer size
isochParamBlock.actualCount = 0;
isochParamBlock.completionProc = DVIsochComponentWriteCallback;
isochParamBlock.refCon = iGlobals;
err = IDHWrite( isochInstance, &isochParamBlock);
if( err != noErr)
goto error;
Callback from write request (client supplies the buffer)
--------------------------------------------------------
// called when a new isoch read is received
OSStatus DVIsochComponentWriteCallback( IDHGenericEvent *eventRecord, void *userData)
{
OSErr result = noErr;
ComponentInstancePtr iGlobals = userData;
IDHParameterBlock *pb = (IDHParameterBlock *) eventRecord;
// fill out structure
isochParamBlock.buffer = myBuffer;
isochParamBlock.requestedCount = 120000; // NTSC buffer size
isochParamBlock.actualCount = 0;
isochParamBlock.completionProc = DVIsochComponentWriteCallback;
isochParamBlock.refCon = iGlobals;
// do another read
result = IDHWrite( isochInstance, pb);
if( result != noErr)
goto error;
error:
return result;
}
Writing to device (isoch component supplies the buffer)
-------------------------------------------------------
// we are doing isoch reads with only one buffer at a time
isochParamBlock.buffer = nil;
isochParamBlock.requestedCount = 120000; // NTSC buffer size
isochParamBlock.actualCount = 0;
isochParamBlock.completionProc = DVIsochComponentWriteCallback;
isochParamBlock.refCon = iGlobals;
err = IDHWrite( isochInstance, &isochParamBlock);
if( err != noErr)
goto error;
Callback from write request (isoch component supplies the buffer)
-----------------------------------------------------------------
// called when a new isoch read is received
OSStatus DVIsochComponentWriteCallback( IDHGenericEvent *eventRecord, void *userData)
{
OSErr result = noErr;
ComponentInstancePtr iGlobals = userData;
IDHParameterBlock *pb = (IDHParameterBlock *) eventRecord;
BlockMove( myBuffer, pb->buffer, 120000);
// fill out structure
isochParamBlock.buffer = nil;
isochParamBlock.requestedCount = 120000; // NTSC buffer size
isochParamBlock.actualCount = 0;
isochParamBlock.completionProc = DVIsochComponentWriteCallback;
isochParamBlock.refCon = iGlobals;
// do another read
result = IDHWrite( isochInstance, pb);
if( result != noErr)
goto error;
error:
return result;
}
Closing down the isoch device
-----------------------------
result = IDHCancelPendingIO( isochInstance, &isochParamBlock);
result = IDHCloseDevice( isochInstance);
CloseComponent( isochInstance); // close isoch component
Writing a device control command to a device
--------------------------------------------
ComponentInstance deviceControlInstance;
result = IDHGetDeviceControl( isochInstance, &deviceControlInstance);
if( result != noErr)
goto error;
result = DeviceControlDoAVCTransaction( deviceControlInstance, (DVCTransactionParams *) pParams);
if( result != noErr)
goto error;
Setting up notification for a device being enabled for reads
------------------------------------------------------------
deviceNotificationID = 0;
result = IDHNewNotification( isochInstance, kIDHDeviceIDEveryDevice, DVDeviceCallback,
(void *) iGlobals, &deviceNotificationID);
if( result != noErr)
goto error;
result = IDHNotifyMeWhen( isochInstance, deviceNotificationID, kIDHEventReadEnabled);
if( result != noErr)
goto error;
Getting called on a notification event
--------------------------------------
OSStatus DVDeviceCallback( IDHGenericEvent *event, void *userData)
{
switch( event->eventHeader.event)
{
case kIDHEventReadEnabled:
deviceHasBeenReadEnabled( event);
break;
}
}