Beispiel #1
0
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;
}
Beispiel #2
0
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);
		}
	}
}
Beispiel #3
0
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;
		}
	}
}
Beispiel #5
0
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;
}
Beispiel #6
0
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);
}
Beispiel #8
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
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;
}
Beispiel #14
0
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);
		}
	}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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;
}
Beispiel #21
0
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;
	}
}
Beispiel #22
0
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;
}