static gboolean media_reader(GIOChannel *source, GIOCondition condition, gpointer data) { char buf[UINT16_MAX]; struct rtp_header *rtp = (void *) buf; static bool decode = false; uint16_t imtu; int fd, ret; if (!avdtp_stream_get_transport(avdtp_stream, &fd, &imtu, NULL, NULL)) return TRUE; ret = read(fd, buf, imtu); if (ret < 0) { printf("Reading failed (%s)\n", strerror(errno)); return TRUE; } if (ret < (int) sizeof(*rtp)) { printf("Not enough media data received (%u bytes)", ret); return TRUE; } if (!decode) { printf("V=%u P=%u X=%u CC=%u M=%u PT=%u SeqNr=%d\n", rtp->v, rtp->p, rtp->x, rtp->cc, rtp->m, rtp->pt, be16_to_cpu(rtp->sequence_number)); decode = true; } send_command(); return TRUE; }
static void a2dp_config_complete(struct avdtp *session, struct a2dp_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data) { struct unix_client *client = user_data; char buf[BT_SUGGESTED_BUFFER_SIZE]; struct bt_set_configuration_rsp *rsp = (void *) buf; struct a2dp_data *a2dp = &client->d.a2dp; uint16_t imtu, omtu; GSList *caps; client->req_id = 0; if (err) goto failed; memset(buf, 0, sizeof(buf)); if (!stream) goto failed; if (client->cb_id > 0) avdtp_stream_remove_cb(a2dp->session, a2dp->stream, client->cb_id); a2dp->sep = sep; a2dp->stream = stream; if (!avdtp_stream_get_transport(stream, &client->data_fd, &imtu, &omtu, &caps)) { error("Unable to get stream transport"); goto failed; } rsp->h.type = BT_RESPONSE; rsp->h.name = BT_SET_CONFIGURATION; rsp->h.length = sizeof(*rsp); /* FIXME: Use imtu when fd_opt is CFG_FD_OPT_READ */ rsp->link_mtu = omtu; unix_ipc_sendmsg(client, &rsp->h); client->cb_id = avdtp_stream_add_cb(session, stream, stream_state_changed, client); return; failed: error("config failed"); unix_ipc_error(client, BT_SET_CONFIGURATION, EIO); avdtp_unref(a2dp->session); a2dp->session = NULL; a2dp->stream = NULL; a2dp->sep = NULL; }
static void a2dp_resume_complete(struct avdtp *session, struct avdtp_error *err, void *user_data) { struct media_owner *owner = user_data; struct media_request *req = owner->pending; struct media_transport *transport = owner->transport; struct a2dp_sep *sep = media_endpoint_get_sep(transport->endpoint); struct avdtp_stream *stream; int fd; uint16_t imtu, omtu; gboolean ret; req->id = 0; if (err) goto fail; stream = a2dp_sep_get_stream(sep); if (stream == NULL) goto fail; ret = avdtp_stream_get_transport(stream, &fd, &imtu, &omtu, NULL); if (ret == FALSE) goto fail; media_transport_set_fd(transport, fd, imtu, omtu); if (g_strstr_len(owner->accesstype, -1, "r") == NULL) imtu = 0; if (g_strstr_len(owner->accesstype, -1, "w") == NULL) omtu = 0; ret = g_dbus_send_reply(transport->conn, req->msg, DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_UINT16, &imtu, DBUS_TYPE_UINT16, &omtu, DBUS_TYPE_INVALID); if (ret == FALSE) goto fail; media_owner_remove(owner); return; fail: media_transport_remove(transport, owner); }
static bool start_media_player(void) { int fd; uint16_t omtu; printf("Media streaming started\n"); if (media_player || !avdtp_stream) return false; if (!avdtp_stream_get_transport(avdtp_stream, &fd, NULL, &omtu, NULL)) return false; media_player = g_timeout_add(200, media_writer, NULL); if (!media_player) return false; return true; }
static void bt_stream_open(const void *buf, uint16_t len) { const struct audio_cmd_open_stream *cmd = buf; struct audio_rsp_open_stream *rsp; struct a2dp_setup *setup; int fd; uint16_t omtu; DBG(""); if (cmd->id) setup = find_setup(cmd->id); else setup = setups ? setups->data : NULL; if (!setup) { error("Unable to find stream for endpoint %u", cmd->id); ipc_send_rsp(audio_ipc, AUDIO_SERVICE_ID, AUDIO_OP_OPEN_STREAM, AUDIO_STATUS_FAILED); return; } if (!avdtp_stream_get_transport(setup->stream, &fd, NULL, &omtu, NULL)) { error("avdtp_stream_get_transport: failed"); ipc_send_rsp(audio_ipc, AUDIO_SERVICE_ID, AUDIO_OP_OPEN_STREAM, AUDIO_STATUS_FAILED); return; } len = sizeof(struct audio_rsp_open_stream) + sizeof(struct audio_preset) + setup->preset->len; rsp = g_malloc0(len); rsp->id = setup->endpoint->id; rsp->mtu = omtu; rsp->preset->len = setup->preset->len; memcpy(rsp->preset->data, setup->preset->data, setup->preset->len); ipc_send_rsp_full(audio_ipc, AUDIO_SERVICE_ID, AUDIO_OP_OPEN_STREAM, len, rsp, fd); g_free(rsp); }
static gboolean media_writer(gpointer user_data) { uint16_t omtu; int fd; int to_write; if (!avdtp_stream_get_transport(avdtp_stream, &fd, NULL, &omtu, NULL)) return TRUE; if (omtu < sizeof(sbc_media_frame)) to_write = omtu; else to_write = sizeof(sbc_media_frame); if (write(fd, sbc_media_frame, to_write) < 0) return TRUE; send_command(); return TRUE; }
static bool start_media_recorder(void) { int fd; uint16_t omtu; GIOChannel *chan; printf("Media recording started\n"); if (media_recorder || !avdtp_stream) return false; if (!avdtp_stream_get_transport(avdtp_stream, &fd, NULL, &omtu, NULL)) return false; chan = g_io_channel_unix_new(fd); media_recorder = g_io_add_watch(chan, G_IO_IN, media_reader, NULL); g_io_channel_unref(chan); if (!media_recorder) return false; return true; }