blob: cfb67b87b7a37fd9455c1c322340aacbe90c1b8a [file] [log] [blame]
Luiz Augusto von Dentza0af7ee2008-01-23 13:14:02 +00001/*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
5 * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org>
6 *
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
38#include "ipc.h"
39#include "rtp.h"
40#include "gstsbcutil.h"
41
42#include "gsta2dpsendersink.h"
43
44GST_DEBUG_CATEGORY_STATIC(a2dp_sender_sink_debug);
45#define GST_CAT_DEFAULT a2dp_sender_sink_debug
46
47#define BUFFER_SIZE 2048
48#define TEMPLATE_MAX_BITPOOL 64
49
50#define GST_A2DP_SENDER_SINK_MUTEX_LOCK(s) G_STMT_START { \
51 g_mutex_lock (s->sink_lock); \
52 } G_STMT_END
53
54#define GST_A2DP_SENDER_SINK_MUTEX_UNLOCK(s) G_STMT_START { \
55 g_mutex_unlock (s->sink_lock); \
56 } G_STMT_END
57
58
59struct bluetooth_data {
60 struct bt_getcapabilities_rsp caps; /* Bluetooth device caps */
61 guint link_mtu;
62
63 gchar buffer[BUFFER_SIZE]; /* Codec transfer buffer */
64};
65
66#define IS_SBC(n) (strcmp((n), "audio/x-sbc") == 0)
67#define IS_MPEG(n) (strcmp((n), "audio/mpeg") == 0)
68
69enum {
70 PROP_0,
71 PROP_DEVICE,
72};
73
74GST_BOILERPLATE(GstA2dpSenderSink, gst_a2dp_sender_sink, GstBaseSink,
75 GST_TYPE_BASE_SINK);
76
77static const GstElementDetails a2dp_sender_sink_details =
78 GST_ELEMENT_DETAILS("Bluetooth A2DP sink",
79 "Sink/Audio",
80 "Plays audio to an A2DP device",
81 "Marcel Holtmann <marcel@holtmann.org>");
82
83static GstStaticPadTemplate a2dp_sender_sink_factory =
84 GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
85 GST_STATIC_CAPS("application/x-rtp, "
86 "media = (string) \"audio\", "
87 "encoding-name = (string) \"SBC\""
88 ));
89
90static GIOError gst_a2dp_sender_sink_audioservice_send(GstA2dpSenderSink *self,
91 const bt_audio_msg_header_t *msg);
92static GIOError gst_a2dp_sender_sink_audioservice_expect(
93 GstA2dpSenderSink *self,
94 bt_audio_msg_header_t *outmsg,
95 int expected_type);
96
97
98static void gst_a2dp_sender_sink_base_init(gpointer g_class)
99{
100 GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
101
102 gst_element_class_add_pad_template(element_class,
103 gst_static_pad_template_get(&a2dp_sender_sink_factory));
104
105 gst_element_class_set_details(element_class, &a2dp_sender_sink_details);
106}
107
108static gboolean gst_a2dp_sender_sink_stop(GstBaseSink *basesink)
109{
110 GstA2dpSenderSink *self = GST_A2DP_SENDER_SINK(basesink);
111
112 GST_INFO_OBJECT(self, "stop");
113
114 if (self->watch_id != 0) {
115 g_source_remove(self->watch_id);
116 self->watch_id = 0;
117 }
118
119 if (self->server) {
120 bt_audio_service_close(g_io_channel_unix_get_fd(self->server));
121 g_io_channel_unref(self->server);
122 self->server = NULL;
123 }
124
125 if (self->stream) {
126 g_io_channel_flush(self->stream, NULL);
127 g_io_channel_close(self->stream);
128 g_io_channel_unref(self->stream);
129 self->stream = NULL;
130 }
131
132 if (self->data) {
133 g_free(self->data);
134 self->data = NULL;
135 }
136
137 if (self->stream_caps) {
138 gst_caps_unref(self->stream_caps);
139 self->stream_caps = NULL;
140 }
141
142 if (self->dev_caps) {
143 gst_caps_unref(self->dev_caps);
144 self->dev_caps = NULL;
145 }
146
147 return TRUE;
148}
149
150static void gst_a2dp_sender_sink_finalize(GObject *object)
151{
152 GstA2dpSenderSink *self = GST_A2DP_SENDER_SINK(object);
153
154 if (self->data)
155 gst_a2dp_sender_sink_stop(GST_BASE_SINK(self));
156
157 if (self->device)
158 g_free(self->device);
159
160 g_mutex_free(self->sink_lock);
161
162 G_OBJECT_CLASS(parent_class)->finalize(object);
163}
164
165static void gst_a2dp_sender_sink_set_property(GObject *object, guint prop_id,
166 const GValue *value, GParamSpec *pspec)
167{
168 GstA2dpSenderSink *sink = GST_A2DP_SENDER_SINK(object);
169
170 switch (prop_id) {
171 case PROP_DEVICE:
172 if (sink->device)
173 g_free(sink->device);
174 sink->device = g_value_dup_string(value);
175 break;
176
177 default:
178 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
179 break;
180 }
181}
182
183static void gst_a2dp_sender_sink_get_property(GObject *object, guint prop_id,
184 GValue *value, GParamSpec *pspec)
185{
186 GstA2dpSenderSink *sink = GST_A2DP_SENDER_SINK(object);
187
188 switch (prop_id) {
189 case PROP_DEVICE:
190 g_value_set_string(value, sink->device);
191 break;
192
193 default:
194 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
195 break;
196 }
197}
198
199static gint gst_a2dp_sender_sink_bluetooth_recvmsg_fd(GstA2dpSenderSink *sink)
200{
201 int err, ret;
202
203 ret = bt_audio_service_get_data_fd(
204 g_io_channel_unix_get_fd(sink->server));
205
206 if (ret < 0) {
207 err = errno;
208 GST_ERROR_OBJECT(sink, "Unable to receive fd: %s (%d)",
209 strerror(err), err);
210 return -err;
211 }
212
213 sink->stream = g_io_channel_unix_new(ret);
214 GST_DEBUG_OBJECT(sink, "stream_fd=%d", ret);
215
216 return 0;
217}
218
219static gboolean gst_a2dp_sender_sink_init_pkt_conf(GstA2dpSenderSink *sink,
220 GstCaps *caps,
221 sbc_capabilities_t *pkt)
222{
223 sbc_capabilities_t *cfg = &sink->data->caps.sbc_capabilities;
224 const GValue *value = NULL;
225 const char *pref, *name;
226 gint rate, subbands, blocks;
227 GstStructure *structure = gst_caps_get_structure(caps, 0);
228
229 name = gst_structure_get_name(structure);
230 /* FIXME only sbc supported here, should suport mp3 */
231 if (!(IS_SBC(name))) {
232 GST_ERROR_OBJECT(sink, "Unsupported format %s", name);
233 return FALSE;
234 }
235
236 value = gst_structure_get_value(structure, "rate");
237 rate = g_value_get_int(value);
238 if (rate == 44100)
239 cfg->frequency = BT_A2DP_SAMPLING_FREQ_44100;
240 else if (rate == 48000)
241 cfg->frequency = BT_A2DP_SAMPLING_FREQ_48000;
242 else if (rate == 32000)
243 cfg->frequency = BT_A2DP_SAMPLING_FREQ_32000;
244 else if (rate == 16000)
245 cfg->frequency = BT_A2DP_SAMPLING_FREQ_16000;
246 else {
247 GST_ERROR_OBJECT(sink, "Invalid rate while setting caps");
248 return FALSE;
249 }
250
251 value = gst_structure_get_value(structure, "mode");
252 pref = g_value_get_string(value);
253 if (strcmp(pref, "auto") == 0)
254 cfg->channel_mode = BT_A2DP_CHANNEL_MODE_AUTO;
255 else if (strcmp(pref, "mono") == 0)
256 cfg->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
257 else if (strcmp(pref, "dual") == 0)
258 cfg->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
259 else if (strcmp(pref, "stereo") == 0)
260 cfg->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
261 else if (strcmp(pref, "joint") == 0)
262 cfg->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
263 else {
264 GST_ERROR_OBJECT(sink, "Invalid mode %s", pref);
265 return FALSE;
266 }
267
268 value = gst_structure_get_value(structure, "allocation");
269 pref = g_value_get_string(value);
270 if (strcmp(pref, "auto") == 0)
271 cfg->allocation_method = BT_A2DP_ALLOCATION_AUTO;
272 else if (strcmp(pref, "loudness") == 0)
273 cfg->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
274 else if (strcmp(pref, "snr") == 0)
275 cfg->allocation_method = BT_A2DP_ALLOCATION_SNR;
276 else {
277 GST_ERROR_OBJECT(sink, "Invalid allocation: %s", pref);
278 return FALSE;
279 }
280
281 value = gst_structure_get_value(structure, "subbands");
282 subbands = g_value_get_int(value);
283 if (subbands == 8)
284 cfg->subbands = BT_A2DP_SUBBANDS_8;
285 else if (subbands == 4)
286 cfg->subbands = BT_A2DP_SUBBANDS_4;
287 else {
288 GST_ERROR_OBJECT(sink, "Invalid subbands %d", subbands);
289 return FALSE;
290 }
291
292 value = gst_structure_get_value(structure, "blocks");
293 blocks = g_value_get_int(value);
294 if (blocks == 16)
295 cfg->block_length = BT_A2DP_BLOCK_LENGTH_16;
296 else if (blocks == 12)
297 cfg->block_length = BT_A2DP_BLOCK_LENGTH_12;
298 else if (blocks == 8)
299 cfg->block_length = BT_A2DP_BLOCK_LENGTH_8;
300 else if (blocks == 4)
301 cfg->block_length = BT_A2DP_BLOCK_LENGTH_4;
302 else {
303 GST_ERROR_OBJECT(sink, "Invalid blocks %d", blocks);
304 return FALSE;
305 }
306
307 value = gst_structure_get_value(structure, "bitpool");
308 cfg->max_bitpool = cfg->min_bitpool = g_value_get_int(value);
309
310 memcpy(pkt, cfg, sizeof(*pkt));
311
312 return TRUE;
313}
314
315static gboolean gst_a2dp_sender_sink_conf_recv_stream_fd(
316 GstA2dpSenderSink *self)
317{
318 struct bluetooth_data *data = self->data;
319 gint ret;
320 GIOError err;
321 GError *gerr = NULL;
322 GIOStatus status;
323 GIOFlags flags;
324 gsize read;
325
326 ret = gst_a2dp_sender_sink_bluetooth_recvmsg_fd(self);
327 if (ret < 0)
328 return FALSE;
329
330 if (!self->stream) {
331 GST_ERROR_OBJECT(self, "Error while configuring device: "
332 "could not acquire audio socket");
333 return FALSE;
334 }
335
336 /* set stream socket to nonblock */
337 GST_LOG_OBJECT(self, "setting stream socket to nonblock");
338 flags = g_io_channel_get_flags(self->stream);
339 flags |= G_IO_FLAG_NONBLOCK;
340 status = g_io_channel_set_flags(self->stream, flags, &gerr);
341 if (status != G_IO_STATUS_NORMAL) {
342 if (gerr)
343 GST_WARNING_OBJECT(self, "Error while "
344 "setting server socket to nonblock: "
345 "%s", gerr->message);
346 else
347 GST_WARNING_OBJECT(self, "Error while "
348 "setting server "
349 "socket to nonblock");
350 }
351
352 /* It is possible there is some outstanding
353 data in the pipe - we have to empty it */
354 GST_LOG_OBJECT(self, "emptying stream pipe");
355 while (1) {
356 err = g_io_channel_read(self->stream, data->buffer,
357 (gsize) data->link_mtu,
358 &read);
359 if (err != G_IO_ERROR_NONE || read <= 0)
360 break;
361 }
362
363 /* set stream socket to block */
364 GST_LOG_OBJECT(self, "setting stream socket to block");
365 flags = g_io_channel_get_flags(self->stream);
366 flags &= ~G_IO_FLAG_NONBLOCK;
367 status = g_io_channel_set_flags(self->stream, flags, &gerr);
368 if (status != G_IO_STATUS_NORMAL) {
369 if (gerr)
370 GST_WARNING_OBJECT(self, "Error while "
371 "setting server socket to block:"
372 "%s", gerr->message);
373 else
374 GST_WARNING_OBJECT(self, "Error while "
375 "setting server "
376 "socket to block");
377 }
378
379 memset(data->buffer, 0, sizeof(data->buffer));
380
381 return TRUE;
382}
383
384static gboolean server_callback(GIOChannel *chan,
385 GIOCondition cond, gpointer data)
386{
387 GstA2dpSenderSink *sink;
388
389 if (cond & G_IO_HUP || cond & G_IO_NVAL)
390 return FALSE;
391 else if (cond & G_IO_ERR) {
392 sink = GST_A2DP_SENDER_SINK(data);
393 GST_WARNING_OBJECT(sink, "Untreated callback G_IO_ERR");
394 }
395
396 return TRUE;
397}
398
399static gboolean gst_a2dp_sender_sink_update_caps(GstA2dpSenderSink *self)
400{
401 sbc_capabilities_t *sbc = &self->data->caps.sbc_capabilities;
402 GstStructure *structure;
403 GValue *value;
404 GValue *list;
405 gchar *tmp;
406 gboolean mono, stereo;
407
408 GST_LOG_OBJECT(self, "updating device caps");
409
410 structure = gst_structure_empty_new("audio/x-sbc");
411 value = g_value_init(g_new0(GValue, 1), G_TYPE_STRING);
412
413 /* mode */
414 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
415 if (sbc->channel_mode == BT_A2DP_CHANNEL_MODE_AUTO) {
416 g_value_set_static_string(value, "joint");
417 gst_value_list_prepend_value(list, value);
418 g_value_set_static_string(value, "stereo");
419 gst_value_list_prepend_value(list, value);
420 g_value_set_static_string(value, "mono");
421 gst_value_list_prepend_value(list, value);
422 g_value_set_static_string(value, "dual");
423 gst_value_list_prepend_value(list, value);
424 } else {
425 if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) {
426 g_value_set_static_string(value, "mono");
427 gst_value_list_prepend_value(list, value);
428 }
429 if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) {
430 g_value_set_static_string(value, "stereo");
431 gst_value_list_prepend_value(list, value);
432 }
433 if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) {
434 g_value_set_static_string(value, "dual");
435 gst_value_list_prepend_value(list, value);
436 }
437 if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) {
438 g_value_set_static_string(value, "joint");
439 gst_value_list_prepend_value(list, value);
440 }
441 }
442 g_value_unset(value);
443 if (list) {
444 gst_structure_set_value(structure, "mode", list);
445 g_free(list);
446 list = NULL;
447 }
448
449 /* subbands */
450 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
451 value = g_value_init(value, G_TYPE_INT);
452 if (sbc->subbands & BT_A2DP_SUBBANDS_4) {
453 g_value_set_int(value, 4);
454 gst_value_list_prepend_value(list, value);
455 }
456 if (sbc->subbands & BT_A2DP_SUBBANDS_8) {
457 g_value_set_int(value, 8);
458 gst_value_list_prepend_value(list, value);
459 }
460 g_value_unset(value);
461 if (list) {
462 gst_structure_set_value(structure, "subbands", list);
463 g_free(list);
464 list = NULL;
465 }
466
467 /* blocks */
468 value = g_value_init(value, G_TYPE_INT);
469 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
470 if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_16) {
471 g_value_set_int(value, 16);
472 gst_value_list_prepend_value(list, value);
473 }
474 if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_12) {
475 g_value_set_int(value, 12);
476 gst_value_list_prepend_value(list, value);
477 }
478 if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_8) {
479 g_value_set_int(value, 8);
480 gst_value_list_prepend_value(list, value);
481 }
482 if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_4) {
483 g_value_set_int(value, 4);
484 gst_value_list_prepend_value(list, value);
485 }
486 g_value_unset(value);
487 if (list) {
488 gst_structure_set_value(structure, "blocks", list);
489 g_free(list);
490 list = NULL;
491 }
492
493 /* allocation */
494 g_value_init(value, G_TYPE_STRING);
495 list = g_value_init(g_new0(GValue,1), GST_TYPE_LIST);
496 if (sbc->allocation_method == BT_A2DP_ALLOCATION_AUTO) {
497 g_value_set_static_string(value, "loudness");
498 gst_value_list_prepend_value(list, value);
499 g_value_set_static_string(value, "snr");
500 gst_value_list_prepend_value(list, value);
501 } else {
502 if (sbc->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) {
503 g_value_set_static_string(value, "loudness");
504 gst_value_list_prepend_value(list, value);
505 }
506 if (sbc->allocation_method & BT_A2DP_ALLOCATION_SNR) {
507 g_value_set_static_string(value, "snr");
508 gst_value_list_prepend_value(list, value);
509 }
510 }
511 g_value_unset(value);
512 if (list) {
513 gst_structure_set_value(structure, "allocation", list);
514 g_free(list);
515 list = NULL;
516 }
517
518 /* rate */
519 g_value_init(value, G_TYPE_INT);
520 list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST);
521 if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_48000) {
522 g_value_set_int(value, 48000);
523 gst_value_list_prepend_value(list, value);
524 }
525 if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_44100) {
526 g_value_set_int(value, 44100);
527 gst_value_list_prepend_value(list, value);
528 }
529 if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_32000) {
530 g_value_set_int(value, 32000);
531 gst_value_list_prepend_value(list, value);
532 }
533 if (sbc->frequency & BT_A2DP_SAMPLING_FREQ_16000) {
534 g_value_set_int(value, 16000);
535 gst_value_list_prepend_value(list, value);
536 }
537 g_value_unset(value);
538 if (list) {
539 gst_structure_set_value(structure, "rate", list);
540 g_free(list);
541 list = NULL;
542 }
543
544 /* bitpool */
545 value = g_value_init(value, GST_TYPE_INT_RANGE);
546 gst_value_set_int_range(value,
547 MIN(sbc->min_bitpool, TEMPLATE_MAX_BITPOOL),
548 MIN(sbc->max_bitpool, TEMPLATE_MAX_BITPOOL));
549 gst_structure_set_value(structure, "bitpool", value);
550 g_value_unset(value);
551
552 /* channels */
553 if (sbc->channel_mode == BT_A2DP_CHANNEL_MODE_AUTO) {
554 g_value_init(value, GST_TYPE_INT_RANGE);
555 gst_value_set_int_range(value, 1, 2);
556 } else {
557 mono = FALSE;
558 stereo = FALSE;
559 if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
560 mono = TRUE;
561 if ((sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) ||
562 (sbc->channel_mode &
563 BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) ||
564 (sbc->channel_mode &
565 BT_A2DP_CHANNEL_MODE_JOINT_STEREO))
566 stereo = TRUE;
567
568 if (mono && stereo) {
569 g_value_init(value, GST_TYPE_INT_RANGE);
570 gst_value_set_int_range(value, 1, 2);
571 } else {
572 g_value_init(value, G_TYPE_INT);
573 if (mono)
574 g_value_set_int(value, 1);
575 else if (stereo)
576 g_value_set_int(value, 2);
577 else {
578 GST_ERROR_OBJECT(self,
579 "Unexpected number of channels");
580 g_value_set_int(value, 0);
581 }
582 }
583 }
584 gst_structure_set_value(structure, "channels", value);
585 g_free(value);
586
587 if (self->dev_caps != NULL)
588 gst_caps_unref(self->dev_caps);
589 self->dev_caps = gst_caps_new_full(structure, NULL);
590
591 tmp = gst_caps_to_string(self->dev_caps);
592 GST_DEBUG_OBJECT(self, "Device capabilities: %s", tmp);
593 g_free(tmp);
594
595 return TRUE;
596}
597
598static gboolean gst_a2dp_sender_sink_get_capabilities(GstA2dpSenderSink *self)
599{
600 gchar *buf[BT_AUDIO_IPC_PACKET_SIZE];
601 struct bt_getcapabilities_req *req = (void *) buf;
602 struct bt_getcapabilities_rsp *rsp = (void *) buf;
603 GIOError io_error;
604
605 memset(req, 0, BT_AUDIO_IPC_PACKET_SIZE);
606
607 req->h.msg_type = BT_GETCAPABILITIES_REQ;
608 if (self->device == NULL)
609 return FALSE;
610 strncpy(req->device, self->device, 18);
611
612 io_error = gst_a2dp_sender_sink_audioservice_send(self, &req->h);
613 if (io_error != G_IO_ERROR_NONE) {
614 GST_ERROR_OBJECT(self, "Error while asking device caps");
615 }
616
617 io_error = gst_a2dp_sender_sink_audioservice_expect(self,
618 &rsp->rsp_h.msg_h, BT_GETCAPABILITIES_RSP);
619 if (io_error != G_IO_ERROR_NONE) {
620 GST_ERROR_OBJECT(self, "Error while getting device caps");
621 return FALSE;
622 }
623
624 if (rsp->rsp_h.posix_errno != 0) {
625 GST_ERROR_OBJECT(self, "BT_GETCAPABILITIES failed : %s(%d)",
626 strerror(rsp->rsp_h.posix_errno),
627 rsp->rsp_h.posix_errno);
628 return FALSE;
629 }
630
631 memcpy(&self->data->caps, rsp, sizeof(*rsp));
632 if (!gst_a2dp_sender_sink_update_caps(self)) {
633 GST_WARNING_OBJECT(self, "failed to update capabilities");
634 return FALSE;
635 }
636
637 return TRUE;
638}
639
640static gboolean gst_a2dp_sender_sink_start(GstBaseSink *basesink)
641{
642 GstA2dpSenderSink *self = GST_A2DP_SENDER_SINK(basesink);
643 gint sk;
644 gint err;
645
646 GST_INFO_OBJECT(self, "start");
647
648 self->watch_id = 0;
649
650 sk = bt_audio_service_open();
651 if (sk <= 0) {
652 err = errno;
653 GST_ERROR_OBJECT(self, "Cannot open connection to bt "
654 "audio service: %s %d", strerror(err), err);
655 goto failed;
656 }
657
658 self->server = g_io_channel_unix_new(sk);
659 self->watch_id = g_io_add_watch(self->server, G_IO_HUP | G_IO_ERR |
660 G_IO_NVAL, server_callback, self);
661
662 self->data = g_new0(struct bluetooth_data, 1);
663 memset(self->data, 0, sizeof(struct bluetooth_data));
664
665 self->stream = NULL;
666 self->stream_caps = NULL;
667
668 if (!gst_a2dp_sender_sink_get_capabilities(self))
669 goto failed;
670
671 return TRUE;
672
673failed:
674 bt_audio_service_close(sk);
675 return FALSE;
676}
677
678static gboolean gst_a2dp_sender_sink_stream_start(GstA2dpSenderSink *self)
679{
680 gchar buf[BT_AUDIO_IPC_PACKET_SIZE];
681 struct bt_streamstart_req *req = (void *) buf;
682 struct bt_streamstart_rsp *rsp = (void *) buf;
683 struct bt_streamfd_ind *ind = (void*) buf;
684 GIOError io_error;
685
686 GST_DEBUG_OBJECT(self, "stream start");
687
688 memset (req, 0, sizeof(buf));
689 req->h.msg_type = BT_STREAMSTART_REQ;
690
691 io_error = gst_a2dp_sender_sink_audioservice_send(self, &req->h);
692 if (io_error != G_IO_ERROR_NONE) {
693 GST_ERROR_OBJECT(self, "Error ocurred while sending "
694 "start packet");
695 return FALSE;
696 }
697
698 GST_DEBUG_OBJECT(self, "stream start packet sent");
699
700 io_error = gst_a2dp_sender_sink_audioservice_expect(self,
701 &rsp->rsp_h.msg_h, BT_STREAMSTART_RSP);
702 if (io_error != G_IO_ERROR_NONE) {
703 GST_ERROR_OBJECT(self, "Error while stream "
704 "start confirmation");
705 return FALSE;
706 }
707
708 if (rsp->rsp_h.posix_errno != 0) {
709 GST_ERROR_OBJECT(self, "BT_STREAMSTART_RSP failed : %s(%d)",
710 strerror(rsp->rsp_h.posix_errno),
711 rsp->rsp_h.posix_errno);
712 return FALSE;
713 }
714
715 GST_DEBUG_OBJECT(self, "stream started");
716
717 io_error = gst_a2dp_sender_sink_audioservice_expect(self, &ind->h,
718 BT_STREAMFD_IND);
719 if (io_error != G_IO_ERROR_NONE) {
720 GST_ERROR_OBJECT(self, "Error while receiving "
721 "stream filedescriptor");
722 return FALSE;
723 }
724
725 if (!gst_a2dp_sender_sink_conf_recv_stream_fd(self))
726 return FALSE;
727
728 return TRUE;
729}
730
731static gboolean gst_a2dp_sender_sink_configure(GstA2dpSenderSink *self,
732 GstCaps *caps)
733{
734 gchar buf[BT_AUDIO_IPC_PACKET_SIZE];
735 struct bt_setconfiguration_req *req = (void *) buf;
736 struct bt_setconfiguration_rsp *rsp = (void *) buf;
737 gboolean ret;
738 GIOError io_error;
739 gchar *temp;
740
741 temp = gst_caps_to_string(caps);
742 GST_DEBUG_OBJECT(self, "configuring device with caps: %s", temp);
743 g_free(temp);
744
745 memset (req, 0, sizeof(buf));
746 req->h.msg_type = BT_SETCONFIGURATION_REQ;
747 req->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE;
748 strncpy(req->device, self->device, 18);
749 ret = gst_a2dp_sender_sink_init_pkt_conf(self, caps,
750 &req->sbc_capabilities);
751 if (!ret) {
752 GST_ERROR_OBJECT(self, "Couldn't parse caps "
753 "to packet configuration");
754 return FALSE;
755 }
756
757 io_error = gst_a2dp_sender_sink_audioservice_send(self, &req->h);
758 if (io_error != G_IO_ERROR_NONE) {
759 GST_ERROR_OBJECT(self, "Error ocurred while sending "
760 "configurarion packet");
761 return FALSE;
762 }
763
764 GST_DEBUG_OBJECT(self, "configuration packet sent");
765
766 io_error = gst_a2dp_sender_sink_audioservice_expect(self,
767 &rsp->rsp_h.msg_h, BT_SETCONFIGURATION_RSP);
768 if (io_error != G_IO_ERROR_NONE) {
769 GST_ERROR_OBJECT(self, "Error while receiving device "
770 "confirmation");
771 return FALSE;
772 }
773
774 if (rsp->rsp_h.posix_errno != 0) {
775 GST_ERROR_OBJECT(self, "BT_SETCONFIGURATION_RSP failed : "
776 "%s(%d)",
777 strerror(rsp->rsp_h.posix_errno),
778 rsp->rsp_h.posix_errno);
779 return FALSE;
780 }
781
782 self->data->link_mtu = rsp->link_mtu;
783 GST_DEBUG_OBJECT(self, "configuration set");
784
785 return TRUE;
786}
787
788static GstFlowReturn gst_a2dp_sender_sink_preroll(GstBaseSink *basesink,
789 GstBuffer *buffer)
790{
791 GstA2dpSenderSink *sink = GST_A2DP_SENDER_SINK(basesink);
792 gboolean ret;
793
794 GST_A2DP_SENDER_SINK_MUTEX_LOCK(sink);
795
796 ret = gst_a2dp_sender_sink_stream_start(sink);
797
798 GST_A2DP_SENDER_SINK_MUTEX_UNLOCK(sink);
799
800 if (!ret)
801 return GST_FLOW_ERROR;
802
803 return GST_FLOW_OK;
804}
805
806static GstFlowReturn gst_a2dp_sender_sink_render(GstBaseSink *basesink,
807 GstBuffer *buffer)
808{
809 GstA2dpSenderSink *self = GST_A2DP_SENDER_SINK(basesink);
810 gsize ret;
811 GIOError err;
812
813 err = g_io_channel_write(self->stream, (gchar*)GST_BUFFER_DATA(buffer),
814 (gsize)(GST_BUFFER_SIZE(buffer)), &ret);
815
816 if (err != G_IO_ERROR_NONE) {
817 GST_ERROR_OBJECT(self, "Error while writting to socket: %d %s",
818 errno, strerror(errno));
819 return GST_FLOW_ERROR;
820 }
821
822 return GST_FLOW_OK;
823}
824
825static gboolean gst_a2dp_sender_sink_unlock(GstBaseSink *basesink)
826{
827 GstA2dpSenderSink *self = GST_A2DP_SENDER_SINK(basesink);
828
829 if (self->stream != NULL)
830 g_io_channel_flush (self->stream, NULL);
831
832 return TRUE;
833}
834
835static GstFlowReturn gst_a2dp_sender_sink_buffer_alloc(GstBaseSink *basesink,
836 guint64 offset, guint size, GstCaps* caps,
837 GstBuffer **buf)
838{
839 GstA2dpSenderSink *self = GST_A2DP_SENDER_SINK(basesink);
840
841 *buf = gst_buffer_new_and_alloc(size);
842 if (!(*buf)) {
843 GST_ERROR_OBJECT(self, "buffer allocation failed");
844 return GST_FLOW_ERROR;
845 }
846
847 gst_buffer_set_caps(*buf, caps);
848
849 GST_BUFFER_OFFSET(*buf) = offset;
850
851 return GST_FLOW_OK;
852}
853
854static void gst_a2dp_sender_sink_class_init(GstA2dpSenderSinkClass *klass)
855{
856 GObjectClass *object_class = G_OBJECT_CLASS(klass);
857 GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS(klass);
858
859 parent_class = g_type_class_peek_parent(klass);
860
861 object_class->finalize = GST_DEBUG_FUNCPTR(
862 gst_a2dp_sender_sink_finalize);
863 object_class->set_property = GST_DEBUG_FUNCPTR(
864 gst_a2dp_sender_sink_set_property);
865 object_class->get_property = GST_DEBUG_FUNCPTR(
866 gst_a2dp_sender_sink_get_property);
867
868 basesink_class->start = GST_DEBUG_FUNCPTR(gst_a2dp_sender_sink_start);
869 basesink_class->stop = GST_DEBUG_FUNCPTR(gst_a2dp_sender_sink_stop);
870 basesink_class->render = GST_DEBUG_FUNCPTR(
871 gst_a2dp_sender_sink_render);
872 basesink_class->preroll = GST_DEBUG_FUNCPTR(
873 gst_a2dp_sender_sink_preroll);
874 basesink_class->unlock = GST_DEBUG_FUNCPTR(
875 gst_a2dp_sender_sink_unlock);
876
877 basesink_class->buffer_alloc =
878 GST_DEBUG_FUNCPTR(gst_a2dp_sender_sink_buffer_alloc);
879
880 g_object_class_install_property(object_class, PROP_DEVICE,
881 g_param_spec_string("device", "Device",
882 "Bluetooth remote device address",
883 NULL, G_PARAM_READWRITE));
884
885 GST_DEBUG_CATEGORY_INIT(a2dp_sender_sink_debug, "a2dpsendersink", 0,
886 "A2DP sink element");
887}
888
889static void gst_a2dp_sender_sink_init(GstA2dpSenderSink *self,
890 GstA2dpSenderSinkClass *klass)
891{
892 self->device = NULL;
893 self->data = NULL;
894
895 self->stream = NULL;
896
897 self->dev_caps = NULL;
898
899 self->sink_lock = g_mutex_new();
900}
901
902static GIOError gst_a2dp_sender_sink_audioservice_send(
903 GstA2dpSenderSink *self,
904 const bt_audio_msg_header_t *msg)
905{
906 GIOError error;
907 gsize written;
908
909 error = g_io_channel_write(self->server, (const gchar*) msg,
910 BT_AUDIO_IPC_PACKET_SIZE, &written);
911 if (error != G_IO_ERROR_NONE)
912 GST_ERROR_OBJECT(self, "Error sending data to audio service:"
913 " %s(%d)", strerror(errno), errno);
914
915 return error;
916}
917
918static GIOError gst_a2dp_sender_sink_audioservice_recv(
919 GstA2dpSenderSink *self,
920 bt_audio_msg_header_t *inmsg)
921{
922 GIOError status;
923 gsize bytes_read;
924 const char *type;
925
926 status = g_io_channel_read(self->server, (gchar*) inmsg,
927 BT_AUDIO_IPC_PACKET_SIZE, &bytes_read);
928 if (status != G_IO_ERROR_NONE) {
929 GST_ERROR_OBJECT(self, "Error receiving data from "
930 "audio service");
931 return status;
932 }
933
934 type = bt_audio_strmsg(inmsg->msg_type);
935 if (!type) {
936 status = G_IO_ERROR_INVAL;
937 GST_ERROR_OBJECT(self, "Bogus message type %d "
938 "received from audio service",
939 inmsg->msg_type);
940 }
941
942 return status;
943}
944
945static GIOError gst_a2dp_sender_sink_audioservice_expect(
946 GstA2dpSenderSink *self, bt_audio_msg_header_t *outmsg,
947 int expected_type)
948{
949 GIOError status;
950
951 status = gst_a2dp_sender_sink_audioservice_recv(self, outmsg);
952 if (status != G_IO_ERROR_NONE)
953 return status;
954
955 if (outmsg->msg_type != expected_type)
956 status = G_IO_ERROR_INVAL;
957
958 return status;
959}
960
961gboolean gst_a2dp_sender_sink_plugin_init (GstPlugin * plugin)
962{
963 return gst_element_register (plugin, "a2dpsendersink",
964 GST_RANK_NONE, GST_TYPE_A2DP_SENDER_SINK);
965}
966
967
968/* public functions */
969GstCaps *gst_a2dp_sender_sink_get_device_caps(GstA2dpSenderSink *sink)
970{
971 if (sink->dev_caps == NULL)
972 return NULL;
973
974 return gst_caps_copy(sink->dev_caps);
975}
976
977gboolean gst_a2dp_sender_sink_set_device_caps(GstA2dpSenderSink *self,
978 GstCaps *caps)
979{
980 gboolean ret;
981
982 GST_DEBUG_OBJECT(self, "setting device caps");
983 GST_A2DP_SENDER_SINK_MUTEX_LOCK(self);
984 ret = gst_a2dp_sender_sink_configure(self, caps);
985
986 if (self->stream_caps)
987 gst_caps_unref(self->stream_caps);
988 self->stream_caps = gst_caps_ref(caps);
989
990 GST_A2DP_SENDER_SINK_MUTEX_UNLOCK(self);
991
992 return ret;
993}
994
995guint gst_a2dp_sender_sink_get_link_mtu(GstA2dpSenderSink *sink)
996{
997 return sink->data->link_mtu;
998}
999
1000void gst_a2dp_sender_sink_set_device(GstA2dpSenderSink *self, const gchar* dev)
1001{
1002 if (self->device != NULL)
1003 g_free(self->device);
1004
1005 GST_LOG_OBJECT(self, "Setting device: %s", dev);
1006 self->device = g_strdup(dev);
1007}
1008
1009gchar *gst_a2dp_sender_sink_get_device(GstA2dpSenderSink *self)
1010{
1011 return g_strdup(self->device);
1012}
1013