snapshot, with wip bt headset2 patches (#1045548,#1067470)

This commit is contained in:
Rex Dieter 2014-10-22 09:20:18 -05:00
parent 7167b336b7
commit 311762276e
10 changed files with 642 additions and 227 deletions

View File

@ -0,0 +1,74 @@
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

View File

@ -0,0 +1,48 @@
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

View File

@ -0,0 +1,490 @@
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

View File

@ -1,35 +0,0 @@
From ef4a41e8b0ef81a53769d853dbc7679b25252327 Mon Sep 17 00:00:00 2001
From: David Henningsson <david.henningsson@canonical.com>
Date: Fri, 28 Mar 2014 11:59:09 +0100
Subject: [PATCH 36/38] module-switch-on-port-available: Don't switch profiles
on uninitialized cards
This could cause the HDMI port to become the default on some systems
where analog output was available.
BugLink: https://bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/1256511
BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=73375
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
---
src/modules/module-switch-on-port-available.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
index 2c7ad17..c560306 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -173,6 +173,11 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port
return PA_HOOK_OK;
}
+ if (pa_idxset_size(card->sinks) == 0 && pa_idxset_size(card->sources) == 0)
+ /* This card is not initialized yet. We'll handle it in
+ sink_new / source_new callbacks later. */
+ return PA_HOOK_OK;
+
find_sink_and_source(card, port, &sink, &source);
is_active_profile = card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name);
--
1.9.0

View File

@ -1,77 +0,0 @@
From a5ba31bf9627b6c7d7f5e03cdccff2d52fa3299d Mon Sep 17 00:00:00 2001
From: "Alexander E. Patrakov" <patrakov@gmail.com>
Date: Thu, 10 Apr 2014 21:13:43 +0600
Subject: [PATCH 039/156] Name HDMI outputs uniquely
On Haswell hardware, there are multiple HDMI outputs capable of
digital sound output. As they were identically named, KDE's control
center was unable to distinguish them, restored the wrong profile and
thus routed sound to the wrong HDMI monitor.
Also, having identically-named menu items in other mixer applications
looks like a bug.
---
src/modules/alsa/mixer/profile-sets/extra-hdmi.conf | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/modules/alsa/mixer/profile-sets/extra-hdmi.conf b/src/modules/alsa/mixer/profile-sets/extra-hdmi.conf
index 96652f8..191a652 100644
--- a/src/modules/alsa/mixer/profile-sets/extra-hdmi.conf
+++ b/src/modules/alsa/mixer/profile-sets/extra-hdmi.conf
@@ -116,7 +116,7 @@ priority = 3
direction = output
[Mapping hdmi-stereo-extra1]
-description = Digital Stereo (HDMI)
+description = Digital Stereo (HDMI 2)
device-strings = hdmi:%f,1
paths-output = hdmi-output-1
channel-map = left,right
@@ -124,7 +124,7 @@ priority = 2
direction = output
[Mapping hdmi-surround-extra1]
-description = Digital Surround 5.1 (HDMI)
+description = Digital Surround 5.1 (HDMI 2)
device-strings = hdmi:%f,1
paths-output = hdmi-output-1
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
@@ -132,7 +132,7 @@ priority = 1
direction = output
[Mapping hdmi-stereo-extra2]
-description = Digital Stereo (HDMI)
+description = Digital Stereo (HDMI 3)
device-strings = hdmi:%f,2
paths-output = hdmi-output-2
channel-map = left,right
@@ -140,7 +140,7 @@ priority = 2
direction = output
[Mapping hdmi-surround-extra2]
-description = Digital Surround 5.1 (HDMI)
+description = Digital Surround 5.1 (HDMI 3)
device-strings = hdmi:%f,2
paths-output = hdmi-output-2
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
@@ -148,7 +148,7 @@ priority = 1
direction = output
[Mapping hdmi-stereo-extra3]
-description = Digital Stereo (HDMI)
+description = Digital Stereo (HDMI 4)
device-strings = hdmi:%f,3
paths-output = hdmi-output-3
channel-map = left,right
@@ -156,7 +156,7 @@ priority = 2
direction = output
[Mapping hdmi-surround-extra3]
-description = Digital Surround 5.1 (HDMI)
+description = Digital Surround 5.1 (HDMI 4)
device-strings = hdmi:%f,3
paths-output = hdmi-output-3
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
--
1.9.3

