[PVR][Estuary] Timer settings dialog: Show client name in timer type selection dialog...
[xbmc.git] / xbmc / platform / linux / DBusUtil.cpp
blob2efb75cb0866468df62a89f474843677faac8a6a
1 /*
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.
7 */
8 #include "DBusUtil.h"
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");
16 CVariant result;
18 message.AppendArgument(interface);
19 message.AppendArgument(property);
20 DBusMessage *reply = message.SendSystem();
22 if (reply)
24 DBusMessageIter iter;
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));
31 else
32 result = ParseVariant(&iter);
36 return result;
39 CVariant CDBusUtil::GetAll(const char *destination, const char *object, const char *interface)
41 CDBusMessage message(destination, object, "org.freedesktop.DBus.Properties", "GetAll");
42 CVariant properties;
43 message.AppendArgument(interface);
44 DBusMessage *reply = message.SendSystem();
45 if (reply)
47 DBusMessageIter iter;
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));
53 else
57 DBusMessageIter sub;
58 dbus_message_iter_recurse(&iter, &sub);
61 DBusMessageIter dict;
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))
69 break;
71 CVariant value = ParseVariant(&dict);
73 if (!value.isNull())
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));
85 return properties;
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)
98 CVariant value;
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;
105 double doublev = 0;
107 int type = dbus_message_iter_get_arg_type(itr);
108 switch (type)
110 case DBUS_TYPE_OBJECT_PATH:
111 case DBUS_TYPE_STRING:
112 dbus_message_iter_get_basic(itr, &string);
113 value = string;
114 break;
115 case DBUS_TYPE_UINT32:
116 dbus_message_iter_get_basic(itr, &uint32);
117 value = (uint64_t)uint32;
118 break;
119 case DBUS_TYPE_BYTE:
120 case DBUS_TYPE_INT32:
121 dbus_message_iter_get_basic(itr, &int32);
122 value = (int64_t)int32;
123 break;
124 case DBUS_TYPE_UINT64:
125 dbus_message_iter_get_basic(itr, &uint64);
126 value = (uint64_t)uint64;
127 break;
128 case DBUS_TYPE_INT64:
129 dbus_message_iter_get_basic(itr, &int64);
130 value = (int64_t)int64;
131 break;
132 case DBUS_TYPE_BOOLEAN:
133 dbus_message_iter_get_basic(itr, &boolean);
134 value = (bool)boolean;
135 break;
136 case DBUS_TYPE_DOUBLE:
137 dbus_message_iter_get_basic(itr, &doublev);
138 value = doublev;
139 break;
140 case DBUS_TYPE_ARRAY:
141 DBusMessageIter array;
142 dbus_message_iter_recurse(itr, &array);
144 value = CVariant::VariantTypeArray;
148 CVariant item = ParseType(&array);
149 if (!item.isNull())
150 value.push_back(item);
151 } while (dbus_message_iter_next(&array));
152 break;
155 return value;
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);
161 CDBusError error;
162 message.Send(bus, error);
163 if (error)
165 error.Log(LOGDEBUG, std::string("DBus method call to ") + interface + "." + method + " at " + object + " of " + destination + " failed");
167 return !error;
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)
179 CDBusError error;
180 Connect(bus, error, openPrivate);
181 if (error)
183 error.Log(LOGWARNING, "DBus connection failed");
184 return false;
187 return true;
190 bool CDBusConnection::Connect(DBusBusType bus, CDBusError& error, bool openPrivate)
192 if (m_connection)
194 throw std::logic_error("Cannot reopen connected DBus connection");
197 m_connection.get_deleter().closeBeforeUnref = openPrivate;
199 if (openPrivate)
201 m_connection.reset(dbus_bus_get_private(bus, error));
203 else
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()
238 Reset();
241 void CDBusError::Reset()
243 dbus_error_free(&m_error);
246 CDBusError::operator DBusError*()
248 return &m_error;
251 bool CDBusError::IsSet() const
253 return dbus_error_is_set(&m_error);
256 CDBusError::operator bool()
258 return IsSet();
261 CDBusError::operator bool() const
263 return IsSet();
266 std::string CDBusError::Name() const
268 if (!IsSet())
270 throw std::logic_error("Cannot retrieve name of unset DBus error");
272 return m_error.name;
275 std::string CDBusError::Message() const
277 if (!IsSet())
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
291 if (!IsSet())
293 throw std::logic_error("Cannot log unset DBus error");
295 CLog::Log(level, "{}: {} - {}", message, m_error.name, m_error.message);