Merge "Use existing callback ID for recurring callbacks" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / dbus-tizen.cpp
1 /*
2  * Copyright 2019  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *  http://www.apache.org/licenses/LICENSE-2.0
9
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // CLASS HEADER
18 #include <dali/internal/accessibility/bridge/dbus.h>
19 #include <dali/internal/accessibility/bridge/accessibility-common.h>
20
21 // EXTERNAL INCLUDES
22 #include <sstream>
23 #include <iostream>
24 #include <mutex>
25
26 #include <Eldbus.h>
27 #include <Ecore_Input.h>
28
29 // INTERNAL INCLUDES
30 #include <dali/public-api/dali-adaptor-common.h>
31
32 #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
33
34 #undef EINA_FALSE
35 #undef EINA_TRUE
36 #define EINA_TRUE static_cast< Eina_Bool >( 1 )
37 #define EINA_FALSE static_cast< Eina_Bool >( 0 )
38
39 //#define DBUS_DEBUG(...) do { DBus::debugPrint(__FILE__, __LINE__, __VA_ARGS__); } while (0)
40
41 std::atomic< unsigned int > DBus::detail::CallId::LastId{0};
42 static std::function< void( const char*, size_t ) > debugPrinter;
43 static std::mutex debugLock;
44
45 thread_local std::string DBus::DBusServer::currentObjectPath;
46 thread_local DBusWrapper::ConnectionPtr DBus::DBusServer::currentConnection;
47
48 void DBus::setDebugPrinter( std::function< void( const char*, size_t ) > printer )
49 {
50   std::lock_guard< std::mutex > lock( debugLock );
51   debugPrinter = std::move( printer );
52 }
53
54 void DBus::debugPrint( const char* file, size_t line, const char* format, ... )
55 {
56   std::function< void( const char*, size_t ) > debugPrintFunc;
57   {
58     std::lock_guard< std::mutex > lock( debugLock );
59     if( !debugPrinter )
60       return;
61     debugPrintFunc = debugPrinter;
62   }
63   std::vector< char > buf( 4096 );
64   int offset;
65   while( true )
66   {
67     offset = snprintf( buf.data(), buf.size(), "%s:%u: ", file, static_cast< unsigned int >( line ) );
68     if( offset < 0 )
69       return;
70     if( static_cast< size_t >( offset ) < buf.size() )
71       break;
72     buf.resize( offset + 1 );
73   }
74
75   while( true )
76   {
77     va_list args;
78     va_start( args, format );
79     int z = vsnprintf( buf.data() + offset, buf.size() - offset, format, args );
80     va_end( args );
81     if( z < 0 )
82       return;
83     bool done = static_cast< size_t >( z ) + static_cast< size_t >( offset ) < buf.size();
84     buf.resize( static_cast< size_t >( z ) + static_cast< size_t >( offset ) );
85     if( done )
86       break;
87   }
88   debugPrintFunc( buf.data(), buf.size() );
89 }
90
91 DBusWrapper::ConnectionPtr DBus::getDBusConnectionByName( const std::string& name )
92 {
93   return DBUS_W->eldbus_address_connection_get_impl( name );
94 }
95
96 DBusWrapper::ConnectionPtr DBus::getDBusConnectionByType( ConnectionType connectionType )
97 {
98   return DBUS_W->eldbus_connection_get_impl(connectionType);
99 }
100
101 DBus::DBusClient::DBusClient( std::string busName, std::string pathName, std::string interfaceName, ConnectionType tp ) : DBusClient( std::move( busName ), std::move( pathName ), std::move( interfaceName ), getDBusConnectionByType( tp ) )
102 {
103 }
104
105 DBus::DBusClient::DBusClient( std::string busName, std::string pathName, std::string interfaceName, const DBusWrapper::ConnectionPtr &conn )
106 {
107   if( !conn )
108     connectionState->connection = getDBusConnectionByType( ConnectionType::SESSION );
109   else
110     connectionState->connection = conn;
111
112   std::ostringstream o;
113   o << "bus = " << busName << " path = " << pathName << " connection = " << DBUS_W->eldbus_connection_unique_name_get_impl( connectionState->connection );
114   info = o.str();
115
116   connectionState->object = DBUS_W->eldbus_object_get_impl( connectionState->connection, busName.c_str(), pathName.c_str() );
117   if( connectionState->object )
118   {
119     connectionState->proxy = DBUS_W->eldbus_proxy_get_impl( connectionState->object, interfaceName );
120     if( interfaceName != DBUS_INTERFACE_PROPERTIES )
121     {
122       connectionState->propertiesProxy = DBUS_W->eldbus_proxy_get_impl( connectionState->object, DBUS_INTERFACE_PROPERTIES );
123     }
124     else
125     {
126       connectionState->propertiesProxy = DBUS_W->eldbus_proxy_copy_impl( connectionState->proxy );
127     }
128   }
129   connectionInfo = std::make_shared< ConnectionInfo >();
130   connectionInfo->busName = std::move( busName );
131   connectionInfo->pathName = std::move( pathName );
132   connectionInfo->interfaceName = std::move( interfaceName );
133 }
134
135 DBus::DBusServer::DBusServer( ConnectionType tp ) : DBus::DBusServer( DBus::getDBusConnectionByType( tp ) )
136 {
137 }
138
139 DBus::DBusServer::DBusServer( const DBusWrapper::ConnectionPtr &conn )
140 {
141   if( !conn )
142     connection = getDBusConnectionByType( ConnectionType::SESSION );
143   else
144     connection = conn;
145 }
146
147 DBus::DBusInterfaceDescription::DBusInterfaceDescription( std::string interfaceName ) : interfaceName( std::move( interfaceName ) )
148 {
149 }
150
151 void DBus::DBusServer::addInterface( const std::string& pathName, DBusInterfaceDescription& dscr, bool fallback )
152 {
153   DBUS_W->add_interface_impl( fallback, pathName, connection, destructorObject->destructors, dscr.interfaceName, dscr.methods, dscr.properties, dscr.signals );
154 }
155
156 std::string DBus::DBusServer::getBusName() const
157 {
158   return getConnectionName( connection );
159 }
160
161 std::string DBus::getConnectionName( const DBusWrapper::ConnectionPtr &c )
162 {
163   return DBUS_W->eldbus_connection_unique_name_get_impl( c );
164 }
165
166 bool DBus::DBusClient::getFromEinaValue(const _Eina_Value *v, void *dst)
167 {
168   return eina_value_get(const_cast<Eina_Value*>(v), dst);
169 }
170
171 static std::unique_ptr<DBusWrapper> InstalledWrapper;
172
173 struct DefaultDBusWrapper : public DBusWrapper
174 {
175   constexpr static int ELDBUS_CALL_TIMEOUT = 1000;
176
177   DefaultDBusWrapper()
178   {
179   }
180
181   ~DefaultDBusWrapper()
182   {
183   }
184
185   #define DEFINE_GS(name, eldbus_name, unref_call) \
186     static eldbus_name *get(const std::shared_ptr<name> &a) { \
187       return static_cast<name ## Impl*>(a.get())->Value; \
188     } \
189     static eldbus_name *release(const std::shared_ptr<name> &a) { \
190       auto z = static_cast<name ## Impl*>(a.get())->Value; \
191       static_cast<name ## Impl*>(a.get())->Value = nullptr; \
192       return z; \
193     } \
194     template <typename ... ARGS> static std::shared_ptr<name> create(const eldbus_name *v, ARGS && ... args) { \
195       return std::make_shared<name ## Impl>(const_cast<eldbus_name*>(v), std::forward<ARGS>(args)...); \
196     }
197
198   #define DEFINE_TYPE(name, eldbus_name, unref_call) \
199   struct name ## Impl : public name { \
200     eldbus_name *Value = nullptr; \
201     bool EraseOnExit = false; \
202     name ## Impl(eldbus_name *Value, bool EraseOnExit = false) : Value(Value), EraseOnExit(EraseOnExit) { } \
203     ~name ## Impl() { \
204       if (EraseOnExit && Value) { unref_call; } \
205     } \
206   }; \
207   DEFINE_GS(name, eldbus_name, unref_call)
208
209   struct ConnectionImpl : public Connection
210   {
211     Eldbus_Connection *Value = nullptr;
212     bool EraseOnExit = false;
213     ConnectionImpl(Eldbus_Connection *Value, bool EraseOnExit = false) : Value(Value), EraseOnExit(EraseOnExit)
214     {
215       ecore_event_init();
216       eldbus_init();
217     }
218
219     ~ConnectionImpl()
220     {
221       if (EraseOnExit && Value)
222       {
223         eldbus_connection_unref( Value );
224       }
225       eldbus_shutdown();
226       ecore_event_shutdown();
227     }
228   };
229
230   struct MessageIterImpl : public MessageIter
231   {
232     Eldbus_Message_Iter *Value = nullptr, *Parent = nullptr;
233     bool EraseOnExit = false;
234     MessageIterImpl(Eldbus_Message_Iter *Value, Eldbus_Message_Iter *Parent, bool EraseOnExit = false) : Value(Value), Parent(Parent), EraseOnExit(EraseOnExit)
235     {
236     }
237
238     ~MessageIterImpl()
239     {
240       if (EraseOnExit && Value && Parent)
241       {
242         eldbus_message_iter_container_close(Parent, Value);
243       }
244     }
245   };
246
247   DEFINE_GS(Connection, Eldbus_Connection, )
248   DEFINE_GS(MessageIter, Eldbus_Message_Iter, )
249   DEFINE_TYPE(Message, Eldbus_Message, eldbus_message_unref( Value ))
250   DEFINE_TYPE(Proxy, Eldbus_Proxy, )
251   DEFINE_TYPE(Object, Eldbus_Object, eldbus_object_unref( Value ))
252   DEFINE_TYPE(Pending, Eldbus_Pending, )
253   DEFINE_TYPE(EventPropertyChanged, Eldbus_Proxy_Event_Property_Changed, )
254   #undef DEFINE_TYPE
255
256   std::shared_ptr<Connection> eldbus_address_connection_get_impl(const std::string &addr) override
257   {
258     eldbus_init();
259     auto p = eldbus_address_connection_get(addr.c_str());
260     auto w = create(p, true);
261     eldbus_shutdown();
262     return w;
263   }
264
265 #define eldbus_message_iter_arguments_append_impl_basic(type, sig) \
266   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, type src) override { \
267     eldbus_message_iter_arguments_append( get(it), #sig, src ); \
268   } \
269   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, type &dst) override { \
270     return eldbus_message_iter_get_and_next( get(it), (#sig)[0], &dst ); \
271   }
272
273   eldbus_message_iter_arguments_append_impl_basic(uint8_t, y)
274   eldbus_message_iter_arguments_append_impl_basic(uint16_t, q)
275   eldbus_message_iter_arguments_append_impl_basic(uint32_t, u)
276   eldbus_message_iter_arguments_append_impl_basic(uint64_t, t)
277   eldbus_message_iter_arguments_append_impl_basic(int16_t, n)
278   eldbus_message_iter_arguments_append_impl_basic(int32_t, i)
279   eldbus_message_iter_arguments_append_impl_basic(int64_t, x)
280   eldbus_message_iter_arguments_append_impl_basic(double, d)
281
282 #undef eldbus_message_iter_arguments_append_impl_basic
283
284   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, bool src) override
285   {
286     eldbus_message_iter_arguments_append( get(it), "b", src ? 1 : 0 );
287   }
288
289   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, bool &dst) override
290   {
291     unsigned char q;
292     auto z = eldbus_message_iter_get_and_next( get(it), 'b', &q );
293     dst = q != 0;
294     return z;
295   }
296
297   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, const std::string &src) override
298   {
299     eldbus_message_iter_arguments_append( get(it), "s", src.c_str() );
300   }
301
302   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, std::string &dst) override
303   {
304     auto iter = get(it);
305     const char* q;
306     if( !eldbus_message_iter_get_and_next( iter, 's', &q ) )
307     {
308       if( !eldbus_message_iter_get_and_next( iter, 'o', &q ) )
309       {
310         return false;
311       }
312     }
313     dst = q;
314     return true;
315   }
316
317   void eldbus_message_iter_arguments_append_impl(const MessageIterPtr &it, const ObjectPath &src) override
318   {
319     eldbus_message_iter_arguments_append( get(it), "o", src.value.c_str() );
320   }
321
322   bool eldbus_message_iter_get_and_next_impl(const MessageIterPtr &it, ObjectPath &dst) override
323   {
324     const char* q;
325     if( !eldbus_message_iter_get_and_next( get(it), 'o', &q ) )
326     {
327       return false;
328     }
329     dst.value = q;
330     return true;
331   }
332
333   MessageIterPtr eldbus_message_iter_container_new_impl(const MessageIterPtr &it, int type, const std::string &sig) override
334   {
335     auto z = eldbus_message_iter_container_new( get(it), type, !sig.empty() ? sig.c_str() : NULL );
336     return create(z, get(it), true);
337   }
338
339   MessageIterPtr eldbus_message_iter_get_and_next_by_type_impl(const MessageIterPtr &it, int type) override
340   {
341     Eldbus_Message_Iter* entry;
342     if (!eldbus_message_iter_get_and_next( get(it), type, &entry ) )
343     {
344       return {};
345     }
346     return create(entry, get(it), false);
347   }
348
349   MessageIterPtr eldbus_message_iter_get_impl(const MessagePtr &msg, bool) override
350   {
351     return create(eldbus_message_iter_get(get(msg)), nullptr, false);
352   }
353
354   MessagePtr eldbus_proxy_method_call_new_impl(const ProxyPtr &proxy, const std::string &funcName)
355   {
356     return create(eldbus_proxy_method_call_new( get(proxy), funcName.c_str() ) );
357   }
358
359   MessagePtr eldbus_proxy_send_and_block_impl(const ProxyPtr &proxy, const MessagePtr &msg) override
360   {
361     return create(eldbus_proxy_send_and_block(get(proxy), release(msg), ELDBUS_CALL_TIMEOUT) );
362   }
363
364   bool eldbus_message_error_get_impl(const MessagePtr &msg, std::string &name, std::string &text) override
365   {
366     const char *errname, *errmsg;
367     if( eldbus_message_error_get( get(msg), &errname, &errmsg ) )
368     {
369       name = errname;
370       text = errmsg;
371       return true;
372     }
373     return false;
374   }
375
376   std::string eldbus_message_signature_get_impl(const MessagePtr &msg) override
377   {
378     return eldbus_message_signature_get(get(msg));
379   }
380
381   static void callAsyncCb( void* data, const Eldbus_Message *msg,  Eldbus_Pending *pending )
382   {
383     auto d = static_cast< SendCallback* >( data );
384     (*d)( create(msg, false) );
385   }
386
387   static void pendingFreeCb( void* data, const void* )
388   {
389     auto d = static_cast< SendCallback* >( data );
390     delete d;
391   }
392
393   static void listenerCallbackFree( void* data, const void* )
394   {
395     auto d = static_cast< std::function< void( const Eldbus_Message* msg ) >* >( data );
396     delete d;
397   }
398
399   PendingPtr eldbus_proxy_send_impl(const ProxyPtr &proxy, const MessagePtr &msg, const SendCallback &callback) override
400   {
401     auto cb = new SendCallback{ callback };
402     auto pending = eldbus_proxy_send( get(proxy), release(msg), callAsyncCb, cb, ELDBUS_CALL_TIMEOUT );
403     if( pending )
404     {
405       eldbus_pending_free_cb_add( pending, pendingFreeCb, cb );
406     }
407     else
408     {
409       delete cb;
410     }
411     return create(pending, false);
412   }
413
414   std::string eldbus_proxy_interface_get_impl(const ProxyPtr &proxy) override
415   {
416     return eldbus_proxy_interface_get( get(proxy) );
417   }
418
419   static void listenerCallback( void* data, const Eldbus_Message* msg )
420   {
421     auto p = static_cast< std::function< void( const Eldbus_Message* msg ) >* >( data );
422     ( *p )( msg );
423   }
424
425   void eldbus_proxy_signal_handler_add_impl(const ProxyPtr &proxy, const std::string &member, const std::function<void(const MessagePtr &)> &cb) override
426   {
427     auto tmp = new std::function< void( const Eldbus_Message* msg ) >
428     {
429       [cb](const Eldbus_Message* msg)
430       {
431         cb(create(msg, false));
432       }
433     };
434     auto handler = eldbus_proxy_signal_handler_add( get(proxy), member.c_str(), listenerCallback, tmp );
435     if( handler )
436     {
437       eldbus_proxy_free_cb_add( get(proxy), listenerCallbackFree, tmp );
438      }
439     else
440     {
441       delete tmp;
442      }
443   }
444
445   std::string eldbus_message_iter_signature_get_impl(const MessageIterPtr &iter) override
446   {
447     return eldbus_message_iter_signature_get( get(iter) );
448   }
449
450   MessagePtr eldbus_message_method_return_new_impl( const MessagePtr &msg) override
451   {
452     return create(eldbus_message_method_return_new( get(msg) ) );
453   }
454
455   MessagePtr eldbus_message_error_new_impl( const MessagePtr &msg, const std::string &err, const std::string &txt ) override
456   {
457     return create(eldbus_message_error_new( get(msg), err.c_str(), txt.c_str() ) );
458   }
459
460   PendingPtr eldbus_connection_send_impl(const ConnectionPtr &conn, const MessagePtr &msg) override
461   {
462     return create(eldbus_connection_send( get(conn), get(msg), NULL, NULL, -1 ) );
463   }
464
465   MessagePtr eldbus_message_signal_new_impl(const std::string &path, const std::string &iface, const std::string &name) override
466   {
467     return create(eldbus_message_signal_new( path.c_str(), iface.c_str(), name.c_str() ) );
468   }
469
470   MessagePtr eldbus_message_ref_impl(const MessagePtr &msg) override
471   {
472     return create(eldbus_message_ref( get(msg) ), true );
473   }
474
475   ConnectionPtr eldbus_connection_get_impl(ConnectionType type) override
476   {
477     Eldbus_Connection_Type eldbusType = ELDBUS_CONNECTION_TYPE_SYSTEM;
478
479     switch( type )
480     {
481       case ConnectionType::SYSTEM:
482       {
483         eldbusType = ELDBUS_CONNECTION_TYPE_SYSTEM;
484         break;
485       }
486       case ConnectionType::SESSION:
487       {
488         eldbusType = ELDBUS_CONNECTION_TYPE_SESSION;
489         break;
490       }
491     }
492
493     eldbus_init();
494     auto p = eldbus_connection_get( eldbusType );
495     auto w = create(p, true);
496     eldbus_shutdown();
497     return w;
498   }
499
500   std::string eldbus_connection_unique_name_get_impl(const ConnectionPtr &conn) override
501   {
502     return eldbus_connection_unique_name_get( get(conn) );
503   }
504
505   ObjectPtr eldbus_object_get_impl( const ConnectionPtr &conn, const std::string &bus, const std::string &path ) override
506   {
507       return create(eldbus_object_get(get(conn), bus.c_str(), path.c_str() ), true );
508   }
509
510   ProxyPtr eldbus_proxy_get_impl( const ObjectPtr &obj, const std::string &interface ) override
511   {
512     return create(eldbus_proxy_get(get(obj), interface.c_str() ), false );
513   }
514
515   ProxyPtr eldbus_proxy_copy_impl( const ProxyPtr &ptr) override
516   {
517     return create(get(ptr), false );
518   }
519
520   struct Implementation
521   {
522     Eldbus_Service_Interface_Desc dsc;
523     std::vector< std::vector< Eldbus_Arg_Info > > argsInfos;
524     std::vector< Eldbus_Method > methods;
525     std::vector< Eldbus_Signal > signals;
526     std::vector< Eldbus_Property > properties;
527
528     std::unordered_map< std::string, DBusWrapper::MethodInfo > methodsMap;
529     std::unordered_map< std::string, DBusWrapper::PropertyInfo > propertiesMap;
530     std::unordered_map< unsigned int, DBusWrapper::SignalInfo > signalsMap;
531
532     DBusWrapper::ConnectionWeakPtr connection;
533   };
534
535   static std::unordered_map< const Eldbus_Service_Interface*, std::unique_ptr< Implementation > > globalEntries;
536   static std::mutex globalEntriesMutex;
537
538 #undef EINA_FALSE
539 #undef EINA_TRUE
540 #define EINA_FALSE static_cast<Eina_Bool>(0)
541 #define EINA_TRUE static_cast<Eina_Bool>(1)
542
543   static Eina_Bool property_get_callback( const Eldbus_Service_Interface* iface, const char* propertyName, Eldbus_Message_Iter* iter,
544                                           const Eldbus_Message* message, Eldbus_Message** error )
545   {
546     Implementation* impl = nullptr;
547     {
548       std::lock_guard< std::mutex > lock( globalEntriesMutex );
549       auto it = globalEntries.find( iface );
550       if( it != globalEntries.end() )
551       {
552         impl = it->second.get();
553       }
554     }
555     if( !impl )
556     {
557       return EINA_FALSE;
558     }
559
560     auto it = impl->propertiesMap.find( propertyName );
561     if( it == impl->propertiesMap.end() || !it->second.getCallback )
562     {
563       return EINA_FALSE;
564     }
565
566     auto connection = impl->connection.lock();
567     if( !connection )
568     {
569       return EINA_FALSE;
570     }
571
572     DBus::DBusServer::CurrentObjectSetter currentObjectSetter( connection, eldbus_message_path_get( message ) );
573     auto reply = it->second.getCallback( create(message, false), create(iter, nullptr, false) );
574     if( !reply.empty() )
575     {
576       if( error )
577       {
578         *error = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", reply.c_str() );
579       }
580       return EINA_FALSE;
581     }
582
583     return EINA_TRUE;
584   }
585
586   static Eldbus_Message* property_set_callback( const Eldbus_Service_Interface* iface, const char* propertyName, Eldbus_Message_Iter* iter,
587                                                 const Eldbus_Message* message )
588   {
589     Implementation* impl = nullptr;
590     {
591       std::lock_guard< std::mutex > lock( globalEntriesMutex );
592       auto it = globalEntries.find( iface );
593       if( it != globalEntries.end() )
594       {
595         impl = it->second.get();
596       }
597     }
598     if( !impl )
599     {
600       auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Unknown interface" );
601       return ret;
602     }
603     auto it = impl->propertiesMap.find( propertyName );
604     if( it == impl->propertiesMap.end() || !it->second.setCallback )
605     {
606       auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Unknown setter" );
607       return ret;
608     }
609     auto connection = impl->connection.lock();
610     if( !connection )
611     {
612       auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Connection lost" );
613       return ret;
614     }
615
616     DBus::DBusServer::CurrentObjectSetter currentObjectSetter( connection, eldbus_message_path_get( message ) );
617     auto reply = it->second.setCallback( create(message, false), create(iter, nullptr, false) );
618
619     Eldbus_Message* ret = nullptr;
620     if( !reply.empty() )
621     {
622       ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", reply.c_str() );
623     }
624     else
625     {
626       ret = eldbus_message_method_return_new( message );
627     }
628     return ret;
629   }
630
631   static Eldbus_Message* method_callback( const Eldbus_Service_Interface* iface, const Eldbus_Message* message )
632   {
633     Implementation* impl = nullptr;
634     {
635       std::lock_guard< std::mutex > lock( globalEntriesMutex );
636       auto it = globalEntries.find( iface );
637       if( it != globalEntries.end() )
638         impl = it->second.get();
639     }
640     if( !impl )
641     {
642       auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Unknown interface" );
643       return ret;
644     }
645     std::string memberName = eldbus_message_member_get( message );
646     auto it = impl->methodsMap.find( memberName );
647     if( it == impl->methodsMap.end() )
648     {
649       auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Unknown method" );
650       return ret;
651     }
652     auto connection = impl->connection.lock();
653     if( !connection )
654     {
655       auto ret = eldbus_message_error_new( message, "org.freedesktop.DBus.Error.Failed", "Connection lost" );
656       return ret;
657     }
658     DBus::DBusServer::CurrentObjectSetter currentObjectSetter( connection, eldbus_message_path_get( message ) );
659     auto reply = it->second.callback( create(message) );
660     return release(reply);
661   }
662
663   void add_interface_impl( bool fallback, const std::string& pathName,
664                               const ConnectionPtr &connection,
665                               std::vector<std::function<void()>> &destructors,
666                               const std::string& interfaceName,
667                               std::vector< MethodInfo >& dscrMethods,
668                               std::vector< PropertyInfo >& dscrProperties,
669                               std::vector< SignalInfo >& dscrSignals ) override
670   {
671     std::vector< Eldbus_Method > methods;
672     std::vector< Eldbus_Signal > signals;
673     std::vector< Eldbus_Property > properties;
674     std::vector< std::vector< Eldbus_Arg_Info > > argsInfos;
675     std::unordered_map< std::string, DBus::DBusInterfaceDescription::MethodInfo > methodsMap;
676     std::unordered_map< std::string, DBus::DBusInterfaceDescription::PropertyInfo > propertiesMap;
677     std::unordered_map< unsigned int, DBus::DBusInterfaceDescription::SignalInfo > signalsMap;
678
679     DBUS_DEBUG( "interface %s path %s on bus %s", interfaceName.c_str(), pathName.c_str(), DBus::getConnectionName( connection ).c_str() );
680     auto makeArgInfo = [&](const std::vector<std::pair<std::string, std::string>> &input) {
681       argsInfos.push_back({});
682       auto &dst = argsInfos.back();
683       for(auto &s : input)
684       {
685         auto a = Strings.add(s.first);
686         auto b = Strings.add(s.second);
687         dst.push_back({ a, b });
688       }
689       dst.push_back({ nullptr, nullptr });
690       return dst.data();
691     };
692     for( auto& ee : dscrMethods )
693     {
694       auto key = ee.memberName;
695       DBUS_DEBUG( "adding method %s", ee.memberName.c_str() );
696       for( auto& r : ee.in )
697       {
698         DBUS_DEBUG( "in %s '%s'", r.first.c_str(), r.second.c_str() );
699       }
700       for( auto& r : ee.out )
701       {
702         DBUS_DEBUG( "out %s '%s'", r.first.c_str(), r.second.c_str() );
703       }
704       auto& e = ( methodsMap[key] = std::move( ee ) );
705       methods.push_back( {} );
706       auto& m = methods.back();
707       m.member = e.memberName.c_str();
708       m.in = makeArgInfo(e.in);
709       m.out = makeArgInfo(e.out);
710       m.cb = method_callback;
711       m.flags = 0;
712     }
713     for( auto& ee : dscrProperties )
714     {
715       auto key = ee.memberName;
716       DBUS_DEBUG( "adding property %s", ee.memberName.c_str() );
717       auto& e = ( propertiesMap[key] = std::move( ee ) );
718       properties.push_back( {} );
719       auto& m = properties.back();
720       m.name = e.memberName.c_str();
721       m.type = e.typeSignature.c_str();
722       m.get_func = e.getCallback ? property_get_callback : nullptr;
723       m.set_func = e.setCallback ? property_set_callback : nullptr;
724       m.flags = 0;
725     }
726     dscrMethods.clear();
727     dscrProperties.clear();
728     dscrSignals.clear();
729
730     methods.push_back( {nullptr, nullptr, nullptr, nullptr, 0} );
731     signals.push_back( {nullptr, nullptr, 0} );
732     properties.push_back( {nullptr, nullptr, nullptr, nullptr, 0} );
733
734     auto impl = std::unique_ptr< Implementation >( new Implementation{
735         {interfaceName.c_str(),
736         methods.data(),
737         signals.data(),
738         properties.data(),
739         nullptr,
740         nullptr},
741         std::move( argsInfos ),
742         std::move( methods ),
743         std::move( signals ),
744         std::move( properties ),
745         std::move( methodsMap ),
746         std::move( propertiesMap ),
747         std::move( signalsMap ),
748         connection} );
749
750     {
751       std::lock_guard< std::mutex > lock( globalEntriesMutex );
752       auto v = fallback ? eldbus_service_interface_fallback_register( get(connection), pathName.c_str(), &impl->dsc ) : eldbus_service_interface_register( get(connection), pathName.c_str(), &impl->dsc );
753       assert( v );
754       globalEntries[v] = std::move( impl );
755       DBUS_DEBUG( "registering interface %p (%d)", v, fallback ? 1 : 0 );
756       destructors.push_back([=]()
757         {
758           DBUS_DEBUG( "unregistering interface %p", v );
759           {
760             std::lock_guard< std::mutex > lock( globalEntriesMutex );
761             globalEntries.erase( v );
762           }
763           eldbus_service_interface_unregister( v );
764         }
765       );
766     }
767   }
768
769   static void listenerEventChangedCallback( void* data, Eldbus_Proxy* proxy EINA_UNUSED, void* event )
770   {
771     auto p = static_cast< std::function< void( Eldbus_Proxy_Event_Property_Changed* ) >* >( data );
772     ( *p )( static_cast< Eldbus_Proxy_Event_Property_Changed* >( event ) );
773   }
774
775   static void ProxyEventCallbackDelCb( void* data, const void *obj )
776   {
777     auto d = static_cast< std::function< void( Eldbus_Proxy_Event_Property_Changed* ) >* >( data );
778     delete d;
779   }
780
781   void add_property_changed_event_listener_impl( const ProxyPtr &proxy, const std::string &interface, const std::string &name, std::function< void( const Eina_Value * ) > cb) override
782   {
783     auto callbackLambdaPtr = new std::function< void( Eldbus_Proxy_Event_Property_Changed *epc ) >
784     {
785       [cb, name, interface]( Eldbus_Proxy_Event_Property_Changed *ev )
786       {
787         const char* ifc = eldbus_proxy_interface_get( ev->proxy );
788         if( ev->name && ev->name == name && ifc && interface == ifc )
789         {
790           cb(ev->value);
791         }
792       }
793     };
794     auto p = get(proxy);
795     eldbus_proxy_event_callback_add( p, ELDBUS_PROXY_EVENT_PROPERTY_CHANGED, listenerEventChangedCallback, callbackLambdaPtr );
796     eldbus_proxy_free_cb_add( p, ProxyEventCallbackDelCb, callbackLambdaPtr );
797   }
798 };
799
800 std::unordered_map< const Eldbus_Service_Interface*, std::unique_ptr< DefaultDBusWrapper::Implementation > > DefaultDBusWrapper::globalEntries;
801 std::mutex DefaultDBusWrapper::globalEntriesMutex;
802
803 DBusWrapper *DBusWrapper::Installed()
804 {
805   if (!InstalledWrapper)
806   {
807     InstalledWrapper.reset(new DefaultDBusWrapper);
808   }
809   return InstalledWrapper.get();
810 }
811
812 void DBusWrapper::Install(std::unique_ptr<DBusWrapper> w)
813 {
814   InstalledWrapper = std::move(w);
815 }