/* * Copyright (C) 2016 "IoT.bzh" * Author Fulup Ar Foll * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, something express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Reference: * Json load using json_unpack https://jansson.readthedocs.io/en/2.9/apiref.html#parsing-and-validating-values */ #define _GNU_SOURCE #include #include #include "ctl-config.h" void* getPluginContext(CtlPluginT *plugin) { return plugin->context; } void setPluginContext(CtlPluginT *plugin, void *context) { plugin->context = context; } int PluginGetCB (AFB_ApiT apiHandle, CtlActionT *action , json_object *callbackJ) { const char *plugin=NULL, *function=NULL; json_object *argsJ; int idx; CtlConfigT *ctlConfig = (CtlConfigT *) AFB_ApiGetUserData(apiHandle); CtlPluginT *ctlPlugins = ctlConfig ? ctlConfig->ctlPlugins : NULL; if (!ctlPlugins) { AFB_ApiError(apiHandle, "PluginGetCB plugin section missing cannot call '%s'", json_object_get_string(callbackJ)); return 1; } int err = wrap_json_unpack(callbackJ, "{ss,ss,s?o!}", "plugin", &plugin, "function", &function, "args", &argsJ); if (err) { AFB_ApiError(apiHandle, "PluginGet missing plugin|function|[args] in %s", json_object_get_string(callbackJ)); return 1; } for (idx=0; ctlPlugins[idx].uid != NULL; idx++) { if (!strcasecmp (ctlPlugins[idx].uid, plugin)) break; } if (!ctlPlugins[idx].uid) { AFB_ApiError(apiHandle, "PluginGetCB no plugin with uid=%s", plugin); return 1; } action->exec.cb.funcname = function; action->exec.cb.callback = dlsym(ctlPlugins[idx].dlHandle, function); action->exec.cb.plugin= &ctlPlugins[idx]; if (!action->exec.cb.callback) { AFB_ApiError(apiHandle, "PluginGetCB no plugin=%s no function=%s", plugin, function); return 1; } return 0; } // Wrapper to Lua2c plugin command add context and delegate to LuaWrapper static int DispatchOneL2c(void* luaState, char *funcname, Lua2cFunctionT callback) { #ifndef CONTROL_SUPPORT_LUA fprintf(stderr, "CTL-ONE-L2C: LUA support not selected (cf:CONTROL_SUPPORT_LUA) in config.cmake"); return 1; #else int err=Lua2cWrapper(luaState, funcname, callback); return err; #endif } static int PluginLoadCOne(AFB_ApiT apiHandle, const char *pluginpath, json_object *lua2csJ, const char *lua2c_prefix, void * handle, CtlPluginT *ctlPlugin) { void *dlHandle = dlopen(pluginpath, RTLD_NOW); if (!dlHandle) { AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE Fail to load pluginpath=%s err= %s", pluginpath, dlerror()); return -1; } CtlPluginMagicT *ctlPluginMagic = (CtlPluginMagicT*) dlsym(dlHandle, "CtlPluginMagic"); if (!ctlPluginMagic || ctlPluginMagic->magic != CTL_PLUGIN_MAGIC) { AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE symbol'CtlPluginMagic' missing or != CTL_PLUGIN_MAGIC plugin=%s", pluginpath); return -1; } else { AFB_ApiNotice(apiHandle, "CTL-PLUGIN-LOADONE %s successfully registered", ctlPluginMagic->uid); } // store dlopen handle to enable onload action at exec time ctlPlugin->dlHandle = dlHandle; #if (defined(AFB_BINDING_PREV3) || (AFB_BINDING_VERSION == 3)) // Jose hack to make verbosity visible from sharelib with API-V2 struct afb_binding_data_v2 *afbHidenData = dlsym(dlHandle, "afbBindingV2data"); if (afbHidenData) *afbHidenData = afbBindingV2data; #endif // Push lua2cWrapper @ into plugin Lua2cWrapperT *lua2cInPlug = dlsym(dlHandle, "Lua2cWrap"); #ifndef CONTROL_SUPPORT_LUA if (lua2cInPlug) *lua2cInPlug = NULL; #else // Lua2cWrapper is part of binder and not expose to dynamic link if (lua2csJ && lua2cInPlug) { *lua2cInPlug = (Lua2cWrapperT)DispatchOneL2c; int Lua2cAddOne(luaL_Reg *l2cFunc, const char* l2cName, int index) { if(ctlPlugin->ctlL2cFunc->l2cCount) {index += ctlPlugin->ctlL2cFunc->l2cCount+1;} char *funcName; size_t p_length = 6 + strlen(l2cName); funcName = malloc(p_length + 1); strncpy(funcName, "lua2c_", p_length); strncat(funcName, l2cName, p_length - strlen (funcName)); Lua2cFunctionT l2cFunction = (Lua2cFunctionT) dlsym(dlHandle, funcName); if (!l2cFunction) { AFB_ApiError(apiHandle, "CTL-PLUGIN-LOADONE symbol'%s' missing err=%s", funcName, dlerror()); return 1; } l2cFunc[index].func = (void*) l2cFunction; l2cFunc[index].name = strdup(l2cName); return 0; } int count = 0, errCount = 0; luaL_Reg *l2cFunc = NULL; if(!ctlPlugin->ctlL2cFunc) { ctlPlugin->ctlL2cFunc = calloc(1, sizeof(CtlLua2cFuncT)); } ctlPlugin->ctlL2cFunc->prefix = (lua2c_prefix) ? lua2c_prefix : ctlPlugin->uid; // look on l2c command and push them to LUA if (json_object_get_type(lua2csJ) == json_type_array) { size_t length = json_object_array_length(lua2csJ); l2cFunc = calloc(length + ctlPlugin->ctlL2cFunc->l2cCount + 1, sizeof (luaL_Reg)); for (count = 0; count < length; count++) { int err; const char *l2cName = json_object_get_string(json_object_array_get_idx(lua2csJ, count)); err = Lua2cAddOne(l2cFunc, l2cName, count); if (err) errCount++; } } else { l2cFunc = calloc(2 + ctlPlugin->ctlL2cFunc->l2cCount, sizeof (luaL_Reg)); const char *l2cName = j
SUMMARY = "Flutter MediaPlayer app for IVI"
DESCRIPTION = "A Flutter based IVI Dashboard Application for automotive grade Linux"

