update on dbus
[profile/ivi/audiomanager.git] / AudioManagerDaemon / Router.cpp
1 /**
2  * Copyright (C) 2011, BMW AG
3  *
4  * AudioManangerDeamon
5  *
6  * \file Router.cpp
7  *
8  * \date 20.05.2011
9  * \author Christian Müller (christian.ei.mueller@bmw.de)
10  *
11  * \section License
12  * GNU Lesser General Public License, version 2.1, with special exception (GENIVI clause)
13  * Copyright (C) 2011, BMW AG – Christian Müller  Christian.ei.mueller@bmw.de
14  *
15  * This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License, version 2.1, as published by the Free Software Foundation.
16  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License, version 2.1, for more details.
17  * You should have received a copy of the GNU Lesser General Public License, version 2.1, along with this program; if not, see <http://www.gnu.org/licenses/lgpl-2.1.html>.
18  * Note that the copyright holders assume that the GNU Lesser General Public License, version 2.1, may also be applicable to programs even in cases in which the program is not a library in the technical sense.
19  * Linking AudioManager statically or dynamically with other modules is making a combined work based on AudioManager. You may license such other modules under the GNU Lesser General Public License, version 2.1. If you do not want to license your linked modules under the GNU Lesser General Public License, version 2.1, you may use the program under the following exception.
20  * As a special exception, the copyright holders of AudioManager give you permission to combine AudioManager with software programs or libraries that are released under any license unless such a combination is not permitted by the license of such a software program or library. You may copy and distribute such a system following the terms of the GNU Lesser General Public License, version 2.1, including this special exception, for AudioManager and the licenses of the other code concerned.
21  * Note that people who make modified versions of AudioManager are not obligated to grant this special exception for their modified versions; it is their choice whether to do so. The GNU Lesser General Public License, version 2.1, gives permission to release a modified version without this exception; this exception also makes it possible to release a modified version which carries forward this exception.
22  *
23  *
24  */
25
26 #include <iostream>
27 #include <stdio.h>
28 #include <dirent.h>
29 #include <dlfcn.h>
30 #include <libgen.h>
31 #include <unistd.h>
32 #include <string>
33
34 #include "audioManagerIncludes.h"
35
36 const char* routingPluginDirectories[] = { "/home/christian/workspace/gitserver/build/plugins/routing"};
37 uint routingPluginDirectoriesCount = sizeof(routingPluginDirectories) / sizeof(routingPluginDirectories[0]);
38
39 Router::Router() {
40 }
41
42 Router::~Router() {
43 }
44
45 void Router::registerDatabasehandler(DataBaseHandler* db_handler) {
46         m_dbHandler = db_handler;
47 }
48
49 bool Router::get_Route_from_Source_ID_to_Sink_ID(const bool onlyfree,
50                 const source_t Source_ID, const sink_t Sink_ID,
51                 std::list<genRoute_t>* ReturnList) {
52
53         domain_t Source_Domain = m_dbHandler->get_Domain_ID_from_Source_ID(
54                         Source_ID); //first find out in which domains the source and sink are
55         domain_t Sink_Domain = m_dbHandler->get_Domain_ID_from_Sink_ID(Sink_ID);
56
57         if (Source_Domain == -1 || Sink_Domain == -1) {
58                 return false;
59         } //if source or sink does not exists, exit here
60
61         RoutingTree routingtree(Source_Domain); //Build up a Tree from the Source_Domain to every other domain.
62         std::list<RoutingTreeItem*> flattree; //This list is the flat tree
63         std::list<RoutingTreeItem*> matchtree; //This List holds all TreeItems which have the right Domain Sink IDs
64         std::list<gateway_t> gwids; //holds all gateway ids of the route
65         genRoutingElement_t element;
66         std::list<genRoutingElement_t> actualRoutingElement;//intermediate list of current routing pairs
67         genRoute_t actualRoute; //holds the actual Route
68         source_t ReturnSource = 0;
69         sink_t ReturnSink = 0;
70         source_t LastSource = 0;
71         domain_t ReturnDomain = 0;
72
73         //TODO: kind of unclean. The separation between database and router could be better.
74         m_dbHandler->get_Domain_ID_Tree(onlyfree, &routingtree, &flattree); //Build up the tree out of the database as
75
76         //we go through the returned flattree and look for our sink, after that flattree holds only treeItems that match
77         for(std::list<RoutingTreeItem*>::iterator rTree=flattree.begin();rTree!=flattree.end();rTree++) {
78                 RoutingTreeItem *p=*rTree;
79                 if (p->returnDomainID() == Sink_Domain) {
80                         matchtree.push_back(*rTree);
81                 }
82         }
83
84         //No we need to trace back the routes for each entry in matchtree
85         for(std::list<RoutingTreeItem*>::iterator match=matchtree.begin(); match!=matchtree.end(); match++)
86                 {
87                         //getting the route for the actual item
88                         actualRoute.len = routingtree.getRoute(*match, &gwids); //This gives only the Gateway IDs we need more
89
90                         //go throught the gatewayids and get more information
91                         for (std::list<gateway_t>::iterator i=gwids.begin(); i!=gwids.end();i++) {
92                                 m_dbHandler->get_Gateway_Source_Sink_Domain_ID_from_ID(*i, &ReturnSource, &ReturnSink,&ReturnDomain);
93                                 //first routing pair is source to ReturnSink of course;
94 //                              if (i == 0) {
95 //                                      element.source = Source_ID;
96 //                                      element.sink = ReturnSink;
97 //                                      element.Domain_ID = Source_Domain;
98 //                              }
99 //
100 //                              else {
101 //                                      element.source = LastSource;
102 //                                      element.sink = ReturnSink;
103 //                                      element.Domain_ID = ReturnDomain;
104 //                              }
105                                 actualRoutingElement.push_back(element);
106                                 LastSource = ReturnSource;
107                         }
108                         element.source = LastSource;
109                         element.sink = Sink_ID;
110                         element.Domain_ID = Sink_Domain;
111                         actualRoutingElement.push_back(element);
112
113                         actualRoute.Source_ID = Source_ID;
114                         actualRoute.Sink_ID = Sink_ID;
115                         actualRoute.route = actualRoutingElement;
116                         ReturnList->push_back(actualRoute);
117                 }
118
119         return true;
120         //TODO: return actual status !
121 }
122
123 RoutingTreeItem::RoutingTreeItem(const domain_t Domain_Id,
124                 const gateway_t Gateway_Id, RoutingTreeItem *parent) {
125         parentItem = parent;
126         m_domainID = Domain_Id;
127         m_gatewayID = Gateway_Id;
128 }
129
130 RoutingTreeItem::RoutingTreeItem() {
131
132 }
133
134 RoutingTreeItem::~RoutingTreeItem() {
135         for (std::list<RoutingTreeItem*>::iterator i=childItems.begin();i!=childItems.end();i++) {
136                 delete *i;
137         }
138 }
139
140 void RoutingTreeItem::appendChild(RoutingTreeItem *item) {
141         childItems.push_back(item);
142 }
143
144 RoutingTreeItem *RoutingTreeItem::return_Parent() {
145         return parentItem;
146 }
147
148 domain_t RoutingTreeItem::returnDomainID() {
149         return m_domainID;
150 }
151
152 gateway_t RoutingTreeItem::returnGatewayID() {
153         return m_gatewayID;
154 }
155
156 RoutingTree::RoutingTree(const domain_t Root_ID) :
157         m_rootItem(RoutingTreeItem(Root_ID)) {
158 }
159
160 RoutingTree::~RoutingTree() {
161 }
162
163 RoutingTreeItem* RoutingTree::insertItem(const domain_t Domain_ID,
164                 const gateway_t Gateway_ID, RoutingTreeItem *parentItem) {
165         RoutingTreeItem *newTree = new RoutingTreeItem(Domain_ID, Gateway_ID,
166                         parentItem);
167         parentItem->appendChild(newTree);
168         m_allChildList.push_back(newTree);
169         return newTree;
170 }
171
172 int RoutingTree::getRoute(RoutingTreeItem* Targetitem, std::list<gateway_t>* route) {
173         int hopps = 0;
174         RoutingTreeItem *parentItem = Targetitem;
175         while (parentItem != &m_rootItem) {
176                 route->push_front(parentItem->returnGatewayID());
177                 hopps++;
178                 parentItem = parentItem->return_Parent();
179         }
180         return hopps;
181 }
182
183 int RoutingTree::returnRootDomainID() {
184         return m_rootItem.returnDomainID();
185 }
186
187 RoutingTreeItem* RoutingTree::returnRootItem() {
188         return &m_rootItem;
189 }
190
191
192 void Bushandler::load_Bus_plugins() {
193         std::list<std::string> sharedLibraryNameList;
194
195         for (uint dirIndex = 0; dirIndex < routingPluginDirectoriesCount; ++dirIndex) {
196         const char* directoryName = routingPluginDirectories[dirIndex];
197         DLT_LOG(AudioManager,DLT_LOG_INFO, DLT_STRING("Searching for Routing in"),DLT_STRING(directoryName));
198         std::list<std::string> newList=m_core->getSharedLibrariesFromDirectory(directoryName);
199         sharedLibraryNameList.insert(sharedLibraryNameList.end(),newList.begin(),newList.end());
200     }
201
202
203     // iterate all communicator plugins and start them
204     std::list<std::string>::iterator iter = sharedLibraryNameList.begin();
205     std::list<std::string>::iterator iterEnd = sharedLibraryNameList.end();
206
207     for (; iter != iterEnd; ++iter)
208     {
209         DLT_LOG(AudioManager,DLT_LOG_INFO, DLT_STRING("Loading Routing plugin"),DLT_STRING(iter->c_str()));
210
211         RoutingSendInterface* (*createFunc)();
212         createFunc = getCreateFunction<RoutingSendInterface*()>(*iter);
213
214         if (!createFunc) {
215             DLT_LOG(AudioManager,DLT_LOG_INFO, DLT_STRING("Entry point of Communicator not found"));
216             continue;
217         }
218
219         RoutingSendInterface* RoutingPlugin = createFunc();
220
221
222         if (!RoutingPlugin) {
223                 DLT_LOG(AudioManager,DLT_LOG_INFO, DLT_STRING("RoutingPlugin initialization failed. Entry Function not callable"));
224             continue;
225         }
226
227         Bus newBus;
228         char BusName[40];
229         RoutingPlugin->return_BusName(BusName);
230         newBus.Name=std::string(BusName);
231         newBus.sendInterface=RoutingPlugin;
232         RoutingPlugin->startup_interface(m_receiver,m_core->returnDbusHandler());
233                 DLT_LOG( AudioManager, DLT_LOG_INFO, DLT_STRING("Registered Routing Plugin:"), DLT_STRING(BusName));
234         Busses.push_back(newBus);
235     }
236 }
237
238 void Bushandler::StartupInterfaces() {
239         std::list<Bus>::iterator busIter;
240         std::list<Bus>::iterator busStart=Busses.begin();
241         std::list<Bus>::iterator busEnd=Busses.end();
242
243         for (busIter=busStart;busIter!=busEnd;busIter++) {
244                 busIter->sendInterface->system_ready();
245                 DLT_LOG(AudioManager,DLT_LOG_INFO, DLT_STRING("Bushandler:Started Interface"), DLT_STRING(busIter->Name.c_str()));
246         }
247 }
248
249 void Bushandler::registerReceiver(RoutingReceiver * receiver) {
250         m_receiver = receiver;
251 }
252
253 void Bushandler::registerCore (AudioManagerCore* core) {
254         m_core=core;
255 }
256
257 RoutingSendInterface* Bushandler::getInterfaceforBus(std::string bus) {
258         /**
259          * \todo this could be done more nicer and faster with a hash lookup or so.. worht it??
260          */
261         std::list<Bus>::iterator busIter;
262         std::list<Bus>::iterator busStart=Busses.begin();
263         std::list<Bus>::iterator busEnd=Busses.end();
264
265         for (busIter=busStart;busIter!=busEnd;busIter++) {
266                 {
267                         if (busIter->Name.compare(bus) == 0) {
268                                 return busIter->sendInterface;
269                         }
270                 }
271         }
272         return NULL;
273 }
274