1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2019 Pali Rohár <pali.rohar@gmail.com> 5 6 PulseAudio is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as 8 published by the Free Software Foundation; either version 2.1 of the 9 License, or (at your option) any later version. 10 11 PulseAudio is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 18***/ 19 20#ifdef HAVE_CONFIG_H 21#include <config.h> 22#endif 23 24#include <pulsecore/core.h> 25#include <pulsecore/core-util.h> 26#if defined(HAVE_GSTAPTX) || defined(HAVE_GSTLDAC) 27#include <gst/gst.h> 28#endif 29 30#include "a2dp-codec-util.h" 31 32extern const pa_bt_codec pa_bt_codec_msbc; 33extern const pa_bt_codec pa_bt_codec_cvsd; 34 35/* List of HSP/HFP codecs. 36 */ 37static const pa_bt_codec *pa_hf_codecs[] = { 38 &pa_bt_codec_cvsd, 39 &pa_bt_codec_msbc, 40}; 41 42extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_sbc; 43extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_sbc_xq_453; 44extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_sbc_xq_512; 45extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_sbc_xq_552; 46#ifdef HAVE_GSTAPTX 47extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_aptx; 48extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_aptx_hd; 49#endif 50#ifdef HAVE_GSTLDAC 51extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_hq; 52extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_sq; 53extern const pa_a2dp_endpoint_conf pa_a2dp_endpoint_conf_ldac_eqmid_mq; 54#endif 55 56/* This is list of supported codecs. Their order is important. 57 * Codec with lower index has higher priority. */ 58static const pa_a2dp_endpoint_conf *pa_a2dp_endpoint_configurations[] = { 59#ifdef HAVE_GSTLDAC 60 &pa_a2dp_endpoint_conf_ldac_eqmid_hq, 61 &pa_a2dp_endpoint_conf_ldac_eqmid_sq, 62 &pa_a2dp_endpoint_conf_ldac_eqmid_mq, 63#endif 64#ifdef HAVE_GSTAPTX 65 &pa_a2dp_endpoint_conf_aptx_hd, 66 &pa_a2dp_endpoint_conf_aptx, 67#endif 68 &pa_a2dp_endpoint_conf_sbc, 69 &pa_a2dp_endpoint_conf_sbc_xq_453, 70 &pa_a2dp_endpoint_conf_sbc_xq_512, 71 &pa_a2dp_endpoint_conf_sbc_xq_552, 72}; 73 74unsigned int pa_bluetooth_a2dp_endpoint_conf_count(void) { 75 return PA_ELEMENTSOF(pa_a2dp_endpoint_configurations); 76} 77 78const pa_a2dp_endpoint_conf *pa_bluetooth_a2dp_endpoint_conf_iter(unsigned int i) { 79 pa_assert(i < pa_bluetooth_a2dp_endpoint_conf_count()); 80 return pa_a2dp_endpoint_configurations[i]; 81} 82 83unsigned int pa_bluetooth_hf_codec_count(void) { 84 return PA_ELEMENTSOF(pa_hf_codecs); 85} 86 87const pa_bt_codec *pa_bluetooth_hf_codec_iter(unsigned int i) { 88 pa_assert(i < pa_bluetooth_hf_codec_count()); 89 return pa_hf_codecs[i]; 90} 91 92const pa_bt_codec *pa_bluetooth_get_hf_codec(const char *name) { 93 unsigned int i; 94 95 for (i = 0; i < PA_ELEMENTSOF(pa_hf_codecs); ++i) { 96 if (pa_streq(pa_hf_codecs[i]->name, name)) 97 return pa_hf_codecs[i]; 98 } 99 100 return NULL; 101} 102 103const pa_a2dp_endpoint_conf *pa_bluetooth_get_a2dp_endpoint_conf(const char *name) { 104 unsigned int i; 105 unsigned int count = pa_bluetooth_a2dp_endpoint_conf_count(); 106 107 for (i = 0; i < count; i++) { 108 if (pa_streq(pa_a2dp_endpoint_configurations[i]->bt_codec.name, name)) 109 return pa_a2dp_endpoint_configurations[i]; 110 } 111 112 return NULL; 113} 114 115void pa_bluetooth_a2dp_codec_gst_init(void) { 116#if defined(HAVE_GSTAPTX) || defined(HAVE_GSTLDAC) 117 GError *error = NULL; 118 119 if (!gst_init_check(NULL, NULL, &error)) { 120 pa_log_error("Could not initialise GStreamer: %s", error->message); 121 g_error_free(error); 122 return; 123 } 124 pa_log_info("GStreamer initialisation done"); 125#endif 126} 127 128bool pa_bluetooth_a2dp_codec_is_available(const pa_a2dp_codec_id *id, bool is_a2dp_sink) { 129 unsigned int i; 130 unsigned int count = pa_bluetooth_a2dp_endpoint_conf_count(); 131 const pa_a2dp_endpoint_conf *conf; 132 133 for (i = 0; i < count; i++) { 134 conf = pa_bluetooth_a2dp_endpoint_conf_iter(i); 135 if (memcmp(id, &conf->id, sizeof(pa_a2dp_codec_id)) == 0 136 && conf->can_be_supported(is_a2dp_sink)) 137 return true; 138 } 139 140 return false; 141} 142