FskErr FskAudioDecompressFrames(FskAudioDecompress deco, const void *data, UInt32 dataSize, UInt32 frameCount, UInt32 *frameSizes, void **samples, UInt32 *audioFormat, UInt32 *sampleCount, UInt32 *channelCount) { FskErr err; UInt32 samplesSize = 0; #if SUPPORT_INSTRUMENTATION FskTimeRecord start, now; if (FskInstrumentedItemHasListenersForLevel(deco, kFskInstrumentationLevelDebug)) FskTimeGetNow(&start); else start.seconds = start.useconds = 0; #endif *samples = 0; *sampleCount = 0; err = (deco->decoder->doDecompressFrames)(deco->state, deco, data, dataSize, frameCount, frameSizes, samples, &samplesSize); if (err) { FskInstrumentedItemSendMessageMinimal(deco, kFskAudioDecompressInstrDecompressFailed, (void *)err); goto bail; } deco->frameNumber += frameCount; *sampleCount = samplesSize / (2 * deco->outputChannelCount); if (audioFormat) *audioFormat = deco->outputFormat; if (channelCount) *channelCount = deco->outputChannelCount; #if SUPPORT_INSTRUMENTATION if (FskInstrumentedItemHasListenersForLevel(deco, kFskInstrumentationLevelMinimal)) { void *msgData[5]; msgData[0] = (void *)data; msgData[1] = (void *)dataSize; msgData[2] = (void *)frameCount; msgData[3] = (void *)*sampleCount; if (!start.seconds) msgData[4] = (void *)0; else { FskTimeGetNow(&now); FskTimeSub(&start, &now); msgData[4] = (void *)FskTimeInMS(&now); } FskInstrumentedItemSendMessageForLevel(deco, kFskAudioDecompressInstrDecompress, msgData, kFskInstrumentationLevelMinimal); } #endif bail: return err; }
void flipThread(void *refcon) { KplScreen screen = refcon; FskThread mainThread = FskThreadGetMain(); FskTimeRecord later; SInt32 ms; FskThreadInitializationComplete(FskThreadGetCurrent()); while (!gQuitting) { //Save the last Flip time FskTimeGetNow(&gKplScreen->lastFlipTime); FskTimeCopy(&later, &gKplScreen->nextFlipTime); FskTimeSub(&gKplScreen->lastFlipTime, &later); ms = FskTimeInMS(&later); if (ms > 0) { FskDelay(ms); MLOG("[%s] delay %d ms\n", threadName, ms); } // Kick off the next cycle if (gKplScreen->drawingPumpEnabled) { FskSemaphoreAcquire(screen->flipSemaphore); gKplScreen->callbackPostedCount++; FskThreadPostCallback(mainThread, drawingPumpCallback, (void*)gKplScreen->callbackPostedCount, NULL, NULL, NULL); } } }
static void drawingPumpUpdate(FskWindow win) { FskTimeRecord delta, now; FskTimeGetNow(&now); gKplScreen->unlocked = false; FskTimeCopy(&delta, &now); FskTimeSub(&gKplScreen->lastUpdateTime, &delta); FskTimeCopy(&gKplScreen->lastUpdateTime, &now); MLOG("[%s] called %d ms after last update\n", threadName, FskTimeInMS(&delta)); // estimate next flip time by adding vSync interval to previous flip time FskTimeCopy(&gKplScreen->nextFlipTime, &gKplScreen->lastFlipTime); FskTimeAdd(&gKplScreen->vSyncIntervalTime, &gKplScreen->nextFlipTime); while (FskTimeCompare(&gKplScreen->nextFlipTime, &now) > 0) FskTimeAdd(&gKplScreen->vSyncIntervalTime, &gKplScreen->nextFlipTime); MLOG("Next flip time %ld.%06ld \n", gKplScreen->nextFlipTime.seconds, gKplScreen->nextFlipTime.useconds); FskWindowCheckEventQueue(win); FskWindowUpdate(win, &gKplScreen->nextFlipTime); if (!gKplScreen->unlocked) FskSemaphoreRelease(gKplScreen->flipSemaphore); MLOG("[%s] Finished callback %ld, nextFlipTime %1d.%03d\n", threadName, gKplScreen->callbackFiredCount, gKplScreen->nextFlipTime.seconds, gKplScreen->nextFlipTime.useconds / 1000); }
static void KprCoAPClientResolverResolved(FskResolver rr) { FskErr err = kFskErrNone; KprCoAPClientResolver self = (KprCoAPClientResolver)rr->ref; KprCoAPMessageQueue entry; self->resolver = NULL; bailIfError(rr->err); self->ipaddr = rr->resolvedIP; FskTimeGetNow(&self->resolvedAt); entry = self->waiting; while (entry) { KprCoAPMessageQueue next = entry->next; KprCoAPMessage message = entry->message; bailIfError(KprCoAPClientStartRequest(self->client, self->ipaddr, self->port, message)); entry = next; } bail: if (err) { if (self->constructed) { KprCoAPClientReportError(self->client, err, "dns resolve error"); } else { self->err = err; } } }
FskErr FskUUIDCreate(FskUUID uuid) { FskTimeRecord time; static UInt32 clockSequence = 0; static FskTimeRecord lastTime; char MAC[6]; FskNetInterfaceRecord *netInterface = NULL; UInt32 numInterfaces; // find a suitable network interface to get the MAC address from numInterfaces = FskNetInterfaceEnumerate(); while (numInterfaces--) { FskNetInterfaceDescribe(numInterfaces, &netInterface); if ((0 == netInterface->MAC[0]) && (0 == netInterface->MAC[1]) && (0 == netInterface->MAC[2]) && (0 == netInterface->MAC[3]) && (0 == netInterface->MAC[4]) && (0 == netInterface->MAC[5])) { FskNetInterfaceDescriptionDispose(netInterface); netInterface = NULL; continue; } break; } if (NULL == netInterface) { // can't fail - clients need a value. make something up. (this happens if all network interfaces are disabled on a phone) int i; for (i = 0; i < 6; i++) MAC[i] = (char)FskRandom(); } else { FskMemMove(MAC, netInterface->MAC, sizeof(netInterface->MAC)); FskNetInterfaceDescriptionDispose(netInterface); } // make sure the clock sequence is good while (0 == clockSequence) clockSequence = FskRandom(); // we need the time, and make sure it is unique. FskTimeGetNow(&time); //@@ should be UTC time time.useconds = (time.useconds >> 4) | (time.seconds << 28); // only uses 60 bits of time time.seconds >>= 4; // only uses 60 bits of time if (FskTimeCompare(&time, &lastTime) <= 0) clockSequence += 1; lastTime = time; // put the pieces together time.useconds = FskEndianU32_NtoB(time.useconds); FskMemCopy(&uuid->value[0], &time.useconds, sizeof(time.useconds)); uuid->value[4] = (UInt8)time.seconds; uuid->value[5] = (UInt8)(time.seconds >> 8); uuid->value[6] = (((UInt8)(time.seconds >> 24)) & 0x0f) | 1; uuid->value[7] = (UInt8)(time.seconds >> 16); uuid->value[8] = ((UInt8)(clockSequence >> 8) & 0x3f) | 0x80; uuid->value[9] = (UInt8)clockSequence; FskMemCopy(&uuid->value[10], MAC, sizeof(MAC)); return kFskErrNone; }
FskErr FskHTTPServerStop(FskHTTPServer http, Boolean flush) { if (!http) return kFskErrInvalidParameter; if (http->stopped == false) { FskHTTPServerRequest request = http->activeRequests; http->stopped = true; FskTimeGetNow(&http->stats.serverStopped); // -- should we kill off live requests here? no. can restart. // -- should we kill off active sessions here? yes when waiting on a keep alive. while (request) { if (request->state == kHTTPReadRequestHeaders) { request->state = kHTTPClose; FskHTTPServerRequestCycle(request); request = http->activeRequests; } else request = request->next; } } else { FskInstrumentedItemSendMessage(http, kFskHTTPInstrMsgServerStoppedAlready, http); } return kFskErrNone; }
FskErr KprWebSocketEndpointSendPing(KprWebSocketEndpoint self) { if (self->state != kKprWebSocketStateOpen) return kFskErrBadState; FskTimeGetNow(&self->pingSent); self->pongReceived = false; return KprWebSocketEndpointSendRawFrame(self, kKprWebSocketOpcodePing, NULL, 0); }
static void KprMQTTClientResetKeepAliveTimer(KprMQTTClient self) { FskTimeCallbackRemove(self->pingRequestCallaback); if (self->keepAlive > 0) { FskTimeRecord when; FskTimeGetNow(&when); FskTimeAddSecs(&when, self->keepAlive); FskTimeCallbackSet(self->pingRequestCallaback, &when, KprMQTTClientIdle, self); } }
FskErr mp3ReaderGetSeekableSegment(void *readerState, void *track, UInt32 propertyID, FskMediaPropertyValue property) { mp3Reader state = readerState; property->type = kFskMediaPropertyTypeFloat; if (state->isOrbiter) { FskTimeRecord now; FskTimeGetNow(&now); FskTimeSub(&state->orbStart, &now); property->value.number = FskTimeInMS(&now) / 500.0; // assume it can transcode at twice real time if (property->value.number > state->mi.duration) { property->value.number = state->mi.duration; state->reader->needsIdle = false; } return kFskErrNone; } if (!(kFskMediaSpoolerDownloading & state->spooler->flags) || (-1 == state->mi.duration)) return kFskErrUnimplemented; if ((state->spoolerPosition <= state->mi.dataOffset) || (0 == state->mi.dataSize)) property->value.number = 0; else { FskInt64 position = state->spoolerPosition - state->mi.dataOffset; double time; time = (((double)position) / ((double)state->mi.dataSize)) * (double)(state->mi.duration * state->mi.frequency); while (state->mi.xingToc) { FskInt64 xingPos; mp3TimeToPosition(state, time, &xingPos); xingPos -= state->mi.dataOffset; if (xingPos <= position) break; if (0 == time) break; if (time < state->mi.frequency) time = 0; else time -= state->mi.frequency; } property->value.number = time / ((double)state->mi.frequency); } return kFskErrNone; }
FskErr FskHTTPServerStart(FskHTTPServer http) { if (!http) return kFskErrInvalidParameter; if (http->stopped) { FskInstrumentedItemSendMessage(http, kFskHTTPInstrMsgServerStart, http); http->stopped = false; FskTimeGetNow(&http->stats.serverStarted); } else { FskInstrumentedItemSendMessage(http, kFskHTTPInstrMsgServerStartedAlready, http); } return kFskErrNone; }
FskErr androidAudioOutStart(FskAudioOut audioOut, FskSampleTime atSample) { FskErr err = kFskErrNone; androidAudioExt *ext = (androidAudioExt*)audioOut->ext; SLresult res; FskAudioNativePrintfVerbose("audioOutStart %x - atSample %lld", audioOut, atSample); if (audioOut->playing) goto bail; if (!ext->playItf) { FskAudioNativePrintfMinimal("huh? No playItf"); err = kFskErrOperationFailed; goto bail; } audioOut->zeroTime = atSample; ext->stoppedAtSamplePosition = 0; FskTimeCallbackNew(&ext->flushTimer); FskTimeCallbackScheduleFuture(ext->flushTimer, 0, kFlushAndRefillTime, flushNowCallback, audioOut); FskAudioNativePrintfVerbose("androidAudioOutStart %x - zeroTime %d", audioOut, audioOut->zeroTime); // in case volume has changed when audio was off // androidAudioOutSetVolume(audioOut, audioOut->leftVolume, audioOut->rightVolume); refillQueue(audioOut); fillBuffers(audioOut); audioOut->playing = true; // refillQueue(audioOut); FskTimeGetNow(&ext->lastTime); FskMutexAcquire(gActiveAudioMutex); gActiveAudioOut = audioOut; FskMutexRelease(gActiveAudioMutex); res = (*ext->playItf)->SetPlayState(ext->playItf, SL_PLAYSTATE_PLAYING); CheckErr(" audioOutStart - set playstate playing", res); { SLmillisecond msec; res = (*ext->playItf)->GetPosition(ext->playItf, &msec); CheckErr(" androidAudioOutStart", res); ext->startedAtSamplePosition = MSToSamples(audioOut, msec); } bail: return err; }
FskErr KprSoundPlayMore(struct FskSndChannelRecord *sndChan, void *it, SInt32 requestedSamples UNUSED) { KprSound self = it; FskSampleTime now; FskTimeRecord when; if (kFskErrNone != FskSndChannelGetSamplePosition(sndChan, &now)) now = 0; FskTimeGetNow(&when); FskTimeAddMS(&when, 100 + (1000.0 * ((self->duration / self->timeScale) - ((double)now / (double)self->sampleRate)))); FskTimeCallbackSet(gSoundTimer, &when, KprSoundPlayMoreCallback, self); FskSndChannelSetMoreCallback(sndChan, NULL, NULL); return kFskErrEndOfFile; }
FskErr FskHTTPServerStop(FskHTTPServer http, Boolean flush) { if (!http) return kFskErrInvalidParameter; if (http->stopped == false) { http->stopped = true; FskTimeGetNow(&http->stats.serverStopped); // -- should we kill off live requests here? no. can restart. // -- should we kill off active sessions here? } else { FskInstrumentedItemSendMessage(http, kFskHTTPInstrMsgServerStoppedAlready, http); } return kFskErrNone; }
FskErr KplScreenSetContinuousDrawing(void *state, void *obj, UInt32 propertyID, FskMediaPropertyValue property) { Boolean on = property->value.b; #if SUPPORT_FLIP_THREAD if (on) { if (!gKplScreen->drawingPumpEnabled) { gKplScreen->drawingPumpEnabled = true; FskTimeClear(&gKplScreen->lastUpdateTime); FskTimeGetNow(&gKplScreen->lastFlipTime); // Just trying to get close, since we just turned on the pump and can't rely on the last flip time FskTimeAddMS(&gKplScreen->lastFlipTime, FskTimeInMS(&gKplScreen->updateIntervalTime) >> 1); FskInstrumentedTypePrintfNormal(&gKplScreenTypeInstrumentation, "START drawing pump **\n"); // Kick off the drawing pump FskThreadPostCallback(FskThreadGetMain(), drawingPumpCallback, (void*)gKplScreen->callbackPostedCount, NULL, NULL, NULL); } }
FskErr KprLibraryServerNew(KprLibraryServer* it) { FskErr err = kFskErrNone; KprLibraryServer self = NULL; FskTimeRecord now; bailIfError(KprMemPtrNewClear(sizeof(KprLibraryServerRecord), it)); self = *it; FskInstrumentedItemNew(self, NULL, &KprLibraryServerInstrumentation); self->vectors.requestCondition = KprLibraryServerRequestConditionCallback; self->vectors.requestReceiveRequest = KprLibraryServerRequestBodyCallback; self->vectors.requestGenerateResponseBody = KprLibraryServerResponseBodyCallback; FskMutexNew(&self->queryMutex, "query"); FskTimeGetNow(&now); self->queryIndex = FskTimeInSecs(&now); gLibraryServer = self; bail: return err; }
FskErr KprSocketRecv(KprSocket self, FskMemPtr buffer, int bufferSize, int *amt) { FskErr err; FskTimeGetNow(&self->lastDataArrived); switch (self->mode) { case kKprSocketModeTCP: { err = FskNetSocketRecvTCP(self->socket, buffer, bufferSize, amt); break; } case kKprSocketModeUDP: { err = FskNetSocketRecvUDP(self->socket, buffer, bufferSize, amt, NULL, NULL); break; } default: err = kFskErrBadSocket; break; } return err; }
FskErr KprMQTTQueueOutboxPut(KprMQTTQueue self, KprMQTTMessage *it) { KprMQTTMessage message = *it; int i; double m; if (KprMQTTQueueOutboxFind(self, message->messageId) != NULL) return kFskErrDuplicateElement; FskTimeGetNow(&message->nextTime); m = 1.0; for (i = 0; i < message->retryCount; i++) { m *= 1.1; } FskTimeAddSecs(&message->nextTime, self->resendInterval * m); message->retryCount += 1; FskListAppend(&self->outbox, message); KprMQTTQueueReschedule(self); *it = NULL; return kFskErrNone; }
static FskErr DragDropTargetProc(UInt32 message, UInt32 mouseX, UInt32 mouseY, void *dropData, void *refCon) { FskErr err = kFskErrNone; FskWindow window = (FskWindow)refCon; FskDragDropFile fileList; UInt32 fileListSize; FskEvent event; FskPointAndTicksRecord pos; FskTimeRecord now; FskTimeGetNow(&now); pos.pt.x = mouseX; pos.pt.y = mouseY; pos.ticks = (((double)now.seconds) * 1000.0) + (((double)now.useconds) / 1000.0); switch(message) { case kFskDragDropTargetEnterWindow: // Calculate the size of the packed file list fileList = (FskDragDropFile)dropData; fileListSize = 0; while (NULL != fileList) { fileListSize += FskStrLen(fileList->fullPathName) + 1; fileList = fileList->next; } // Pack the file list into a null separated list // Post a "drop target enter window" event if (0 != fileListSize) { char *packedFileList = 0; char *packedFileListWalker; ++fileListSize; FskMemPtrNewClear(fileListSize, &packedFileList); *packedFileList = 0; packedFileListWalker = packedFileList; fileList = (FskDragDropFile)dropData; while (NULL != fileList) { FskStrCopy(packedFileListWalker, fileList->fullPathName); if (NULL != fileList->next) { packedFileListWalker += FskStrLen(fileList->fullPathName) + 1; } fileList = fileList->next; } if ((err = FskEventNew(&event, kFskEventWindowDragEnter, NULL, kFskEventModifierNotSet)) != kFskErrNone) goto bail; FskEventParameterAdd(event, kFskEventParameterMouseLocation, sizeof(pos), &pos); FskEventParameterAdd(event, kFskEventParameterFileList, fileListSize, packedFileList); FskWindowEventSend(window, event); FskMemPtrDispose(packedFileList); } break; case kFskDragDropTargetOverWindow: // Windows doesn't send WM_MOUSEMOVE events when dragging over a window!! #if TARGET_OS_WIN32 || TARGET_OS_MAC if ((err = FskEventNew(&event, kFskEventMouseMoved, NULL, kFskEventModifierNotSet)) != kFskErrNone) goto bail; FskEventParameterAdd(event, kFskEventParameterMouseLocation, sizeof(pos), &pos); FskWindowEventSend(window, event); #endif break; case kFskDragDropTargetLeaveWindow: if ((err = FskEventNew(&event, kFskEventWindowDragLeave, NULL, kFskEventModifierNotSet)) != kFskErrNone) goto bail; FskWindowEventSend(window, event); break; case kFskDragDropTargetDropInWindow: if ((err = FskEventNew(&event, kFskEventMouseUp, NULL, kFskEventModifierNotSet)) != kFskErrNone) goto bail; FskEventParameterAdd(event, kFskEventParameterMouseLocation, sizeof(pos), &pos); FskWindowEventSend(window, event); break; } bail: return err; }
static void httpServerEngineCycle(void *param) { FskErr err = kFskErrNone, retVal = kFskErrNeedMoreTime; FskHTTPServerRequest request = (FskHTTPServerRequest)param; int amt, ret, chunkSize = 0; UInt32 chunkSizeL; char *s, *p; Boolean readSomeMore, needsDispose = false; FskThreadRemoveDataHandler(&request->dataHandler); switch (request->state) { case kHTTPNewSession: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); FskTimeGetNow(&request->stats.requestStarted); request->state = kHTTPReadRequestHeaders; case kHTTPReadRequestHeaders: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); shoveBuffer(request->in); amt = request->in.bufferSize - request->in.max; if (amt) { err = FskNetSocketRecvTCP(request->skt, &request->in.buf[request->in.max], amt, &ret); switch (err) { case kFskErrNone: #if SUPPORT_INSTRUMENTATION if (FskInstrumentedItemHasListeners(request)) { FskHTTPInstrMsgDataRecord msg; msg.buffer = &request->in.buf[request->in.max]; msg.amt = ret; FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestRecvData, &msg); } #endif request->http->stats.requestsStarted += 1; request->in.max += ret; request->state = kHTTPProcessRequestHeaders; request->stats.bytesReceived += ret; request->http->stats.bytesReceived += ret; break; case kFskErrNoData: retVal = kFskErrNoData; break; case kFskErrConnectionClosed: if (request->stats.bytesReceived) { request->state = kHTTPSocketError; } else { request->state = kHTTPDone; } break; default: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgErrString, "kHTTPReadRequestHeaders: RecvTCP - error"); request->state = kHTTPSocketError; break; } } else request->state = kHTTPProcessRequestHeaders; if (request->state != kHTTPProcessRequestHeaders) break; case kHTTPProcessRequestHeaders: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); amt = request->in.max - request->in.pos; if (amt) { ret = FskHeadersParseChunk(&request->in.buf[request->in.pos], amt, kFskHeaderTypeRequest, request->requestHeaders); if (ret < 0) { err = kFskErrBadData; request->state = kHTTPSocketError; break; } request->in.pos += ret; if (request->requestHeaders->headersParsed) { httpProcessRequestHeaders(request); } else if (ret != amt) { // odd case - we didn't consume all the data, but // the header parsing isn't complete. request->state = kHTTPServerError; } } else request->state = kHTTPReadRequestHeaders; if (request->state != kHTTPReadRequestBody) break; case kHTTPReadRequestBody: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); readSomeMore = false; amt = request->in.max - request->in.pos; if (request->requestBodyContentLength > 0) { if (amt) { request->state = kHTTPProcessRequestBody; } else { request->in.max = 0; request->in.pos = 0; readSomeMore = true; } } else if (request->requestBodyChunked) { // chunked if (amt == 0) { readSomeMore = true; } else { p = &request->in.buf[request->in.pos]; while ((amt > 1) && lineEnd(p)) { // consume line-ends amt -= 2; request->in.pos += 2; p += 2; } while ((amt > 1) && !lineEnd(p)) { // scan for chunk size amt--; p++; } if ((amt > 1) && lineEnd(p)) { // convert the chunksize s = &request->in.buf[request->in.pos]; chunkSize = FskStrHexToNum(s, p-s); p += 2; //lineend request->requestBodyContentLength = chunkSize; request->in.pos += (p-s); request->state = kHTTPReadRequestBody; if (0 == chunkSize) { // we've read the end indicator (0) if ((amt > 1) && lineEnd(p)) request->in.pos += 2; // consume last cr/lf } request->requestBodyChunked = false; } } else { readSomeMore = true; } } } else { // we're done reading chunks // we're done reading the request request->state = kHTTPPrepareResponse; doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestRequestFinished, request->refCon); } if (readSomeMore) { shoveBuffer(request->in); err = FskNetSocketRecvTCP(request->skt, &request->in.buf[request->in.max], request->in.bufferSize - request->in.max, &ret); switch (err) { case kFskErrNone: #if SUPPORT_INSTRUMENTATION if (FskInstrumentedItemHasListeners(request)) { FskHTTPInstrMsgDataRecord msg; msg.buffer = &request->in.buf[request->in.max]; msg.amt = ret; FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestRecvData, &msg); } #endif request->in.max += ret; if (request->requestBodyChunked) // chunked? request->state = kHTTPReadRequestBody; else request->state = kHTTPProcessRequestBody; request->stats.bytesReceived += ret; request->http->stats.bytesReceived += ret; break; case kFskErrNoData: retVal = kFskErrNoData; break; default: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgErrString, "kHTTPReadRequestBody: RecvTCP - error"); request->http->stats.requestsFailed += 1; request->state = kHTTPSocketError; break; } } if (request->state != kHTTPProcessRequestBody) break; case kHTTPProcessRequestBody: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); amt = request->in.max - request->in.pos; if (amt > request->requestBodyContentLength) { if (false == request->requestBodyChunked) request->requestBodyContentLength = amt; else amt = request->requestBodyContentLength; } chunkSizeL = (UInt32)chunkSize; err = doDataCallback(request->http->callbacks->requestReceiveRequest, request, &request->in.buf[request->in.pos], amt, &chunkSizeL, request->refCon); chunkSize = (int)chunkSizeL; if (kFskErrNone == err) { if (chunkSize) { request->in.pos += chunkSize; request->requestBodyContentLength -= chunkSize; request->stats.requestBodyReceived += chunkSize; if (false == request->requestBodyChunked) { if (0 == request->requestBodyContentLength) request->state = kHTTPPrepareResponse; else request->state = kHTTPReadRequestBody; } else request->state = kHTTPReadRequestBody; } else { // data callback wants to suspend the session and not // consume the chunk, it can do so if (request->state != kHTTPSessionSuspend) request->state = kHTTPServerError; } } else { // the data callback returned an error. if (request->state != kHTTPSessionSuspend) request->state = kHTTPServerError; } if (request->state != kHTTPPrepareResponse) break; doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestRequestFinished, request->refCon); if (request->state != kHTTPPrepareResponse) break; case kHTTPPrepareResponse: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); request->state = kHTTPProcessResponse; err = doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestGenerateResponseHeaders, request->refCon); if (err == kFskErrNeedMoreTime) request->state = kHTTPSessionSuspend; else if (err) request->responseHeaders->responseCode = 500; if (request->state != kHTTPProcessResponse) break; case kHTTPProcessResponse: request->state = kHTTPGetDataChunk; httpPrepareResponseHeaders(request); if (request->state != kHTTPGetDataChunk) break; case kHTTPGetDataChunk: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); if (0 == FskStrCompare(kFskStrHEAD, FskHeaderMethod(request->requestHeaders))) { request->state = kHTTPSendDataChunk; request->nextState = kHTTPSetupNextRequest; break; } p = &request->out.buf[request->out.max]; if (request->transferEncoding == kFskTransferEncodingChunked) { request->out.max += 6; } chunkSize = 0; amt = (request->out.bufferSize - request->out.max) - 2; // fetch response data from callback chunkSizeL = (UInt32)chunkSize; err = doDataCallback(request->http->callbacks->requestGenerateResponseBody, request, &request->out.buf[request->out.max], amt, &chunkSizeL, request->refCon); chunkSize = (int)chunkSizeL; FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "doDataCallback returns err: %d, chunkSize: %d\n", err, chunkSize); if ((kFskErrNone != err) && (kFskErrEndOfFile != err)) { FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "about to doCallCondition -requestResponseFinished - FAIL\n"); doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestResponseFinished, request->refCon); request->http->stats.requestsFailed += 1; request->state = kHTTPServerError; break; } request->out.max += chunkSize; if ((0 == chunkSize) && (request->state == kHTTPSessionSuspend)) { if (kFskTransferEncodingChunked == request->transferEncoding) request->out.max -= 6; break; } request->state = kHTTPSendDataChunk; if ((chunkSize == 0) || (kFskErrEndOfFile == err)) { request->nextState = kHTTPSetupNextRequest; } else request->nextState = kHTTPGetDataChunk; if (request->transferEncoding == kFskTransferEncodingChunked) { FskStrNumToHex(chunkSize, p, 4); p += 4; *p++ = kFskCR; *p++ = kFskLF; if (chunkSize) p += chunkSize; *p++ = kFskCR; *p++ = kFskLF; request->out.max += 2; } request->stats.bodyBytesSent += chunkSize; if (request->state != kHTTPSendDataChunk) break; case kHTTPSendDataChunk: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, " - request->out.max %d - request->out.pos %d\n", request->out.max, request->out.pos); amt = request->out.max - request->out.pos; if (0 == amt) { FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "amt is zero now - transition to next state.\n"); request->state = request->nextState; break; } err = FskNetSocketSendTCP(request->skt, &request->out.buf[request->out.pos], amt, &ret); switch (err) { case kFskErrNone: #if SUPPORT_INSTRUMENTATION if (FskInstrumentedItemHasListeners(request)) { FskHTTPInstrMsgDataRecord msg; msg.buffer = &request->out.buf[request->out.pos]; msg.amt = ret; FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestSendData, &msg); } #endif request->out.pos += ret; request->stats.bytesSent += ret; request->http->stats.bytesSent += ret; if (request->transferEncoding == kFskTransferEncodingChunked) { request->stats.bytesSent -= 8; } if (request->out.pos == request->out.max) { request->out.pos = 0; request->out.max = 0; request->state = request->nextState; } break; case kFskErrNoData: retVal = kFskErrSocketFull; break; default: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgErrString, "kHTTPSendDataChunk: SendTCP - error"); request->state = kHTTPSocketError; request->http->stats.requestsFailed += 1; break; } if (request->state != kHTTPSetupNextRequest) break; case kHTTPSetupNextRequest: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); FskTimeGetNow(&request->stats.requestStopped); request->http->stats.requestsFinished += 1; doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestResponseFinished, request->refCon); request->state = kHTTPDone; if (request->keepAlive && !request->http->stopped) { if ((request->in.max - request->in.pos) > 0) { FskHeaderStructDispose(request->requestHeaders); FskHeaderStructDispose(request->responseHeaders); FskHeaderStructNew(&request->requestHeaders); FskHeaderStructNew(&request->responseHeaders); request->keepAlive = false; request->out.max = 0; request->out.pos = 0; FskMemSet(&request->stats, 0, sizeof(request->stats)); FskTimeGetNow(&request->stats.requestStarted); request->state = kHTTPProcessRequestHeaders; } } if (request->state != kHTTPDone) break; case kHTTPDone: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); if (request->keepAlive && !request->http->stopped) { FskHeaderStructDispose(request->requestHeaders); FskHeaderStructDispose(request->responseHeaders); FskHeaderStructNew(&request->requestHeaders); FskHeaderStructNew(&request->responseHeaders); request->keepAlive = false; request->in.max = 0; request->in.pos = 0; request->out.max = 0; request->out.pos = 0; FskMemSet(&request->stats, 0, sizeof(request->stats)); retVal = kFskErrNoData; // will cause data handler to be installed request->state = kHTTPNewSession; } else { request->state = kHTTPClose; retVal = kFskErrNeedMoreTime; } break; case kHTTPFulfillExpectation: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); request->state = kHTTPSendDataChunk; request->nextState = kHTTPReadRequestBody; request->out.max += snprintf(request->out.buf, request->out.bufferSize, "%s %d %s\r\n\r\n", httpProtocolVersionString(request), 100, FskFindResponse(100)); break; case kHTTPDenyExpectation: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); request->state = kHTTPSendDataChunk; request->nextState = kHTTPDone; request->out.max += snprintf(request->out.buf, request->out.bufferSize, "%s %d %s\r\n\r\n", httpProtocolVersionString(request), 417, FskFindResponse(417)); break; case kHTTPServerError: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); request->state = kHTTPSocketError; // fall through case kHTTPSocketError: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); request->http->stats.connectionsAborted++; doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestErrorAbort, request->refCon); request->state = kHTTPClose; // fall through case kHTTPClose: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); request->state = kHTTPRequestComplete; needsDispose = true; break; case kHTTPRequestComplete: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); retVal = kFskErrNone; // request is finished, don't call back break; case kHTTPSessionSuspend: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); retVal = kFskErrNone; // do nothing in suspend state break; default: FskInstrumentedItemSendMessage(request, kFskHTTPInstrMsgRequestState, request); request->state = kHTTPClose; // unknown state break; ; } if ((request->state == kHTTPServerError) || (request->state == kHTTPSocketError) || (request->state == kHTTPDone) || (request->state == kHTTPClose)) retVal = kFskErrNeedMoreTime; if (retVal == kFskErrNoData) { FskThreadAddDataHandler(&request->dataHandler, (FskThreadDataSource)request->skt, httpServerDataHandler, true, false, request); } else if (retVal == kFskErrSocketFull) { FskThreadAddDataHandler(&request->dataHandler, (FskThreadDataSource)request->skt, httpServerDataHandler, false, true, request); } else if (retVal == kFskErrNeedMoreTime) { FskTimeCallbackScheduleNextRun(request->cycleCallback, httpServerTimeCycle, request); } else if (retVal == kFskErrNone) { // nothing doin } else { FskInstrumentedTypePrintfDebug(&gFskHTTPServerTypeInstrumentation, "httpCycle - weird retVal %d\n", retVal); } if (needsDispose) { FskListRemove((FskList*)&request->http->activeRequests, request); FskTimeCallbackDispose(request->keepAliveKillCallback); request->keepAliveKillCallback = NULL; if (kFskErrNone != doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionConnectionTerminating, request->refCon)) FskHTTPServerRequestDispose(request); } else { if ((retVal == kFskErrNeedMoreTime) || ((retVal != kFskErrNone) && request->keepAlive)) { FskTimeCallbackScheduleFuture(request->keepAliveKillCallback, FskHTTPServerRequestGetKeepAliveTimeout(request), 0, httpKillKeepAlive, request); } } }
FskErr mp3SpoolerCallback(void *clientRefCon, UInt32 operation, void *param) { mp3Reader state = clientRefCon; FskErr err = kFskErrNone; switch (operation) { case kFskMediaSpoolerOperationDataReady: state->spoolerPosition += (UInt32)param; if (state->reader->mediaState < kFskMediaPlayerStateStopped) { if (state->id3.data) { UInt32 percent, bytesRead; void *buffer; if (state->id3.size != state->id3.offset) { err = FskMediaSpoolerRead(state->spooler, state->id3.offset, (UInt32)(state->id3.size - state->id3.offset), &buffer, &bytesRead); if (kFskErrNone == err) { FskMemMove((char *)state->id3.data + state->id3.offset, buffer, bytesRead); state->id3.offset += bytesRead; } } percent = (UInt32)((((float)state->id3.offset) / ((float)state->id3.size)) * 100.0); if (percent < 100) (state->reader->doSetState)(state->reader, kFskMediaPlayerStateInstantiatingProgress + percent); else err = mp3Instantiate(state); } else err = mp3Instantiate(state); } break; case kFskMediaSpoolerOperationSetHeaders: { FskHeaders *headers = param; FskHeaderAddString("icy-metadata", "1", headers); } break; case kFskMediaSpoolerOperationGetHeaders: { FskHeaders *headers = param; char *value = FskHeaderFind("icy-metaint", headers); state->icy.metaInt = (NULL != value) ? FskStrToNum(value) : 0; state->icy.nextMetaPosition = state->icy.metaInt; if ((NULL == state->mi.meta) || (kFskErrNone != FskMediaMetaDataGet(state->mi.meta, "FullName", 0, NULL, NULL))) { value = FskHeaderFind("icy-name", headers); if (NULL == value) value = FskHeaderFind("x-audiocast-name", headers); state->icy.title = FskStrDoCopy(value); } state->icy.isProtocol = 0 == FskStrCompare(headers->protocol, "ICY"); value = FskHeaderFind("Server", headers); if (NULL != value) { if (0 == FskStrCompareWithLength("Orbiter", value, 7)) { if (!state->isOrbiter) { state->isOrbiter = true; state->reader->needsIdle = true; FskTimeGetNow(&state->orbStart); } } } if (state->icy.isNanocaster) { value = FskHeaderFind("icy-genre", headers); if ((NULL != value) && (0 == FskStrCompareCaseInsensitive(value, "error"))) (state->reader->doSetState)(state->reader, kFskMediaPlayerStateFailed); } value = FskHeaderFind("availableSeekRange.dlna.org", headers); if (value && (0 == FskStrCompareWithLength("1 npt=", value, 6))) { char *dash = FskStrChr(value + 6, '-'); double duration; if (dash && (kFskErrNone == FskMediaParseNPT(dash + 1, &duration))) state->dlnaDuration = duration; } } break; case kFskMediaSpoolerOperationGetURI: state->spoolerPosition = ((FskMediaSpoolerGetURI)param)->position; break; } return err; }
static void fxDoConnect(txMachine *the) { if (!FskStrLen(debugAddress)) { char *address = FskEnvironmentGet("debugger"); if (address) FskStrCopy(debugAddress, address); #if TARGET_OS_WIN32 || (TARGET_OS_MAC && !TARGET_OS_IPHONE) else FskStrCopy(debugAddress, "localhost"); #endif } if (FskStrLen(debugAddress) && !debugAddressFailed) { FskErr err; char host[64]; char* colon; int port; FskTimeRecord expireTime, now; SInt32 waitMS; colon = FskStrNCopyUntil(host, debugAddress, 63, ':'); if (*colon) port = FskStrToNum(colon); else port = 5002; #if TARGET_OS_MAC waitMS = 0; #else waitMS = -1; #endif // Connect to the host asynchronously err = FskNetConnectToHostPrioritized(host, port, false, fxConnectComplete, the, 0, 0, NULL, "fxConnect"); if (err) goto bail; // Allow two seconds for the connection to resolve and for the socket to become readable and writable FskTimeGetNow(&expireTime); FskTimeAddSecs(&expireTime, 2); while (!the->connection) { FskTimeGetNow(&now); if (FskTimeCompare(&expireTime, &now) > 0) goto bail; FskThreadRunloopCycle(waitMS); } while (!FskNetSocketIsReadable((FskSocket)the->connection) && !FskNetSocketIsWritable((FskSocket)the->connection)) { FskTimeGetNow(&now); if (FskTimeCompare(&expireTime, &now) > 0) goto bail; FskThreadRunloopCycle(waitMS); } // Make the socket blocking FskNetSocketMakeBlocking((FskSocket)the->connection); return; bail: if (the->connection) { FskNetSocketClose((FskSocket)the->connection); the->connection = 0; } debugAddressFailed = true; } }
FskErr KplScreenGetBitmap(KplBitmap *bitmap) { FskErr err = kFskErrNone; KplScreen screen = NULL; int bpp; // Perform one-time intialization on the first request if (!gKplScreen) { FrameBufferVectorSet vectors; char *fbdev = deviceName; FskTimeRecord now; if (getenv("FRAMEBUFFER")) fbdev = getenv("FRAMEBUFFER"); BAIL_IF_ERR(err = FskMemPtrNewClear(sizeof(KplScreenRecord), (FskMemPtr *)&screen)); BAIL_IF_ERR(err = FskMemPtrNewClear(sizeof(KplBitmapRecord), (FskMemPtr *)&screen->bitmap)); screen->fbfd = open(fbdev, O_RDWR); if (-1 != screen->fbfd) { if (ioctl(screen->fbfd, FBIOGET_FSCREENINFO, &screen->finfo)) { fprintf(stderr, "Error: fb - reading fixed info\n"); exit(2); } if (ioctl(screen->fbfd, FBIOGET_VSCREENINFO, &screen->vinfo)) { fprintf(stderr, "Error: fb - reading variable info\n"); exit(3); } gScreenWidth = screen->vinfo.xres; gScreenHeight = screen->vinfo.yres; bpp = screen->vinfo.bits_per_pixel; screen->rowBytes = screen->vinfo.xres_virtual * bpp / 8; screen->screensize = gScreenHeight * screen->rowBytes; screen->framebuffer = (char*)mmap((void*)screen->finfo.smem_start, screen->finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, screen->fbfd, 0); fprintf(stderr, "framebuffer mem_start: %d, length %d\n", screen->finfo.smem_start, screen->finfo.smem_len); fprintf(stderr, "mmio_start: %d, mmio_len: %d\n", screen->finfo.mmio_start, screen->finfo.mmio_len); if (screen->framebuffer == (char*)-1) { fprintf(stderr,"Error: can't map framebuffer %d\n", errno); exit(4); } screen->displayPage = 0; screen->baseAddr[0] = screen->framebuffer; // screen->baseAddr[1] = screen->framebuffer + screen->finfo.ypanstep * screen->finfo.line_length; FskBitmapNew(gScreenWidth, gScreenHeight, kFskBitmapFormat16RGB565LE, &screen->bitmaps[0]); // FskBitmapNew(gScreenWidth, gScreenHeight, kFskBitmapFormat16RGB565LE, &screen->bitmaps[1]); FskBitmapWriteBegin(screen->bitmaps[0], NULL, NULL, NULL); // FskBitmapWriteBegin(screen->bitmaps[1], NULL, NULL, NULL); FskMutexNew(&screen->withCare, "screen flipper"); } else { fprintf(stderr, "Error: can't open framebuffer device - use ram\n"); gScreenWidth = 320; gScreenHeight = 240; bpp = 16; screen->rowBytes = gScreenWidth * bpp / 8; screen->screensize = gScreenHeight * screen->rowBytes; FskMemPtrNew(screen->screensize, (FskMemPtr*)&screen->framebuffer); } #if 0 devFBFlip(screen); devFBFlip(screen); #endif FskTimeGetNow(&now); devFBFlip(screen); FskTimeGetNow(&screen->vSyncIntervalTime); FskTimeSub(&now, &screen->vSyncIntervalTime); screen->vSyncInterval = FskTimeInMS(&screen->vSyncIntervalTime); // if (!screen->vSyncInterval) screen->vSyncInterval = 1; if (!screen->vSyncInterval) screen->vSyncInterval = 32; FskInstrumentedTypePrintfDebug(&gKplScreenTypeInstrumentation, "VsyncInterval = %d", screen->vSyncInterval); screen->bitmap->baseAddress = screen->baseAddr[screen->displayPage]; screen->bitmap->rowBytes = screen->rowBytes; screen->bitmap->pixelFormat = kFskBitmapFormat16RGB565LE; screen->bitmap->depth = 16; screen->bitmap->width = gScreenWidth; screen->bitmap->height = gScreenHeight; #if SUPPORT_FLIP_THREAD FskSemaphoreNew(&screen->flipSemaphore, 0); FskThreadCreate(&screen->flipThread, flipThread, kFskThreadFlagsJoinable | kFskThreadFlagsWaitForInit | kFskThreadFlagsHighPriority, screen, "dfb flip"); #endif BAIL_IF_ERR(err = FskFrameBufferGetVectors(&vectors)); vectors->doHasProperty = KplScreenHasProperty; vectors->doSetProperty = KplScreenSetProperty; vectors->doGetProperty = KplScreenGetProperty; gKplScreen = screen; initializeLinuxInput(gScreenWidth, gScreenHeight); } *bitmap = gKplScreen->bitmap; if (NULL == *bitmap) err = kFskErrNotFound; bail: if (err) { if (screen) { //dispose of data structures here FskMemPtrDispose(screen); } *bitmap = NULL; } return err; }