mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	bluez5: add convenience helper for dbus pending calls
This commit is contained in:
		
							parent
							
								
									42e463f726
								
							
						
					
					
						commit
						a07dfbbdb9
					
				
					 2 changed files with 104 additions and 35 deletions
				
			
		| 
						 | 
					@ -292,36 +292,26 @@ static void interfaces_removed(struct impl *impl, DBusMessageIter *arg_iter)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void get_managed_objects_reply(DBusPendingCall *pending, void *user_data)
 | 
					static void get_managed_objects_reply(DBusPendingCall **call_ptr, DBusMessage *r)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = user_data;
 | 
						struct impl *impl = SPA_CONTAINER_OF(call_ptr, struct impl, get_managed_objects_call);
 | 
				
			||||||
	DBusMessage *r;
 | 
					 | 
				
			||||||
	DBusMessageIter it[6];
 | 
						DBusMessageIter it[6];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_assert(pending == impl->get_managed_objects_call);
 | 
					 | 
				
			||||||
	impl->get_managed_objects_call = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	r = dbus_pending_call_steal_reply(pending);
 | 
					 | 
				
			||||||
	dbus_pending_call_unref(pending);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (r == NULL)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (dbus_message_is_error(r, DBUS_ERROR_UNKNOWN_METHOD)) {
 | 
						if (dbus_message_is_error(r, DBUS_ERROR_UNKNOWN_METHOD)) {
 | 
				
			||||||
		spa_log_warn(impl->log, "BlueZ D-Bus ObjectManager not available");
 | 
							spa_log_warn(impl->log, "BlueZ D-Bus ObjectManager not available");
 | 
				
			||||||
		goto done;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
 | 
						if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
 | 
				
			||||||
		spa_log_error(impl->log, "GetManagedObjects() failed: %s",
 | 
							spa_log_error(impl->log, "GetManagedObjects() failed: %s",
 | 
				
			||||||
				dbus_message_get_error_name(r));
 | 
									dbus_message_get_error_name(r));
 | 
				
			||||||
		goto done;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!dbus_message_iter_init(r, &it[0]) ||
 | 
						if (!dbus_message_iter_init(r, &it[0]) ||
 | 
				
			||||||
			!spa_streq(dbus_message_get_signature(r), "a{oa{sa{sv}}}")) {
 | 
								!spa_streq(dbus_message_get_signature(r), "a{oa{sa{sv}}}")) {
 | 
				
			||||||
		spa_log_error(impl->log, "Invalid reply signature for GetManagedObjects()");
 | 
							spa_log_error(impl->log, "Invalid reply signature for GetManagedObjects()");
 | 
				
			||||||
		goto done;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Add fake object representing the service itself */
 | 
						/* Add fake object representing the service itself */
 | 
				
			||||||
| 
						 | 
					@ -338,17 +328,11 @@ static void get_managed_objects_reply(DBusPendingCall *pending, void *user_data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->objects_listed = true;
 | 
						impl->objects_listed = true;
 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	dbus_message_unref(r);
 | 
					 | 
				
			||||||
	return;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int get_managed_objects(struct impl *impl)
 | 
					static int get_managed_objects(struct impl *impl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	DBusMessage *m = NULL;
 | 
						DBusMessage *m;
 | 
				
			||||||
	DBusPendingCall *call;
 | 
					 | 
				
			||||||
	int res = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->objects_listed || impl->get_managed_objects_call)
 | 
						if (impl->objects_listed || impl->get_managed_objects_call)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -362,19 +346,8 @@ static int get_managed_objects(struct impl *impl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dbus_message_set_auto_start(m, false);
 | 
						dbus_message_set_auto_start(m, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!dbus_connection_send_with_reply(impl->conn, m, &call, -1)) {
 | 
						return spa_dbus_async_call(impl->conn, m, &impl->get_managed_objects_call,
 | 
				
			||||||
		res = -EIO;
 | 
								get_managed_objects_reply);
 | 
				
			||||||
		goto done;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dbus_pending_call_set_notify(call, get_managed_objects_reply, impl, NULL);
 | 
					 | 
				
			||||||
	impl->get_managed_objects_call = call;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
done:
 | 
					 | 
				
			||||||
	if (m)
 | 
					 | 
				
			||||||
		dbus_message_unref(m);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return res;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -696,3 +669,72 @@ struct spa_list *spa_dbus_monitor_object_list(struct spa_dbus_monitor *this, con
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return object_list;
 | 
						return object_list;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*pending_call_reply_t)(DBusPendingCall **, DBusMessage *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static dbus_int32_t async_call_reply_id = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void async_call_reply(DBusPendingCall *pending, void *user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DBusPendingCall **call_ptr = user_data;
 | 
				
			||||||
 | 
						DBusMessage *r;
 | 
				
			||||||
 | 
						pending_call_reply_t reply;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_assert(pending == *call_ptr);
 | 
				
			||||||
 | 
						*call_ptr = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r = dbus_pending_call_steal_reply(pending);
 | 
				
			||||||
 | 
						reply = dbus_pending_call_get_data(pending, async_call_reply_id);
 | 
				
			||||||
 | 
						dbus_pending_call_unref(pending);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_assert(reply != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (r == NULL)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reply(call_ptr, r);
 | 
				
			||||||
 | 
						dbus_message_unref(r);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spa_dbus_async_call(DBusConnection *conn, DBusMessage *msg,
 | 
				
			||||||
 | 
							DBusPendingCall **call_ptr,
 | 
				
			||||||
 | 
							pending_call_reply_t reply)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int res = -EIO;
 | 
				
			||||||
 | 
						DBusPendingCall *pending;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_assert(msg);
 | 
				
			||||||
 | 
						spa_assert(call_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (async_call_reply_id == -1) {
 | 
				
			||||||
 | 
							if (!dbus_pending_call_allocate_data_slot(&async_call_reply_id))
 | 
				
			||||||
 | 
								goto done;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*call_ptr) {
 | 
				
			||||||
 | 
							res = -EBUSY;
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!dbus_connection_send_with_reply(conn, msg, &pending, -1))
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!dbus_pending_call_set_data(pending, async_call_reply_id, reply, NULL)) {
 | 
				
			||||||
 | 
							dbus_pending_call_cancel(pending);
 | 
				
			||||||
 | 
							dbus_pending_call_unref(pending);
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!dbus_pending_call_set_notify(pending, async_call_reply, call_ptr, NULL)) {
 | 
				
			||||||
 | 
							dbus_pending_call_cancel(pending);
 | 
				
			||||||
 | 
							dbus_pending_call_unref(pending);
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*call_ptr = pending;
 | 
				
			||||||
 | 
						res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					done:
 | 
				
			||||||
 | 
						dbus_message_unref(msg);
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,7 @@ struct spa_dbus_interface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Interface at the object path removed.
 | 
						 * Interface at the object path removed.
 | 
				
			||||||
 | 
						 * No other hooks will be called after this.
 | 
				
			||||||
	 * The object will be deallocated after this, so any associated data,
 | 
						 * The object will be deallocated after this, so any associated data,
 | 
				
			||||||
	 * for example in a custom object struct, can be freed in this hook.
 | 
						 * for example in a custom object struct, can be freed in this hook.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -136,4 +137,30 @@ void spa_dbus_monitor_ignore_object(struct spa_dbus_monitor *monitor,
 | 
				
			||||||
struct spa_list *spa_dbus_monitor_object_list(struct spa_dbus_monitor *monitor,
 | 
					struct spa_list *spa_dbus_monitor_object_list(struct spa_dbus_monitor *monitor,
 | 
				
			||||||
		const char *interface);
 | 
							const char *interface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Make an asynchronous DBus call.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * On successful return, *call_ptr contains the pending call handle.
 | 
				
			||||||
 | 
					 * The same address is passed to the reply function, and can be used
 | 
				
			||||||
 | 
					 * to locate the address container object. The reply function does not
 | 
				
			||||||
 | 
					 * need to unref the reply, or set *call_ptr to NULL itself.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The msg passed in is stolen, and unref'd also on errors.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \returns 0 on success, < 0 on error.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int spa_dbus_async_call(DBusConnection *conn, DBusMessage *msg,
 | 
				
			||||||
 | 
							DBusPendingCall **call_ptr,
 | 
				
			||||||
 | 
							void (*reply)(DBusPendingCall **call_ptr, DBusMessage *reply));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Convenience for pending call cancel + unref */
 | 
				
			||||||
 | 
					static inline void spa_dbus_async_call_cancel(DBusPendingCall **call_ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (*call_ptr) {
 | 
				
			||||||
 | 
							dbus_pending_call_cancel(*call_ptr);
 | 
				
			||||||
 | 
							dbus_pending_call_unref(*call_ptr);
 | 
				
			||||||
 | 
							*call_ptr = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue