The dev team seems to be more concerned about discussing about doc and concepts for decades,  than implementing a well engineered, simple, efficient, and reliable solution.<div><br /></div><div>Meanwhile thousands users are using my SBC XQ patch and nobody reported any problem : for a good reason: it's simple enough to be reliable.</div><div><br /></div><div>I hope you will manage to merge Pali's patch set before 2030.</div><div><br /></div><div>I have to remind you about reality: Bluetooth and DLNA are the way 90% of the people are listening to music in 2020. Everything else can be delayed.</div><div><br /></div><div>Oups : sorry, there's no DLNA support at all in Pulseaudio. .. so it's maybe time to start implememting it before PA version 0.1 ? Oups we passed version  0.1 without wireless audio support .... worth a Black Mirror episode ?</div><div><br /></div><div>Jp</div><div><br />13:57, 9 décembre 2019, Hyperion <h1p8r10n@yandex.com>:<br /><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote"><p><br /><br />09.12.2019, 12:33, "Andrey Semashev" <<a href="mailto:andrey.semashev@gmail.com">andrey.semashev@gmail.com</a>>:<br /></p><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote"> I have another piece of feedback to provide. Sometimes I experience<br /> audio dropouts. Sometimes in both left and right headphones, sometimes<br /> just one. In particular, I noticed this happen when I have a<br /> Bluetooth-connected DualShock 4 gamepad connected and playing games, but<br /> it also happens without it, although less often.<br /><br /> I assume this is caused by Bluetooth bandwidth limitation. Note that EOZ<br /> Air are "truly wireless" (i.e. the two headphones connect wirelessly),<br /> and I have multiple WiFi networks available (one access point in the<br /> same room as the Bluetooth transmitter, a few others behind walls). I<br /> expect 2.4 GHz radio to be rather crowded. The gamepad and the<br /> headphones are in the same room as the Bluetooth transmitter, in clear<br /> direct visibility, so it can't get better than that.<br /><br /> I can see Pali's patches offer reduce_encoder_bitrate API that is<br /> supposed to mitigate this problem, but both SBC XQ profiles don't allow<br /> bitrate reduction. I think, SBC XQ desperately needs to support bitrate<br /> reduction, as the codec with the highest bitrate out of all.<br /></blockquote><p><br />Yes, and my patch was providing 100% adaptative SBC XQ, with native bitpool <br />reduction, as you suggest. But something more complex and yet more "static"' has <br />been preferred.<br /><br /> Users might<br /></p><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote"> actually have reduced experience due to audio dropouts compared to the<br /> previously supported SBC HQ.<br /><br /> On <span class="177d5a4333ac019606de889e143743a1wmi-callto">2019-12-07 21</span>:09, Andrey Semashev wrote:<br /><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote">  FWIW, I tested the patch[1] from your github repository with PulseAudio<br />  13.0 on Ubuntu 19.10 with my EOZ Air. It works, and the sound quality is<br />  subjectively better compared to the stock PA 13.0. The noise level that<br />  can be heard on silent audio sections seems to be lower.<br /><br />  However, I can still hear compression artefacts on quiet or nearly<br />  silent audio sections, which sound like high-pitch squeaking sounds. It<br />  can often be heard on various music fade out sections. I don't know if<br />  this is inherrent from SBC codec itself or is a deficiency of libsbc<br />  implementation, or the headphones. These artefacts are my main complaint<br />  about SBC.<br /><br />  My EOZ Air also supports AAC, and the audio quality is better still with<br />  it (I tested with pulseaudio-modules-bt[2] and my Android phone). There<br />  are no squeaky artefacts with AAC.<br /><br />  Which brings me to my question to PA developers. Would an addition of<br />  support for AAC be possible?<br /><br />  pulseaudio-modules-bt uses libfdk-aac to implement AAC, and if possible,<br />  I would prefer that library as it provides the best quality available on<br />  Linux. However, if licensing is an issue, there is also a built-in<br />  implementation in ffmpeg.<br /><br />  [1]: Patch obtained with `git diff<br />  200618b32f0964a479d69c9b6e5073e6931c370a..0853d<span class="177d5a4333ac019606de889e143743a1wmi-callto">7465729</span>c1fb6c25745c05dc749a1b9a8d6f`<br /><br />  [2]: <a href="https://github.com/EHfive/pulseaudio-modules-bt">https://github.com/EHfive/pulseaudio-modules-bt</a><br /><br />  On <span class="177d5a4333ac019606de889e143743a1wmi-callto">2019-09-20 12</span>:45, Hyperion wrote:<br /><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote">  HI,<br /><br />  I have reworked my mod so that it can safely achieve bitpool 94 in<br />  both dual channel and joint stereo, as long as the device supports it<br />  (only my high end Harman Kardon support 94 in joint stereo).<br />  Devices supporting only bitpool 53 are kept safe (bitpool is always<br />  negociated, never forced : this doesn't use fixed caps).<br /><br />  Anyway most devices support at least bitpool 47 in dual channel mode,<br />  and BT (version 3 and up) bandwidth is much higher : so this patch<br />  deprecates both APTX and LDAC.<br /><br />  The Git is up to date : <a href="https://github.com/JPGuillemin/pulseaudio">https://github.com/JPGuillemin/pulseaudio</a><br /><br />  This patch is likely safe to be applied on the official master cause<br />  it doesn't need Bluez multi-codec API, and doesn't introduce any<br />  patent issue (mainly from CSR, openaptx being underground reverse<br />  ingeniering).<br /><br />  All the best<br />  JP<br /><br />  19.09.2019, 13:07, "Hyperion" <<a href="mailto:h1p8r10n@yandex.com">h1p8r10n@yandex.com</a>>:<br /><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote">  The Git branch with my mods :<br />  <a href="https://github.com/JPGuillemin/pulseaudio/tree/SBC-XQ">https://github.com/JPGuillemin/pulseaudio/tree/SBC-XQ</a><br /><br />  I'm sure it needs improvement, but I need testers ;) for now it works<br />  as expected on all my devices...<br /><br />  JP<br /><br />  19.09.2019, 11:21, "Hyperion" <<a href="mailto:h1p8r10n@yandex.com">h1p8r10n@yandex.com</a>>:<br /><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote">    Yes, thanks, you're right, I'm going to do it as soon as I get<br />  enough testing feedback.<br /><br />    Talking about tests : I'm going to switch back to Pali's default<br />  values for announced bitpool capabilities, cause some (rare) devices<br />  produces a few distorsion with dual channel 47 bitpool.<br /><br />    So back to dual 38 / 76 , which should be ok on any device.<br /><br />    New patch :<br />  <a href="http://download.zenwalk.org/x86_64/testing/pulseaudio-13.0-SBC-XQ_V3.patch">http://download.zenwalk.org/x86_64/testing/pulseaudio-13.0-SBC-XQ_V3.patch</a><br /><br />    Thanks for testing :)<br /><br />    jp<br /><br />    19.09.2019, 10:27, "Andrey Semashev" <<a href="mailto:andrey.semashev@gmail.com">andrey.semashev@gmail.com</a>>:<br /><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote">     I'm not the maintainer, but it might be better to create a merge<br />  request<br />     in GitLab project:<br /><br />     <a href="https://gitlab.freedesktop.org/pulseaudio/pulseaudio">https://gitlab.freedesktop.org/pulseaudio/pulseaudio</a><br /><br />     and post any additional information there so it doesn't get lost.<br /><br />     On <span class="177d5a4333ac019606de889e143743a1wmi-callto">2019-09-18 14</span>:02, Hyperion wrote:<br /><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote">      Patch V2 with added DUAL_CHANNEL as preferred mode.<br /><br />      Works without any issue on more than 10 stereo and mono<br />  devices that I have here.<br /><br />      <a href="http://download.zenwalk.org/x86_64/testing/pulseaudio-13.0-SBC-XQ_V2.patch">http://download.zenwalk.org/x86_64/testing/pulseaudio-13.0-SBC-XQ_V2.patch</a><br /><br />      /***<br />         This file is part of PulseAudio.<br /><br />         Copyright <span class="177d5a4333ac019606de889e143743a1wmi-callto">2018-2019</span> Pali Rohár <<a href="mailto:pali.rohar@gmail.com">pali.rohar@gmail.com</a>><br /><br />         PulseAudio is free software; you can redistribute it and/or<br />  modify<br />         it under the terms of the GNU Lesser General Public License as<br />         published by the Free Software Foundation; either version<br />  2.1 of the<br />         License, or (at your option) any later version.<br /><br />         PulseAudio is distributed in the hope that it will be<br />  useful, but<br />         WITHOUT ANY WARRANTY; without even the implied warranty of<br />         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See<br />  the GNU<br />         General Public License for more details.<br /><br />         You should have received a copy of the GNU Lesser General<br />  Public<br />         License along with PulseAudio; if not, see<br />  <<a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>>.<br />      ***/<br /><br />      #ifdef HAVE_CONFIG_H<br />      #include <config.h><br />      #endif<br /><br />      #include <pulsecore/core-util.h><br />      #include <pulsecore/log.h><br />      #include <pulsecore/macro.h><br />      #include <pulsecore/once.h><br />      #include <pulse/sample.h><br />      #include <pulse/xmalloc.h><br /><br />      #include <arpa/inet.h><br /><br />      #include <sbc/sbc.h><br /><br />      #include "a2dp-codecs.h"<br />      #include "a2dp-codec-api.h"<br />      #include "rtp.h"<br /><br />      #define SBC_BITPOOL_DEC_LIMIT 32<br />      #define SBC_BITPOOL_DEC_STEP 5<br /><br />      struct sbc_info {<!-- --><br />           sbc_t sbc; /* Codec data */<br />           size_t codesize, frame_length; /* SBC Codesize,<br />  frame_length. We simply cache those values here */<br />           uint16_t seq_num; /* Cumulative packet sequence */<br />           uint8_t frequency;<br />           uint8_t blocks;<br />           uint8_t subbands;<br />           uint8_t mode;<br />           uint8_t allocation;<br />           uint8_t initial_bitpool;<br />           uint8_t min_bitpool;<br />           uint8_t max_bitpool;<br />      };<br /><br />      static bool can_accept_capabilities(const uint8_t<br />  *capabilities_buffer, uint8_t capabilities_size, bool for_encoding) {<!-- --><br />           const a2dp_sbc_t *capabilities = (const a2dp_sbc_t *)<br />  capabilities_buffer;<br /><br />           if (capabilities_size != sizeof(*capabilities))<br />               return false;<br /><br />           if (!(capabilities->frequency & (SBC_SAMPLING_FREQ_16000<br />  | SBC_SAMPLING_FREQ_32000 | SBC_SAMPLING_FREQ_44100 |<br />  SBC_SAMPLING_FREQ_48000)))<br />               return false;<br /><br />           if (!(capabilities->channel_mode & (SBC_CHANNEL_MODE_MONO<br />  | SBC_CHANNEL_MODE_DUAL_CHANNEL | SBC_CHANNEL_MODE_STEREO |<br />  SBC_CHANNEL_MODE_JOINT_STEREO)))<br />               return false;<br /><br />           if (!(capabilities->allocation_method &<br />  (SBC_ALLOCATION_SNR | SBC_ALLOCATION_LOUDNESS)))<br />               return false;<br /><br />           if (!(capabilities->subbands & (SBC_SUBBANDS_4 |<br />  SBC_SUBBANDS_8)))<br />               return false;<br /><br />           if (!(capabilities->block_length & (SBC_BLOCK_LENGTH_4 |<br />  SBC_BLOCK_LENGTH_8 | SBC_BLOCK_LENGTH_12 | SBC_BLOCK_LENGTH_16)))<br />               return false;<br /><br />           return true;<br />      }<br /><br />      static const char *choose_remote_endpoint(const pa_hashmap<br />  *capabilities_hashmap, const pa_sample_spec *default_sample_spec,<br />  bool for_encoding) {<!-- --><br />           const pa_a2dp_codec_capabilities *a2dp_capabilities;<br />           const char *key;<br />           void *state;<br /><br />           /* There is no preference, just choose random valid entry */<br />           PA_HASHMAP_FOREACH_KV(key, a2dp_capabilities,<br />  capabilities_hashmap, state) {<!-- --><br />               if<br />  (can_accept_capabilities(a2dp_capabilities->buffer,<br />  a2dp_capabilities->size, for_encoding))<br />                   return key;<br />           }<br /><br />           return NULL;<br />      }<br /><br />      static uint8_t fill_capabilities(uint8_t<br />  capabilities_buffer[MAX_A2DP_CAPS_SIZE]) {<!-- --><br />           a2dp_sbc_t *capabilities = (a2dp_sbc_t *)<br />  capabilities_buffer;<br /><br />           pa_zero(*capabilities);<br /><br />           capabilities->channel_mode = SBC_CHANNEL_MODE_MONO |<br />  SBC_CHANNEL_MODE_DUAL_CHANNEL | SBC_CHANNEL_MODE_STEREO |<br />                                        SBC_CHANNEL_MODE_JOINT_STEREO;<br />           capabilities->frequency = SBC_SAMPLING_FREQ_16000 |<br />  SBC_SAMPLING_FREQ_32000 | SBC_SAMPLING_FREQ_44100 |<br />                                     SBC_SAMPLING_FREQ_48000;<br />           capabilities->allocation_method = SBC_ALLOCATION_SNR |<br />  SBC_ALLOCATION_LOUDNESS;<br />           capabilities->subbands = SBC_SUBBANDS_4 | SBC_SUBBANDS_8;<br />           capabilities->block_length = SBC_BLOCK_LENGTH_4 |<br />  SBC_BLOCK_LENGTH_8 | SBC_BLOCK_LENGTH_12 | SBC_BLOCK_LENGTH_16;<br />           capabilities->min_bitpool = SBC_MIN_BITPOOL;<br />           capabilities->max_bitpool =<br />  SBC_BITPOOL_HQ_JOINT_STEREO_44100;<br /><br />           return sizeof(*capabilities);<br />      }<br /><br />      static bool is_configuration_valid(const uint8_t<br />  *config_buffer, uint8_t config_size) {<!-- --><br />           const a2dp_sbc_t *config = (const a2dp_sbc_t *)<br />  config_buffer;<br /><br />           if (config_size != sizeof(*config)) {<!-- --><br />               pa_log_error("Invalid size of config buffer");<br />               return false;<br />           }<br /><br />           if (config->frequency != SBC_SAMPLING_FREQ_16000 &&<br />  config->frequency != SBC_SAMPLING_FREQ_32000 &&<br />               config->frequency != SBC_SAMPLING_FREQ_44100 &&<br />  config->frequency != SBC_SAMPLING_FREQ_48000) {<!-- --><br />               pa_log_error("Invalid sampling frequency in<br />  configuration");<br />               return false;<br />           }<br /><br />           if (config->channel_mode != SBC_CHANNEL_MODE_MONO &&<br />  config->channel_mode != SBC_CHANNEL_MODE_DUAL_CHANNEL &&<br />               config->channel_mode != SBC_CHANNEL_MODE_STEREO &&<br />  config->channel_mode != SBC_CHANNEL_MODE_JOINT_STEREO) {<!-- --><br />               pa_log_error("Invalid channel mode in configuration");<br />               return false;<br />           }<br /><br />           if (config->allocation_method != SBC_ALLOCATION_SNR &&<br />  config->allocation_method != SBC_ALLOCATION_LOUDNESS) {<!-- --><br />               pa_log_error("Invalid allocation method in<br />  configuration");<br />               return false;<br />           }<br /><br />           if (config->subbands != SBC_SUBBANDS_4 &&<br />  config->subbands != SBC_SUBBANDS_8) {<!-- --><br />               pa_log_error("Invalid SBC subbands in configuration");<br />               return false;<br />           }<br /><br />           if (config->block_length != SBC_BLOCK_LENGTH_4 &&<br />  config->block_length != SBC_BLOCK_LENGTH_8 &&<br />               config->block_length != SBC_BLOCK_LENGTH_12 &&<br />  config->block_length != SBC_BLOCK_LENGTH_16) {<!-- --><br />               pa_log_error("Invalid block length in configuration");<br />               return false;<br />           }<br /><br />           if (config->min_bitpool > config->max_bitpool) {<!-- --><br />               pa_log_error("Invalid bitpool in configuration");<br />               return false;<br />           }<br /><br />           return true;<br />      }<br /><br />      static uint8_t default_bitpool(uint8_t freq, uint8_t mode) {<!-- --><br />           /* These bitpool values were chosen based on the A2DP<br />  spec recommendation */<br />           switch (freq) {<!-- --><br />               case SBC_SAMPLING_FREQ_48000:<br />                   switch (mode) {<!-- --><br />                       case SBC_CHANNEL_MODE_MONO:<br />                       case SBC_CHANNEL_MODE_DUAL_CHANNEL:<br />                           return SBC_BITPOOL_HQ_MONO_48000;<br /><br />                       case SBC_CHANNEL_MODE_STEREO:<br />                       case SBC_CHANNEL_MODE_JOINT_STEREO:<br />                           return SBC_BITPOOL_HQ_JOINT_STEREO_48000;<br />                   }<br />                   break;<br />               case SBC_SAMPLING_FREQ_44100:<br />                   switch (mode) {<!-- --><br />                       case SBC_CHANNEL_MODE_MONO:<br />                       case SBC_CHANNEL_MODE_DUAL_CHANNEL:<br />                           return SBC_BITPOOL_HQ_MONO_44100;<br /><br />                       case SBC_CHANNEL_MODE_STEREO:<br />                       case SBC_CHANNEL_MODE_JOINT_STEREO:<br />                           return SBC_BITPOOL_HQ_JOINT_STEREO_44100;<br />                   }<br />                   break;<br />               case SBC_SAMPLING_FREQ_16000:<br />               case SBC_SAMPLING_FREQ_32000:<br />                   switch (mode) {<!-- --><br />                       case SBC_CHANNEL_MODE_MONO:<br />                       case SBC_CHANNEL_MODE_DUAL_CHANNEL:<br />                       case SBC_CHANNEL_MODE_STEREO:<br />                       case SBC_CHANNEL_MODE_JOINT_STEREO:<br />                           return SBC_BITPOOL_HQ_JOINT_STEREO_44100;<br />                   }<br />                   break;<br />           }<br /><br />           pa_assert_not_reached();<br />      }<br /><br />      static uint8_t fill_preferred_configuration(const<br />  pa_sample_spec *default_sample_spec, const uint8_t<br />  *capabilities_buffer, uint8_t capabilities_size, uint8_t<br />  config_buffer[MAX_A2DP_CAPS_SIZE]) {<!-- --><br />           a2dp_sbc_t *config = (a2dp_sbc_t *) config_buffer;<br />           const a2dp_sbc_t *capabilities = (const a2dp_sbc_t *)<br />  capabilities_buffer;<br />           int i;<br /><br />           static const struct {<!-- --><br />               uint32_t rate;<br />               uint8_t cap;<br />           } freq_table[] = {<!-- --><br />               { 16000U, SBC_SAMPLING_FREQ_16000 },<br />               { 32000U, SBC_SAMPLING_FREQ_32000 },<br />               { 44100U, SBC_SAMPLING_FREQ_44100 },<br />               { 48000U, SBC_SAMPLING_FREQ_48000 }<br />           };<br /><br />           if (capabilities_size != sizeof(*capabilities)) {<!-- --><br />               pa_log_error("Invalid size of capabilities buffer");<br />               return 0;<br />           }<br /><br />           pa_zero(*config);<br /><br />           /* Find the lowest freq that is at least as high as the<br />  requested sampling rate */<br />           for (i = 0; (unsigned) i < PA_ELEMENTSOF(freq_table); i++)<br />               if (freq_table[i].rate >= default_sample_spec->rate<br />  && (capabilities->frequency & freq_table[i].cap)) {<!-- --><br />                   config->frequency = freq_table[i].cap;<br />                   break;<br />               }<br /><br />           if ((unsigned) i == PA_ELEMENTSOF(freq_table)) {<!-- --><br />               for (--i; i >= 0; i--) {<!-- --><br />                   if (capabilities->frequency & freq_table[i].cap) {<!-- --><br />                       config->frequency = freq_table[i].cap;<br />                       break;<br />                   }<br />               }<br /><br />               if (i < 0) {<!-- --><br />                   pa_log_error("Not suitable sample rate");<br />                   return 0;<br />               }<br />           }<br /><br />           pa_assert((unsigned) i < PA_ELEMENTSOF(freq_table));<br /><br />           if (default_sample_spec->channels <= 1) {<!-- --><br />               if (capabilities->channel_mode & SBC_CHANNEL_MODE_MONO)<br />                   config->channel_mode = SBC_CHANNEL_MODE_MONO;<br />               else if (capabilities->channel_mode &<br />  SBC_CHANNEL_MODE_JOINT_STEREO)<br />                   config->channel_mode =<br />  SBC_CHANNEL_MODE_JOINT_STEREO;<br />               else if (capabilities->channel_mode &<br />  SBC_CHANNEL_MODE_STEREO)<br />                   config->channel_mode = SBC_CHANNEL_MODE_STEREO;<br />               else if (capabilities->channel_mode &<br />  SBC_CHANNEL_MODE_DUAL_CHANNEL)<br />                   config->channel_mode =<br />  SBC_CHANNEL_MODE_DUAL_CHANNEL;<br />               else {<!-- --><br />                   pa_log_error("No supported channel modes");<br />                   return 0;<br />               }<br />           } else {<!-- --><br />               if (capabilities->channel_mode &<br />  SBC_CHANNEL_MODE_DUAL_CHANNEL)<br />                   config->channel_mode =<br />  SBC_CHANNEL_MODE_DUAL_CHANNEL;<br />               else if (capabilities->channel_mode &<br />  SBC_CHANNEL_MODE_STEREO)<br />                   config->channel_mode = SBC_CHANNEL_MODE_STEREO;<br />               else if (capabilities->channel_mode &<br />  SBC_CHANNEL_MODE_JOINT_STEREO)<br />                   config->channel_mode =<br />  SBC_CHANNEL_MODE_JOINT_STEREO;<br />               else if (capabilities->channel_mode &<br />  SBC_CHANNEL_MODE_MONO)<br />                   config->channel_mode = SBC_CHANNEL_MODE_MONO;<br />               else {<!-- --><br />                   pa_log_error("No supported channel modes");<br />                   return 0;<br />               }<br />           }<br /><br />           if (capabilities->block_length & SBC_BLOCK_LENGTH_16)<br />               config->block_length = SBC_BLOCK_LENGTH_16;<br />           else if (capabilities->block_length & SBC_BLOCK_LENGTH_12)<br />               config->block_length = SBC_BLOCK_LENGTH_12;<br />           else if (capabilities->block_length & SBC_BLOCK_LENGTH_8)<br />               config->block_length = SBC_BLOCK_LENGTH_8;<br />           else if (capabilities->block_length & SBC_BLOCK_LENGTH_4)<br />               config->block_length = SBC_BLOCK_LENGTH_4;<br />           else {<!-- --><br />               pa_log_error("No supported block lengths");<br />               return 0;<br />           }<br /><br />           if (capabilities->subbands & SBC_SUBBANDS_8)<br />               config->subbands = SBC_SUBBANDS_8;<br />           else if (capabilities->subbands & SBC_SUBBANDS_4)<br />               config->subbands = SBC_SUBBANDS_4;<br />           else {<!-- --><br />               pa_log_error("No supported subbands");<br />               return 0;<br />           }<br /><br />           if (capabilities->allocation_method &<br />  SBC_ALLOCATION_LOUDNESS)<br />               config->allocation_method = SBC_ALLOCATION_LOUDNESS;<br />           else if (capabilities->allocation_method &<br />  SBC_ALLOCATION_SNR)<br />               config->allocation_method = SBC_ALLOCATION_SNR;<br />           else {<!-- --><br />               pa_log_error("No supported allocation method");<br />               return 0;<br />           }<br /><br />           config->min_bitpool = (uint8_t) PA_MAX(SBC_MIN_BITPOOL,<br />  capabilities->min_bitpool);<br />           config->max_bitpool = (uint8_t)<br />  PA_MIN(default_bitpool(config->frequency, config->channel_mode),<br />  capabilities->max_bitpool);<br /><br />           if (config->min_bitpool > config->max_bitpool) {<!-- --><br />               pa_log_error("No supported bitpool");<br />               return 0;<br />           }<br /><br />           return sizeof(*config);<br />      }<br /><br />      static void set_params(struct sbc_info *sbc_info) {<!-- --><br />           sbc_info->sbc.frequency = sbc_info->frequency;<br />           sbc_info->sbc.blocks = sbc_info->blocks;<br />           sbc_info->sbc.subbands = sbc_info->subbands;<br />           sbc_info->sbc.mode = sbc_info->mode;<br />           sbc_info->sbc.allocation = sbc_info->allocation;<br />           sbc_info->sbc.bitpool = sbc_info->initial_bitpool;<br />           sbc_info->sbc.endian = SBC_LE;<br /><br />           sbc_info->codesize = sbc_get_codesize(&sbc_info->sbc);<br />           sbc_info->frame_length =<br />  sbc_get_frame_length(&sbc_info->sbc);<br />      }<br /><br />      static void *init(bool for_encoding, bool for_backchannel,<br />  const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec<br />  *sample_spec) {<!-- --><br />           struct sbc_info *sbc_info;<br />           const a2dp_sbc_t *config = (const a2dp_sbc_t *)<br />  config_buffer;<br />           int ret;<br /><br />           pa_assert(config_size == sizeof(*config));<br />           pa_assert(!for_backchannel);<br /><br />           sbc_info = pa_xnew0(struct sbc_info, 1);<br /><br />           ret = sbc_init(&sbc_info->sbc, 0);<br />           if (ret != 0) {<!-- --><br />               pa_xfree(sbc_info);<br />               pa_log_error("SBC initialization failed: %d", ret);<br />               return NULL;<br />           }<br /><br />           sample_spec->format = PA_SAMPLE_S16LE;<br /><br />           switch (config->frequency) {<!-- --><br />               case SBC_SAMPLING_FREQ_48000:<br />                   sbc_info->frequency = SBC_FREQ_48000;<br />                   sample_spec->rate = 48000U;<br />                   break;<br />               case SBC_SAMPLING_FREQ_44100:<br />                   sbc_info->frequency = SBC_FREQ_44100;<br />                   sample_spec->rate = 44100U;<br />                   break;<br />               case SBC_SAMPLING_FREQ_32000:<br />                   sbc_info->frequency = SBC_FREQ_32000;<br />                   sample_spec->rate = 32000U;<br />                   break;<br />               case SBC_SAMPLING_FREQ_16000:<br />                   sbc_info->frequency = SBC_FREQ_16000;<br />                   sample_spec->rate = 16000U;<br />                   break;<br />               default:<br />                   pa_assert_not_reached();<br />           }<br /><br />           switch (config->channel_mode) {<!-- --><br />               case SBC_CHANNEL_MODE_DUAL_CHANNEL:<br />                   sbc_info->mode = SBC_MODE_DUAL_CHANNEL;<br />                   sample_spec->channels = 2;<br />                   break;<br />               case SBC_CHANNEL_MODE_STEREO:<br />                   sbc_info->mode = SBC_MODE_STEREO;<br />                   sample_spec->channels = 2;<br />                   break;<br />               case SBC_CHANNEL_MODE_JOINT_STEREO:<br />                   sbc_info->mode = SBC_MODE_JOINT_STEREO;<br />                   sample_spec->channels = 2;<br />                   break;<br />               case SBC_CHANNEL_MODE_MONO:<br />                   sbc_info->mode = SBC_MODE_MONO;<br />                   sample_spec->channels = 1;<br />                   break;<br />               default:<br />                   pa_assert_not_reached();<br />           }<br /><br />           switch (config->allocation_method) {<!-- --><br />               case SBC_ALLOCATION_LOUDNESS:<br />                   sbc_info->allocation = SBC_AM_LOUDNESS;<br />                   break;<br />               case SBC_ALLOCATION_SNR:<br />                   sbc_info->allocation = SBC_AM_SNR;<br />                   break;<br />               default:<br />                   pa_assert_not_reached();<br />           }<br /><br />           switch (config->subbands) {<!-- --><br />               case SBC_SUBBANDS_4:<br />                   sbc_info->subbands = SBC_SB_4;<br />                   break;<br />               case SBC_SUBBANDS_8:<br />                   sbc_info->subbands = SBC_SB_8;<br />                   break;<br />               default:<br />                   pa_assert_not_reached();<br />           }<br /><br />           switch (config->block_length) {<!-- --><br />               case SBC_BLOCK_LENGTH_4:<br />                   sbc_info->blocks = SBC_BLK_4;<br />                   break;<br />               case SBC_BLOCK_LENGTH_8:<br />                   sbc_info->blocks = SBC_BLK_8;<br />                   break;<br />               case SBC_BLOCK_LENGTH_12:<br />                   sbc_info->blocks = SBC_BLK_12;<br />                   break;<br />               case SBC_BLOCK_LENGTH_16:<br />                   sbc_info->blocks = SBC_BLK_16;<br />                   break;<br />               default:<br />                   pa_assert_not_reached();<br />           }<br /><br />           sbc_info->min_bitpool = config->min_bitpool;<br />           sbc_info->max_bitpool = config->max_bitpool;<br /><br />           /* Set minimum bitpool for source to get the maximum<br />  possible block_size<br />            * in get_block_size() function. This block_size is<br />  length of buffer used<br />            * for decoded audio data and so is inversely<br />  proportional to frame length<br />            * which depends on bitpool value. Bitpool is controlled<br />  by other side from<br />            * range [min_bitpool, max_bitpool]. */<br />           sbc_info->initial_bitpool = for_encoding ?<br />  sbc_info->max_bitpool : sbc_info->min_bitpool;<br /><br />           set_params(sbc_info);<br /><br />           pa_log_info("SBC parameters: allocation=%s, subbands=%u,<br />  blocks=%u, mode=%s bitpool=%u codesize=%u frame_length=%u",<br />                       sbc_info->sbc.allocation ? "SNR" :<br />  "Loudness", sbc_info->sbc.subbands ? 8 : 4,<br />                       (sbc_info->sbc.blocks+1)*4,<br />  sbc_info->sbc.mode == SBC_MODE_MONO ? "Mono" :<br />                       sbc_info->sbc.mode == SBC_MODE_DUAL_CHANNEL ?<br />  "DualChannel" :<br />                       sbc_info->sbc.mode == SBC_MODE_STEREO ?<br />  "Stereo" : "JointStereo",<br />                       sbc_info->sbc.bitpool,<br />  (unsigned)sbc_info->codesize, (unsigned)sbc_info->frame_length);<br /><br />           return sbc_info;<br />      }<br /><br />      static void deinit(void *codec_info) {<!-- --><br />           struct sbc_info *sbc_info = (struct sbc_info *) codec_info;<br /><br />           sbc_finish(&sbc_info->sbc);<br />           pa_xfree(sbc_info);<br />      }<br /><br />      static void set_bitpool(struct sbc_info *sbc_info, uint8_t<br />  bitpool) {<!-- --><br />           if (bitpool > sbc_info->max_bitpool)<br />               bitpool = sbc_info->max_bitpool;<br />           else if (bitpool < sbc_info->min_bitpool)<br />               bitpool = sbc_info->min_bitpool;<br /><br />           sbc_info->sbc.bitpool = bitpool;<br /><br />           sbc_info->codesize = sbc_get_codesize(&sbc_info->sbc);<br />           sbc_info->frame_length =<br />  sbc_get_frame_length(&sbc_info->sbc);<br /><br />           pa_log_debug("Bitpool has changed to %u",<br />  sbc_info->sbc.bitpool);<br />      }<br /><br />      static int reset(void *codec_info) {<!-- --><br />           struct sbc_info *sbc_info = (struct sbc_info *) codec_info;<br />           int ret;<br /><br />           ret = sbc_reinit(&sbc_info->sbc, 0);<br />           if (ret != 0) {<!-- --><br />               pa_log_error("SBC reinitialization failed: %d", ret);<br />               return -1;<br />           }<br /><br />           /* sbc_reinit() sets also default parameters, so reset<br />  them back */<br />           set_params(sbc_info);<br /><br />           sbc_info->seq_num = 0;<br />           return 0;<br />      }<br /><br />      static size_t get_block_size(void *codec_info, size_t link_mtu) {<!-- --><br />           struct sbc_info *sbc_info = (struct sbc_info *) codec_info;<br />           size_t rtp_size = sizeof(struct rtp_header) +<br />  sizeof(struct rtp_sbc_payload);<br />           size_t frame_count = (link_mtu - rtp_size) /<br />  sbc_info->frame_length;<br /><br />           /* frame_count is only 4 bit number */<br />           if (frame_count > 15)<br />               frame_count = 15;<br /><br />           return frame_count * sbc_info->codesize;<br />      }<br /><br />      static size_t reduce_encoder_bitrate(void *codec_info, size_t<br />  write_link_mtu) {<!-- --><br />           struct sbc_info *sbc_info = (struct sbc_info *) codec_info;<br />           uint8_t bitpool;<br /><br />           /* Check if bitpool is already at its limit */<br />           if (sbc_info->sbc.bitpool <= SBC_BITPOOL_DEC_LIMIT)<br />               return 0;<br /><br />           bitpool = sbc_info->sbc.bitpool - SBC_BITPOOL_DEC_STEP;<br /><br />           if (bitpool < SBC_BITPOOL_DEC_LIMIT)<br />               bitpool = SBC_BITPOOL_DEC_LIMIT;<br /><br />           if (sbc_info->sbc.bitpool == bitpool)<br />               return 0;<br /><br />           set_bitpool(sbc_info, bitpool);<br />           return get_block_size(codec_info, write_link_mtu);<br />      }<br /><br />      static size_t encode_buffer(void *codec_info, uint32_t<br />  timestamp, const uint8_t *input_buffer, size_t input_size, uint8_t<br />  *output_buffer, size_t output_size, size_t *processed) {<!-- --><br />           struct sbc_info *sbc_info = (struct sbc_info *) codec_info;<br />           struct rtp_header *header;<br />           struct rtp_sbc_payload *payload;<br />           uint8_t *d;<br />           const uint8_t *p;<br />           size_t to_write, to_encode;<br />           uint8_t frame_count;<br /><br />           header = (struct rtp_header*) output_buffer;<br />           payload = (struct rtp_sbc_payload*) (output_buffer +<br />  sizeof(*header));<br /><br />           frame_count = 0;<br /><br />           p = input_buffer;<br />           to_encode = input_size;<br /><br />           d = output_buffer + sizeof(*header) + sizeof(*payload);<br />           to_write = output_size - sizeof(*header) - sizeof(*payload);<br /><br />           /* frame_count is only 4 bit number */<br />           while (PA_LIKELY(to_encode > 0 && to_write > 0 &&<br />  frame_count < 15)) {<!-- --><br />               ssize_t written;<br />               ssize_t encoded;<br /><br />               encoded = sbc_encode(&sbc_info->sbc,<br />                                    p, to_encode,<br />                                    d, to_write,<br />                                    &written);<br /><br />               if (PA_UNLIKELY(encoded <= 0)) {<!-- --><br />                   pa_log_error("SBC encoding error (%li)", (long)<br />  encoded);<br />                   break;<br />               }<br /><br />               if (PA_UNLIKELY(written < 0)) {<!-- --><br />                   pa_log_error("SBC encoding error (%li)", (long)<br />  written);<br />                   break;<br />               }<br /><br />               pa_assert_fp((size_t) encoded <= to_encode);<br />               pa_assert_fp((size_t) encoded == sbc_info->codesize);<br /><br />               pa_assert_fp((size_t) written <= to_write);<br />               pa_assert_fp((size_t) written ==<br />  sbc_info->frame_length);<br /><br />               p += encoded;<br />               to_encode -= encoded;<br /><br />               d += written;<br />               to_write -= written;<br /><br />               frame_count++;<br />           }<br /><br />           PA_ONCE_BEGIN {<!-- --><br />               pa_log_debug("Using SBC codec implementation: %s",<br />  pa_strnull(sbc_get_implementation_info(&sbc_info->sbc)));<br />           } PA_ONCE_END;<br /><br />           if (PA_UNLIKELY(frame_count == 0)) {<!-- --><br />               *processed = 0;<br />               return 0;<br />           }<br /><br />           /* write it to the fifo */<br />           pa_memzero(output_buffer, sizeof(*header) +<br />  sizeof(*payload));<br />           header->v = 2;<br /><br />           /* A2DP spec: "A payload type in the RTP dynamic range<br />  shall be chosen".<br />            * RFC3551 defines the dynamic range to span from 96 to<br />  127, and 96 appears<br />            * to be the most common choice in A2DP implementations. */<br />           header->pt = 96;<br /><br />           header->sequence_number = htons(sbc_info->seq_num++);<br />           header->timestamp = htonl(timestamp);<br />           header->ssrc = htonl(1);<br />           payload->frame_count = frame_count;<br /><br />           *processed = p - input_buffer;<br />           return d - output_buffer;<br />      }<br /><br />      static size_t decode_buffer(void *codec_info, const uint8_t<br />  *input_buffer, size_t input_size, uint8_t *output_buffer, size_t<br />  output_size, size_t *processed) {<!-- --><br />           struct sbc_info *sbc_info = (struct sbc_info *) codec_info;<br /><br />           struct rtp_header *header;<br />           struct rtp_sbc_payload *payload;<br />           const uint8_t *p;<br />           uint8_t *d;<br />           size_t to_write, to_decode;<br />           uint8_t frame_count;<br /><br />           header = (struct rtp_header *) input_buffer;<br />           payload = (struct rtp_sbc_payload*) (input_buffer +<br />  sizeof(*header));<br /><br />           frame_count = payload->frame_count;<br /><br />           /* TODO: Add support for decoding fragmented SBC frames */<br />           if (payload->is_fragmented) {<!-- --><br />               pa_log_error("Unsupported fragmented SBC frame");<br />               *processed = 0;<br />               return 0;<br />           }<br /><br />           p = input_buffer + sizeof(*header) + sizeof(*payload);<br />           to_decode = input_size - sizeof(*header) - sizeof(*payload);<br /><br />           d = output_buffer;<br />           to_write = output_size;<br /><br />           while (PA_LIKELY(to_decode > 0 && to_write > 0 &&<br />  frame_count > 0)) {<!-- --><br />               size_t written;<br />               ssize_t decoded;<br /><br />               decoded = sbc_decode(&sbc_info->sbc,<br />                                    p, to_decode,<br />                                    d, to_write,<br />                                    &written);<br /><br />               if (PA_UNLIKELY(decoded <= 0)) {<!-- --><br />                   pa_log_error("SBC decoding error (%li)", (long)<br />  decoded);<br />                   break;<br />               }<br /><br />               /* Reset frame length, it can be changed due to<br />  bitpool change */<br />               sbc_info->frame_length =<br />  sbc_get_frame_length(&sbc_info->sbc);<br /><br />               pa_assert_fp((size_t) decoded <= to_decode);<br />               pa_assert_fp((size_t) decoded ==<br />  sbc_info->frame_length);<br /><br />               pa_assert_fp((size_t) written <= to_write);<br />               pa_assert_fp((size_t) written == sbc_info->codesize);<br /><br />               p += decoded;<br />               to_decode -= decoded;<br /><br />               d += written;<br />               to_write -= written;<br /><br />               frame_count--;<br />           }<br /><br />           *processed = p - input_buffer;<br />           return d - output_buffer;<br />      }<br /><br />      const pa_a2dp_codec pa_a2dp_codec_sbc = {<!-- --><br />           .name = "sbc",<br />           .description = "SBC",<br />           .id = { A2DP_CODEC_SBC, 0, 0 },<br />           .support_backchannel = false,<br />           .can_accept_capabilities = can_accept_capabilities,<br />           .choose_remote_endpoint = choose_remote_endpoint,<br />           .fill_capabilities = fill_capabilities,<br />           .is_configuration_valid = is_configuration_valid,<br />           .fill_preferred_configuration =<br />  fill_preferred_configuration,<br />           .init = init,<br />           .deinit = deinit,<br />           .reset = reset,<br />           .get_read_block_size = get_block_size,<br />           .get_write_block_size = get_block_size,<br />           .reduce_encoder_bitrate = reduce_encoder_bitrate,<br />           .encode_buffer = encode_buffer,<br />           .decode_buffer = decode_buffer,<br />      };<br /><br />      17.09.2019, 09:34, "Hyperion" <<a href="mailto:h1p8r10n@yandex.com">h1p8r10n@yandex.com</a>>:<br /><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote">      btw here's the updated V12-12 patch in Pali's latest rel95<br />  patchset that applies to PA 13.0.<br /><br />        <a href="http://download.zenwalk.org/x86_64/testing/v12-12-13-zen-bluetooth-Implement-A2DP-codec-switching-and-backchannel-support-.patch">http://download.zenwalk.org/x86_64/testing/v12-12-13-zen-bluetooth-Implement-A2DP-codec-switching-and-backchannel-support-.patch</a><br /><br />      JP<br /><br />      16.09.2019, 09:32, "Hyperion" <<a href="mailto:h1p8r10n@yandex.com">h1p8r10n@yandex.com</a>>:<br /><blockquote class="b4fd5cf2ec92bc68cb898700bb81355fwmi-quote">        Hi,<br /><br />        Following what has already be done in some Android<br />  derivatives, here's a simple patch that extend SBP bitpool<br />  negociation to XQ quality.<br /><br />        According to :<br />        --><br />  <a href="http://soundexpert.org/articles/-/blogs/audio-quality-of-sbc-xq-bluetooth-audio-codec">http://soundexpert.org/articles/-/blogs/audio-quality-of-sbc-xq-bluetooth-audio-codec</a><br /><br />        --> <a href="https://lineageos.org/engineering/Bluetooth-SBC-XQ/">https://lineageos.org/engineering/Bluetooth-SBC-XQ/</a> ,<br />        --> and confirmed by my own experimentation on more than<br />  10 different devices,<br /><br />        here are the features of the (very simple and non<br />  intrusive) patch :<br />        - allow to use bitpool 76 on devices that support it, aka<br />  SBC XQ<br />        - harmless for devices limited to bitpool 53<br />        - deprecates the need for APTX & APTX HD support, which<br />  are not better than SBC XQ, are not Open Source, and less<br />  supported by devices<br /><br />        This patch will be superseded by multi-profiles Pali Rohar<br />  A2DP stack implementation, when it's ready for production.<br />  Thanks to Pali for the help testing many codec parameters.<br /><br />        Let me know if I have to clone the git to push my patch,<br />  or if a regular PA dev could do it.<br /><br />        All the best<br />        JP<br /><br />        diff -rNaud<br />  pulseaudio-13.0/src/modules/bluetooth/a2dp-codec-sbc.c<br />  pulseaudio-13.0-new/src/modules/bluetooth/a2dp-codec-sbc.c<br />        --- pulseaudio-13.0/src/modules/bluetooth/a2dp-codec-sbc.c<br />  <span class="177d5a4333ac019606de889e143743a1wmi-callto">2019-09-13 15</span>:20:03.<span class="177d5a4333ac019606de889e143743a1wmi-callto">000000000</span> +0200<br />        +++<br />  pulseaudio-13.0-new/src/modules/bluetooth/a2dp-codec-sbc.c<br />  <span class="177d5a4333ac019606de889e143743a1wmi-callto">2019-09-16 08</span>:57:50.<span class="177d5a4333ac019606de889e143743a1wmi-callto">363122019</span> +0200<br />        @@ -290,10 +290,10 @@<br />                 return 0;<br />             }<br /><br />        - if (capabilities->allocation_method &<br />  SBC_ALLOCATION_LOUDNESS)<br />        - config->allocation_method = SBC_ALLOCATION_LOUDNESS;<br />        - else if (capabilities->allocation_method &<br />  SBC_ALLOCATION_SNR)<br />        + if (capabilities->allocation_method & SBC_ALLOCATION_SNR)<br />                 config->allocation_method = SBC_ALLOCATION_SNR;<br />        + else if (capabilities->allocation_method &<br />  SBC_ALLOCATION_LOUDNESS)<br />        + config->allocation_method = SBC_ALLOCATION_LOUDNESS;<br />             else {<!-- --><br />                 pa_log_error("No supported allocation method");<br />                 return 0;<br />        diff -rNaud<br />  pulseaudio-13.0/src/modules/bluetooth/a2dp-codecs.h<br />  pulseaudio-13.0-new/src/modules/bluetooth/a2dp-codecs.h<br />        --- pulseaudio-13.0/src/modules/bluetooth/a2dp-codecs.h<br />  <span class="177d5a4333ac019606de889e143743a1wmi-callto">2019-09-13 15</span>:20:03.<span class="177d5a4333ac019606de889e143743a1wmi-callto">000000000</span> +0200<br />        +++<br />  pulseaudio-13.0-new/src/modules/bluetooth/a2dp-codecs.h<br />  <span class="177d5a4333ac019606de889e143743a1wmi-callto">2019-09-16 08</span>:44:20.<span class="177d5a4333ac019606de889e143743a1wmi-callto">382086305</span> +0200<br />        @@ -61,14 +61,11 @@<br />          * Allocation method = Loudness<br />          * Subbands = 8<br />          */<br />        -#define SBC_BITPOOL_MQ_MONO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">44100 19</span><br />        -#define SBC_BITPOOL_MQ_MONO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">48000 18</span><br />        -#define SBC_BITPOOL_MQ_JOINT_STEREO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">44100 35</span><br />        -#define SBC_BITPOOL_MQ_JOINT_STEREO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">48000 33</span><br />        -#define SBC_BITPOOL_HQ_MONO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">44100 31</span><br />        -#define SBC_BITPOOL_HQ_MONO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">48000 29</span><br />        -#define SBC_BITPOOL_HQ_JOINT_STEREO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">44100 53</span><br />        -#define SBC_BITPOOL_HQ_JOINT_STEREO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">48000 51</span><br />        +<br />        +#define SBC_BITPOOL_HQ_MONO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">44100 38</span><br />        +#define SBC_BITPOOL_HQ_MONO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">48000 38</span><br />        +#define SBC_BITPOOL_HQ_JOINT_STEREO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">44100 76</span><br />        +#define SBC_BITPOOL_HQ_JOINT_STEREO_<span class="177d5a4333ac019606de889e143743a1wmi-callto">48000 76</span><br /><br />         #define MPEG_CHANNEL_MODE_MONO (1 << 3)<br />         #define MPEG_CHANNEL_MODE_DUAL_CHANNEL (1 << 2)<br /><br />        _______________________________________________<br />        pulseaudio-discuss mailing list<br />        <a href="mailto:pulseaudio-discuss@lists.freedesktop.org">pulseaudio-discuss@lists.freedesktop.org</a><br />        <a href="https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss">https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss</a><br /></blockquote></blockquote>      _______________________________________________<br />      pulseaudio-discuss mailing list<br />      <a href="mailto:pulseaudio-discuss@lists.freedesktop.org">pulseaudio-discuss@lists.freedesktop.org</a><br />      <a href="https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss">https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss</a><br /></blockquote><br />     _______________________________________________<br />     pulseaudio-discuss mailing list<br />     <a href="mailto:pulseaudio-discuss@lists.freedesktop.org">pulseaudio-discuss@lists.freedesktop.org</a><br />     <a href="https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss">https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss</a><br /></blockquote><br />    _______________________________________________<br />    pulseaudio-discuss mailing list<br />    <a href="mailto:pulseaudio-discuss@lists.freedesktop.org">pulseaudio-discuss@lists.freedesktop.org</a><br />    <a href="https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss">https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss</a><br /></blockquote><br />  _______________________________________________<br />  pulseaudio-discuss mailing list<br />  <a href="mailto:pulseaudio-discuss@lists.freedesktop.org">pulseaudio-discuss@lists.freedesktop.org</a><br />  <a href="https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss">https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss</a><br /></blockquote>  _______________________________________________<br />  pulseaudio-discuss mailing list<br />  <a href="mailto:pulseaudio-discuss@lists.freedesktop.org">pulseaudio-discuss@lists.freedesktop.org</a><br />  <a href="https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss">https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss</a><br /></blockquote></blockquote><br /> _______________________________________________<br /> pulseaudio-discuss mailing list<br /> <a href="mailto:pulseaudio-discuss@lists.freedesktop.org">pulseaudio-discuss@lists.freedesktop.org</a><br /> <a href="https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss">https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss</a><br /></blockquote></blockquote><br /><br />-- <br />Sent from Yandex.Mail for mobile</div>