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; ibuffer = 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; } }