Skip to content

Commit

Permalink
multi-client support
Browse files Browse the repository at this point in the history
  • Loading branch information
borine committed Jun 1, 2024
1 parent 261f184 commit d460cd2
Show file tree
Hide file tree
Showing 31 changed files with 2,061 additions and 39 deletions.
2 changes: 2 additions & 0 deletions .github/iwyu.imp
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@

{ include: [ '<spandsp/plc.h>', private, '<spandsp.h>', public ] },

{ include: [ '<bits/types/struct_itimerspec.h>', private, '<sys/timerfd.h>', public ] },

]
3 changes: 3 additions & 0 deletions .github/spellcheck-wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ BTRH
BTT
bttransport
btusb
# aspell considers PIPE_BUF to be 2 words :(
BUF
CCE
CIEV
CIND
Expand All @@ -183,6 +185,7 @@ ENODEV
EP
EPIPE
EPMR
epoll
EQMID
errno
FB
Expand Down
6 changes: 6 additions & 0 deletions doc/bluealsa.8.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ OPTIONS
Without this option, **bluealsa** registers itself as an "org.bluealsa"
D-Bus service. For more information see the EXAMPLES_ below.

-M, --multi-client
Permit multiple clients to connect to the same PCM stream.
Without this option, only one client can connect to a PCM.
With this option, for playback clients, the streams are mixed together;
for capture each client receives a copy of the stream.

-i hciX, --device=hciX
HCI device to use. Can be specified multiple times to select more than one
HCI. Because HCI numbering can change after a system reboot, this option
Expand Down
3 changes: 3 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ bluealsa_SOURCES = \
ba-transport-pcm.c \
bluealsa-dbus.c \
bluealsa-iface.xml \
bluealsa-mix-buffer.c \
bluealsa-pcm-client.c \
bluealsa-pcm-multi.c \
bluez.c \
bluez-iface.xml \
codec-sbc.c \
Expand Down
11 changes: 11 additions & 0 deletions src/a2dp-aac.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "ba-config.h"
#include "ba-transport.h"
#include "ba-transport-pcm.h"
#include "bluealsa-pcm-multi.h"
#include "io.h"
#include "rtp.h"
#include "utils.h"
Expand Down Expand Up @@ -195,6 +196,11 @@ void *a2dp_aac_enc_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

rtp_header_t *rtp_header;
/* initialize RTP header and get anchor for payload */
uint8_t *rtp_payload = rtp_a2dp_init(bt.data, &rtp_header, NULL, 0);
Expand Down Expand Up @@ -375,6 +381,11 @@ void *a2dp_aac_dec_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

struct rtp_state rtp = { .synced = false };
/* RTP clock frequency equal to 90kHz */
rtp_state_init(&rtp, samplerate, 90000);
Expand Down
11 changes: 11 additions & 0 deletions src/a2dp-aptx-hd.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "ba-config.h"
#include "ba-transport.h"
#include "ba-transport-pcm.h"
#include "bluealsa-pcm-multi.h"
#include "codec-aptx.h"
#include "io.h"
#include "rtp.h"
Expand Down Expand Up @@ -67,6 +68,11 @@ void *a2dp_aptx_hd_enc_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

rtp_header_t *rtp_header;
/* initialize RTP header and get anchor for payload */
uint8_t *rtp_payload = rtp_a2dp_init(bt.data, &rtp_header, NULL, 0);
Expand Down Expand Up @@ -200,6 +206,11 @@ void *a2dp_aptx_hd_dec_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

struct rtp_state rtp = { .synced = false };
/* RTP clock frequency equal to audio samplerate */
rtp_state_init(&rtp, samplerate, samplerate);
Expand Down
11 changes: 11 additions & 0 deletions src/a2dp-aptx.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "ba-config.h"
#include "ba-transport.h"
#include "ba-transport-pcm.h"
#include "bluealsa-pcm-multi.h"
#include "codec-aptx.h"
#include "io.h"
#include "shared/a2dp-codecs.h"
Expand Down Expand Up @@ -64,6 +65,11 @@ void *a2dp_aptx_enc_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

