summaryrefslogtreecommitdiffstats
path: root/plugins/lib/bluealsa/hal-bluealsa-transports.c
diff options
context:
space:
mode:
authorThierry Bultel <thierry.bultel@iot.bzh>2018-12-05 14:05:10 +0100
committerThierry Bultel <thierry.bultel@iot.bzh>2018-12-20 16:55:46 +0000
commit01d55ed8cdd01ca4a7b391ca61c80084bd5a6f2f (patch)
treed73ce778a2177e82e07e9d31891a827467fbadd4 /plugins/lib/bluealsa/hal-bluealsa-transports.c
parentdbe555be80dd10bb315b14bbebcb42f8b883e2c9 (diff)
Adds support for bluetooth audio through bluez-alsaguppy_6.99.4guppy_6.99.3guppy/6.99.4guppy/6.99.36.99.46.99.3
Implements a new bluealsa plugin to the HAL manager, reacting to the changes of the available transports. This plugin is linked with the new bluealsa.so shared library. New transports (SCO & A2DP) result in softmixer invocations of the "attach" verb, that creates the new capture (eg, A2DP capture from bluealsa ioplug PCM, SCO microphone capture), playbacks (SCO playback to a softmixer zone, and SCO output to bluealsa iogplug PCM). When a transport disappears, the hal manager calls the transaction deletion verb that will tell the softmixer to remove the created streams and associated objects. Change-Id: I36037a4f14ef7fee38070fc0df66c40b4ce46e8b Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
Diffstat (limited to 'plugins/lib/bluealsa/hal-bluealsa-transports.c')
-rw-r--r--plugins/lib/bluealsa/hal-bluealsa-transports.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/plugins/lib/bluealsa/hal-bluealsa-transports.c b/plugins/lib/bluealsa/hal-bluealsa-transports.c
new file mode 100644
index 0000000..2c58023
--- /dev/null
+++ b/plugins/lib/bluealsa/hal-bluealsa-transports.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2018 "IoT.bzh"
+ * Author : Thierry Bultel <thierry.bultel@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <malloc.h>
+
+#include "hal-bluealsa-transports.h"
+
+
+static bool halBlueAlsaTransportMatch(
+ const struct ba_msg_transport * transport1,
+ const struct ba_msg_transport * transport2);
+
+int halBlueAlsaTransportsInit(bluealsa_transport_t * list) {
+ CDS_INIT_LIST_HEAD(&list->list);
+ return 0;
+}
+
+bluealsa_transport_t * halBlueAlsaTransportsAdd(
+ const bluealsa_watch * watch,
+ bluealsa_transport_t * list,
+ const struct ba_msg_transport * transport) {
+
+ bluealsa_transport_t * newTransport = (bluealsa_transport_t*) calloc(1, sizeof(bluealsa_transport_t));
+ if (newTransport == NULL)
+ goto fail;
+
+ memcpy(&newTransport->transport, transport, sizeof(struct ba_msg_transport));
+
+ newTransport->watch = watch;
+
+ CDS_INIT_LIST_HEAD(&newTransport->list);
+ cds_list_add(&newTransport->list, &list->list);
+
+ return newTransport;
+fail:
+ return NULL;
+
+}
+
+bool halBlueAlsaTransportFind(
+ const bluealsa_watch * watch,
+ bluealsa_transport_t * list,
+ const struct ba_msg_transport * transport) {
+
+ bluealsa_transport_t *tmp;
+ bool found = false;
+ cds_list_for_each_entry(tmp, &list->list, list) {
+ struct ba_msg_transport * _transport = &tmp->transport;
+
+ if (watch != tmp->watch)
+ continue;
+
+ if (!halBlueAlsaTransportMatch(_transport, transport))
+ continue;
+
+ found = true;
+ break;
+ }
+ return found;
+}
+
+
+int halBlueAlsaTransportUpdate(
+ const bluealsa_watch * watch,
+ bluealsa_transport_t * list,
+ const struct ba_msg_transport *transports,
+ size_t nb,
+ transport_destructor destructor) {
+
+ bluealsa_transport_t *transport, *sav;
+
+ cds_list_for_each_entry_safe(transport, sav, &list->list, list) {
+ struct ba_msg_transport * ba_transport1 = &transport->transport;
+
+ if (watch != transport->watch)
+ continue;
+
+ bool found = false;
+
+ for (int ix = 0; ix<nb; ix++) {
+ const struct ba_msg_transport * ba_transport2 = &transports[ix];
+
+ if (halBlueAlsaTransportMatch(ba_transport1, ba_transport2)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ char transportS[HAL_BLUEALSA_TRANSPORT_LEN_MAX];
+
+ AFB_ApiInfo(watch->plugin->api,
+ "Unregister transport %s",
+ halBlueAlsaTransportAsString(transportS, HAL_BLUEALSA_TRANSPORT_LEN_MAX, &transport->transport));
+
+ cds_list_del(&transport->list);
+ if (destructor) {
+ destructor(transport);
+ }
+
+ free(transport->transactionUidS);
+ free(transport);
+
+ }
+
+ return 0;
+}
+
+
+static bool halBlueAlsaTransportMatch(const struct ba_msg_transport * transport1, const struct ba_msg_transport * transport2) {
+ bool ret = false;
+
+ if (transport1->type != transport2->type)
+ goto done;
+
+ if (transport1->stream != transport2->stream)
+ goto done;
+
+ if (bacmp(&transport1->addr, &transport2->addr) != 0) {
+ goto done;
+ }
+ ret = true;
+done:
+ return ret;
+}
+
+
+char * halBlueAlsaTransportAsString(char * buff, size_t len, const struct ba_msg_transport * transport) {
+ char addr[18];
+
+ ba2str(&transport->addr, addr);
+ snprintf(buff, len, "%s,%s,%s", addr,
+ transport->type == BA_PCM_TYPE_A2DP?"a2dp":"sco",
+ transport->stream == BA_PCM_STREAM_PLAYBACK?"playback":"capture");
+
+ return buff;
+}