View File

@ -1,58 +0,0 @@
From 26b9d22dd24c17eb118d0205bf7b02b75d435e3c Mon Sep 17 00:00:00 2001
From: "Alexander E. Patrakov" <patrakov@gmail.com>
Date: Thu, 5 Jun 2014 22:29:25 +0600
Subject: [PATCH 112/156] rtp-recv: fix crash on empty UDP packets
(CVE-2014-3970)
On FIONREAD returning 0 bytes, we cannot return success, as the caller
(rtpoll_work_cb in module-rtp-recv.c) would then try to
pa_memblock_unref(chunk.memblock) and, because memblock is NULL, trigger
an assertion.
Also we have to read out the possible empty packet from the socket, so
that the kernel doesn't tell us again and again about it.
Signed-off-by: Alexander E. Patrakov <patrakov@gmail.com>
---
src/modules/rtp/rtp.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c
index 570737e..7b75e0e 100644
--- a/src/modules/rtp/rtp.c
+++ b/src/modules/rtp/rtp.c
@@ -182,8 +182,29 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, struct
goto fail;
}
- if (size <= 0)
- return 0;
+ if (size <= 0) {
+ /* size can be 0 due to any of the following reasons:
+ *
+ * 1. Somebody sent us a perfectly valid zero-length UDP packet.
+ * 2. Somebody sent us a UDP packet with a bad CRC.
+ *
+ * It is unknown whether size can actually be less than zero.
+ *
+ * In the first case, the packet has to be read out, otherwise the
+ * kernel will tell us again and again about it, thus preventing
+ * reception of any further packets. So let's just read it out
+ * now and discard it later, when comparing the number of bytes
+ * received (0) with the number of bytes wanted (1, see below).
+ *
+ * In the second case, recvmsg() will fail, thus allowing us to
+ * return the error.
+ *
+ * Just to avoid passing zero-sized memchunks and NULL pointers to
+ * recvmsg(), let's force allocation of at least one byte by setting
+ * size to 1.
+ */
+ size = 1;
+ }
if (c->memchunk.length < (unsigned) size) {
size_t l;
--
1.9.3

View File

@ -1,16 +0,0 @@
diff -up pulseaudio-4.0-266-gf81e3/src/daemon/pulseaudio-kde.desktop.in.kde_autostart_phase pulseaudio-4.0-266-gf81e3/src/daemon/pulseaudio-kde.desktop.in
--- pulseaudio-4.0-266-gf81e3/src/daemon/pulseaudio-kde.desktop.in.kde_autostart_phase 2013-10-10 17:02:01.000000000 -0500
+++ pulseaudio-4.0-266-gf81e3/src/daemon/pulseaudio-kde.desktop.in 2013-12-07 13:15:24.034110082 -0600
@@ -9,3 +9,4 @@ Type=Application
Categories=
GenericName=
OnlyShowIn=KDE;
+X-KDE-autostart-phase=1
diff -up pulseaudio-4.0-266-gf81e3/src/daemon/pulseaudio.desktop.in.kde_autostart_phase pulseaudio-4.0-266-gf81e3/src/daemon/pulseaudio.desktop.in
--- pulseaudio-4.0-266-gf81e3/src/daemon/pulseaudio.desktop.in.kde_autostart_phase 2013-10-10 17:02:01.000000000 -0500
+++ pulseaudio-4.0-266-gf81e3/src/daemon/pulseaudio.desktop.in 2013-12-07 13:15:17.579180709 -0600
@@ -9,3 +9,4 @@ Type=Application
Categories=
GenericName=
X-GNOME-Autostart-Phase=Initialization
+X-KDE-autostart-phase=1

View File

@ -1,14 +0,0 @@
diff -up pulseaudio-4.0-266-gf81e3/src/daemon/start-pulseaudio-x11.in.x11_device_manager pulseaudio-4.0-266-gf81e3/src/daemon/start-pulseaudio-x11.in
--- pulseaudio-4.0-266-gf81e3/src/daemon/start-pulseaudio-x11.in.x11_device_manager 2013-10-10 17:02:01.000000000 -0500
+++ pulseaudio-4.0-266-gf81e3/src/daemon/start-pulseaudio-x11.in 2013-10-14 09:44:04.375542726 -0500
@@ -26,6 +26,10 @@ if [ x"$DISPLAY" != x ] ; then
@PACTL_BINARY@ load-module module-x11-publish "display=$DISPLAY" > /dev/null
@PACTL_BINARY@ load-module module-x11-cork-request "display=$DISPLAY" > /dev/null
+ if [ x"$KDE_FULL_SESSION" = x"true" ]; then
+ @PACTL_BINARY@ load-module module-device-manager "do_routing=1" > /dev/null
+ fi
+
if [ x"$SESSION_MANAGER" != x ] ; then
@PACTL_BINARY@ load-module module-x11-xsmp "display=$DISPLAY session_manager=$SESSION_MANAGER" > /dev/null
fi

View File

@ -1,9 +1,10 @@
%global pa_major 5.0
#global pa_minor 0
#global gitrel 266
#global gitcommit f81e3e1d7852c05b4b737ac7dac4db95798f0117
#global shortcommit %(c=%{gitcommit}; echo ${c:0:5})
%global snap 20141019
%global gitrel 287
%global gitcommit 4971dc9ed695256cfb179c5ef4d7bf43d3826ba2
%global shortcommit %(c=%{gitcommit}; echo ${c:0:5})
%ifarch %{ix86} x86_64 %{arm}
%global with_webrtc 1
@ -18,7 +19,7 @@
Name: pulseaudio
Summary: Improved Linux Sound Server
Version: %{pa_major}%{?pa_minor:.%{pa_minor}}
Release: 10%{?gitcommit:.git%{shortcommit}}%{?dist}
Release: 20%{?snap:.%{snap}git%{shortcommit}}%{?dist}
License: LGPLv2+
URL: http://www.freedesktop.org/wiki/Software/PulseAudio
%if 0%{?gitrel}
@ -31,17 +32,12 @@ Source0: http://freedesktop.org/software/pulseaudio/releases/pulseaudio-%
Source1: default.pa-for-gdm
## upstream patches
# https://bugzilla.redhat.com/show_bug.cgi?id=1035025
# https://bugs.freedesktop.org/show_bug.cgi?id=73375
Patch036: 0036-module-switch-on-port-available-Don-t-switch-profile.patch
Patch039: 0039-Name-HDMI-outputs-uniquely.patch
Patch112: 0112-rtp-recv-fix-crash-on-empty-UDP-packets-CVE-2014-397.patch
## upstreamable patches
# simplify and ship only 1 autostart file
Patch501: pulseaudio-x11_device_manager.patch
# set X-KDE-autostart-phase=1
Patch502: pulseaudio-4.0-kde_autostart_phase.patch
# WIP bluetooth headset work from http://cgit.freedesktop.org/~wtay/pulseaudio/log/?h=headset2
Patch1: 0001-bluez5-device-use-get_profile_direction.patch
Patch2: 0002-bluez5-util-add-dispose-function.patch
Patch3: 0003-backend-native-add-a-new-native-headset-backend.patch
BuildRequires: m4
BuildRequires: libtool-ltdl-devel
@ -220,15 +216,16 @@ Requires(pre): gdm
%description gdm-hooks
This package contains GDM integration hooks for the PulseAudio sound server.
%prep
%setup -q -T -b0 -n %{name}-%{version}%{?gitrel:-%{gitrel}-g%{shortcommit}}
%patch036 -p1 -b .0036
%patch039 -p1 -b .0039
%patch112 -p1 -b .0112
%patch1 -p1 -b .0001
%patch2 -p1 -b .0002
%patch3 -p1 -b .0003
%patch501 -p1 -b .x11_device_manager
%patch502 -p1 -b .kde_autostart_phase
# needed by patch3
./bootstrap.sh
sed -i.no_consolekit -e \
's/^load-module module-console-kit/#load-module module-console-kit/' \
@ -244,9 +241,10 @@ sed -i -e 's|"/lib /usr/lib|"/%{_lib} %{_libdir}|' configure
%endif
%endif
%build
%build
%configure \
--disable-silent-rules \
--disable-static \
--disable-rpath \
--with-system-user=pulse \
@ -270,6 +268,7 @@ sed -i -e 's|"/lib /usr/lib|"/%{_lib} %{_libdir}|' configure
make %{?_smp_mflags} V=1
make doxygen
%install
make install DESTDIR=$RPM_BUILD_ROOT
@ -300,9 +299,6 @@ install -p -m644 -D %{SOURCE1} $RPM_BUILD_ROOT%{_localstatedir}/lib/gdm/.pulse/d
rm -fv $RPM_BUILD_ROOT%{_libdir}/*.la $RPM_BUILD_ROOT%{_libdir}/pulse-%{pa_major}/modules/*.la
# PA_MODULE_DEPRECATED("Please use module-udev-detect instead of module-detect!");
rm -fv $RPM_BUILD_ROOT%{_libdir}/pulse-%{pa_major}/modules/module-detect.so
# x11_device_manager folds -kde functionality into single -x11 autostart, so this
# one is no longer needed
rm -fv $RPM_BUILD_ROOT%{_sysconfdir}/xdg/autostart/pulseaudio-kde.desktop
%find_lang %{name}
@ -442,6 +438,9 @@ exit 0
%{_prefix}/lib/udev/rules.d/90-pulseaudio.rules
%dir %{_libexecdir}/pulse
%attr(0700, pulse, pulse) %dir %{_localstatedir}/lib/pulse
%dir %{_datadir}/zsh/
%dir %{_datadir}/zsh/site-functions/
%{_datadir}/zsh/site-functions/_pulseaudio
%files qpaeq
%{_bindir}/qpaeq
@ -458,15 +457,12 @@ exit 0
%files module-x11
%{_sysconfdir}/xdg/autostart/pulseaudio.desktop
## no longer included per x11_device_manager.patch
#config %{_sysconfdir}/xdg/autostart/pulseaudio-kde.desktop
%{_bindir}/start-pulseaudio-kde
#{_bindir}/start-pulseaudio-kde
%{_bindir}/start-pulseaudio-x11
%{_libdir}/pulse-%{pa_major}/modules/module-x11-bell.so
%{_libdir}/pulse-%{pa_major}/modules/module-x11-publish.so
%{_libdir}/pulse-%{pa_major}/modules/module-x11-xsmp.so
%{_libdir}/pulse-%{pa_major}/modules/module-x11-cork-request.so
%{_mandir}/man1/start-pulseaudio-kde.1.gz
%{_mandir}/man1/start-pulseaudio-x11.1.gz
%files module-zeroconf
@ -529,6 +525,9 @@ exit 0
%{_datadir}/vala/vapi/libpulse.deps
%{_datadir}/vala/vapi/libpulse-mainloop-glib.vapi
%{_datadir}/vala/vapi/libpulse-mainloop-glib.deps
%{_datadir}/vala/vapi/libpulse-simple.deps
%{_datadir}/vala/vapi/libpulse-simple.vapi
%dir %{_libdir}/cmake
%{_libdir}/cmake/PulseAudio/
@ -558,7 +557,11 @@ exit 0
%attr(0700, gdm, gdm) %dir %{_localstatedir}/lib/gdm/.pulse
%attr(0600, gdm, gdm) %{_localstatedir}/lib/gdm/.pulse/default.pa
%changelog
* Wed Oct 22 2014 Rex Dieter <rdieter@fedoraproject.org> 5.0-20.20141007git4971d
- snapshot, with wip bt headset2 patches (#1045548,#1067470)
* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 5.0-10
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild

View File

@ -1 +1 @@
c43749838612f4860465e83ed62ca38e pulseaudio-5.0.tar.xz
8872ddac114237c314887dafb526a928 pulseaudio-5.0-287-g4971d.tar.xz