diff options
author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-01-23 13:16:02 +0000 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-01-23 13:16:02 +0000 |
commit | 489c2e0dbd76d9cecec62d19fafd9e7baddb72e7 (patch) | |
tree | d8ec2cba32e8a20443eb85e4162d0b38f0fd0d31 /audio/a2dp.c | |
parent | a0af7ee44534dad8f35a4142c6a22177e54ffc57 (diff) |
Add mpeg12 sep registration.
Diffstat (limited to 'audio/a2dp.c')
-rw-r--r-- | audio/a2dp.c | 144 |
1 files changed, 131 insertions, 13 deletions
diff --git a/audio/a2dp.c b/audio/a2dp.c index 1c59374f..b1409f5c 100644 --- a/audio/a2dp.c +++ b/audio/a2dp.c @@ -58,6 +58,7 @@ struct a2dp_sep { uint8_t type; + uint8_t codec; struct avdtp_local_sep *sep; struct avdtp *session; struct avdtp_stream *stream; @@ -280,7 +281,7 @@ static void stream_state_changed(struct avdtp_stream *stream, } -static gboolean setconf_ind(struct avdtp *session, +static gboolean sbc_setconf_ind(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, GSList *caps, uint8_t *err, @@ -331,7 +332,7 @@ static gboolean setconf_ind(struct avdtp *session, return TRUE; } -static gboolean getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep, +static gboolean sbc_getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep, GSList **caps, uint8_t *err, void *user_data) { struct a2dp_sep *a2dp_sep = user_data; @@ -386,6 +387,84 @@ static gboolean getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep, return TRUE; } +static gboolean mpeg_setconf_ind(struct avdtp *session, + struct avdtp_local_sep *sep, + struct avdtp_stream *stream, + GSList *caps, uint8_t *err, + uint8_t *category, void *user_data) +{ + struct a2dp_sep *a2dp_sep = user_data; + struct device *dev; + + if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) + debug("SBC Sink: Set_Configuration_Ind"); + else + debug("SBC Source: Set_Configuration_Ind"); + + dev = a2dp_get_dev(session); + if (!dev) { + *err = AVDTP_UNSUPPORTED_CONFIGURATION; + *category = 0x00; + return FALSE; + } + + avdtp_stream_add_cb(session, stream, stream_state_changed, a2dp_sep); + a2dp_sep->stream = stream; + + if (a2dp_sep->type == AVDTP_SEP_TYPE_SOURCE) + sink_new_stream(dev, session, stream); + + return TRUE; +} + +static gboolean mpeg_getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep, + GSList **caps, uint8_t *err, void *user_data) +{ + struct a2dp_sep *a2dp_sep = user_data; + struct avdtp_service_capability *media_transport, *media_codec; + struct mpeg_codec_cap mpeg_cap; + + if (a2dp_sep->type == AVDTP_SEP_TYPE_SINK) + debug("SBC Sink: Get_Capability_Ind"); + else + debug("SBC Source: Get_Capability_Ind"); + + *caps = NULL; + + media_transport = avdtp_service_cap_new(AVDTP_MEDIA_TRANSPORT, + NULL, 0); + + *caps = g_slist_append(*caps, media_transport); + + memset(&mpeg_cap, 0, sizeof(struct mpeg_codec_cap)); + + mpeg_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO; + mpeg_cap.cap.media_codec_type = A2DP_CODEC_MPEG12; + + mpeg_cap.frequency = ( MPEG_SAMPLING_FREQ_48000 | + MPEG_SAMPLING_FREQ_44100 | + MPEG_SAMPLING_FREQ_32000 | + MPEG_SAMPLING_FREQ_24000 | + MPEG_SAMPLING_FREQ_22050 | + MPEG_SAMPLING_FREQ_16000 ); + + mpeg_cap.channel_mode = ( MPEG_CHANNEL_MODE_JOINT_STEREO | + MPEG_CHANNEL_MODE_STEREO | + MPEG_CHANNEL_MODE_DUAL_CHANNEL | + MPEG_CHANNEL_MODE_MONO ); + + mpeg_cap.layer = ( MPEG_LAYER_MP3 | MPEG_LAYER_MP2 | MPEG_LAYER_MP1 ); + + mpeg_cap.bitrate = 0xFFFF; + + media_codec = avdtp_service_cap_new(AVDTP_MEDIA_CODEC, &mpeg_cap, + sizeof(mpeg_cap)); + + *caps = g_slist_append(*caps, media_codec); + + return TRUE; +} + static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep, struct avdtp_stream *stream, struct avdtp_error *err, void *user_data) @@ -797,9 +876,21 @@ static struct avdtp_sep_cfm cfm = { .reconfigure = reconf_cfm }; -static struct avdtp_sep_ind ind = { - .get_capability = getcap_ind, - .set_configuration = setconf_ind, +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, @@ -880,23 +971,27 @@ static int a2dp_sink_record(sdp_buf_t *buf) return 0; } -static struct a2dp_sep *a2dp_add_sep(DBusConnection *conn, uint8_t type) +static struct a2dp_sep *a2dp_add_sep(DBusConnection *conn, uint8_t type, + uint8_t codec) { struct a2dp_sep *sep; GSList **l; int (*create_record)(sdp_buf_t *buf); uint32_t *record_id; sdp_buf_t buf; + struct avdtp_sep_ind *ind; sep = g_new0(struct a2dp_sep, 1); - sep->sep = avdtp_register_sep(type, AVDTP_MEDIA_TYPE_AUDIO, - &ind, &cfm, sep); + ind = (codec == A2DP_CODEC_MPEG12) ? &mpeg_ind : &sbc_ind; + sep->sep = avdtp_register_sep(type, AVDTP_MEDIA_TYPE_AUDIO, codec, + ind, &cfm, sep); if (sep->sep == NULL) { g_free(sep); return NULL; } + sep->codec = codec; sep->type = type; if (type == AVDTP_SEP_TYPE_SOURCE) { @@ -945,11 +1040,15 @@ int a2dp_init(DBusConnection *conn, int sources, int sinks) avdtp_init(); - for (i = 0; i < sources; i++) - a2dp_add_sep(conn, AVDTP_SEP_TYPE_SOURCE); + for (i = 0; i < sources; i++) { + a2dp_add_sep(conn, AVDTP_SEP_TYPE_SOURCE, A2DP_CODEC_SBC); + a2dp_add_sep(conn, AVDTP_SEP_TYPE_SOURCE, A2DP_CODEC_MPEG12); + } - for (i = 0; i < sinks; i++) - a2dp_add_sep(conn, AVDTP_SEP_TYPE_SINK); + for (i = 0; i < sinks; i++) { + a2dp_add_sep(conn, AVDTP_SEP_TYPE_SINK, A2DP_CODEC_SBC); + a2dp_add_sep(conn, AVDTP_SEP_TYPE_SINK, A2DP_CODEC_MPEG12); + } return 0; } @@ -1025,14 +1124,32 @@ unsigned int a2dp_source_config(struct avdtp *session, a2dp_config_cb_t cb, struct a2dp_sep *sep = NULL; struct avdtp_local_sep *lsep; struct avdtp_remote_sep *rsep; + struct avdtp_service_capability *cap; + struct avdtp_media_codec_capability *codec_cap = NULL; int posix_err; + for (l = caps; l != NULL; l = l->next) { + cap = l->data; + + if (cap->category != AVDTP_MEDIA_CODEC) + continue; + + codec_cap = (void *) cap->data; + break; + } + + if (!codec_cap) + return 0; + for (l = sources; l != NULL; l = l->next) { struct a2dp_sep *tmp = l->data; if (tmp->locked) continue; + if (tmp->codec != codec_cap->media_codec_type) + continue; + if (!tmp->stream || avdtp_has_stream(session, tmp->stream)) { sep = tmp; break; @@ -1067,7 +1184,8 @@ unsigned int a2dp_source_config(struct avdtp *session, a2dp_config_cb_t cb, switch (avdtp_sep_get_state(sep->sep)) { case AVDTP_STATE_IDLE: if (avdtp_get_seps(session, AVDTP_SEP_TYPE_SINK, - AVDTP_MEDIA_TYPE_AUDIO, A2DP_CODEC_SBC, + codec_cap->media_type, + codec_cap->media_codec_type, &lsep, &rsep) < 0) { error("No matching ACP and INT SEPs found"); goto failed; |