HOMEPAGE = "https://gerrit.automotivelinux.org/gerrit/apps/flutter-mediaplayer"

BUGTRACKER = "https://github.com/hritik-chouhan/musicplayer/issues"

SECTION = "graphics"

LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://License.md;md5=f712ede8d4f845976061925d1416fc40"


SRC_URI = "git://gerrit.automotivelinux.org/gerrit/apps/flutter-mediaplayer;protocol=https;branch=${AGL_BRANCH}"
SRCREV = "735de5a38ea937ee13157f6ac594053ddb8b027b"
S = "${WORKDIR}/git"

inherit agl-app flutter-app

# flutter-app
#############
PUBSPEC_APPNAME = "musicplayer"
FLUTTER_APPLICATION_INSTALL_PREFIX = "/flutter"
FLUTTER_BUILD_ARGS = "bundle -v"

# agl-app
#########
AGL_APP_TEMPLATE = "agl-app-flutter"
AGL_APP_ID = "musicplayer"
AGL_APP_NAME = "Flutter MediaPlayer"
; } free(searchPath); json_object_put(pluginPathJ); // No more needs for that json_object. return 0; } static int PluginParse(AFB_ApiT apiHandle, CtlSectionT *section, json_object *pluginsJ) { int err = 0, idx = 0, pluginToAddNumber, totalPluginNumber; CtlConfigT *ctlConfig = (CtlConfigT *) AFB_ApiGetUserData(apiHandle); CtlPluginT *ctlPluginsNew, *ctlPluginsOrig = ctlConfig ? ctlConfig->ctlPlugins : NULL; while(ctlPluginsOrig && ctlPluginsOrig[idx].uid != NULL) idx++; totalPluginNumber = idx; switch (json_object_get_type(pluginsJ)) { case json_type_array: { pluginToAddNumber = (int) json_object_array_length(pluginsJ); break; } case json_type_object: { pluginToAddNumber = 1; break; } default: { AFB_ApiError(apiHandle, "Wrong JSON object passed: %s", json_object_get_string(pluginsJ)); return -1; } } totalPluginNumber += pluginToAddNumber; ctlPluginsNew = calloc (totalPluginNumber + 1, sizeof(CtlPluginT)); memcpy(ctlPluginsNew, ctlPluginsOrig, idx * sizeof(CtlPluginT)); while(idx < totalPluginNumber) { json_object *pluginJ = json_object_is_type(pluginsJ, json_type_array) ? json_object_array_get_idx(pluginsJ, idx) : pluginsJ; err += PluginLoad(apiHandle, &ctlPluginsNew[idx], pluginJ, section->handle, section->prefix); idx++; } ctlConfig->ctlPlugins = ctlPluginsNew; free(ctlPluginsOrig); return err; } int PluginConfig(AFB_ApiT apiHandle, CtlSectionT *section, json_object *pluginsJ) { int err = 0, idx = 0; CtlConfigT *ctlConfig = (CtlConfigT *) AFB_ApiGetUserData(apiHandle); CtlPluginT *ctlPlugins = ctlConfig ? ctlConfig->ctlPlugins : NULL; // First plugins load if(pluginsJ) { err = PluginParse(apiHandle, section, pluginsJ); } // Code executed executed at Controller ConfigExec step else if (ctlPlugins) { while(ctlPlugins[idx].uid != NULL) { // Calling plugin Init function DispatchPluginInstallCbT ctlPluginInit = dlsym(ctlPlugins[idx].dlHandle, "CtlPluginInit"); if (ctlPluginInit) { if((*ctlPluginInit) (&ctlPlugins[idx], ctlPlugins[idx].context)) { AFB_ApiError(apiHandle, "Plugin Init function hasn't finish well. Abort initialization"); return -1; } } idx++; } } return err; }