static GVBool gviHardwareInitCapture(GVIDevice * device) { GVIHardwareData * data = (GVIHardwareData *)device->m_data; UInt32 size; OSStatus result; GVICapturedFrame * frame; int numCaptureBufferBytes; int numCaptureBufferFrames; int i; // get the capture format size = sizeof(AudioStreamBasicDescription); result = AudioDeviceGetProperty(device->m_deviceID, 0, true, kAudioDevicePropertyStreamFormat, &size, &data->m_captureStreamDescriptor); if(result != noErr) return GVFalse; // create a converter from the capture format to the GV format result = AudioConverterNew(&data->m_captureStreamDescriptor, &GVIVoiceFormat, &data->m_captureConverter); if(result != noErr) return GVFalse; // allocate a capture buffer data->m_captureBuffer = (GVSample *)gsimalloc(GVIBytesPerFrame); if(!data->m_captureBuffer) { AudioConverterDispose(data->m_captureConverter); return GVFalse; } // allocate space for holding captured frames numCaptureBufferBytes = gviMultiplyByBytesPerMillisecond(GVI_CAPTURE_BUFFER_MILLISECONDS); numCaptureBufferBytes = gviRoundUpToNearestMultiple(numCaptureBufferBytes, GVIBytesPerFrame); numCaptureBufferFrames = (numCaptureBufferBytes / GVIBytesPerFrame); for(i = 0 ; i < numCaptureBufferFrames ; i++) { frame = (GVICapturedFrame *)gsimalloc(sizeof(GVICapturedFrame) + GVIBytesPerFrame - sizeof(GVSample)); if(!frame) { gviFreeCapturedFrames(&data->m_captureAvailableFrames); gsifree(data->m_captureBuffer); AudioConverterDispose(data->m_captureConverter); return GVFalse; } gviPushFirstFrame(&data->m_captureAvailableFrames, frame); } // init the last crossed time data->m_captureLastCrossedThresholdTime = (data->m_captureClock - GVI_HOLD_THRESHOLD_FRAMES - 1); // add property listener AudioDeviceAddPropertyListener(device->m_deviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, gviPropertyListener, device); #if GVI_VOLUME_IN_SOFTWARE // init volume data->m_captureVolume = (GVScalar)1.0; #endif return GVTrue; }
SCResult SC_CALL sciCreateReport(gsi_u8 theSessionGuid[SC_SESSION_GUID_SIZE], gsi_u32 theHeaderVersion, gsi_u32 thePlayerCount, gsi_u32 theTeamCount, SCIReport ** theReportOut) { SCIReport * theNewReport; SCIReportHeader * theReportHeader; gsi_u8 * theReportData; // roster is [CCID (16) + TeamIndex (4)] * numplayers const gsi_u32 theRosterSize = SC_GUID_BINARY_SIZE * thePlayerCount + SC_REPORT_TEAMINDEX_LENGTH * thePlayerCount; GS_ASSERT(theReportOut != NULL); // allocate the report //GS_ASSERT(0); // todo: memalignment theNewReport = (SCIReport*)gsimalloc(sizeof(SCIReport)); if (theNewReport == NULL) return SCResult_OUT_OF_MEMORY; memset(theNewReport, 0, sizeof(SCIReport)); // allocate the report buffer (holds submission data) theReportData = (gsi_u8*)gsimalloc(SC_REPORT_BUFFER_BYTES); if (theReportData == NULL) { gsifree(theNewReport); return SCResult_OUT_OF_MEMORY; } memset(theReportData, 0, SC_REPORT_BUFFER_BYTES); theNewReport->mBuffer.mIsStatic = gsi_false; theNewReport->mBuffer.mCapacity = SC_REPORT_BUFFER_BYTES; // Fill in report header theReportHeader = (SCIReportHeader*)theReportData; memset(theReportHeader, 0, sizeof(SCIReportHeader)); theReportHeader->mProtocolVersion = htonl(SC_REPORT_PROTOCOL); theReportHeader->mDeveloperVersion = htonl(theHeaderVersion); theReportHeader->mRosterSectionLength = theRosterSize; theReportHeader->mAuthSectionLength = SC_REPORT_AUTHDATA_LENGTH * thePlayerCount; theReportHeader->mResultsSectionLength = SC_REPORT_ENTITYRESULT_LENGTH * (thePlayerCount + theTeamCount); theReportHeader->mPlayerCount = (gsi_u16)thePlayerCount; theReportHeader->mTeamCount = (gsi_u16)theTeamCount; //theReportHeader->mFlags = (gsi_u32)theOptionsFlags; // Finished, return new report theNewReport->mReportState = SCIReportState_ROSTER; theNewReport->mBuffer.mData = (char *)theReportData; theNewReport->mCurEntityStartPos = -1; theNewReport->mNumTeamsReported = 0; *theReportOut = theNewReport; GSI_UNUSED(theSessionGuid); return SCResult_NO_ERROR; }
static GVIPendingFrame * gviNewPendingFrame(void) { GVIPendingFrame * frame; // allocate a new frame #if GVI_PRE_DECODE frame = (GVIPendingFrame *)gsimalloc(sizeof(GVIPendingFrame) + GVIBytesPerFrame - sizeof(GVSample)); #else frame = (GVIPendingFrame *)gsimalloc(sizeof(GVIPendingFrame) + GVIEncodedFrameSize - 1); #endif // return it return frame; }
gsi_u32 wsLoginRemoteAuth(int partnerCode, int namespaceId, const gsi_char authtoken[WS_LOGIN_AUTHTOKEN_LEN], const gsi_char partnerChallenge[WS_LOGIN_PARTNERCHALLENGE_LEN], WSLoginCallback userCallback, void * userData) { GSXmlStreamWriter writer; WSIRequestData * requestData = NULL; //gsi_u8 encryptedChallenge[GS_CRYPT_RSA_BYTE_SIZE]; if (!wsiServiceAvailable()) return WSLogin_NoAvailabilityCheck; GS_ASSERT(partnerCode >= 0); // allocate the request values requestData = (WSIRequestData*)gsimalloc(sizeof(WSIRequestData)); if (requestData == NULL) return WSLogin_OutOfMemory; requestData->mUserCallback.mLoginCallback = userCallback; requestData->mUserData = userData; // encrypt the password (includes safety padding and hash) //wsiLoginEncryptPassword(partnerChallenge, encryptedChallenge); // create the xml request writer = gsXmlCreateStreamWriter(WS_AUTHSERVICE_NAMESPACES, WS_AUTHSERVICE_NAMESPACE_COUNT); if (writer != NULL) { GSSoapTask * aTask = NULL; if (gsi_is_false(gsXmlWriteOpenTag (writer, WS_AUTHSERVICE_NAMESPACE, WS_AUTHSERVICE_LOGINREMOTEAUTH)) || gsi_is_false(gsXmlWriteIntElement (writer, WS_AUTHSERVICE_NAMESPACE, "version", WS_AUTHSERVICE_PROTOVERSION)) || gsi_is_false(gsXmlWriteIntElement (writer, WS_AUTHSERVICE_NAMESPACE, "partnercode", (gsi_u32)partnerCode)) || gsi_is_false(gsXmlWriteIntElement (writer, WS_AUTHSERVICE_NAMESPACE, "namespaceid", (gsi_u32)namespaceId)) || gsi_is_false(gsXmlWriteTStringElement(writer, WS_AUTHSERVICE_NAMESPACE, "authtoken", authtoken)) || gsi_is_false(gsXmlWriteTStringElement(writer, WS_AUTHSERVICE_NAMESPACE, "challenge", partnerChallenge)) || //gsi_is_false(gsXmlWriteOpenTag (writer, WS_AUTHSERVICE_NAMESPACE, "challenge")) || //gsi_is_false(gsXmlWriteHexBinaryElement(writer, WS_AUTHSERVICE_NAMESPACE, "Value", encryptedChallenge, GS_CRYPT_RSA_BYTE_SIZE)) || //gsi_is_false(gsXmlWriteCloseTag (writer, WS_AUTHSERVICE_NAMESPACE, "challenge")) || gsi_is_false(gsXmlWriteCloseTag (writer, WS_AUTHSERVICE_NAMESPACE, WS_AUTHSERVICE_LOGINREMOTEAUTH)) || gsi_is_false(gsXmlCloseWriter (writer)) ) { gsXmlFreeWriter(writer); return WSLogin_OutOfMemory; } aTask = gsiExecuteSoap(wsAuthServiceURL, WS_AUTHSERVICE_LOGINREMOTEAUTH_SOAP, writer, wsLoginRemoteAuthCallback, (void*)requestData); if (aTask == NULL) { gsXmlFreeWriter(writer); gsifree(requestData); return WSLogin_OutOfMemory; } } return 0; }
SCResult sciInterfaceCreate(SCInterface** theInterfaceOut) { #ifdef GSI_SC_STATIC_MEM static SCInterface gStaticInterface; #endif GS_ASSERT(theInterfaceOut != NULL); // Check to see if the availability check has been performed and if it has // set the service URL prepended with the gamename if (__GSIACResult == GSIACAvailable) { if (scServiceURL[0] == '\0') snprintf(scServiceURL, SC_SERVICE_MAX_URL_LEN, SC_SERVICE_URL_FORMAT, __GSIACGamename); } else return SCResult_NO_AVAILABILITY_CHECK; #ifdef GSI_SC_STATIC_MEM *theInterfaceOut = &gStaticInterface; #else *theInterfaceOut = (SCInterface*)gsimalloc(sizeof(SCInterface)); if (*theInterfaceOut == NULL) { return SCResult_OUT_OF_MEMORY; } #endif GS_ASSERT(*theInterfaceOut != NULL); memset(*theInterfaceOut, 0, sizeof(SCInterface)); return SCResult_NO_ERROR; }
GPIPeer * gpiAddPeer( GPConnection * connection, int profileid, GPIBool initiate ) { GPIPeer * peer; GPIConnection * iconnection = (GPIConnection*)*connection; // Create a new peer. ///////////////////// peer = (GPIPeer *)gsimalloc(sizeof(GPIPeer)); if(peer == NULL) return NULL; memset(peer, 0, sizeof(GPIPeer)); peer->state = GPI_PEER_NOT_CONNECTED; peer->initiated = initiate; //peer->sock = INVALID_SOCKET; peer->profile = profileid; peer->timeout = (time(NULL) + GPI_PEER_TIMEOUT); peer->pnext = iconnection->peerList; peer->messages = ArrayNew(sizeof(GPIMessage), 0, gpiFreeMessage); iconnection->peerList = peer; peer->peerOpQueue.first = NULL; peer->peerOpQueue.last = NULL; peer->peerOpQueue.opList = NULL; return peer; }
// Used to check for any timed out peer operations // assumes peer is not NULL // makes no assumption of the operation queue void gpiCheckTimedOutPeerOperations(GPConnection * connection, GPIPeer *peer) { GPIPeerOp *anIterator = peer->peerOpQueue.first; GS_ASSERT(peer); if (!peer) return; while (anIterator && anIterator != peer->peerOpQueue.last) { if (anIterator->state != GPI_PEER_OP_STATE_FINISHED && current_time() > anIterator->timeout && anIterator->callback) { // currently only one type of peer operation exists // when it's found, we need to provide the application with // a result of no data if (anIterator->type == GPI_BM_KEYS_REQUEST) { GPICallback callback; GPGetBuddyStatusInfoKeysArg *arg = (GPGetBuddyStatusInfoKeysArg *)gsimalloc(sizeof(GPGetBuddyStatusInfoKeysArg)); callback.callback = anIterator->callback; callback.param = anIterator->userData; arg->keys = NULL; arg->numKeys = 0; arg->values = NULL; arg->profile = peer->profile; gpiAddCallback(connection, callback, arg, NULL, 0); } // The peer operation is removed regardless of type gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Misc, GSIDebugLevel_Notice, "Peer operation timed out"); gpiPeerRemoveOp(peer, anIterator); } anIterator = anIterator->next; } }
PTBool ptCreateCheckPatchTrackUsageReqA ( int userID, int productID, const char * versionUniqueID, int distributionID, ptPatchCallback callback, PTBool blocking, int *request, void * param ) { int charsWritten; char aURL[PTA_MAX_STRING_SIZE]; ptaPatchData * data; // check if the backend is available if(__GSIACResult != GSIACAvailable) return PTFalse; // Check the arguments. /////////////////////// assert(versionUniqueID); if(!versionUniqueID) return PTFalse; assert(callback); if(!callback) return PTFalse; // Store some data. /////////////////// data = (ptaPatchData *)gsimalloc(sizeof(ptaPatchData)); if(!data) return PTFalse; memset(data, 0, sizeof(ptaPatchData)); data->callback = callback; data->param = param; // override hostname? if (gPTAVercheckURL[0] == '\0') sprintf(gPTAVercheckURL, PTA_DEFAULT_VERCHECK_URL); // Build the URL. ///////////////// charsWritten = snprintf(aURL, PTA_MAX_STRING_SIZE, "%s?userid=%d&productid=%d&versionuniqueid=%s&distid=%d&uniqueid=%s&gamename=%s", gPTAVercheckURL, userID, productID, versionUniqueID, distributionID, GOAGetUniqueID(), __GSIACGamename); assert(charsWritten >= 0); if (charsWritten < 0) return PTFalse; // Send the request. //////////////////// *request = ghttpGetFileA(aURL, (GHTTPBool)blocking, ptaPatchCompletedCallback, data); if (*request == -1) return PTFalse; return PTTrue; }
GT2Bool gti2AllocateBuffer(GTI2Buffer * buffer, int size) { buffer->buffer = (GT2Byte *)gsimalloc((unsigned int)size); if(!buffer->buffer) return GT2False; buffer->size = size; return GT2True; }
static GVBool gviPS2EyetoyInitDevice(GVIDevice * device, int deviceIndex, GVDeviceType type) { lgVidDeviceDesc eyetoyDesc; lgVidOpenParam openParam; GVIPS2EyetoyData * data; int result; int size; int i; // we only support capture if(type != GV_CAPTURE) return GVFalse; // enum the device to get a list of supported modes result = lgVidEnumerate(deviceIndex, &eyetoyDesc); if(LGVID_FAILED(result)) return GVFalse; // find a supported device mode //TODO: make this better at choosing the video mode that uses the least CPU and memory (ideally none at all) for(i = 0 ; i < eyetoyDesc.SupportedModesCount ; i++) { if(eyetoyDesc.SupportedModes[i].OperatingMode.AudioRate == LGVID_AUD_8000) break; } if(i == eyetoyDesc.SupportedModesCount) return GVFalse; // setup the open param memcpy(&openParam.OperatingMode, &eyetoyDesc.SupportedModes[i].OperatingMode, sizeof(lgVidOperatingMode)); openParam.AudioBufferDuration = GVI_CAPTURE_BUFFER_MILLISECONDS; // get a pointer to the data data = (GVIPS2EyetoyData *)device->m_data; // open the device result = lgVidOpen(deviceIndex, &openParam, &data->m_handle); if(LGVID_FAILED(result)) return GVFalse; // set some data vars data->m_captureLastCrossedThresholdTime = (GVFrameStamp)(data->m_captureClock - GVI_HOLD_THRESHOLD_FRAMES - 1); // allocate the buffer size = (GVI_CAPTURE_BUFFER_MILLISECONDS * GV_BYTES_PER_SECOND / 1000); size += GVIBytesPerFrame; data->m_captureBuffer = (GVSample *)gsimalloc((unsigned)size); if(!data->m_captureBuffer) { lgVidClose(data->m_handle); return GVFalse; } return GVTrue; }
bucketset_t NewBucketSet(void) { bucketset_t set; set = (bucketset_t)gsimalloc(sizeof (struct bucketset_s)); assert(set); set->buckets = TableNew(sizeof(bucket_t),32,BucketHash, BucketCompare, BucketFree); g_buckets = set; return set; }
GVBool gviSpeexInitialize(int quality, GVRate sampleRate) { int rate; int bitsPerFrame; int samplesPerSecond; // we shouldn't already be initialized if(gviSpeexInitialized) return GVFalse; // create a new encoder state if (sampleRate == GVRate_8KHz) gviSpeexEncoderState = speex_encoder_init(&speex_nb_mode); else if (sampleRate == GVRate_16KHz) gviSpeexEncoderState = speex_encoder_init(&speex_wb_mode); else return GVFalse; if(!gviSpeexEncoderState) return GVFalse; // set the sampling rate samplesPerSecond = sampleRate; speex_encoder_ctl(gviSpeexEncoderState, SPEEX_SET_SAMPLING_RATE, &samplesPerSecond); // Get the samples per frame setting. speex_encoder_ctl(gviSpeexEncoderState, SPEEX_GET_FRAME_SIZE, &gviSpeexSamplesPerFrame); // set the quality speex_encoder_ctl(gviSpeexEncoderState, SPEEX_SET_QUALITY, &quality); // initialize the bits struct speex_bits_init(&gviSpeexBits); // get the bitrate speex_encoder_ctl(gviSpeexEncoderState, SPEEX_GET_BITRATE, &rate); // convert to bits per frame bitsPerFrame = (rate / (sampleRate / gviSpeexSamplesPerFrame)); // convert to bytes per frame and store, round up to allocate more space than needed. gviSpeexEncodedFrameSize = (bitsPerFrame / 8); if (bitsPerFrame % 8) gviSpeexEncodedFrameSize++; // create our encoding and decoding buffer. gviSpeexBuffer = (float *)gsimalloc(gviSpeexSamplesPerFrame * sizeof(float)); // we're now initialized gviSpeexInitialized = GVTrue; return GVTrue; }
// Creates a lock. ////////////////// static GLock GNewLock(void) { CRITICAL_SECTION * criticalSection; criticalSection = (CRITICAL_SECTION *)gsimalloc(sizeof(CRITICAL_SECTION)); if(!criticalSection) return NULL; InitializeCriticalSection(criticalSection); return (GLock)criticalSection; }
char *DumpBucketSet(bucketset_t set) { dumpdata_t data; if (set == NULL) set = g_buckets; assert(set); data.data = (char *)gsimalloc(128); //alloc an initial buffer data.data[0] = 0; data.len = 0; data.maxlen = 128; TableMap(set->buckets,DumpMap, &data); return data.data; }
GPResult gpiAddOperation( GPConnection * connection, int type, void * data, GPIOperation ** op, GPEnum blocking, GPCallback callback, void * param ) { GPIOperation * operation; GPIConnection * iconnection = (GPIConnection*)*connection; // Create a new operation struct. ///////////////////////////////// operation = (GPIOperation *)gsimalloc(sizeof(GPIOperation)); if(operation == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); // Set the data. //////////////// operation->type = type; operation->data = data; operation->blocking = (GPIBool)blocking; operation->state = GPI_START; if(type == GPI_CONNECT) { // Connect is always ID 1. ////////////////////////// operation->id = 1; } else { operation->id = iconnection->nextOperationID++; if(iconnection->nextOperationID < 2) iconnection->nextOperationID = 2; } operation->result = GP_NO_ERROR; operation->callback.callback = callback; operation->callback.param = param; // Add it to the list. ////////////////////// operation->pnext = iconnection->operationList; iconnection->operationList = operation; *op = operation; return GP_NO_ERROR; }
DArray ArrayNew(int elemSize, int numElemsToAllocate, ArrayElementFreeFn elemFreeFn) { DArray array; array = (DArray) gsimalloc(sizeof(struct DArrayImplementation)); GS_ASSERT(array); GS_ASSERT(elemSize); if (numElemsToAllocate == 0) numElemsToAllocate = DEF_GROWBY; array->count = 0; array->capacity = numElemsToAllocate;; array->elemsize = elemSize; array->growby = numElemsToAllocate; array->elemfreefn = elemFreeFn; if (array->capacity != 0) { array->list = gsimalloc((size_t)array->capacity * array->elemsize); GS_ASSERT(array->list); } else array->list = NULL; return array; }
// 9/7/2004 (xgd) ptLookupFilePlanetInfo() deprecated; per case 2724. // PTBool ptLookupFilePlanetInfo ( int fileID, ptFilePlanetInfoCallback callback, PTBool blocking, void * param ) { char aURL[PTA_MAX_STRING_SIZE]; ptaFilePlanetInfoData * data; // Check the arguments. /////////////////////// assert(callback); if(!callback) return PTFalse; // override hostname? if (gPTAFilePlanetURL[0] == '\0') sprintf(gPTAFilePlanetURL, PTA_DEFAULT_FILEPLANET_URL); // Store some data. /////////////////// data = (ptaFilePlanetInfoData *)gsimalloc(sizeof(ptaFilePlanetInfoData)); if(!data) return PTFalse; memset(data, 0, sizeof(ptaFilePlanetInfoData)); data->callback = callback; data->param = param; data->fileID = fileID; // Build the URL. ///////////////// // 11/24/2004 - Added By Saad Nader // Now using string size as limit for printing // also null terminate string automatically /////////////////////////////////////////////// snprintf(aURL, PTA_MAX_STRING_SIZE, "%s?file=%d&gamename=%s", gPTAFilePlanetURL, fileID, __GSIACGamename); // Send the request. //////////////////// if((ghttpGetFileA(aURL, (GHTTPBool)blocking, ptaFilePlanetCompletedCallback, data) == -1) && !blocking) return PTFalse; return PTTrue; }
/*********** ** BUFFER ** ***********/ static CHATBool ciBufferInit(ciBuffer * buffer) { assert(buffer != NULL); buffer->length = 0; buffer->size = BUFFER_INC; buffer->buffer = (char *)gsimalloc((unsigned int)buffer->size + 1); if(buffer->buffer == NULL) return CHATFalse; // Just for fun. //////////////// buffer->buffer[0] = '\0'; return CHATTrue; }
void *BucketConcat(bucketset_t set, char *name, void *value) { bucket_t *pbucket = DoFind(set, name); char *temp, *s; if (!pbucket) return NULL; assert(pbucket->type == bt_string); s = DoGet(pbucket); temp = (char *)gsimalloc(strlen(s) + strlen(value) + 1); strcpy(temp,s); strcat(temp, value); DoSet(pbucket, temp); gsifree(temp); return DoGet(pbucket); }
ServerBrowser ServerBrowserNewA(const char *queryForGamename, const char *queryFromGamename, const char *queryFromKey, int queryFromVersion, int maxConcUpdates, int queryVersion, SBBool lanBrowse, ServerBrowserCallback callback, void *instance) { ServerBrowser sb; if(lanBrowse == SBFalse) { if(__GSIACResult != GSIACAvailable) return NULL; } sb = (ServerBrowser)gsimalloc(sizeof(struct _ServerBrowser)); if (sb == NULL) return NULL; sb->BrowserCallback = callback; sb->instance = instance; sb->dontUpdate = SBFalse; SBServerListInit(&sb->list, queryForGamename, queryFromGamename, queryFromKey, queryFromVersion, lanBrowse, ListCallback, sb); SBQueryEngineInit(&sb->engine, maxConcUpdates, queryVersion, lanBrowse, EngineCallback, sb); return sb; }
static int gviCountChannels(AudioDeviceID deviceID, bool input) { OSStatus result; UInt32 size; AudioBufferList * list; int numChannels; int i; // get the size of the buffer list result = AudioDeviceGetPropertyInfo(deviceID, 0, input, kAudioDevicePropertyStreamConfiguration, &size, NULL); if(result != noErr) return 0; // allocate the buffer list list = (AudioBufferList *)gsimalloc(size); if(list == NULL) return 0; // fill the buffer list result = AudioDeviceGetProperty(deviceID, 0, input, kAudioDevicePropertyStreamConfiguration, &size, list); if(result != noErr) { gsifree(list); return 0; } // count the number of channels numChannels = 0; for(i = 0 ; i < list->mNumberBuffers ; i++) numChannels += list->mBuffers[i].mNumberChannels; // free the list gsifree(list); return numChannels; }
static CHATBool ciAddParam(const char *param, ciServerMessage * message) { void * tempPtr; // Reallocate the parameter array. ////////////////////////////////// tempPtr = gsirealloc(message->params, sizeof(char *) * (message->numParams + 1)); if(tempPtr == NULL) return CHATFalse; //ERRCON message->params = (char **)tempPtr; // Allocate mem for the param. ////////////////////////////// tempPtr = gsimalloc(strlen(param) + 1); if(tempPtr == NULL) return CHATFalse; //ERRCON // Copy the param. ////////////////// strcpy((char *)tempPtr, param); message->params[message->numParams++] = (char *)tempPtr; return CHATTrue; }
/********************** ** RECEIVING HEADERS ** **********************/ void ghiDoReceivingHeaders ( GHIConnection * connection ) { char buffer[4096]; int bufferLen; GHIRecvResult result; GHTTPBool hasHeaders = GHTTPTrue; char * headers; char * endOfHeaders = NULL; gsDebugFormat(GSIDebugCat_HTTP, GSIDebugType_State, GSIDebugLevel_Comment, "Receiving Headers\n"); // Get data. //////////// bufferLen = sizeof(buffer); result = ghiDoReceive(connection, buffer, &bufferLen); // Handle error, no data, conn closed. ////////////////////////////////////// if(result == GHIError) return; if(result == GHINoData) return; // Only append data if we got data. /////////////////////////////////// if(result == GHIRecvData) { // Check for encryption. //////////////////////// if (connection->encryptor.mEngine != GHTTPEncryptionEngine_None) { // Append new encrypted data to anything we've held over // We have to do this because we can't decrypt partial SSL messages if (!ghiAppendDataToBuffer(&connection->decodeBuffer, buffer, bufferLen)) return; // Decrypt as much as we can if (!ghiDecryptReceivedData(connection)) { connection->completed = GHTTPTrue; connection->result = GHTTPEncryptionError; return; } } else { // Add the data directly to the buffer. /////////////////////////////////////// if(!ghiAppendDataToBuffer(&connection->recvBuffer, buffer, bufferLen)) return; } } // Cache a pointer to the front of the headers. /////////////////////////////////////////////// headers = (connection->recvBuffer.data + connection->headerStringIndex); // Check if the headers are finished. ///////////////////////////////////// if( ((connection->statusCode / 100) == 1) && (strncmp(headers, "\r\n", 2) == 0 || strncmp(headers, "\xA\xA", 2) == 0) ) { // If a continue doesn't have a header (immediate CRLF) move on to next status endOfHeaders = headers; hasHeaders = GHTTPFalse; } else { endOfHeaders = strstr(headers, CRLF CRLF); } if(!endOfHeaders) { endOfHeaders = strstr(headers, "\xA\xA"); // some servers seem to use LFs only?! Seen in 302 redirect. (28may01/bgw) } if(endOfHeaders) { char * fileStart; int fileLength; //int headersLength; char * contentLength; #ifdef HTTP_LOG int headersLength; #endif // Clear off the empty line. //////////////////////////// if (GHTTPTrue == hasHeaders) endOfHeaders += 2; *endOfHeaders = '\0'; // Figure out where the file starts, and how many bytes. //////////////////////////////////////////////////////// #ifdef HTTP_LOG headersLength = (endOfHeaders - headers); #endif fileStart = (endOfHeaders + 2); fileLength = (connection->recvBuffer.len - (fileStart - connection->recvBuffer.data)); // Set the headers buffer's new length. /////////////////////////////////////// connection->recvBuffer.len = (endOfHeaders - connection->recvBuffer.data + 1); connection->recvBuffer.pos = connection->recvBuffer.len; // Log it. ////////// #ifdef HTTP_LOG ghiLogResponse(headers, headersLength); ghiLogResponse("\n", 1); #endif // Check for continue. ////////////////////// if((connection->statusCode / 100) == 1) { if(fileLength) { // Move any data to the front of the buffer. //////////////////////////////////////////// memmove(connection->recvBuffer.data, fileStart, (unsigned int)fileLength + 1); connection->recvBuffer.len = fileLength; } else { // Reset the buffer. ///////////////////////// ghiResetBuffer(&connection->recvBuffer); } // Some posts must wait for continue before uploading // Check if we should return to posting if (connection->postingState.waitPostContinue) { connection->postingState.waitPostContinue = GHTTPFalse; connection->state = GHTTPPosting; ghiCallProgressCallback(connection, NULL, 0); } // We're back to receiving status. ////////////////////////////////// connection->state = GHTTPReceivingStatus; ghiCallProgressCallback(connection, NULL, 0); return; } // Check for redirection. ///////////////////////// if((connection->statusCode / 100) == 3) { char * location; // Are we over our redirection count? ///////////////////////////////////// if(connection->redirectCount > 10) { connection->completed = GHTTPTrue; connection->result = GHTTPFileNotFound; return; } // Find the new location. ///////////////////////// location = strstr(headers, "Location:"); if(location) { char * end; // Find the start of the URL. ///////////////////////////// location += 9; while(isspace(*location)) location++; // Find the end. //////////////// for(end = location; *end && !isspace(*end) ; end++) { }; *end = '\0'; // Check if this is not a full URL. /////////////////////////////////// if(*location == '/') { int len; // Recompose the URL ourselves. /////////////////////////////// len = (int)(strlen(connection->serverAddress) + 13 + strlen(location) + 1); connection->redirectURL = (char *)gsimalloc((unsigned int)len); if(!connection->redirectURL) { connection->completed = GHTTPTrue; connection->result = GHTTPOutOfMemory; } sprintf(connection->redirectURL, "http://%s:%d%s", connection->serverAddress, connection->serverPort, location); } else { // Set the redirect URL. //////////////////////// connection->redirectURL = strdup(location); if(!connection->redirectURL) { connection->completed = GHTTPTrue; connection->result = GHTTPOutOfMemory; } } return; } } // If we know the file-length, set it. ////////////////////////////////////// contentLength = strstr(headers, "Content-Length:"); if(contentLength) { // Verify that the download size is something we can handle /////////////////////////////////////////////////////////// #if (GSI_MAX_INTEGRAL_BITS >= 64) char szMaxSize[] = "9223372036854775807"; // == GSI_MAX_I64 #else char szMaxSize[] = "2147483647"; // == GSI_MAX_I32 #endif char* pStart = contentLength+16; char* pEnd = pStart; int nMaxLen = (int)strlen(szMaxSize); // Skip to the end of the line while( pEnd && *pEnd != '\0' && *pEnd != '\n' && *pEnd != '\r' && *pEnd != ' ' ) pEnd++; if( pEnd-pStart > nMaxLen ) { // Wow, that IS a big number connection->completed = GHTTPTrue; connection->result = GHTTPFileToBig; return; } else if( pEnd-pStart == nMaxLen ) { // Same length, maybe a bigger number if( strncmp(pStart,szMaxSize,(unsigned int)(pEnd-pStart)) >= 0 ) { connection->completed = GHTTPTrue; connection->result = GHTTPFileToBig; return; } } // Record the full size of the expected download //////////////////////////////////////////////// #if (GSI_MAX_INTEGRAL_BITS >= 64) connection->totalSize = _atoi64(pStart); #else connection->totalSize = atoi(pStart); #endif } // Check the chunky. //////////////////// connection->chunkedTransfer = (strstr(headers, "Transfer-Encoding: chunked") != NULL)?GHTTPTrue:GHTTPFalse; if(connection->chunkedTransfer) { connection->chunkHeader[0] = '\0'; connection->chunkHeaderLen = 0; connection->chunkBytesLeft = 0; connection->chunkReadingState = CRHeader; } // If we're just getting headers, or only posting data, we're done. /////////////////////////////////////////////////////////////////// if((connection->type == GHIHEAD) || (connection->type == GHIPOST)) { connection->completed = GHTTPTrue; return; } // We're receiving file data now. ///////////////////////////////// connection->state = GHTTPReceivingFile; // Is this an empty file? ///////////////////////// if(contentLength && !connection->totalSize) { connection->completed = GHTTPTrue; return; } // If any of the body has arrived, handle it. ///////////////////////////////////////////// if(fileLength > 0) ghiProcessIncomingFileData(connection, fileStart, fileLength); // Don't reset the buffer -- we store status and header info //ghiResetBuffer(&connection->recvBuffer); } else if(result == GHIConnClosed) { // The conn was closed, and we didn't finish the headers - bad. /////////////////////////////////////////////////////////////// connection->completed = GHTTPTrue; connection->result = GHTTPBadResponse; connection->socketError = GOAGetLastError(connection->socket); } }
GPResult gpiRecvToBuffer( GPConnection * connection, SOCKET sock, GPIBuffer * inputBuffer, int * bytesRead, GPIBool * connClosed, char id[3] ) { char * buffer; int len; int size; int rcode; int total; GPIBool closed; assert(sock != INVALID_SOCKET); assert(inputBuffer != NULL); assert(bytesRead != NULL); assert(connClosed != NULL); // Init locals. /////////////// buffer = inputBuffer->buffer; len = inputBuffer->len; size = inputBuffer->size; total = 0; closed = GPIFalse; do { // Check if the buffer needs to be resized. /////////////////////////////////////////// if((len + GPI_READ_SIZE) > size) { size = (len + GPI_READ_SIZE); buffer = (char *)gsirealloc(buffer, (unsigned int)size + 1); if(buffer == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); } // Read from the network. rcode = recv(sock, &buffer[len], size - len, 0); if(gsiSocketIsError(rcode)) { int error = GOAGetLastError(sock); if((error != WSAEWOULDBLOCK) && (error != WSAEINPROGRESS) && (error != WSAETIMEDOUT) ) { Error(connection, GP_NETWORK_ERROR, "There was an error reading from a socket."); } } else if(rcode == 0) { // Check for a closed connection. ///////////////////////////////// closed = GPITrue; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment, "RECVXXXX(%s): Connection closed\n", id); } else { #if defined(GPI_DUMP_NET_TRAFFIC) && defined(GSI_COMMON_DEBUG) { static int recvCount; char *buf = (char *)gsimalloc((size_t)(rcode + 1)); memcpy(buf, &buffer[len], (size_t)rcode); buf[rcode] = '\0'; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "RECV%04d(%s): %s\n", recvCount++, id, buf); freeclear(buf); } #elif defined(GSI_COMMON_DEBUG) { static int recvCount; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "RECV%04d(%s): %d\n", recvCount++, id, rcode); } #endif // Update the buffer len. ///////////////////////// len += rcode; // Update the total. //////////////////// total += rcode; } buffer[len] = '\0'; } while((rcode >= 0) && !closed && (total < (128 * 1024))); if(total) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "RECVTOTL(%s): %d\n", id, total); } // Set output stuff. //////////////////// inputBuffer->buffer = buffer; inputBuffer->len = len; inputBuffer->size = size; *bytesRead = total; *connClosed = closed; GSI_UNUSED(id); //to get rid of codewarrior warnings return GP_NO_ERROR; }
static GPResult gpiSendData( GPConnection * connection, SOCKET sock, const char * buffer, int bufferLen, GPIBool * closed, int * sent, char id[3] ) { int rcode; rcode = send(sock, buffer, bufferLen, 0); if(gsiSocketIsError(rcode)) { rcode = GOAGetLastError(sock); if((rcode != WSAEWOULDBLOCK) && (rcode != WSAEINPROGRESS) && (rcode != WSAETIMEDOUT) ) { // handle peer connections specially if((id[0] == 'P') && (id[1] == 'R')) return GP_NETWORK_ERROR; CallbackError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error sending on a socket."); } *sent = 0; *closed = GPIFalse; } else if(rcode == 0) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment, "SENDXXXX(%s): Connection closed\n", id); *sent = 0; *closed = GPITrue; } else { #if defined(GPI_DUMP_NET_TRAFFIC) && defined(GSI_COMMON_DEBUG) { static int sendCount; char *buf = (char *)gsimalloc((size_t)(rcode + 1)); memcpy(buf, buffer, (size_t)rcode); buf[rcode] = '\0'; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "SENT%04d(%s): %s\n", sendCount++, id, buf); freeclear(buf); } #elif defined(GSI_COMMON_DEBUG) { static int sendCount; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "SENT%04d(%s): %d\n", sendCount++, id, rcode); } #endif *sent = rcode; *closed = GPIFalse; } return GP_NO_ERROR; }
static GVBool gviHardwareInitPlayback(GVIDevice * device) { GVIHardwareData * data = (GVIHardwareData *)device->m_data; UInt32 size; OSStatus result; UInt32 primeMethod; SInt32 channelMap[100]; int i; // create the array of sources data->m_playbackSources = gviNewSourceList(); if(!data->m_playbackSources) return GVFalse; // get the playback format size = sizeof(AudioStreamBasicDescription); result = AudioDeviceGetProperty(device->m_deviceID, 0, false, kAudioDevicePropertyStreamFormat, &size, &data->m_playbackStreamDescriptor); if(result != noErr) { gviFreeSourceList(data->m_playbackSources); return GVFalse; } // create a converter from the GV format to the playback format result = AudioConverterNew(&GVIVoiceFormat, &data->m_playbackStreamDescriptor, &data->m_playbackConverter); if(result != noErr) { gviFreeSourceList(data->m_playbackSources); return GVFalse; } // set it to do no priming primeMethod = kConverterPrimeMethod_None; result = AudioConverterSetProperty(data->m_playbackConverter, kAudioConverterPrimeMethod, sizeof(UInt32), &primeMethod); if(result != noErr) { AudioConverterDispose(data->m_playbackConverter); gviFreeSourceList(data->m_playbackSources); return GVFalse; } // setup the converter to map the input channel to all output channels result = AudioConverterGetPropertyInfo(data->m_playbackConverter, kAudioConverterChannelMap, &size, NULL); if(result == noErr) { result = AudioConverterGetProperty(data->m_playbackConverter, kAudioConverterChannelMap, &size, channelMap); if(result == noErr) { for(i = 0 ; i < (size / sizeof(SInt32)) ; i++) channelMap[i] = 0; AudioConverterSetProperty(data->m_playbackConverter, kAudioConverterChannelMap, size, channelMap); } } // allocate the playback buffer data->m_playbackBuffer = (GVSample *)gsimalloc(GVIBytesPerFrame); if(!data->m_playbackBuffer) { AudioConverterDispose(data->m_playbackConverter); gviFreeSourceList(data->m_playbackSources); return GVFalse; } // add property listener AudioDeviceAddPropertyListener(device->m_deviceID, 0, false, kAudioDevicePropertyDeviceIsAlive, gviPropertyListener, device); #if GVI_VOLUME_IN_SOFTWARE // init volume data->m_playbackVolume = (GVScalar)1.0; #endif return GVTrue; }
static GHTTPBool ptaFilePlanetCompletedCallback ( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param ) { ptaFilePlanetInfoData * data = (ptaFilePlanetInfoData *)param; int len; char description[256]; char size[64]; char * mirrorNames[MAX_MIRRORS]; char * mirrorURLs[MAX_MIRRORS]; int i; char * str; // check if the backend is available if(__GSIACResult != GSIACAvailable) return GHTTPFalse; GSI_UNUSED(request); GSI_UNUSED(bufferLen); // Check for success. ///////////////////// if(result != GHTTPSuccess) return ptaFilePlanetInfoFailed(data); // Get the description. /////////////////////// len = ptaFillLine(buffer); if(len == EOF) return ptaFilePlanetInfoFailed(data); buffer += len; strncpy(description, Line, sizeof(description)); description[sizeof(description) - 1] = '\0'; // Get the size. //////////////// len = ptaFillLine(buffer); if(len == EOF) return ptaFilePlanetInfoFailed(data); buffer += len; strncpy(size, Line, sizeof(size)); size[sizeof(size) - 1] = '\0'; // Get the mirrors. /////////////////// for(i = 0 ; (i < MAX_MIRRORS) && ((len = ptaFillLine(buffer)) != EOF) ; ) { // Adjust the buffer. ///////////////////// buffer += len; // Find the tab. //////////////// str = strchr(Line, '\t'); if(!str) continue; // Copy off the name. ///////////////////// len = (str - Line); mirrorNames[i] = (char *)gsimalloc((unsigned int)len + 1); if(!mirrorNames[i]) break; memcpy(mirrorNames[i], Line, (unsigned int)len); mirrorNames[i][len] = '\0'; // Copy off the URL. //////////////////// str++; len = (int)strlen(str); mirrorURLs[i] = (char *)gsimalloc((unsigned int)len + 1); if(!mirrorURLs[i]) { gsifree(mirrorNames[i]); break; } strcpy(mirrorURLs[i], str); // One more mirror. /////////////////// i++; } // Call the callback. ///////////////////// ptaCallFilePlanetInfoCallback(data, PTTrue, description, size, i, mirrorNames, mirrorURLs); return GHTTPTrue; }
/**************** ** HOST LOOKUP ** ****************/ void ghiDoHostLookup ( GHIConnection * connection ) { HOSTENT * host; const char * server; #if !defined(GSI_NO_THREADS) //check to see if asynch lookup is taking place if (connection->handle != NULL) { GSI_UNUSED(host); GSI_UNUSED(server); //lookup incomplete - set to lookupPending state connection->state = GHTTPLookupPending; ghiCallProgressCallback(connection, NULL, 0); return; } #endif gsDebugFormat(GSIDebugCat_HTTP, GSIDebugType_State, GSIDebugLevel_Comment, "Host Lookup\n"); #if !defined(GSI_NO_THREADS) //allocate memory for the handle used for asynch DNS Lookup connection->handle = (GSIResolveHostnameHandle *)gsimalloc(sizeof(GSIResolveHostnameHandle)); #endif // Check for using a proxy. /////////////////////////// if (connection->proxyOverrideServer) // request specific proxy server = connection->proxyOverrideServer; else if(ghiProxyAddress) server = ghiProxyAddress; else server = connection->serverAddress; // Try resolving the address as an IP a.b.c.d number. ///////////////////////////////////////////////////// connection->serverIP = inet_addr(server); if(connection->serverIP == INADDR_NONE) { // Try resolving with DNS - asynchronously if possible ////////////////////////// #if defined(GSI_NO_THREADS) //blocking version - no threads host = gethostbyname(server); if(host == NULL) { gsDebugFormat(GSIDebugCat_HTTP, GSIDebugType_State, GSIDebugLevel_HotError, "Host Lookup failed\n"); connection->completed = GHTTPTrue; connection->result = GHTTPHostLookupFailed; return; } // Get the IP. ////////////// connection->serverIP = *(unsigned int *)host->h_addr_list[0]; #else //threaded version if (gsiStartResolvingHostname(server, connection->handle) == -1) { gsDebugFormat(GSIDebugCat_HTTP, GSIDebugType_State, GSIDebugLevel_HotError, "Thread Creation Failed\n"); //make sure to free handle memory and set it back to NULL gsifree(connection->handle); connection->handle = NULL; //exit with Host Lookup Failed error message connection->completed = GHTTPTrue; connection->result = GHTTPHostLookupFailed; return; } else { //thread created properly - continue into lookupPending state GSI_UNUSED(host); } #endif } // Progress. //////////// //check to see if lookup is complete if (connection->serverIP == INADDR_NONE) { //lookup incomplete - set to lookupPending state connection->state = GHTTPLookupPending; ghiCallProgressCallback(connection, NULL, 0); } else { //lookup complete - proceed with connection stage connection->state = GHTTPConnecting; ghiCallProgressCallback(connection, NULL, 0); } }
//FUNCTIONS /////////// GPResult gpiFailedOpCallback( GPConnection * connection, const GPIOperation * operation ) { GPICallback callback; GPIConnection * iconnection = (GPIConnection*)*connection; assert(connection != NULL); assert(*connection != NULL); assert(operation != NULL); callback = operation->callback; if(callback.callback != NULL) { // Handle based on operation type. ////////////////////////////////// switch(operation->type) { case GPI_CONNECT: { GPConnectResponseArg * arg; arg = (GPConnectResponseArg *)gsimalloc(sizeof(GPConnectResponseArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); memset(arg, 0, sizeof(GPConnectResponseArg)); arg->result = operation->result; if(iconnection->errorCode == GP_NEWUSER_BAD_NICK) { arg->profile = (GPProfile)iconnection->profileid; iconnection->profileid = 0; } CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0)); break; } case GPI_NEW_PROFILE: { GPNewProfileResponseArg * arg; arg = (GPNewProfileResponseArg *)gsimalloc(sizeof(GPNewProfileResponseArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); memset(arg, 0, sizeof(GPNewProfileResponseArg)); arg->result = operation->result; CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0)); break; } case GPI_DELETE_PROFILE: { GPDeleteProfileResponseArg * arg; arg = (GPDeleteProfileResponseArg *)gsimalloc(sizeof(GPDeleteProfileResponseArg)); if (arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); memset(arg, 0, sizeof(GPDeleteProfileResponseArg)); arg->result = operation->result; CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0)); break; } case GPI_GET_INFO: { GPGetInfoResponseArg * arg; arg = (GPGetInfoResponseArg *)gsimalloc(sizeof(GPGetInfoResponseArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); memset(arg, 0, sizeof(GPGetInfoResponseArg)); arg->result = operation->result; CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0)); break; } case GPI_PROFILE_SEARCH: { GPProfileSearchResponseArg * arg; arg = (GPProfileSearchResponseArg *)gsimalloc(sizeof(GPProfileSearchResponseArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); memset(arg, 0, sizeof(GPProfileSearchResponseArg)); arg->result = operation->result; ((GPProfileSearchResponseArg *)arg)->matches = NULL; CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0)); break; } case GPI_REGISTER_UNIQUENICK: { GPRegisterUniqueNickResponseArg * arg; arg = (GPRegisterUniqueNickResponseArg *)gsimalloc(sizeof(GPRegisterUniqueNickResponseArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); memset(arg, 0, sizeof(GPRegisterUniqueNickResponseArg)); arg->result = operation->result; CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0)); break; } case GPI_REGISTER_CDKEY: { GPRegisterCdKeyResponseArg * arg; arg = (GPRegisterCdKeyResponseArg *)gsimalloc(sizeof(GPRegisterCdKeyResponseArg)); if(arg == NULL) Error(connection, GP_MEMORY_ERROR, "Out of memory."); memset(arg, 0, sizeof(GPRegisterCdKeyResponseArg)); arg->result = operation->result; CHECK_RESULT(gpiAddCallback(connection, callback, arg, operation, 0)); break; } default: assert(0); } } return GP_NO_ERROR; }
int gviHardwareListDevices(GVDeviceInfo devices[], int maxDevices, GVDeviceType types) { OSStatus result; UInt32 size; int numDevices; int deviceCount; AudioDeviceID * deviceIDs; AudioDeviceID defaultCaptureDeviceID; AudioDeviceID defaultPlaybackDeviceID; GVDeviceType defaultTypes; int i; // get the default device ids size = sizeof(AudioDeviceID); result = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &size, &defaultCaptureDeviceID); if(result != noErr) defaultCaptureDeviceID = kAudioDeviceUnknown; result = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &defaultPlaybackDeviceID); if(result != noErr) defaultPlaybackDeviceID = kAudioDeviceUnknown; // get the size of the device ids array result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, NULL); if(result != noErr) return 0; // calc the number of devices numDevices = (size / sizeof(AudioDeviceID)); // allocate the array of device ids deviceIDs = (AudioDeviceID *)gsimalloc(size); if(deviceIDs == NULL) return 0; // get the device ids result = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, deviceIDs); if(result != noErr) { gsifree(deviceIDs); return 0; } // fill the array of devices with info deviceCount = 0; for(i = 0 ; (i < maxDevices) && (deviceCount < numDevices) ; i++) { // try to add the device to the list GVBool addedDevice = gviFillDeviceInfo(deviceIDs[i], &devices[deviceCount], types); // check if it was added successfully if(addedDevice) { // check it against the defaults defaultTypes = (GVDeviceType)0; if(deviceIDs[i] == defaultCaptureDeviceID) defaultTypes |= GV_CAPTURE; if(deviceIDs[i] == defaultPlaybackDeviceID) defaultTypes |= GV_PLAYBACK; devices[deviceCount].m_defaultDevice = defaultTypes; // increment the count deviceCount++; } } // free the array gsifree(deviceIDs); return deviceCount; }