diff options
author | Nick Stoughton <nstoughton@aether.com> | 2014-12-30 07:21:44 -0800 |
---|---|---|
committer | Arun Raghavan <git@arunraghavan.net> | 2015-07-03 15:41:52 +0530 |
commit | 2aa0eba67391887f8d08b2aec9ee4a3c439b6e0f (patch) | |
tree | f65cd055b76babde259e3b8f19f567879140852e /sys | |
parent | f17899a55cff8bf7ab61b4fe565d0f8e81a74751 (diff) | |
download | gstreamer-plugins-bad-2aa0eba67391887f8d08b2aec9ee4a3c439b6e0f.tar.gz |
bluez: refactor to use glib and add connection state tracking
Diffstat (limited to 'sys')
-rw-r--r-- | sys/bluez/Makefile.am | 24 | ||||
-rw-r--r-- | sys/bluez/gstavdtpsink.c | 4 | ||||
-rw-r--r-- | sys/bluez/gstavdtpsrc.c | 4 | ||||
-rw-r--r-- | sys/bluez/gstavdtputil.c | 274 | ||||
-rw-r--r-- | sys/bluez/gstavdtputil.h | 12 | ||||
-rw-r--r-- | sys/bluez/org.bluez.xml | 29 |
6 files changed, 151 insertions, 196 deletions
diff --git a/sys/bluez/Makefile.am b/sys/bluez/Makefile.am index cc9017654..b67c8ba63 100644 --- a/sys/bluez/Makefile.am +++ b/sys/bluez/Makefile.am @@ -5,20 +5,23 @@ libgstbluez_la_SOURCES = \ gsta2dpsink.c \ gstavdtpsink.c \ gstavdtpsrc.c \ - gstavdtputil.c + gstavdtputil.c \ + $(BUILT_SOURCES) libgstbluez_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) \ $(GST_BASE_CFLAGS) \ $(GST_CFLAGS) \ - $(DBUS_CFLAGS) + $(GIO_CFLAGS) \ + $(GIO_UNIX_CFLAGS) libgstbluez_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) \ -lgstaudio-$(GST_API_VERSION) \ -lgstrtp-$(GST_API_VERSION) \ $(GST_BASE_LIBS) \ $(GST_LIBS) \ - $(DBUS_LIBS) + $(GIO_LIBS) \ + $(GIO_UNIX_LIBS) libgstbluez_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstbluez_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) @@ -27,4 +30,17 @@ noinst_HEADERS = \ gsta2dpsink.h \ gstavdtpsink.h \ gstavdtpsrc.h \ - gstavdtputil.h + gstavdtputil.h \ + bluez.h + +BUILT_SOURCES = \ + bluez.h \ + bluez.c + +bluez.h: bluez.c +bluez.c: org.bluez.xml + $(AM_V_GEN) $(GDBUS_CODEGEN) \ + --c-namespace=Bluez \ + --generate-c-code=bluez \ + --interface-prefix=org.bluez \ + $< diff --git a/sys/bluez/gstavdtpsink.c b/sys/bluez/gstavdtpsink.c index b549caaa1..70dc742a5 100644 --- a/sys/bluez/gstavdtpsink.c +++ b/sys/bluez/gstavdtpsink.c @@ -34,8 +34,6 @@ #include <fcntl.h> #include <netinet/in.h> -#include <dbus/dbus.h> - #include "a2dp-codecs.h" #include "gstavdtpsink.h" @@ -263,7 +261,7 @@ gst_avdtp_sink_start (GstBaseSink * basesink) if (self->conn.transport == NULL) return FALSE; - if (!gst_avdtp_connection_acquire (&self->conn)) { + if (!gst_avdtp_connection_acquire (&self->conn, FALSE)) { GST_ERROR_OBJECT (self, "Failed to acquire connection"); return FALSE; } diff --git a/sys/bluez/gstavdtpsrc.c b/sys/bluez/gstavdtpsrc.c index 311c407b7..176c2d4d0 100644 --- a/sys/bluez/gstavdtpsrc.c +++ b/sys/bluez/gstavdtpsrc.c @@ -39,7 +39,7 @@ GST_DEBUG_CATEGORY_STATIC (avdtpsrc_debug); enum { PROP_0, - PROP_TRANSPORT + PROP_TRANSPORT, }; #define parent_class gst_avdtp_src_parent_class @@ -262,7 +262,7 @@ gst_avdtp_src_start (GstBaseSrc * bsrc) * connection to figure out what format the device is going to send us. */ - if (!gst_avdtp_connection_acquire (&avdtpsrc->conn)) { + if (!gst_avdtp_connection_acquire (&avdtpsrc->conn, FALSE)) { GST_ERROR_OBJECT (avdtpsrc, "Failed to acquire connection"); return FALSE; } diff --git a/sys/bluez/gstavdtputil.c b/sys/bluez/gstavdtputil.c index 787a06309..52a90a5b6 100644 --- a/sys/bluez/gstavdtputil.c +++ b/sys/bluez/gstavdtputil.c @@ -36,98 +36,131 @@ #include <bluetooth/bluetooth.h> #include "a2dp-codecs.h" +#include <gio/gunixfdlist.h> #include <gst/gst.h> #include "gstavdtputil.h" +#include "bluez.h" #define TEMPLATE_MAX_BITPOOL 64 GST_DEBUG_CATEGORY_EXTERN (avdtp_debug); #define GST_CAT_DEFAULT avdtp_debug +static void gst_avdtp_connection_transport_release (GstAvdtpConnection * conn); + +static gboolean +on_state_change (BluezMediaTransport1 * proxy, GParamSpec * pspec, + GstAvdtpConnection * conn) +{ + const gchar *newstate; + gboolean is_idle; + + newstate = bluez_media_transport1_get_state (proxy); + is_idle = g_str_equal (newstate, "idle"); + + if (!conn->data.is_acquired && !is_idle) { + GST_DEBUG ("Re-acquiring connection"); + gst_avdtp_connection_acquire (conn, TRUE); + + } else if (is_idle) { + /* We don't know if we need to release the transport -- that may have been + * done for us by bluez already! Or not ... so release it just in case, but + * mark its stale beforehand to suppress any errors. */ + GST_DEBUG ("Marking connection stale"); + conn->data.is_acquired = FALSE; + gst_avdtp_connection_transport_release (conn); + + } else + GST_DEBUG ("State is %s, acquired is %s", newstate, + conn->data.is_acquired ? "true" : "false"); + + return TRUE; +} + gboolean -gst_avdtp_connection_acquire (GstAvdtpConnection * conn) +gst_avdtp_connection_acquire (GstAvdtpConnection * conn, gboolean use_try) { - DBusMessage *msg, *reply; - DBusError err; -#ifdef HAVE_BLUEZ4 - const char *access_type = "rw"; -#endif + GVariant *handle = NULL; + GUnixFDList *fd_list = NULL; + GError *err = NULL; int fd; uint16_t imtu, omtu; - dbus_error_init (&err); - if (conn->transport == NULL) { GST_ERROR ("No transport specified"); return FALSE; } - if (conn->data.conn == NULL) - conn->data.conn = dbus_bus_get (DBUS_BUS_SYSTEM, &err); - -#ifdef HAVE_BLUEZ4 - msg = dbus_message_new_method_call ("org.bluez", conn->transport, - "org.bluez.MediaTransport", "Acquire"); + if (conn->data.conn == NULL) { + conn->data.conn = + bluez_media_transport1_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, "org.bluez", conn->transport, NULL, &err); - dbus_message_append_args (msg, DBUS_TYPE_STRING, &access_type, - DBUS_TYPE_INVALID); -#else - msg = dbus_message_new_method_call ("org.bluez", conn->transport, - "org.bluez.MediaTransport1", "Acquire"); -#endif + if (conn->data.conn == NULL) { + GST_ERROR ("Failed to create proxy for media transport: %s", + err && err->message ? err->message : "Unknown error"); + return FALSE; + } - reply = dbus_connection_send_with_reply_and_block (conn->data.conn, - msg, -1, &err); + g_signal_connect (conn->data.conn, "notify::state", + G_CALLBACK (on_state_change), conn); + } - dbus_message_unref (msg); + if (conn->data.is_acquired) { + GST_INFO ("Transport is already acquired"); + return TRUE; + } - if (dbus_error_is_set (&err)) - goto fail; + if (use_try) { + if (!bluez_media_transport1_call_try_acquire_sync (conn->data.conn, + NULL, &handle, &imtu, &omtu, &fd_list, NULL, &err)) + goto fail; + } else { + if (!bluez_media_transport1_call_acquire_sync (conn->data.conn, + NULL, &handle, &imtu, &omtu, &fd_list, NULL, &err)) + goto fail; + } - if (dbus_message_get_args (reply, &err, DBUS_TYPE_UNIX_FD, &fd, - DBUS_TYPE_UINT16, &imtu, - DBUS_TYPE_UINT16, &omtu, DBUS_TYPE_INVALID) == FALSE) + fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (handle), &err); + if (fd < 0) goto fail; - dbus_message_unref (reply); - + g_variant_unref (handle); + g_object_unref (fd_list); conn->stream = g_io_channel_unix_new (fd); g_io_channel_set_encoding (conn->stream, NULL, NULL); g_io_channel_set_close_on_unref (conn->stream, TRUE); conn->data.link_mtu = omtu; + conn->data.is_acquired = TRUE; return TRUE; fail: - GST_ERROR ("Failed to acquire transport stream: %s", err.message); - - dbus_error_free (&err); + GST_ERROR ("Failed to %s transport stream: %s", use_try ? "try_acquire" : + "acquire", err && err->message ? err->message : "unknown error"); - if (reply) - dbus_message_unref (reply); + g_clear_error (&err); + if (handle) + g_variant_unref (handle); + conn->data.is_acquired = FALSE; return FALSE; } static void gst_avdtp_connection_transport_release (GstAvdtpConnection * conn) { - DBusMessage *msg; -#ifdef HAVE_BLUEZ4 - const char *access_type = "rw"; - - msg = dbus_message_new_method_call ("org.bluez", conn->transport, - "org.bluez.MediaTransport", "Release"); + GError *err = NULL; - dbus_message_append_args (msg, DBUS_TYPE_STRING, &access_type, - DBUS_TYPE_INVALID); -#else - msg = dbus_message_new_method_call ("org.bluez", conn->transport, - "org.bluez.MediaTransport1", "Release"); -#endif - dbus_connection_send (conn->data.conn, msg, NULL); + if (!bluez_media_transport1_call_release_sync (conn->data.conn, NULL, &err)) { + /* We don't care about errors if the transport was already marked stale */ + if (!conn->data.is_acquired) + return; - dbus_message_unref (msg); + GST_ERROR ("Failed to release transport stream: %s", err->message ? + err->message : "unknown error"); + } + conn->data.is_acquired = FALSE; } void @@ -153,9 +186,7 @@ gst_avdtp_connection_release (GstAvdtpConnection * conn) if (conn->transport) gst_avdtp_connection_transport_release (conn); - dbus_connection_unref (conn->data.conn); - - conn->data.conn = NULL; + g_clear_object (&conn->data.conn); } } @@ -194,145 +225,22 @@ gst_avdtp_connection_set_transport (GstAvdtpConnection * conn, conn->transport = g_strdup (transport); } -static gboolean -gst_avdtp_connection_parse_property (GstAvdtpConnection * conn, - DBusMessageIter * i) -{ - const char *key; - DBusMessageIter variant_i; - - if (dbus_message_iter_get_arg_type (i) != DBUS_TYPE_STRING) { - GST_ERROR ("Property name not a string."); - return FALSE; - } - - dbus_message_iter_get_basic (i, &key); - - if (!dbus_message_iter_next (i)) { - GST_ERROR ("Property value missing"); - return FALSE; - } - - if (dbus_message_iter_get_arg_type (i) != DBUS_TYPE_VARIANT) { - GST_ERROR ("Property value not a variant."); - return FALSE; - } - - dbus_message_iter_recurse (i, &variant_i); - - switch (dbus_message_iter_get_arg_type (&variant_i)) { - case DBUS_TYPE_BYTE:{ - uint8_t value; - dbus_message_iter_get_basic (&variant_i, &value); - - if (g_str_equal (key, "Codec") == TRUE) - conn->data.codec = value; - - break; - } - case DBUS_TYPE_STRING:{ - const char *value; - dbus_message_iter_get_basic (&variant_i, &value); - - if (g_str_equal (key, "UUID") == TRUE) { - g_free (conn->data.uuid); - conn->data.uuid = g_strdup (value); - } - - break; - } - case DBUS_TYPE_ARRAY:{ - DBusMessageIter array_i; - char *value; - int size; - - dbus_message_iter_recurse (&variant_i, &array_i); - dbus_message_iter_get_fixed_array (&array_i, &value, &size); - - if (g_str_equal (key, "Configuration")) { - g_free (conn->data.config); - conn->data.config = g_new0 (guint8, size); - conn->data.config_size = size; - memcpy (conn->data.config, value, size); - } - - break; - } - } - - return TRUE; -} - gboolean gst_avdtp_connection_get_properties (GstAvdtpConnection * conn) { - DBusMessage *msg, *reply; - DBusMessageIter arg_i, ele_i; - DBusError err; -#ifndef HAVE_BLUEZ4 - const char *interface; -#endif - - dbus_error_init (&err); - -#ifdef HAVE_BLUEZ4 - msg = dbus_message_new_method_call ("org.bluez", conn->transport, - "org.bluez.MediaTransport", "GetProperties"); -#else - msg = dbus_message_new_method_call ("org.bluez", conn->transport, - "org.freedesktop.DBus.Properties", "GetAll"); -#endif - if (!msg) { - GST_ERROR ("D-Bus Memory allocation failed"); - return FALSE; - } -#ifndef HAVE_BLUEZ4 - interface = "org.bluez.MediaTransport1"; - dbus_message_append_args (msg, DBUS_TYPE_STRING, &interface, - DBUS_TYPE_INVALID); -#endif - reply = dbus_connection_send_with_reply_and_block (conn->data.conn, - msg, -1, &err); - - dbus_message_unref (msg); - - if (dbus_error_is_set (&err)) { - GST_ERROR ("GetProperties failed: %s", err.message); - dbus_error_free (&err); - return FALSE; - } - - if (!dbus_message_iter_init (reply, &arg_i)) { - GST_ERROR ("GetProperties reply has no arguments."); - goto fail; - } - - if (dbus_message_iter_get_arg_type (&arg_i) != DBUS_TYPE_ARRAY) { - GST_ERROR ("GetProperties argument is not an array."); - goto fail; - } - - dbus_message_iter_recurse (&arg_i, &ele_i); - while (dbus_message_iter_get_arg_type (&ele_i) != DBUS_TYPE_INVALID) { + GVariant *var; - if (dbus_message_iter_get_arg_type (&ele_i) == DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter dict_i; + conn->data.codec = bluez_media_transport1_get_codec (conn->data.conn); - dbus_message_iter_recurse (&ele_i, &dict_i); + conn->data.uuid = bluez_media_transport1_dup_uuid (conn->data.conn); - gst_avdtp_connection_parse_property (conn, &dict_i); - } - - if (!dbus_message_iter_next (&ele_i)) - break; - } + var = bluez_media_transport1_dup_configuration (conn->data.conn); + conn->data.config_size = g_variant_get_size (var); + conn->data.config = g_new0 (guint8, conn->data.config_size); + g_variant_store (var, conn->data.config); + g_variant_unref (var); return TRUE; - -fail: - dbus_message_unref (reply); - return FALSE; - } static GstStructure * diff --git a/sys/bluez/gstavdtputil.h b/sys/bluez/gstavdtputil.h index b551781af..131944186 100644 --- a/sys/bluez/gstavdtputil.h +++ b/sys/bluez/gstavdtputil.h @@ -27,20 +27,23 @@ #include <glib.h> -#include <dbus/dbus.h> +#include "bluez.h" G_BEGIN_DECLS + #define DEFAULT_CODEC_BUFFER_SIZE 2048 #define TEMPLATE_MAX_BITPOOL_STR "64" - struct bluetooth_data + +struct bluetooth_data { guint link_mtu; - DBusConnection *conn; + BluezMediaTransport1 *conn; guint8 codec; /* Bluetooth transport configuration */ gchar *uuid; guint8 *config; gint config_size; + gboolean is_acquired; gchar buffer[DEFAULT_CODEC_BUFFER_SIZE]; /* Codec transfer buffer */ }; @@ -56,7 +59,8 @@ struct _GstAvdtpConnection struct bluetooth_data data; }; -gboolean gst_avdtp_connection_acquire (GstAvdtpConnection * conn); +gboolean gst_avdtp_connection_acquire (GstAvdtpConnection * conn, + gboolean use_try); void gst_avdtp_connection_release (GstAvdtpConnection * conn); void gst_avdtp_connection_reset (GstAvdtpConnection * conn); gboolean gst_avdtp_connection_get_properties (GstAvdtpConnection * conn); diff --git a/sys/bluez/org.bluez.xml b/sys/bluez/org.bluez.xml new file mode 100644 index 000000000..ff52ee303 --- /dev/null +++ b/sys/bluez/org.bluez.xml @@ -0,0 +1,29 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + +<node> +<interface name="org.bluez.MediaTransport1"> + <method name="Acquire"> + <annotation name="org.gtk.GDBus.C.UnixFD" value="true" /> + <arg name="fd" type="h" direction="out"/> + <arg name="mtu_r" type="q" direction="out"/> + <arg name="mtu_w" type="q" direction="out"/> + </method> + <method name="TryAcquire"> + <annotation name="org.gtk.GDBus.C.UnixFD" value="true" /> + <arg name="fd" type="h" direction="out"/> + <arg name="mtu_r" type="q" direction="out"/> + <arg name="mtu_w" type="q" direction="out"/> + </method> + <method name="Release"></method> + <property name="Device" type="o" access="read"></property> + <property name="UUID" type="s" access="read"></property> + <property name="Codec" type="y" access="read"></property> + <property name="Configuration" type="ay" access="read"> + <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true" /> + </property> + <property name="State" type="s" access="read"></property> + <property name="Delay" type="q" access="read"></property> + <property name="Volume" type="q" access="readwrite"></property> +</interface> +</node> |