diff --git a/sys/bluez/gstavdtpsink.c b/sys/bluez/gstavdtpsink.c index 1423897f39..a2986feaeb 100644 --- a/sys/bluez/gstavdtpsink.c +++ b/sys/bluez/gstavdtpsink.c @@ -39,7 +39,6 @@ #include -#include "ipc.h" #include "rtp.h" #include "a2dp-codecs.h" @@ -66,7 +65,6 @@ GST_DEBUG_CATEGORY_STATIC (avdtp_sink_debug); struct bluetooth_data { - struct bt_get_capabilities_rsp *caps; /* Bluetooth device caps */ guint link_mtu; DBusConnection *conn; @@ -117,12 +115,6 @@ static GstStaticPadTemplate avdtp_sink_factory = GST_RTP_PAYLOAD_DYNAMIC_STRING ", " "clock-rate = (int) 90000, " "encoding-name = (string) \"MPA\"")); -static int gst_avdtp_sink_audioservice_send (GstAvdtpSink * self, - const bt_audio_msg_header_t * msg); -static int gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self, - bt_audio_msg_header_t * outmsg, guint8 expected_name); - - static void gst_avdtp_sink_base_init (gpointer g_class) { @@ -163,12 +155,6 @@ gst_avdtp_sink_stop (GstBaseSink * basesink) self->watch_id = 0; } - if (self->server) { - bt_audio_service_close (g_io_channel_unix_get_fd (self->server)); - g_io_channel_unref (self->server); - self->server = NULL; - } - if (self->stream) { g_io_channel_shutdown (self->stream, TRUE, NULL); g_io_channel_unref (self->stream); @@ -270,510 +256,6 @@ gst_avdtp_sink_get_property (GObject * object, guint prop_id, } } -static gint -gst_avdtp_sink_bluetooth_recvmsg_fd (GstAvdtpSink * sink) -{ - int err, ret; - - ret = bt_audio_service_get_data_fd (g_io_channel_unix_get_fd (sink->server)); - - if (ret < 0) { - err = -errno; - GST_ERROR_OBJECT (sink, "Unable to receive fd: %s (%d)", - strerror (-err), -err); - return err; - } - - sink->stream = g_io_channel_unix_new (ret); - g_io_channel_set_encoding (sink->stream, NULL, NULL); - GST_DEBUG_OBJECT (sink, "stream_fd=%d", ret); - - return 0; -} - -static codec_capabilities_t * -gst_avdtp_find_caps (GstAvdtpSink * sink, uint8_t codec_type) -{ - struct bt_get_capabilities_rsp *rsp = sink->data->caps; - codec_capabilities_t *codec = (void *) rsp->data; - int bytes_left = rsp->h.length - sizeof (*rsp); - - while (bytes_left > 0) { - if ((codec->type == codec_type) && !(codec->lock & BT_WRITE_LOCK)) - break; - - bytes_left -= codec->length; - codec = (void *) codec + codec->length; - } - - if (bytes_left <= 0) - return NULL; - - return codec; -} - -static gboolean -gst_avdtp_sink_init_sbc_pkt_conf (GstAvdtpSink * sink, - GstCaps * caps, sbc_capabilities_t * pkt) -{ - sbc_capabilities_t *cfg; - const GValue *value = NULL; - const char *pref, *name; - gint rate, subbands, blocks; - GstStructure *structure = gst_caps_get_structure (caps, 0); - - cfg = (void *) gst_avdtp_find_caps (sink, BT_A2DP_SBC_SINK); - name = gst_structure_get_name (structure); - - if (!(IS_SBC (name))) { - GST_ERROR_OBJECT (sink, "Unexpected format %s, " "was expecting sbc", name); - return FALSE; - } - - value = gst_structure_get_value (structure, "rate"); - rate = g_value_get_int (value); - if (rate == 44100) - cfg->frequency = BT_SBC_SAMPLING_FREQ_44100; - else if (rate == 48000) - cfg->frequency = BT_SBC_SAMPLING_FREQ_48000; - else if (rate == 32000) - cfg->frequency = BT_SBC_SAMPLING_FREQ_32000; - else if (rate == 16000) - cfg->frequency = BT_SBC_SAMPLING_FREQ_16000; - else { - GST_ERROR_OBJECT (sink, "Invalid rate while setting caps"); - return FALSE; - } - - value = gst_structure_get_value (structure, "mode"); - pref = g_value_get_string (value); - if (strcmp (pref, "mono") == 0) - cfg->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; - else if (strcmp (pref, "dual") == 0) - cfg->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; - else if (strcmp (pref, "stereo") == 0) - cfg->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; - else if (strcmp (pref, "joint") == 0) - cfg->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; - else { - GST_ERROR_OBJECT (sink, "Invalid mode %s", pref); - return FALSE; - } - - value = gst_structure_get_value (structure, "allocation"); - pref = g_value_get_string (value); - if (strcmp (pref, "loudness") == 0) - cfg->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; - else if (strcmp (pref, "snr") == 0) - cfg->allocation_method = BT_A2DP_ALLOCATION_SNR; - else { - GST_ERROR_OBJECT (sink, "Invalid allocation: %s", pref); - return FALSE; - } - - value = gst_structure_get_value (structure, "subbands"); - subbands = g_value_get_int (value); - if (subbands == 8) - cfg->subbands = BT_A2DP_SUBBANDS_8; - else if (subbands == 4) - cfg->subbands = BT_A2DP_SUBBANDS_4; - else { - GST_ERROR_OBJECT (sink, "Invalid subbands %d", subbands); - return FALSE; - } - - value = gst_structure_get_value (structure, "blocks"); - blocks = g_value_get_int (value); - if (blocks == 16) - cfg->block_length = BT_A2DP_BLOCK_LENGTH_16; - else if (blocks == 12) - cfg->block_length = BT_A2DP_BLOCK_LENGTH_12; - else if (blocks == 8) - cfg->block_length = BT_A2DP_BLOCK_LENGTH_8; - else if (blocks == 4) - cfg->block_length = BT_A2DP_BLOCK_LENGTH_4; - else { - GST_ERROR_OBJECT (sink, "Invalid blocks %d", blocks); - return FALSE; - } - - value = gst_structure_get_value (structure, "bitpool"); - cfg->max_bitpool = cfg->min_bitpool = g_value_get_int (value); - - memcpy (pkt, cfg, sizeof (*pkt)); - - return TRUE; -} - -static gboolean -gst_avdtp_sink_conf_recv_stream_fd (GstAvdtpSink * self) -{ - struct bluetooth_data *data = self->data; - gint ret; - GError *gerr = NULL; - GIOStatus status; - GIOFlags flags; - int fd; - - /* Proceed if stream was already acquired */ - if (self->stream != NULL) - goto proceed; - - ret = gst_avdtp_sink_bluetooth_recvmsg_fd (self); - if (ret < 0) - return FALSE; - - if (!self->stream) { - GST_ERROR_OBJECT (self, "Error while configuring device: " - "could not acquire audio socket"); - return FALSE; - } - -proceed: - /* set stream socket to nonblock */ - GST_LOG_OBJECT (self, "setting stream socket to nonblock"); - flags = g_io_channel_get_flags (self->stream); - flags |= G_IO_FLAG_NONBLOCK; - status = g_io_channel_set_flags (self->stream, flags, &gerr); - if (status != G_IO_STATUS_NORMAL) { - if (gerr) - GST_WARNING_OBJECT (self, "Error while " - "setting server socket to nonblock: " "%s", gerr->message); - else - GST_WARNING_OBJECT (self, "Error while " - "setting server " "socket to nonblock"); - } - - fd = g_io_channel_unix_get_fd (self->stream); - - /* It is possible there is some outstanding - data in the pipe - we have to empty it */ - GST_LOG_OBJECT (self, "emptying stream pipe"); - while (1) { - ssize_t bread = read (fd, data->buffer, data->link_mtu); - if (bread <= 0) - break; - } - - /* set stream socket to block */ - GST_LOG_OBJECT (self, "setting stream socket to block"); - flags = g_io_channel_get_flags (self->stream); - flags &= ~G_IO_FLAG_NONBLOCK; - status = g_io_channel_set_flags (self->stream, flags, &gerr); - if (status != G_IO_STATUS_NORMAL) { - if (gerr) - GST_WARNING_OBJECT (self, "Error while " - "setting server socket to block:" "%s", gerr->message); - else - GST_WARNING_OBJECT (self, "Error while " - "setting server " "socket to block"); - } - - memset (data->buffer, 0, sizeof (data->buffer)); - - return TRUE; -} - -static gboolean -server_callback (GIOChannel * chan, GIOCondition cond, gpointer data) -{ - if (cond & G_IO_HUP || cond & G_IO_NVAL) - return FALSE; - else if (cond & G_IO_ERR) - GST_WARNING_OBJECT (GST_AVDTP_SINK (data), "Untreated callback G_IO_ERR"); - - return TRUE; -} - -static GstStructure * -gst_avdtp_sink_parse_sbc_caps (GstAvdtpSink * self, sbc_capabilities_t * sbc) -{ - GstStructure *structure; - GValue *value; - GValue *list; - gboolean mono, stereo; - - if (sbc == NULL) - return NULL; - - structure = gst_structure_empty_new ("audio/x-sbc"); - value = g_value_init (g_new0 (GValue, 1), G_TYPE_STRING); - - /* mode */ - list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) { - g_value_set_static_string (value, "mono"); - gst_value_list_prepend_value (list, value); - } - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) { - g_value_set_static_string (value, "stereo"); - gst_value_list_prepend_value (list, value); - } - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) { - g_value_set_static_string (value, "dual"); - gst_value_list_prepend_value (list, value); - } - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) { - g_value_set_static_string (value, "joint"); - gst_value_list_prepend_value (list, value); - } - g_value_unset (value); - if (list) { - gst_structure_set_value (structure, "mode", list); - g_free (list); - list = NULL; - } - - /* subbands */ - list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - value = g_value_init (value, G_TYPE_INT); - if (sbc->subbands & BT_A2DP_SUBBANDS_4) { - g_value_set_int (value, 4); - gst_value_list_prepend_value (list, value); - } - if (sbc->subbands & BT_A2DP_SUBBANDS_8) { - g_value_set_int (value, 8); - gst_value_list_prepend_value (list, value); - } - g_value_unset (value); - if (list) { - gst_structure_set_value (structure, "subbands", list); - g_free (list); - list = NULL; - } - - /* blocks */ - value = g_value_init (value, G_TYPE_INT); - list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_16) { - g_value_set_int (value, 16); - gst_value_list_prepend_value (list, value); - } - if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_12) { - g_value_set_int (value, 12); - gst_value_list_prepend_value (list, value); - } - if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_8) { - g_value_set_int (value, 8); - gst_value_list_prepend_value (list, value); - } - if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_4) { - g_value_set_int (value, 4); - gst_value_list_prepend_value (list, value); - } - g_value_unset (value); - if (list) { - gst_structure_set_value (structure, "blocks", list); - g_free (list); - list = NULL; - } - - /* allocation */ - g_value_init (value, G_TYPE_STRING); - list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (sbc->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) { - g_value_set_static_string (value, "loudness"); - gst_value_list_prepend_value (list, value); - } - if (sbc->allocation_method & BT_A2DP_ALLOCATION_SNR) { - g_value_set_static_string (value, "snr"); - gst_value_list_prepend_value (list, value); - } - g_value_unset (value); - if (list) { - gst_structure_set_value (structure, "allocation", list); - g_free (list); - list = NULL; - } - - /* rate */ - g_value_init (value, G_TYPE_INT); - list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (sbc->frequency & BT_SBC_SAMPLING_FREQ_48000) { - g_value_set_int (value, 48000); - gst_value_list_prepend_value (list, value); - } - if (sbc->frequency & BT_SBC_SAMPLING_FREQ_44100) { - g_value_set_int (value, 44100); - gst_value_list_prepend_value (list, value); - } - if (sbc->frequency & BT_SBC_SAMPLING_FREQ_32000) { - g_value_set_int (value, 32000); - gst_value_list_prepend_value (list, value); - } - if (sbc->frequency & BT_SBC_SAMPLING_FREQ_16000) { - g_value_set_int (value, 16000); - gst_value_list_prepend_value (list, value); - } - g_value_unset (value); - if (list) { - gst_structure_set_value (structure, "rate", list); - g_free (list); - list = NULL; - } - - /* bitpool */ - value = g_value_init (value, GST_TYPE_INT_RANGE); - gst_value_set_int_range (value, - MIN (sbc->min_bitpool, TEMPLATE_MAX_BITPOOL), - MIN (sbc->max_bitpool, TEMPLATE_MAX_BITPOOL)); - gst_structure_set_value (structure, "bitpool", value); - g_value_unset (value); - - /* channels */ - mono = FALSE; - stereo = FALSE; - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) - mono = TRUE; - if ((sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) || - (sbc->channel_mode & - BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) || - (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)) - stereo = TRUE; - - if (mono && stereo) { - g_value_init (value, GST_TYPE_INT_RANGE); - gst_value_set_int_range (value, 1, 2); - } else { - g_value_init (value, G_TYPE_INT); - if (mono) - g_value_set_int (value, 1); - else if (stereo) - g_value_set_int (value, 2); - else { - GST_ERROR_OBJECT (self, "Unexpected number of channels"); - g_value_set_int (value, 0); - } - } - - gst_structure_set_value (structure, "channels", value); - g_free (value); - - return structure; -} - -static GstStructure * -gst_avdtp_sink_parse_mpeg_caps (GstAvdtpSink * self, mpeg_capabilities_t * mpeg) -{ - GstStructure *structure; - GValue *value; - GValue *list; - gboolean valid_layer = FALSE; - gboolean mono, stereo; - - if (!mpeg) - return NULL; - - GST_LOG_OBJECT (self, "parsing mpeg caps"); - - structure = gst_structure_empty_new ("audio/mpeg"); - value = g_new0 (GValue, 1); - g_value_init (value, G_TYPE_INT); - - list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - g_value_set_int (value, 1); - gst_value_list_prepend_value (list, value); - g_value_set_int (value, 2); - gst_value_list_prepend_value (list, value); - gst_structure_set_value (structure, "mpegversion", list); - g_free (list); - - /* layer */ - GST_LOG_OBJECT (self, "setting mpeg layer"); - list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (mpeg->layer & BT_MPEG_LAYER_1) { - g_value_set_int (value, 1); - gst_value_list_prepend_value (list, value); - valid_layer = TRUE; - } - if (mpeg->layer & BT_MPEG_LAYER_2) { - g_value_set_int (value, 2); - gst_value_list_prepend_value (list, value); - valid_layer = TRUE; - } - if (mpeg->layer & BT_MPEG_LAYER_3) { - g_value_set_int (value, 3); - gst_value_list_prepend_value (list, value); - valid_layer = TRUE; - } - if (list) { - gst_structure_set_value (structure, "layer", list); - g_free (list); - list = NULL; - } - - if (!valid_layer) { - gst_structure_free (structure); - g_free (value); - return NULL; - } - - /* rate */ - GST_LOG_OBJECT (self, "setting mpeg rate"); - list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_48000) { - g_value_set_int (value, 48000); - gst_value_list_prepend_value (list, value); - } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_44100) { - g_value_set_int (value, 44100); - gst_value_list_prepend_value (list, value); - } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_32000) { - g_value_set_int (value, 32000); - gst_value_list_prepend_value (list, value); - } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_24000) { - g_value_set_int (value, 24000); - gst_value_list_prepend_value (list, value); - } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_22050) { - g_value_set_int (value, 22050); - gst_value_list_prepend_value (list, value); - } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_16000) { - g_value_set_int (value, 16000); - gst_value_list_prepend_value (list, value); - } - g_value_unset (value); - if (list) { - gst_structure_set_value (structure, "rate", list); - g_free (list); - list = NULL; - } - - /* channels */ - GST_LOG_OBJECT (self, "setting mpeg channels"); - mono = FALSE; - stereo = FALSE; - if (mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) - mono = TRUE; - if ((mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) || - (mpeg->channel_mode & - BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) || - (mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)) - stereo = TRUE; - - if (mono && stereo) { - g_value_init (value, GST_TYPE_INT_RANGE); - gst_value_set_int_range (value, 1, 2); - } else { - g_value_init (value, G_TYPE_INT); - if (mono) - g_value_set_int (value, 1); - else if (stereo) - g_value_set_int (value, 2); - else { - GST_ERROR_OBJECT (self, "Unexpected number of channels"); - g_value_set_int (value, 0); - } - } - gst_structure_set_value (structure, "channels", value); - g_free (value); - - return structure; -} - static GstStructure * gst_avdtp_sink_parse_sbc_raw (GstAvdtpSink * self) { @@ -788,19 +270,19 @@ gst_avdtp_sink_parse_sbc_raw (GstAvdtpSink * self) /* mode */ list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) { + if (sbc->channel_mode & SBC_CHANNEL_MODE_MONO) { g_value_set_static_string (value, "mono"); gst_value_list_prepend_value (list, value); } - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) { + if (sbc->channel_mode & SBC_CHANNEL_MODE_STEREO) { g_value_set_static_string (value, "stereo"); gst_value_list_prepend_value (list, value); } - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) { + if (sbc->channel_mode & SBC_CHANNEL_MODE_DUAL_CHANNEL) { g_value_set_static_string (value, "dual"); gst_value_list_prepend_value (list, value); } - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) { + if (sbc->channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO) { g_value_set_static_string (value, "joint"); gst_value_list_prepend_value (list, value); } @@ -814,11 +296,11 @@ gst_avdtp_sink_parse_sbc_raw (GstAvdtpSink * self) /* subbands */ list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); value = g_value_init (value, G_TYPE_INT); - if (sbc->subbands & BT_A2DP_SUBBANDS_4) { + if (sbc->subbands & SBC_SUBBANDS_4) { g_value_set_int (value, 4); gst_value_list_prepend_value (list, value); } - if (sbc->subbands & BT_A2DP_SUBBANDS_8) { + if (sbc->subbands & SBC_SUBBANDS_8) { g_value_set_int (value, 8); gst_value_list_prepend_value (list, value); } @@ -832,19 +314,19 @@ gst_avdtp_sink_parse_sbc_raw (GstAvdtpSink * self) /* blocks */ value = g_value_init (value, G_TYPE_INT); list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_16) { + if (sbc->block_length & SBC_BLOCK_LENGTH_16) { g_value_set_int (value, 16); gst_value_list_prepend_value (list, value); } - if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_12) { + if (sbc->block_length & SBC_BLOCK_LENGTH_12) { g_value_set_int (value, 12); gst_value_list_prepend_value (list, value); } - if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_8) { + if (sbc->block_length & SBC_BLOCK_LENGTH_8) { g_value_set_int (value, 8); gst_value_list_prepend_value (list, value); } - if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_4) { + if (sbc->block_length & SBC_BLOCK_LENGTH_4) { g_value_set_int (value, 4); gst_value_list_prepend_value (list, value); } @@ -858,11 +340,11 @@ gst_avdtp_sink_parse_sbc_raw (GstAvdtpSink * self) /* allocation */ g_value_init (value, G_TYPE_STRING); list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (sbc->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) { + if (sbc->allocation_method & SBC_ALLOCATION_LOUDNESS) { g_value_set_static_string (value, "loudness"); gst_value_list_prepend_value (list, value); } - if (sbc->allocation_method & BT_A2DP_ALLOCATION_SNR) { + if (sbc->allocation_method & SBC_ALLOCATION_SNR) { g_value_set_static_string (value, "snr"); gst_value_list_prepend_value (list, value); } @@ -876,19 +358,19 @@ gst_avdtp_sink_parse_sbc_raw (GstAvdtpSink * self) /* rate */ g_value_init (value, G_TYPE_INT); list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (sbc->frequency & BT_SBC_SAMPLING_FREQ_48000) { + if (sbc->frequency & SBC_SAMPLING_FREQ_48000) { g_value_set_int (value, 48000); gst_value_list_prepend_value (list, value); } - if (sbc->frequency & BT_SBC_SAMPLING_FREQ_44100) { + if (sbc->frequency & SBC_SAMPLING_FREQ_44100) { g_value_set_int (value, 44100); gst_value_list_prepend_value (list, value); } - if (sbc->frequency & BT_SBC_SAMPLING_FREQ_32000) { + if (sbc->frequency & SBC_SAMPLING_FREQ_32000) { g_value_set_int (value, 32000); gst_value_list_prepend_value (list, value); } - if (sbc->frequency & BT_SBC_SAMPLING_FREQ_16000) { + if (sbc->frequency & SBC_SAMPLING_FREQ_16000) { g_value_set_int (value, 16000); gst_value_list_prepend_value (list, value); } @@ -910,12 +392,12 @@ gst_avdtp_sink_parse_sbc_raw (GstAvdtpSink * self) /* channels */ mono = FALSE; stereo = FALSE; - if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) + if (sbc->channel_mode & SBC_CHANNEL_MODE_MONO) mono = TRUE; - if ((sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) || + if ((sbc->channel_mode & SBC_CHANNEL_MODE_STEREO) || (sbc->channel_mode & - BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) || - (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)) + SBC_CHANNEL_MODE_DUAL_CHANNEL) || + (sbc->channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO)) stereo = TRUE; if (mono && stereo) { @@ -966,17 +448,17 @@ gst_avdtp_sink_parse_mpeg_raw (GstAvdtpSink * self) /* layer */ GST_LOG_OBJECT (self, "setting mpeg layer"); list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (mpeg->layer & BT_MPEG_LAYER_1) { + if (mpeg->layer & MPEG_LAYER_MP1) { g_value_set_int (value, 1); gst_value_list_prepend_value (list, value); valid_layer = TRUE; } - if (mpeg->layer & BT_MPEG_LAYER_2) { + if (mpeg->layer & MPEG_LAYER_MP2) { g_value_set_int (value, 2); gst_value_list_prepend_value (list, value); valid_layer = TRUE; } - if (mpeg->layer & BT_MPEG_LAYER_3) { + if (mpeg->layer & MPEG_LAYER_MP3) { g_value_set_int (value, 3); gst_value_list_prepend_value (list, value); valid_layer = TRUE; @@ -996,27 +478,27 @@ gst_avdtp_sink_parse_mpeg_raw (GstAvdtpSink * self) /* rate */ GST_LOG_OBJECT (self, "setting mpeg rate"); list = g_value_init (g_new0 (GValue, 1), GST_TYPE_LIST); - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_48000) { + if (mpeg->frequency & MPEG_SAMPLING_FREQ_48000) { g_value_set_int (value, 48000); gst_value_list_prepend_value (list, value); } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_44100) { + if (mpeg->frequency & MPEG_SAMPLING_FREQ_44100) { g_value_set_int (value, 44100); gst_value_list_prepend_value (list, value); } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_32000) { + if (mpeg->frequency & MPEG_SAMPLING_FREQ_32000) { g_value_set_int (value, 32000); gst_value_list_prepend_value (list, value); } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_24000) { + if (mpeg->frequency & MPEG_SAMPLING_FREQ_24000) { g_value_set_int (value, 24000); gst_value_list_prepend_value (list, value); } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_22050) { + if (mpeg->frequency & MPEG_SAMPLING_FREQ_22050) { g_value_set_int (value, 22050); gst_value_list_prepend_value (list, value); } - if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_16000) { + if (mpeg->frequency & MPEG_SAMPLING_FREQ_16000) { g_value_set_int (value, 16000); gst_value_list_prepend_value (list, value); } @@ -1031,12 +513,12 @@ gst_avdtp_sink_parse_mpeg_raw (GstAvdtpSink * self) GST_LOG_OBJECT (self, "setting mpeg channels"); mono = FALSE; stereo = FALSE; - if (mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) + if (mpeg->channel_mode & MPEG_CHANNEL_MODE_MONO) mono = TRUE; - if ((mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) || + if ((mpeg->channel_mode & MPEG_CHANNEL_MODE_STEREO) || (mpeg->channel_mode & - BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) || - (mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)) + MPEG_CHANNEL_MODE_DUAL_CHANNEL) || + (mpeg->channel_mode & MPEG_CHANNEL_MODE_JOINT_STEREO)) stereo = TRUE; if (mono && stereo) { @@ -1095,95 +577,25 @@ gst_avdtp_sink_update_config (GstAvdtpSink * self) static gboolean gst_avdtp_sink_update_caps (GstAvdtpSink * self) { - sbc_capabilities_t *sbc; - mpeg_capabilities_t *mpeg; - GstStructure *sbc_structure; - GstStructure *mpeg_structure; - gchar *tmp; - GST_LOG_OBJECT (self, "updating device caps"); - if (self->data->config_size != 0 && self->data->config != NULL) - return gst_avdtp_sink_update_config (self); - - sbc = (void *) gst_avdtp_find_caps (self, BT_A2DP_SBC_SINK); - mpeg = (void *) gst_avdtp_find_caps (self, BT_A2DP_MPEG12_SINK); - - if (!sbc) { - GST_ERROR_OBJECT (self, "Failed to find mandatory SBC sink"); + if (self->data->config_size == 0 || self->data->config == NULL) return FALSE; - } - sbc_structure = gst_avdtp_sink_parse_sbc_caps (self, sbc); - mpeg_structure = gst_avdtp_sink_parse_mpeg_caps (self, mpeg); - - if (self->dev_caps != NULL) - gst_caps_unref (self->dev_caps); - self->dev_caps = gst_caps_new_full (sbc_structure, NULL); - if (mpeg_structure != NULL) - gst_caps_append_structure (self->dev_caps, mpeg_structure); - - tmp = gst_caps_to_string (self->dev_caps); - GST_DEBUG_OBJECT (self, "Device capabilities: %s", tmp); - g_free (tmp); - - return TRUE; -} - -static gboolean -gst_avdtp_sink_get_capabilities (GstAvdtpSink * self) -{ - gchar buf[BT_SUGGESTED_BUFFER_SIZE]; - struct bt_get_capabilities_req *req = (void *) buf; - struct bt_get_capabilities_rsp *rsp = (void *) buf; - int err; - - memset (req, 0, BT_SUGGESTED_BUFFER_SIZE); - - req->h.type = BT_REQUEST; - req->h.name = BT_GET_CAPABILITIES; - req->h.length = sizeof (*req); - - if (self->device == NULL) - return FALSE; - strncpy (req->destination, self->device, 18); - if (self->autoconnect) - req->flags |= BT_FLAG_AUTOCONNECT; - - err = gst_avdtp_sink_audioservice_send (self, &req->h); - if (err < 0) { - GST_ERROR_OBJECT (self, "Error while asking device caps"); - return FALSE; - } - - rsp->h.length = 0; - err = gst_avdtp_sink_audioservice_expect (self, &rsp->h, BT_GET_CAPABILITIES); - if (err < 0) { - GST_ERROR_OBJECT (self, "Error while getting device caps"); - return FALSE; - } - - self->data->caps = g_malloc0 (rsp->h.length); - memcpy (self->data->caps, rsp, rsp->h.length); - if (!gst_avdtp_sink_update_caps (self)) { - GST_WARNING_OBJECT (self, "failed to update capabilities"); - return FALSE; - } - - return TRUE; + return gst_avdtp_sink_update_config (self); } static gint gst_avdtp_sink_get_channel_mode (const gchar * mode) { if (strcmp (mode, "stereo") == 0) - return BT_A2DP_CHANNEL_MODE_STEREO; + return SBC_CHANNEL_MODE_STEREO; else if (strcmp (mode, "joint-stereo") == 0) - return BT_A2DP_CHANNEL_MODE_JOINT_STEREO; + return SBC_CHANNEL_MODE_JOINT_STEREO; else if (strcmp (mode, "dual-channel") == 0) - return BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; + return SBC_CHANNEL_MODE_DUAL_CHANNEL; else if (strcmp (mode, "mono") == 0) - return BT_A2DP_CHANNEL_MODE_MONO; + return SBC_CHANNEL_MODE_MONO; else return -1; } @@ -1425,8 +837,6 @@ static gboolean gst_avdtp_sink_start (GstBaseSink * basesink) { GstAvdtpSink *self = GST_AVDTP_SINK (basesink); - gint sk; - gint err; GST_INFO_OBJECT (self, "start"); @@ -1437,244 +847,68 @@ gst_avdtp_sink_start (GstBaseSink * basesink) self->mp3_using_crc = -1; self->channel_mode = -1; - if (self->transport != NULL) - return gst_avdtp_sink_transport_get_properties (self); - - self->watch_id = 0; - - sk = bt_audio_service_open (); - if (sk < 0) { - err = -errno; - GST_ERROR_OBJECT (self, "Cannot open connection to bt " - "audio service: %s %d", strerror (-err), -err); + if (self->transport == NULL) return FALSE; - } - self->server = g_io_channel_unix_new (sk); - g_io_channel_set_encoding (self->server, NULL, NULL); - self->watch_id = g_io_add_watch (self->server, G_IO_HUP | G_IO_ERR | - G_IO_NVAL, server_callback, self); - - if (!gst_avdtp_sink_get_capabilities (self)) { - GST_ERROR_OBJECT (self, "failed to get capabilities " "from device"); - goto failed; - } - - return TRUE; - -failed: - bt_audio_service_close (sk); - return FALSE; + return gst_avdtp_sink_transport_get_properties (self); } static gboolean -gst_avdtp_sink_stream_start (GstAvdtpSink * self) +gst_avdtp_sink_conf_recv_stream_fd (GstAvdtpSink * self) { - gchar buf[BT_SUGGESTED_BUFFER_SIZE]; - struct bt_start_stream_req *req = (void *) buf; - struct bt_start_stream_rsp *rsp = (void *) buf; - struct bt_new_stream_ind *ind = (void *) buf; - int err; + struct bluetooth_data *data = self->data; + GError *gerr = NULL; + GIOStatus status; + GIOFlags flags; + int fd; - if (self->transport != NULL) - return gst_avdtp_sink_conf_recv_stream_fd (self); - - memset (req, 0, sizeof (buf)); - req->h.type = BT_REQUEST; - req->h.name = BT_START_STREAM; - req->h.length = sizeof (*req); - - err = gst_avdtp_sink_audioservice_send (self, &req->h); - if (err < 0) { - GST_ERROR_OBJECT (self, "Error occurred while sending " "start packet"); + /* Proceed if stream was already acquired */ + if (self->stream == NULL) { + GST_ERROR_OBJECT (self, "Error while configuring device: " + "could not acquire audio socket"); return FALSE; } - rsp->h.length = sizeof (*rsp); - err = gst_avdtp_sink_audioservice_expect (self, &rsp->h, BT_START_STREAM); - if (err < 0) { - GST_ERROR_OBJECT (self, "Error while stream " "start confirmation"); - return FALSE; + /* set stream socket to nonblock */ + GST_LOG_OBJECT (self, "setting stream socket to nonblock"); + flags = g_io_channel_get_flags (self->stream); + flags |= G_IO_FLAG_NONBLOCK; + status = g_io_channel_set_flags (self->stream, flags, &gerr); + if (status != G_IO_STATUS_NORMAL) { + if (gerr) + GST_WARNING_OBJECT (self, "Error while " + "setting server socket to nonblock: " "%s", gerr->message); + else + GST_WARNING_OBJECT (self, "Error while " + "setting server " "socket to nonblock"); } - ind->h.length = sizeof (*ind); - err = gst_avdtp_sink_audioservice_expect (self, &ind->h, BT_NEW_STREAM); - if (err < 0) { - GST_ERROR_OBJECT (self, "Error while receiving " "stream filedescriptor"); - return FALSE; + fd = g_io_channel_unix_get_fd (self->stream); + + /* It is possible there is some outstanding + data in the pipe - we have to empty it */ + GST_LOG_OBJECT (self, "emptying stream pipe"); + while (1) { + ssize_t bread = read (fd, data->buffer, data->link_mtu); + if (bread <= 0) + break; } - if (!gst_avdtp_sink_conf_recv_stream_fd (self)) - return FALSE; - - return TRUE; -} - -static gboolean -gst_avdtp_sink_init_mp3_pkt_conf (GstAvdtpSink * self, GstCaps * caps, - mpeg_capabilities_t * pkt) -{ - const GValue *value = NULL; - gint rate, layer; - const gchar *name; - GstStructure *structure = gst_caps_get_structure (caps, 0); - - name = gst_structure_get_name (structure); - - if (!(IS_MPEG_AUDIO (name))) { - GST_ERROR_OBJECT (self, "Unexpected format %s, " "was expecting mp3", name); - return FALSE; + /* set stream socket to block */ + GST_LOG_OBJECT (self, "setting stream socket to block"); + flags = g_io_channel_get_flags (self->stream); + flags &= ~G_IO_FLAG_NONBLOCK; + status = g_io_channel_set_flags (self->stream, flags, &gerr); + if (status != G_IO_STATUS_NORMAL) { + if (gerr) + GST_WARNING_OBJECT (self, "Error while " + "setting server socket to block:" "%s", gerr->message); + else + GST_WARNING_OBJECT (self, "Error while " + "setting server " "socket to block"); } - /* layer */ - value = gst_structure_get_value (structure, "layer"); - layer = g_value_get_int (value); - if (layer == 1) - pkt->layer = BT_MPEG_LAYER_1; - else if (layer == 2) - pkt->layer = BT_MPEG_LAYER_2; - else if (layer == 3) - pkt->layer = BT_MPEG_LAYER_3; - else { - GST_ERROR_OBJECT (self, "Unexpected layer: %d", layer); - return FALSE; - } - - /* crc */ - if (self->mp3_using_crc != -1) - pkt->crc = self->mp3_using_crc; - else { - GST_ERROR_OBJECT (self, "No info about crc was received, " - " can't proceed"); - return FALSE; - } - - /* channel mode */ - if (self->channel_mode != -1) - pkt->channel_mode = self->channel_mode; - else { - GST_ERROR_OBJECT (self, "No info about channel mode " - "received, can't proceed"); - return FALSE; - } - - /* mpf - we will only use the mandatory one */ - pkt->mpf = 0; - - value = gst_structure_get_value (structure, "rate"); - rate = g_value_get_int (value); - if (rate == 44100) - pkt->frequency = BT_MPEG_SAMPLING_FREQ_44100; - else if (rate == 48000) - pkt->frequency = BT_MPEG_SAMPLING_FREQ_48000; - else if (rate == 32000) - pkt->frequency = BT_MPEG_SAMPLING_FREQ_32000; - else if (rate == 24000) - pkt->frequency = BT_MPEG_SAMPLING_FREQ_24000; - else if (rate == 22050) - pkt->frequency = BT_MPEG_SAMPLING_FREQ_22050; - else if (rate == 16000) - pkt->frequency = BT_MPEG_SAMPLING_FREQ_16000; - else { - GST_ERROR_OBJECT (self, "Invalid rate while setting caps"); - return FALSE; - } - - /* vbr - we always say its vbr, we don't have how to know it */ - pkt->bitrate = 0x8000; - - return TRUE; -} - -static gboolean -gst_avdtp_sink_configure (GstAvdtpSink * self, GstCaps * caps) -{ - gchar buf[BT_SUGGESTED_BUFFER_SIZE]; - struct bt_open_req *open_req = (void *) buf; - struct bt_open_rsp *open_rsp = (void *) buf; - struct bt_set_configuration_req *req = (void *) buf; - struct bt_set_configuration_rsp *rsp = (void *) buf; - gboolean ret; - gchar *temp; - GstStructure *structure; - codec_capabilities_t *codec = NULL; - int err; - - temp = gst_caps_to_string (caps); - GST_DEBUG_OBJECT (self, "configuring device with caps: %s", temp); - g_free (temp); - - /* Transport already configured */ - if (self->transport != NULL) - return TRUE; - - structure = gst_caps_get_structure (caps, 0); - - if (gst_structure_has_name (structure, "audio/x-sbc")) - codec = (void *) gst_avdtp_find_caps (self, BT_A2DP_SBC_SINK); - else if (gst_structure_has_name (structure, "audio/mpeg")) - codec = (void *) gst_avdtp_find_caps (self, BT_A2DP_MPEG12_SINK); - - if (codec == NULL) { - GST_ERROR_OBJECT (self, "Couldn't parse caps " "to packet configuration"); - return FALSE; - } - - memset (req, 0, BT_SUGGESTED_BUFFER_SIZE); - open_req->h.type = BT_REQUEST; - open_req->h.name = BT_OPEN; - open_req->h.length = sizeof (*open_req); - - strncpy (open_req->destination, self->device, 18); - open_req->seid = codec->seid; - open_req->lock = BT_WRITE_LOCK; - - err = gst_avdtp_sink_audioservice_send (self, &open_req->h); - if (err < 0) { - GST_ERROR_OBJECT (self, "Error occurred while sending " "open packet"); - return FALSE; - } - - open_rsp->h.length = sizeof (*open_rsp); - err = gst_avdtp_sink_audioservice_expect (self, &open_rsp->h, BT_OPEN); - if (err < 0) { - GST_ERROR_OBJECT (self, "Error while receiving device " "confirmation"); - return FALSE; - } - - memset (req, 0, sizeof (buf)); - req->h.type = BT_REQUEST; - req->h.name = BT_SET_CONFIGURATION; - req->h.length = sizeof (*req); - memcpy (&req->codec, codec, sizeof (req->codec)); - - if (codec->type == BT_A2DP_SBC_SINK) - ret = gst_avdtp_sink_init_sbc_pkt_conf (self, caps, (void *) &req->codec); - else - ret = gst_avdtp_sink_init_mp3_pkt_conf (self, caps, (void *) &req->codec); - - if (!ret) { - GST_ERROR_OBJECT (self, "Couldn't parse caps " "to packet configuration"); - return FALSE; - } - - req->h.length += req->codec.length - sizeof (req->codec); - err = gst_avdtp_sink_audioservice_send (self, &req->h); - if (err < 0) { - GST_ERROR_OBJECT (self, "Error occurred while sending " - "configurarion packet"); - return FALSE; - } - - rsp->h.length = sizeof (*rsp); - err = gst_avdtp_sink_audioservice_expect (self, &rsp->h, - BT_SET_CONFIGURATION); - if (err < 0) { - GST_ERROR_OBJECT (self, "Error while receiving device " "confirmation"); - return FALSE; - } - - self->data->link_mtu = rsp->link_mtu; + memset (data->buffer, 0, sizeof (data->buffer)); return TRUE; } @@ -1687,7 +921,7 @@ gst_avdtp_sink_preroll (GstBaseSink * basesink, GstBuffer * buffer) GST_AVDTP_SINK_MUTEX_LOCK (sink); - ret = gst_avdtp_sink_stream_start (sink); + ret = gst_avdtp_sink_conf_recv_stream_fd (sink); GST_AVDTP_SINK_MUTEX_UNLOCK (sink); @@ -1807,98 +1041,6 @@ gst_avdtp_sink_init (GstAvdtpSink * self, GstAvdtpSinkClass * klass) */ } -static int -gst_avdtp_sink_audioservice_send (GstAvdtpSink * self, - const bt_audio_msg_header_t * msg) -{ - ssize_t written; - const char *type, *name; - uint16_t length; - int fd, err; - - length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE; - - fd = g_io_channel_unix_get_fd (self->server); - - written = write (fd, msg, length); - if (written < 0) { - err = -errno; - GST_ERROR_OBJECT (self, "Error sending data to audio service:" - " %s", strerror (-err)); - return err; - } - - type = bt_audio_strtype (msg->type); - name = bt_audio_strname (msg->name); - - GST_DEBUG_OBJECT (self, "sent: %s -> %s", type, name); - - return 0; -} - -static int -gst_avdtp_sink_audioservice_recv (GstAvdtpSink * self, - bt_audio_msg_header_t * inmsg) -{ - ssize_t bytes_read; - const char *type, *name; - uint16_t length; - int fd, err = 0; - - length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE; - - fd = g_io_channel_unix_get_fd (self->server); - - bytes_read = read (fd, inmsg, length); - if (bytes_read < 0) { - err = -errno; - GST_ERROR_OBJECT (self, "Error receiving data from " - "audio service: %s", strerror (-err)); - return err; - } - - type = bt_audio_strtype (inmsg->type); - if (!type) { - err = -EINVAL; - GST_ERROR_OBJECT (self, "Bogus message type %d " - "received from audio service", inmsg->type); - } - - name = bt_audio_strname (inmsg->name); - if (!name) { - err = -EINVAL; - GST_ERROR_OBJECT (self, "Bogus message name %d " - "received from audio service", inmsg->name); - } - - if (inmsg->type == BT_ERROR) { - bt_audio_error_t *msg = (void *) inmsg; - err = -EINVAL; - GST_ERROR_OBJECT (self, "%s failed : " - "%s(%d)", name, strerror (msg->posix_errno), msg->posix_errno); - } - - GST_DEBUG_OBJECT (self, "received: %s <- %s", type, name); - - return err; -} - -static int -gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self, - bt_audio_msg_header_t * outmsg, guint8 expected_name) -{ - int err; - - err = gst_avdtp_sink_audioservice_recv (self, outmsg); - if (err < 0) - return err; - - if (outmsg->name != expected_name) - return -EINVAL; - - return 0; -} - gboolean gst_avdtp_sink_plugin_init (GstPlugin * plugin) { @@ -1920,11 +1062,8 @@ gst_avdtp_sink_get_device_caps (GstAvdtpSink * sink) gboolean gst_avdtp_sink_set_device_caps (GstAvdtpSink * self, GstCaps * caps) { - gboolean ret; - GST_DEBUG_OBJECT (self, "setting device caps"); GST_AVDTP_SINK_MUTEX_LOCK (self); - ret = gst_avdtp_sink_configure (self, caps); if (self->stream_caps) gst_caps_unref (self->stream_caps); @@ -1932,7 +1071,7 @@ gst_avdtp_sink_set_device_caps (GstAvdtpSink * self, GstCaps * caps) GST_AVDTP_SINK_MUTEX_UNLOCK (self); - return ret; + return TRUE; } guint diff --git a/sys/bluez/gstavdtpsink.h b/sys/bluez/gstavdtpsink.h index c4e5645163..eb998ac41e 100644 --- a/sys/bluez/gstavdtpsink.h +++ b/sys/bluez/gstavdtpsink.h @@ -56,7 +56,6 @@ struct _GstAvdtpSink { struct bluetooth_data *data; gboolean autoconnect; - GIOChannel *server; /* mp3 stream data (outside caps data)*/ gint mp3_using_crc;