📄 a2dp.c
字号:
} avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep); a2dp_sep->stream = stream; if (!setup) return; dev = a2dp_get_dev(session); /* Notify sink.c of the new stream */ sink_new_stream(dev, session, setup->stream); ret = avdtp_open(session, stream); if (ret < 0) { error("Error on avdtp_open %s (%d)", strerror(-ret), -ret); setup->stream = NULL; finalize_config_errno(setup, ret); }}static gboolean getconf_ind(struct avdtp *session, struct avdtp_local_sep *sep, uint8_t *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Get_Configuration_Ind"); else debug("Source %p: Get_Configuration_Ind"); return TRUE;}static void getconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Set_Configuration_Cfm", sep); else debug("Source %p: Set_Configuration_Cfm", sep);}static gboolean open_ind(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, uint8_t *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Open_Ind", sep); else debug("Source %p: Open_Ind", sep); return TRUE;}static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; struct a2dp_setup *setup; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Open_Cfm", sep); else debug("Source %p: Open_Cfm", sep); setup = find_setup_by_session(session); if (!setup) return; if (setup->canceled) { if (!err) avdtp_close(session, stream); setup_unref(setup); return; } if (setup->reconfigure) setup->reconfigure = FALSE; if (err) { setup->stream = NULL; setup->err = err; finalize_config(setup); } else finalize_config_errno(setup, 0);}static gboolean suspend_timeout(struct a2dp_sep *sep){ if (avdtp_suspend(sep->session, sep->stream) == 0) sep->suspending = TRUE; sep->suspend_timer = 0; avdtp_unref(sep->session); sep->session = NULL; return FALSE;}static gboolean start_ind(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, uint8_t *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Start_Ind", sep); else debug("Source %p: Start_Ind", sep); if (!a2dp_sep->locked) { a2dp_sep->session = avdtp_ref(session); a2dp_sep->suspend_timer = g_timeout_add(SUSPEND_TIMEOUT, (GSourceFunc) suspend_timeout, a2dp_sep); } return TRUE;}static void start_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; struct a2dp_setup *setup; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Start_Cfm", sep); else debug("Source %p: Start_Cfm", sep); setup = find_setup_by_session(session); if (!setup) return; if (setup->canceled) { if (!err) avdtp_close(session, stream); setup_unref(setup); return; } if (err) { setup->stream = NULL; setup->err = err; finalize_resume(setup); } else finalize_resume_errno(setup, 0);}static gboolean suspend_ind(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, uint8_t *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Suspend_Ind", sep); else debug("Source %p: Suspend_Ind", sep); if (a2dp_sep->suspend_timer) { g_source_remove(a2dp_sep->suspend_timer); a2dp_sep->suspend_timer = 0; avdtp_unref(a2dp_sep->session); a2dp_sep->session = NULL; } return TRUE;}static void suspend_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; struct a2dp_setup *setup; gboolean start; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Suspend_Cfm", sep); else debug("Source %p: Suspend_Cfm", sep); a2dp_sep->suspending = FALSE; setup = find_setup_by_session(session); if (!setup) return; start = setup->start; setup->start = FALSE; if (err) { setup->stream = NULL; setup->err = err; finalize_suspend(setup); } else finalize_suspend_errno(setup, 0); if (!start) return; if (err) { setup->err = err; finalize_suspend(setup); } else if (avdtp_start(session, a2dp_sep->stream) < 0) { struct avdtp_error start_err; error("avdtp_start failed"); avdtp_error_init(&start_err, AVDTP_ERROR_ERRNO, EIO); setup->err = err; finalize_suspend(setup); }}static gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, uint8_t *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Close_Ind", sep); else debug("Source %p: Close_Ind", sep); return TRUE;}static gboolean a2dp_reconfigure(gpointer data){ struct a2dp_setup *setup = data; struct avdtp_local_sep *lsep; struct avdtp_remote_sep *rsep; struct avdtp_service_capability *cap; struct avdtp_media_codec_capability *codec_cap = NULL; GSList *l; int posix_err; for (l = setup->client_caps; l != NULL; l = l->next) { cap = l->data; if (cap->category != AVDTP_MEDIA_CODEC) continue; codec_cap = (void *) cap->data; break; } posix_err = avdtp_get_seps(setup->session, AVDTP_SEP_TYPE_SINK, codec_cap->media_type, codec_cap->media_codec_type, &lsep, &rsep); if (posix_err < 0) { error("No matching ACP and INT SEPs found"); finalize_config_errno(setup, posix_err); } posix_err = avdtp_set_configuration(setup->session, rsep, lsep, setup->client_caps, &setup->stream); if (posix_err < 0) { error("avdtp_set_configuration: %s", strerror(-posix_err)); finalize_config_errno(setup, posix_err); } return FALSE;}static void close_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; struct a2dp_setup *setup; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Close_Cfm", sep); else debug("Source %p: Close_Cfm", sep); setup = find_setup_by_session(session); if (!setup) return; if (setup->canceled) { setup_unref(setup); return; } if (err) { setup->stream = NULL; setup->err = err; finalize_config(setup); return; } if (setup->reconfigure) g_timeout_add(RECONFIGURE_TIMEOUT, a2dp_reconfigure, setup);}static gboolean abort_ind(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, uint8_t *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Abort_Ind", sep); else debug("Source %p: Abort_Ind", sep); a2dp_sep->stream = NULL; return TRUE;}static void abort_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; struct a2dp_setup *setup; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: Abort_Cfm", sep); else debug("Source %p: Abort_Cfm", sep); setup = find_setup_by_session(session); if (!setup) return; setup_unref(setup);}static gboolean reconf_ind(struct avdtp *session, struct avdtp_local_sep *sep, uint8_t *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: ReConfigure_Ind", sep); else debug("Source %p: ReConfigure_Ind", sep); return TRUE;}static void reconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data){ struct a2dp_sep *a2dp_sep = user_data; struct a2dp_setup *setup; if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) debug("Sink %p: ReConfigure_Cfm", sep); else debug("Source %p: ReConfigure_Cfm", sep); setup = find_setup_by_session(session); if (!setup) return; if (setup->canceled) { if (!err) avdtp_close(session, stream); setup_unref(setup); return; } if (err) { setup->stream = NULL; setup->err = err; finalize_config(setup); } else finalize_config_errno(setup, 0);}static struct avdtp_sep_cfm cfm = { .set_configuration = setconf_cfm, .get_configuration = getconf_cfm, .open = open_cfm, .start = start_cfm, .suspend = suspend_cfm, .close = close_cfm, .abort = abort_cfm, .reconfigure = reconf_cfm};static struct avdtp_sep_ind sbc_ind = { .get_capability = sbc_getcap_ind, .set_configuration = sbc_setconf_ind, .get_configuration = getconf_ind, .open = open_ind, .start = start_ind, .suspend = suspend_ind, .close = close_ind, .abort = abort_ind, .reconfigure = reconf_ind};static struct avdtp_sep_ind mpeg_ind = { .get_capability = mpeg_getcap_ind, .set_configuration = mpeg_setconf_ind, .get_configuration = getconf_ind, .open = open_ind, .start = start_ind, .suspend = suspend_ind, .close = close_ind, .abort = abort_ind, .reconfigure = reconf_ind};static sdp_record_t *a2dp_source_record(){ sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, l2cap, avdtp, a2src; sdp_profile_desc_t profile[1]; sdp_list_t *aproto, *proto[2]; sdp_record_t *record; sdp_data_t *psm, *version, *features; uint16_t lp = AVDTP_UUID, ver = 0x0100, feat = 0x000F; record = sdp_record_alloc(); if (!record) return NULL; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(record, root); sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID); svclass_id = sdp_list_append(0, &a2src); sdp_set_service_classes(record, svclass_id); sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID); profile[0].version = 0x0100; pfseq = sdp_list_append(0, &profile[0]); sdp_set_profile_descs(record, pfseq); sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(0, &l2cap); psm = sdp_data_alloc(SDP_UINT16, &lp); proto[0] = sdp_list_append(proto[0], psm); apseq = sdp_list_append(0, proto[0]); sdp_uuid16_create(&avdtp, AVDTP_UUID); proto[1] = sdp_list_append(0, &avdtp); version = sdp_data_alloc(SDP_UINT16, &ver); proto[1] = sdp_list_append(proto[1], version); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(record, aproto); features = sdp_data_alloc(SDP_UINT16, &feat); sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features); sdp_set_info_attr(record, "Audio Source", 0, 0); free(psm); free(version); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(pfseq, 0); sdp_list_free(aproto, 0); sdp_list_free(root, 0); sdp_list_free(svclass_id, 0); return record;}static sdp_record_t *a2dp_sink_record(){ return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -