20141103 snapshot
This commit is contained in:
parent
96714d4b6b
commit
195da1d2e4
@ -1,74 +0,0 @@
|
||||
From def5cd8f4a7e29dd52c93308bfcaf9d0a33b5232 Mon Sep 17 00:00:00 2001
|
||||
From: Wim Taymans <wtaymans@redhat.com>
|
||||
Date: Mon, 1 Sep 2014 10:43:46 +0200
|
||||
Subject: [PATCH 1/3] bluez5-device: use get_profile_direction
|
||||
|
||||
Use the get_profile_direction() helper function to decide when to add a
|
||||
source and a sink instead of enumerating profiles.
|
||||
---
|
||||
src/modules/bluetooth/module-bluez5-device.c | 32 +++++++++++++---------------
|
||||
1 file changed, 15 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
|
||||
index 48e498b..15731d1 100644
|
||||
--- a/src/modules/bluetooth/module-bluez5-device.c
|
||||
+++ b/src/modules/bluetooth/module-bluez5-device.c
|
||||
@@ -1210,6 +1210,19 @@ static int setup_transport(struct userdata *u) {
|
||||
}
|
||||
|
||||
/* Run from main thread */
|
||||
+static pa_direction_t get_profile_direction(pa_bluetooth_profile_t p) {
|
||||
+ static const pa_direction_t profile_direction[] = {
|
||||
+ [PA_BLUETOOTH_PROFILE_A2DP_SINK] = PA_DIRECTION_OUTPUT,
|
||||
+ [PA_BLUETOOTH_PROFILE_A2DP_SOURCE] = PA_DIRECTION_INPUT,
|
||||
+ [PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
|
||||
+ [PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
|
||||
+ [PA_BLUETOOTH_PROFILE_OFF] = 0
|
||||
+ };
|
||||
+
|
||||
+ return profile_direction[p];
|
||||
+}
|
||||
+
|
||||
+/* Run from main thread */
|
||||
static int init_profile(struct userdata *u) {
|
||||
int r = 0;
|
||||
pa_assert(u);
|
||||
@@ -1220,13 +1233,11 @@ static int init_profile(struct userdata *u) {
|
||||
|
||||
pa_assert(u->transport);
|
||||
|
||||
- if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK || u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT ||
|
||||
- u->profile == PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY)
|
||||
+ if (get_profile_direction (u->profile) & PA_DIRECTION_OUTPUT)
|
||||
if (add_sink(u) < 0)
|
||||
r = -1;
|
||||
|
||||
- if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE || u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT ||
|
||||
- u->profile == PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY)
|
||||
+ if (get_profile_direction (u->profile) & PA_DIRECTION_INPUT)
|
||||
if (add_source(u) < 0)
|
||||
r = -1;
|
||||
|
||||
@@ -1546,19 +1557,6 @@ static char *cleanup_name(const char *name) {
|
||||
}
|
||||
|
||||
/* Run from main thread */
|
||||
-static pa_direction_t get_profile_direction(pa_bluetooth_profile_t p) {
|
||||
- static const pa_direction_t profile_direction[] = {
|
||||
- [PA_BLUETOOTH_PROFILE_A2DP_SINK] = PA_DIRECTION_OUTPUT,
|
||||
- [PA_BLUETOOTH_PROFILE_A2DP_SOURCE] = PA_DIRECTION_INPUT,
|
||||
- [PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
|
||||
- [PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT,
|
||||
- [PA_BLUETOOTH_PROFILE_OFF] = 0
|
||||
- };
|
||||
-
|
||||
- return profile_direction[p];
|
||||
-}
|
||||
-
|
||||
-/* Run from main thread */
|
||||
static pa_available_t get_port_availability(struct userdata *u, pa_direction_t direction) {
|
||||
pa_available_t result = PA_AVAILABLE_NO;
|
||||
unsigned i;
|
||||
--
|
||||
2.1.0
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
From 91164da48032b078783defaa3cf1f1e173525af0 Mon Sep 17 00:00:00 2001
|
||||
From: Wim Taymans <wtaymans@redhat.com>
|
||||
Date: Mon, 1 Sep 2014 13:12:27 +0200
|
||||
Subject: [PATCH 2/3] bluez5-util: add dispose function
|
||||
|
||||
Add a dispose function to the transport that is called before freeing
|
||||
the transport. Useful for cleaning up extra userdata.
|
||||
---
|
||||
src/modules/bluetooth/bluez5-util.c | 2 ++
|
||||
src/modules/bluetooth/bluez5-util.h | 2 ++
|
||||
2 files changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c
|
||||
index 1ee2f33..50f977e 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.c
|
||||
+++ b/src/modules/bluetooth/bluez5-util.c
|
||||
@@ -205,6 +205,8 @@ void pa_bluetooth_transport_unlink(pa_bluetooth_transport *t) {
|
||||
void pa_bluetooth_transport_free(pa_bluetooth_transport *t) {
|
||||
pa_assert(t);
|
||||
|
||||
+ if (t->dispose)
|
||||
+ t->dispose (t);
|
||||
pa_bluetooth_transport_unlink(t);
|
||||
|
||||
pa_xfree(t->owner);
|
||||
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
||||
index 8db4a17..fde2e78 100644
|
||||
--- a/src/modules/bluetooth/bluez5-util.h
|
||||
+++ b/src/modules/bluetooth/bluez5-util.h
|
||||
@@ -60,6 +60,7 @@ typedef enum pa_bluetooth_transport_state {
|
||||
|
||||
typedef int (*pa_bluetooth_transport_acquire_cb)(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu);
|
||||
typedef void (*pa_bluetooth_transport_release_cb)(pa_bluetooth_transport *t);
|
||||
+typedef void (*pa_bluetooth_transport_dispose_cb)(pa_bluetooth_transport *t);
|
||||
|
||||
struct pa_bluetooth_transport {
|
||||
pa_bluetooth_device *device;
|
||||
@@ -76,6 +77,7 @@ struct pa_bluetooth_transport {
|
||||
|
||||
pa_bluetooth_transport_acquire_cb acquire;
|
||||
pa_bluetooth_transport_release_cb release;
|
||||
+ pa_bluetooth_transport_dispose_cb dispose;
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
--
|
||||
2.1.0
|
||||
|
||||
@ -1,490 +0,0 @@
|
||||
From 682329bb2fc4dc337bf980aae86aa9fa1b6608ab Mon Sep 17 00:00:00 2001
|
||||
From: Wim Taymans <wtaymans@redhat.com>
|
||||
Date: Mon, 1 Sep 2014 15:18:22 +0200
|
||||
Subject: [PATCH 3/3] backend-native: add a new native headset backend
|
||||
|
||||
Add a simple native headset backend that implements support for the
|
||||
blutooth HSP profile.
|
||||
This allows pulseaudio to output audio to a Headset using the HSP profile.
|
||||
|
||||
Make the native backend the default.
|
||||
---
|
||||
configure.ac | 6 +-
|
||||
src/modules/bluetooth/backend-native.c | 443 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 446 insertions(+), 3 deletions(-)
|
||||
create mode 100644 src/modules/bluetooth/backend-native.c
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 74bea71..9a595cb 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -1032,14 +1032,14 @@ AM_CONDITIONAL([HAVE_BLUEZ], [test "x$HAVE_BLUEZ" = x1])
|
||||
## Bluetooth Headset profiles backend ##
|
||||
|
||||
AC_ARG_WITH(bluetooth_headset_backend,
|
||||
- AS_HELP_STRING([--with-bluetooth-headset-backend=<ofono|null>],[Backend for Bluetooth headset profiles (ofono)]))
|
||||
+ AS_HELP_STRING([--with-bluetooth-headset-backend=<ofono|native|null>],[Backend for Bluetooth headset profiles (native)]))
|
||||
if test -z "$with_bluetooth_headset_backend" ; then
|
||||
- BLUETOOTH_HEADSET_BACKEND=ofono
|
||||
+ BLUETOOTH_HEADSET_BACKEND=native
|
||||
else
|
||||
BLUETOOTH_HEADSET_BACKEND=$with_bluetooth_headset_backend
|
||||
fi
|
||||
|
||||
-AS_IF([test "x$BLUETOOTH_HEADSET_BACKEND" != "xofono" && test "x$BLUETOOTH_HEADSET_BACKEND" != "xnull"],
|
||||
+AS_IF([test "x$BLUETOOTH_HEADSET_BACKEND" != "xofono" && test "x$BLUETOOTH_HEADSET_BACKEND" != "xnull" && test "x$BLUETOOTH_HEADSET_BACKEND" != "xnative"],
|
||||
[AC_MSG_ERROR([*** Invalid Bluetooth Headset backend])])
|
||||
|
||||
AC_SUBST(BLUETOOTH_HEADSET_BACKEND)
|
||||
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
||||
new file mode 100644
|
||||
index 0000000..b3c4220
|
||||
--- /dev/null
|
||||
+++ b/src/modules/bluetooth/backend-native.c
|
||||
@@ -0,0 +1,443 @@
|
||||
+/***
|
||||
+ This file is part of PulseAudio.
|
||||
+
|
||||
+ Copyright 2014 Wim Taymans <wim.taymans at gmail.com>
|
||||
+
|
||||
+ PulseAudio is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU Lesser General Public License as
|
||||
+ published by the Free Software Foundation; either version 2.1 of the
|
||||
+ License, or (at your option) any later version.
|
||||
+
|
||||
+ PulseAudio is distributed in the hope that it will be useful, but
|
||||
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with PulseAudio; if not, write to the Free Software
|
||||
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
+ USA.
|
||||
+***/
|
||||
+
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+#include <config.h>
|
||||
+#endif
|
||||
+
|
||||
+#include <pulsecore/shared.h>
|
||||
+#include <pulsecore/core-error.h>
|
||||
+#include <pulsecore/core-util.h>
|
||||
+#include <pulsecore/dbus-shared.h>
|
||||
+#include <pulsecore/log.h>
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/socket.h>
|
||||
+
|
||||
+#include <bluetooth/bluetooth.h>
|
||||
+#include <bluetooth/sco.h>
|
||||
+
|
||||
+#include "bluez5-util.h"
|
||||
+
|
||||
+struct pa_bluetooth_backend {
|
||||
+ pa_core *core;
|
||||
+ pa_dbus_connection *connection;
|
||||
+ pa_bluetooth_discovery *discovery;
|
||||
+
|
||||
+ PA_LLIST_HEAD(pa_dbus_pending, pending);
|
||||
+};
|
||||
+
|
||||
+struct transport_rfcomm {
|
||||
+ int rfcomm_fd;
|
||||
+ pa_io_event *rfcomm_io;
|
||||
+ pa_mainloop_api *mainloop;
|
||||
+};
|
||||
+
|
||||
+#define BLUEZ_SERVICE "org.bluez"
|
||||
+#define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE ".MediaTransport1"
|
||||
+
|
||||
+#define BLUEZ_ERROR_NOT_SUPPORTED "org.bluez.Error.NotSupported"
|
||||
+
|
||||
+#define BLUEZ_PROFILE_MANAGER_INTERFACE BLUEZ_SERVICE ".ProfileManager1"
|
||||
+#define BLUEZ_PROFILE_INTERFACE BLUEZ_SERVICE ".Profile1"
|
||||
+
|
||||
+#define HSP_AG_PROFILE "/Profile/HSPAGProfile"
|
||||
+
|
||||
+#define PROFILE_INTROSPECT_XML \
|
||||
+ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
|
||||
+ "<node>" \
|
||||
+ " <interface name=\"" BLUEZ_PROFILE_INTERFACE "\">" \
|
||||
+ " <method name=\"Release\">" \
|
||||
+ " </method>" \
|
||||
+ " <method name=\"RequestDisconnection\">" \
|
||||
+ " <arg name=\"device\" direction=\"in\" type=\"o\"/>" \
|
||||
+ " </method>" \
|
||||
+ " <method name=\"NewConnection\">" \
|
||||
+ " <arg name=\"device\" direction=\"in\" type=\"o\"/>" \
|
||||
+ " <arg name=\"fd\" direction=\"in\" type=\"h\"/>" \
|
||||
+ " <arg name=\"opts\" direction=\"in\" type=\"a{sv}\"/>" \
|
||||
+ " </method>" \
|
||||
+ " </interface>" \
|
||||
+ " <interface name=\"org.freedesktop.DBus.Introspectable\">" \
|
||||
+ " <method name=\"Introspect\">" \
|
||||
+ " <arg name=\"data\" type=\"s\" direction=\"out\"/>" \
|
||||
+ " </method>" \
|
||||
+ " </interface>" \
|
||||
+ "</node>"
|
||||
+
|
||||
+static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_backend *backend, DBusMessage *m,
|
||||
+ DBusPendingCallNotifyFunction func, void *call_data) {
|
||||
+ pa_dbus_pending *p;
|
||||
+ DBusPendingCall *call;
|
||||
+
|
||||
+ pa_assert(backend);
|
||||
+ pa_assert(m);
|
||||
+
|
||||
+ pa_assert_se(dbus_connection_send_with_reply(pa_dbus_connection_get(backend->connection), m, &call, -1));
|
||||
+
|
||||
+ p = pa_dbus_pending_new(pa_dbus_connection_get(backend->connection), m, call, backend, call_data);
|
||||
+ PA_LLIST_PREPEND(pa_dbus_pending, backend->pending, p);
|
||||
+ dbus_pending_call_set_notify(call, func, p, NULL);
|
||||
+
|
||||
+ return p;
|
||||
+}
|
||||
+
|
||||
+static int bluez5_sco_acquire_cb(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu) {
|
||||
+ pa_bluetooth_device *d = t->device;
|
||||
+ struct sockaddr_sco addr;
|
||||
+ int err, i;
|
||||
+ int sock;
|
||||
+ bdaddr_t src;
|
||||
+ bdaddr_t dst;
|
||||
+ const char *src_addr, *dst_addr;
|
||||
+
|
||||
+ src_addr = d->adapter->address;
|
||||
+ dst_addr = d->address;
|
||||
+
|
||||
+ for (i = 5; i >= 0; i--, src_addr += 3)
|
||||
+ src.b[i] = strtol(src_addr, NULL, 16);
|
||||
+ for (i = 5; i >= 0; i--, dst_addr += 3)
|
||||
+ dst.b[i] = strtol(dst_addr, NULL, 16);
|
||||
+
|
||||
+ sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
|
||||
+ if (sock < 0) {
|
||||
+ pa_log_error("socket(SEQPACKET, SCO) %s", pa_cstrerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ memset(&addr, 0, sizeof(addr));
|
||||
+ addr.sco_family = AF_BLUETOOTH;
|
||||
+ bacpy(&addr.sco_bdaddr, &src);
|
||||
+
|
||||
+ if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
+ pa_log_error("bind(): %s", pa_cstrerror(errno));
|
||||
+ goto fail_close;
|
||||
+ }
|
||||
+
|
||||
+ memset(&addr, 0, sizeof(addr));
|
||||
+ addr.sco_family = AF_BLUETOOTH;
|
||||
+ bacpy(&addr.sco_bdaddr, &dst);
|
||||
+
|
||||
+ pa_log_info ("doing connect\n");
|
||||
+ err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
|
||||
+ if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
|
||||
+ pa_log_error("connect(): %s", pa_cstrerror(errno));
|
||||
+ goto fail_close;
|
||||
+ }
|
||||
+
|
||||
+ if (imtu)
|
||||
+ *imtu = 48;
|
||||
+
|
||||
+ if (omtu)
|
||||
+ *omtu = 48;
|
||||
+
|
||||
+ return sock;
|
||||
+
|
||||
+fail_close:
|
||||
+ close(sock);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static void bluez5_sco_release_cb(pa_bluetooth_transport *t) {
|
||||
+ pa_log_info("Transport %s released", t->path);
|
||||
+ /* device will close the SCO socket for us */
|
||||
+}
|
||||
+
|
||||
+static void register_profile_reply(DBusPendingCall *pending, void *userdata) {
|
||||
+ DBusMessage *r;
|
||||
+ pa_dbus_pending *p;
|
||||
+ pa_bluetooth_backend *b;
|
||||
+ char *profile;
|
||||
+
|
||||
+ pa_assert(pending);
|
||||
+ pa_assert_se(p = userdata);
|
||||
+ pa_assert_se(b = p->context_data);
|
||||
+ pa_assert_se(profile = p->call_data);
|
||||
+ pa_assert_se(r = dbus_pending_call_steal_reply(pending));
|
||||
+
|
||||
+ if (dbus_message_is_error(r, BLUEZ_ERROR_NOT_SUPPORTED)) {
|
||||
+ pa_log_info("Couldn't register profile %s because it is disabled in BlueZ", profile);
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+ if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
|
||||
+ pa_log_error(BLUEZ_PROFILE_MANAGER_INTERFACE ".RegisterProfile() failed: %s: %s", dbus_message_get_error_name(r),
|
||||
+ pa_dbus_get_error_message(r));
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
+finish:
|
||||
+ dbus_message_unref(r);
|
||||
+
|
||||
+ PA_LLIST_REMOVE(pa_dbus_pending, b->pending, p);
|
||||
+ pa_dbus_pending_free(p);
|
||||
+
|
||||
+ pa_xfree(profile);
|
||||
+}
|
||||
+
|
||||
+static void register_profile(pa_bluetooth_backend *b, const char *profile, const char *uuid) {
|
||||
+ DBusMessage *m;
|
||||
+ DBusMessageIter i, d;
|
||||
+
|
||||
+ pa_log_debug("Registering Profile %s", profile);
|
||||
+
|
||||
+ pa_assert_se(m = dbus_message_new_method_call(BLUEZ_SERVICE, "/org/bluez", BLUEZ_PROFILE_MANAGER_INTERFACE, "RegisterProfile"));
|
||||
+
|
||||
+ dbus_message_iter_init_append(m, &i);
|
||||
+ dbus_message_iter_append_basic(&i, DBUS_TYPE_OBJECT_PATH, &profile);
|
||||
+ dbus_message_iter_append_basic(&i, DBUS_TYPE_STRING, &uuid);
|
||||
+ dbus_message_iter_open_container(&i, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING
|
||||
+ DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &d);
|
||||
+ dbus_message_iter_close_container(&i, &d);
|
||||
+
|
||||
+ send_and_add_to_pending(b, m, register_profile_reply, pa_xstrdup(profile));
|
||||
+}
|
||||
+
|
||||
+static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
|
||||
+ pa_bluetooth_transport *t = userdata;
|
||||
+
|
||||
+ pa_assert(io);
|
||||
+ pa_assert(t);
|
||||
+
|
||||
+ if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) {
|
||||
+ pa_log("Lost RFCOMM connection.");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (events & PA_IO_EVENT_INPUT) {
|
||||
+ char buf[512];
|
||||
+ ssize_t len;
|
||||
+
|
||||
+ len = read (fd, buf, 511);
|
||||
+ buf[len] = 0;
|
||||
+ pa_log("RFCOMM << %s", buf);
|
||||
+
|
||||
+ pa_log("RFCOMM >> OK");
|
||||
+ len = write (fd, "\r\nOK\r\n", 5);
|
||||
+ /* we ignore any errors, it's not critical and real errors should
|
||||
+ * be caught with the HANGUP and ERROR events handled above */
|
||||
+ if (len < 0)
|
||||
+ pa_log_error("RFCOMM write error: %s", pa_cstrerror(errno));
|
||||
+ }
|
||||
+ return;
|
||||
+
|
||||
+fail:
|
||||
+ pa_bluetooth_transport_unlink(t);
|
||||
+ pa_bluetooth_transport_free(t);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void transport_dispose(pa_bluetooth_transport *t) {
|
||||
+ struct transport_rfcomm *trfc = t->userdata;
|
||||
+
|
||||
+ trfc->mainloop->io_free(trfc->rfcomm_io);
|
||||
+ shutdown (trfc->rfcomm_fd, SHUT_RDWR);
|
||||
+ close (trfc->rfcomm_fd);
|
||||
+
|
||||
+ pa_xfree(trfc);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static DBusMessage *profile_new_connection(DBusConnection *conn, DBusMessage *m, void *userdata) {
|
||||
+ pa_bluetooth_backend *b = userdata;
|
||||
+ pa_bluetooth_device *d;
|
||||
+ pa_bluetooth_transport *t;
|
||||
+ pa_bluetooth_profile_t p;
|
||||
+ DBusMessage *r;
|
||||
+ int fd;
|
||||
+ const char *sender, *path, *handler;
|
||||
+ DBusMessageIter arg_i;
|
||||
+ char *pathfd;
|
||||
+ struct transport_rfcomm *trfc;
|
||||
+
|
||||
+ if (!dbus_message_iter_init(m, &arg_i) || !pa_streq(dbus_message_get_signature(m), "oha{sv}")) {
|
||||
+ pa_log_error("Invalid signature found in NewConnection");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ handler = dbus_message_get_path(m);
|
||||
+ pa_assert (pa_streq(handler, HSP_AG_PROFILE));
|
||||
+
|
||||
+ pa_assert(dbus_message_iter_get_arg_type(&arg_i) == DBUS_TYPE_OBJECT_PATH);
|
||||
+ dbus_message_iter_get_basic(&arg_i, &path);
|
||||
+
|
||||
+ d = pa_bluetooth_discovery_get_device_by_path(b->discovery, path);
|
||||
+ if (d == NULL) {
|
||||
+ pa_log_error("Device doesnt exist for %s", path);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ pa_assert_se(dbus_message_iter_next(&arg_i));
|
||||
+
|
||||
+ pa_assert(dbus_message_iter_get_arg_type(&arg_i) == DBUS_TYPE_UNIX_FD);
|
||||
+ dbus_message_iter_get_basic(&arg_i, &fd);
|
||||
+
|
||||
+ pa_log_debug("dbus: NewConnection path=%s, fd=%d", path, fd);
|
||||
+
|
||||
+ sender = dbus_message_get_sender(m);
|
||||
+
|
||||
+ p = PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT;
|
||||
+ pathfd = pa_sprintf_malloc ("%s/fd%d", path, fd);
|
||||
+ d->transports[p] = t = pa_bluetooth_transport_new(d, sender, pathfd, p, NULL, 0);
|
||||
+ pa_xfree(pathfd);
|
||||
+
|
||||
+ t->acquire = bluez5_sco_acquire_cb;
|
||||
+ t->release = bluez5_sco_release_cb;
|
||||
+ t->dispose = transport_dispose;
|
||||
+
|
||||
+ trfc = pa_xnew0(struct transport_rfcomm, 1);
|
||||
+ trfc->rfcomm_fd = fd;
|
||||
+ trfc->mainloop = b->core->mainloop;
|
||||
+ trfc->rfcomm_io = trfc->mainloop->io_new(b->core->mainloop, fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP,
|
||||
+ rfcomm_io_callback, t);
|
||||
+ t->userdata = trfc;
|
||||
+
|
||||
+ pa_bluetooth_transport_put(t);
|
||||
+
|
||||
+ pa_log_debug("Transport %s available for profile %s", t->path, pa_bluetooth_profile_to_string(t->profile));
|
||||
+
|
||||
+ pa_assert_se(r = dbus_message_new_method_return(m));
|
||||
+
|
||||
+ return r;
|
||||
+
|
||||
+fail:
|
||||
+ pa_assert_se(r = dbus_message_new_error(m, "org.bluez.Error.InvalidArguments", "Unable to handle new connection"));
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static DBusMessage *profile_request_disconnection(DBusConnection *conn, DBusMessage *m, void *userdata) {
|
||||
+ DBusMessage *r;
|
||||
+
|
||||
+ pa_assert_se(r = dbus_message_new_method_return(m));
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static DBusHandlerResult profile_handler(DBusConnection *c, DBusMessage *m, void *userdata) {
|
||||
+ pa_bluetooth_backend *b = userdata;
|
||||
+ DBusMessage *r = NULL;
|
||||
+ const char *path, *interface, *member;
|
||||
+
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ path = dbus_message_get_path(m);
|
||||
+ interface = dbus_message_get_interface(m);
|
||||
+ member = dbus_message_get_member(m);
|
||||
+
|
||||
+ pa_log_debug("dbus: path=%s, interface=%s, member=%s", path, interface, member);
|
||||
+
|
||||
+ if (!pa_streq(path, HSP_AG_PROFILE))
|
||||
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
+
|
||||
+ if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
|
||||
+ const char *xml = PROFILE_INTROSPECT_XML;
|
||||
+
|
||||
+ pa_assert_se(r = dbus_message_new_method_return(m));
|
||||
+ pa_assert_se(dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID));
|
||||
+
|
||||
+ } else if (dbus_message_is_method_call(m, BLUEZ_PROFILE_INTERFACE, "Release")) {
|
||||
+ } else if (dbus_message_is_method_call(m, BLUEZ_PROFILE_INTERFACE, "RequestDisconnection")) {
|
||||
+ r = profile_request_disconnection(c, m, userdata);
|
||||
+ } else if (dbus_message_is_method_call(m, BLUEZ_PROFILE_INTERFACE, "NewConnection"))
|
||||
+ r = profile_new_connection(c, m, userdata);
|
||||
+ else
|
||||
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
+
|
||||
+ if (r) {
|
||||
+ pa_assert_se(dbus_connection_send(pa_dbus_connection_get(b->connection), r, NULL));
|
||||
+ dbus_message_unref(r);
|
||||
+ }
|
||||
+
|
||||
+ return DBUS_HANDLER_RESULT_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static void profile_init(pa_bluetooth_backend *b, pa_bluetooth_profile_t profile) {
|
||||
+ static const DBusObjectPathVTable vtable_profile = {
|
||||
+ .message_function = profile_handler,
|
||||
+ };
|
||||
+ const char *object_name;
|
||||
+ const char *uuid;
|
||||
+
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ switch(profile) {
|
||||
+ case PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT:
|
||||
+ object_name = HSP_AG_PROFILE;
|
||||
+ uuid = PA_BLUETOOTH_UUID_HSP_AG;
|
||||
+ break;
|
||||
+ default:
|
||||
+ pa_assert_not_reached();
|
||||
+ break;
|
||||
+ }
|
||||
+ pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(b->connection),
|
||||
+ object_name, &vtable_profile, b));
|
||||
+ register_profile (b, object_name, uuid);
|
||||
+}
|
||||
+
|
||||
+static void profile_done(pa_bluetooth_backend *b, pa_bluetooth_profile_t profile) {
|
||||
+ pa_assert(b);
|
||||
+
|
||||
+ switch(profile) {
|
||||
+ case PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT:
|
||||
+ dbus_connection_unregister_object_path(pa_dbus_connection_get(b->connection), HSP_AG_PROFILE);
|
||||
+ break;
|
||||
+ default:
|
||||
+ pa_assert_not_reached();
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+pa_bluetooth_backend *pa_bluetooth_backend_new(pa_core *c, pa_bluetooth_discovery *y) {
|
||||
+ pa_bluetooth_backend *backend;
|
||||
+ DBusError err;
|
||||
+
|
||||
+ pa_log_debug("Bluetooth Headset Backend API support using the NULL backend");
|
||||
+
|
||||
+ backend = pa_xnew0(pa_bluetooth_backend, 1);
|
||||
+ backend->core = c;
|
||||
+
|
||||
+ dbus_error_init(&err);
|
||||
+ if (!(backend->connection = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &err))) {
|
||||
+ pa_log("Failed to get D-Bus connection: %s", err.message);
|
||||
+ dbus_error_free(&err);
|
||||
+ pa_xfree(backend);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ backend->discovery = y;
|
||||
+
|
||||
+ profile_init(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
|
||||
+
|
||||
+ return backend;
|
||||
+}
|
||||
+
|
||||
+void pa_bluetooth_backend_free(pa_bluetooth_backend *backend) {
|
||||
+ pa_assert(backend);
|
||||
+
|
||||
+ pa_dbus_free_pending_list(&backend->pending);
|
||||
+
|
||||
+ profile_done(backend, PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT);
|
||||
+
|
||||
+ pa_dbus_connection_unref(backend->connection);
|
||||
+
|
||||
+ pa_xfree(backend);
|
||||
+}
|
||||
--
|
||||
2.1.0
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
%global pa_major 5.0
|
||||
#global pa_minor 0
|
||||
|
||||
%global snap 20141019
|
||||
%global gitrel 287
|
||||
%global gitcommit 4971dc9ed695256cfb179c5ef4d7bf43d3826ba2
|
||||
%global snap 20141103
|
||||
%global gitrel 323
|
||||
%global gitcommit 6d1fd4d1aab38a18925972f11face92ea602adf0
|
||||
%global shortcommit %(c=%{gitcommit}; echo ${c:0:5})
|
||||
|
||||
#323-g6d1fd
|
||||
|
||||
%ifarch %{ix86} x86_64 %{arm}
|
||||
%global with_webrtc 1
|
||||
%endif
|
||||
@ -19,7 +21,7 @@
|
||||
Name: pulseaudio
|
||||
Summary: Improved Linux Sound Server
|
||||
Version: %{pa_major}%{?pa_minor:.%{pa_minor}}
|
||||
Release: 22%{?snap:.%{snap}git%{shortcommit}}%{?dist}
|
||||
Release: 23%{?snap:.%{snap}git%{shortcommit}}%{?dist}
|
||||
License: LGPLv2+
|
||||
URL: http://www.freedesktop.org/wiki/Software/PulseAudio
|
||||
%if 0%{?gitrel}
|
||||
@ -221,13 +223,6 @@ This package contains GDM integration hooks for the PulseAudio sound server.
|
||||
%prep
|
||||
%setup -q -T -b0 -n %{name}-%{version}%{?gitrel:-%{gitrel}-g%{shortcommit}}
|
||||
|
||||
%patch1 -p1 -b .0001
|
||||
%patch2 -p1 -b .0002
|
||||
%patch3 -p1 -b .0003
|
||||
|
||||
# needed by patch3
|
||||
./bootstrap.sh
|
||||
|
||||
sed -i.no_consolekit -e \
|
||||
's/^load-module module-console-kit/#load-module module-console-kit/' \
|
||||
src/daemon/default.pa.in
|
||||
@ -560,6 +555,9 @@ exit 0
|
||||
|
||||
|
||||
%changelog
|
||||
* Wed Nov 05 2014 Rex Dieter <rdieter@fedoraproject.org> 5.0-23.20141103git6d1fd
|
||||
- 20141103 snapshot
|
||||
|
||||
* Wed Nov 05 2014 Orion Poplawski <orion@cora.nwra.com> 5.0-22.20141007git4971d
|
||||
- Really add pulse-rt group when needed (bug #885020)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user