mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	a2dp: add props param support for LDAC
LDAC quality can now be set with SPA_PROP_quality on a2dp-sink node. Also fix a NULL reference if device setting is empty.
This commit is contained in:
		
							parent
							
								
									1d390addb1
								
							
						
					
					
						commit
						abfa04caa4
					
				
					 1 changed files with 92 additions and 0 deletions
				
			
		| 
						 | 
					@ -27,6 +27,8 @@
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <arpa/inet.h>
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <spa/pod/parser.h>
 | 
				
			||||||
 | 
					#include <spa/param/props.h>
 | 
				
			||||||
#include <spa/param/audio/format.h>
 | 
					#include <spa/param/audio/format.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <ldacBT.h>
 | 
					#include <ldacBT.h>
 | 
				
			||||||
| 
						 | 
					@ -75,6 +77,8 @@ struct impl {
 | 
				
			||||||
	int frame_length;
 | 
						int frame_length;
 | 
				
			||||||
	int frame_count;
 | 
						int frame_count;
 | 
				
			||||||
	int frame_count_factor;
 | 
						int frame_count_factor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const struct props *props;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
| 
						 | 
					@ -354,6 +358,65 @@ static void codec_clear_props(void *props)
 | 
				
			||||||
	free(props);
 | 
						free(props);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int codec_enum_props(void *props, const struct spa_dict *settings, uint32_t id, uint32_t idx,
 | 
				
			||||||
 | 
								struct spa_pod_builder *b, struct spa_pod **param)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct props *p = props;
 | 
				
			||||||
 | 
						switch (id) {
 | 
				
			||||||
 | 
						case SPA_PARAM_PropInfo:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							switch (idx) {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								*param = spa_pod_builder_add_object(b,
 | 
				
			||||||
 | 
									SPA_TYPE_OBJECT_PropInfo, id,
 | 
				
			||||||
 | 
									SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_quality),
 | 
				
			||||||
 | 
									SPA_PROP_INFO_name, SPA_POD_String("LDAC quality"),
 | 
				
			||||||
 | 
									SPA_PROP_INFO_type, SPA_POD_CHOICE_ENUM_Int(5,
 | 
				
			||||||
 | 
												p->eqmid,
 | 
				
			||||||
 | 
												LDACBT_EQMID_AUTO,
 | 
				
			||||||
 | 
												LDACBT_EQMID_HQ,
 | 
				
			||||||
 | 
												LDACBT_EQMID_SQ,
 | 
				
			||||||
 | 
												LDACBT_EQMID_MQ));
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						case SPA_PARAM_Props:
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							switch (idx) {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								*param = spa_pod_builder_add_object(b,
 | 
				
			||||||
 | 
									SPA_TYPE_OBJECT_Props, id,
 | 
				
			||||||
 | 
									SPA_PROP_quality, SPA_POD_Int(p->eqmid));
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int codec_set_props(void *props, const struct spa_pod *param)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct props *p = props;
 | 
				
			||||||
 | 
						const int prev_eqmid = p->eqmid;
 | 
				
			||||||
 | 
						if (param == NULL) {
 | 
				
			||||||
 | 
							p->eqmid = LDACBT_EQMID_AUTO;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							spa_pod_parse_object(param,
 | 
				
			||||||
 | 
									SPA_TYPE_OBJECT_Props, NULL,
 | 
				
			||||||
 | 
									SPA_PROP_quality, SPA_POD_OPT_Int(&p->eqmid));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return prev_eqmid != p->eqmid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
 | 
					static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
 | 
				
			||||||
		void *config, size_t config_len, const struct spa_audio_info *info,
 | 
							void *config, size_t config_len, const struct spa_audio_info *info,
 | 
				
			||||||
		void *props, size_t mtu)
 | 
							void *props, size_t mtu)
 | 
				
			||||||
| 
						 | 
					@ -480,6 +543,32 @@ static void codec_deinit(void *data)
 | 
				
			||||||
	free(this);
 | 
						free(this);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int codec_update_props(void *data, void *props)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct impl *this = data;
 | 
				
			||||||
 | 
						struct props *p = props;
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (p == NULL)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (p->eqmid == LDACBT_EQMID_AUTO) {
 | 
				
			||||||
 | 
							this->eqmid = LDACBT_EQMID_SQ;
 | 
				
			||||||
 | 
							this->enable_abr = true;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							this->eqmid = p->eqmid;
 | 
				
			||||||
 | 
							this->enable_abr = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((res = ldacBT_set_eqmid(this->ldac, this->eqmid)) < 0)
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						if ((res = update_frame_info(this)) < 0)
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					error:
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int codec_abr_process(void *data, size_t unsent)
 | 
					static int codec_abr_process(void *data, size_t unsent)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef ENABLE_LDAC_ABR
 | 
					#ifdef ENABLE_LDAC_ABR
 | 
				
			||||||
| 
						 | 
					@ -547,9 +636,12 @@ const struct a2dp_codec a2dp_codec_ldac = {
 | 
				
			||||||
	.select_config = codec_select_config,
 | 
						.select_config = codec_select_config,
 | 
				
			||||||
	.enum_config = codec_enum_config,
 | 
						.enum_config = codec_enum_config,
 | 
				
			||||||
	.init_props = codec_init_props,
 | 
						.init_props = codec_init_props,
 | 
				
			||||||
 | 
						.enum_props = codec_enum_props,
 | 
				
			||||||
 | 
						.set_props = codec_set_props,
 | 
				
			||||||
	.clear_props = codec_clear_props,
 | 
						.clear_props = codec_clear_props,
 | 
				
			||||||
	.init = codec_init,
 | 
						.init = codec_init,
 | 
				
			||||||
	.deinit = codec_deinit,
 | 
						.deinit = codec_deinit,
 | 
				
			||||||
 | 
						.update_props = codec_update_props,
 | 
				
			||||||
	.get_block_size = codec_get_block_size,
 | 
						.get_block_size = codec_get_block_size,
 | 
				
			||||||
	.get_num_blocks = codec_get_num_blocks,
 | 
						.get_num_blocks = codec_get_num_blocks,
 | 
				
			||||||
	.abr_process = codec_abr_process,
 | 
						.abr_process = codec_abr_process,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue