Re: [PATCH BlueZ 1/2] mpris-proxy: Add mpris:artUrl support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Frédéric,

On Fri, Jan 24, 2025 at 11:48 AM Frédéric Danis
<frederic.danis@xxxxxxxxxxxxx> wrote:
>
> This commit connects to the bip-avrcp Obex service if the
> org.bluez.MediaPlayer ObexPort property exists.
> Once connected, the Track properties update may contain an
> ImgHandle which is automatically downloaded, then a Metadata
> property updated signal is sent on org.mpris.MediaPlayer2.Player
> interface.
>
> Some devices share the Obex session between multiple players. So
> the Obex session is created by device.

Can you add a sample output? Also our long term plan is to integrate
mpris-player functionality into bluetoothctl.

> ---
>  tools/mpris-proxy.c | 435 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 425 insertions(+), 10 deletions(-)
>
> diff --git a/tools/mpris-proxy.c b/tools/mpris-proxy.c
> index e5fc91fdb..1f6c86777 100644
> --- a/tools/mpris-proxy.c
> +++ b/tools/mpris-proxy.c
> @@ -30,11 +30,18 @@
>  #define BLUEZ_BUS_NAME "org.bluez"
>  #define BLUEZ_PATH "/org/bluez"
>  #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1"
> +#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1"
>  #define BLUEZ_MEDIA_INTERFACE "org.bluez.Media1"
>  #define BLUEZ_MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer1"
>  #define BLUEZ_MEDIA_FOLDER_INTERFACE "org.bluez.MediaFolder1"
>  #define BLUEZ_MEDIA_ITEM_INTERFACE "org.bluez.MediaItem1"
>  #define BLUEZ_MEDIA_TRANSPORT_INTERFACE "org.bluez.MediaTransport1"
> +#define BLUEZ_OBEX_BUS_NAME "org.bluez.obex"
> +#define BLUEZ_OBEX_PATH "/org/bluez/obex"
> +#define BLUEZ_OBEX_CLIENT_PATH BLUEZ_OBEX_PATH "/client"
> +#define BLUEZ_OBEX_CLIENT_INTERFACE "org.bluez.obex.Client1"
> +#define BLUEZ_OBEX_IMAGE_INTERFACE "org.bluez.obex.Image1"
> +#define BLUEZ_OBEX_TRANSFER_INTERFACE "org.bluez.obex.Transfer1"
>  #define MPRIS_BUS_NAME "org.mpris.MediaPlayer2."
>  #define MPRIS_INTERFACE "org.mpris.MediaPlayer2"
>  #define MPRIS_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
> @@ -48,8 +55,10 @@ static GDBusProxy *adapter = NULL;
>  static DBusConnection *sys = NULL;
>  static DBusConnection *session = NULL;
>  static GDBusClient *client = NULL;
> +static GDBusClient *obex_client;
>  static GSList *players = NULL;
>  static GSList *transports = NULL;
> +static GSList *obex_sessions;
>
>  static gboolean option_version = FALSE;
>  static gboolean option_export = FALSE;
> @@ -59,6 +68,12 @@ struct tracklist {
>         GSList *items;
>  };
>
> +struct obex_session {
> +       GDBusProxy *device;
> +       GDBusProxy *obex;
> +       uint16_t port;
> +};
> +
>  struct player {
>         char *bus_name;
>         DBusConnection *conn;
> @@ -67,11 +82,14 @@ struct player {
>         GDBusProxy *device;
>         GDBusProxy *transport;
>         GDBusProxy *playlist;
> +       struct obex_session *obex;
>         struct tracklist *tracklist;
> +       char *filename;
>  };
>
>  typedef int (* parse_metadata_func) (DBusMessageIter *iter, const char *key,
> -                                               DBusMessageIter *metadata);
> +                                               DBusMessageIter *metadata,
> +                                               void *userdata);
>
>  static void dict_append_entry(DBusMessageIter *dict, const char *key, int type,
>                                                                 void *val);
> @@ -240,7 +258,8 @@ static void dict_append_iter(DBusMessageIter *dict, const char *key,
>  }
>
>  static int parse_metadata_entry(DBusMessageIter *entry, const char *key,
> -                                               DBusMessageIter *metadata)
> +                                               DBusMessageIter *metadata,
> +                                               void *userdata)
>  {
>         if (dbus_message_iter_get_arg_type(entry) != DBUS_TYPE_VARIANT)
>                 return -EINVAL;
> @@ -251,7 +270,8 @@ static int parse_metadata_entry(DBusMessageIter *entry, const char *key,
>  }
>
>  static int parse_metadata(DBusMessageIter *args, DBusMessageIter *metadata,
> -                                               parse_metadata_func func)
> +                                               parse_metadata_func func,
> +                                               void *userdata)
>  {
>         DBusMessageIter dict;
>         int ctype;
> @@ -277,7 +297,7 @@ static int parse_metadata(DBusMessageIter *args, DBusMessageIter *metadata,
>                 dbus_message_iter_get_basic(&entry, &key);
>                 dbus_message_iter_next(&entry);
>
> -               if (func(&entry, key, metadata) < 0)
> +               if (func(&entry, key, metadata, userdata) < 0)
>                         return -EINVAL;
>
>                 dbus_message_iter_next(&dict);
> @@ -299,7 +319,7 @@ static void append_metadata(DBusMessageIter *iter, DBusMessageIter *dict,
>                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
>                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata);
>
> -       parse_metadata(dict, &metadata, func);
> +       parse_metadata(dict, &metadata, func, NULL);
>
>         dbus_message_iter_close_container(&value, &metadata);
>         dbus_message_iter_close_container(iter, &value);
> @@ -1223,7 +1243,8 @@ static gboolean parse_path_metadata(DBusMessageIter *iter, const char *key,
>  }
>
>  static int parse_track_entry(DBusMessageIter *entry, const char *key,
> -                                               DBusMessageIter *metadata)
> +                                               DBusMessageIter *metadata,
> +                                               void *userdata)
>  {
>         DBusMessageIter var;
>
> @@ -1253,6 +1274,30 @@ static int parse_track_entry(DBusMessageIter *entry, const char *key,
>         } else if (strcasecmp(key, "Item") == 0) {
>                 if (!parse_path_metadata(&var, "mpris:trackid", metadata))
>                         return -EINVAL;
> +       } else if (strcasecmp(key, "ImgHandle") == 0) {
> +               struct player *player = userdata;
> +               const char *handle, *path;
> +               char *filename, *uri;
> +
> +               if (!player || !player->obex)
> +                       return -EINVAL;
> +
> +               path = g_dbus_proxy_get_path(player->obex->obex);
> +
> +               if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
> +                       return -EINVAL;
> +               dbus_message_iter_get_basic(&var, &handle);
> +
> +               filename = g_strconcat(g_get_tmp_dir(), "/",
> +                               path + strlen(BLUEZ_OBEX_CLIENT_PATH "/"),
> +                               "-", handle, NULL);
> +               if (access(filename, F_OK) == 0) {
> +                       uri = g_strconcat("file://", filename, NULL);
> +                       dict_append_entry(metadata, "mpris:artUrl",
> +                                               DBUS_TYPE_STRING, &uri);
> +                       g_free(uri);
> +               }
> +               g_free(filename);
>         }
>
>         return 0;
> @@ -1272,7 +1317,7 @@ static gboolean get_track(const GDBusPropertyTable *property,
>                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
>                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata);
>
> -       parse_metadata(&var, &metadata, parse_track_entry);
> +       parse_metadata(&var, &metadata, parse_track_entry, player);
>
>         dbus_message_iter_close_container(iter, &metadata);
>
> @@ -1443,7 +1488,7 @@ static void append_item_metadata(void *data, void *user_data)
>                                                                         &path);
>
>         if (g_dbus_proxy_get_property(item, "Metadata", &var))
> -               parse_metadata(&var, &metadata, parse_track_entry);
> +               parse_metadata(&var, &metadata, parse_track_entry, NULL);
>
>         dbus_message_iter_close_container(iter, &metadata);
>
> @@ -1938,11 +1983,72 @@ static void register_tracklist(GDBusProxy *proxy)
>                                 player, NULL);
>  }
>
> +static GDBusProxy *connect_obex_session(const char *address, uint16_t port)
> +{
> +       static const char *target_str = "bip-avrcp";
> +       DBusMessage *msg, *reply;
> +       DBusMessageIter iter, array;
> +       const char *path;
> +       DBusError err;
> +
> +       msg = dbus_message_new_method_call(BLUEZ_OBEX_BUS_NAME,
> +                                       BLUEZ_OBEX_PATH,
> +                                       BLUEZ_OBEX_CLIENT_INTERFACE,
> +                                       "CreateSession");
> +       dbus_message_iter_init_append(msg, &iter);
> +       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &address);
> +       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
> +                                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
> +                                       DBUS_TYPE_STRING_AS_STRING
> +                                       DBUS_TYPE_VARIANT_AS_STRING
> +                                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
> +                                       &array);
> +       dict_append_entry(&array, "Target", DBUS_TYPE_STRING, &target_str);
> +       dict_append_entry(&array, "PSM", DBUS_TYPE_UINT16, &port);
> +       dbus_message_iter_close_container(&iter, &array);
> +
> +       dbus_error_init(&err);
> +       reply = dbus_connection_send_with_reply_and_block(session, msg, -1,
> +                                                               &err);
> +       dbus_message_unref(msg);
> +       if (!reply) {
> +               if (dbus_error_is_set(&err)) {
> +                       fprintf(stderr, "%s\n", err.message);
> +                       dbus_error_free(&err);
> +               }
> +               return NULL;
> +       }
> +
> +       if (!dbus_message_get_args(reply, NULL,
> +                                       DBUS_TYPE_OBJECT_PATH, &path,
> +                                       DBUS_TYPE_INVALID)) {
> +               dbus_message_unref(reply);
> +               return NULL;
> +       }
> +
> +       return g_dbus_proxy_new(obex_client, path, BLUEZ_OBEX_IMAGE_INTERFACE);
> +}
> +
> +static struct obex_session *find_obex_session_by_device(const char *device)
> +{
> +       GSList *l;
> +
> +       for (l = obex_sessions; l; l = l->next) {
> +               struct obex_session *session = l->data;
> +               const char *path = g_dbus_proxy_get_path(session->device);
> +
> +               if (g_strcmp0(device, path) == 0)
> +                       return session;
> +       }
> +
> +       return NULL;
> +}
> +
>  static void register_player(GDBusProxy *proxy)
>  {
>         struct player *player;
>         DBusMessageIter iter;
> -       const char *path, *alias, *name;
> +       const char *path, *alias, *name, *address;
>         char *busname;
>         GDBusProxy *device, *transport;
>
> @@ -1960,6 +2066,11 @@ static void register_player(GDBusProxy *proxy)
>
>         dbus_message_iter_get_basic(&iter, &alias);
>
> +       if (!g_dbus_proxy_get_property(device, "Address", &iter))
> +               return;
> +
> +       dbus_message_iter_get_basic(&iter, &address);
> +
>         if (g_dbus_proxy_get_property(proxy, "Name", &iter)) {
>                 dbus_message_iter_get_basic(&iter, &name);
>                 busname = g_strconcat(alias, " ", name, NULL);
> @@ -1971,6 +2082,27 @@ static void register_player(GDBusProxy *proxy)
>         player->proxy = g_dbus_proxy_ref(proxy);
>         player->device = device;
>
> +       if (g_dbus_proxy_get_property(proxy, "ObexPort", &iter)) {
> +               uint16_t port;
> +               struct obex_session *session;
> +
> +               dbus_message_iter_get_basic(&iter, &port);
> +
> +               session = find_obex_session_by_device(path);
> +               if (session == NULL || session->port != port) {
> +                       printf("Create new session\n");
> +                       session = g_new0(struct obex_session, 1);
> +                       session->obex = connect_obex_session(address, port);
> +                       session->device = g_dbus_proxy_ref(device);
> +                       session->port = port;
> +
> +                       obex_sessions = g_slist_prepend(obex_sessions, session);
> +               }
> +               player->obex = session;
> +       } else {
> +               player->obex = NULL;
> +       }
> +
>         g_free(busname);
>
>         players = g_slist_prepend(players, player);
> @@ -2177,7 +2309,7 @@ static void register_item(struct player *player, GDBusProxy *proxy)
>                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
>                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &metadata);
>
> -       parse_metadata(&iter, &metadata, parse_track_entry);
> +       parse_metadata(&iter, &metadata, parse_track_entry, player);
>
>         dbus_message_iter_close_container(&args, &metadata);
>
> @@ -2377,6 +2509,121 @@ static const char *property_to_mpris(const char *property)
>         return NULL;
>  }
>
> +static const char *obex_get_image_handle(DBusMessageIter *args)
> +{
> +       DBusMessageIter dict, var;
> +       int ctype;
> +
> +       ctype = dbus_message_iter_get_arg_type(args);
> +       if (ctype != DBUS_TYPE_ARRAY)
> +               return NULL;
> +
> +       dbus_message_iter_recurse(args, &dict);
> +
> +       while ((ctype = dbus_message_iter_get_arg_type(&dict)) !=
> +                                                       DBUS_TYPE_INVALID) {
> +               DBusMessageIter entry;
> +               const char *key;
> +
> +               if (ctype != DBUS_TYPE_DICT_ENTRY)
> +                       return NULL;
> +
> +               dbus_message_iter_recurse(&dict, &entry);
> +               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
> +                       return NULL;
> +
> +               dbus_message_iter_get_basic(&entry, &key);
> +               dbus_message_iter_next(&entry);
> +
> +               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
> +                       return NULL;
> +
> +               dbus_message_iter_recurse(&entry, &var);
> +
> +               if (strcasecmp(key, "ImgHandle") == 0) {
> +                       const char *handle;
> +
> +                       dbus_message_iter_get_basic(&var, &handle);
> +                       return handle;
> +               }
> +
> +               dbus_message_iter_next(&dict);
> +       }
> +
> +       return NULL;
> +}
> +
> +static void obex_get_image(struct player *player, const char *handle)
> +{
> +       DBusMessage *msg;
> +       DBusMessageIter iter, array;
> +       struct obex_session *obex_session = player->obex;
> +       const char *path = g_dbus_proxy_get_path(obex_session->obex);
> +       char *filename;
> +
> +       player->filename = g_strconcat(g_get_tmp_dir(), "/",
> +                               path + strlen(BLUEZ_OBEX_CLIENT_PATH "/"),
> +                               "-", handle, NULL);
> +       filename = g_strconcat(player->filename, ".tmp", NULL);
> +
> +       msg = dbus_message_new_method_call(BLUEZ_OBEX_BUS_NAME,
> +                                       path,
> +                                       BLUEZ_OBEX_IMAGE_INTERFACE,
> +                                       "Get");
> +       dbus_message_iter_init_append(msg, &iter);
> +       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &filename);
> +       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &handle);
> +       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
> +                                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
> +                                       DBUS_TYPE_STRING_AS_STRING
> +                                       DBUS_TYPE_VARIANT_AS_STRING
> +                                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
> +                                       &array);
> +       dbus_message_iter_close_container(&iter, &array);
> +
> +       if (!g_dbus_send_message(session, msg)) {
> +               g_free(player->filename);
> +               player->filename = NULL;
> +       }
> +       g_free(filename);
> +}
> +
> +static void device_property_changed(GDBusProxy *proxy, const char *name,
> +                                       DBusMessageIter *iter, void *user_data)
> +{
> +       const char *path;
> +       struct obex_session *session;
> +       gboolean connected;
> +       GSList *l;
> +
> +       path = g_dbus_proxy_get_path(proxy);
> +
> +       if (strcasecmp(name, "Connected") != 0)
> +               return;
> +
> +       dbus_message_iter_get_basic(iter, &connected);
> +
> +       if (connected)
> +               return;
> +
> +       printf("Bluetooth Device %s disconnected\n", path);
> +       session = find_obex_session_by_device(path);
> +       if (session == NULL)
> +               return;
> +
> +       for (l = players; l; l = l->next) {
> +               struct player *player = l->data;
> +
> +               if (player->obex == session)
> +                       player->obex = NULL;
> +       }
> +
> +       g_dbus_proxy_unref(session->obex);
> +       g_dbus_proxy_unref(session->device);
> +       obex_sessions = g_slist_remove(obex_sessions, session);
> +       g_free(session);
> +}
> +
>  static void player_property_changed(GDBusProxy *proxy, const char *name,
>                                         DBusMessageIter *iter, void *user_data)
>  {
> @@ -2397,6 +2644,13 @@ static void player_property_changed(GDBusProxy *proxy, const char *name,
>                                                 MPRIS_PLAYER_INTERFACE,
>                                                 property);
>
> +       if (strcasecmp(name, "Track") == 0 && player->obex) {
> +               const char *handle = obex_get_image_handle(iter);
> +
> +               if (handle)
> +                       obex_get_image(player, handle);
> +       }
> +
>         if (strcasecmp(name, "Position") != 0)
>                 return;
>
> @@ -2485,6 +2739,9 @@ static void property_changed(GDBusProxy *proxy, const char *name,
>
>         interface = g_dbus_proxy_get_interface(proxy);
>
> +       if (strcmp(interface, BLUEZ_DEVICE_INTERFACE) == 0)
> +               return device_property_changed(proxy, name, iter, user_data);
> +
>         if (strcmp(interface, BLUEZ_MEDIA_PLAYER_INTERFACE) == 0)
>                 return player_property_changed(proxy, name, iter, user_data);
>
> @@ -2496,6 +2753,151 @@ static void property_changed(GDBusProxy *proxy, const char *name,
>                 return item_property_changed(proxy, name, iter, user_data);
>  }
>
> +static struct player *find_player_by_obex(const char *path)
> +{
> +       GSList *l;
> +
> +       for (l = players; l; l = l->next) {
> +               struct player *player = l->data;
> +               struct obex_session *session = player->obex;
> +               const char *obex_path = g_dbus_proxy_get_path(session->obex);
> +
> +               if (g_str_has_prefix(path, obex_path))
> +                       return player;
> +       }
> +
> +       return NULL;
> +}
> +
> +static void obex_connect_handler(DBusConnection *connection, void *user_data)
> +{
> +       printf("org.bluez.obex appeared\n");
> +}
> +
> +static void obex_disconnect_handler(DBusConnection *connection,
> +                                       void *user_data)
> +{
> +       printf("org.bluez.obex disappeared\n");
> +}
> +
> +static void obex_proxy_added(GDBusProxy *proxy, void *user_data)
> +{
> +       const char *interface;
> +       const char *path;
> +
> +       interface = g_dbus_proxy_get_interface(proxy);
> +       path = g_dbus_proxy_get_path(proxy);
> +
> +       if (!strcmp(interface, BLUEZ_OBEX_CLIENT_INTERFACE)) {
> +               GSList *l;
> +
> +               printf("Bluetooth Obex Client %s found\n", path);
> +
> +               for (l = players; l; l = l->next) {
> +                       struct player *player = l->data;
> +                       DBusMessageIter iter;
> +                       const char *address;
> +                       uint16_t port;
> +                       struct obex_session *session;
> +
> +                       if (!g_dbus_proxy_get_property(player->proxy,
> +                                       "ObexPort", &iter) ||
> +                                       player->obex)
> +                               continue;
> +
> +                       dbus_message_iter_get_basic(&iter, &port);
> +
> +                       if (!g_dbus_proxy_get_property(player->device,
> +                                       "Address", &iter))
> +                               continue;
> +
> +                       dbus_message_iter_get_basic(&iter, &address);
> +
> +                       session = find_obex_session_by_device(path);
> +                       if (session == NULL || session->port != port) {
> +                               printf("Bluetooth Obex Create new session\n");
> +                               session = g_new0(struct obex_session, 1);
> +                               session->obex = connect_obex_session(address,
> +                                                                       port);
> +                               session->device = g_dbus_proxy_ref(
> +                                                       player->device);
> +                               session->port = port;
> +
> +                               obex_sessions = g_slist_prepend(obex_sessions,
> +                                                               session);
> +                       }
> +                       player->obex = session;
> +               }
> +       }
> +}
> +
> +static void obex_proxy_removed(GDBusProxy *proxy, void *user_data)
> +{
> +       const char *interface;
> +       const char *path;
> +
> +       if (adapter == NULL)
> +               return;
> +
> +       interface = g_dbus_proxy_get_interface(proxy);
> +       path = g_dbus_proxy_get_path(proxy);
> +
> +       if (strcmp(interface, BLUEZ_OBEX_CLIENT_INTERFACE) == 0) {
> +               GSList *l;
> +
> +               printf("Bluetooth Obex Client %s removed\n", path);
> +
> +               for (l = players; l; l = l->next) {
> +                       struct player *player = l->data;
> +
> +                       player->obex = NULL;
> +               }
> +
> +               while (obex_sessions) {
> +                       struct obex_session *session = obex_sessions->data;
> +
> +                       g_dbus_proxy_unref(session->device);
> +                       g_dbus_proxy_unref(session->obex);
> +                       obex_sessions = g_slist_remove(obex_sessions, session);
> +               }
> +       }
> +}
> +
> +static void obex_property_changed(GDBusProxy *proxy, const char *name,
> +                                       DBusMessageIter *iter, void *user_data)
> +{
> +       const char *interface;
> +       const char *path;
> +
> +       interface = g_dbus_proxy_get_interface(proxy);
> +       path = g_dbus_proxy_get_path(proxy);
> +
> +       if (strcmp(interface, BLUEZ_OBEX_TRANSFER_INTERFACE) == 0) {
> +               struct player *player;
> +               const char *status;
> +
> +               if (strcasecmp(name, "Status") != 0)
> +                       return;
> +
> +               dbus_message_iter_get_basic(iter, &status);
> +
> +               player = find_player_by_obex(path);
> +               if (player && strcasecmp(status, "complete") == 0) {
> +                       char *filename;
> +
> +                       filename = g_strconcat(player->filename, ".tmp", NULL);
> +                       rename(filename, player->filename);
> +                       g_free(player->filename);
> +                       player->filename = NULL;
> +
> +                       g_dbus_emit_property_changed(player->conn,
> +                                                       MPRIS_PLAYER_PATH,
> +                                                       MPRIS_PLAYER_INTERFACE,
> +                                                       "Metadata");
> +               }
> +       }
> +}
> +
>  int main(int argc, char *argv[])
>  {
>         GOptionContext *context;
> @@ -2566,6 +2968,19 @@ int main(int argc, char *argv[])
>         g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
>                                                 property_changed, NULL);
>
> +       obex_client = g_dbus_client_new(session, BLUEZ_OBEX_BUS_NAME,
> +                                       BLUEZ_OBEX_PATH);
> +
> +       g_dbus_client_set_connect_watch(obex_client, obex_connect_handler,
> +                                       NULL);
> +       g_dbus_client_set_disconnect_watch(obex_client,
> +                                               obex_disconnect_handler,
> +                                               NULL);
> +
> +       g_dbus_client_set_proxy_handlers(obex_client, obex_proxy_added,
> +                                               obex_proxy_removed,
> +                                               obex_property_changed, NULL);
> +
>         g_main_loop_run(main_loop);
>
>         g_dbus_remove_watch(session, owner_watch);
> --
> 2.43.0
>
>


-- 
Luiz Augusto von Dentz





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux