1/* 2 * Copyright (c) 2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <Carbon/Carbon.h> 25 26typedef struct IsochComponentInstance IsochComponentInstance, *IsochComponentInstancePtr; 27typedef struct IsochComponentGlobals IsochComponentGlobals, *IsochComponentGlobalsPtr; 28 29#define CALLCOMPONENT_BASENAME() IDHDV 30#define CALLCOMPONENT_GLOBALS() IsochComponentInstancePtr storage 31 32#define IDH_BASENAME() FWDV 33#define IDH_GLOBALS() IsochComponentInstancePtr storage 34#include "IsochronousDataHandler.k.h" 35 36#include "DeviceControlPriv.h" 37 38#include "DVVers.h" 39 40#include <stdio.h> 41#include <stdlib.h> 42#include <unistd.h> // usleep() 43#include <pthread.h> 44#include <syslog.h> // Debug messages 45 46// Timebase stuff 47#include <mach/clock.h> 48#include <mach/clock_types.h> 49// Trace stuff 50#include <sys/syscall.h> 51 52#include <CoreFoundation/CoreFoundation.h> 53#include <IOKit/IOKitLib.h> 54 55#include <IOKit/IOMessage.h> 56#include <IOKit/firewire/IOFireWireFamilyCommon.h> 57#include <IOKit/avc/IOFireWireAVCConsts.h> 58 59#include "DVLib.h" 60 61#define kDVRequestID 0 62#define kIOPending 1 63#define kIORunning 2 64#define kMaxDeviceClients 4 65 66#define kDCLBlockTime (100.0/8000.0) 67 68#define DEBUG 0 69//#define DRAWRINGBUFFERGRAPH 70/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 71 72#define kDVDeviceInfo 'ddin' // DV device info 73#define kMaxInstances 10 // max clients attached to a device 74#define kMaxNotifications 100 // 100 notifications can be supported 75#define kNTSCCompressedBufferSize 120000 76#define kPALCompressedBufferSize 144000 77#define kIDHSeedAtomType 'seed' // seed for device atom validity 78#define kIDHDevicePresentType 'pres' // is device present? 79#define kServiceTypeDVServices 'avc ' 80#define kTimeoutDuration (1000 / 15) * durationMillisecond // 1/15 second (2 frame times) 81 82typedef OSStatus (*RequestFunc)(IsochComponentInstancePtr ih, void *params); 83 84typedef struct ClientNotification { 85 ComponentInstance ihc; 86 IDHDeviceID deviceID; 87 IDHNotificationProc notificationProc; 88 IDHEvent events; 89 void *userData; 90} ClientNotification; 91 92// describes a device on the firewire bus 93typedef struct DeviceDescription { 94 DVDevice *fDevice; 95 IsochComponentGlobalsPtr fGlobals; 96 UInt32 fNumOutputFrames; 97 UInt8* bufMem[kDVMaxFrames]; 98 DVFrameVars *fReadSharedVars; // Structure shared with isoc program thread 99 DVFrameVars *fWriteSharedVars; // Structure shared with isoc program thread 100 DVGlobalOutPtr fWrite; 101 DVGlobalInPtr fRead; 102 UInt8 * fDCLBuffer; // DCL Buffers shared with kernel driver 103 DVSharedVars *fSharedWriteVars; // For access to output DCL variables 104 UInt32 * fOldWriteTimeStamps; 105 int fDCLReadPos; // Which block the DCL write program will process next 106 int fBufWritePos; // Next block to write data into 107 int fFrameBufferPos; // Current offset into current frame buffer 108 int fDCLSavedPacketNum; // Current packet in DCL buffer when we're waiting for a frame 109 UInt8 * fDCLSavedWritePos; // Current position in DCL buffer when we're waiting for the next frame 110 int fBufSize; // NTSC or PAL frame 111 int fOldDrop; // Dropped before 112 int fOldRead; // Where DV driver was before 113 IsochComponentInstancePtr fOpenClients[kMaxDeviceClients]; // component instances doing I/O to/from device 114 int fBufferLocks[kDVMaxFrames]; 115 ComponentInstance deviceControlInstance; // device control component instance 116 Component clock; // FireWire clock component, clients get their own instance, not sure why 117 QTAtomContainer deviceContainer; // contains device database 118 SInt16 deviceControlCount; // number of clients using device control 119 SInt16 readLocks; // num clients that have device open for reads 120 SInt16 writeLocks; // num clients that have device open for writes 121 Boolean fActive; // device is currently online 122 UInt8 fOutputMode; // AVC output signal mode - NTSC/SDL etc. 123 UInt8 fWaitingStartWrite; // 1 = if we're filling up buffers before starting to write, 2 = need to retry start 124 UInt8 fConnected; // Number of times device has been selected (via IDHSetDeviceConfiguration) 125 UInt8 fReadStage; 126 UInt8 fNoAVC; // True if device doesn't do AVC commands 127#ifdef DRAWRINGBUFFERGRAPH 128 Ptr fScreenBaseAddr; 129 UInt32 fPixDepth; 130 UInt32 fRowBytes; 131#endif 132} DeviceDescription, *DeviceDescriptionPtr; 133 134#ifdef DRAWRINGBUFFERGRAPH 135static void SetUpBlitGlobals(DeviceDescriptionPtr ddp); 136static void BlitBufferGraph(DeviceDescriptionPtr ddp); 137#endif 138 139struct IsochComponentGlobals 140{ 141 // Globals 142 UInt32 useCMP; // CMP off by default, turn on by adding 'ucmp' resource 143 DeviceDescription deviceDescription[kDVMaxDevicesActive]; // description of each device 144 ClientNotification clientNotification[kMaxNotifications]; // arbirtary # of notifications 145 UInt32 nDevices; // number of devices in the list 146 UInt32 seed; // keep track of device lists 147 148 // X Stuff 149 DVThread * fDVThread; 150 CFBundleRef fBundleID; // Of the DV component's bundle 151 UInt16 fBundleResRef; // ref for the resource file 152 153 int fNumInstances; 154}; 155 156 157struct IsochComponentInstance 158{ 159 // Instance variables 160 ComponentInstance self; 161 QTAtomSpec currentConfig; // current device config set by client 162 IDHDeviceID deviceID; // current deviceID 163 UInt16 fClientIndex; // into device client list 164 long permissions; // open permissions 165 IDHParameterBlock * fHead; // Of I/O queue 166 IDHParameterBlock * fTail; // Of I/O queue 167 IDHParameterBlock * fActiveHead; // Of I/Os referencing the ring buffer 168 IDHParameterBlock * fActiveTail; // Of I/O referencing the ring buffer 169 UInt32 fSyncRequest; // Flag to indicate completion of synchronous operation 170 ComponentResult fSyncResult; // Result of sync operation 171 Boolean hasDeviceControl; // does this client have device control? 172}; 173 174/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 175 176/* Function prototypes */ 177 178pascal ComponentResult 179FWDVICodecComponentDispatch(ComponentParameters *params, char ** storage); 180static pascal ComponentResult 181FWDVIDHCloseDevice(IsochComponentInstancePtr ih); 182 183static OSStatus doAVCTransaction(DeviceDescriptionPtr deviceDescriptionPtr, 184 DVCTransactionParams* inTransaction); 185 186static OSStatus disableRead(DeviceDescription *deviceDescriptionPtr); 187static void disableWrite(DeviceDescription *deviceDescriptionPtr); 188 189/* Globals */ 190static IsochComponentGlobals globals; 191 192 193/* ---------------------- Debug Stuff -------------------------- */ 194#ifdef DEBUG 195#define FailMessage(cond) assert (!(cond)) 196#else 197#define FailMessage(cond) {} 198#endif 199#define FailWithVal(cond, handler,num) \ 200 if (cond) { \ 201 goto handler; \ 202 } 203#define FailWithAction(cond, action, handler) \ 204 if (cond) { \ 205 { action; } \ 206 goto handler; \ 207 } 208 209#define FailIf(cond, handler) \ 210 if (cond) { \ 211 FailMessage(false); \ 212 goto handler; \ 213 } 214 215#if DEBUG 216static char * print4(UInt32 val, char *buf) 217{ 218 char a, b, c, d; 219 a = val>>24; 220 b = val>>16; 221 c = val>>8; 222 d = val; 223 224 if(a >= ' ' && b >= ' ' && c >= ' ' && d >= ' ') 225 //printf("%c%c%c%c", a, b, c, d); 226 //syslog(LOG_INFO, "%c%c%c%c", a, b, c, d); 227 snprintf(buf, 8, "%c%c%c%c", a, b, c, d); 228 else 229 //printf(" 0x%x ", (int)val); 230 //syslog(LOG_INFO, " 0x%x ", (int)val); 231 snprintf(buf, 8, " 0x%x ", (int)val); 232 233 return buf + strlen(buf); 234} 235 236static void RecordEventLogger(UInt32 a, UInt32 b, UInt32 c, UInt32 d) 237{ 238 char buf[256]; 239 char *curr = buf; 240 snprintf(buf, 11, "0x%x:", (unsigned int) pthread_self()); 241 curr = buf + strlen(buf); 242 if(a) 243 curr = print4(a, curr); 244 if(b) 245 curr = print4(b, curr); 246 if(c) 247 curr = print4(c, curr); 248 if(d) 249 curr = print4(d, curr); 250 printf("%s\n", buf); 251 syslog(LOG_INFO, buf); 252} 253#else 254#define RecordEventLogger(a, b, c, d) 255#endif 256 257//masks for SYS_kdebug_trace code 258#define kKernelTraceEnable (1 << 0 ) 259#define kKernelTraceDisable (1 << 1 ) 260#define kIOFWDVTrace 0x08001000 261 262#if 0 263static int pKGSysCall_Start (int code, int param1, int param2, int param3, int param4, int param5, int param6 ) 264{ 265 return syscall ( SYS_kdebug_trace, code | kKernelTraceEnable, param1, param2, param3, param4, param5, param6 ); 266} 267 268static int pKGSysCall_End (int code, int param1, int param2, int param3, int param4, int param5, int param6 ) 269{ 270 return syscall ( SYS_kdebug_trace, code | kKernelTraceDisable, param1, param2, param3, param4, param5, param6 ); 271} 272#endif 273 274static int pKGSysCall_Insert (int code, int param1, int param2, int param3, int param4, int param5, int param6 ) 275{ 276 return syscall ( SYS_kdebug_trace, code , param1, param2, param3, param4, param5, param6 ); 277} 278 279static void dropMsg(DeviceDescription *deviceDescriptionPtr, UInt32 dropped) 280{ 281 IsochComponentGlobalsPtr g = deviceDescriptionPtr->fGlobals; 282 UInt32 i; 283 IDHDeviceFrameDroppedEvent dropEvent; 284 pKGSysCall_Insert (kIOFWDVTrace, 'drop', dropped-deviceDescriptionPtr->fOldDrop, dropped, 0, 0, 0); 285 286 for (i = 0; i < kMaxNotifications ; ++i) 287 { 288 ClientNotification* clientNotification = &g->clientNotification[i]; 289 IDHDeviceID clientDeviceID = clientNotification->deviceID; 290 IDHEvent wantedEvents = clientNotification->events; 291 if (kIDHEventFrameDropped & wantedEvents) 292 { 293 // Send notification if the device matches the client's desired device 294 // or client specified all devices. 295 if ((kIDHDeviceIDEveryDevice == clientDeviceID) || 296 ((IDHDeviceID)deviceDescriptionPtr == clientDeviceID) ) 297 { 298 // we currently only support a one-shot notification, like clock callbacks 299 clientNotification->events = 0; 300 301 dropEvent.eventHeader.event = kIDHEventFrameDropped; 302 dropEvent.eventHeader.deviceID = (IDHDeviceID)deviceDescriptionPtr; 303 dropEvent.eventHeader.notificationID = 304 (UInt32)clientNotification; 305 dropEvent.totalDropped = dropped; 306 dropEvent.newlyDropped = dropped - deviceDescriptionPtr->fOldDrop; 307 308 (*clientNotification->notificationProc) 309 ((IDHGenericEvent*)&dropEvent, 310 clientNotification->userData); 311 } 312 } 313 } 314 315 // syslog(LOG_INFO,"Just dropped %ld frames (total %ld)!\n", dropped-deviceDescriptionPtr->fOldDrop, dropped); 316 317 deviceDescriptionPtr->fOldDrop = dropped; 318} 319 320static inline UInt32 cycles(UInt32 cycleReg) 321{ 322#if 0 323 UInt32 result; 324 result = ((cycleReg & 0xFE000000) >> 25) * 8000; 325 result += (cycleReg & 0x01FFF000) >> 12; 326 return result; 327#else 328 return (cycleReg & 0x01FFF000) >> 12; 329#endif 330} 331 332/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 333 334OSStatus findDeviceDescriptionforDevice( IsochComponentInstancePtr ih, UInt32 deviceID, DeviceDescription **deviceDescription) 335{ 336 OSStatus result = noErr; 337 *deviceDescription = (DeviceDescriptionPtr)deviceID; 338 return result; 339} 340 341//��� do a super find atom someday 342static OSStatus findAtom( const QTAtomSpec *atomSpec, OSType theType, QTAtom *theAtom) 343{ 344 OSStatus result = noErr; 345 OSType type; 346 QTAtom atom; 347 348 atom = atomSpec->atom; 349 350 result = QTGetAtomTypeAndID( atomSpec->container, atom, (long *) &type, nil); 351 FailWithVal( result != noErr, Exit, result); 352 353 while( type != kIDHDeviceAtomType && type != theType) 354 { 355 atom = QTGetAtomParent( atomSpec->container, atom); // should be isoch atom 356 FailWithAction( atom == nil || atom == -1, result = kIDHErrDeviceList, Exit); 357 358 result = QTGetAtomTypeAndID( atomSpec->container, atom, (long *) &type, nil); 359 FailWithVal( result != noErr, Exit, result); 360 } 361 362 if( theType == type) 363 { 364 *theAtom = atom; 365 result = noErr; 366 } 367 else 368 { 369 *theAtom = nil; 370 result = kIDHErrDeviceList; 371 } 372 373Exit: 374 return result; 375} 376 377static OSStatus getDeviceID( QTAtomSpec *configID, UInt32 *deviceID) 378{ 379 OSStatus result = noErr; 380 QTAtom deviceAtom; 381 382 *deviceID = nil; 383 384 result = findAtom( configID, kIDHDeviceAtomType, &deviceAtom); 385 FailWithVal( result != noErr, Exit, result); 386 387 result = QTGetAtomTypeAndID( configID->container, deviceAtom, nil, (long *) deviceID); 388 FailWithVal( result != noErr, Exit, result); 389 390Exit: 391 return result; 392} 393 394static OSStatus closeDeviceControl( IsochComponentInstancePtr ih, DeviceDescriptionPtr deviceDescriptionPtr) 395{ 396 OSStatus result = noErr; 397 398#ifdef kIDH_Verbose_Debug_Logging 399 syslog(LOG_INFO, "IDH: closeDeviceControl begin\n"); 400#endif 401 402 if( deviceDescriptionPtr->deviceControlInstance) 403 { 404 if( --deviceDescriptionPtr->deviceControlCount <= 0) 405 { 406 deviceDescriptionPtr->deviceControlCount = 0; 407 408 result = DeviceControlDisableAVCTransactions(deviceDescriptionPtr->deviceControlInstance); 409 result = DeviceControlSetDeviceConnectionID(deviceDescriptionPtr->deviceControlInstance, 410 kIDHInvalidDeviceID); 411 412 CloseComponent(deviceDescriptionPtr->deviceControlInstance); 413 414 deviceDescriptionPtr->deviceControlInstance = nil; 415 } 416 } 417 418#ifdef kIDH_Verbose_Debug_Logging 419 syslog(LOG_INFO, "IDH: closeDeviceControl end\n"); 420#endif 421 422 return result; 423} 424 425OSStatus checkSeed( IsochComponentGlobalsPtr gGlobals, QTAtomSpec *configID) 426{ 427 QTAtom seedAtom; 428 OSStatus result = noErr; 429 UInt32 seed; 430 431 // look for device in device container 432 seedAtom = QTFindChildByIndex( configID->container, kParentAtomIsContainer, kIDHSeedAtomType, 1, nil); 433 FailWithAction( seedAtom == nil, result = kIDHErrDeviceList, Exit); 434 435 QTLockContainer( configID->container); 436 437 // get the value of the devicePresent atom 438 QTCopyAtomDataToPtr( configID->container, seedAtom, true, sizeof( seed), &seed, nil); 439 440 QTUnlockContainer( configID->container); 441 442 // seed has expired? 443 if( seed != gGlobals->seed) 444 { 445 result = kIDHErrDeviceList; 446 goto Exit; 447 } 448 449Exit: 450 return result; 451} 452 453static OSStatus setupVideoAtoms( QTAtomContainer container, QTAtom isocAtom, UInt32 standard, Boolean isSDL, Boolean isDVCPro) 454{ 455 OSStatus result = noErr; 456 QTAtom configAtom; 457 OSType type; 458 long size; 459 float interval; 460 long direction; 461 IDHDimension dimension; 462 IDHResolution resolution; 463 Fixed refresh; 464 OSType pixel; 465 OSType decoType; 466 Component decoComponent; 467 ComponentDescription compDescrip; 468 469#ifdef kIDH_Verbose_Debug_Logging 470 syslog(LOG_INFO, "IDH: setupVideoAtoms begin\n"); 471#endif 472 473 // create a vide NTSC mode 474 result = QTInsertChild( container, isocAtom, kIDHIsochModeAtomType, 475 0, 0, 0, nil, &configAtom); 476 FailWithVal( result != noErr, Exit, result); 477 478 type = kIDHVideoMediaAtomType; 479 result = QTInsertChild( container, configAtom, kIDHIsochMediaType, 480 0, 0, sizeof( type), &type, nil); 481 FailWithVal( result != noErr, Exit, result); 482 483 if(isSDL) { 484 result = QTInsertChild( container, configAtom, kIDHNameAtomType, 485 0, 0, 7, "\pDV-SDL", nil); 486 } 487 else if(isDVCPro) { 488 result = QTInsertChild( container, configAtom, kIDHNameAtomType, 489 0, 0, 7, "\pDVCPro", nil); 490 } 491 else { 492 result = QTInsertChild( container, configAtom, kIDHNameAtomType, 493 0, 0, 3, "\pDV", nil); 494 } 495 FailWithVal( result != noErr, Exit, result); 496 497 type = (standard == ntscIn)?'DVC ':'DVCP'; 498 result = QTInsertChild( container, configAtom, kIDHDataTypeAtomType, 499 0, 0, sizeof( type), &type, nil); 500 FailWithVal( result != noErr, Exit, result); 501 502 size = (standard == ntscIn)?kNTSCCompressedBufferSize:kPALCompressedBufferSize; 503 if(isSDL) 504 size /= 2; 505 result = QTInsertChild( container, configAtom, kIDHDataSizeAtomType, 506 0, 0, sizeof( size), &size, nil); 507 FailWithVal( result != noErr, Exit, result); 508 509 result = QTInsertChild( container, configAtom, kIDHDataBufferSizeAtomType, 510 0, 0, sizeof( size), &size, nil); 511 FailWithVal( result != noErr, Exit, result); 512 513 interval = 29.97; 514 result = QTInsertChild( container, configAtom, kIDHDataIntervalAtomType, 515 0, 0, sizeof( interval), &interval, nil); 516 FailWithVal( result != noErr, Exit, result); 517 518 direction = kIDHDataTypeIsInputAndOutput; 519 result = QTInsertChild( container, configAtom, kIDHDataIODirectionAtomType, 520 0, 0, sizeof( direction), &direction, nil); 521 FailWithVal( result != noErr, Exit, result); 522 523 dimension.x = 720; dimension.y = (standard == ntscIn)?480:576; 524 result = QTInsertChild( container, configAtom, kIDHVideoDimensionsAtomType, 525 0, 0, sizeof( dimension), &dimension, nil); 526 FailWithVal( result != noErr, Exit, result); 527 528 resolution.x = 72 << 16; resolution.y = 72 << 16; 529 result = QTInsertChild( container, configAtom, kIDHVideoResolutionAtomType, 530 0, 0, sizeof( resolution), &resolution, nil); 531 FailWithVal( result != noErr, Exit, result); 532 533 refresh = (29 << 16) + 97; //��� 534 result = QTInsertChild( container, configAtom, kIDHVideoRefreshRateAtomType, 535 0, 0, sizeof( refresh), &refresh, nil); 536 FailWithVal( result != noErr, Exit, result); 537 538 pixel = 'dv '; //��� 539 result = QTInsertChild( container, configAtom, kIDHVideoPixelTypeAtomType, 540 0, 0, sizeof( pixel), &pixel, nil); 541 FailWithVal( result != noErr, Exit, result); 542 543//��� kIDHVideoDecompressorsAtomType = FOUR_CHAR_CODE('deco'), 544 545 decoType = (standard == ntscIn)?'dvc ':'dvcp'; 546 result = QTInsertChild( container, configAtom, kIDHVideoDecompressorTypeAtomType, 547 0, 0, sizeof( decoType), &decoType, nil); 548 FailWithVal( result != noErr, Exit, result); 549 550 compDescrip.componentType = 'imdc'; 551 compDescrip.componentSubType = decoType; 552 compDescrip.componentManufacturer = 0; 553 compDescrip.componentFlags = 0; 554 compDescrip.componentFlagsMask = 0; 555 556 decoComponent = FindNextComponent( nil, &compDescrip); 557 result = QTInsertChild( container, configAtom, kIDHVideoDecompressorComponentAtomType, 558 0, 0, sizeof( decoComponent), &decoComponent, nil); 559 FailWithVal( result != noErr, Exit, result); 560 561Exit: 562 563#ifdef kIDH_Verbose_Debug_Logging 564 syslog(LOG_INFO, "IDH: setupVideoAtoms end\n"); 565#endif 566 567 return result; 568} 569 570static OSStatus setup48kAudioAtoms( QTAtomContainer container, QTAtom isocAtom, UInt32 standard) 571{ 572 OSStatus err; 573 QTAtom configAtom; 574 575 StringPtr name; 576 OSType type; 577 long size; 578 Fixed rate; 579 float interval; 580 long direction; 581 582 // create a vide NTSC mode 583 err = QTInsertChild( container, isocAtom, kIDHIsochModeAtomType, 584 0, 0, 0, nil, &configAtom); 585 FailWithVal( err != noErr, Exit, err); 586 587 type = kIDHSoundMediaAtomType; 588 err = QTInsertChild( container, configAtom, kIDHIsochMediaType, 589 0, 0, sizeof( type), &type, nil); 590 FailWithVal( err != noErr, Exit, err); 591 592 name = "\pDV-48khz"; 593 err = QTInsertChild( container, configAtom, kIDHNameAtomType, 594 0, 0, name[0]+1, name, nil); 595 FailWithVal( err != noErr, Exit, err); 596 597 type = 'DV48'; 598 err = QTInsertChild( container, configAtom, kIDHDataTypeAtomType, 599 0, 0, sizeof( type), &type, nil); 600 FailWithVal( err != noErr, Exit, err); 601 602 size = (standard == ntscIn)?kNTSCCompressedBufferSize:kPALCompressedBufferSize; 603 err = QTInsertChild( container, configAtom, kIDHDataSizeAtomType, 604 0, 0, sizeof( size), &size, nil); 605 FailWithVal( err != noErr, Exit, err); 606 607 size = (standard == ntscIn)?kNTSCCompressedBufferSize:kPALCompressedBufferSize; 608 err = QTInsertChild( container, configAtom, kIDHDataBufferSizeAtomType, 609 0, 0, sizeof( size), &size, nil); 610 FailWithVal( err != noErr, Exit, err); 611 612 interval = 29.97; 613 err = QTInsertChild( container, configAtom, kIDHDataIntervalAtomType, 614 0, 0, sizeof( interval), &interval, nil); 615 FailWithVal( err != noErr, Exit, err); 616 617 direction = kIDHDataTypeIsInputAndOutput; 618 err = QTInsertChild( container, configAtom, kIDHDataIODirectionAtomType, 619 0, 0, sizeof( direction), &direction, nil); 620 FailWithVal( err != noErr, Exit, err); 621 622 size = 2; 623 err = QTInsertChild( container, configAtom, kIDHSoundChannelCountAtomType, 624 0, 0, sizeof( size), &size, nil); 625 FailWithVal( err != noErr, Exit, err); 626 627 size = 2; 628 err = QTInsertChild( container, configAtom, kIDHSoundSampleSizeAtomType, 629 0, 0, sizeof( size), &size, nil); 630 FailWithVal( err != noErr, Exit, err); 631 632 rate = rate44khz; 633 err = QTInsertChild( container, configAtom, kIDHSoundSampleRateAtomType, 634 0, 0, sizeof( rate), &rate, nil); 635 FailWithVal( err != noErr, Exit, err); 636 637Exit: 638 return err; 639} // sound 1 config 640 641static OSStatus setup32kAudioAtoms( QTAtomContainer container, QTAtom isocAtom, UInt32 standard) 642{ 643 OSStatus err; 644 QTAtom configAtom; 645 646 StringPtr name; 647 OSType type; 648 long size; 649 Fixed rate; 650 float interval; 651 long direction; 652 653 // create a vide NTSC mode 654 err = QTInsertChild( container, isocAtom, kIDHIsochModeAtomType, 655 0, 0, 0, nil, &configAtom); 656 FailWithVal( err != noErr, Exit, err); 657 658 type = kIDHSoundMediaAtomType; 659 err = QTInsertChild( container, configAtom, kIDHIsochMediaType, 660 0, 0, sizeof( type), &type, nil); 661 FailWithVal( err != noErr, Exit, err); 662 663 name = "\pDV-32khz"; 664 err = QTInsertChild( container, configAtom, kIDHNameAtomType, 665 0, 0, name[0]+1, name, nil); 666 FailWithVal( err != noErr, Exit, err); 667 668 type = 'DV32'; 669 err = QTInsertChild( container, configAtom, kIDHDataTypeAtomType, 670 0, 0, sizeof( type), &type, nil); 671 FailWithVal( err != noErr, Exit, err); 672 673 size = (standard == ntscIn)?kNTSCCompressedBufferSize:kPALCompressedBufferSize; 674 err = QTInsertChild( container, configAtom, kIDHDataSizeAtomType, 675 0, 0, sizeof( size), &size, nil); 676 FailWithVal( err != noErr, Exit, err); 677 678 size = (standard == ntscIn)?kNTSCCompressedBufferSize:kPALCompressedBufferSize; 679 err = QTInsertChild( container, configAtom, kIDHDataBufferSizeAtomType, 680 0, 0, sizeof( size), &size, nil); 681 FailWithVal( err != noErr, Exit, err); 682 683 interval = 29.97; 684 err = QTInsertChild( container, configAtom, kIDHDataIntervalAtomType, 685 0, 0, sizeof( interval), &interval, nil); 686 FailWithVal( err != noErr, Exit, err); 687 688 direction = kIDHDataTypeIsInputAndOutput; 689 err = QTInsertChild( container, configAtom, kIDHDataIODirectionAtomType, 690 0, 0, sizeof( direction), &direction, nil); 691 FailWithVal( err != noErr, Exit, err); 692 693 size = 4; 694 err = QTInsertChild( container, configAtom, kIDHSoundChannelCountAtomType, 695 0, 0, sizeof( size), &size, nil); 696 FailWithVal( err != noErr, Exit, err); 697 698 size = 2; 699 err = QTInsertChild( container, configAtom, kIDHSoundSampleSizeAtomType, 700 0, 0, sizeof( size), &size, nil); 701 FailWithVal( err != noErr, Exit, err); 702 703 rate = 32000 << 16; 704 err = QTInsertChild( container, configAtom, kIDHSoundSampleRateAtomType, 705 0, 0, sizeof( rate), &rate, nil); 706 FailWithVal( err != noErr, Exit, err); 707 708Exit: 709 return err; 710} // sound 2 config 711 712static OSStatus setup44kAudioAtoms( QTAtomContainer container, QTAtom isocAtom, UInt32 standard) 713{ 714 OSStatus err; 715 QTAtom configAtom; 716 717 StringPtr name; 718 OSType type; 719 long size; 720 Fixed rate; 721 float interval; 722 long direction; 723 724 // create a vide NTSC mode 725 err = QTInsertChild( container, isocAtom, kIDHIsochModeAtomType, 726 0, 0, 0, nil, &configAtom); 727 FailWithVal( err != noErr, Exit, err); 728 729 type = kIDHSoundMediaAtomType; 730 err = QTInsertChild( container, configAtom, kIDHIsochMediaType, 731 0, 0, sizeof( type), &type, nil); 732 FailWithVal( err != noErr, Exit, err); 733 734 name = "\pDV-44khz"; 735 err = QTInsertChild( container, configAtom, kIDHNameAtomType, 736 0, 0, name[0]+1, name, nil); 737 FailWithVal( err != noErr, Exit, err); 738 739 type = 'DV44'; 740 err = QTInsertChild( container, configAtom, kIDHDataTypeAtomType, 741 0, 0, sizeof( type), &type, nil); 742 FailWithVal( err != noErr, Exit, err); 743 744 size = (standard == ntscIn)?kNTSCCompressedBufferSize:kPALCompressedBufferSize; 745 err = QTInsertChild( container, configAtom, kIDHDataSizeAtomType, 746 0, 0, sizeof( size), &size, nil); 747 FailWithVal( err != noErr, Exit, err); 748 749 size = (standard == ntscIn)?kNTSCCompressedBufferSize:kPALCompressedBufferSize; 750 err = QTInsertChild( container, configAtom, kIDHDataBufferSizeAtomType, 751 0, 0, sizeof( size), &size, nil); 752 FailWithVal( err != noErr, Exit, err); 753 754 interval = 29.97; 755 err = QTInsertChild( container, configAtom, kIDHDataIntervalAtomType, 756 0, 0, sizeof( interval), &interval, nil); 757 FailWithVal( err != noErr, Exit, err); 758 759 direction = kIDHDataTypeIsInputAndOutput; 760 err = QTInsertChild( container, configAtom, kIDHDataIODirectionAtomType, 761 0, 0, sizeof( direction), &direction, nil); 762 FailWithVal( err != noErr, Exit, err); 763 764 size = 4; 765 err = QTInsertChild( container, configAtom, kIDHSoundChannelCountAtomType, 766 0, 0, sizeof( size), &size, nil); 767 FailWithVal( err != noErr, Exit, err); 768 769 size = 2; 770 err = QTInsertChild( container, configAtom, kIDHSoundSampleSizeAtomType, 771 0, 0, sizeof( size), &size, nil); 772 FailWithVal( err != noErr, Exit, err); 773 774 rate = 44100 << 16; 775 err = QTInsertChild( container, configAtom, kIDHSoundSampleRateAtomType, 776 0, 0, sizeof( rate), &rate, nil); 777 FailWithVal( err != noErr, Exit, err); 778 779Exit: 780 return err; 781} // sound 3 config 782 783static OSStatus cameraNameLookup(DeviceDescriptionPtr pDeviceDescription, UInt8 *name) 784{ 785 OSStatus result = noErr; 786 int len = strlen(pDeviceDescription->fDevice->fName); 787 788#ifdef kIDH_Verbose_Debug_Logging 789 syslog(LOG_INFO, "IDH: cameraNameLookup begin\n"); 790#endif 791 792 if(len) 793 { 794 if(len>255) 795 len = 255; 796 name[0] = len; 797 BlockMoveData(pDeviceDescription->fDevice->fName, name+1, len); 798 } 799 else 800 { 801 // Look up vendor ID in resource list 802 UInt32 vendorID = pDeviceDescription->fDevice->fGUID >> 40; 803 CFStringRef cameraName = CFStringCreateWithCString(kCFAllocatorDefault, "DV", CFStringGetSystemEncoding()); 804 SInt16 refNum = -1, localizedRefNum = -1; 805 Boolean stringFound = false; 806 807 CFBundleRef myRef = 0; 808 809 // read vendor id resource and look for matching guid 810 if(pDeviceDescription->fGlobals->fBundleID == 0) 811 { 812 myRef = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.IOFWDVComponents")); 813 CFBundleOpenBundleResourceFiles(myRef, &refNum, &localizedRefNum); 814 pDeviceDescription->fGlobals->fBundleID = myRef; 815 pDeviceDescription->fGlobals->fBundleResRef = localizedRefNum; 816 } 817 else 818 { 819 myRef = pDeviceDescription->fGlobals->fBundleID; 820 } 821 822 if( myRef ) 823 { 824 // form the key 825 CFStringRef keyRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("VENDOR_%08X"), vendorID); 826 827 if( keyRef ) 828 { 829 // lookup the value 830 CFStringRef localizedString = CFBundleCopyLocalizedString ( myRef, keyRef, cameraName, NULL ); 831 832 if ( localizedString ) 833 { 834 CFMutableArrayRef names = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 835 836 if (localizedString && CFStringGetLength(localizedString) > 0) 837 { 838 CFArrayAppendValue(names, (const void *)localizedString); 839 } 840 841 if (cameraName && CFStringGetLength(cameraName) > 0) 842 { 843 CFArrayAppendValue(names, (const void *)cameraName); 844 } 845 846 CFStringRef vendorAndCameraName = CFStringCreateByCombiningStrings(kCFAllocatorDefault, names, CFSTR(" ")); 847 848 if ( vendorAndCameraName ) 849 { 850 stringFound = CFStringGetPascalString ( vendorAndCameraName, name, sizeof(name), CFStringGetSystemEncoding()); 851 CFRelease( vendorAndCameraName ); 852 } 853 854 CFRelease(names); 855 CFRelease( localizedString ); 856 } 857 858 CFRelease( keyRef ); 859 } 860 } 861 862 if(stringFound == false) 863 { 864 CFStringGetPascalString ( CFSTR("DV"), name, sizeof(name), CFStringGetSystemEncoding()); 865 } 866 867 CFRelease(cameraName); 868 } 869 870#ifdef kIDH_Verbose_Debug_Logging 871 syslog(LOG_INFO, "IDH: cameraNameLookup end\n"); 872#endif 873 874 return result; 875} 876 877static OSStatus postEvent(IsochComponentGlobalsPtr g, IDHDeviceID deviceID, IDHEvent event) 878{ 879 UInt32 i; 880 IDHDeviceConnectionEvent connectionEvent; 881 OSStatus error = noErr; 882 883 // We now have two broad classifications of events - ones that need to be 884 // reported ASAP, which are stream related: 885 // 886 // kIDHPrivateEventReadComplete 887 // kIDHPrivateEventWriteComplete 888 // 889 // and ones that are device management related, whose notifications will 890 // probably generate massive amounts of task-level only Toolbox calls: 891 // 892 // kIDHEventDeviceAdded 893 // kIDHEventDeviceRemoved 894 // kIDHEventReadEnabled 895 // kIDHEventReadDisabled 896 // kIDHEventWriteEnabled 897 // kIDHEventWriteDisabled 898 // 899 // kIDHPrivateEventReadComplete and kIDHPrivateEventWriteComplete are posted to a secondary 900 // interrupt handler. All other events are handled immediately. 901 902 903 RecordEventLogger( 'isoc', 'post', deviceID, event); 904 905 for (i = 0; i < kMaxNotifications ; ++i) 906 { 907 ClientNotification* clientNotification = &g->clientNotification[i]; 908 IDHDeviceID clientDeviceID = clientNotification->deviceID; 909 IDHEvent wantedEvents = clientNotification->events; 910 if (event & wantedEvents) 911 { 912 // Send notification if the device matches the client's desired device 913 // or client specified all devices. 914 if ((kIDHDeviceIDEveryDevice == clientDeviceID) || 915 (deviceID == clientDeviceID) ) 916 { 917 // we currently only support a one-shot notification, like clock callbacks 918 clientNotification->events = 0; 919 920 switch(event) 921 { 922 case kIDHEventDeviceChanged: 923 case kIDHEventDeviceAdded: 924 case kIDHEventDeviceRemoved: 925 case kIDHEventReadEnabled: 926 case kIDHEventReadDisabled: 927 case kIDHEventWriteEnabled: 928 case kIDHEventWriteDisabled: 929 930 connectionEvent.eventHeader.event = event; 931 connectionEvent.eventHeader.deviceID = deviceID; 932 connectionEvent.eventHeader.notificationID = 933 (UInt32)clientNotification; 934 935 (*clientNotification->notificationProc) 936 ((IDHGenericEvent*)&connectionEvent, 937 clientNotification->userData); 938 break; 939 940 default: 941 RecordEventLogger( 'isoc', 'post', '????', event); 942 break; 943 } 944 945 } 946 } 947 } 948 949 RecordEventLogger( 'isoc', 'post', 'end ', event); 950 return error; 951 952} 953 954static void deviceMessage(void * refcon, UInt32 messageType, void *messageArgument) 955{ 956 957#ifdef kIDH_Verbose_Debug_Logging 958 syslog(LOG_INFO, "IDH: deviceMessage begin\n"); 959#endif 960 961 // refcon is 1-based device index. 962 DeviceDescriptionPtr deviceDescriptionPtr = &globals.deviceDescription[(int)refcon-1]; 963 //syslog(LOG_INFO,"Got message: refcon %d, type 0x%x arg %p\n", 964 // refcon, messageType, messageArgument); 965 if(messageType == kIOFWMessageServiceIsRequestingClose) { 966 //syslog(LOG_INFO,"Device # %d, ptr %p requesting close\n", 967 // refcon-1, deviceDescriptionPtr); 968 deviceDescriptionPtr->fActive = false; 969 if(deviceDescriptionPtr->deviceControlInstance) { 970 DeviceControlDisableAVCTransactions(deviceDescriptionPtr->deviceControlInstance); 971 DeviceControlSetDeviceConnectionID(deviceDescriptionPtr->deviceControlInstance, 972 kIDHInvalidDeviceID); 973 } 974 if(deviceDescriptionPtr->fDevice) { 975 976 if(deviceDescriptionPtr->fRead != NULL) 977 disableRead(deviceDescriptionPtr); 978 if(deviceDescriptionPtr->fWrite != NULL) 979 disableWrite(deviceDescriptionPtr); 980 981 DVDeviceTerminate(deviceDescriptionPtr->fDevice); 982 deviceDescriptionPtr->fDevice = NULL; 983 } 984 // post a DV event to let the curious know... 985 postEvent(deviceDescriptionPtr->fGlobals, (IDHDeviceID)deviceDescriptionPtr, kIDHEventDeviceRemoved); 986 } 987 988#ifdef kIDH_Verbose_Debug_Logging 989 syslog(LOG_INFO, "IDH: deviceMessage end\n"); 990#endif 991} 992 993 994static OSStatus enableRead(DeviceDescription *deviceDescriptionPtr) 995{ 996 OSStatus result; 997 998#ifdef kIDH_Verbose_Debug_Logging 999 syslog(LOG_INFO, "IDH: enableRead begin\n"); 1000#endif 1001 1002 deviceDescriptionPtr->fNumOutputFrames = 4; 1003 deviceDescriptionPtr->fRead = DVAllocRead(deviceDescriptionPtr->fDevice, globals.fDVThread); 1004 1005 // Get the current device's output-signal mode, and set the signal mode approprietely 1006 { 1007 OSStatus err; 1008 DVCTransactionParams transaction; 1009 UInt8 out[8]; 1010 UInt8 in[8]; 1011 1012 out[0] = kAVCStatusInquiryCommand; 1013 out[1] = kAVCUnitAddress; 1014 out[2] = kAVCOutputPlugSignalFormatOpcode; 1015 out[3] = 0; // Plug 1016 out[4] = out[5] = out[6] = out[7] = 0xff; 1017 transaction.commandBufferPtr = out; 1018 transaction.commandLength = sizeof(out); 1019 transaction.responseBufferPtr = in; 1020 transaction.responseBufferSize = sizeof(in); 1021 transaction.responseHandler = NULL; 1022 1023 err = doAVCTransaction(deviceDescriptionPtr, &transaction); 1024 if(err == noErr && in[0] == 0xc) 1025 { 1026 // Set the mode based on the response from this command 1027 result = DVReadSetSignalMode(deviceDescriptionPtr->fRead, in[5]); 1028 } 1029 } 1030 1031 result = DVReadAllocFrames(deviceDescriptionPtr->fRead, deviceDescriptionPtr->fNumOutputFrames, 1032 &deviceDescriptionPtr->fReadSharedVars, deviceDescriptionPtr->bufMem); 1033 if(result == noErr) 1034 result = DVReadStart(deviceDescriptionPtr->fRead); 1035 if(result == noErr) { 1036 deviceDescriptionPtr->fOldDrop = deviceDescriptionPtr->fReadSharedVars->fDroppedFrames; 1037 DVSetTimeoutTime(deviceDescriptionPtr->fGlobals->fDVThread, CFAbsoluteTimeGetCurrent() + kDCLBlockTime); 1038 } 1039 1040#ifdef kIDH_Verbose_Debug_Logging 1041 syslog(LOG_INFO, "IDH: enableRead end\n"); 1042#endif 1043 1044 return result; 1045} 1046 1047static OSStatus disableRead(DeviceDescription *deviceDescriptionPtr) 1048{ 1049 1050#ifdef kIDH_Verbose_Debug_Logging 1051 syslog(LOG_INFO, "IDH: disableRead begin\n"); 1052#endif 1053 1054 if(deviceDescriptionPtr->fRead) { 1055 DVReadStop(deviceDescriptionPtr->fRead); 1056 DVReadFreeFrames(deviceDescriptionPtr->fRead); 1057 DVReadFree(deviceDescriptionPtr->fRead); 1058 deviceDescriptionPtr->fRead = NULL; 1059 } 1060 1061#ifdef kIDH_Verbose_Debug_Logging 1062 syslog(LOG_INFO, "IDH: disableRead end\n"); 1063#endif 1064 1065 return noErr; 1066} 1067 1068static OSStatus enableWrite(DeviceDescription *deviceDescriptionPtr) 1069{ 1070 OSStatus result; 1071 int i; 1072 1073#ifdef kIDH_Verbose_Debug_Logging 1074 syslog(LOG_INFO, "IDH: enableWrite begin\n"); 1075#endif 1076 1077 deviceDescriptionPtr->fNumOutputFrames = 4; 1078 deviceDescriptionPtr->fWrite = DVAllocWrite(deviceDescriptionPtr->fDevice, 1079 deviceDescriptionPtr->fGlobals->fDVThread); 1080 result = DVWriteSetSignalMode(deviceDescriptionPtr->fWrite, deviceDescriptionPtr->fOutputMode); 1081 result = DVWriteAllocFrames(deviceDescriptionPtr->fWrite, deviceDescriptionPtr->fNumOutputFrames, 1082 &deviceDescriptionPtr->fWriteSharedVars, deviceDescriptionPtr->bufMem); 1083 deviceDescriptionPtr->fDCLBuffer = DVWriteGetDCLBuffer(deviceDescriptionPtr->fWrite, 1084 &deviceDescriptionPtr->fSharedWriteVars); 1085 deviceDescriptionPtr->fBufSize = (deviceDescriptionPtr->fDevice->standard == ntscIn)? 1086 kNTSCCompressedBufferSize:kPALCompressedBufferSize; 1087 if((deviceDescriptionPtr->fOutputMode & 0x7c) == 4) 1088 deviceDescriptionPtr->fBufSize /= 2; // SDL 1089 else if((deviceDescriptionPtr->fOutputMode & 0x7c) == 0x74) 1090 deviceDescriptionPtr->fBufSize *= 2; // DVCPro50 1091 1092 deviceDescriptionPtr->fOldWriteTimeStamps = 1093 (UInt32 *)NewPtr(deviceDescriptionPtr->fSharedWriteVars->fNumGroups*sizeof(UInt32)); 1094 for(i=0; i<deviceDescriptionPtr->fSharedWriteVars->fNumGroups; i++) { 1095 deviceDescriptionPtr->fOldWriteTimeStamps[i] = deviceDescriptionPtr->fSharedWriteVars->fTimeStampPtrs[i]; 1096 } 1097 deviceDescriptionPtr->fDCLReadPos = 0; 1098 deviceDescriptionPtr->fBufWritePos = 0; 1099 deviceDescriptionPtr->fFrameBufferPos = 0; 1100 deviceDescriptionPtr->fDCLSavedWritePos = NULL; 1101 deviceDescriptionPtr->fDCLSavedPacketNum = 0; 1102 1103 deviceDescriptionPtr->fWaitingStartWrite = 1; 1104 deviceDescriptionPtr->fWriteSharedVars->fReader = deviceDescriptionPtr->fWriteSharedVars->fWriter = 0; 1105 deviceDescriptionPtr->fOldDrop = deviceDescriptionPtr->fWriteSharedVars->fDroppedFrames; 1106 1107 DVSetTimeoutTime(deviceDescriptionPtr->fGlobals->fDVThread, CFAbsoluteTimeGetCurrent() + kDCLBlockTime); 1108 1109#ifdef kIDH_Verbose_Debug_Logging 1110 syslog(LOG_INFO, "IDH: enableWrite end\n"); 1111#endif 1112 1113 return result; 1114} 1115 1116static void disableWrite(DeviceDescription *deviceDescriptionPtr) 1117{ 1118#ifdef kIDH_Verbose_Debug_Logging 1119 syslog(LOG_INFO, "IDH: disableWrite begin\n"); 1120#endif 1121 1122 if (deviceDescriptionPtr->fWrite) 1123 { 1124 DVWriteStop(deviceDescriptionPtr->fWrite); 1125 DVWriteFreeFrames(deviceDescriptionPtr->fWrite); 1126 DVWriteFree(deviceDescriptionPtr->fWrite); 1127 deviceDescriptionPtr->fWrite = NULL; 1128 if(deviceDescriptionPtr->fOldWriteTimeStamps) 1129 { 1130 DisposePtr((Ptr)deviceDescriptionPtr->fOldWriteTimeStamps); 1131 deviceDescriptionPtr->fOldWriteTimeStamps = NULL; 1132 } 1133 } 1134 else 1135 { 1136 syslog(LOG_INFO, "IDH: disableWrite called with deviceDescriptionPtr->fWrite == NULL\n"); 1137 } 1138 1139#ifdef kIDH_Verbose_Debug_Logging 1140 syslog(LOG_INFO, "IDH: disableWrite end\n"); 1141#endif 1142 1143} 1144 1145static OSStatus sendMsg(IsochComponentInstancePtr ih, RequestFunc request, void *params) 1146{ 1147 return DVRequest(globals.fDVThread, request, ih, (UInt32)params); 1148} 1149 1150static OSStatus doAVCTransaction(DeviceDescriptionPtr deviceDescriptionPtr, 1151 DVCTransactionParams* inTransaction) 1152{ 1153 IOReturn result = kIDHErrDeviceNotConfigured; 1154 if(deviceDescriptionPtr->fConnected) { 1155 if(!deviceDescriptionPtr->fActive) 1156 return kIDHErrDeviceDisconnected; 1157 if(deviceDescriptionPtr->fNoAVC > 1) 1158 return kIOReturnTimeout; 1159 else { 1160 result = (*deviceDescriptionPtr->fDevice->fAVCInterface)->AVCCommand(deviceDescriptionPtr->fDevice->fAVCInterface, 1161 inTransaction->commandBufferPtr, inTransaction->commandLength, 1162 inTransaction->responseBufferPtr, &inTransaction->responseBufferSize); 1163 1164 if(result == kIOReturnTimeout) 1165 deviceDescriptionPtr->fNoAVC++; 1166 else 1167 deviceDescriptionPtr->fNoAVC = 0; 1168 } 1169 } 1170 return result; 1171} 1172 1173 1174static void deviceArrived(void *refcon, DVDevice *device, UInt32 index, UInt32 refound) 1175{ 1176 IsochComponentGlobalsPtr g = (IsochComponentGlobalsPtr)refcon; 1177 OSStatus result = noErr; 1178 QTAtom deviceAtom, isocAtom; 1179 DeviceDescriptionPtr deviceDescriptionPtr; 1180 IDHDeviceStatus deviceStatus; 1181 ComponentDescription clkDesc; 1182 1183#ifdef kIDH_Verbose_Debug_Logging 1184 syslog(LOG_INFO, "IDH: deviceArrived begin\n"); 1185#endif 1186 1187 RecordEventLogger( 'isoc', 'addv', (int)g, index); 1188 //syslog(LOG_INFO,"deviceArrived: device 0x%x\n", index); 1189 1190 ++g->seed; 1191 1192 // device index is 1-based. 1193 deviceDescriptionPtr = &g->deviceDescription[index-1]; 1194 1195 do { 1196 // look for existing device 1197 if( refound) { 1198 // Get device back to old state, set fActive to true after everything is restored, not before! 1199 deviceDescriptionPtr->fDevice = device; 1200 if(deviceDescriptionPtr->fConnected) { 1201 IOReturn result; 1202 result = DVDeviceOpen(g->fDVThread, deviceDescriptionPtr->fDevice); 1203 if(result == kIOReturnSuccess) { 1204 if(deviceDescriptionPtr->readLocks) { 1205 enableRead(deviceDescriptionPtr); 1206 } 1207 if(deviceDescriptionPtr->writeLocks) { 1208 enableWrite(deviceDescriptionPtr); 1209 } 1210 } 1211 } 1212 deviceDescriptionPtr->fActive = true; 1213 } 1214 else { 1215 Str255 cameraName; 1216 1217 bzero(deviceDescriptionPtr, sizeof(*deviceDescriptionPtr)); 1218 deviceDescriptionPtr->fActive = true; 1219 deviceDescriptionPtr->fGlobals = g; 1220 deviceDescriptionPtr->fDevice = device; 1221#ifdef DRAWRINGBUFFERGRAPH 1222 deviceDescriptionPtr->fScreenBaseAddr = 0; 1223#endif 1224 RecordEventLogger( 'isoc', 'updt', 'add ', 'reg '); 1225 1226 // add its description 1227 g->nDevices++; 1228 1229 //*deviceID = ih->nDevices; 1230 1231 1232 // find clock component 1233 // wouldn't it be better for us to open an instance on OpenDevice, set FWClockPrivLocalReference, etc. 1234 clkDesc.componentType = clockComponentType; 1235 clkDesc.componentSubType = 'fwcy'; 1236 clkDesc.componentManufacturer = 'appl'; 1237 clkDesc.componentFlags = 0L; 1238 clkDesc.componentFlagsMask = 0L; 1239 1240 deviceDescriptionPtr->clock = FindNextComponent( deviceDescriptionPtr->clock, &clkDesc); // Look for FireWire clock component 1241 FailMessage( deviceDescriptionPtr->clock == nil); 1242 // create device description atom structure 1243 result = QTNewAtomContainer( &deviceDescriptionPtr->deviceContainer); 1244 if( result != noErr)break; 1245 1246 // add a device atom 1247 result = QTInsertChild( deviceDescriptionPtr->deviceContainer, kParentAtomIsContainer, kIDHDeviceAtomType, 1248 (long) deviceDescriptionPtr, 0, 0, nil, &deviceAtom); 1249 if( result != noErr)break; 1250 1251 // add the unique 64 bit FireWire GUID id to device atom 1252 result = QTInsertChild( deviceDescriptionPtr->deviceContainer, deviceAtom, kIDHUniqueIDType, 1253 0, 0, sizeof(device->fGUID), &device->fGUID, nil); 1254 if( result != noErr)break; 1255 1256 result = cameraNameLookup(deviceDescriptionPtr, cameraName); 1257 if( result != noErr)break; 1258 result = QTInsertChild( deviceDescriptionPtr->deviceContainer, deviceAtom, kIDHNameAtomType, 1259 0, 0, cameraName[0] + 1, cameraName, nil); 1260 1261 // add the IDH unique id to device atom 1262 result = QTInsertChild( deviceDescriptionPtr->deviceContainer, deviceAtom, kIDHDeviceIDType, 1263 0, 0, sizeof(deviceDescriptionPtr), &deviceDescriptionPtr, nil); 1264 if( result != noErr)break; 1265 1266 // create a device status structure and add it to the device atom 1267 deviceStatus.version = 0x200; 1268 deviceStatus.physicallyConnected = true; 1269 deviceStatus.readEnabled = false; 1270 deviceStatus.writeEnabled = false; 1271 deviceStatus.exclusiveAccess = false; 1272 deviceStatus.currentBandwidth = 0; 1273 deviceStatus.currentChannel = 0; 1274 deviceStatus.inputStandard = deviceDescriptionPtr->fDevice->standard; 1275 deviceStatus.inputFormat = kIDHDV_SD; 1276 1277 deviceStatus.outputFormats = deviceDescriptionPtr->fDevice->fDVFormats; 1278 deviceStatus.deviceActive = false; 1279 1280 result = QTInsertChild( deviceDescriptionPtr->deviceContainer, deviceAtom, kDVDeviceInfo, 1281 0, 0, sizeof( IDHDeviceStatus), &deviceStatus, nil); 1282 if( result != noErr)break; 1283 1284 // add isoch descriptions to structure 1285 result = QTInsertChild( deviceDescriptionPtr->deviceContainer, deviceAtom, kIDHIsochServiceAtomType, 1286 0, 0, 0, nil, &isocAtom); 1287 if( result != noErr)break; 1288 1289 // add the configs to the isoc atom 1290 result = setupVideoAtoms( deviceDescriptionPtr->deviceContainer, isocAtom, 1291 deviceDescriptionPtr->fDevice->standard, false, 1292 deviceDescriptionPtr->fDevice->fDVFormats & (1 << kIDHDVCPro_25)); 1293 if( result != noErr)break; 1294 if(deviceDescriptionPtr->fDevice->fDVFormats & (1 << kIDHDV_SDL)) { 1295 result = setupVideoAtoms( deviceDescriptionPtr->deviceContainer, isocAtom, 1296 deviceDescriptionPtr->fDevice->standard, true, 1297 deviceDescriptionPtr->fDevice->fDVFormats & (1 << kIDHDVCPro_25)); 1298 if( result != noErr)break; 1299 } 1300 1301 if( deviceDescriptionPtr->fDevice->standard == ntscIn) 1302 { 1303 result = setup48kAudioAtoms( deviceDescriptionPtr->deviceContainer, isocAtom, 1304 ntscIn); 1305 if( result != noErr)break; 1306 1307 result = setup32kAudioAtoms( deviceDescriptionPtr->deviceContainer, isocAtom, 1308 ntscIn); 1309 if( result != noErr)break; 1310 } 1311 else // PAL audio 1312 { 1313 result = setup44kAudioAtoms( deviceDescriptionPtr->deviceContainer, isocAtom, 1314 deviceDescriptionPtr->fDevice->standard); 1315 if( result != noErr)break; 1316 } 1317 1318 // Set output signal mode, default to standard DV 1319 deviceDescriptionPtr->fOutputMode = 0; 1320 if(deviceDescriptionPtr->fDevice->standard != ntscIn) 1321 deviceDescriptionPtr->fOutputMode |= 0x80; 1322 } 1323 } while(false); 1324 1325 postEvent(g, (IDHDeviceID)deviceDescriptionPtr, kIDHEventDeviceAdded); 1326 1327#ifdef kIDH_Verbose_Debug_Logging 1328 syslog(LOG_INFO, "IDH: deviceArrived end\n"); 1329#endif 1330 1331} 1332 1333static UInt8 *getNextFrame(DeviceDescription *deviceDescriptionPtr, IsochComponentInstancePtr client, int slack, int waiting) 1334{ 1335 ComponentResult err = noErr; 1336 IDHParameterBlock *pb; 1337 1338 pb = client->fActiveHead; 1339 if(pb && !waiting) { 1340 if(deviceDescriptionPtr->fWaitingStartWrite) { 1341 IOReturn res; 1342 res = DVWriteStart(deviceDescriptionPtr->fWrite); 1343 //if(res == kIOReturnNoResources || res == kIOReturnNoSpace || res == kIOFireWireBusReset) { 1344 if(res != kIOReturnSuccess) { 1345 //syslog(LOG_INFO, "start write returned %x\n", res); 1346 err = kIDHErrDeviceCantWrite; 1347 deviceDescriptionPtr->fWaitingStartWrite = 2; 1348 } 1349 else 1350 deviceDescriptionPtr->fWaitingStartWrite = 0; 1351 } 1352 1353 client->fActiveHead = (IDHParameterBlock *)pb->reserved1; 1354 if(client->fActiveHead == NULL) 1355 client->fActiveTail = NULL; 1356 pb->actualCount = deviceDescriptionPtr->fBufSize; 1357 pb->result = err; 1358 1359 //syslog(LOG_INFO, "write callback, buffer = %p\n", pb->buffer); 1360 //syslog(LOG_INFO, "pb %p = req %d actual %d\n", 1361 // pb, pb->requestedCount, pb->actualCount); 1362 if(pb->completionProc) { 1363 err = pb->completionProc((IDHGenericEvent *)pb, pb->refCon); 1364 if(err != noErr) { 1365 syslog(LOG_INFO, "write callback for pb %p returned error %d\n", pb, err); 1366 } 1367 } 1368 } 1369 if(client->fActiveHead) { 1370 pb = client->fActiveHead; 1371 // We have to copy the buffer because QuickTime only uses one buffer to send data to us, 1372 // so if they drop a frame we don't have anything to send (because they are overwriting the 1373 // buffer with new data) 1374 bcopy(pb->buffer, (UInt8 *)deviceDescriptionPtr->bufMem[0], deviceDescriptionPtr->fBufSize); 1375 } 1376 else { 1377 //syslog(LOG_INFO, "Waiting for next IDHWrite, %d DCL blocks free\n", slack); 1378 if(slack < 3) { 1379 // No new frame to write, re-use the last one, after muting the audio 1380 deviceDescriptionPtr->fWriteSharedVars->fDroppedFrames++; 1381 dropMsg(deviceDescriptionPtr, deviceDescriptionPtr->fWriteSharedVars->fDroppedFrames); 1382 DVSilenceFrame(deviceDescriptionPtr->fOutputMode, (UInt8 *)deviceDescriptionPtr->bufMem[0]); 1383 } 1384 else { 1385 return NULL; // OK to wait for next IDHWrite 1386 } 1387 } 1388 deviceDescriptionPtr->fFrameBufferPos = 0; 1389 return (UInt8 *)deviceDescriptionPtr->bufMem[0]; 1390} 1391 1392static int fillDCLGroup(DeviceDescription *deviceDescriptionPtr, IsochComponentInstancePtr client, int group, int slack) 1393{ 1394 UInt8 *dclPtr; 1395 UInt8 *dataPtr; 1396 UInt32 dataSize = deviceDescriptionPtr->fSharedWriteVars->fPacketDataSize; 1397 UInt32 packetSize = deviceDescriptionPtr->fSharedWriteVars->fAlignedPacketSize; 1398 int i; 1399 int start; 1400 // If we're waiting for a new frame, restore the current DCL pointer 1401 if(deviceDescriptionPtr->fDCLSavedWritePos != NULL) { 1402 dclPtr = deviceDescriptionPtr->fDCLSavedWritePos; 1403 dataPtr = getNextFrame(deviceDescriptionPtr, client, slack, true); 1404 //syslog(LOG_INFO, "Waiting for next frame, new frame = 0x%x\n", dataPtr); 1405 if(dataPtr == NULL) 1406 return 0; // Waiting for next frame. 1407 deviceDescriptionPtr->fDCLSavedWritePos = NULL; // Got a frame, carry on 1408 start = deviceDescriptionPtr->fDCLSavedPacketNum; 1409 deviceDescriptionPtr->fDCLSavedPacketNum = 0; 1410 } 1411 else { 1412 dclPtr = deviceDescriptionPtr->fDCLBuffer + deviceDescriptionPtr->fSharedWriteVars->fDataOffset[group]; 1413 start = 0; 1414 } 1415 1416 if(deviceDescriptionPtr->fWaitingStartWrite) { 1417 if(!client->fActiveHead) { 1418 return 0; // No data, not running yet. 1419 } 1420 else { 1421 bcopy(client->fActiveHead->buffer, (UInt8 *)deviceDescriptionPtr->bufMem[0], 1422 deviceDescriptionPtr->fBufSize); 1423 } 1424 } 1425 dataPtr = (UInt8 *)deviceDescriptionPtr->bufMem[0]; 1426 1427 dataPtr += deviceDescriptionPtr->fFrameBufferPos; 1428 1429 for(i=start; i<deviceDescriptionPtr->fSharedWriteVars->fGroupSize; i++) { 1430 int pageOffset; 1431 // check for buffer crossing page 1432 pageOffset = (int) (dclPtr + packetSize) & 0x0fff; 1433 if (pageOffset < packetSize && pageOffset > 0) { 1434 // if it does, increment buffer pointer 1435 // and lop off page rollover to start at next page 1436 dclPtr += packetSize; 1437 dclPtr = (UInt8 *)((int)dclPtr & 0xfffff000); 1438 } 1439 bcopy(dataPtr, dclPtr+8, dataSize); 1440 dataPtr += dataSize; 1441 deviceDescriptionPtr->fFrameBufferPos += dataSize; 1442 dclPtr += packetSize; 1443 1444 if(deviceDescriptionPtr->fFrameBufferPos >= deviceDescriptionPtr->fBufSize) { 1445 dataPtr = getNextFrame(deviceDescriptionPtr, client, slack, false); 1446 if(dataPtr == NULL) { 1447 deviceDescriptionPtr->fDCLSavedWritePos = dclPtr; 1448 deviceDescriptionPtr->fDCLSavedPacketNum = i+1; 1449 return 0; // Waiting for next frame. 1450 } 1451 deviceDescriptionPtr->fFrameBufferPos = 0; 1452 deviceDescriptionPtr->fDCLSavedWritePos = NULL; 1453 deviceDescriptionPtr->fDCLSavedPacketNum = 0; 1454 } 1455 } 1456 return 1; 1457} 1458 1459static CFAbsoluteTime processWrites(DeviceDescription *deviceDescriptionPtr) 1460{ 1461 int i; 1462 int changed; 1463 int done; 1464 int emptyBlocks, ahead; 1465 int numGroups = deviceDescriptionPtr->fSharedWriteVars->fNumGroups; 1466 IsochComponentInstancePtr client; 1467 int pos; 1468 changed = 0; 1469 1470 client = deviceDescriptionPtr->fOpenClients[0]; 1471 1472 // If we failed to start writing last time through, reset to try again 1473 if(deviceDescriptionPtr->fWaitingStartWrite == 2) { 1474 for(i=0; i<deviceDescriptionPtr->fSharedWriteVars->fNumGroups; i++) { 1475 deviceDescriptionPtr->fOldWriteTimeStamps[i] = deviceDescriptionPtr->fSharedWriteVars->fTimeStampPtrs[i]; 1476 } 1477 //deviceDescriptionPtr->fDCLReadPos = 0; 1478 deviceDescriptionPtr->fBufWritePos = 0; 1479 deviceDescriptionPtr->fFrameBufferPos = 0; 1480 deviceDescriptionPtr->fDCLSavedWritePos = NULL; 1481 deviceDescriptionPtr->fDCLSavedPacketNum = 0; 1482 deviceDescriptionPtr->fWaitingStartWrite = 1; 1483 } 1484 // First find out where the hardware is 1485 pos = deviceDescriptionPtr->fSharedWriteVars->fDMAPos; 1486 ahead = deviceDescriptionPtr->fBufWritePos - pos; 1487 if(ahead < 0) 1488 ahead += numGroups; 1489 emptyBlocks = 4-ahead; 1490 //printf("pos %d wripos %d ahead %d\n", pos, deviceDescriptionPtr->fBufWritePos, ahead); 1491 1492 if(emptyBlocks>3) 1493 emptyBlocks = 3; 1494 1495 done = 0; 1496 for(i=0; i<emptyBlocks; i++) { 1497 int ok; 1498 ok = 1499 fillDCLGroup(deviceDescriptionPtr, client, (deviceDescriptionPtr->fBufWritePos + i) % numGroups, 1500 ahead+done); 1501 if(!ok) 1502 break; 1503 done += ok; 1504 } 1505 deviceDescriptionPtr->fBufWritePos += done; 1506 deviceDescriptionPtr->fBufWritePos %= numGroups; 1507 return CFAbsoluteTimeGetCurrent() + kDCLBlockTime; 1508} 1509 1510static CFAbsoluteTime processReads(DeviceDescription *deviceDescriptionPtr) 1511{ 1512 int doneFrames = 0; 1513 int frameIndex; 1514 IsochComponentInstancePtr client; 1515 int i; 1516 CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); 1517 UInt32 cycleTimeNow; 1518 SInt32 frameDiff; 1519 1520 (*deviceDescriptionPtr->fDevice->fDevInterface)-> 1521 GetCycleTime(deviceDescriptionPtr->fDevice->fDevInterface, &cycleTimeNow); 1522 1523 frameIndex = deviceDescriptionPtr->fReadSharedVars->fReader % deviceDescriptionPtr->fNumOutputFrames; 1524 if(deviceDescriptionPtr->fReadSharedVars->fReader < 1525 deviceDescriptionPtr->fReadSharedVars->fWriter) { 1526 UInt8 *buffer = deviceDescriptionPtr->bufMem[frameIndex]; 1527 UInt32 frameSize = deviceDescriptionPtr->fReadSharedVars->fFrameSize[frameIndex]; 1528 UInt32 frameTime = cycles(deviceDescriptionPtr->fReadSharedVars->fFrameTime[frameIndex]); 1529 1530 // Drop out if too soon 1531 //printf("Cycle now %x frame %x\n", cycles(cycleTimeNow), frameTime); 1532 frameDiff = cycles(cycleTimeNow) - frameTime; 1533 if(frameDiff < 0) 1534 frameDiff += 8000; 1535 1536 frameDiff = 200 - frameDiff; 1537 if(frameDiff > 0) { 1538 //printf("Delaying for %d cycles\n", frameDiff); 1539 return now + frameDiff/8000.0; 1540 } 1541 1542 // Lock buffer while we process stuff 1543 deviceDescriptionPtr->fBufferLocks[frameIndex]++; 1544 if(deviceDescriptionPtr->fOldDrop < deviceDescriptionPtr->fReadSharedVars->fDroppedFrames) { 1545 dropMsg(deviceDescriptionPtr, deviceDescriptionPtr->fReadSharedVars->fDroppedFrames); 1546 } 1547 for(i=0; i<kMaxDeviceClients; i++) { 1548 client = deviceDescriptionPtr->fOpenClients[i]; 1549 if(client) { 1550 if(client->fClientIndex != i) { 1551 syslog(LOG_INFO, "processReads: client %p of %p index is %d not %d\n", 1552 client, deviceDescriptionPtr, client->fClientIndex, i); 1553 } 1554 if(deviceDescriptionPtr->fReadStage == 1) { 1555 syslog(LOG_INFO, "client %d open, head/tail is %p/%p\n", i, client->fHead, client->fTail); 1556 } 1557 if(client->fHead) { 1558 IDHParameterBlock *pb = client->fHead; 1559 OSStatus err; 1560 1561 pb->actualCount = frameSize; 1562 1563 if(pb->buffer != nil) { 1564 // copy frame 1565 bcopy(buffer, pb->buffer, frameSize); 1566 } 1567 else { 1568 deviceDescriptionPtr->fBufferLocks[frameIndex]++; 1569 pb->buffer = buffer; 1570 } 1571 client->fHead = (IDHParameterBlock *)pb->reserved1; 1572 pb->reserved1 = frameTime; 1573 if(client->fHead == NULL) 1574 client->fTail = NULL; 1575 pb->result = noErr; 1576 1577 //syslog(LOG_INFO, "read callback, buffer = %p\n", pb->buffer); 1578 //syslog(LOG_INFO, "pb %p = req %d actual %d\n", 1579 // pb, pb->requestedCount, pb->actualCount); 1580 { 1581#ifdef TIMING 1582 CFAbsoluteTime cstart, cend; 1583 cstart = CFAbsoluteTimeGetCurrent(); 1584#endif 1585 err = pb->completionProc((IDHGenericEvent *)pb, pb->refCon); 1586#ifdef TIMING 1587 cend = CFAbsoluteTimeGetCurrent(); 1588 if(cend-cstart > 0.05) 1589 syslog(LOG_INFO, "read callback took %8.3f to %8.3f\n", cstart, cend); 1590#endif 1591 if(err != noErr) { 1592 syslog(LOG_INFO, "read callback for pb %p returned error %d\n", pb, err); 1593 } 1594 } 1595 doneFrames++; 1596 } 1597 } 1598 } 1599 // unlock buffer 1600 deviceDescriptionPtr->fBufferLocks[frameIndex]--; 1601 if(doneFrames && deviceDescriptionPtr->fBufferLocks[frameIndex] == 0) 1602 deviceDescriptionPtr->fReadSharedVars->fReader += 1; // release buffer 1603 } 1604 1605 return now+kDCLBlockTime; 1606} 1607 1608static ComponentResult queueWrite(IsochComponentInstancePtr client, void *params) 1609{ 1610 IDHParameterBlock *pb = (IDHParameterBlock *)params; 1611 1612 if(pb->buffer) { 1613 if(client->fActiveTail == NULL) { 1614 client->fActiveHead = pb; 1615 } 1616 else 1617 client->fActiveTail->reserved1 = (UInt32)pb; 1618 client->fActiveTail = pb; 1619 } 1620 else { 1621 if(client->fTail == NULL) 1622 client->fHead = pb; 1623 else 1624 client->fTail->reserved1 = (UInt32)pb; 1625 client->fTail = pb; 1626 } 1627 pb->reserved1 = 0; 1628 return noErr; 1629} 1630 1631static ComponentResult queueRead(IsochComponentInstancePtr client, void *params) 1632{ 1633 IDHParameterBlock *pbNew = (IDHParameterBlock *)params; 1634 if(client->fTail == NULL) 1635 client->fHead = pbNew; 1636 else 1637 client->fTail->reserved1 = (UInt32)pbNew; 1638 client->fTail = pbNew; 1639 pbNew->reserved1 = 0; 1640 1641 return noErr; 1642} 1643 1644ComponentResult processOpen(IsochComponentInstancePtr ih, void *params) 1645{ 1646 UInt32 permissions = (UInt32)params; 1647 ComponentResult result = noErr; 1648 int i; 1649 1650 DeviceDescription *deviceDescriptionPtr; 1651 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); // find the device 1652 FailWithVal( result != noErr, Exit, result); 1653 1654 FailWithAction( deviceDescriptionPtr->fActive == false, result = kIDHErrDeviceDisconnected, Exit); 1655 1656 // trying to reopen for read or write? 1657 if( ih->permissions & kIDHOpenForReadTransactions && permissions & kIDHOpenForReadTransactions) 1658 goto Exit; // don't do anything 1659 1660 if( ih->permissions & kIDHOpenForWriteTransactions && permissions & kIDHOpenForWriteTransactions) 1661 goto Exit; // don't do anything 1662 1663 // check for switching directions before opening 1664 FailWithAction( ih->permissions & kIDHOpenForReadTransactions && permissions & kIDHOpenForWriteTransactions, 1665 result = kIDHErrDeviceInUse, Exit); 1666 1667 FailWithAction( ih->permissions & kIDHOpenForWriteTransactions && permissions & kIDHOpenForReadTransactions, 1668 result = kIDHErrDeviceInUse, Exit); 1669 1670 // if user is opening for read, make sure device isn't already opened for writes 1671 if( permissions & kIDHOpenForReadTransactions) 1672 { 1673 FailWithAction( deviceDescriptionPtr->writeLocks, result = kIDHErrDeviceInUse, Exit); 1674 1675 if( deviceDescriptionPtr->readLocks == 0) 1676 { 1677 result = enableRead(deviceDescriptionPtr); 1678 FailWithVal( result != noErr, Exit, result); 1679 } 1680 1681 ++deviceDescriptionPtr->readLocks; // keep track of read count 1682 //syslog(LOG_INFO, "ih %p dev %p Opened for read, count %d\n", 1683 // ih, deviceDescriptionPtr, deviceDescriptionPtr->readLocks); 1684 RecordEventLogger( 'open', ' Now', ih, deviceDescriptionPtr->readLocks); 1685 } 1686 1687 // if user is opening for write, make sure device isn't already opened 1688 if( permissions & kIDHOpenForWriteTransactions) 1689 { 1690 FailWithAction( deviceDescriptionPtr->readLocks || deviceDescriptionPtr->writeLocks, 1691 result = kIDHErrDeviceInUse, Exit); 1692 1693 result = enableWrite(deviceDescriptionPtr); 1694 FailWithVal( result != noErr, Exit, result); 1695 1696 deviceDescriptionPtr->writeLocks = 1; // keep track of write count 1697 } 1698 1699// if( permissions & kIDHOpenWithExclusiveAccess) 1700// deviceDescriptionPtr->exclusiveAccess = true; 1701 1702 ih->permissions = permissions; // save the permissions 1703 // Setup device->component pointer 1704 for(i=0; i<kMaxDeviceClients; i++) { 1705 if(!deviceDescriptionPtr->fOpenClients[i]) { 1706 deviceDescriptionPtr->fOpenClients[i] = ih; 1707 ih->fClientIndex = i; 1708 break; 1709 } 1710 } 1711 1712Exit: 1713 return result; 1714} 1715 1716static ComponentResult processClose(IsochComponentInstancePtr ih, void *junk) 1717{ 1718 ComponentResult result = noErr; 1719 DeviceDescription *deviceDescriptionPtr; 1720 1721#ifdef kIDH_Verbose_Debug_Logging 1722 syslog(LOG_INFO, "IDH: processClose begin\n"); 1723#endif 1724 1725 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); // find the device 1726 FailWithVal( result != noErr, Exit, result); 1727 if( ih->permissions & kIDHOpenForReadTransactions) // tear down read 1728 { 1729 //syslog(LOG_INFO, "ih %p dev %p Closing from read, count %d\n", 1730 // ih, deviceDescriptionPtr, deviceDescriptionPtr->readLocks); 1731 if( --deviceDescriptionPtr->readLocks <= 0) // is device completely freed by clients? 1732 { 1733 if(deviceDescriptionPtr->fActive) 1734 disableRead(deviceDescriptionPtr); 1735 // volatile int *fWriter,*fReader,*fDrop,*fStatus; 1736 1737 //if(deviceDescriptionPtr->fSharedVars) { 1738 // printf("fWriter: %ld", deviceDescriptionPtr->fSharedVars->fWriter); 1739 // printf(" fReader: %ld", deviceDescriptionPtr->fSharedVars->fReader); 1740 // printf(" fDrop: %ld", deviceDescriptionPtr->fSharedVars->fDroppedFrames); 1741 // printf(" fStatus: %ld", deviceDescriptionPtr->fSharedVars->fStatus); 1742 // printf("\n"); 1743 //} 1744 1745 //deviceDescriptionPtr->exclusiveAccess = false; 1746 } 1747 } 1748 1749 if( ih->permissions & kIDHOpenForWriteTransactions) // tear down write 1750 { 1751 if( --deviceDescriptionPtr->writeLocks <= 0) // is device completely freed by clients? 1752 { 1753 if(deviceDescriptionPtr->fActive) 1754 disableWrite(deviceDescriptionPtr); 1755 //if(deviceDescriptionPtr->fSharedVars) { 1756 // printf("fWriter: %ld", deviceDescriptionPtr->fSharedVars->fWriter); 1757 // printf(" fReader: %ld", deviceDescriptionPtr->fSharedVars->fReader); 1758 // printf(" fDrop: %ld", deviceDescriptionPtr->fSharedVars->fDroppedFrames); 1759 // printf(" fStatus: %ld", deviceDescriptionPtr->fSharedVars->fStatus); 1760 // printf("\n"); 1761 //} 1762 1763 //deviceDescriptionPtr->exclusiveAccess = false; 1764 } 1765 } 1766 1767 deviceDescriptionPtr->fOpenClients[ih->fClientIndex] = nil; 1768Exit: 1769 1770#ifdef kIDH_Verbose_Debug_Logging 1771syslog(LOG_INFO, "IDH: processClose end\n"); 1772#endif 1773 1774return result; 1775 1776} 1777 1778static ComponentResult processCancelPendingIO(IsochComponentInstancePtr client, void *params) 1779{ 1780 while(client->fHead) { 1781 IDHParameterBlock *pb = client->fHead; 1782 //syslog(LOG_INFO, "Cancelling IO %p, buffer = %p\n", pb, pb->buffer); 1783 1784 client->fHead = (IDHParameterBlock *)pb->reserved1; 1785 pb->reserved1 = NULL; 1786 } 1787 client->fTail = NULL; 1788 1789 return noErr; 1790} 1791 1792#if TIMING 1793/* raw read of the timebase register */ 1794static void clock_get_uptime( register AbsoluteTime *result) 1795{ 1796#ifdef __ppc__ 1797 1798 register UInt32 hic; 1799 do { 1800 asm volatile(" mftbu %0" : "=r" (result->hi)); 1801 asm volatile(" mftb %0" : "=r" (result->lo)); 1802 asm volatile(" mftbu %0" : "=r" (hic)); 1803 } while (hic != result->hi); 1804 1805#else 1806 result->lo = 0; 1807 result->hi = 0; 1808#endif /* __ppc__ */ 1809 1810} 1811#endif 1812 1813static void timerTick(CFRunLoopTimerRef timer, void *info) 1814{ 1815 IsochComponentGlobalsPtr g = (IsochComponentGlobalsPtr)info; 1816 int dev; 1817 CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); 1818 CFAbsoluteTime fireDate = now + 100.0; 1819#ifdef TIMING 1820 if(now > g->fDVThread->requestTimeoutTime + .03) { 1821 pKGSysCall_Insert (kIOFWDVTrace, 'late', (UInt32)((now-g->fDVThread->requestTimeoutTime)*1000), 0, 0, 0, 0); 1822 syslog(LOG_INFO, "Late timer tick, @ %8.3f, wanted %8.3f\n", now, g->fDVThread->requestTimeoutTime); 1823 DVDumpLog(g->fDVThread); 1824 } 1825#endif 1826 for(dev = 0; dev<g->nDevices; dev++) { 1827 DeviceDescription *deviceDescriptionPtr; 1828 deviceDescriptionPtr = &g->deviceDescription[dev]; 1829 1830 // Process I/O queues 1831 if(deviceDescriptionPtr && deviceDescriptionPtr->fActive) { 1832#if TIMING 1833 clock_get_uptime(×tamp1); 1834#endif 1835 if(deviceDescriptionPtr->fRead) { 1836 fireDate = CFAbsoluteTimeGetCurrent() + kDCLBlockTime; 1837 } 1838 1839 if(deviceDescriptionPtr->writeLocks) { 1840 CFAbsoluteTime writeDate; 1841 writeDate = processWrites(deviceDescriptionPtr); 1842 if(writeDate < fireDate) 1843 fireDate = writeDate; 1844 } 1845 if(deviceDescriptionPtr->readLocks) { 1846 CFAbsoluteTime readDate; 1847 readDate = processReads(deviceDescriptionPtr); 1848 if(readDate < fireDate) 1849 fireDate = readDate; 1850 } 1851#if TIMING 1852 clock_get_uptime(×tamp2); 1853 start = (((unsigned long long)timestamp1.hi) << 32) | 1854 (unsigned long long)((unsigned int)(timestamp1.lo)); 1855 1856 stop = (((unsigned long long)timestamp2.hi) << 32) | 1857 (unsigned long long)((unsigned int)(timestamp2.lo)); 1858 1859 elapsed_msecs = (int)(((double)(stop - start)) / divisor); 1860 if(elapsed_msecs > worst_callback) { 1861 pKGSysCall_Insert (kIOFWDVTrace, 'call', elapsed_msecs, 0, 0, 0, 0); 1862 syslog(LOG_INFO, "callback delay %d mSec\n", 1863 elapsed_msecs); 1864 worst_callback = elapsed_msecs; 1865 } 1866#endif 1867 } 1868 } 1869 DVSetTimeoutTime(g->fDVThread, fireDate); 1870#if TIMING 1871 DVLog(g->fDVThread, 'timr', now, CFAbsoluteTimeGetCurrent()); 1872#endif 1873} 1874 1875/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1876 1877static pascal ComponentResult 1878FWDVComponentOpen(IsochComponentInstancePtr storage, ComponentInstance self) 1879{ 1880 IsochComponentGlobalsPtr g = &globals; 1881 1882#ifdef kIDH_Verbose_Debug_Logging 1883 syslog(LOG_INFO, "IDH: FWDVComponentOpen begin\n"); 1884#endif 1885 1886 RecordEventLogger( 'isoc', 'open', g->fNumInstances, 0); 1887 if( nil == (storage = (IsochComponentInstancePtr)NewPtrClear(sizeof(IsochComponentInstance)))) 1888 return(MemError()); 1889 1890 RecordEventLogger( 'isoc', 'ope2', (int)storage, 0); 1891 //syslog(LOG_INFO, "%x: FWDVComponentOpen count %d\n", pthread_self(), g->fNumInstances); 1892 1893 SetComponentInstanceStorage(self, (Handle) storage); 1894 1895 // One-time initialization of globals 1896 if (!g->fDVThread) { 1897 g->fDVThread = DVCreateThread(deviceArrived, g, timerTick, g, deviceMessage); 1898 if (!g->fDVThread) 1899 return(MemError()); 1900 g->nDevices=0; 1901 DVRunThread(g->fDVThread); 1902 } 1903 1904 g->fNumInstances++; 1905 1906#ifdef kIDH_Verbose_Debug_Logging 1907 syslog(LOG_INFO, "IDH: FWDVComponentOpen fNumInstances: %d\n",g->fNumInstances); 1908#endif 1909 1910#ifdef kIDH_Verbose_Debug_Logging 1911 syslog(LOG_INFO, "IDH: FWDVComponentOpen end\n"); 1912#endif 1913 1914 return(noErr); 1915} 1916 1917/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1918 1919static pascal ComponentResult 1920FWDVComponentClose(IsochComponentInstancePtr ih, ComponentInstance self) 1921{ 1922 int i; 1923 IsochComponentGlobalsPtr g = &globals; 1924 1925#ifdef kIDH_Verbose_Debug_Logging 1926 syslog(LOG_INFO, "IDH: FWDVComponentClose begin\n"); 1927#endif 1928 1929 RecordEventLogger( 'isoc', 'clos', ih, self); 1930 if( !ih) 1931 return( noErr ); 1932 1933 if(ih->hasDeviceControl) { 1934 DeviceDescriptionPtr deviceDescriptionPtr; 1935 if(findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr) == noErr) 1936 closeDeviceControl( ih, deviceDescriptionPtr); 1937 } 1938 1939 if( ih->permissions ) 1940 FWDVIDHCloseDevice(ih); 1941 1942 //syslog(LOG_INFO, "%x: FWDVComponentClose count %d\n", pthread_self(), g->fNumInstances); 1943 g->fNumInstances--; 1944 1945#ifdef kIDH_Verbose_Debug_Logging 1946 syslog(LOG_INFO, "IDH: FWDVComponentClose fNumInstances: %d\n",g->fNumInstances); 1947#endif 1948 1949 if(g->fNumInstances == 0) { 1950 1951 // Free all mach ports etc. 1952 for(i=0; i<g->nDevices; i++) { 1953 DeviceDescriptionPtr dev = &g->deviceDescription[i]; 1954 dev->fConnected = 0; 1955 if(dev->fDevice) { 1956 DVDeviceTerminate(dev->fDevice); 1957 dev->fDevice = NULL; 1958 } 1959 if(dev->deviceContainer) { 1960 QTDisposeAtomContainer(dev->deviceContainer); 1961 dev->deviceContainer = NULL; 1962 } 1963 } 1964 if(g->fDVThread) { 1965 //syslog(LOG_INFO, "%x: Calling DVFreeThread\n", pthread_self()); 1966 DVFreeThread(g->fDVThread); 1967 g->fDVThread = NULL; 1968 } 1969 } 1970 1971 DisposePtr((Ptr) ih); 1972 1973 SetComponentInstanceStorage(self, (Handle) nil ); 1974 RecordEventLogger( 'isoc', 'clos', 'end ', 0); 1975 1976#ifdef kIDH_Verbose_Debug_Logging 1977 syslog(LOG_INFO, "IDH: FWDVComponentClose end\n"); 1978#endif 1979 1980 return( noErr ); 1981} 1982 1983/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1984 1985static pascal ComponentResult 1986FWDVComponentVersion(IsochComponentInstancePtr storage) 1987{ 1988 RecordEventLogger( 'isoc', 'vers', 0, 0); 1989 return (DVVersion << 16) | DVRevision; 1990} 1991 1992static pascal ComponentResult 1993FWDVComponentRegister(IsochComponentInstancePtr storage) 1994{ 1995 // need to re-register with each source type? 1996 RecordEventLogger( 'isoc', 'reg ', 0, 0); 1997 return( noErr ); 1998} 1999 2000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2001static pascal ComponentResult 2002FWDVIDHGetDeviceList(IsochComponentInstancePtr storage, 2003 QTAtomContainer *deviceList ) 2004{ 2005 OSStatus result = noErr; 2006 QTAtomContainer container = nil; 2007 int devIndex; 2008 UInt32 version; 2009 IsochComponentGlobalsPtr g = &globals; 2010 2011#ifdef kIDH_Verbose_Debug_Logging 2012 syslog(LOG_INFO, "IDH: FWDVIDHGetDeviceList begin\n"); 2013#endif 2014 2015 RecordEventLogger( 'isoc', 'get ', 'dev ', 'list'); 2016 do { 2017 // create device atom list now 2018 result = QTNewAtomContainer( &container); 2019 if(result != noErr) 2020 break; 2021 2022 // save seed 2023 result = QTInsertChild( container, kParentAtomIsContainer, kIDHSeedAtomType, 0, 0, 2024 sizeof( g->seed), &g->seed, nil); 2025 if(result != noErr) 2026 break; 2027 2028 version = (DVVersion << 24) | (DVRevision << 16) | DVBuildNumber; 2029 2030 // save isoch version 2031 result = QTInsertChild( container, kParentAtomIsContainer, kIDHIsochVersionAtomType, 0, 0, 2032 sizeof( UInt32), &version, nil); 2033 if(result != noErr) 2034 break; 2035 2036 // save useCMP value 2037 result = QTInsertChild( container, kParentAtomIsContainer, kIDHUseCMPAtomType, 0, 0, 2038 sizeof( UInt32), &g->useCMP, nil); 2039 if(result != noErr) 2040 break; 2041 2042 // save each active device 2043 for( devIndex=0; devIndex<kDVMaxDevicesActive; ++devIndex) 2044 { 2045 if( g->deviceDescription[devIndex].fDevice != 0 && g->deviceDescription[devIndex].fActive) 2046 { 2047 result = QTInsertChildren( container, kParentAtomIsContainer, 2048 g->deviceDescription[devIndex].deviceContainer); 2049 if(result != noErr) 2050 break; 2051 } 2052 } 2053 2054 *deviceList = container; 2055 return noErr; 2056 } while (false); 2057 2058 if(container) { 2059 QTRemoveChildren( container, kParentAtomIsContainer); 2060 QTDisposeAtomContainer( container); 2061 } 2062 2063#ifdef kIDH_Verbose_Debug_Logging 2064 syslog(LOG_INFO, "IDH: FWDVIDHGetDeviceList end\n"); 2065#endif 2066 2067 return result; 2068} 2069 2070static pascal ComponentResult 2071FWDVIDHSetDeviceConfiguration(IsochComponentInstancePtr ih, 2072 const QTAtomSpec *configID) 2073{ 2074 OSStatus result = noErr; 2075 QTAtomSpec volatileAtomSpec; 2076 QTAtom nameAtom; 2077 IDHDeviceID previousDeviceID; 2078 DeviceDescription *deviceDescriptionPtr; 2079 IsochComponentGlobalsPtr g = &globals; 2080 Boolean isSDL; 2081 2082#ifdef kIDH_Verbose_Debug_Logging 2083 syslog(LOG_INFO, "IDH: FWDVIDHSetDeviceConfiguration begin\n"); 2084#endif 2085 2086 RecordEventLogger( 'isoc', 'set ', 'conf', ih); 2087 2088 FailWithAction( configID == nil, result = paramErr, Exit); 2089 2090 FailWithAction( configID->container == nil, result = paramErr, Exit); 2091 2092 // if the client is setting to the same config, then we are ok 2093 if( configID->container == ih->currentConfig.container && 2094 configID->atom == ih->currentConfig.atom) 2095 goto Exit; 2096 2097 // device already in use, please close device first 2098 FailWithAction( ih->permissions != 0, result = kIDHErrDeviceInUse, Exit); 2099 2100 previousDeviceID = ih->deviceID; 2101 2102 volatileAtomSpec = *configID; 2103 result = getDeviceID( &volatileAtomSpec, &ih->deviceID); 2104 FailWithVal( result != noErr, Exit, result); 2105 2106 result = checkSeed( g, &volatileAtomSpec); 2107 FailWithVal( result != noErr, Exit, result); 2108 2109 ih->currentConfig = *configID; 2110 2111 nameAtom = QTFindChildByIndex( configID->container, configID->atom, kIDHNameAtomType, 1, nil); 2112 if( nameAtom != nil) { 2113 Str255 name; 2114 long size; 2115 QTCopyAtomDataToPtr( configID->container, nameAtom, true, 255, name, &size); 2116 isSDL = !strncmp(name, "\pDV-SDL", *name); 2117 } 2118 else 2119 isSDL = false; 2120 2121 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2122 FailWithVal( result != noErr, Exit, result); 2123 2124 // Open device 2125 if(deviceDescriptionPtr->fDevice->fDevInterface == NULL) { 2126 result = DVDeviceOpen(g->fDVThread, deviceDescriptionPtr->fDevice); 2127 if (result != kIOReturnSuccess) { 2128 goto Exit; 2129 } 2130 deviceDescriptionPtr->fConnected = 1; 2131 } 2132 else 2133 deviceDescriptionPtr->fConnected++; 2134 2135 FailWithAction( deviceDescriptionPtr->fActive == false, result = kIDHErrDeviceDisconnected, Exit); 2136 2137 // if this client had a previous connection, close that and if it had device control, 2138 // close that too. 2139 if( previousDeviceID && previousDeviceID != ih->deviceID) { 2140 DeviceDescription *deviceDescriptionPtr2; 2141 2142 result = findDeviceDescriptionforDevice( ih, previousDeviceID, &deviceDescriptionPtr2); 2143 FailWithVal( result != noErr, Exit, result); 2144 if(deviceDescriptionPtr2->fConnected) { 2145 deviceDescriptionPtr2->fConnected--; 2146 // Close device if nobody else has it open and it hasn't been unplugged already 2147 if(deviceDescriptionPtr2->fConnected == 0 && deviceDescriptionPtr2->fActive && 2148 deviceDescriptionPtr2->fDevice->fDevInterface) { 2149 DVDeviceClose(deviceDescriptionPtr2->fDevice); 2150 } 2151 } 2152 if(ih->hasDeviceControl) { 2153 result = closeDeviceControl( ih, deviceDescriptionPtr2); 2154 FailMessage( result != noErr); 2155 2156 ih->hasDeviceControl = false; 2157 } 2158 } 2159 2160Exit: 2161 RecordEventLogger( 'isoc', 'set ', 'Exit', ih); 2162 2163#ifdef kIDH_Verbose_Debug_Logging 2164 syslog(LOG_INFO, "IDH: FWDVIDHSetDeviceConfiguration end\n"); 2165#endif 2166 2167 return result; 2168} 2169 2170static pascal ComponentResult 2171FWDVIDHOpenDevice(IsochComponentInstancePtr ih, UInt32 permissions) 2172{ 2173 ComponentResult result = noErr; 2174 IsochComponentGlobalsPtr g = &globals; 2175 2176#ifdef kIDH_Verbose_Debug_Logging 2177 syslog(LOG_INFO, "IDH: FWDVIDHOpenDevice begin\n"); 2178#endif 2179 2180 RecordEventLogger( 'open', ' dev', ih, permissions); 2181 2182 FailWithAction( permissions == 0, result = paramErr, Exit); 2183 2184 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2185 2186 { 2187 DeviceDescription* description ; 2188 FailWithAction( noErr != findDeviceDescriptionforDevice( ih, ih->deviceID, & description ), result = kIDHErrDeviceNotConfigured, Exit ) ; 2189 2190 FailWithAction( description == nil, result = kIDHErrDeviceNotConfigured, Exit ) ; 2191 FailWithAction( description->fDevice == nil, result = kIDHErrDeviceNotConfigured, Exit ) ; 2192 FailWithAction( description->fDevice->fDevInterface == nil, result = kIDHErrDeviceNotConfigured, Exit ) ; 2193 FailWithAction( description->fDevice->fAVCInterface == nil, result = kIDHErrDeviceNotConfigured, Exit ) ; 2194 } 2195 2196 result = sendMsg(ih, processOpen, (void *)permissions); 2197 2198 FailWithVal( result != noErr, Exit, result); 2199 result = postEvent( g, ih->deviceID, 2200 (permissions & kIDHOpenForReadTransactions)?kIDHEventReadEnabled:kIDHEventWriteEnabled); 2201 FailWithVal( result != noErr, Exit, result); 2202#ifdef DRAWRINGBUFFERGRAPH 2203 SetUpBlitGlobals((DeviceDescription *)ih->deviceID); 2204#endif 2205 2206Exit: 2207 2208#ifdef kIDH_Verbose_Debug_Logging 2209 syslog(LOG_INFO, "IDH: FWDVIDHOpenDevice end\n"); 2210#endif 2211 2212 return result; 2213} 2214 2215static pascal ComponentResult 2216FWDVIDHCloseDevice(IsochComponentInstancePtr ih) 2217{ 2218 OSStatus result = noErr; 2219 IsochComponentGlobalsPtr g = &globals; 2220 2221#ifdef kIDH_Verbose_Debug_Logging 2222 syslog(LOG_INFO, "IDH: FWDVIDHCloseDevice begin\n"); 2223#endif 2224 2225 RecordEventLogger( 'isoc', 'clos', ' dev', ih); 2226 2227 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2228 2229 if( ih->permissions == 0) // client has no open devices? 2230 goto Exit; 2231 2232 //syslog(LOG_INFO, "%x: FWDVIDHCloseDevice\n", pthread_self()); 2233 result = sendMsg(ih, processClose, 0); 2234 FailWithVal( result != noErr, Exit, result); 2235 result = postEvent( g, ih->deviceID, 2236 (ih->permissions & kIDHOpenForReadTransactions)?kIDHEventReadDisabled:kIDHEventWriteDisabled); 2237 FailWithVal( result != noErr, Exit, result); 2238 2239Exit: 2240 ih->permissions = 0; // make sure device is closed 2241 ih->fClientIndex = 0xdead; 2242 2243#ifdef kIDH_Verbose_Debug_Logging 2244 syslog(LOG_INFO, "IDH: FWDVIDHCloseDevice end\n"); 2245#endif 2246 2247 return result; 2248} 2249 2250//��� USER BETTER KEEP HIS DEVICE LIST AROUND IF THIS IS TO MEAN ANYTHING 2251static pascal ComponentResult 2252FWDVIDHGetDeviceConfiguration(IsochComponentInstancePtr ih, QTAtomSpec *configID ) 2253{ 2254 OSStatus result = noErr; 2255 2256#ifdef kIDH_Verbose_Debug_Logging 2257 syslog(LOG_INFO, "IDH: FWDVIDHGetDeviceConfiguration begin\n"); 2258#endif 2259 2260 RecordEventLogger( 'isoc', 'get ', 'dev ', 'conf'); 2261 2262 FailWithAction( configID == nil, result = paramErr, Exit); 2263 FailWithAction( ih->currentConfig.container == nil || ih->currentConfig.atom == nil, 2264 result = kIDHErrDeviceNotConfigured, Exit); 2265 2266 *configID = ih->currentConfig; 2267 2268Exit: 2269 2270#ifdef kIDH_Verbose_Debug_Logging 2271 syslog(LOG_INFO, "IDH: FWDVIDHGetDeviceConfiguration end\n"); 2272#endif 2273 2274 return result; 2275} 2276 2277static pascal ComponentResult 2278FWDVIDHGetDeviceStatus(IsochComponentInstancePtr ih, const QTAtomSpec *devSpec, IDHDeviceStatus *status ) 2279{ 2280 OSStatus result = noErr; 2281 IDHDeviceID deviceID = nil; 2282 QTAtom deviceInfoAtom, deviceAtom; 2283 QTAtomSpec volatileAtomSpec; 2284 DeviceDescription *deviceDescriptionPtr; 2285 IsochComponentGlobalsPtr g = &globals; 2286 UInt8 inputFormat = kIDHDV_SD; 2287 2288#ifdef kIDH_Verbose_Debug_Logging 2289 syslog(LOG_INFO, "IDH: FWDVIDHGetDeviceStatus begin\n"); 2290#endif 2291 2292 RecordEventLogger( 'isoc', 'get ', 'stat', ih); 2293 FailWithAction( devSpec == nil, result = paramErr, Exit); 2294 FailWithAction( status == nil, result = paramErr, Exit); 2295 2296 volatileAtomSpec = *devSpec; 2297 2298 result = checkSeed( g, &volatileAtomSpec); 2299 if( result != noErr) 2300 goto Exit; 2301 2302 result = getDeviceID( &volatileAtomSpec, &deviceID); 2303 FailWithVal( result != noErr, Exit, result); 2304 2305 result = findDeviceDescriptionforDevice( ih, deviceID, &deviceDescriptionPtr); // find description for this device 2306 FailWithVal( result != noErr, Exit, result); 2307 2308 deviceAtom = QTFindChildByIndex( deviceDescriptionPtr->deviceContainer, kParentAtomIsContainer, kIDHDeviceAtomType, 1, nil); 2309 FailWithAction( deviceAtom == nil, result = kIDHErrDeviceList, Exit); 2310 2311 // find device status for this device 2312 deviceInfoAtom = QTFindChildByIndex( deviceDescriptionPtr->deviceContainer, deviceAtom, kDVDeviceInfo, 1, nil); 2313 FailWithAction( deviceInfoAtom == nil, result = kIDHErrDeviceList, Exit); 2314 2315 // Ask device what it's currently configured to transmit 2316 // Need to ask info for plug 0 for Panasonic AJ250, which always says 'DV' for kAVCOutputSignalModeOpcode, 2317 // even when sending DVCPro25. 2318#if 1 2319 { 2320 OSStatus err; 2321 DVCTransactionParams transaction; 2322 UInt8 out[8]; 2323 UInt8 in[8]; 2324 2325 out[0] = kAVCStatusInquiryCommand; 2326 out[1] = kAVCUnitAddress; 2327 out[2] = kAVCOutputPlugSignalFormatOpcode; 2328 out[3] = 0; // Plug 2329 out[4] = out[5] = out[6] = out[7] = 0xff; 2330 transaction.commandBufferPtr = out; 2331 transaction.commandLength = sizeof(out); 2332 transaction.responseBufferPtr = in; 2333 transaction.responseBufferSize = sizeof(in); 2334 transaction.responseHandler = NULL; 2335 2336 err = doAVCTransaction(deviceDescriptionPtr, &transaction); 2337 if(err == noErr && in[0] == 0xc) { 2338 inputFormat = (in[5] >> 2) & 0x1f; // Fish out STYPE field 2339 } 2340 } 2341#else 2342 { 2343 OSStatus err; 2344 DVCTransactionParams transaction; 2345 UInt8 out[4]; 2346 UInt8 in[4]; 2347 2348 out[0] = kAVCStatusInquiryCommand; 2349 out[1] = IOAVCAddress(kAVCTapeRecorder, 0); 2350 out[2] = kAVCOutputSignalModeOpcode; 2351 out[3] = kAVCSignalModeDummyOperand; 2352 2353 transaction.commandBufferPtr = out; 2354 transaction.commandLength = sizeof(out); 2355 transaction.responseBufferPtr = in; 2356 transaction.responseBufferSize = sizeof(in); 2357 transaction.responseHandler = NULL; 2358 2359 err = doAVCTransaction(deviceDescriptionPtr, &transaction); 2360 if(err == noErr && in[0] == 0xc) { 2361 inputFormat = (in[3] >> 2) & 0x1f; // Fish out STYPE field 2362 } 2363 } 2364#endif 2365 //status->version = 0x200; 2366 status->physicallyConnected = true; 2367 status->readEnabled = deviceDescriptionPtr->readLocks; 2368 status->writeEnabled = deviceDescriptionPtr->writeLocks; 2369 status->exclusiveAccess = 0;//deviceDescriptionPtr->exclusiveAccess; 2370 status->currentBandwidth = 0; 2371 status->currentChannel = 0; 2372 2373 //��� need to make this work with camera tracking 2374 status->deviceActive = deviceDescriptionPtr->fActive; 2375 status->inputFormat = inputFormat; 2376 if(deviceDescriptionPtr->fActive) { 2377 status->inputStandard = deviceDescriptionPtr->fDevice->standard; 2378 2379 // Does caller want extended status? 2380 if(status->version == 0x200) 2381 status->outputFormats = deviceDescriptionPtr->fDevice->fDVFormats; 2382 } 2383// JKL *** what to to with this? does this mean deviceID, cameraFWClientID, or localNodeFWClientID 2384// Think this is for clock to set the localFWReferenceID 2385 status->localNodeID = (PsuedoID) deviceDescriptionPtr->fDevice; 2386 2387 result = QTSetAtomData( deviceDescriptionPtr->deviceContainer, deviceInfoAtom, sizeof( IDHDeviceStatus), status); 2388 FailWithVal( result != noErr, Exit, result); 2389 2390Exit: 2391 2392#ifdef kIDH_Verbose_Debug_Logging 2393 syslog(LOG_INFO, "IDH: FWDVIDHGetDeviceStatus end\n"); 2394#endif 2395 2396 return result; 2397} 2398 2399static pascal ComponentResult 2400FWDVIDHGetDeviceClock(IsochComponentInstancePtr ih, Component *clock ) 2401{ 2402 DeviceDescription *deviceDescriptionPtr; 2403 OSStatus result = noErr; 2404 2405 RecordEventLogger( 'isoc', 'get ', 'clok', 0); 2406 2407 FailWithAction( clock == nil, result = paramErr, Exit); 2408 2409 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2410 2411 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2412 FailWithVal( result != noErr, Exit, result); 2413 2414// FailWithAction( deviceDescriptionPtr->active == false, result = kIDHErrDeviceDisconnected, Exit); 2415 2416 *clock = deviceDescriptionPtr->clock; 2417 2418Exit: 2419 return result; 2420} 2421 2422// can be called synchronously at task level only 2423static pascal ComponentResult 2424FWDVIDHRead(IsochComponentInstancePtr ih, IDHParameterBlock *pb) 2425{ 2426 OSStatus result = noErr; 2427 DeviceDescription *deviceDescriptionPtr; 2428 2429 RecordEventLogger( 'isoc', 'read', (unsigned long) ih, (unsigned long) pb ); 2430 2431 //syslog(LOG_INFO, "FWDVIDHRead, completion = %p buffer = %p\n", pb->completionProc, pb->buffer); 2432 //syslog(LOG_INFO, "pb %p = req %d actual %d, result %d\n", 2433 // pb, pb->requestedCount, pb->actualCount, pb->result); 2434 2435 FailWithAction( pb == nil, result = paramErr, Exit); 2436 2437 // can't do sync reads in I/O thread 2438 //FailWithAction( pb->completionProc == nil && CurrentExecutionLevel() != kTaskLevel, result = paramErr, Exit); 2439 2440 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2441 2442 FailWithAction( !(ih->permissions & kIDHOpenForReadTransactions), result = kIDHErrDeviceNotOpened, Exit); 2443 2444 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2445 FailWithVal( result != noErr, Exit, result); 2446 2447 FailWithAction( deviceDescriptionPtr->fActive == false, result = kIDHErrDeviceDisconnected, Exit); 2448 2449 if( pb->completionProc == nil) // synchronous read 2450 { 2451 int frameIndex = deviceDescriptionPtr->fReadSharedVars->fReader % deviceDescriptionPtr->fNumOutputFrames; 2452 UInt8 *buffer = (UInt8 *)deviceDescriptionPtr->bufMem[frameIndex]; 2453 UInt32 frameSize; 2454 2455 // wait for writer 2456 // if (*devices[refNum].fReader + 1 >= *devices[refNum].fWriter) return -1; 2457 if( deviceDescriptionPtr->fOldDrop < 2458 deviceDescriptionPtr->fReadSharedVars->fDroppedFrames) { 2459 dropMsg(deviceDescriptionPtr, deviceDescriptionPtr->fReadSharedVars->fDroppedFrames); 2460 } 2461 2462 while (deviceDescriptionPtr->fReadSharedVars->fReader >= deviceDescriptionPtr->fReadSharedVars->fWriter) 2463 { 2464 usleep(12500); // time DCL block takes to run 2465 } 2466 frameSize = deviceDescriptionPtr->fReadSharedVars->fFrameSize[frameIndex]; 2467 pb->actualCount = frameSize; 2468 pb->reserved1 = cycles(deviceDescriptionPtr->fReadSharedVars->fFrameTime[frameIndex]); 2469 if(pb->buffer != nil) { 2470 // copy frame 2471 bcopy(buffer, pb->buffer, frameSize); 2472 deviceDescriptionPtr->fReadSharedVars->fReader += 1; // release buffer 2473 } 2474 else 2475 pb->buffer = buffer; 2476 pb->result = noErr; 2477 } 2478 else { 2479 pb->result = kIDHErrCompletionPending; 2480 //syslog(LOG_INFO, "FWDVIDHRead end, completion = %p buffer = %p\n", pb->completionProc, pb->buffer); 2481 //syslog(LOG_INFO, "pb %p = req %d actual %d, result %d\n", 2482 // pb, pb->requestedCount, pb->actualCount, pb->result); 2483 2484 result = sendMsg(ih, queueRead, pb); 2485 } 2486 2487Exit: 2488#ifdef DRAWRINGBUFFERGRAPH 2489 BlitBufferGraph(deviceDescriptionPtr); 2490#endif 2491 return result; 2492} 2493 2494static pascal ComponentResult 2495FWDVIDHReleaseBuffer(IsochComponentInstancePtr ih, IDHParameterBlock *pb) 2496{ 2497 OSStatus result = noErr; 2498 int frameIndex; 2499 DeviceDescription *deviceDescriptionPtr; 2500 2501 RecordEventLogger( 'isoc', 'rele', 'ase ', 'buff'); 2502 2503 FailWithAction( pb == nil, result = paramErr, Exit); 2504 2505 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2506 2507 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2508 FailWithVal( result != noErr, Exit, result); 2509 frameIndex = deviceDescriptionPtr->fReadSharedVars->fReader % deviceDescriptionPtr->fNumOutputFrames; 2510 if(pb->buffer == (Ptr)deviceDescriptionPtr->bufMem[frameIndex]) { 2511 if(--deviceDescriptionPtr->fBufferLocks[frameIndex] == 0) 2512 deviceDescriptionPtr->fReadSharedVars->fReader += 1; // release buffer, this isn't quite right if several buffers are held. 2513 } 2514Exit: 2515 return result; 2516} 2517 2518static pascal ComponentResult 2519FWDVIDHCancelPendingIO(IsochComponentInstancePtr ih, IDHParameterBlock *pb) 2520{ 2521 OSStatus result = noErr; 2522 DeviceDescription *deviceDescriptionPtr; 2523 2524 RecordEventLogger( 'isoc', 'canc', 'elIO', 0); 2525 2526 FailWithAction( pb == nil, result = paramErr, Exit); 2527 2528 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2529 2530 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2531 FailWithVal( result != noErr, Exit, result); 2532 2533 result = sendMsg(ih, processCancelPendingIO, pb); 2534 2535Exit: 2536#ifdef DRAWRINGBUFFERGRAPH 2537 BlitBufferGraph(deviceDescriptionPtr); 2538#endif 2539 return result; 2540} 2541 2542// can be called synchronously at task level only 2543static pascal ComponentResult 2544FWDVIDHWrite(IsochComponentInstancePtr ih, IDHParameterBlock *pb) 2545{ 2546 OSStatus result = noErr; 2547 DeviceDescription *deviceDescriptionPtr; 2548 2549 RecordEventLogger( 'isoc', 'writ', ih, pb); 2550 2551 FailWithAction( pb == nil, result = paramErr, Exit); 2552 2553 // check for illegal condition 2554 FailWithAction( pb->completionProc == nil && pb->buffer == nil, result = paramErr, Exit); 2555 2556 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2557 2558 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2559 FailWithVal( result != noErr, Exit, result); 2560 2561 FailWithAction( deviceDescriptionPtr->fActive == false, result = kIDHErrDeviceDisconnected, Exit); 2562 2563 if( pb->completionProc == nil) // synchronous write 2564 { 2565 pb->result = kIDHErrCompletionPending; 2566 2567 result = sendMsg(ih, queueWrite, pb); 2568 while (pb->result == kIDHErrCompletionPending) 2569 { 2570 usleep(12500); // time DCL block takes to run 2571 } 2572 } 2573 else { 2574 result = sendMsg(ih, queueWrite, pb); 2575 } 2576 2577 2578Exit: 2579#ifdef DRAWRINGBUFFERGRAPH 2580 BlitBufferGraph(deviceDescriptionPtr); 2581#endif 2582 return result; 2583} 2584 2585static pascal ComponentResult 2586FWDVIDHGetDeviceControl(IsochComponentInstancePtr ih, ComponentInstance *deviceControl) 2587{ 2588 ComponentResult result = noErr; 2589 DeviceDescription *deviceDescriptionPtr; 2590 2591 RecordEventLogger( 'isoc', 'get ', 'dev ', 'ctrl'); 2592 2593 if ( deviceControl == nil ) 2594 return(paramErr); 2595 2596 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2597 2598 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2599 FailWithVal( result != noErr, Exit, result); 2600 2601 FailWithAction( deviceDescriptionPtr->fActive == false, result = kIDHErrDeviceDisconnected, Exit); 2602 2603 // ======================================================================= 2604 // All should be good here from a device stand point, now open the device 2605 // control component. If the devc is not nil either we didn't release it 2606 // from close or the same client is calling open again. 2607 2608 if ( deviceDescriptionPtr->deviceControlInstance == nil) 2609 { 2610 ComponentDescription devcDesc; 2611 Component devcComp; 2612 ComponentInstance devc; 2613 2614 devcDesc.componentType = kDeviceControlComponentType; 2615 devcDesc.componentSubType = kDeviceControlSubtypeFWDV; 2616 devcDesc.componentManufacturer = 0; 2617 devcDesc.componentFlags = 0L; 2618 devcDesc.componentFlagsMask = 0L; 2619 2620 devcComp = nil; 2621 devcComp = FindNextComponent( devcComp, &devcDesc); 2622 FailMessage( devcComp == nil); 2623 if ( devcComp ) 2624 { 2625 result = OpenAComponent(devcComp, &devc); 2626 FailWithVal( result != noErr, Exit, result); 2627 2628 result = DeviceControlSetDeviceConnectionID(devc, 2629 (DeviceConnectionID) deviceDescriptionPtr->fDevice->fAVCInterface); 2630 FailWithVal( result != noErr, Exit, result); 2631 result = DeviceControlEnableAVCTransactions(devc); 2632 FailWithVal( result != noErr, Exit, result); 2633 2634 deviceDescriptionPtr->deviceControlInstance = devc; 2635 } 2636 } 2637 2638 if( ih->hasDeviceControl == false && deviceDescriptionPtr->deviceControlInstance != nil) 2639 { 2640 ih->hasDeviceControl = true; 2641 ++deviceDescriptionPtr->deviceControlCount; 2642 } 2643 2644 2645 *deviceControl = deviceDescriptionPtr->deviceControlInstance; 2646 2647 FailMessage( *deviceControl == nil); 2648 2649Exit: 2650 return(result); 2651} 2652 2653static pascal ComponentResult 2654FWDVIDHUpdateDeviceList(IsochComponentInstancePtr ih, QTAtomContainer *deviceList ) 2655{ 2656 OSStatus result = noErr; 2657 short nDVDevices, i; 2658 QTAtomSpec atomSpec; 2659 IsochComponentGlobalsPtr g = &globals; 2660 2661 RecordEventLogger( 'isoc', 'updt', 'dev ', 'list'); 2662 2663 FailWithAction( deviceList == nil, result = paramErr, Exit); 2664 2665 atomSpec.container = *deviceList; 2666 2667 result = checkSeed( g, &atomSpec); // make sure the container is current 2668 if( result != noErr) 2669 goto Exit; 2670 2671 // check for useCMP value changing 2672 if (result == noErr) 2673 { 2674 QTAtom useCMPAtom; 2675 UInt32 useCMPValue; 2676 2677 useCMPAtom = QTFindChildByIndex(*deviceList, kParentAtomIsContainer, kIDHUseCMPAtomType, 1, nil); 2678 if (useCMPAtom) 2679 { 2680 QTLockContainer(*deviceList); 2681 result = QTCopyAtomDataToPtr(*deviceList, useCMPAtom, true, 4, &useCMPValue, nil); 2682 QTUnlockContainer(*deviceList); 2683 2684 if (result == noErr) 2685 g->useCMP = useCMPValue; 2686 2687 } 2688 } 2689 2690 // move all volatile atoms here 2691 nDVDevices = QTCountChildrenOfType( *deviceList, kParentAtomIsContainer, kIDHDeviceAtomType); 2692 for( i=0; i<nDVDevices; ++i) 2693 { 2694 QTAtom deviceAtomNew, nameAtomNew, deviceIDAtom; 2695 QTAtom deviceAtomOld, nameAtomOld; 2696 DeviceDescription *deviceDescriptionPtr; 2697 IDHDeviceID deviceID; 2698 UInt8 newName[256]; 2699 SInt32 actualSize; 2700 2701 // get the client supplied atoms 2702 deviceAtomNew = QTFindChildByIndex( *deviceList, kParentAtomIsContainer, kIDHDeviceAtomType, i + 1, nil); 2703 FailIf( deviceAtomNew == nil, Exit); 2704 2705 nameAtomNew = QTFindChildByIndex( *deviceList, deviceAtomNew, kIDHNameAtomType, 1, nil); 2706 FailIf( nameAtomNew == nil, Exit); 2707 2708 deviceIDAtom = QTFindChildByIndex( *deviceList, deviceAtomNew, kIDHDeviceIDType, 1, nil); 2709 FailIf( deviceIDAtom == nil, Exit); 2710 2711 QTLockContainer( *deviceList); 2712 2713 QTCopyAtomDataToPtr( *deviceList, deviceIDAtom, true, sizeof( IDHDeviceID), &deviceID, nil); 2714 2715 QTUnlockContainer( *deviceList); 2716 2717 // find the local copy of this device container 2718 result = findDeviceDescriptionforDevice( ih, deviceID, &deviceDescriptionPtr); 2719 FailWithVal( result != noErr, Exit, result); 2720 2721 deviceAtomOld = QTFindChildByIndex( deviceDescriptionPtr->deviceContainer, kParentAtomIsContainer, kIDHDeviceAtomType, 1, nil); 2722 FailIf( deviceAtomOld == nil, Exit); 2723 2724 nameAtomOld = QTFindChildByIndex( deviceDescriptionPtr->deviceContainer, deviceAtomOld, kIDHNameAtomType, 1, nil); 2725 FailIf( nameAtomOld == nil, Exit); 2726 2727 // get new name 2728 QTLockContainer( *deviceList); 2729 result = QTCopyAtomDataToPtr(*deviceList, nameAtomNew, true, 256, newName, &actualSize); 2730 QTUnlockContainer( *deviceList); 2731 FailWithVal( result != noErr, Exit, result); 2732 2733 // update prefs file with new name 2734 // JKL, don't want to do this for now since FCP might be using this routine to toggle CMP 2735// updateCameraName(&deviceDescriptionPtr->uniqueID, newName); 2736 2737 // copy the new data into the current atom 2738 result = QTReplaceAtom( deviceDescriptionPtr->deviceContainer, nameAtomOld, *deviceList, nameAtomNew); 2739 FailWithVal( result != noErr, Exit, result); 2740 } 2741 2742Exit: 2743 return result; 2744} 2745 2746static pascal ComponentResult 2747FWDVIDHGetDeviceTime(IsochComponentInstancePtr ih, TimeRecord *time) 2748{ 2749 OSStatus result; 2750 DeviceDescription *deviceDescriptionPtr; 2751 UInt32 busTime, cycleTime; 2752 UInt64 cycles; 2753 2754 FailWithAction( time == nil, result = paramErr, Exit); 2755 2756 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2757 2758 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2759 FailWithVal( result != noErr, Exit, result); 2760 2761 FailWithAction( deviceDescriptionPtr->fActive == false, result = kIDHErrDeviceDisconnected, Exit); 2762 2763 result = (*deviceDescriptionPtr->fDevice->fDevInterface)-> 2764 GetBusCycleTime(deviceDescriptionPtr->fDevice->fDevInterface, &busTime, &cycleTime); 2765 2766 if(result == noErr) { 2767 cycles = busTime * 8000; // Seconds converted to cycles 2768 cycles += (cycleTime >> 12) & 0x1fff; // Extract cycle count from cyletime register 2769 2770 time->value.lo = cycles & 0xffffffff; 2771 time->value.hi = (cycles >> 32) & 0xffffffff; 2772 time->scale = 8000; 2773 } 2774Exit: 2775 return result; 2776} 2777 2778static pascal ComponentResult 2779FWDVIDHNewNotification(IsochComponentInstancePtr ihc, IDHDeviceID deviceID, 2780 IDHNotificationProc notificationProc, void* userData, IDHNotificationID* notificationID) 2781{ 2782 UInt32 i; 2783 Boolean addedClient = false; 2784 OSStatus result = noErr; 2785 IsochComponentGlobalsPtr g = &globals; 2786 2787 RecordEventLogger( 'isoc', 'new ', 'noti', 'fy '); 2788 2789 FailWithAction( notificationProc == nil, result = paramErr, Exit); 2790 FailWithAction( notificationID == nil, result = paramErr, Exit); 2791 2792 i = 0; 2793 while (i < kMaxNotifications) 2794 { 2795 if (0 == g->clientNotification[i].deviceID) 2796 { 2797 g->clientNotification[i].deviceID = deviceID; 2798 g->clientNotification[i].notificationProc = notificationProc; 2799 g->clientNotification[i].events = 0; 2800 g->clientNotification[i].userData = userData; 2801 *notificationID = (UInt32)&g->clientNotification[i]; 2802 addedClient = true; 2803 break; 2804 } 2805 2806 ++i; 2807 } 2808 2809 if (!addedClient) // List is full. Unable to add addtional clients 2810 result = paramErr; 2811 2812Exit: 2813 return result; 2814} 2815 2816static pascal ComponentResult 2817FWDVIDHNotifyMeWhen(ComponentInstance idh, IDHNotificationID notificationID, IDHEvent events) 2818{ 2819 OSStatus result = noErr; 2820 ClientNotification* clientNotification = (ClientNotification*)notificationID; 2821 2822 RecordEventLogger( 'isoc', 'noti', 'when', events); 2823 2824 FailWithAction( clientNotification == nil, result = paramErr, Exit); 2825 2826 clientNotification->events = events; 2827 2828Exit: 2829 return result; 2830} 2831 2832static pascal ComponentResult 2833FWDVIDHCancelNotification(ComponentInstance idh, IDHNotificationID notificationID) 2834{ 2835 OSStatus result = noErr; 2836 ClientNotification* clientNotification = (ClientNotification*)notificationID; 2837 2838 RecordEventLogger( 'isoc', 'canc', 'el ', 'noti'); 2839 2840 FailWithAction( clientNotification == nil, result = paramErr, Exit); 2841 2842 clientNotification->events = 0; 2843 2844Exit: 2845 return result; 2846} 2847 2848static pascal ComponentResult 2849FWDVIDHDisposeNotification(ComponentInstance idh, IDHNotificationID notificationID) 2850{ 2851 OSStatus result = noErr; 2852 ClientNotification* clientNotification = (ClientNotification*)notificationID; 2853 2854 RecordEventLogger( 'isoc', 'disp', 'ose ', 'noti'); 2855 2856 FailWithAction( clientNotification == nil, result = paramErr, Exit); 2857 2858 clientNotification->deviceID = 0; 2859 2860Exit: 2861 return result; 2862} 2863 2864static pascal ComponentResult 2865FWDVIDHSetFormat(IsochComponentInstancePtr ih, UInt32 format) 2866{ 2867 OSStatus result = noErr; 2868 DeviceDescription *deviceDescriptionPtr; 2869 2870 RecordEventLogger( 'isoc', 'setf', 'ormt', format); 2871 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2872 2873 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2874 FailWithVal( result != noErr, Exit, result); 2875 2876 deviceDescriptionPtr->fOutputMode = format << 2; // Get STYPE field into position 2877 if(deviceDescriptionPtr->fDevice->standard != ntscIn) 2878 deviceDescriptionPtr->fOutputMode |= 0x80; // PAL flag 2879 2880Exit: 2881 return result; 2882} 2883 2884static pascal ComponentResult 2885FWDVIDHGetFormat(IsochComponentInstancePtr ih, UInt32 *format) 2886{ 2887 OSStatus result = noErr; 2888 DeviceDescription *deviceDescriptionPtr; 2889 2890 RecordEventLogger( 'isoc', 'getf', 'ormt', format); 2891 FailWithAction( ih->deviceID == nil, result = kIDHErrDeviceNotConfigured, Exit); 2892 2893 result = findDeviceDescriptionforDevice( ih, ih->deviceID, &deviceDescriptionPtr); 2894 FailWithVal( result != noErr, Exit, result); 2895 2896 *format = (deviceDescriptionPtr->fOutputMode >> 2) & 0x1f; // Return just STYPE field, in bottom bits 2897 2898Exit: 2899 return result; 2900} 2901 2902/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2903 2904#define DoCDispatchWS(x,p,s) \ 2905 case k ## x ## Select: \ 2906 /* printf("FWDV" #x "{"); */ \ 2907 { ComponentResult err; \ 2908 err = CallComponentFunctionWithStorageProcInfo( s, p, (ProcPtr) FWDV ## x, \ 2909 uppCall ## x ## ProcInfo ); \ 2910 /* printf("%ld}\n", err); */ \ 2911 return err; } 2912 2913#define DoDispatchWS(x,p,s) \ 2914 case k ## x ## Select: \ 2915 /* printf("FWDV" #x "{"); */ \ 2916 { ComponentResult err; \ 2917 err = CallComponentFunctionWithStorageProcInfo( s, p, (ProcPtr) FWDV ## x, \ 2918 upp ## x ## ProcInfo ); \ 2919 /* printf("%ld}\n", err); */ \ 2920 return err; } 2921 2922 2923static pascal ComponentResult 2924FWDVComponentCanDo(IsochComponentInstancePtr storage, short selector) 2925{ 2926 ComponentResult result; 2927 RecordEventLogger( 'isoc', 'cand', 0, 0); 2928 2929 switch(selector) { 2930 /* Standard selectors */ 2931 case kComponentOpenSelect: 2932 case kComponentCloseSelect: 2933 case kComponentCanDoSelect: 2934 case kComponentVersionSelect: 2935 2936 /* IDH selectors */ 2937 case kIDHGetDeviceListSelect: 2938 case kIDHGetDeviceConfigurationSelect: 2939 case kIDHSetDeviceConfigurationSelect: 2940 case kIDHGetDeviceStatusSelect: 2941 case kIDHGetDeviceClockSelect: 2942 case kIDHOpenDeviceSelect: 2943 case kIDHCloseDeviceSelect: 2944 case kIDHReadSelect: 2945 case kIDHWriteSelect: 2946 case kIDHNewNotificationSelect: 2947 case kIDHNotifyMeWhenSelect: 2948 case kIDHCancelNotificationSelect: 2949 case kIDHDisposeNotificationSelect: 2950 case kIDHReleaseBufferSelect: 2951 case kIDHCancelPendingIOSelect: 2952 case kIDHGetDeviceControlSelect: 2953 case kIDHUpdateDeviceListSelect: 2954 case kIDHGetDeviceTimeSelect: 2955 case kIDHSetFormatSelect: 2956 case kIDHGetFormatSelect: 2957 return(true); 2958 2959 default: 2960 RecordEventLogger( 'isoc', 'cant', selector, 0); 2961 result = false; 2962 return (result); 2963 } 2964} 2965 2966 2967pascal ComponentResult 2968FWDVICodecComponentDispatch(ComponentParameters *params, char ** storage) 2969{ 2970 ComponentResult result; 2971 2972 /* If the selector is less than zero, it's a Component manager selector. */ 2973 2974 if ( params->what < 0 ) { 2975 switch ( params->what ) { 2976 DoCDispatchWS( ComponentOpen, params, storage ); 2977 DoCDispatchWS( ComponentClose, params, storage ); 2978 DoCDispatchWS( ComponentRegister, params, storage ); 2979 DoCDispatchWS( ComponentCanDo, params, storage ); 2980 DoCDispatchWS( ComponentVersion, params, storage ); 2981 2982 default : 2983 return (paramErr); 2984 } 2985 } 2986 2987 /* 2988 * Here we dispatch the rest of our calls. We use the magic thing manager routine which 2989 * calls our subroutines with the proper parameters. The prototypes are in Image Codec.h. 2990 */ 2991 switch ( params->what ) { 2992 DoDispatchWS( IDHGetDeviceList, params, storage ); 2993 DoDispatchWS( IDHGetDeviceConfiguration, params, storage ); 2994 DoDispatchWS( IDHSetDeviceConfiguration, params, storage ); 2995 DoDispatchWS( IDHGetDeviceStatus, params, storage ); 2996 DoDispatchWS( IDHGetDeviceClock, params, storage ); 2997 DoDispatchWS( IDHOpenDevice, params, storage ); 2998 DoDispatchWS( IDHCloseDevice, params, storage ); 2999 DoDispatchWS( IDHRead, params, storage ); 3000 DoDispatchWS( IDHWrite, params, storage ); 3001 DoDispatchWS( IDHReleaseBuffer, params, storage ); 3002 DoDispatchWS( IDHCancelPendingIO, params, storage ); 3003 DoDispatchWS( IDHGetDeviceControl, params, storage ); 3004 DoDispatchWS( IDHUpdateDeviceList, params, storage ); 3005 DoDispatchWS( IDHGetDeviceTime, params, storage ); 3006 DoDispatchWS( IDHNewNotification, params, storage ); 3007 DoDispatchWS( IDHNotifyMeWhen, params, storage ); 3008 DoDispatchWS( IDHCancelNotification, params, storage ); 3009 DoDispatchWS( IDHDisposeNotification, params, storage ); 3010 DoDispatchWS( IDHSetFormat, params, storage ); 3011 DoDispatchWS( IDHGetFormat, params, storage ); 3012 3013 default: 3014 { 3015 int len = params->paramSize/4; 3016 int i; 3017 printf("IDH unimp:%d %d ", params->what, params->paramSize); 3018 for(i=0; i<len; i++) 3019 printf("0x%lx ", params->params[i]); 3020 printf("\n"); 3021 result = paramErr; 3022 return(result); 3023 } 3024 } 3025} 3026 3027#ifdef DRAWRINGBUFFERGRAPH 3028 3029static void SetUpBlitGlobals(DeviceDescriptionPtr ddp) 3030{ 3031 GDHandle gdh = GetMainDevice(); 3032if (gdh) 3033 { 3034 ddp->fScreenBaseAddr = gdh[0]->gdPMap[0]->baseAddr; 3035 ddp->fRowBytes = gdh[0]->gdPMap[0]->rowBytes & 0x3FFF; 3036 ddp->fPixDepth = gdh[0]->gdPMap[0]->pixelSize; 3037 } 3038} 3039 3040#define spacerColour 0xFFFF 3041#define unusedColour 0x0000 3042#define emptyColour (16<<10) + (16<<5) +(16) 3043#define hasDataColour (0<<10) + (31<<5) +(0) 3044#define readColour (31<<10) + (31<<5) +(0) 3045#define writeColour (0<<10) + (31<<5) +(31) 3046#define collisionColour (31<<10) + (0<<5) +(0) 3047 3048static void BlitBufferGraph(DeviceDescriptionPtr ddp) 3049{ 3050 short * line0Ptr = nil; 3051 short * line00Ptr = nil; 3052 short * line1Ptr = nil; 3053 short * line2Ptr = nil; 3054 short * line3Ptr = nil; 3055 short buffCol = 0; 3056 long flags =0; 3057 int x,i,read,write; 3058 if (ddp->fPixDepth != 16 || ddp->fScreenBaseAddr ==0 || ddp->fRowBytes ==0) 3059 return; 3060 line00Ptr =(short*) (ddp->fScreenBaseAddr + ddp->fRowBytes*18-ddp->fRowBytes/4); 3061 line0Ptr =(short*) (ddp->fScreenBaseAddr + ddp->fRowBytes*19-ddp->fRowBytes/4); 3062 line1Ptr =(short*) (ddp->fScreenBaseAddr + ddp->fRowBytes*16-ddp->fRowBytes/4); 3063 line2Ptr =(short*) (ddp->fScreenBaseAddr + ddp->fRowBytes*17-ddp->fRowBytes/4); 3064 line3Ptr =(short*) (ddp->fScreenBaseAddr + ddp->fRowBytes*15-ddp->fRowBytes/4); 3065 read = ddp->fSharedVars->fReader % ddp->fNumOutputFrames; 3066 write = ddp->fSharedVars->fWriter % ddp->fNumOutputFrames; 3067 for(x =0;x < ddp->fNumOutputFrames; x++) 3068 { 3069 *line1Ptr++ = (short)spacerColour; 3070 *line2Ptr++ = (short)spacerColour; 3071 *line0Ptr++ = (short)spacerColour; 3072 *line00Ptr++ = (short)spacerColour; 3073 3074 for(i=0;i<ddp->fBufferLocks[x];i++) { 3075 short* beardPtr = line0Ptr+ddp->fRowBytes*i*2; 3076 *beardPtr++ = unusedColour; 3077 *beardPtr++ = unusedColour; 3078 *beardPtr++ = unusedColour; 3079 *beardPtr++ = unusedColour; 3080 } 3081 3082 if (ddp->fBufferLocks[x]) { 3083 buffCol = hasDataColour; 3084 } else { 3085 buffCol = emptyColour; 3086 } 3087 *line1Ptr++ = buffCol; 3088 *line1Ptr++ = buffCol; 3089 *line1Ptr++ = buffCol; 3090 *line1Ptr++ = buffCol; 3091 3092 *line2Ptr++ = buffCol; 3093 *line2Ptr++ = buffCol; 3094 *line2Ptr++ = buffCol; 3095 *line2Ptr++ = buffCol; 3096 3097 buffCol = (short)spacerColour; 3098 if (read == x) 3099 buffCol = readColour; 3100 if (write == x) 3101 { 3102 if (buffCol == readColour) 3103 buffCol = collisionColour; 3104 else 3105 buffCol = writeColour; 3106 } 3107 *line00Ptr++ = buffCol; 3108 *line00Ptr++ = buffCol; 3109 *line00Ptr++ = buffCol; 3110 *line00Ptr++ = buffCol; 3111 3112 *line0Ptr++ = buffCol; 3113 *line0Ptr++ = buffCol; 3114 *line0Ptr++ = buffCol; 3115 *line0Ptr++ = buffCol; 3116 } 3117 3118 3119} 3120#endif 3121 3122