Re: [PATCH BlueZ v2 4/7] obexd: Add BIP client for AVRCP cover art download.

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

 



Hi Frédéric,

On Thu, Sep 12, 2024 at 1:50 PM Frédéric Danis
<frederic.danis@xxxxxxxxxxxxx> wrote:
>
> The cover art image handle is available in the metadata of the track
> when the OBEX BIP session is connected to the PSM port provided
> in AVRCP SDP record and available as org.bluez.MediaPlayer property.
>
> This service allows to get the thumbnail.
> ---
>  Makefile.obexd           |   1 +
>  obexd/client/bip-avrcp.c | 171 +++++++++++++++++++++++++++++++++++++++
>  obexd/client/bip-avrcp.h |  12 +++

Id got with bit.{c,h} so we can reuse the implementation for BIP.

>  obexd/client/manager.c   |   2 +
>  obexd/client/transfer.c  |  16 ++++
>  obexd/client/transfer.h  |   2 +
>  6 files changed, 204 insertions(+)
>  create mode 100644 obexd/client/bip-avrcp.c
>  create mode 100644 obexd/client/bip-avrcp.h
>
> diff --git a/Makefile.obexd b/Makefile.obexd
> index 4cdce73af..8038d2327 100644
> --- a/Makefile.obexd
> +++ b/Makefile.obexd
> @@ -81,6 +81,7 @@ obexd_src_obexd_SOURCES = $(btio_sources) $(gobex_sources) \
>                         obexd/client/ftp.h obexd/client/ftp.c \
>                         obexd/client/opp.h obexd/client/opp.c \
>                         obexd/client/map.h obexd/client/map.c \
> +                       obexd/client/bip-avrcp.h obexd/client/bip-avrcp.c \
>                         obexd/client/map-event.h obexd/client/map-event.c \
>                         obexd/client/transfer.h obexd/client/transfer.c \
>                         obexd/client/transport.h obexd/client/transport.c \
> diff --git a/obexd/client/bip-avrcp.c b/obexd/client/bip-avrcp.c
> new file mode 100644
> index 000000000..ca702be5a
> --- /dev/null
> +++ b/obexd/client/bip-avrcp.c
> @@ -0,0 +1,171 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + *
> + *  OBEX Client
> + *
> + *  Copyright (C) 2024  Collabora Ltd.
> + *
> + *
> + */
> +
> +#define _GNU_SOURCE
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include "gdbus/gdbus.h"
> +#include "gobex/gobex.h"
> +
> +#include "obexd/src/log.h"
> +#include "transfer.h"
> +#include "session.h"
> +#include "driver.h"
> +#include "bip-avrcp.h"
> +
> +#define OBEX_BIP_AVRCP_UUID \
> +       "\x71\x63\xDD\x54\x4A\x7E\x11\xE2\xB4\x7C\x00\x50\xC2\x49\x00\x48"
> +#define OBEX_BIP_AVRCP_UUID_LEN 16
> +
> +#define BIP_AVRCP_INTERFACE "org.bluez.obex.BipAvrcp1"
> +#define ERROR_INTERFACE "org.bluez.obex.Error"
> +#define BIP_AVRCP_UUID "0000111A-0000-1000-8000-00805f9b34fb"
> +
> +#define IMG_HANDLE_TAG  0x30
> +
> +static DBusConnection *conn;
> +
> +struct bip_avrcp_data {
> +       struct obc_session *session;
> +};
> +
> +static DBusMessage *get_image_thumbnail(DBusConnection *connection,
> +                                       DBusMessage *message, void *user_data)
> +{
> +       struct bip_avrcp_data *bip_avrcp = user_data;
> +       const char *handle = NULL, *image_path = NULL;
> +       struct obc_transfer *transfer;
> +       GObexHeader *header;
> +       DBusMessage *reply = NULL;
> +       GError *err = NULL;
> +
> +       DBG("");
> +
> +       if (dbus_message_get_args(message, NULL,
> +                               DBUS_TYPE_STRING, &image_path,
> +                               DBUS_TYPE_STRING, &handle,
> +                               DBUS_TYPE_INVALID) == FALSE) {
> +               reply = g_dbus_create_error(message,
> +                               ERROR_INTERFACE ".InvalidArguments", NULL);
> +               goto fail;
> +       }
> +
> +       transfer = obc_transfer_get("x-bt/img-thm", NULL, image_path, &err);
> +       if (transfer == NULL)
> +               goto fail;
> +
> +       header = g_obex_header_new_unicode(IMG_HANDLE_TAG, handle);
> +       obc_transfer_add_header(transfer, header);
> +
> +       if (!obc_session_queue(bip_avrcp->session, transfer, NULL, NULL, &err))
> +               goto fail;
> +
> +       return obc_transfer_create_dbus_reply(transfer, message);
> +
> +fail:
> +       reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s",
> +                                                               err->message);
> +       g_error_free(err);
> +       return reply;
> +}
> +
> +static const GDBusMethodTable bip_avrcp_methods[] = {
> +       { GDBUS_ASYNC_METHOD("GetImageThumbnail",
> +               GDBUS_ARGS({ "file", "s" }, { "handle", "s"}),
> +               GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }),
> +               get_image_thumbnail) },
> +       { }
> +};
> +
> +static void bip_avrcp_free(void *data)
> +{
> +       struct bip_avrcp_data *bip_avrcp = data;
> +
> +       obc_session_unref(bip_avrcp->session);
> +       g_free(bip_avrcp);
> +}
> +
> +static int bip_avrcp_probe(struct obc_session *session)
> +{
> +       struct bip_avrcp_data *bip_avrcp;
> +       const char *path;
> +
> +       path = obc_session_get_path(session);
> +
> +       DBG("%s", path);
> +
> +       bip_avrcp = g_try_new0(struct bip_avrcp_data, 1);
> +       if (!bip_avrcp)
> +               return -ENOMEM;
> +
> +       bip_avrcp->session = obc_session_ref(session);
> +
> +       if (!g_dbus_register_interface(conn, path, BIP_AVRCP_INTERFACE,
> +                                       bip_avrcp_methods,
> +                                       NULL, NULL,
> +                                       bip_avrcp, bip_avrcp_free)) {
> +               bip_avrcp_free(bip_avrcp);
> +               return -ENOMEM;
> +       }
> +
> +       return 0;
> +}
> +
> +static void bip_avrcp_remove(struct obc_session *session)
> +{
> +       const char *path = obc_session_get_path(session);
> +
> +       DBG("%s", path);
> +
> +       g_dbus_unregister_interface(conn, path, BIP_AVRCP_INTERFACE);
> +}
> +
> +static struct obc_driver bip_avrcp = {
> +       .service = "BIP-AVRCP",
> +       .uuid = BIP_AVRCP_UUID,
> +       .target = OBEX_BIP_AVRCP_UUID,
> +       .target_len = OBEX_BIP_AVRCP_UUID_LEN,
> +       .probe = bip_avrcp_probe,
> +       .remove = bip_avrcp_remove
> +};

