void LSCompiler::initialize() { AssemblyReader::addLibraryAssemblyPath("./libs"); if (rootBuildFile.length() != 0) { rootBuildInfo = loadBuildFile(rootBuildFile); } else { rootBuildInfo = BuildInfo::createDefaultBuildFile(); } if (!rootBuildInfo) { lmLog(compilerLogGroup, "Unable to open build info file '%s'", rootBuildFile.c_str()); exit(EXIT_FAILURE); } if (rootBuildInfo->parseErrors) { lmLog(compilerLogGroup, "Please fix the following parser errors and recompile"); LSCompilerLog::dump(); exit(EXIT_FAILURE); } generateRootDependencies(); compileRootBuildDependencies(); compileAssembly(rootBuildInfo); }
// Dump connected clients to the console; useful for telling who is connected to the console! static void listClients() { loom_mutex_lock(gActiveSocketsMutex); // Blast it out to all clients. lmLog(gAssetAgentLogGroup, "Clients"); for (UTsize i = 0; i < gActiveHandlers.size(); i++) { lmLog(gAssetAgentLogGroup, " #%d - %s", gActiveHandlers[i]->getId(), gActiveHandlers[i]->description().c_str()); } loom_mutex_unlock(gActiveSocketsMutex); }
void platform_videoPlayFullscreen(const char *video, int scaleMode, int controlMode, unsigned int bgColor) { ///strip out the raw filename only to use on Android int index = 0; int firstChar = 0; int lastChar = strlen(video) - 1; while(video[index] != '\0') { ///track extention start if found if(video[index] == '.') { lastChar = index - 1; } else if((video[index] == '/') || (video[index] == '\\')) { firstChar = index + 1; } index++; } int len = (lastChar - firstChar) + 1; char *newVideoName = new char[len + 1]; memcpy(newVideoName, &video[firstChar], len * sizeof(char)); newVideoName[len] = '\0'; ///call java method to play the video lmLog(gAndroidVideoLogGroup, "videoPlayFullscreen: '%s' became '%s'", video, newVideoName); jstring jVideo = gPlayVideoFullscreen.env->NewStringUTF(newVideoName); gPlayVideoFullscreen.env->CallStaticVoidMethod(gPlayVideoFullscreen.classID, gPlayVideoFullscreen.methodID, jVideo, scaleMode, controlMode, bgColor); gPlayVideoFullscreen.env->DeleteLocalRef(jVideo); delete []newVideoName; }
void Java_co_theengine_loomdemo_LoomVideo_nativeCallback(JNIEnv *env, jobject thiz, jint callbackType, jstring data) { lmLog(gAndroidVideoLogGroup, "LoomVideo Android Callback fired! %d", callbackType); const char *dataString = env->GetStringUTFChars(data, 0); if (gEventCallback) { const char *typeString = NULL; switch (callbackType) { case 0: gEventCallback("fail", dataString); break; case 1: lmLogError(gAndroidVideoLogGroup, "Video playback complete"); gEventCallback("complete", dataString); break; default: lmLogError(gAndroidVideoLogGroup, "Got Android Video event of type %d but don't know how to handle it, ignoring...", callbackType); break; } } else { lmLogError(gAndroidVideoLogGroup, "Got Android Video event of type %d but don't know how to handle it, ignoring...", callbackType); } env->ReleaseStringUTFChars(data, dataString); }
void loom_asset_flush(const char *name) { // Currently we only want to do this on the main thread so piggy back on the // native delegate sanity check to bail if on secondary thread. if(platform_getCurrentThreadId() != LS::NativeDelegate::smMainThreadID && LS::NativeDelegate::smMainThreadID != 0xBAADF00D) return; loom_mutex_lock(gAssetLock); // Delete it + unload it. loom_asset_t *asset = loom_asset_getAssetByName(name, 0); if(!asset || asset->isSupplied) { loom_mutex_unlock(gAssetLock); return; } lmLog(gAssetLogGroup, "Flushing '%s'", name); if (asset->blob) { asset->blob->decRef(); asset->blob = NULL; } asset->state = loom_asset_t::Unloaded; // Fire subscribers. loom_asset_notifySubscribers(asset->name.c_str()); loom_mutex_unlock(gAssetLock); }
static bool getMethodInfo_(loomJniMethodInfo& methodinfo, const char *className, const char *methodName, const char *paramCode) { jmethodID methodID = 0; JNIEnv *pEnv = 0; bool bRet = false; do { if (!getEnv(&pEnv)) { break; } jclass classID = getClassID_(className, pEnv); if (!classID) { return false; } methodID = pEnv->GetMethodID(classID, methodName, paramCode); if (!methodID) { lmLog(jniLogGroup, "Failed to find method id of %s", methodName); break; } methodinfo.classID = classID; methodinfo.methodID = methodID; bRet = true; } while (0); return bRet; }
void loom_asset_supply(const char *name, void *bits, int length) { loom_mutex_lock(gAssetLock); // Prep the asset. loom_asset_t *asset = loom_asset_getAssetByName(name, 1); // Make sure it's pristine. lmAssert(asset->state == loom_asset_t::Unloaded, "Can't supply an asset that's already queued or in process of loading. Supply assets before you make any asset requests!"); // Figure out the type from the path. utString nameAsUt = name; int type = loom_asset_recognizeAssetTypeFromPath(nameAsUt); if (type == 0) { lmLog(gAssetLogGroup, "Could not infer type of supplied resource '%s', skipping it...", name); asset->state = loom_asset_t::Unloaded; return; } // Deserialize it. LoomAssetCleanupCallback dtor = NULL; void *assetBits = loom_asset_deserializeAsset(name, type, length, bits, &dtor); // Instate the asset. // TODO: We can save some memory by pointing directly and not making a copy. asset->instate(type, assetBits, dtor); // Note it's supplied so we don't flush it. asset->isSupplied = 1; loom_mutex_unlock(gAssetLock); }
void loom_asset_initialize(const char *rootUri) { // Set up the lock for the mutex. lmAssert(gAssetLock == NULL, "Double initialization!"); gAssetLock = loom_mutex_create(); // Note the CWD. char tmpBuff[1024]; platform_getCurrentWorkingDir(tmpBuff, 1024); lmLog(gAssetLogGroup, "Current working directory ='%s'", tmpBuff); // And the allocator. //gAssetAllocator = loom_allocator_initializeTrackerProxyAllocator(loom_allocator_getGlobalHeap()); gAssetAllocator = (loom_allocator_getGlobalHeap()); // Clear, it might have been filled up before (for unit tests) gAssetLoadQueue.clear(); gAssetHash.clear(); // Asset server connection state. gAssetServerSocketLock = loom_mutex_create(); // And set up some default asset types. loom_asset_registerType(LATText, loom_asset_textDeserializer, loom_asset_textRecognizer); loom_asset_registerType(LATBinary, loom_asset_binaryDeserializer, loom_asset_binaryRecognizer); loom_asset_registerImageAsset(); loom_asset_registerSoundAsset(); loom_asset_registerScriptAsset(); // Listen to log and send it if we have a connection. loom_log_addListener(loom_asset_logListener, NULL); }
const char *LoomJni::getPackageName() { static utString packageName; if (packageName.size()) { return packageName.c_str(); } loomJniMethodInfo t; if (getStaticMethodInfo(t, "co/theengine/loomdemo/LoomDemo", "getActivityPackageName", "()Ljava/lang/String;")) { jstring str = (jstring)t.getEnv()->CallStaticObjectMethod(t.classID, t.methodID); t.getEnv()->DeleteLocalRef(t.classID); packageName = jstring2string(str); t.getEnv()->DeleteLocalRef(str); lmLog(jniLogGroup, "package name %s", packageName.c_str()); return packageName.c_str(); } return 0; }
///initializes the data for the Mobile class for Android void platform_mobileInitialize(SensorTripleChangedCallback sensorTripleChangedCB) { lmLog(gAndroidMobileLogGroup, "INIT ***** MOBILE ***** ANDROID ****"); gTripleChangedCallback = sensorTripleChangedCB; ///Bind to JNI entry points. ///Mobile LoomJni::getStaticMethodInfo(gAllowScreenSleep, "co/theengine/loomdemo/LoomMobile", "allowScreenSleep", "(Z)V"); LoomJni::getStaticMethodInfo(gIsSensorSupported, "co/theengine/loomdemo/LoomSensors", "isSensorSupported", "(I)Z"); LoomJni::getStaticMethodInfo(gIsSensorEnabled, "co/theengine/loomdemo/LoomSensors", "isSensorEnabled", "(I)Z"); LoomJni::getStaticMethodInfo(gHasSensorReceivedData, "co/theengine/loomdemo/LoomSensors", "hasSensorReceivedData", "(I)Z"); LoomJni::getStaticMethodInfo(gEnableSensor, "co/theengine/loomdemo/LoomSensors", "enableSensor", "(I)Z"); LoomJni::getStaticMethodInfo(gDisableSensor, "co/theengine/loomdemo/LoomSensors", "disableSensor", "(I)V"); ///Dolby LoomJni::getStaticMethodInfo(gIsDolbyAudioSupported, "com/dolby/DolbyAudio", "isProcessingSupported", "()Z"); LoomJni::getStaticMethodInfo(gSetDolbyAudioProcessingEnabled, "com/dolby/DolbyAudio", "setProcessingEnabled", "(Z)V"); LoomJni::getStaticMethodInfo(gIsDolbyAudioProcessingEnabled, "com/dolby/DolbyAudio", "isProcessingEnabled", "()Z"); LoomJni::getStaticMethodInfo(gIsDolbyAudioProcessingProfileSupported, "com/dolby/DolbyAudio", "isProcessingProfileSupported", "(Ljava/lang/String;)Z"); LoomJni::getStaticMethodInfo(gSetDolbyAudioProcessingProfile, "com/dolby/DolbyAudio", "setProcessingProfile", "(Ljava/lang/String;)Z"); LoomJni::getStaticMethodInfo(gGetSelectedDolbyAudioProfile, "com/dolby/DolbyAudio", "getSelectedProfile", "()Ljava/lang/String;"); }
static jclass getClassID_(const char *className, JNIEnv *env) { JNIEnv *pEnv = env; jclass ret = 0; do { if (!pEnv) { if (!getEnv(&pEnv)) { break; } } ret = pEnv->FindClass(className); if (!ret) { lmLog(jniLogGroup, "Failed to find class of %s", className); jthrowable exc; exc = pEnv->ExceptionOccurred(); if (exc) { pEnv->ExceptionClear(); } break; } } while (0); return ret; }
void LSCompiler::logVerbose(const char *format, ...) { char* buff; va_list args; lmLogArgs(args, buff, format); lmLog(compilerVerboseLogGroup, "%s", buff); lmFree(NULL, buff); }
void LSProfiler::dump(lua_State *L) { dumpAllocations(L); while (methodStack.size()) { leaveMethod(methodStack.peek(0)->getFullMemberName()); methodStack.pop(); } gLoomProfiler->dumpToConsole(); #ifdef LOOM_ENABLE_JIT lmLog(gProfilerLogGroup, ""); lmLog(gProfilerLogGroup, "Please note: Profiling under JIT does not include native function calls."); lmLog(gProfilerLogGroup, "switch to the interpreted VM in order to gather native method timings"); #endif }
// Helper to fully shut down the listen socket; helps quite a bit on OS X. static void shutdownListenSocket() { if (gListenSocket) { lmLogDebug(gAssetAgentLogGroup, "Shutting down listen socket..."); loom_net_closeTCPSocket(gListenSocket); lmLog(gAssetAgentLogGroup, "Done! Goodbye."); gListenSocket = 0; } }
/* * Get the implementation dependent name of a gamepad */ const char * input_gamepadName(int device_index) { if ((device_index < 0) || (device_index >= _numgamepads)) { lmLog(gamepadLogGroup, "There are %d gamepads available", _numgamepads); return(NULL); } return(input_sysGamepadName(device_index)); }
void loom_asset_pump() { // Currently we only want to do this on the main thread so piggy back on the // native delegate sanity check to bail if on secondary thread. if(platform_getCurrentThreadId() != LS::NativeDelegate::smMainThreadID && LS::NativeDelegate::smMainThreadID != 0xBAADF00D) return; loom_mutex_lock(gAssetLock); // Talk to the asset server. loom_asset_serviceServer(); // For now just blast all the data from each file into the asset. while(gAssetLoadQueue.size()) { loom_asset_t *asset = gAssetLoadQueue.front(); // Figure out the type from the path. utString path = asset->name; int type = loom_asset_recognizeAssetTypeFromPath(path); if(type == 0) { lmLog(gAssetLogGroup, "Could not infer type of resource '%s', skipping it...", path.c_str()); asset->state = loom_asset_t::Unloaded; gAssetLoadQueue.erase((UTsize)0, true); continue; } // Open the file. void *ptr; long size; if(!platform_mapFile(asset->name.c_str(), &ptr, &size)) { lmAssert(false, "Could not open file '%s'.", asset->name.c_str()); } // Deserialize it. LoomAssetCleanupCallback dtor = NULL; void *assetBits = loom_asset_deserializeAsset(path, type, size, ptr, &dtor); // Close the file. platform_unmapFile(ptr); // Instate the asset. asset->instate(type, assetBits, dtor); // Done! Update queue. gAssetLoadQueue.erase((UTsize)0, true); } loom_mutex_unlock(gAssetLock); }
void platform_videoInitialize(VideoEventCallback eventCallback) { gEventCallback = eventCallback; lmLog(gAndroidVideoLogGroup, "INIT ***** VIDEO ***** ANDROID ****"); // Bind to JNI entry points. LoomJni::getStaticMethodInfo(gPlayVideoFullscreen, "co/theengine/loomdemo/LoomVideo", "playFullscreen", "(Ljava/lang/String;III)V"); }
static bool initBinderMethod(loomJniMethodInfo& methodInfo, const char *name, const char *sig) { bool result = LoomJni::getStaticMethodInfo(methodInfo, "co/theengine/loomdemo/OuyaControllerBinder", name, sig); if (!result) { lmLog(ouyaLogGroup, "Error: unable to get method %s:%s", name, sig); } return result; }
/* * Checks to make sure the gamepad is valid. */ int input_privateGamepadValid(InputGamepad **gamepad) { int valid; if (*gamepad == NULL) { lmLog(gamepadLogGroup, "Gamepad hasn't been opened yet"); valid = 0; } else { valid = 1; } return valid; }
/* * Get the current state of an axis control on a gamepad */ int input_gamepadGetAxis(InputGamepad *gamepad, int axis) { int state; if (!input_privateGamepadValid(&gamepad)) { return(0); } if (axis < gamepad->naxes) { state = gamepad->axes[axis]; } else { lmLog(gamepadLogGroup, "Gamepad only has %d axes", gamepad->naxes); state = 0; } return(state); }
/* * Get the current state of a hat on a joystick */ int input_gamepadGetHat(InputGamepad *gamepad, int hat) { int state; if (!input_privateGamepadValid(&gamepad)) { return(0); } if (hat < gamepad->nhats) { state = gamepad->hats[hat]; } else { lmLog(gamepadLogGroup, "Gamepad only has %d hats", gamepad->nhats); state = 0; } return(state); }
/* * Get the current state of a button on a gamepad */ int input_gamepadGetButton(InputGamepad *gamepad, int button) { int state; if (!input_privateGamepadValid(&gamepad)) { return(0); } if (button < gamepad->nbuttons) { state = gamepad->buttons[button]; } else { lmLog(gamepadLogGroup, "Gamepad only has %d buttons", gamepad->nbuttons); state = 0; } return(state); }
///initializes the data for the Parse class for Android void platform_parseInitialize() { lmLog(gAndroidParseLogGroup, "INIT ***** PARSE ***** ANDROID ****"); ///Bind to JNI entry points. LoomJni::getStaticMethodInfo(gIsActive, "co/theengine/loomdemo/LoomParse", "isActive", "()Z"); LoomJni::getStaticMethodInfo(gGetInstallationID, "co/theengine/loomdemo/LoomParse", "getInstallationID", "()Ljava/lang/String;"); LoomJni::getStaticMethodInfo(gGetInstallationObjectID, "co/theengine/loomdemo/LoomParse", "getInstallationObjectID", "()Ljava/lang/String;"); LoomJni::getStaticMethodInfo(gUpdateInstallationUserID, "co/theengine/loomdemo/LoomParse", "updateInstallationUserID", "(Ljava/lang/String;)Z"); }
const char *LoomJni::getWritablePath() { static utString writablePath; loomJniMethodInfo t; if (getStaticMethodInfo(t, "co/theengine/loomdemo/LoomDemo", "getActivityWritablePath", "()Ljava/lang/String;")) { jstring str = (jstring)t.getEnv()->CallStaticObjectMethod(t.classID, t.methodID); writablePath = jstring2string(str); t.getEnv()->DeleteLocalRef(str); lmLog(jniLogGroup, "writable path %s", writablePath.c_str()); return writablePath.c_str(); } return 0; }
/** * Post all known files to all clients, or if specified, a single client. * * Useful for fully synching client with the current asset state. * * TODO: Optimize to use hashes to only transmit modified data, based on * client's starting assets. */ static void postAllFiles(int clientId = -1) { lmLog(gAssetAgentLogGroup, "Queueing all files for client %d.", clientId); loom_mutex_lock(gFileScannerLock); // Walk all the files. utArray<FileEntry> *list = lmNew(NULL) utArray<FileEntry>(); platform_walkFiles(".", handleFileStateWalkCallback, list); // Queue them all to be sent. for (UTsize i = 0; i < list->size(); i++) { FileModificationNote note; note.path = stringtable_insert((*list)[i].path.c_str()); note.lastSeenTime = 0; note.onlyForClient = clientId; gPendingModifications.push_back(note); } loom_mutex_unlock(gFileScannerLock); }
const char *LoomJni::getSettingsPath() { static utString path; loomJniMethodInfo t; if (getStaticMethodInfo(t, "co/theengine/loomplayer/LoomPlayer", "getActivitySettingsPath", "()Ljava/lang/String;")) { jstring str = (jstring)t.getEnv()->CallStaticObjectMethod(t.classID, t.methodID); path = jstring2string(str); t.getEnv()->DeleteLocalRef(str); lmLog(jniLogGroup, "settings path %s", path.c_str()); return path.c_str(); } return 0; }
static int _jsonParseInt(const char *key, json_t *value) { if (!value) { return 0; } if (json_is_true(value)) { return 1; } if (json_is_false(value)) { return 0; } if (json_is_integer(value)) { return (int)json_integer_value(value); } if (json_is_real(value)) { return (int)json_real_value(value); } if (json_is_string(value)) { char *pEnd; return strtol(json_string_value(value), &pEnd, 10); } lmLog(gLoomApplicationConfigLogGroup, "WARNING: unknown json int conversion in config for key %s", key); return 0; }
// little helpers that do conversion static bool _jsonParseBool(const char *key, json_t *value) { if (!value) { return false; } if (json_is_true(value)) { return true; } if (json_is_false(value)) { return false; } if (json_is_integer(value)) { return json_integer_value(value) ? true : false; } if (json_is_real(value)) { return json_real_value(value) ? true : false; } if (json_is_string(value)) { return !stricmp(json_string_value(value), "true") ? true : false; } lmLog(gLoomApplicationConfigLogGroup, "WARNING: unknown json bool conversion in config for key %s", key); return false; }
// this will always be in assets/loom.config (unless we decide to move it) void LoomApplicationConfig::parseApplicationConfig(const utString& jsonString) { configJSON = jsonString; // verify config is valid JSON json_error_t jerror; json_t *json = json_loadb(jsonString.c_str(), jsonString.length(), 0, &jerror); lmAssert(json, "LoomApplicationConfig::parseApplicationConfig() error parsing application config %s\n %s %i\n", jerror.source, jerror.text, jerror.line); if (json_t *wfaa = json_object_get(json, "waitForAssetAgent")) { _waitForAssetAgent = _jsonParseInt("waitForAssetAgent", wfaa); } if (json_t *ah = json_object_get(json, "assetAgentHost")) { if (!json_is_string(ah)) { lmLog(gLoomApplicationConfigLogGroup, "assetAgentHost was specified but is not a string!"); } else { assetHost = json_string_value(ah); } } if (json_t *ap = json_object_get(json, "assetAgentPort")) { assetPort = _jsonParseInt("assetAgentPort", ap); } const char *v = json_string_value(json_object_get(json, "version")); if (v != NULL) { _version = v; } const char *app_id = json_string_value(json_object_get(json, "app_id")); if (app_id != NULL) { _applicationId = app_id; } // Parse log block. if (json_t *logBlock = json_object_get(json, "log")) { // Walk the children. const char *key; json_t *value; json_object_foreach(logBlock, key, value) { // Key is the prefix for the rule. // Maybe we have level or enabled data? int enabledRule = -1; int filterRule = -1; if (json_t *enabledBlock = json_object_get(value, "enabled")) { enabledRule = _jsonParseBool("log.enabled", value); } // TODO: Allow info, warn, error as parameters here. if (json_t *levelBlock = json_object_get(value, "level")) { filterRule = (int)json_integer_value(levelBlock); } loom_log_addRule(key, enabledRule, filterRule); } }
// Service our connection to the asset agent. static void loom_asset_serviceServer() { loom_mutex_lock(gAssetServerSocketLock); // Try to connect to the asset server if we aren't already, and it is set. if ((gAssetServerSocket == NULL) && ((ASSET_STREAM_HOST != NULL) && (strlen(ASSET_STREAM_HOST) > 0)) && ((platform_getMilliseconds() - gAssetServerLastConnectTryTime) > gAssetServerConnectTryInterval)) { lmLog(gAssetLogGroup, "Attempting to stream assets from %s:%d", ASSET_STREAM_HOST, ASSET_STREAM_PORT); gAssetServerLastConnectTryTime = platform_getMilliseconds(); gAssetServerSocket = loom_net_openTCPSocket(ASSET_STREAM_HOST, ASSET_STREAM_PORT, 0); gAssetConnectionOpen = false; loom_asset_notifyPendingCountChange(); loom_mutex_unlock(gAssetServerSocketLock); return; } if ((gAssetServerSocket != NULL) && (gAssetConnectionOpen == false)) { // We are waiting on the connection, see if it's writable... If not, return. if (loom_net_isSocketWritable(gAssetServerSocket) == 0) { loom_mutex_unlock(gAssetServerSocketLock); return; } if (loom_net_isSocketDead(gAssetServerSocket) == 1) { // Might be DOA, ie, connect failed. lmLog(gAssetLogGroup, "Failed to connect to asset server %s:%d", ASSET_STREAM_HOST, ASSET_STREAM_PORT); loom_net_closeTCPSocket(gAssetServerSocket); gAssetServerSocket = NULL; lmSafeDelete(NULL, gAssetProtocolHandler); gAssetConnectionOpen = false; loom_asset_notifyPendingCountChange(); loom_mutex_unlock(gAssetServerSocketLock); return; } lmLog(gAssetLogGroup, "Successfully connected to asset server %s:%d!", ASSET_STREAM_HOST, ASSET_STREAM_PORT); // Do this now to avoid clobbering error state and seeing the socket as // "open" when it is really dead. loom_net_enableSocketKeepalive(gAssetServerSocket); gAssetConnectionOpen = true; loom_asset_notifyPendingCountChange(); // Make sure we have a protocol handler. if (!gAssetProtocolHandler) { gAssetProtocolHandler = lmNew(NULL) AssetProtocolHandler(gAssetServerSocket); gAssetProtocolHandler->registerListener(lmNew(NULL) AssetProtocolFileMessageListener()); gAssetProtocolHandler->registerListener(lmNew(NULL) AssetProtocolCommandListener()); } loom_mutex_unlock(gAssetServerSocketLock); return; } // See if the socket is dead, and if so, clean up. if ((gAssetServerSocket != NULL) && (loom_net_isSocketDead(gAssetServerSocket) == 1)) { lmLog(gAssetLogGroup, "Lost connection to asset server."); loom_net_closeTCPSocket(gAssetServerSocket); gAssetServerSocket = NULL; lmSafeDelete(NULL, gAssetProtocolHandler); gAssetConnectionOpen = false; loom_asset_notifyPendingCountChange(); loom_mutex_unlock(gAssetServerSocketLock); return; } // Bail if we don't have a connection. if (!gAssetServerSocket || !gAssetConnectionOpen) { loom_mutex_unlock(gAssetServerSocketLock); return; } // Ping if we need to. if (platform_getMilliseconds() - gAssetServerLastPingTime > gAssetServerPingInterval) { gAssetProtocolHandler->sendPing(); gAssetServerLastPingTime = platform_getMilliseconds(); } // Service the asset server connection. gAssetProtocolHandler->process(); loom_mutex_unlock(gAssetServerSocketLock); }