2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
10 #include "utils/log.h"
12 CVariant
CDBusUtil::GetVariant(const char *destination
, const char *object
, const char *interface
, const char *property
)
14 //dbus-send --system --print-reply --dest=destination object org.freedesktop.DBus.Properties.Get string:interface string:property
15 CDBusMessage
message(destination
, object
, "org.freedesktop.DBus.Properties", "Get");
18 message
.AppendArgument(interface
);
19 message
.AppendArgument(property
);
20 DBusMessage
*reply
= message
.SendSystem();
26 if (dbus_message_iter_init(reply
, &iter
))
28 if (!dbus_message_has_signature(reply
, "v"))
29 CLog::Log(LOGERROR
, "DBus: wrong signature on Get - should be \"v\" but was {}",
30 dbus_message_iter_get_signature(&iter
));
32 result
= ParseVariant(&iter
);
39 CVariant
CDBusUtil::GetAll(const char *destination
, const char *object
, const char *interface
)
41 CDBusMessage
message(destination
, object
, "org.freedesktop.DBus.Properties", "GetAll");
43 message
.AppendArgument(interface
);
44 DBusMessage
*reply
= message
.SendSystem();
48 if (dbus_message_iter_init(reply
, &iter
))
50 if (!dbus_message_has_signature(reply
, "a{sv}"))
51 CLog::Log(LOGERROR
, "DBus: wrong signature on GetAll - should be \"a{sv}\" but was {}",
52 dbus_message_iter_get_signature(&iter
));
58 dbus_message_iter_recurse(&iter
, &sub
);
62 dbus_message_iter_recurse(&sub
, &dict
);
65 const char * key
= NULL
;
67 dbus_message_iter_get_basic(&dict
, &key
);
68 if (!dbus_message_iter_next(&dict
))
71 CVariant value
= ParseVariant(&dict
);
74 properties
[key
] = value
;
76 } while (dbus_message_iter_next(&dict
));
78 } while (dbus_message_iter_next(&sub
));
80 } while (dbus_message_iter_next(&iter
));
88 CVariant
CDBusUtil::ParseVariant(DBusMessageIter
*itr
)
90 DBusMessageIter variant
;
91 dbus_message_iter_recurse(itr
, &variant
);
93 return ParseType(&variant
);
96 CVariant
CDBusUtil::ParseType(DBusMessageIter
*itr
)
99 const char * string
= NULL
;
100 dbus_int32_t int32
= 0;
101 dbus_uint32_t uint32
= 0;
102 dbus_int64_t int64
= 0;
103 dbus_uint64_t uint64
= 0;
104 dbus_bool_t boolean
= false;
107 int type
= dbus_message_iter_get_arg_type(itr
);
110 case DBUS_TYPE_OBJECT_PATH
:
111 case DBUS_TYPE_STRING
:
112 dbus_message_iter_get_basic(itr
, &string
);
115 case DBUS_TYPE_UINT32
:
116 dbus_message_iter_get_basic(itr
, &uint32
);
117 value
= (uint64_t)uint32
;
120 case DBUS_TYPE_INT32
:
121 dbus_message_iter_get_basic(itr
, &int32
);
122 value
= (int64_t)int32
;
124 case DBUS_TYPE_UINT64
:
125 dbus_message_iter_get_basic(itr
, &uint64
);
126 value
= (uint64_t)uint64
;
128 case DBUS_TYPE_INT64
:
129 dbus_message_iter_get_basic(itr
, &int64
);
130 value
= (int64_t)int64
;
132 case DBUS_TYPE_BOOLEAN
:
133 dbus_message_iter_get_basic(itr
, &boolean
);
134 value
= (bool)boolean
;
136 case DBUS_TYPE_DOUBLE
:
137 dbus_message_iter_get_basic(itr
, &doublev
);
140 case DBUS_TYPE_ARRAY
:
141 DBusMessageIter array
;
142 dbus_message_iter_recurse(itr
, &array
);
144 value
= CVariant::VariantTypeArray
;
148 CVariant item
= ParseType(&array
);
150 value
.push_back(item
);
151 } while (dbus_message_iter_next(&array
));
158 bool CDBusUtil::TryMethodCall(DBusBusType bus
, const char* destination
, const char* object
, const char* interface
, const char* method
)
160 CDBusMessage
message(destination
, object
, interface
, method
);
162 message
.Send(bus
, error
);
165 error
.Log(LOGDEBUG
, std::string("DBus method call to ") + interface
+ "." + method
+ " at " + object
+ " of " + destination
+ " failed");
170 bool CDBusUtil::TryMethodCall(DBusBusType bus
, std::string
const& destination
, std::string
const& object
, std::string
const& interface
, std::string
const& method
)
172 return TryMethodCall(bus
, destination
.c_str(), object
.c_str(), interface
.c_str(), method
.c_str());
175 CDBusConnection::CDBusConnection() = default;
177 bool CDBusConnection::Connect(DBusBusType bus
, bool openPrivate
)
180 Connect(bus
, error
, openPrivate
);
183 error
.Log(LOGWARNING
, "DBus connection failed");
190 bool CDBusConnection::Connect(DBusBusType bus
, CDBusError
& error
, bool openPrivate
)
194 throw std::logic_error("Cannot reopen connected DBus connection");
197 m_connection
.get_deleter().closeBeforeUnref
= openPrivate
;
201 m_connection
.reset(dbus_bus_get_private(bus
, error
));
205 m_connection
.reset(dbus_bus_get(bus
, error
));
208 return !!m_connection
;
211 CDBusConnection::operator DBusConnection
*()
213 return m_connection
.get();
216 void CDBusConnection::DBusConnectionDeleter::operator()(DBusConnection
* connection
) const
218 if (closeBeforeUnref
)
220 dbus_connection_close(connection
);
222 dbus_connection_unref(connection
);
225 void CDBusConnection::Destroy()
227 m_connection
.reset();
231 CDBusError::CDBusError()
233 dbus_error_init(&m_error
);
236 CDBusError::~CDBusError()
241 void CDBusError::Reset()
243 dbus_error_free(&m_error
);
246 CDBusError::operator DBusError
*()
251 bool CDBusError::IsSet() const
253 return dbus_error_is_set(&m_error
);
256 CDBusError::operator bool()
261 CDBusError::operator bool() const
266 std::string
CDBusError::Name() const
270 throw std::logic_error("Cannot retrieve name of unset DBus error");
275 std::string
CDBusError::Message() const
279 throw std::logic_error("Cannot retrieve message of unset DBus error");
281 return m_error
.message
;
284 void CDBusError::Log(std::string
const& message
) const
286 Log(LOGERROR
, message
);
289 void CDBusError::Log(int level
, const std::string
& message
) const
293 throw std::logic_error("Cannot log unset DBus error");
295 CLog::Log(level
, "{}: {} - {}", message
, m_error
.name
, m_error
.message
);