This can stay as bip_arvcp, since obc_driver is per-uuid, but in the
future if someone wants to add BIP uuid it just registers another
driver.

> +int bip_avrcp_init(void)
> +{
> +       int err;
> +
> +       DBG("");
> +
> +       conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
> +       if (!conn)
> +               return -EIO;
> +
> +       err = obc_driver_register(&bip_avrcp);
> +       if (err < 0)
> +               goto failed;
> +
> +       return 0;
> +
> +failed:
> +       dbus_connection_unref(conn);
> +       conn = NULL;
> +       return err;
> +}
> +
> +void bip_avrcp_exit(void)
> +{
> +       DBG("");
> +
> +       dbus_connection_unref(conn);
> +       conn = NULL;
> +
> +       obc_driver_unregister(&bip_avrcp);
> +}
> diff --git a/obexd/client/bip-avrcp.h b/obexd/client/bip-avrcp.h
> new file mode 100644
> index 000000000..acd8068f2
> --- /dev/null
> +++ b/obexd/client/bip-avrcp.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + *
> + *  OBEX Client
> + *
> + *  Copyright (C) 2024  Collabora Ltd.
> + *
> + *
> + */
> +
> +int bip_avrcp_init(void);
> +void bip_avrcp_exit(void);
> diff --git a/obexd/client/manager.c b/obexd/client/manager.c
> index 52c00fb0c..5078f56da 100644
> --- a/obexd/client/manager.c
> +++ b/obexd/client/manager.c
> @@ -32,6 +32,7 @@
>  #include "pbap.h"
>  #include "sync.h"
>  #include "map.h"
> +#include "bip-avrcp.h"
>  #include "manager.h"
>
>  #define CLIENT_INTERFACE       "org.bluez.obex.Client1"
> @@ -258,6 +259,7 @@ static const struct obc_module {
>         { "pbap", pbap_init, pbap_exit },
>         { "sync", sync_init, sync_exit },
>         { "map", map_init, map_exit },
> +       { "bip-avrcp", bip_avrcp_init, bip_avrcp_exit },

For the module it shall be just bip, avrcp specific UUID is handled by
a dedicated driver.

>         { }
>  };
>
> diff --git a/obexd/client/transfer.c b/obexd/client/transfer.c
> index a7a85a0c0..fdf32a985 100644
> --- a/obexd/client/transfer.c
> +++ b/obexd/client/transfer.c
> @@ -57,6 +57,7 @@ struct obc_transfer {
>         GObex *obex;
>         uint8_t status;
>         GObexApparam *apparam;
> +       GSList *headers;
>         guint8 op;
>         struct transfer_callback *callback;
>         DBusConnection *conn;
> @@ -820,6 +821,16 @@ static gboolean transfer_start_get(struct obc_transfer *transfer, GError **err)
>                 g_obex_packet_add_bytes(req, G_OBEX_HDR_TYPE, transfer->type,
>                                                 strlen(transfer->type) + 1);
>
> +       if (transfer->headers != NULL) {
> +               GSList *l;
> +
> +               for (l = transfer->headers; l != NULL; l = g_slist_next(l)) {
> +                       GObexHeader *hdr = l->data;
> +
> +                       g_obex_packet_add_header(req, hdr);
> +               }
> +       }

This one seems to be a different change, so Id put it in a different patch.

> +
>         if (transfer->apparam != NULL) {
>                 hdr = g_obex_header_new_apparam(transfer->apparam);
>                 g_obex_packet_add_header(req, hdr);
> @@ -974,3 +985,8 @@ gint64 obc_transfer_get_size(struct obc_transfer *transfer)
>  {
>         return transfer->size;
>  }
> +
> +void obc_transfer_add_header(struct obc_transfer *transfer, void *data)
> +{
> +       transfer->headers = g_slist_append(transfer->headers, data);
> +}
> diff --git a/obexd/client/transfer.h b/obexd/client/transfer.h
> index 323332a62..1ed195984 100644
> --- a/obexd/client/transfer.h
> +++ b/obexd/client/transfer.h
> @@ -47,3 +47,5 @@ gint64 obc_transfer_get_size(struct obc_transfer *transfer);
>
>  DBusMessage *obc_transfer_create_dbus_reply(struct obc_transfer *transfer,
>                                                         DBusMessage *message);
> +
> +void obc_transfer_add_header(struct obc_transfer *transfer, void *data);
> --
> 2.34.1
>
>


-- 
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