59495cb5186fdb0fb6b307caf13612d34f331c62
[profile/ivi/layer-management.git] / LayerManagerService / src / main.cpp
1 /***************************************************************************
2  *
3  * Copyright 2010,2011 BMW Car IT GmbH
4  *
5  *
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
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  ****************************************************************************/
19
20 #include "Layermanager.h"
21 #include "config.h"
22 #include "IRenderer.h"
23 #include "ICommunicator.h"
24 #include "ISceneProvider.h"
25 #include "ICommandExecutor.h"
26 #include <iostream>
27 #include <sys/types.h>
28 #include <dirent.h>
29 #include <errno.h>
30 #include <dlfcn.h>
31 #include "Log.h"
32 #include <getopt.h>
33 #include <libgen.h> // basename
34 #include <signal.h>
35 #include <execinfo.h> // for stacktrace
36
37 #include <list>
38 using std::list;
39
40 #include <string.h>
41 using std::string;
42
43 typedef list<string> tFileList;
44 typedef list<string>::iterator tFileListIterator;
45
46
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
51
52 const char* gRendererPluginDirectories[] = { "/renderer" };
53
54 uint gRendererPluginDirectoriesCount = sizeof(gRendererPluginDirectories) / sizeof(gRendererPluginDirectories[0]);
55
56 const char* gCommunicatorPluginDirectories[] = { "/communicator" };
57
58 uint gCommunicatorPluginDirectoriesCount = sizeof(gCommunicatorPluginDirectories) / sizeof(gCommunicatorPluginDirectories[0]);
59                                                  
60 const char* gScenePluginDirectories[] = { "" };
61
62 uint gScenePluginDirectoriesCount = sizeof(gScenePluginDirectories) / sizeof(gScenePluginDirectories[0]);                                                 
63                                                  
64 const char* USAGE_DESCRIPTION = "Usage:\t LayerManagerService [options]\n"
65                                 "options:\t\n\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";
73
74 bool g_LayerManagerRunning;
75
76 template<class T>
77 T* getCreateFunction(string libname)
78 {
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);
83
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);
87
88     // open library
89     void *libraryHandle;
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)
94     {
95         LOG_ERROR("LayerManagerService", "dlopen failed: " << dlopen_error);
96         return 0;
97     }
98
99     // get entry point from shared lib
100     dlerror(); // Clear any existing error
101     LOG_DEBUG("LayerManagerService", "loading external function with name: " << createFunctionName);
102
103     union
104     {
105         void* voidPointer;
106         T* typedPointer;
107     } functionPointer;
108
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"
112
113     functionPointer.voidPointer = dlsym(libraryHandle, createFunctionName.c_str());
114     T* createFunction = functionPointer.typedPointer;
115
116     const char* dlsym_error = dlerror();
117     if (!createFunction || dlsym_error)
118     {
119         LOG_ERROR("LayerManagerService", "Failed to load shared lib entry point: " << dlsym_error);
120     }
121
122     return createFunction;
123 }
124
125 void parseCommandLine(int argc, char **argv)
126 {
127     while (optind < argc)
128     {
129         int option = getopt(argc, argv, "w::h::d::?::c::f::v::");
130         switch (option)
131         {
132         case 'd':
133             displayName = optarg;
134             break;
135         case 'w':
136             displayWidth = atoi(optarg);
137             break;
138         case 'h':
139             displayHeight = atoi(optarg);
140             break;
141         case 'c':
142             if ( atoi(optarg) < LOG_MAX_LEVEL ) 
143             {
144                 Log::consoleLogLevel = (LOG_MODES) atoi(optarg);
145             }
146             break;
147         case 'f':
148             if ( atoi(optarg) < LOG_MAX_LEVEL ) 
149             {
150                 Log::fileLogLevel = (LOG_MODES) atoi(optarg);
151             }
152             break;
153         case 'v':
154             printf("LayerManagerService\nVersion: %s\n", ILM_VERSION);
155             exit(-1);
156             break;
157         case '?':   
158         default:
159             printf("LayerManagerService\nVersion: %s\n", ILM_VERSION);
160             puts(USAGE_DESCRIPTION);
161             exit(-1);
162         }
163     }
164 }
165
166 void getSharedLibrariesFromDirectory(tFileList& fileList, string dirName)
167 {
168     // open directory
169     DIR *directory = opendir(dirName.c_str());
170     if (!directory)
171     {
172         LOG_ERROR("LayerManagerService", "Error(" << errno << ") opening " << dirName);
173         return;
174     }
175
176     // iterate content of directory
177     struct dirent *itemInDirectory = 0;
178     while ((itemInDirectory = readdir(directory)))
179     {
180         unsigned char entryType = itemInDirectory->d_type;
181         string entryName = itemInDirectory->d_name;
182
183         bool regularFile = (entryType == DT_REG);
184         bool sharedLibExtension = ("so" == entryName.substr(entryName.find_last_of(".") + 1));
185
186         if (regularFile && sharedLibExtension)
187         {
188             LOG_DEBUG("LayerManagerService", "adding file " << entryName);
189             fileList.push_back(dirName + "/" + entryName);
190         }
191         else
192         {
193             LOG_DEBUG("LayerManagerService", "ignoring file " << entryName);
194         }
195     }
196
197     closedir(directory);
198 }
199
200 void loadScenePlugins(SceneProviderList& sceneProviderList, ICommandExecutor* executor)
201 {
202     tFileList sharedLibraryNameList;
203
204     // search sceneprovider plugins in configured directories
205     for (uint dirIndex = 0; dirIndex < gScenePluginDirectoriesCount; ++dirIndex)
206     {
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);
212     }
213
214     LOG_DEBUG("LayerManagerService", sharedLibraryNameList.size() << " SceneProvider plugins found");
215
216     // iterate all communicator plugins and start them
217     tFileListIterator iter = sharedLibraryNameList.begin();
218     tFileListIterator iterEnd = sharedLibraryNameList.end();
219
220     for (; iter != iterEnd; ++iter)
221     {
222         LOG_INFO("LayerManagerService", "Loading SceneProvider plugin " << *iter);
223
224         ISceneProvider* (*createFunc)(ICommandExecutor*);
225         createFunc = getCreateFunction<ISceneProvider*(ICommandExecutor*)>(*iter);
226
227         if (!createFunc)
228         {
229             LOG_DEBUG("LayerManagerService", "Entry point of SceneProvider not found");
230             continue;
231         }
232
233         LOG_DEBUG("LayerManagerService", "Creating SceneProvider instance");
234         ISceneProvider* newSceneProvider = createFunc(executor);
235
236         if (!newSceneProvider)
237         {
238             LOG_ERROR("LayerManagerService","SceneProvider initialization failed. Entry Function not callable");
239             continue;
240         }
241
242         sceneProviderList.push_back(newSceneProvider);
243     }
244 }
245
246
247 void loadCommunicatorPlugins(CommunicatorList& communicatorList, ICommandExecutor* executor)
248 {
249     tFileList sharedLibraryNameList;
250
251     // search communicator plugins in configured directories
252     for (uint dirIndex = 0; dirIndex < gCommunicatorPluginDirectoriesCount; ++dirIndex)
253     {
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);
259     }
260
261     LOG_DEBUG("LayerManagerService", sharedLibraryNameList.size() << " Communicator plugins found");
262
263     // iterate all communicator plugins and start them
264     tFileListIterator iter = sharedLibraryNameList.begin();
265     tFileListIterator iterEnd = sharedLibraryNameList.end();
266
267     for (; iter != iterEnd; ++iter)
268     {
269         LOG_INFO("LayerManagerService", "Loading Communicator plugin " << *iter);
270
271         ICommunicator* (*createFunc)(ICommandExecutor*);
272         createFunc = getCreateFunction<ICommunicator*(ICommandExecutor*)>(*iter);
273
274         if (!createFunc)
275         {
276             LOG_DEBUG("LayerManagerService", "Entry point of Communicator not found");
277             continue;
278         }
279
280         LOG_DEBUG("LayerManagerService", "Creating Communicator instance");
281         ICommunicator* newCommunicator = createFunc(executor);
282
283         if (!newCommunicator)
284         {
285             LOG_ERROR("LayerManagerService","Communicator initialization failed. Entry Function not callable");
286             continue;
287         }
288
289         communicatorList.push_back(newCommunicator);
290     }
291 }
292
293 void loadRendererPlugins(RendererList& rendererList, IScene* pScene)
294 {
295     tFileList sharedLibraryNameList;
296
297     // search communicator plugins in configured directories
298     for (uint dirIndex = 0; dirIndex < gRendererPluginDirectoriesCount; ++dirIndex)
299     {
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);
305     }
306
307     LOG_DEBUG("LayerManagerService", sharedLibraryNameList.size() << " Renderer plugins found");
308
309     // currently the use of only one renderer is enforced
310     if (sharedLibraryNameList.size() > 1)
311     {
312         LOG_WARNING("LayerManagerService", "more than 1 Renderer plugin found. using only " << sharedLibraryNameList.front());
313         while (sharedLibraryNameList.size() > 1)
314         {
315             sharedLibraryNameList.pop_back();
316         }
317     }
318
319     // iterate all renderer plugins and start them
320     tFileListIterator iter = sharedLibraryNameList.begin();
321     tFileListIterator iterEnd = sharedLibraryNameList.end();
322
323     for (; iter != iterEnd; ++iter)
324     {
325         LOG_INFO("LayerManagerService", "Loading Renderer plugin " << *iter);
326         IRenderer* (*createFunc)(IScene*);
327         createFunc = getCreateFunction<IRenderer*(IScene*)>(*iter);
328         if (!createFunc)
329         {
330             LOG_DEBUG("LayerManagerService", "Entry point of Renderer not found");
331             continue;
332         }
333
334         LOG_DEBUG("LayerManagerService", "Creating Renderer instance");
335         IRenderer* newRenderer = createFunc(pScene);
336         if (!newRenderer)
337         {
338             LOG_ERROR("LayerManagerService","Renderer initialization failed. Entry Function not callable");
339             continue;
340         }
341
342         rendererList.push_back(newRenderer);
343     }
344 }
345
346 void printStackTrace()
347 {
348     const int maxStackSize = 32;
349     void* array[maxStackSize];
350     size_t size;
351     char **strings;
352     size_t count;
353
354     size = backtrace(array, maxStackSize);
355     strings = backtrace_symbols(array, size);
356
357     LOG_ERROR("LayerManagerService", "--------------------------------------------------");
358     for (int i = 0; i < size; ++i)
359     {
360         LOG_ERROR("LayerManagerService", "Stack-Trace [" << i << "]: " << strings[i]);
361     }
362     LOG_ERROR("LayerManagerService", "--------------------------------------------------");
363
364     LOG_DEBUG("LayerManagerService", "Exiting application.")
365     exit(-1);
366 }
367
368 void signalHandler(int sig)
369 {
370     switch (sig)
371     {
372     case SIGTERM:
373         g_LayerManagerRunning = false;
374         LOG_INFO("LayerManagerService", "Signal SIGTERM received. Shutting down.");
375         break;
376
377     case SIGINT:
378         g_LayerManagerRunning = false;
379         LOG_INFO("LayerManagerService", "Signal SIGINT received. Shutting down.");
380         break;
381
382     case SIGBUS:
383         g_LayerManagerRunning = false;
384         LOG_ERROR("LayerManagerService", "Signal SIGBUS received. Shutting down.");
385         printStackTrace();
386         break;
387
388     case SIGSEGV:
389         g_LayerManagerRunning = false;
390         LOG_ERROR("LayerManagerService", "Signal SIGSEGV received. Shutting down.");
391         printStackTrace();
392         break;
393
394     default:
395         LOG_INFO("LayerManagerService", "Signal " << sig << " received.");
396     }
397 }
398
399 int main(int argc, char **argv)
400 {
401     // setup signal handler and global flag to handle shutdown
402     g_LayerManagerRunning = true;
403     signal(SIGBUS, signalHandler);
404     signal(SIGSEGV, signalHandler);
405     signal(SIGTERM, signalHandler);
406     signal(SIGINT, signalHandler);
407
408     parseCommandLine(argc, (char**) argv);
409     char* pluginLookupPath = getenv("LM_PLUGIN_PATH");
410     LOG_INFO("LayerManagerService", "Starting Layermanager.");
411
412     printConfiguration();
413
414     if  (pluginLookupPath != NULL ) 
415     {
416         gPluginLookupPath = pluginLookupPath;
417     }
418     LOG_INFO("LayerManagerService", "Used plugin directory is " << gPluginLookupPath);
419
420     LOG_DEBUG("LayerManagerService", "Creating Layermanager.");
421     ICommandExecutor* pManager = new Layermanager();
422     IScene* pScene = pManager->getScene();
423
424     // Create and load Renderer plugins
425     LOG_DEBUG("LayerManagerService", "Loading renderer plugins.");
426     RendererList rendererList;
427     loadRendererPlugins(rendererList, pScene);
428
429     // register renderer plugins at layermanager
430     LOG_DEBUG("LayerManagerService", "Using " << rendererList.size() << " Renderer plugins");
431     RendererListIterator rendererIter = rendererList.begin();
432     RendererListIterator rendererIterEnd = rendererList.end();
433     for (; rendererIter != rendererIterEnd; ++rendererIter)
434     {
435         pManager->addRenderer(*rendererIter);
436     }
437
438     // Create and load communicator plugins
439     LOG_DEBUG("LayerManagerService", "Loading communicator plugins.");
440     CommunicatorList communicatorList;
441     loadCommunicatorPlugins(communicatorList, pManager);
442
443     // register communicator plugins at layermanager
444     LOG_DEBUG("LayerManagerService", "Using " << communicatorList.size() << " Communicator plugins");
445     CommunicatorListIterator commIter = communicatorList.begin();
446     CommunicatorListIterator commIterEnd = communicatorList.end();
447     for (; commIter != commIterEnd; ++commIter)
448     {
449         pManager->addCommunicator(*commIter);
450     }
451     LOG_DEBUG("LayerManagerService", "Loading scene provider plugins.");
452     SceneProviderList sceneProviderList;
453     loadScenePlugins(sceneProviderList, pManager);
454
455     // register communicator plugins at layermanager
456     LOG_DEBUG("LayerManagerService", "Using " << sceneProviderList.size() << " SceneProvider plugins");
457     SceneProviderListIterator sceneProviderIter = sceneProviderList.begin();
458     SceneProviderListIterator sceneProviderIterEnd = sceneProviderList.end();
459     for (; sceneProviderIter != sceneProviderIterEnd; ++sceneProviderIter)
460     {
461         pManager->addSceneProvider(*sceneProviderIter);
462     }
463     bool started = pManager->startManagement(displayWidth, displayHeight, displayName);
464
465     if (!started)
466     {
467         goto cleanup;
468     }
469
470     // must stay within main method or else application would completely exit
471     LOG_INFO("LayerManagerService", "Startup complete. EnterMainloop");
472
473     while (g_LayerManagerRunning)
474     {
475         CommunicatorListIterator commIter = communicatorList.begin();
476         CommunicatorListIterator commIterEnd = communicatorList.end();
477         for (; commIter != commIterEnd; ++commIter)
478         {
479             (*commIter)->process(100);
480         }
481     }
482
483
484     // cleanup
485     cleanup:
486
487     LOG_INFO("LayerManagerService", "Exiting Application.");
488     pManager->stopManagement();
489     //delete pRenderer; TODO
490     //delete pCommunicator; TODO
491     delete pManager;
492
493     // reset signal handling to default
494     signal(SIGBUS, SIG_DFL);
495     signal(SIGSEGV, SIG_DFL);
496     signal(SIGTERM, SIG_DFL);
497     signal(SIGINT, SIG_DFL);
498
499     return (int)started - 1;
500 }