blob: 601791001cf1b847b14f0574851045c660c91bb5 [file] [log] [blame]
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001/*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
Marcel Holtmann9184e2e2010-01-01 17:08:17 -08005 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00006 *
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <unistd.h>
29#include <sys/un.h>
30#include <sys/socket.h>
31#include <fcntl.h>
32#include <pthread.h>
33
34#include <netinet/in.h>
35
36#include <bluetooth/bluetooth.h>
37
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +000038#include <gst/rtp/gstrtpbuffer.h>
39
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +030040#include <dbus/dbus.h>
41
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000042#include "rtp.h"
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +030043#include "a2dp-codecs.h"
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000044
Marcel Holtmanne20bd412010-05-19 16:59:30 +020045#include "gstpragma.h"
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +000046#include "gstavdtpsink.h"
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000047
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +000048GST_DEBUG_CATEGORY_STATIC(avdtp_sink_debug);
49#define GST_CAT_DEFAULT avdtp_sink_debug
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000050
51#define BUFFER_SIZE 2048
52#define TEMPLATE_MAX_BITPOOL 64
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +000053#define CRC_PROTECTED 1
54#define CRC_UNPROTECTED 0
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000055
Luiz Augusto von Dentz6c4268d2008-01-30 17:30:27 +000056#define DEFAULT_AUTOCONNECT TRUE
57
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +000058#define GST_AVDTP_SINK_MUTEX_LOCK(s) G_STMT_START { \
Johan Hedbergcc49c312008-12-20 21:42:49 +020059 g_mutex_lock(s->sink_lock); \
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000060 } G_STMT_END
61
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +000062#define GST_AVDTP_SINK_MUTEX_UNLOCK(s) G_STMT_START { \
Johan Hedbergcc49c312008-12-20 21:42:49 +020063 g_mutex_unlock(s->sink_lock); \
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000064 } G_STMT_END
65
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000066struct bluetooth_data {
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000067 guint link_mtu;
68
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +030069 DBusConnection *conn;
70 guint8 codec; /* Bluetooth transport configuration */
71 gchar *uuid;
72 guint8 *config;
73 gint config_size;
74
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000075 gchar buffer[BUFFER_SIZE]; /* Codec transfer buffer */
76};
77
78#define IS_SBC(n) (strcmp((n), "audio/x-sbc") == 0)
Luiz Augusto von Dentz3ad68672008-01-30 14:21:43 +000079#define IS_MPEG_AUDIO(n) (strcmp((n), "audio/mpeg") == 0)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000080
81enum {
82 PROP_0,
83 PROP_DEVICE,
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +030084 PROP_AUTOCONNECT,
85 PROP_TRANSPORT
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000086};
87
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +000088GST_BOILERPLATE(GstAvdtpSink, gst_avdtp_sink, GstBaseSink,
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000089 GST_TYPE_BASE_SINK);
90
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +000091static const GstElementDetails avdtp_sink_details =
92 GST_ELEMENT_DETAILS("Bluetooth AVDTP sink",
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000093 "Sink/Audio",
94 "Plays audio to an A2DP device",
95 "Marcel Holtmann <marcel@holtmann.org>");
96
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +000097static GstStaticPadTemplate avdtp_sink_factory =
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +000098 GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
99 GST_STATIC_CAPS("application/x-rtp, "
Luiz Augusto von Dentz3ad68672008-01-30 14:21:43 +0000100 "media = (string) \"audio\","
101 "payload = (int) "
102 GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
103 "clock-rate = (int) { 16000, 32000, "
104 "44100, 48000 }, "
105 "encoding-name = (string) \"SBC\"; "
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000106 "application/x-rtp, "
107 "media = (string) \"audio\", "
108 "payload = (int) "
109 GST_RTP_PAYLOAD_MPA_STRING ", "
110 "clock-rate = (int) 90000; "
111 "application/x-rtp, "
112 "media = (string) \"audio\", "
113 "payload = (int) "
114 GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
115 "clock-rate = (int) 90000, "
116 "encoding-name = (string) \"MPA\""
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000117 ));
118
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000119static void gst_avdtp_sink_base_init(gpointer g_class)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000120{
121 GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
122
123 gst_element_class_add_pad_template(element_class,
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000124 gst_static_pad_template_get(&avdtp_sink_factory));
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000125
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000126 gst_element_class_set_details(element_class, &avdtp_sink_details);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000127}
128
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300129static void gst_avdtp_sink_transport_release(GstAvdtpSink *self)
130{
131 DBusMessage *msg;
132 const char *access_type = "w";
133
134 msg = dbus_message_new_method_call("org.bluez", self->transport,
135 "org.bluez.MediaTransport",
136 "Release");
137
138 dbus_message_append_args(msg, DBUS_TYPE_STRING, &access_type,
139 DBUS_TYPE_INVALID);
140
141 dbus_connection_send(self->data->conn, msg, NULL);
142
143 dbus_message_unref(msg);
144}
145
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000146static gboolean gst_avdtp_sink_stop(GstBaseSink *basesink)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000147{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000148 GstAvdtpSink *self = GST_AVDTP_SINK(basesink);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000149
150 GST_INFO_OBJECT(self, "stop");
151
152 if (self->watch_id != 0) {
153 g_source_remove(self->watch_id);
154 self->watch_id = 0;
155 }
156
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000157 if (self->stream) {
Luiz Augusto von Dentz10d68582009-02-19 15:58:15 -0300158 g_io_channel_shutdown(self->stream, TRUE, NULL);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000159 g_io_channel_unref(self->stream);
160 self->stream = NULL;
161 }
162
163 if (self->data) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300164 if (self->transport)
165 gst_avdtp_sink_transport_release(self);
166 if (self->data->conn)
167 dbus_connection_unref(self->data->conn);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000168 g_free(self->data);
169 self->data = NULL;
170 }
171
172 if (self->stream_caps) {
173 gst_caps_unref(self->stream_caps);
174 self->stream_caps = NULL;
175 }
176
177 if (self->dev_caps) {
178 gst_caps_unref(self->dev_caps);
179 self->dev_caps = NULL;
180 }
181
182 return TRUE;
183}
184
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000185static void gst_avdtp_sink_finalize(GObject *object)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000186{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000187 GstAvdtpSink *self = GST_AVDTP_SINK(object);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000188
189 if (self->data)
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000190 gst_avdtp_sink_stop(GST_BASE_SINK(self));
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000191
192 if (self->device)
193 g_free(self->device);
194
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300195 if (self->transport)
196 g_free(self->transport);
197
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000198 g_mutex_free(self->sink_lock);
199
200 G_OBJECT_CLASS(parent_class)->finalize(object);
201}
202
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000203static void gst_avdtp_sink_set_property(GObject *object, guint prop_id,
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000204 const GValue *value, GParamSpec *pspec)
205{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000206 GstAvdtpSink *sink = GST_AVDTP_SINK(object);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000207
208 switch (prop_id) {
209 case PROP_DEVICE:
210 if (sink->device)
211 g_free(sink->device);
212 sink->device = g_value_dup_string(value);
213 break;
214
Luiz Augusto von Dentz6c4268d2008-01-30 17:30:27 +0000215 case PROP_AUTOCONNECT:
216 sink->autoconnect = g_value_get_boolean(value);
217 break;
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300218
219 case PROP_TRANSPORT:
220 if (sink->transport)
221 g_free(sink->transport);
222 sink->transport = g_value_dup_string(value);
223 break;
224
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000225 default:
226 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
227 break;
228 }
229}
230
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000231static void gst_avdtp_sink_get_property(GObject *object, guint prop_id,
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000232 GValue *value, GParamSpec *pspec)
233{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000234 GstAvdtpSink *sink = GST_AVDTP_SINK(object);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000235
236 switch (prop_id) {
237 case PROP_DEVICE:
238 g_value_set_string(value, sink->device);
239 break;
240
Luiz Augusto von Dentz6c4268d2008-01-30 17:30:27 +0000241 case PROP_AUTOCONNECT:
242 g_value_set_boolean(value, sink->autoconnect);
243 break;
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300244
245 case PROP_TRANSPORT:
246 g_value_set_string(value, sink->transport);
247 break;
248
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000249 default:
250 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
251 break;
252 }
253}
254
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300255static GstStructure *gst_avdtp_sink_parse_sbc_raw(GstAvdtpSink *self)
256{
257 a2dp_sbc_t *sbc = (a2dp_sbc_t *) self->data->config;
258 GstStructure *structure;
259 GValue *value;
260 GValue *list;
261 gboolean mono, stereo;
262
263 structure = gst_structure_empty_new("audio/x-sbc");
264 value = g_value_init(g_new0(GValue, 1), G_TYPE_STRING);
265
266 /* mode */
267 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300268 if (sbc->channel_mode & SBC_CHANNEL_MODE_MONO) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300269 g_value_set_static_string(value, "mono");
270 gst_value_list_prepend_value(list, value);
271 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300272 if (sbc->channel_mode & SBC_CHANNEL_MODE_STEREO) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300273 g_value_set_static_string(value, "stereo");
274 gst_value_list_prepend_value(list, value);
275 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300276 if (sbc->channel_mode & SBC_CHANNEL_MODE_DUAL_CHANNEL) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300277 g_value_set_static_string(value, "dual");
278 gst_value_list_prepend_value(list, value);
279 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300280 if (sbc->channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300281 g_value_set_static_string(value, "joint");
282 gst_value_list_prepend_value(list, value);
283 }
284 g_value_unset(value);
285 if (list) {
286 gst_structure_set_value(structure, "mode", list);
287 g_free(list);
288 list = NULL;
289 }
290
291 /* subbands */
292 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
293 value = g_value_init(value, G_TYPE_INT);
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300294 if (sbc->subbands & SBC_SUBBANDS_4) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300295 g_value_set_int(value, 4);
296 gst_value_list_prepend_value(list, value);
297 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300298 if (sbc->subbands & SBC_SUBBANDS_8) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300299 g_value_set_int(value, 8);
300 gst_value_list_prepend_value(list, value);
301 }
302 g_value_unset(value);
303 if (list) {
304 gst_structure_set_value(structure, "subbands", list);
305 g_free(list);
306 list = NULL;
307 }
308
309 /* blocks */
310 value = g_value_init(value, G_TYPE_INT);
311 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300312 if (sbc->block_length & SBC_BLOCK_LENGTH_16) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300313 g_value_set_int(value, 16);
314 gst_value_list_prepend_value(list, value);
315 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300316 if (sbc->block_length & SBC_BLOCK_LENGTH_12) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300317 g_value_set_int(value, 12);
318 gst_value_list_prepend_value(list, value);
319 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300320 if (sbc->block_length & SBC_BLOCK_LENGTH_8) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300321 g_value_set_int(value, 8);
322 gst_value_list_prepend_value(list, value);
323 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300324 if (sbc->block_length & SBC_BLOCK_LENGTH_4) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300325 g_value_set_int(value, 4);
326 gst_value_list_prepend_value(list, value);
327 }
328 g_value_unset(value);
329 if (list) {
330 gst_structure_set_value(structure, "blocks", list);
331 g_free(list);
332 list = NULL;
333 }
334
335 /* allocation */
336 g_value_init(value, G_TYPE_STRING);
337 list = g_value_init(g_new0(GValue,1), GST_TYPE_LIST);
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300338 if (sbc->allocation_method & SBC_ALLOCATION_LOUDNESS) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300339 g_value_set_static_string(value, "loudness");
340 gst_value_list_prepend_value(list, value);
341 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300342 if (sbc->allocation_method & SBC_ALLOCATION_SNR) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300343 g_value_set_static_string(value, "snr");
344 gst_value_list_prepend_value(list, value);
345 }
346 g_value_unset(value);
347 if (list) {
348 gst_structure_set_value(structure, "allocation", list);
349 g_free(list);
350 list = NULL;
351 }
352
353 /* rate */
354 g_value_init(value, G_TYPE_INT);
355 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300356 if (sbc->frequency & SBC_SAMPLING_FREQ_48000) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300357 g_value_set_int(value, 48000);
358 gst_value_list_prepend_value(list, value);
359 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300360 if (sbc->frequency & SBC_SAMPLING_FREQ_44100) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300361 g_value_set_int(value, 44100);
362 gst_value_list_prepend_value(list, value);
363 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300364 if (sbc->frequency & SBC_SAMPLING_FREQ_32000) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300365 g_value_set_int(value, 32000);
366 gst_value_list_prepend_value(list, value);
367 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300368 if (sbc->frequency & SBC_SAMPLING_FREQ_16000) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300369 g_value_set_int(value, 16000);
370 gst_value_list_prepend_value(list, value);
371 }
372 g_value_unset(value);
373 if (list) {
374 gst_structure_set_value(structure, "rate", list);
375 g_free(list);
376 list = NULL;
377 }
378
379 /* bitpool */
380 value = g_value_init(value, GST_TYPE_INT_RANGE);
381 gst_value_set_int_range(value,
382 MIN(sbc->min_bitpool, TEMPLATE_MAX_BITPOOL),
383 MIN(sbc->max_bitpool, TEMPLATE_MAX_BITPOOL));
384 gst_structure_set_value(structure, "bitpool", value);
385 g_value_unset(value);
386
387 /* channels */
388 mono = FALSE;
389 stereo = FALSE;
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300390 if (sbc->channel_mode & SBC_CHANNEL_MODE_MONO)
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300391 mono = TRUE;
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300392 if ((sbc->channel_mode & SBC_CHANNEL_MODE_STEREO) ||
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300393 (sbc->channel_mode &
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300394 SBC_CHANNEL_MODE_DUAL_CHANNEL) ||
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300395 (sbc->channel_mode &
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300396 SBC_CHANNEL_MODE_JOINT_STEREO))
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300397 stereo = TRUE;
398
399 if (mono && stereo) {
400 g_value_init(value, GST_TYPE_INT_RANGE);
401 gst_value_set_int_range(value, 1, 2);
402 } else {
403 g_value_init(value, G_TYPE_INT);
404 if (mono)
405 g_value_set_int(value, 1);
406 else if (stereo)
407 g_value_set_int(value, 2);
408 else {
409 GST_ERROR_OBJECT(self,
410 "Unexpected number of channels");
411 g_value_set_int(value, 0);
412 }
413 }
414
415 gst_structure_set_value(structure, "channels", value);
416 g_free(value);
417
418 return structure;
419}
420
421static GstStructure *gst_avdtp_sink_parse_mpeg_raw(GstAvdtpSink *self)
422{
423 a2dp_mpeg_t *mpeg = (a2dp_mpeg_t *) self->data->config;
424 GstStructure *structure;
425 GValue *value;
426 GValue *list;
427 gboolean valid_layer = FALSE;
428 gboolean mono, stereo;
429
430 GST_LOG_OBJECT(self, "parsing mpeg caps");
431
432 structure = gst_structure_empty_new("audio/mpeg");
433 value = g_new0(GValue, 1);
434 g_value_init(value, G_TYPE_INT);
435
436 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
437 g_value_set_int(value, 1);
438 gst_value_list_prepend_value(list, value);
439 g_value_set_int(value, 2);
440 gst_value_list_prepend_value(list, value);
441 gst_structure_set_value(structure, "mpegversion", list);
442 g_free(list);
443
444 /* layer */
445 GST_LOG_OBJECT(self, "setting mpeg layer");
446 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300447 if (mpeg->layer & MPEG_LAYER_MP1) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300448 g_value_set_int(value, 1);
449 gst_value_list_prepend_value(list, value);
450 valid_layer = TRUE;
451 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300452 if (mpeg->layer & MPEG_LAYER_MP2) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300453 g_value_set_int(value, 2);
454 gst_value_list_prepend_value(list, value);
455 valid_layer = TRUE;
456 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300457 if (mpeg->layer & MPEG_LAYER_MP3) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300458 g_value_set_int(value, 3);
459 gst_value_list_prepend_value(list, value);
460 valid_layer = TRUE;
461 }
462 if (list) {
463 gst_structure_set_value(structure, "layer", list);
464 g_free(list);
465 list = NULL;
466 }
467
468 if (!valid_layer) {
469 gst_structure_free(structure);
470 g_free(value);
471 return NULL;
472 }
473
474 /* rate */
475 GST_LOG_OBJECT(self, "setting mpeg rate");
476 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300477 if (mpeg->frequency & MPEG_SAMPLING_FREQ_48000) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300478 g_value_set_int(value, 48000);
479 gst_value_list_prepend_value(list, value);
480 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300481 if (mpeg->frequency & MPEG_SAMPLING_FREQ_44100) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300482 g_value_set_int(value, 44100);
483 gst_value_list_prepend_value(list, value);
484 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300485 if (mpeg->frequency & MPEG_SAMPLING_FREQ_32000) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300486 g_value_set_int(value, 32000);
487 gst_value_list_prepend_value(list, value);
488 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300489 if (mpeg->frequency & MPEG_SAMPLING_FREQ_24000) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300490 g_value_set_int(value, 24000);
491 gst_value_list_prepend_value(list, value);
492 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300493 if (mpeg->frequency & MPEG_SAMPLING_FREQ_22050) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300494 g_value_set_int(value, 22050);
495 gst_value_list_prepend_value(list, value);
496 }
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300497 if (mpeg->frequency & MPEG_SAMPLING_FREQ_16000) {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300498 g_value_set_int(value, 16000);
499 gst_value_list_prepend_value(list, value);
500 }
501 g_value_unset(value);
502 if (list) {
503 gst_structure_set_value(structure, "rate", list);
504 g_free(list);
505 list = NULL;
506 }
507
508 /* channels */
509 GST_LOG_OBJECT(self, "setting mpeg channels");
510 mono = FALSE;
511 stereo = FALSE;
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300512 if (mpeg->channel_mode & MPEG_CHANNEL_MODE_MONO)
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300513 mono = TRUE;
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300514 if ((mpeg->channel_mode & MPEG_CHANNEL_MODE_STEREO) ||
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300515 (mpeg->channel_mode &
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300516 MPEG_CHANNEL_MODE_DUAL_CHANNEL) ||
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300517 (mpeg->channel_mode &
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300518 MPEG_CHANNEL_MODE_JOINT_STEREO))
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300519 stereo = TRUE;
520
521 if (mono && stereo) {
522 g_value_init(value, GST_TYPE_INT_RANGE);
523 gst_value_set_int_range(value, 1, 2);
524 } else {
525 g_value_init(value, G_TYPE_INT);
526 if (mono)
527 g_value_set_int(value, 1);
528 else if (stereo)
529 g_value_set_int(value, 2);
530 else {
531 GST_ERROR_OBJECT(self,
532 "Unexpected number of channels");
533 g_value_set_int(value, 0);
534 }
535 }
536 gst_structure_set_value(structure, "channels", value);
537 g_free(value);
538
539 return structure;
540}
541
542static gboolean gst_avdtp_sink_update_config(GstAvdtpSink *self)
543{
544 GstStructure *structure;
545 gchar *tmp;
546
547 switch (self->data->codec) {
548 case A2DP_CODEC_SBC:
549 structure = gst_avdtp_sink_parse_sbc_raw(self);
550 break;
551 case A2DP_CODEC_MPEG12:
552 structure = gst_avdtp_sink_parse_mpeg_raw(self);
553 break;
554 default:
555 GST_ERROR_OBJECT(self, "Unsupported configuration");
556 return FALSE;
557 }
558
559 if (structure == NULL)
560 return FALSE;
561
562 if (self->dev_caps != NULL)
563 gst_caps_unref(self->dev_caps);
564
565 self->dev_caps = gst_caps_new_full(structure, NULL);
566
567 tmp = gst_caps_to_string(self->dev_caps);
568 GST_DEBUG_OBJECT(self, "Transport configuration: %s", tmp);
569 g_free(tmp);
570
571 return TRUE;
572}
573
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000574static gboolean gst_avdtp_sink_update_caps(GstAvdtpSink *self)
Luiz Augusto von Dentz489c2e02008-01-23 13:16:02 +0000575{
Luiz Augusto von Dentz489c2e02008-01-23 13:16:02 +0000576 GST_LOG_OBJECT(self, "updating device caps");
577
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300578 if (self->data->config_size == 0 || self->data->config == NULL)
Chan-yeol Park5c092d32012-04-16 11:59:59 +0900579 return FALSE;
Chan-yeol Park5c092d32012-04-16 11:59:59 +0900580
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300581 return gst_avdtp_sink_update_config(self);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000582}
583
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000584static gint gst_avdtp_sink_get_channel_mode(const gchar *mode)
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000585{
586 if (strcmp(mode, "stereo") == 0)
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300587 return SBC_CHANNEL_MODE_STEREO;
Luiz Augusto von Dentzf4250652008-10-07 11:55:58 -0300588 else if (strcmp(mode, "joint-stereo") == 0)
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300589 return SBC_CHANNEL_MODE_JOINT_STEREO;
Luiz Augusto von Dentzb65d02a2008-10-07 12:07:14 -0300590 else if (strcmp(mode, "dual-channel") == 0)
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300591 return SBC_CHANNEL_MODE_DUAL_CHANNEL;
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000592 else if (strcmp(mode, "mono") == 0)
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300593 return SBC_CHANNEL_MODE_MONO;
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000594 else
595 return -1;
596}
597
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000598static void gst_avdtp_sink_tag(const GstTagList *taglist,
Johan Hedbergb0f85af2008-12-20 21:04:44 +0200599 const gchar *tag, gpointer user_data)
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000600{
601 gboolean crc;
602 gchar *channel_mode = NULL;
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000603 GstAvdtpSink *self = GST_AVDTP_SINK(user_data);
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000604
605 if (strcmp(tag, "has-crc") == 0) {
606
607 if (!gst_tag_list_get_boolean(taglist, tag, &crc)) {
608 GST_WARNING_OBJECT(self, "failed to get crc tag");
Luiz Augusto von Dentz3ad68672008-01-30 14:21:43 +0000609 return;
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000610 }
611
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000612 gst_avdtp_sink_set_crc(self, crc);
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000613
614 } else if (strcmp(tag, "channel-mode") == 0) {
615
616 if (!gst_tag_list_get_string(taglist, tag, &channel_mode)) {
617 GST_WARNING_OBJECT(self,
618 "failed to get channel-mode tag");
Luiz Augusto von Dentz3ad68672008-01-30 14:21:43 +0000619 return;
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000620 }
621
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000622 self->channel_mode = gst_avdtp_sink_get_channel_mode(
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000623 channel_mode);
624 if (self->channel_mode == -1)
625 GST_WARNING_OBJECT(self, "Received invalid channel "
626 "mode: %s", channel_mode);
627 g_free(channel_mode);
628
629 } else
630 GST_DEBUG_OBJECT(self, "received unused tag: %s", tag);
631}
632
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000633static gboolean gst_avdtp_sink_event(GstBaseSink *basesink,
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000634 GstEvent *event)
635{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000636 GstAvdtpSink *self = GST_AVDTP_SINK(basesink);
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000637 GstTagList *taglist = NULL;
638
639 if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
640 /* we check the tags, mp3 has tags that are importants and
641 * are outside caps */
642 gst_event_parse_tag(event, &taglist);
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000643 gst_tag_list_foreach(taglist, gst_avdtp_sink_tag, self);
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +0000644 }
645
646 return TRUE;
647}
648
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300649static gboolean gst_avdtp_sink_transport_parse_property(GstAvdtpSink *self,
650 DBusMessageIter *i)
651{
652 const char *key;
653 DBusMessageIter variant_i;
654
655 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) {
656 GST_ERROR_OBJECT(self, "Property name not a string.");
657 return FALSE;
658 }
659
660 dbus_message_iter_get_basic(i, &key);
661
662 if (!dbus_message_iter_next(i)) {
663 GST_ERROR_OBJECT(self, "Property value missing");
664 return FALSE;
665 }
666
667 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) {
668 GST_ERROR_OBJECT(self, "Property value not a variant.");
669 return FALSE;
670 }
671
672 dbus_message_iter_recurse(i, &variant_i);
673
674 switch (dbus_message_iter_get_arg_type(&variant_i)) {
675 case DBUS_TYPE_BYTE: {
676 uint8_t value;
677 dbus_message_iter_get_basic(&variant_i, &value);
678
679 if (g_str_equal(key, "Codec") == TRUE)
680 self->data->codec = value;
681
682 break;
683 }
Luiz Augusto von Dentzdec7a252011-01-20 11:29:41 +0200684 case DBUS_TYPE_STRING: {
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300685 const char *value;
686 dbus_message_iter_get_basic(&variant_i, &value);
687
688 if (g_str_equal(key, "UUID") == TRUE) {
689 g_free(self->data->uuid);
690 self->data->uuid = g_strdup(value);
691 }
692
693 break;
694 }
695 case DBUS_TYPE_ARRAY: {
696 DBusMessageIter array_i;
697 char *value;
698 int size;
699
700 dbus_message_iter_recurse(&variant_i, &array_i);
701 dbus_message_iter_get_fixed_array(&array_i, &value, &size);
702
703 if (g_str_equal(key, "Configuration")) {
704 g_free(self->data->config);
705 self->data->config = g_new0(guint8, size);
706 self->data->config_size = size;
707 memcpy(self->data->config, value, size);
708 }
709
710 break;
711 }
712 }
713
714 return TRUE;
715}
716
717static gboolean gst_avdtp_sink_transport_acquire(GstAvdtpSink *self)
718{
719 DBusMessage *msg, *reply;
720 DBusError err;
721 const char *access_type = "w";
722 int fd;
Luiz Augusto von Dentzdec7a252011-01-20 11:29:41 +0200723 uint16_t imtu, omtu;
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300724
725 dbus_error_init(&err);
726
727 if (self->data->conn == NULL)
728 self->data->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
729
730 msg = dbus_message_new_method_call("org.bluez", self->transport,
731 "org.bluez.MediaTransport",
732 "Acquire");
733
734 dbus_message_append_args(msg, DBUS_TYPE_STRING, &access_type,
735 DBUS_TYPE_INVALID);
736
737 reply = dbus_connection_send_with_reply_and_block(self->data->conn,
738 msg, -1, &err);
739
Syam Sidhardhan9ec21322012-04-12 20:32:55 +0530740 dbus_message_unref(msg);
741
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300742 if (dbus_error_is_set(&err))
743 goto fail;
744
745 if (dbus_message_get_args(reply, &err, DBUS_TYPE_UNIX_FD, &fd,
Luiz Augusto von Dentzdec7a252011-01-20 11:29:41 +0200746 DBUS_TYPE_UINT16, &imtu,
747 DBUS_TYPE_UINT16, &omtu,
748 DBUS_TYPE_INVALID) == FALSE)
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300749 goto fail;
750
751 dbus_message_unref(reply);
752
753 self->stream = g_io_channel_unix_new(fd);
Luiz Augusto von Dentz4aecf0a2011-01-19 10:04:49 +0200754 g_io_channel_set_encoding(self->stream, NULL, NULL);
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300755 g_io_channel_set_close_on_unref(self->stream, TRUE);
Luiz Augusto von Dentzdec7a252011-01-20 11:29:41 +0200756 self->data->link_mtu = omtu;
757 GST_DEBUG_OBJECT(self, "stream_fd=%d mtu=%d", fd, omtu);
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300758
759 return TRUE;
760
761fail:
762 GST_ERROR_OBJECT(self, "Failed to acquire transport stream: %s",
763 err.message);
764
765 dbus_error_free(&err);
766
767 if (reply)
Syam Sidhardhan9ec21322012-04-12 20:32:55 +0530768 dbus_message_unref(reply);
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300769
770 return FALSE;
771}
772
773static gboolean gst_avdtp_sink_transport_get_properties(GstAvdtpSink *self)
774{
775 DBusMessage *msg, *reply;
776 DBusMessageIter arg_i, ele_i;
777 DBusError err;
778
779 dbus_error_init(&err);
780
781 /* Transport need to be acquire first to make sure the MTUs are
782 available */
783 if (gst_avdtp_sink_transport_acquire(self) == FALSE)
784 return FALSE;
785
786 msg = dbus_message_new_method_call("org.bluez", self->transport,
787 "org.bluez.MediaTransport",
788 "GetProperties");
Syam Sidhardhan7730ff42012-09-14 21:40:10 +0530789 if (!msg) {
790 GST_ERROR_OBJECT(self, "D-Bus Memory allocation failed");
791 return FALSE;
792 }
793
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300794 reply = dbus_connection_send_with_reply_and_block(self->data->conn,
795 msg, -1, &err);
Syam Sidhardhan7730ff42012-09-14 21:40:10 +0530796 dbus_message_unref(msg);
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300797
Syam Sidhardhan7730ff42012-09-14 21:40:10 +0530798 if (dbus_error_is_set(&err)) {
799 GST_ERROR_OBJECT(self, "GetProperties failed: %s", err.message);
800 dbus_error_free(&err);
801 return FALSE;
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300802 }
803
804 if (!dbus_message_iter_init(reply, &arg_i)) {
805 GST_ERROR_OBJECT(self, "GetProperties reply has no arguments.");
806 goto fail;
807 }
808
809 if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
810 GST_ERROR_OBJECT(self, "GetProperties argument is not an array.");
811 goto fail;
812 }
813
814 dbus_message_iter_recurse(&arg_i, &ele_i);
815 while (dbus_message_iter_get_arg_type(&ele_i) != DBUS_TYPE_INVALID) {
816
817 if (dbus_message_iter_get_arg_type(&ele_i) ==
818 DBUS_TYPE_DICT_ENTRY) {
819 DBusMessageIter dict_i;
820
821 dbus_message_iter_recurse(&ele_i, &dict_i);
822
823 gst_avdtp_sink_transport_parse_property(self, &dict_i);
824 }
825
826 if (!dbus_message_iter_next(&ele_i))
827 break;
828 }
829
830 return gst_avdtp_sink_update_caps(self);
831
832fail:
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300833 dbus_message_unref(reply);
834 return FALSE;
835
836}
837
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000838static gboolean gst_avdtp_sink_start(GstBaseSink *basesink)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000839{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000840 GstAvdtpSink *self = GST_AVDTP_SINK(basesink);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000841
842 GST_INFO_OBJECT(self, "start");
843
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +0300844 self->data = g_new0(struct bluetooth_data, 1);
845
846 self->stream = NULL;
847 self->stream_caps = NULL;
848 self->mp3_using_crc = -1;
849 self->channel_mode = -1;
850
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300851 if (self->transport == NULL)
Anderson Lizardo5e9048c2011-11-17 13:29:06 -0400852 return FALSE;
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000853
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300854 return gst_avdtp_sink_transport_get_properties(self);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000855}
856
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300857static gboolean gst_avdtp_sink_conf_recv_stream_fd(GstAvdtpSink *self)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000858{
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300859 struct bluetooth_data *data = self->data;
860 GError *gerr = NULL;
861 GIOStatus status;
862 GIOFlags flags;
863 int fd;
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000864
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300865 /* Proceed if stream was already acquired */
866 if (self->stream == NULL) {
867 GST_ERROR_OBJECT(self, "Error while configuring device: "
868 "could not acquire audio socket");
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000869 return FALSE;
870 }
871
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300872 /* set stream socket to nonblock */
873 GST_LOG_OBJECT(self, "setting stream socket to nonblock");
874 flags = g_io_channel_get_flags(self->stream);
875 flags |= G_IO_FLAG_NONBLOCK;
876 status = g_io_channel_set_flags(self->stream, flags, &gerr);
877 if (status != G_IO_STATUS_NORMAL) {
878 if (gerr)
879 GST_WARNING_OBJECT(self, "Error while "
880 "setting server socket to nonblock: "
881 "%s", gerr->message);
882 else
883 GST_WARNING_OBJECT(self, "Error while "
884 "setting server "
885 "socket to nonblock");
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000886 }
887
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300888 fd = g_io_channel_unix_get_fd(self->stream);
889
890 /* It is possible there is some outstanding
891 data in the pipe - we have to empty it */
892 GST_LOG_OBJECT(self, "emptying stream pipe");
893 while (1) {
894 ssize_t bread = read(fd, data->buffer, data->link_mtu);
895 if (bread <= 0)
896 break;
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000897 }
898
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300899 /* set stream socket to block */
900 GST_LOG_OBJECT(self, "setting stream socket to block");
901 flags = g_io_channel_get_flags(self->stream);
902 flags &= ~G_IO_FLAG_NONBLOCK;
903 status = g_io_channel_set_flags(self->stream, flags, &gerr);
904 if (status != G_IO_STATUS_NORMAL) {
905 if (gerr)
906 GST_WARNING_OBJECT(self, "Error while "
907 "setting server socket to block:"
908 "%s", gerr->message);
909 else
910 GST_WARNING_OBJECT(self, "Error while "
911 "setting server "
912 "socket to block");
Luiz Augusto von Dentz3ad68672008-01-30 14:21:43 +0000913 }
914
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300915 memset(data->buffer, 0, sizeof(data->buffer));
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000916
917 return TRUE;
918}
919
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000920static GstFlowReturn gst_avdtp_sink_preroll(GstBaseSink *basesink,
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000921 GstBuffer *buffer)
922{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000923 GstAvdtpSink *sink = GST_AVDTP_SINK(basesink);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000924 gboolean ret;
925
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000926 GST_AVDTP_SINK_MUTEX_LOCK(sink);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000927
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +0300928 ret = gst_avdtp_sink_conf_recv_stream_fd(sink);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000929
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000930 GST_AVDTP_SINK_MUTEX_UNLOCK(sink);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000931
932 if (!ret)
933 return GST_FLOW_ERROR;
934
935 return GST_FLOW_OK;
936}
937
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000938static GstFlowReturn gst_avdtp_sink_render(GstBaseSink *basesink,
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000939 GstBuffer *buffer)
940{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000941 GstAvdtpSink *self = GST_AVDTP_SINK(basesink);
Luiz Augusto von Dentz4aecf0a2011-01-19 10:04:49 +0200942 ssize_t ret;
943 int fd;
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000944
Luiz Augusto von Dentz4aecf0a2011-01-19 10:04:49 +0200945 fd = g_io_channel_unix_get_fd(self->stream);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000946
Luiz Augusto von Dentz4aecf0a2011-01-19 10:04:49 +0200947 ret = write(fd, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
948 if (ret < 0) {
949 GST_ERROR_OBJECT(self, "Error while writting to socket: %s",
950 strerror(errno));
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000951 return GST_FLOW_ERROR;
952 }
953
954 return GST_FLOW_OK;
955}
956
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000957static gboolean gst_avdtp_sink_unlock(GstBaseSink *basesink)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000958{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000959 GstAvdtpSink *self = GST_AVDTP_SINK(basesink);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000960
961 if (self->stream != NULL)
Johan Hedbergcc49c312008-12-20 21:42:49 +0200962 g_io_channel_flush(self->stream, NULL);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000963
964 return TRUE;
965}
966
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000967static GstFlowReturn gst_avdtp_sink_buffer_alloc(GstBaseSink *basesink,
Johan Hedbergb0f85af2008-12-20 21:04:44 +0200968 guint64 offset, guint size, GstCaps *caps,
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000969 GstBuffer **buf)
970{
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000971 GstAvdtpSink *self = GST_AVDTP_SINK(basesink);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000972
973 *buf = gst_buffer_new_and_alloc(size);
974 if (!(*buf)) {
975 GST_ERROR_OBJECT(self, "buffer allocation failed");
976 return GST_FLOW_ERROR;
977 }
978
979 gst_buffer_set_caps(*buf, caps);
980
981 GST_BUFFER_OFFSET(*buf) = offset;
982
983 return GST_FLOW_OK;
984}
985
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000986static void gst_avdtp_sink_class_init(GstAvdtpSinkClass *klass)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000987{
988 GObjectClass *object_class = G_OBJECT_CLASS(klass);
989 GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS(klass);
990
991 parent_class = g_type_class_peek_parent(klass);
992
993 object_class->finalize = GST_DEBUG_FUNCPTR(
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000994 gst_avdtp_sink_finalize);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000995 object_class->set_property = GST_DEBUG_FUNCPTR(
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000996 gst_avdtp_sink_set_property);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000997 object_class->get_property = GST_DEBUG_FUNCPTR(
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +0000998 gst_avdtp_sink_get_property);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +0000999
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001000 basesink_class->start = GST_DEBUG_FUNCPTR(gst_avdtp_sink_start);
1001 basesink_class->stop = GST_DEBUG_FUNCPTR(gst_avdtp_sink_stop);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001002 basesink_class->render = GST_DEBUG_FUNCPTR(
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001003 gst_avdtp_sink_render);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001004 basesink_class->preroll = GST_DEBUG_FUNCPTR(
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001005 gst_avdtp_sink_preroll);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001006 basesink_class->unlock = GST_DEBUG_FUNCPTR(
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001007 gst_avdtp_sink_unlock);
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +00001008 basesink_class->event = GST_DEBUG_FUNCPTR(
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001009 gst_avdtp_sink_event);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001010
1011 basesink_class->buffer_alloc =
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001012 GST_DEBUG_FUNCPTR(gst_avdtp_sink_buffer_alloc);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001013
1014 g_object_class_install_property(object_class, PROP_DEVICE,
1015 g_param_spec_string("device", "Device",
1016 "Bluetooth remote device address",
1017 NULL, G_PARAM_READWRITE));
1018
Luiz Augusto von Dentz6c4268d2008-01-30 17:30:27 +00001019 g_object_class_install_property(object_class, PROP_AUTOCONNECT,
1020 g_param_spec_boolean("auto-connect",
1021 "Auto-connect",
1022 "Automatically attempt to connect "
1023 "to device", DEFAULT_AUTOCONNECT,
1024 G_PARAM_READWRITE));
1025
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +03001026 g_object_class_install_property(object_class, PROP_TRANSPORT,
1027 g_param_spec_string("transport",
1028 "Transport",
1029 "Use configured transport",
1030 NULL, G_PARAM_READWRITE));
1031
Luiz Augusto von Dentz3ad68672008-01-30 14:21:43 +00001032 GST_DEBUG_CATEGORY_INIT(avdtp_sink_debug, "avdtpsink", 0,
1033 "A2DP headset sink element");
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001034}
1035
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001036static void gst_avdtp_sink_init(GstAvdtpSink *self,
1037 GstAvdtpSinkClass *klass)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001038{
1039 self->device = NULL;
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +03001040 self->transport = NULL;
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001041 self->data = NULL;
1042
1043 self->stream = NULL;
1044
1045 self->dev_caps = NULL;
1046
Luiz Augusto von Dentz6c4268d2008-01-30 17:30:27 +00001047 self->autoconnect = DEFAULT_AUTOCONNECT;
1048
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001049 self->sink_lock = g_mutex_new();
Luiz Augusto von Dentz3ad68672008-01-30 14:21:43 +00001050
1051 /* FIXME this is for not synchronizing with clock, should be tested
1052 * with devices to see the behaviour
1053 gst_base_sink_set_sync(GST_BASE_SINK(self), FALSE);
1054 */
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001055}
1056
Johan Hedbergcc49c312008-12-20 21:42:49 +02001057gboolean gst_avdtp_sink_plugin_init(GstPlugin *plugin)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001058{
Johan Hedbergcc49c312008-12-20 21:42:49 +02001059 return gst_element_register(plugin, "avdtpsink", GST_RANK_NONE,
1060 GST_TYPE_AVDTP_SINK);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001061}
1062
1063
1064/* public functions */
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001065GstCaps *gst_avdtp_sink_get_device_caps(GstAvdtpSink *sink)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001066{
1067 if (sink->dev_caps == NULL)
1068 return NULL;
1069
1070 return gst_caps_copy(sink->dev_caps);
1071}
1072
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001073gboolean gst_avdtp_sink_set_device_caps(GstAvdtpSink *self,
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001074 GstCaps *caps)
1075{
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001076 GST_DEBUG_OBJECT(self, "setting device caps");
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001077 GST_AVDTP_SINK_MUTEX_LOCK(self);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001078
1079 if (self->stream_caps)
1080 gst_caps_unref(self->stream_caps);
1081 self->stream_caps = gst_caps_ref(caps);
1082
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001083 GST_AVDTP_SINK_MUTEX_UNLOCK(self);
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001084
Luiz Augusto von Dentzf2bdd722012-06-25 12:06:17 +03001085 return TRUE;
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001086}
1087
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001088guint gst_avdtp_sink_get_link_mtu(GstAvdtpSink *sink)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001089{
1090 return sink->data->link_mtu;
1091}
1092
Johan Hedbergb0f85af2008-12-20 21:04:44 +02001093void gst_avdtp_sink_set_device(GstAvdtpSink *self, const gchar *dev)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001094{
1095 if (self->device != NULL)
1096 g_free(self->device);
1097
1098 GST_LOG_OBJECT(self, "Setting device: %s", dev);
1099 self->device = g_strdup(dev);
1100}
1101
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +03001102void gst_avdtp_sink_set_transport(GstAvdtpSink *self, const gchar *trans)
1103{
1104 if (self->transport != NULL)
1105 g_free(self->transport);
1106
1107 GST_LOG_OBJECT(self, "Setting transport: %s", trans);
1108 self->transport = g_strdup(trans);
1109}
1110
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001111gchar *gst_avdtp_sink_get_device(GstAvdtpSink *self)
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001112{
1113 return g_strdup(self->device);
1114}
1115
Luiz Augusto von Dentz36227902010-05-06 17:14:14 +03001116gchar *gst_avdtp_sink_get_transport(GstAvdtpSink *self)
1117{
1118 return g_strdup(self->transport);
1119}
1120
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001121void gst_avdtp_sink_set_crc(GstAvdtpSink *self, gboolean crc)
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +00001122{
1123 gint new_crc;
1124
1125 new_crc = crc ? CRC_PROTECTED : CRC_UNPROTECTED;
1126
1127 /* test if we already received a different crc */
1128 if (self->mp3_using_crc != -1 && new_crc != self->mp3_using_crc) {
Luiz Augusto von Dentz3ad68672008-01-30 14:21:43 +00001129 GST_WARNING_OBJECT(self, "crc changed during stream");
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +00001130 return;
1131 }
1132 self->mp3_using_crc = new_crc;
1133
1134}
1135
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001136void gst_avdtp_sink_set_channel_mode(GstAvdtpSink *self,
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +00001137 const gchar *mode)
1138{
1139 gint new_mode;
1140
Luiz Augusto von Dentze8e68d22008-01-23 15:18:15 +00001141 new_mode = gst_avdtp_sink_get_channel_mode(mode);
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +00001142
1143 if (self->channel_mode != -1 && new_mode != self->channel_mode) {
Luiz Augusto von Dentz3ad68672008-01-30 14:21:43 +00001144 GST_WARNING_OBJECT(self, "channel mode changed during stream");
1145 return;
Luiz Augusto von Dentzde8b4e72008-01-23 13:19:32 +00001146 }
1147
1148 self->channel_mode = new_mode;
1149 if (self->channel_mode == -1)
1150 GST_WARNING_OBJECT(self, "Received invalid channel "
1151 "mode: %s", mode);
1152}