refactor(examples/classic_bt): Add common code for AVRCP cover art example
This commit is contained in:
+4
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "avrcp_cover_art_utils.c"
|
||||
"avrcp_cover_art_service.c"
|
||||
PRIV_REQUIRES bt esp_lcd avrcp_common_utils
|
||||
INCLUDE_DIRS "." "../include")
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
menu "AVRCP Cover Art Example Configuration"
|
||||
config EXAMPLE_LCD_FLUSH_PARALLEL_LINES
|
||||
int "LCD flush parallel lines"
|
||||
default 16
|
||||
help
|
||||
To speed up transfers, every SPI transfer sends a bunch of lines.
|
||||
|
||||
endmenu
|
||||
+347
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "jpeg_decoder.h"
|
||||
#include "avrcp_common_utils.h"
|
||||
#include "avrcp_cover_art_service.h"
|
||||
|
||||
/* tags*/
|
||||
#define RC_CA_SRV_TAG "RC_CA_SRV"
|
||||
|
||||
//Define the height and width of the jpeg file. Make sure this matches the actual jpeg
|
||||
//dimensions.
|
||||
#define IMAGE_W 200
|
||||
#define IMAGE_H 200
|
||||
|
||||
// Using SPI2 in the example, as it also supports octal modes on some targets
|
||||
#define LCD_HOST SPI2_HOST
|
||||
// To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many.
|
||||
// More means more memory use, but less overhead for setting up / finishing transfers. Make sure 240
|
||||
// is dividable by this.
|
||||
#define PARALLEL_LINES CONFIG_EXAMPLE_LCD_FLUSH_PARALLEL_LINES
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////// Please update the following configuration according to your LCD spec //////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000)
|
||||
#define EXAMPLE_LCD_BK_LIGHT_ON_LEVEL 0
|
||||
#define EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL !EXAMPLE_LCD_BK_LIGHT_ON_LEVEL
|
||||
#define EXAMPLE_PIN_NUM_DATA0 23 /*!< for 1-line SPI, this also referred as MOSI */
|
||||
#define EXAMPLE_PIN_NUM_PCLK 19
|
||||
#define EXAMPLE_PIN_NUM_CS 22
|
||||
#define EXAMPLE_PIN_NUM_DC 21
|
||||
#define EXAMPLE_PIN_NUM_RST 18
|
||||
#define EXAMPLE_PIN_NUM_BK_LIGHT 5
|
||||
|
||||
// The pixel number in horizontal and vertical
|
||||
#define EXAMPLE_LCD_H_RES 200
|
||||
#define EXAMPLE_LCD_V_RES 200
|
||||
// Bit number used to represent command and parameter
|
||||
#define EXAMPLE_LCD_CMD_BITS 8
|
||||
#define EXAMPLE_LCD_PARAM_BITS 8
|
||||
|
||||
/**
|
||||
* @brief AVRCP cover art service control block structure
|
||||
*/
|
||||
typedef struct {
|
||||
bool connected; /* Connection status flag */
|
||||
bool getting; /* Flag indicating if image is being retrieved */
|
||||
/* Related to the image */
|
||||
uint8_t image_hdl_old[7]; /* Previous image handle, used to detect image changes */
|
||||
uint32_t image_size; /* Size of the image data in bytes */
|
||||
uint8_t *image_data; /* Pointer to the image data buffer */
|
||||
bool image_final; /* Indicate whether the image reception has been completed */
|
||||
uint16_t *pixels; /* Pointer to decoded pixel data */
|
||||
esp_lcd_panel_io_handle_t io_handle; /* LCD panel IO handle */
|
||||
esp_lcd_panel_handle_t panel_handle; /* LCD panel handle */
|
||||
} avrc_cover_art_srv_cb_t;
|
||||
|
||||
/*******************************
|
||||
* STATIC FUNCTION DECLARATIONS
|
||||
******************************/
|
||||
|
||||
/* image handle check */
|
||||
static bool avrc_cover_art_srv_image_handle_check(uint8_t *image_handle, int len);
|
||||
/* free image data */
|
||||
static void avrc_cover_art_srv_free_image_data(void);
|
||||
/* initialize display (currently supports LCD only) */
|
||||
static void avrc_cover_art_srv_init_display(void);
|
||||
/* deinitialize display (currently supports LCD only) */
|
||||
static void avrc_cover_art_srv_deinit_display(void);
|
||||
/* free pixels */
|
||||
static void avrc_cover_art_srv_free_pixels(void);
|
||||
/* decode image */
|
||||
static esp_err_t avrc_cover_art_srv_decode_image(void);
|
||||
/* display image */
|
||||
static void avrc_cover_art_srv_display_image(void);
|
||||
|
||||
/*******************************
|
||||
* STATIC VARIABLE DEFINITIONS
|
||||
******************************/
|
||||
|
||||
/* avrcp cover art service control block */
|
||||
static avrc_cover_art_srv_cb_t s_avrc_cover_art_srv_cb;
|
||||
|
||||
/********************************
|
||||
* STATIC FUNCTION DEFINITIONS
|
||||
*******************************/
|
||||
|
||||
static bool avrc_cover_art_srv_image_handle_check(uint8_t *image_handle, int len)
|
||||
{
|
||||
/* Image handle length must be 7 */
|
||||
if (len == 7 && memcmp(s_avrc_cover_art_srv_cb.image_hdl_old, image_handle, 7) != 0) {
|
||||
memcpy(s_avrc_cover_art_srv_cb.image_hdl_old, image_handle, 7);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void avrc_cover_art_srv_free_image_data(void)
|
||||
{
|
||||
if (s_avrc_cover_art_srv_cb.image_data) {
|
||||
free(s_avrc_cover_art_srv_cb.image_data);
|
||||
s_avrc_cover_art_srv_cb.image_data = NULL;
|
||||
}
|
||||
s_avrc_cover_art_srv_cb.image_size = 0;
|
||||
}
|
||||
|
||||
static void avrc_cover_art_srv_init_display(void)
|
||||
{
|
||||
gpio_config_t bk_gpio_config = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT
|
||||
};
|
||||
/* Initialize the GPIO of backlight */
|
||||
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
|
||||
|
||||
spi_bus_config_t buscfg = {
|
||||
.sclk_io_num = EXAMPLE_PIN_NUM_PCLK,
|
||||
.mosi_io_num = EXAMPLE_PIN_NUM_DATA0,
|
||||
.miso_io_num = -1,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = PARALLEL_LINES * EXAMPLE_LCD_H_RES * 2 + 8
|
||||
};
|
||||
/* Initialize the SPI bus */
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.dc_gpio_num = EXAMPLE_PIN_NUM_DC,
|
||||
.cs_gpio_num = EXAMPLE_PIN_NUM_CS,
|
||||
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
|
||||
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
|
||||
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
|
||||
.spi_mode = 0,
|
||||
.trans_queue_depth = 10,
|
||||
};
|
||||
/* Attach the LCD to the SPI bus */
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &s_avrc_cover_art_srv_cb.io_handle));
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.bits_per_pixel = 16,
|
||||
};
|
||||
/* Initialize the LCD configuration */
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(s_avrc_cover_art_srv_cb.io_handle, &panel_config, &s_avrc_cover_art_srv_cb.panel_handle));
|
||||
|
||||
/* Turn off backlight to avoid unpredictable display on the LCD screen while initializing
|
||||
* the LCD panel driver. (Different LCD screens may need different levels) */
|
||||
ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL));
|
||||
|
||||
/* Reset the display */
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_reset(s_avrc_cover_art_srv_cb.panel_handle));
|
||||
|
||||
/* Initialize LCD panel */
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(s_avrc_cover_art_srv_cb.panel_handle));
|
||||
|
||||
/* Turn on the screen */
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(s_avrc_cover_art_srv_cb.panel_handle, true));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_invert_color(s_avrc_cover_art_srv_cb.panel_handle, true));
|
||||
|
||||
/* Swap x and y axis (Different LCD screens may need different options) */
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(s_avrc_cover_art_srv_cb.panel_handle, true));
|
||||
|
||||
/* Turn on backlight (Different LCD screens may need different levels) */
|
||||
ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL));
|
||||
}
|
||||
|
||||
static void avrc_cover_art_srv_deinit_display(void)
|
||||
{
|
||||
/* Turn off backlight first */
|
||||
ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_OFF_LEVEL));
|
||||
|
||||
/* Turn off the display */
|
||||
if (s_avrc_cover_art_srv_cb.panel_handle) {
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(s_avrc_cover_art_srv_cb.panel_handle, false));
|
||||
/* Delete the LCD panel */
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_del(s_avrc_cover_art_srv_cb.panel_handle));
|
||||
s_avrc_cover_art_srv_cb.panel_handle = NULL;
|
||||
}
|
||||
|
||||
/* Delete the LCD panel IO */
|
||||
if (s_avrc_cover_art_srv_cb.io_handle) {
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_io_del(s_avrc_cover_art_srv_cb.io_handle));
|
||||
s_avrc_cover_art_srv_cb.io_handle = NULL;
|
||||
}
|
||||
|
||||
/* Free the SPI bus */
|
||||
ESP_ERROR_CHECK(spi_bus_free(LCD_HOST));
|
||||
|
||||
/* Reset backlight GPIO */
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(EXAMPLE_PIN_NUM_BK_LIGHT));
|
||||
}
|
||||
|
||||
static void avrc_cover_art_srv_free_pixels(void)
|
||||
{
|
||||
if (s_avrc_cover_art_srv_cb.pixels) {
|
||||
free(s_avrc_cover_art_srv_cb.pixels);
|
||||
s_avrc_cover_art_srv_cb.pixels = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t avrc_cover_art_srv_decode_image(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
avrc_cover_art_srv_free_pixels();
|
||||
|
||||
/* Allocate pixel memory. Each line is an array of IMAGE_W 16-bit pixels; the `s_avrc_cover_art_srv_cb.pixels` array itself contains pointers to these lines. */
|
||||
s_avrc_cover_art_srv_cb.pixels = calloc(IMAGE_H * IMAGE_W, sizeof(uint16_t));
|
||||
|
||||
ESP_GOTO_ON_FALSE(s_avrc_cover_art_srv_cb.pixels, ESP_ERR_NO_MEM, err, RC_CA_SRV_TAG, "Error allocating memory for lines");
|
||||
|
||||
/* JPEG decode config */
|
||||
esp_jpeg_image_cfg_t jpeg_cfg = {
|
||||
.indata = (uint8_t *)s_avrc_cover_art_srv_cb.image_data,
|
||||
.indata_size = s_avrc_cover_art_srv_cb.image_size,
|
||||
.outbuf = (uint8_t*)(s_avrc_cover_art_srv_cb.pixels),
|
||||
.outbuf_size = IMAGE_W * IMAGE_H * sizeof(uint16_t),
|
||||
.out_format = JPEG_IMAGE_FORMAT_RGB565,
|
||||
.out_scale = JPEG_IMAGE_SCALE_0,
|
||||
.flags = {
|
||||
.swap_color_bytes = 1,
|
||||
}
|
||||
};
|
||||
|
||||
/* JPEG decode */
|
||||
esp_jpeg_image_output_t outimg;
|
||||
ret = esp_jpeg_decode(&jpeg_cfg, &outimg);
|
||||
|
||||
ESP_LOGI(RC_CA_SRV_TAG, "JPEG image decoded! Size of the decoded image is: %dpx x %dpx.", outimg.width, outimg.height);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
/* Something went wrong! Exit cleanly, de-allocating everything we allocated. */
|
||||
avrc_cover_art_srv_free_pixels();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void avrc_cover_art_srv_display_image(void)
|
||||
{
|
||||
if (s_avrc_cover_art_srv_cb.panel_handle && s_avrc_cover_art_srv_cb.pixels) {
|
||||
esp_lcd_panel_draw_bitmap(s_avrc_cover_art_srv_cb.panel_handle, 0, 0, EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES, s_avrc_cover_art_srv_cb.pixels);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************
|
||||
* EXTERNAL FUNCTION DEFINITIONS
|
||||
*******************************/
|
||||
|
||||
void avrc_cover_art_srv_open(void)
|
||||
{
|
||||
memset(&s_avrc_cover_art_srv_cb, 0, sizeof(avrc_cover_art_srv_cb_t));
|
||||
/* initialize the display */
|
||||
avrc_cover_art_srv_init_display();
|
||||
}
|
||||
|
||||
void avrc_cover_art_srv_close(void)
|
||||
{
|
||||
/* deinitialize the display */
|
||||
avrc_cover_art_srv_deinit_display();
|
||||
|
||||
avrc_cover_art_srv_free_image_data();
|
||||
avrc_cover_art_srv_free_pixels();
|
||||
|
||||
memset(&s_avrc_cover_art_srv_cb, 0, sizeof(avrc_cover_art_srv_cb_t));
|
||||
}
|
||||
|
||||
void avrc_cover_art_srv_connect(uint16_t mtu)
|
||||
{
|
||||
if (!s_avrc_cover_art_srv_cb.connected) {
|
||||
ESP_LOGW(RC_CA_SRV_TAG, "Start cover art connection...");
|
||||
/* start the cover art connection */
|
||||
esp_avrc_ct_cover_art_connect(mtu);
|
||||
}
|
||||
}
|
||||
|
||||
void avrc_cover_art_srv_set_image_final(bool final)
|
||||
{
|
||||
s_avrc_cover_art_srv_cb.image_final = final;
|
||||
if (s_avrc_cover_art_srv_cb.image_final) {
|
||||
ESP_LOGI(RC_CA_SRV_TAG, "Cover Art Client final data event, image size: %lu bytes", s_avrc_cover_art_srv_cb.image_size);
|
||||
|
||||
/* decode and display the image */
|
||||
avrc_cover_art_srv_decode_image();
|
||||
/* display the image */
|
||||
avrc_cover_art_srv_display_image();
|
||||
/* set the getting state to false, we can get next image now */
|
||||
s_avrc_cover_art_srv_cb.getting = false;
|
||||
}
|
||||
}
|
||||
|
||||
void avrc_cover_art_srv_set_connected(bool connected)
|
||||
{
|
||||
s_avrc_cover_art_srv_cb.connected = connected;
|
||||
}
|
||||
|
||||
void avrc_cover_art_srv_ca_req(void)
|
||||
{
|
||||
/* request cover art */
|
||||
if (s_avrc_cover_art_srv_cb.connected) {
|
||||
uint8_t attr_mask = ESP_AVRC_MD_ATTR_COVER_ART;
|
||||
|
||||
esp_avrc_ct_send_metadata_cmd(bt_avrc_common_alloc_tl(), attr_mask);
|
||||
}
|
||||
}
|
||||
|
||||
void avrc_cover_art_srv_save_image_data(uint8_t *p_data, uint16_t data_len)
|
||||
{
|
||||
s_avrc_cover_art_srv_cb.image_size += data_len;
|
||||
|
||||
uint8_t *p_buf = (uint8_t *)realloc(s_avrc_cover_art_srv_cb.image_data, s_avrc_cover_art_srv_cb.image_size * sizeof(uint8_t));
|
||||
if (!p_buf) {
|
||||
ESP_LOGE(RC_CA_SRV_TAG, "%s: The memory allocation of Cover art image data failed", __func__);
|
||||
avrc_cover_art_srv_free_image_data();
|
||||
return;
|
||||
}
|
||||
s_avrc_cover_art_srv_cb.image_data = p_buf;
|
||||
memcpy(s_avrc_cover_art_srv_cb.image_data + s_avrc_cover_art_srv_cb.image_size - data_len, p_data, data_len);
|
||||
}
|
||||
|
||||
void avrc_cover_art_srv_ct_metadata_update(uint8_t *image_handle, int len)
|
||||
{
|
||||
if (s_avrc_cover_art_srv_cb.connected && !s_avrc_cover_art_srv_cb.getting) {
|
||||
/* check image handle is valid and different with last one, we don't want to get an image repeatedly */
|
||||
if (avrc_cover_art_srv_image_handle_check(image_handle, len)) {
|
||||
/* free the previous image data */
|
||||
avrc_cover_art_srv_free_image_data();
|
||||
/* get the linked thumbnail */
|
||||
esp_avrc_ct_cover_art_get_linked_thumbnail(image_handle);
|
||||
s_avrc_cover_art_srv_cb.getting = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#ifndef __AVRCP_COVER_ART_SERVICE_H__
|
||||
#define __AVRCP_COVER_ART_SERVICE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_avrc_api.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief open AVRCP cover art service
|
||||
*/
|
||||
void avrc_cover_art_srv_open(void);
|
||||
|
||||
/**
|
||||
* @brief close AVRCP cover art service
|
||||
*/
|
||||
void avrc_cover_art_srv_close(void);
|
||||
|
||||
/**
|
||||
* @brief start the cover art connection
|
||||
*
|
||||
* @param [in] mtu: maximum transmission unit
|
||||
*/
|
||||
void avrc_cover_art_srv_connect(uint16_t mtu);
|
||||
|
||||
/**
|
||||
* @brief set AVRCP cover art image final, and then if image final is true, display the image
|
||||
*
|
||||
* @param [in] final: true if image reception has been completed, false otherwise
|
||||
*/
|
||||
void avrc_cover_art_srv_set_image_final(bool final);
|
||||
|
||||
/**
|
||||
* @brief set AVRCP cover art connected
|
||||
*
|
||||
* @param [in] connected: true if connected, false otherwise
|
||||
*/
|
||||
void avrc_cover_art_srv_set_connected(bool connected);
|
||||
|
||||
/**
|
||||
* @brief request AVRCP cover art
|
||||
*/
|
||||
void avrc_cover_art_srv_ca_req(void);
|
||||
|
||||
/**
|
||||
* @brief save cover art data
|
||||
*
|
||||
* @param [in] p_data: pointer to the cover art data
|
||||
* @param [in] data_len: length of the cover art data
|
||||
*/
|
||||
void avrc_cover_art_srv_save_image_data(uint8_t *p_data, uint16_t data_len);
|
||||
|
||||
/**
|
||||
* @brief handle the cover art update when metadata response
|
||||
*
|
||||
* @param [in] image_handle: pointer to the image handle
|
||||
* @param [in] len: length of the image handle
|
||||
*/
|
||||
void avrc_cover_art_srv_ct_metadata_update(uint8_t *image_handle, int len);
|
||||
|
||||
#endif /* __AVRCP_COVER_ART_SERVICE_H__ */
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_avrc_api.h"
|
||||
#include "avrcp_utils_tags.h"
|
||||
#include "avrcp_cover_art_service.h"
|
||||
|
||||
void bt_avrc_ca_ct_evt_hdl(uint16_t event, void *param)
|
||||
{
|
||||
ESP_LOGD(BT_RC_CT_TAG, "%s event: %d", __func__, event);
|
||||
|
||||
esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param);
|
||||
|
||||
switch (event) {
|
||||
/* when connection state changed, this event comes */
|
||||
case ESP_AVRC_CT_CONNECTION_STATE_EVT: {
|
||||
if (rc->conn_stat.connected) {
|
||||
/* open the cover art service */
|
||||
avrc_cover_art_srv_open();
|
||||
} else {
|
||||
/* close the cover art service */
|
||||
avrc_cover_art_srv_close();
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* when metadata response, this event comes */
|
||||
case ESP_AVRC_CT_METADATA_RSP_EVT: {
|
||||
ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text);
|
||||
if (rc->meta_rsp.attr_id == ESP_AVRC_MD_ATTR_COVER_ART) {
|
||||
avrc_cover_art_srv_ct_metadata_update(rc->meta_rsp.attr_text, rc->meta_rsp.attr_length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* when notified, this event comes */
|
||||
case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: {
|
||||
if (rc->change_ntf.event_id == ESP_AVRC_RN_TRACK_CHANGE) {
|
||||
/* request the cover art */
|
||||
avrc_cover_art_srv_ca_req();
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* when feature of remote device indicated, this event comes */
|
||||
case ESP_AVRC_CT_REMOTE_FEATURES_EVT: {
|
||||
ESP_LOGI(BT_RC_CT_TAG, "AVRC remote features %"PRIx32", TG features %x", rc->rmt_feats.feat_mask, rc->rmt_feats.tg_feat_flag);
|
||||
if ((rc->rmt_feats.tg_feat_flag & ESP_AVRC_FEAT_FLAG_TG_COVER_ART)) {
|
||||
ESP_LOGW(BT_RC_CT_TAG, "Peer support Cover Art feature");
|
||||
/* start the cover art connection */
|
||||
avrc_cover_art_srv_connect(ESP_AVRC_CA_MTU_MAX);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* when notification capability of peer device got, this event comes */
|
||||
case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: {
|
||||
/* request the cover art */
|
||||
avrc_cover_art_srv_ca_req();
|
||||
break;
|
||||
}
|
||||
/* when the state of cover art changes, this event comes */
|
||||
case ESP_AVRC_CT_COVER_ART_STATE_EVT: {
|
||||
if (rc->cover_art_state.state == ESP_AVRC_COVER_ART_CONNECTED) {
|
||||
avrc_cover_art_srv_set_connected(true);
|
||||
ESP_LOGW(BT_RC_CT_TAG, "Cover Art Client connected");
|
||||
/* request the cover art */
|
||||
avrc_cover_art_srv_ca_req();
|
||||
} else {
|
||||
avrc_cover_art_srv_set_connected(false);
|
||||
ESP_LOGW(BT_RC_CT_TAG, "Cover Art Client disconnected, reason:%d", rc->cover_art_state.reason);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* when obtaining the cover art image data, this event comes */
|
||||
case ESP_AVRC_CT_COVER_ART_DATA_EVT: {
|
||||
/* when rc->cover_art_data.final is true, it means we have received the entire image */
|
||||
avrc_cover_art_srv_set_image_final(rc->cover_art_data.final);
|
||||
break;
|
||||
}
|
||||
/* others */
|
||||
default:
|
||||
ESP_LOGE(BT_RC_CT_TAG, "%s unhandled event: %d", __func__, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#ifndef __AVRCP_COVER_ART_UTILS_H__
|
||||
#define __AVRCP_COVER_ART_UTILS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief handle function for AVRCP controller cover art event
|
||||
*
|
||||
* @param [in] event event id
|
||||
* @param [in] param callback parameter
|
||||
*/
|
||||
void bt_avrc_ca_ct_evt_hdl(uint16_t event, void *param);
|
||||
|
||||
#endif /* __AVRCP_COVER_ART_UTILS_H__*/
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
dependencies:
|
||||
idf: ">=4.4"
|
||||
esp_jpeg: ">=1.0.2"
|
||||
avrcp_common_utils:
|
||||
path: ${IDF_PATH}/examples/bluetooth/bluedroid/classic_bt/common/avrcp_utils/avrcp_common_utils
|
||||
Reference in New Issue
Block a user