1 /***************************************************************************
3 * Copyright 2010,2011 BMW Car IT GmbH
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 ****************************************************************************/
20 #include "Layermanager.h"
22 #include "IRenderer.h"
23 #include "ICommunicator.h"
24 #include "ISceneProvider.h"
25 #include "ICommandExecutor.h"
27 #include <sys/types.h>
33 #include <libgen.h> // basename
35 #include <execinfo.h> // for stacktrace
43 typedef list<string> tFileList;
44 typedef list<string>::iterator tFileListIterator;
47 const char* displayName = ":0";
48 const char* gPluginLookupPath = "/usr/lib/layermanager";
49 int displayWidth = 1280; // default value, override with -w argument
50 int displayHeight = 480; // default value, override with -h argument
52 const char* gRendererPluginDirectories[] = { "/renderer" };
54 uint gRendererPluginDirectoriesCount = sizeof(gRendererPluginDirectories) / sizeof(gRendererPluginDirectories[0]);
56 const char* gCommunicatorPluginDirectories[] = { "/communicator" };
58 uint gCommunicatorPluginDirectoriesCount = sizeof(gCommunicatorPluginDirectories) / sizeof(gCommunicatorPluginDirectories[0]);
60 const char* gScenePluginDirectories[] = { "" };
62 uint gScenePluginDirectoriesCount = sizeof(gScenePluginDirectories) / sizeof(gScenePluginDirectories[0]);
64 const char* USAGE_DESCRIPTION = "Usage:\t LayerManagerService [options]\n"
66 "\t-w: Window Width\t\n"
67 "\t-h: Window Height\t\n"
68 "\t-d: displayName \t\n"
69 "\t-f: loglevel file \t 0 [default] \n\t\t\t\t[0=disabled,1=error,2=info,3=warning,4=debug]\n"
70 "\t-c: loglevel console \t 2 [default] \n\t\t\t\t[0=disabled,1=error,2=info,3=warning,4=debug]\n"
71 "\t-v: show version info\t\n"
72 "\nexample: LayerManagerService -w800 -h480 -d:0\n";
74 bool g_LayerManagerRunning;
77 T* getCreateFunction(string libname)
79 // cut off directories
80 char* fileWithPath = const_cast<char*>(libname.c_str());
81 string libFileName = basename(fileWithPath);
82 LOG_DEBUG("LayerManagerService", "lib name without directory: " << libFileName);
84 // cut off "lib" in front and cut off .so end"
85 string createFunctionName = "create" + libFileName.substr(3, libFileName.length() - 6);
86 LOG_DEBUG("LayerManagerService", "lib entry point name: " << createFunctionName);
90 dlerror(); // Clear any existing error
91 libraryHandle = dlopen(libname.c_str(), RTLD_NOW /*LAZY*/);
92 const char* dlopen_error = dlerror();
93 if (!libraryHandle || dlopen_error)
95 LOG_ERROR("LayerManagerService", "dlopen failed: " << dlopen_error);
99 // get entry point from shared lib
100 dlerror(); // Clear any existing error
101 LOG_DEBUG("LayerManagerService", "loading external function with name: " << createFunctionName);
109 // Note: direct cast is not allowed by ISO C++. e.g.
110 // T* createFunction = reinterpret_cast<T*>(dlsym(libraryHandle, createFunctionName.c_str()));
111 // compiler warning: "forbids casting between pointer-to-function and pointer-to-object"
113 functionPointer.voidPointer = dlsym(libraryHandle, createFunctionName.c_str());
114 T* createFunction = functionPointer.typedPointer;
116 const char* dlsym_error = dlerror();
117 if (!createFunction || dlsym_error)
119 LOG_ERROR("LayerManagerService", "Failed to load shared lib entry point: " << dlsym_error);
122 return createFunction;
125 void parseCommandLine(int argc, char **argv)
127 while (optind < argc)
129 int option = getopt(argc, argv, "w::h::d::?::c::f::v::");
133 displayName = optarg;
136 displayWidth = atoi(optarg);
139 displayHeight = atoi(optarg);
142 if ( atoi(optarg) < LOG_MAX_LEVEL )
144 Log::consoleLogLevel = (LOG_MODES) atoi(optarg);
148 if ( atoi(optarg) < LOG_MAX_LEVEL )
150 Log::fileLogLevel = (LOG_MODES) atoi(optarg);
154 printf("LayerManagerService\nVersion: %s\n", ILM_VERSION);
159 printf("LayerManagerService\nVersion: %s\n", ILM_VERSION);
160 puts(USAGE_DESCRIPTION);
166 void getSharedLibrariesFromDirectory(tFileList& fileList, string dirName)
169 DIR *directory = opendir(dirName.c_str());
172 LOG_ERROR("LayerManagerService", "Error(" << errno << ") opening " << dirName);
176 // iterate content of directory
177 struct dirent *itemInDirectory = 0;
178 while ((itemInDirectory = readdir(directory)))
180 unsigned char entryType = itemInDirectory->d_type;
181 string entryName = itemInDirectory->d_name;
183 bool regularFile = (entryType == DT_REG);
184 bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1));
186 if (regularFile && sharedLibExtension)
188 LOG_DEBUG("LayerManagerService", "adding file " << entryName);
189 fileList.push_back(dirName + "/" + entryName);
193 LOG_DEBUG("LayerManagerService", "ignoring file " << entryName);
200 void loadScenePlugins(SceneProviderList& sceneProviderList, ICommandExecutor* executor)
202 tFileList sharedLibraryNameList;
204 // search sceneprovider plugins in configured directories
205 for (uint dirIndex = 0; dirIndex < gScenePluginDirectoriesCount; ++dirIndex)
207 char directoryName[1024];
208 strcpy(directoryName,gPluginLookupPath);
209 strcat(directoryName,gScenePluginDirectories[dirIndex]);
210 LOG_DEBUG("LayerManagerService", "Searching for SceneProviders in: " << directoryName);
211 getSharedLibrariesFromDirectory(sharedLibraryNameList, directoryName);
214 LOG_DEBUG("LayerManagerService", sharedLibraryNameList.size() << " SceneProvider plugins found");
216 // iterate all communicator plugins and start them
217 tFileListIterator iter = sharedLibraryNameList.begin();
218 tFileListIterator iterEnd = sharedLibraryNameList.end();
220 for (; iter != iterEnd; ++iter)
222 LOG_INFO("LayerManagerService", "Loading SceneProvider plugin " << *iter);
224 ISceneProvider* (*createFunc)(ICommandExecutor*);
225 createFunc = getCreateFunction<ISceneProvider*(ICommandExecutor*)>(*iter);
229 LOG_DEBUG("LayerManagerService", "Entry point of SceneProvider not found");
233 LOG_DEBUG("LayerManagerService", "Creating SceneProvider instance");
234 ISceneProvider* newSceneProvider = createFunc(executor);
236 if (!newSceneProvider)
238 LOG_ERROR("LayerManagerService","SceneProvider initialization failed. Entry Function not callable");
242 sceneProviderList.push_back(newSceneProvider);
247 void loadCommunicatorPlugins(CommunicatorList& communicatorList, ICommandExecutor* executor)
249 tFileList sharedLibraryNameList;
251 // search communicator plugins in configured directories
252 for (uint dirIndex = 0; dirIndex < gCommunicatorPluginDirectoriesCount; ++dirIndex)
254 char directoryName[1024];
255 strcpy(directoryName,gPluginLookupPath);
256 strcat(directoryName,gCommunicatorPluginDirectories[dirIndex]);
257 LOG_DEBUG("LayerManagerService", "Searching for communicator in: " << directoryName);
258 getSharedLibrariesFromDirectory(sharedLibraryNameList, directoryName);
261 LOG_DEBUG("LayerManagerService", sharedLibraryNameList.size() << " Communicator plugins found");
263 // iterate all communicator plugins and start them
264 tFileListIterator iter = sharedLibraryNameList.begin();
265 tFileListIterator iterEnd = sharedLibraryNameList.end();
267 for (; iter != iterEnd; ++iter)
269 LOG_INFO("LayerManagerService", "Loading Communicator plugin " << *iter);
271 ICommunicator* (*createFunc)(ICommandExecutor*);
272 createFunc = getCreateFunction<ICommunicator*(ICommandExecutor*)>(*iter);
276 LOG_DEBUG("LayerManagerService", "Entry point of Communicator not found");
280 LOG_DEBUG("LayerManagerService", "Creating Communicator instance");
281 ICommunicator* newCommunicator = createFunc(executor);
283 if (!newCommunicator)
285 LOG_ERROR("LayerManagerService","Communicator initialization failed. Entry Function not callable");
289 communicatorList.push_back(newCommunicator);
293 void loadRendererPlugins(RendererList& rendererList, IScene* pScene)
295 tFileList sharedLibraryNameList;
297 // search communicator plugins in configured directories
298 for (uint dirIndex = 0; dirIndex < gRendererPluginDirectoriesCount; ++dirIndex)
300 char directoryName[1024];
301 strcpy(directoryName,gPluginLookupPath);
302 strcat(directoryName,gRendererPluginDirectories[dirIndex]);
303 LOG_DEBUG("LayerManagerService", "Searching for renderer in: " << directoryName);
304 getSharedLibrariesFromDirectory(sharedLibraryNameList, directoryName);
307 LOG_DEBUG("LayerManagerService", sharedLibraryNameList.size() << " Renderer plugins found");
309 // currently the use of only one renderer is enforced
310 if (sharedLibraryNameList.size() > 1)
312 LOG_WARNING("LayerManagerService", "more than 1 Renderer plugin found. using only " << sharedLibraryNameList.front());
313 while (sharedLibraryNameList.size() > 1)
315 sharedLibraryNameList.pop_back();
319 // iterate all renderer plugins and start them
320 tFileListIterator iter = sharedLibraryNameList.begin();
321 tFileListIterator iterEnd = sharedLibraryNameList.end();
323 for (; iter != iterEnd; ++iter)
325 LOG_INFO("LayerManagerService", "Loading Renderer plugin " << *iter);
326 IRenderer* (*createFunc)(IScene*);
327 createFunc = getCreateFunction<IRenderer*(IScene*)>(*iter);
330 LOG_DEBUG("LayerManagerService", "Entry point of Renderer not found");
334 LOG_DEBUG("LayerManagerService", "Creating Renderer instance");
335 IRenderer* newRenderer = createFunc(pScene);
338 LOG_ERROR("LayerManagerService","Renderer initialization failed. Entry Function not callable");
342 rendererList.push_back(newRenderer);
346 void printStackTrace()
348 const int maxStackSize = 64;
349 void* stack[maxStackSize];
351 size_t count = backtrace(stack, maxStackSize);
352 char **lines = backtrace_symbols(stack, count);
354 LOG_INFO("LayerManagerService", "--------------------------------------------------");
355 for (unsigned int i = 0; i < count; ++i)
357 LOG_INFO("LayerManagerService", "Stack-Trace [" << i << "]: " << lines[i]);
359 LOG_INFO("LayerManagerService", "--------------------------------------------------");
361 LOG_INFO("LayerManagerService", "Exiting application.")
365 void signalHandler(int sig)
370 g_LayerManagerRunning = false;
371 LOG_INFO("LayerManagerService", "Signal SIGTERM received. Shutting down.");
375 g_LayerManagerRunning = false;
376 LOG_INFO("LayerManagerService", "Signal SIGINT received. Shutting down.");
380 g_LayerManagerRunning = false;
381 LOG_ERROR("LayerManagerService", "Signal SIGBUS received. Shutting down.");
386 g_LayerManagerRunning = false;
387 LOG_ERROR("LayerManagerService", "Signal SIGSEGV received. Shutting down.");
392 LOG_INFO("LayerManagerService", "Signal " << sig << " received.");
396 int main(int argc, char **argv)
398 // setup signal handler and global flag to handle shutdown
399 g_LayerManagerRunning = true;
400 signal(SIGBUS, signalHandler);
401 signal(SIGSEGV, signalHandler);
402 signal(SIGTERM, signalHandler);
403 signal(SIGINT, signalHandler);
405 parseCommandLine(argc, (char**) argv);
406 char* pluginLookupPath = getenv("LM_PLUGIN_PATH");
407 LOG_INFO("LayerManagerService", "Starting Layermanager.");
409 printConfiguration();
411 if (pluginLookupPath != NULL )
413 gPluginLookupPath = pluginLookupPath;
415 LOG_INFO("LayerManagerService", "Used plugin directory is " << gPluginLookupPath);
417 LOG_DEBUG("LayerManagerService", "Creating Layermanager.");
418 ICommandExecutor* pManager = new Layermanager();
419 IScene* pScene = pManager->getScene();
421 // Create and load Renderer plugins
422 LOG_DEBUG("LayerManagerService", "Loading renderer plugins.");
423 RendererList rendererList;
424 loadRendererPlugins(rendererList, pScene);
426 // register renderer plugins at layermanager
427 LOG_DEBUG("LayerManagerService", "Using " << rendererList.size() << " Renderer plugins");
428 RendererListIterator rendererIter = rendererList.begin();
429 RendererListIterator rendererIterEnd = rendererList.end();
430 for (; rendererIter != rendererIterEnd; ++rendererIter)
432 pManager->addRenderer(*rendererIter);
435 // Create and load communicator plugins
436 LOG_DEBUG("LayerManagerService", "Loading communicator plugins.");
437 CommunicatorList communicatorList;
438 loadCommunicatorPlugins(communicatorList, pManager);
440 // register communicator plugins at layermanager
441 LOG_DEBUG("LayerManagerService", "Using " << communicatorList.size() << " Communicator plugins");
442 CommunicatorListIterator commIter = communicatorList.begin();
443 CommunicatorListIterator commIterEnd = communicatorList.end();
444 for (; commIter != commIterEnd; ++commIter)
446 pManager->addCommunicator(*commIter);
448 LOG_DEBUG("LayerManagerService", "Loading scene provider plugins.");
449 SceneProviderList sceneProviderList;
450 loadScenePlugins(sceneProviderList, pManager);
452 // register communicator plugins at layermanager
453 LOG_DEBUG("LayerManagerService", "Using " << sceneProviderList.size() << " SceneProvider plugins");
454 SceneProviderListIterator sceneProviderIter = sceneProviderList.begin();
455 SceneProviderListIterator sceneProviderIterEnd = sceneProviderList.end();
456 for (; sceneProviderIter != sceneProviderIterEnd; ++sceneProviderIter)
458 pManager->addSceneProvider(*sceneProviderIter);
460 bool started = pManager->startManagement(displayWidth, displayHeight, displayName);
467 // must stay within main method or else application would completely exit
468 LOG_INFO("LayerManagerService", "Startup complete. EnterMainloop");
470 while (g_LayerManagerRunning)
472 CommunicatorListIterator commIter = communicatorList.begin();
473 CommunicatorListIterator commIterEnd = communicatorList.end();
474 for (; commIter != commIterEnd; ++commIter)
476 (*commIter)->process(100);
484 LOG_INFO("LayerManagerService", "Exiting Application.");
485 pManager->stopManagement();
486 //delete pRenderer; TODO
487 //delete pCommunicator; TODO
490 // reset signal handling to default
491 signal(SIGBUS, SIG_DFL);
492 signal(SIGSEGV, SIG_DFL);
493 signal(SIGTERM, SIG_DFL);
494 signal(SIGINT, SIG_DFL);
496 return (int)started - 1;