Re: [PATCH BlueZ v2 6/7] obexd: Add GetImage to bip-avrcp

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

 



Hi Frédéric,

On Thu, Sep 12, 2024 at 1:51 PM Frédéric Danis
<frederic.danis@xxxxxxxxxxxxx> wrote:
>
> Retrieves the image corresponding to the handle and the description,
> as one of the descriptions retrieved by GetImageProperties, and store
> it in a local file.
>
> If the "transform" property description exists it should be set
> to one of the value listed by GetImageProperties for this
> description.
> ---
>  obexd/client/bip-avrcp.c  | 155 ++++++++++++++++++++++++++++++++++++++
>  obexd/client/bip-common.c |  21 +++++-
>  obexd/client/bip-common.h |   5 ++
>  profiles/audio/avrcp.c    |  10 ++-
>  4 files changed, 186 insertions(+), 5 deletions(-)
>
> diff --git a/obexd/client/bip-avrcp.c b/obexd/client/bip-avrcp.c
> index 272a288b4..8f00ddf8d 100644
> --- a/obexd/client/bip-avrcp.c
> +++ b/obexd/client/bip-avrcp.c
> @@ -32,6 +32,14 @@
>  #define BIP_AVRCP_UUID "0000111A-0000-1000-8000-00805f9b34fb"
>
>  #define IMG_HANDLE_TAG  0x30
> +#define IMG_DESC_TAG    0x71
> +
> +#define EOL_CHARS "\n"
> +#define IMG_DESC_BEGIN "<image-descriptor version=\"1.0\">" EOL_CHARS
> +#define IMG_BEGIN "<image encoding=\"%s\" pixel=\"%s\""
> +#define IMG_TRANSFORM " transformation=\"%s\""
> +#define IMG_END "/>" EOL_CHARS
> +#define IMG_DESC_END "</image-descriptor>" EOL_CHARS
>
>  static DBusConnection *conn;
>
> @@ -175,11 +183,158 @@ fail:
>         return reply;
>  }
>
> +static gboolean parse_get_image_dict(DBusMessage *msg, char **path,
> +                                       char **handle, char **pixel,
> +                                       char **encoding, uint64_t *maxsize,
> +                                                       char **transform)
> +{
> +       DBusMessageIter iter, array;
> +
> +       DBG("");
> +
> +       *path = NULL;
> +       *handle = NULL;
> +       *pixel = NULL;
> +       *encoding = NULL;
> +       *transform = NULL;
> +
> +       dbus_message_iter_init(msg, &iter);
> +
> +       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
> +               goto failed;
> +       dbus_message_iter_get_basic(&iter, path);
> +       *path = g_strdup(*path);
> +       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
> +               goto failed;
> +       dbus_message_iter_next(&iter);
> +       dbus_message_iter_get_basic(&iter, handle);
> +       *handle = g_strdup(*handle);
> +       dbus_message_iter_next(&iter);
> +       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
> +               goto failed;
> +
> +       dbus_message_iter_recurse(&iter, &array);
> +
> +       while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
> +               DBusMessageIter entry, value;
> +               const char *key, *val;
> +
> +               dbus_message_iter_recurse(&array, &entry);
> +
> +               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
> +                       return FALSE;
> +               dbus_message_iter_get_basic(&entry, &key);
> +               dbus_message_iter_next(&entry);
> +               dbus_message_iter_recurse(&entry, &value);
> +               switch (dbus_message_iter_get_arg_type(&value)) {
> +               case DBUS_TYPE_STRING:
> +                       dbus_message_iter_get_basic(&value, &val);
> +                       if (g_str_equal(key, "pixel")) {
> +                               if (!parse_pixel_range(val, NULL, NULL, NULL))
> +                                       goto failed;
> +                               *pixel = g_strdup(val);
> +                       } else if (g_str_equal(key, "encoding")) {
> +                               if (!verify_encoding(val))
> +                                       goto failed;
> +                               *encoding = g_strdup(val);
> +                               if (*encoding == NULL)
> +                                       goto failed;
> +                       } else if (g_str_equal(key, "transformation")) {
> +                               *transform = parse_transform(val);
> +                               if (*transform == NULL)
> +                                       goto failed;
> +                       }
> +                       break;
> +               case DBUS_TYPE_UINT64:
> +                       if (g_str_equal(key, "maxsize") == TRUE) {
> +                               dbus_message_iter_get_basic(&value, maxsize);
> +                               if (*maxsize == 0)
> +                                       goto failed;
> +                       }
> +                       break;
> +               }
> +               dbus_message_iter_next(&array);
> +       }
> +
> +       if (*pixel == NULL)
> +               *pixel = strdup("");
> +       if (*encoding == NULL)
> +               *encoding = strdup("");
> +
> +       DBG("pixel: '%s' encoding: '%s' maxsize: '%lu' transform: '%s'",
> +                       *pixel, *encoding, *maxsize, *transform
> +       );
> +
> +       return TRUE;
> +failed:
> +       g_free(*path);
> +       g_free(*handle);
> +       g_free(*pixel);
> +       g_free(*encoding);
> +       g_free(*transform);
> +       return FALSE;
> +}
> +
> +static DBusMessage *get_image(DBusConnection *connection,
> +                                       DBusMessage *message, void *user_data)
> +{
> +       struct bip_avrcp_data *bip_avrcp = user_data;
> +       char *handle = NULL, *image_path = NULL, *transform = NULL,
> +               *encoding = NULL, *pixel = NULL;
> +       uint64_t maxsize;
> +       struct obc_transfer *transfer;
> +       GObexHeader *header;
> +       DBusMessage *reply = NULL;
> +       GString *descriptor = NULL;
> +       GError *err = NULL;
> +
> +       DBG("");
> +
> +       if (!parse_get_image_dict(message, &image_path, &handle, &pixel,
> +                                       &encoding, &maxsize, &transform))
> +               return g_dbus_create_error(message,
> +                               ERROR_INTERFACE ".InvalidArguments", NULL);
> +
> +       transfer = obc_transfer_get("x-bt/img-img", 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);
> +
> +       descriptor = g_string_new(IMG_DESC_BEGIN);
> +       g_string_append_printf(descriptor, IMG_BEGIN, encoding, pixel);
> +       if (transform != NULL)
> +               g_string_append_printf(descriptor, IMG_TRANSFORM, transform);
> +       g_string_append(descriptor, IMG_END);
> +       descriptor = g_string_append(descriptor, IMG_DESC_END);
> +       header = g_obex_header_new_bytes(IMG_DESC_TAG, descriptor->str,
> +                                               descriptor->len);
> +       obc_transfer_add_header(transfer, header);
> +       g_string_free(descriptor, TRUE);
> +
> +       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("GetImageProperties",
>                 GDBUS_ARGS({ "handle", "s"}),
>                 GDBUS_ARGS({ "properties", "aa{sv}" }),
>                 get_image_properties) },
> +       { GDBUS_ASYNC_METHOD("GetImage",
> +               GDBUS_ARGS({ "file", "s" }, { "handle", "s"},
> +                               {"properties", "a{sv}"}),
> +               GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }),
> +               get_image) },
>         { GDBUS_ASYNC_METHOD("GetImageThumbnail",
>                 GDBUS_ARGS({ "file", "s" }, { "handle", "s"}),
>                 GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }),
> diff --git a/obexd/client/bip-common.c b/obexd/client/bip-common.c
> index b93921df5..16a199977 100644
> --- a/obexd/client/bip-common.c
> +++ b/obexd/client/bip-common.c
> @@ -49,7 +49,7 @@ static const gchar *convBIP2IM(const gchar *encoding)
>         return NULL;
>  }
>
> -static gboolean parse_pixel_range(const gchar *dim, unsigned int *lower_ret,
> +gboolean parse_pixel_range(const gchar *dim, unsigned int *lower_ret,
>                                                 unsigned int *upper_ret,
>                                                 gboolean *fixed_ratio_ret)
>  {
> @@ -139,6 +139,18 @@ char *transforms[] = {
>         NULL
>  };
>
> +gboolean verify_encoding(const char *encoding)
> +{
> +       struct encconv_pair *et = encconv_table;
> +
> +       while (et->bip) {
> +               if (g_strcmp0(encoding, et->bip) == 0)
> +                       return TRUE;
> +               et++;
> +       }
> +       return FALSE;
> +}
> +
>  static gboolean verify_transform(const char *transform)
>  {
>         char **str = transforms;
> @@ -151,6 +163,13 @@ static gboolean verify_transform(const char *transform)
>         return FALSE;
>  }
>
> +char *parse_transform(const char *transform)
> +{
> +       if (!verify_transform(transform))
> +               return NULL;
> +       return g_strdup(transform);
> +}
> +
>  static char *parse_transform_list(const char *transform)
>  {
>         char **args = NULL, **arg = NULL;
> diff --git a/obexd/client/bip-common.h b/obexd/client/bip-common.h
> index 0fee54636..6e7aac375 100644
> --- a/obexd/client/bip-common.h
> +++ b/obexd/client/bip-common.h
> @@ -13,6 +13,11 @@
>
>  struct prop_object;
>
> +gboolean parse_pixel_range(const gchar *dim, unsigned int *lower_ret,
> +                                               unsigned int *upper_ret,
> +                                               gboolean *fixed_ratio_ret);
> +gboolean verify_encoding(const char *encoding);
> +char *parse_transform(const char *transform);
>  struct prop_object *parse_properties(char *data, unsigned int length,
>                                                         int *err);
>  gboolean verify_properties(struct prop_object *obj);
> diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
> index fe24b5a92..ee750f50b 100644
> --- a/profiles/audio/avrcp.c
> +++ b/profiles/audio/avrcp.c
> @@ -415,10 +415,12 @@ static sdp_record_t *avrcp_ct_record(bool browsing)
>         uint16_t lp = AVCTP_CONTROL_PSM;
>         uint16_t avctp_ver = 0x0103;
>         uint16_t feat = ( AVRCP_FEATURE_CATEGORY_1 |
> -                                               AVRCP_FEATURE_CATEGORY_2 |
> -                                               AVRCP_FEATURE_CATEGORY_3 |
> -                                               AVRCP_FEATURE_CATEGORY_4 |
> -                                               AVRCP_FEATURE_CT_GET_THUMBNAIL);
> +                                       AVRCP_FEATURE_CATEGORY_2 |
> +                                       AVRCP_FEATURE_CATEGORY_3 |
> +                                       AVRCP_FEATURE_CATEGORY_4 |
> +                                       AVRCP_FEATURE_CT_GET_IMAGE_PROP |
> +                                       AVRCP_FEATURE_CT_GET_IMAGE |
> +                                       AVRCP_FEATURE_CT_GET_THUMBNAIL);

Changes to obexd and avrcp shall probably be split, also make sure the
versioning is proper, if I recall it correctly it was added on AVRCP
1.6 so we need to make sure that it is reflected correctly in the
record.

>         record = sdp_record_alloc();
>         if (!record)
> --
> 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