debug_transport_pcm_thread_loop(t_pcm, "START");
for (ba_transport_pcm_state_set_running(t_pcm);;) {

Expand Down Expand Up @@ -178,6 +184,11 @@ void *a2dp_aptx_dec_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

debug_transport_pcm_thread_loop(t_pcm, "START");
for (ba_transport_pcm_state_set_running(t_pcm);;) {

Expand Down
11 changes: 11 additions & 0 deletions src/a2dp-faststream.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "ba-config.h"
#include "ba-transport.h"
#include "ba-transport-pcm.h"
#include "bluealsa-pcm-multi.h"
#include "codec-sbc.h"
#include "io.h"
#include "shared/a2dp-codecs.h"
Expand Down Expand Up @@ -67,6 +68,11 @@ void *a2dp_faststream_enc_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

debug_transport_pcm_thread_loop(t_pcm, "START");
for (ba_transport_pcm_state_set_running(t_pcm);;) {

Expand Down Expand Up @@ -187,6 +193,11 @@ void *a2dp_faststream_dec_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

debug_transport_pcm_thread_loop(t_pcm, "START");
for (ba_transport_pcm_state_set_running(t_pcm);;) {

Expand Down
11 changes: 11 additions & 0 deletions src/a2dp-ldac.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "ba-transport.h"
#include "ba-transport-pcm.h"
#include "ba-config.h"
#include "bluealsa-pcm-multi.h"
#include "io.h"
#include "rtp.h"
#include "utils.h"
Expand Down Expand Up @@ -92,6 +93,11 @@ void *a2dp_ldac_enc_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

rtp_header_t *rtp_header;
rtp_media_header_t *rtp_media_header;
/* initialize RTP headers and get anchor for payload */
Expand Down Expand Up @@ -249,6 +255,11 @@ void *a2dp_ldac_dec_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

struct rtp_state rtp = { .synced = false };
/* RTP clock frequency equal to audio samplerate */
rtp_state_init(&rtp, samplerate, samplerate);
Expand Down
11 changes: 11 additions & 0 deletions src/a2dp-mpeg.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "ba-config.h"
#include "ba-transport.h"
#include "ba-transport-pcm.h"
#include "bluealsa-pcm-multi.h"
#include "io.h"
#include "rtp.h"
#include "utils.h"
Expand Down Expand Up @@ -151,6 +152,11 @@ void *a2dp_mp3_enc_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

rtp_header_t *rtp_header;
rtp_mpeg_audio_header_t *rtp_mpeg_audio_header;
/* initialize RTP headers and get anchor for payload */
Expand Down Expand Up @@ -336,6 +342,11 @@ void *a2dp_mpeg_dec_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

struct rtp_state rtp = { .synced = false };
/* RTP clock frequency equal to 90kHz */
rtp_state_init(&rtp, samplerate, 90000);
Expand Down
11 changes: 11 additions & 0 deletions src/a2dp-sbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "ba-transport.h"
#include "ba-transport-pcm.h"
#include "ba-config.h"
#include "bluealsa-pcm-multi.h"
#include "codec-sbc.h"
#include "io.h"
#include "rtp.h"
Expand Down Expand Up @@ -94,6 +95,11 @@ void *a2dp_sbc_enc_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

rtp_header_t *rtp_header;
rtp_media_header_t *rtp_media_header;

Expand Down Expand Up @@ -237,6 +243,11 @@ void *a2dp_sbc_dec_thread(struct ba_transport_pcm *t_pcm) {
goto fail_ffb;
}

/* start multi client thread if required. */
if (t_pcm->multi &&
!bluealsa_pcm_multi_init(t_pcm->multi, pcm.nmemb))
goto fail_ffb;

struct rtp_state rtp = { .synced = false };
/* RTP clock frequency equal to audio samplerate */
rtp_state_init(&rtp, samplerate, samplerate);
Expand Down
2 changes: 2 additions & 0 deletions src/ba-config.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ struct ba_config config = {

.disable_realtek_usb_fix = false,

.multi_enabled = false,

/* CVSD is a mandatory codec */
.hfp.codecs.cvsd = true,
#if ENABLE_MSBC
Expand Down
3 changes: 3 additions & 0 deletions src/ba-config.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ struct ba_config {
/* disable alt-3 MTU for mSBC with Realtek USB adapters */
bool disable_realtek_usb_fix;

/* Is multi client support enabled? */
bool multi_enabled;

struct {

/* available HFP codecs */
Expand Down
23 changes: 21 additions & 2 deletions src/ba-transport-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "ba-rfcomm.h"
#include "ba-transport.h"
#include "bluealsa-dbus.h"
#include "bluealsa-pcm-multi.h"
#include "bluez-iface.h"
#include "bluez.h"
#include "dbus.h"
Expand Down Expand Up @@ -77,6 +78,9 @@ int transport_pcm_init(
pcm->pipe[0] = -1;
pcm->pipe[1] = -1;

pcm->multi = NULL;
pcm->paused = false;

pcm->volume[0].level = config.volume_init_level;
pcm->volume[1].level = config.volume_init_level;
ba_transport_pcm_volume_set(&pcm->volume[0], NULL, NULL, NULL);
Expand All @@ -97,6 +101,9 @@ int transport_pcm_init(
t->d->ba_dbus_path, transport_get_dbus_path_type(t->profile),
mode == BA_TRANSPORT_PCM_MODE_SOURCE ? "source" : "sink");

if (bluealsa_pcm_multi_enabled(t))
pcm->multi = bluealsa_pcm_multi_create(pcm);

return 0;
}

Expand All @@ -121,6 +128,11 @@ void transport_pcm_free(
g_hash_table_unref(pcm->delay_adjustments);
g_free(pcm->ba_dbus_path);

if (pcm->multi != NULL) {
bluealsa_pcm_multi_free(pcm->multi);
pcm->multi = NULL;
}

}

/**
Expand Down Expand Up @@ -241,6 +253,10 @@ void ba_transport_pcm_thread_cleanup(struct ba_transport_pcm *pcm) {
ba_transport_stop_async(t);
pthread_mutex_unlock(&t->bt_fd_mtx);

/* Stop multi client thread if required. */
if (pcm->multi)
bluealsa_pcm_multi_reset(pcm->multi);

/* Release BT socket file descriptor duplicate created either in the
* ba_transport_pcm_start() function or in the IO thread itself. */
ba_transport_pcm_bt_release(pcm);
Expand Down Expand Up @@ -525,7 +541,7 @@ int ba_transport_pcm_drop(struct ba_transport_pcm *pcm) {
pthread_mutex_unlock(&pcm->mutex);
#endif

if (io_pcm_flush(pcm) == -1)
if (!pcm->multi && io_pcm_flush(pcm) == -1)
return -1;

int rv = ba_transport_pcm_signal_send(pcm, BA_TRANSPORT_PCM_SIGNAL_DROP);
Expand Down Expand Up @@ -711,7 +727,10 @@ int ba_transport_pcm_get_delay(const struct ba_transport_pcm *pcm) {
if (t->profile & BA_TRANSPORT_PROFILE_MASK_SCO)
delay += 10;

return delay;
if (pcm->multi)
return delay + pcm->multi->delay;
else
return delay;
}

int16_t ba_transport_pcm_delay_adjustment_get(
Expand Down
3 changes: 3 additions & 0 deletions src/ba-transport-pcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ struct ba_transport_pcm {
char *ba_dbus_path;
bool ba_dbus_exported;

/* Multi-client stream support */
struct bluealsa_pcm_multi *multi;

};

int transport_pcm_init(
Expand Down
Loading

0 comments on commit d460cd2

Please sign in to comment.