#define A2DP_SOURCE_ENDPOINT "/MediaEndpoint/A2DPSource"
#define A2DP_SINK_ENDPOINT "/MediaEndpoint/A2DPSink"
+#ifdef BLUETOOTH_APTX_SUPPORT
+#define A2DP_APTX_SOURCE_ENDPOINT "/MediaEndpoint/A2DPSource_aptx"
+#endif
#define ENDPOINT_INTROSPECT_XML \
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
" </method>" \
" <method name=\"Release\">" \
" </method>" \
+ " <method name=\"SuspendMedia\">" \
+ " </method>" \
" </interface>" \
" <interface name=\"org.freedesktop.DBus.Introspectable\">" \
" <method name=\"Introspect\">" \
return false;
}
+
+bool pa_bluetooth_device_source_transport_connected(const pa_bluetooth_device *d) {
+ unsigned i;
+
+ pa_assert(d);
+
+ if (d->device_info_valid != 1)
+ return false;
+
+ for (i = 0; i < PA_BLUETOOTH_PROFILE_COUNT; i++)
+ if (d->transports[i] &&
+ d->transports[i]->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE &&
+ d->transports[i]->state != PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED)
+ return true;
+
+ return false;
+}
#endif
static int transport_state_from_string(const char* value, pa_bluetooth_transport_state_t *state) {
DBusMessageIter i, d;
uint8_t codec = 0;
+#ifdef BLUETOOTH_APTX_SUPPORT
+ if(pa_streq(endpoint,A2DP_APTX_SOURCE_ENDPOINT))
+ codec = A2DP_CODEC_VENDOR;
+#endif
pa_log_debug("Registering %s on adapter %s", endpoint, path);
pa_assert_se(m = dbus_message_new_method_call(BLUEZ_SERVICE, path, BLUEZ_MEDIA_INTERFACE, "RegisterEndpoint"));
capabilities.max_bitpool = MAX_BITPOOL;
pa_dbus_append_basic_array_variant_dict_entry(&d, "Capabilities", DBUS_TYPE_BYTE, &capabilities, sizeof(capabilities));
}
+#ifdef BLUETOOTH_APTX_SUPPORT
+ if (codec == A2DP_CODEC_VENDOR ) {
+ /* aptx */
+ a2dp_aptx_t capabilities;
+ capabilities.vendor_id[0] = APTX_VENDOR_ID0;
+ capabilities.vendor_id[1] = APTX_VENDOR_ID1;
+ capabilities.vendor_id[2] = APTX_VENDOR_ID2;
+ capabilities.vendor_id[3] = APTX_VENDOR_ID3;
+ capabilities.codec_id[0] = APTX_CODEC_ID0;
+ capabilities.codec_id[1] = APTX_CODEC_ID1;
+ capabilities.channel_mode= APTX_CHANNEL_MODE_STEREO;
+ capabilities.frequency= APTX_SAMPLING_FREQ_44100;
+ pa_dbus_append_basic_array_variant_dict_entry(&d, "Capabilities", DBUS_TYPE_BYTE, &capabilities, sizeof(capabilities));
+ }
+#endif /* BLUETOOTH_APTX_SUPPORT */
#else
a2dp_sbc_t capabilities;
- capabilities.channel_mode = SBC_CHANNEL_MODE_MONO | SBC_CHANNEL_MODE_DUAL_CHANNEL | SBC_CHANNEL_MODE_STEREO |
- SBC_CHANNEL_MODE_JOINT_STEREO;
- capabilities.frequency = SBC_SAMPLING_FREQ_16000 | SBC_SAMPLING_FREQ_32000 | SBC_SAMPLING_FREQ_44100 |
- SBC_SAMPLING_FREQ_48000;
- capabilities.allocation_method = SBC_ALLOCATION_SNR | SBC_ALLOCATION_LOUDNESS;
- capabilities.subbands = SBC_SUBBANDS_4 | SBC_SUBBANDS_8;
- capabilities.block_length = SBC_BLOCK_LENGTH_4 | SBC_BLOCK_LENGTH_8 | SBC_BLOCK_LENGTH_12 | SBC_BLOCK_LENGTH_16;
- capabilities.min_bitpool = MIN_BITPOOL;
- capabilities.max_bitpool = MAX_BITPOOL;
-
- pa_dbus_append_basic_array_variant_dict_entry(&d, "Capabilities", DBUS_TYPE_BYTE, &capabilities, sizeof(capabilities));
+ capabilities.channel_mode = SBC_CHANNEL_MODE_MONO | SBC_CHANNEL_MODE_DUAL_CHANNEL | SBC_CHANNEL_MODE_STEREO |
+ SBC_CHANNEL_MODE_JOINT_STEREO;
+ capabilities.frequency = SBC_SAMPLING_FREQ_16000 | SBC_SAMPLING_FREQ_32000 | SBC_SAMPLING_FREQ_44100 |
+ SBC_SAMPLING_FREQ_48000;
+ capabilities.allocation_method = SBC_ALLOCATION_SNR | SBC_ALLOCATION_LOUDNESS;
+ capabilities.subbands = SBC_SUBBANDS_4 | SBC_SUBBANDS_8;
+ capabilities.block_length = SBC_BLOCK_LENGTH_4 | SBC_BLOCK_LENGTH_8 | SBC_BLOCK_LENGTH_12 | SBC_BLOCK_LENGTH_16;
+ capabilities.min_bitpool = MIN_BITPOOL;
+ capabilities.max_bitpool = MAX_BITPOOL;
+ pa_dbus_append_basic_array_variant_dict_entry(&d, "Capabilities", DBUS_TYPE_BYTE, &capabilities, sizeof(capabilities));
#endif /* __TIZEN_BT__ */
}
if (!a->address)
return;
- register_endpoint(y, path, A2DP_SOURCE_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SOURCE);
-#ifndef __TIZEN_BT__
register_endpoint(y, path, A2DP_SINK_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SINK);
+ register_endpoint(y, path, A2DP_SOURCE_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SOURCE);
+
+#ifdef BLUETOOTH_APTX_SUPPORT
+ if (aptx_handle)
+ register_endpoint(y, path, A2DP_APTX_SOURCE_ENDPOINT, PA_BLUETOOTH_UUID_A2DP_SOURCE);
#endif
} else if (pa_streq(interface, BLUEZ_DEVICE_INTERFACE)) {
dbus_message_iter_next(&element_i);
}
- PA_HASHMAP_FOREACH(d, y->devices, state) {
- if (d->device_info_valid != 0)
- continue;
-
+ PA_HASHMAP_FOREACH(d, y->devices, state)
if (!d->adapter && d->adapter_path) {
d->adapter = pa_hashmap_get(d->discovery->adapters, d->adapter_path);
if (!d->adapter || !d->adapter->address) {
} else
set_device_info_valid(d, 1);
}
- }
return;
}
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+#ifdef __TIZEN_BT__
+ } else if (dbus_message_is_signal(m, "org.bluez.ag_agent", "SuspendMedia")) {
+ pa_bluetooth_transport *t;
+ pa_log_debug("Signal from ag-agent to Suspend Media");
+ if (!(t = pa_hashmap_first(y->transports)))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_SCO_STATE_CHANGED], t);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+#endif
}
fail:
return 53;
}
+#ifdef BLUETOOTH_APTX_SUPPORT
+static DBusMessage *endpoint_select_configuration_for_aptx(DBusConnection *c, DBusMessage *m, void *userdata) {
+ a2dp_aptx_t *cap;
+ a2dp_aptx_t config;
+ uint8_t *pconf = (uint8_t *) &config;
+ int size;
+ DBusMessage *r;
+ DBusError e;
+
+ dbus_error_init(&e);
+
+ if (!dbus_message_get_args(m, &e, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &cap, &size, DBUS_TYPE_INVALID)) {
+ pa_log("org.bluez.MediaEndpoint.SelectConfiguration: %s", e.message);
+ dbus_error_free(&e);
+ goto fail;
+ }
+
+ pa_assert(size == sizeof(config));
+
+ memset(&config, 0, sizeof(config));
+
+ if (cap->vendor_id[0] == APTX_VENDOR_ID0 &&
+ cap->vendor_id[1] == APTX_VENDOR_ID1 &&
+ cap->vendor_id[2] == APTX_VENDOR_ID2 &&
+ cap->vendor_id[3] == APTX_VENDOR_ID3 &&
+ cap->codec_id[0] == APTX_CODEC_ID0 &&
+ cap->codec_id[1] == APTX_CODEC_ID1 )
+ pa_log_debug("A2DP_CODEC_NON_A2DP and this is APTX Codec");
+ else {
+ pa_log_debug("A2DP_CODEC_NON_A2DP but this is not APTX Codec");
+ goto fail;
+ }
+
+ memcpy(&config,cap, sizeof(config));
+
+/* The below code shuld be re-written by aptx */
+/* And we should configure pulseaudio freq */
+
+ if (cap->frequency & APTX_SAMPLING_FREQ_44100)
+ config.frequency = APTX_SAMPLING_FREQ_44100;
+ else if (cap->frequency & APTX_SAMPLING_FREQ_48000)
+ config.frequency = APTX_SAMPLING_FREQ_48000;
+ else if (cap->frequency & APTX_SAMPLING_FREQ_32000)
+ config.frequency = APTX_SAMPLING_FREQ_32000;
+ else if (cap->frequency & APTX_SAMPLING_FREQ_16000)
+ config.frequency = APTX_SAMPLING_FREQ_16000;
+ else {
+ pa_log_error("No aptx supported frequencies");
+ goto fail;
+ }
+
+ if (cap->channel_mode & APTX_CHANNEL_MODE_JOINT_STEREO)
+ config.channel_mode = APTX_CHANNEL_MODE_STEREO;
+ else if (cap->channel_mode & APTX_CHANNEL_MODE_STEREO)
+ config.channel_mode = APTX_CHANNEL_MODE_STEREO;
+ else if (cap->channel_mode & APTX_CHANNEL_MODE_DUAL_CHANNEL)
+ config.channel_mode = APTX_CHANNEL_MODE_STEREO;
+ else {
+ pa_log_error("No aptx supported channel modes");
+ goto fail;
+ }
+
+ pa_assert_se(r = dbus_message_new_method_return(m));
+
+ pa_assert_se(dbus_message_append_args(
+ r,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &pconf, size,
+ DBUS_TYPE_INVALID));
+
+ return r;
+
+fail:
+ pa_assert_se(r = (dbus_message_new_error(m, "org.bluez.MediaEndpoint.Error.InvalidArguments",
+ "Unable to select configuration")));
+ return r;
+}
+#endif
+
const char *pa_bluetooth_profile_to_string(pa_bluetooth_profile_t profile) {
switch(profile) {
case PA_BLUETOOTH_PROFILE_A2DP_SINK:
dbus_message_iter_get_basic(&value, &uuid);
endpoint_path = dbus_message_get_path(m);
+#ifdef BLUETOOTH_APTX_SUPPORT
+ if (pa_streq(endpoint_path, A2DP_SOURCE_ENDPOINT) ||
+ pa_streq(endpoint_path, A2DP_APTX_SOURCE_ENDPOINT)) {
+ if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SOURCE))
+ p = PA_BLUETOOTH_PROFILE_A2DP_SINK;
+ }
+#else
if (pa_streq(endpoint_path, A2DP_SOURCE_ENDPOINT)) {
if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SOURCE))
p = PA_BLUETOOTH_PROFILE_A2DP_SINK;
- } else if (pa_streq(endpoint_path, A2DP_SINK_ENDPOINT)) {
+ }
+#endif
+ else if (pa_streq(endpoint_path, A2DP_SINK_ENDPOINT)) {
if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK))
p = PA_BLUETOOTH_PROFILE_A2DP_SOURCE;
}
dbus_message_iter_get_basic(&value, &dev_path);
} else if (pa_streq(key, "Configuration")) {
DBusMessageIter array;
- a2dp_sbc_t *c;
if (var != DBUS_TYPE_ARRAY) {
pa_log_error("Property %s of wrong type %c", key, (char)var);
}
dbus_message_iter_get_fixed_array(&array, &config, &size);
+#ifndef BLUETOOTH_APTX_SUPPORT
if (size != sizeof(a2dp_sbc_t)) {
pa_log_error("Configuration array of invalid size");
goto fail;
pa_log_error("Invalid block length in configuration");
goto fail;
}
+#endif
}
dbus_message_iter_next(&props);
d = device_create(y, dev_path);
}
- if (d->transports[p] != NULL) {
+ if (p == PA_BLUETOOTH_PROFILE_OFF || d->transports[p] != NULL) {
pa_log_error("Cannot configure transport %s because profile %s is already used", path, pa_bluetooth_profile_to_string(p));
goto fail2;
}
{ 48000U, SBC_SAMPLING_FREQ_48000 }
};
+#ifdef BLUETOOTH_APTX_SUPPORT
+ if (dbus_message_has_path(m, A2DP_APTX_SOURCE_ENDPOINT))
+ return endpoint_select_configuration_for_aptx(conn ,m ,userdata);
+#endif
+
dbus_error_init(&err);
if (!dbus_message_get_args(m, &err, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &cap, &size, DBUS_TYPE_INVALID)) {
return r;
}
+#ifdef __TIZEN_BT__
+static DBusMessage *endpoint_suspend_media(DBusConnection *conn, DBusMessage *m, void *userdata) {
+ pa_bluetooth_discovery *y = userdata;
+ pa_bluetooth_transport *t;
+ DBusMessage *r;
+
+ pa_log_debug("dbus Call from to Suspend Media");
+ if (!(t = pa_hashmap_first(y->transports)))
+ goto fail;
+
+ pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_SCO_STATE_CHANGED], t);
+
+ pa_assert_se(r = dbus_message_new_method_return(m));
+
+ return r;
+
+fail:
+ pa_assert_se(r = dbus_message_new_error(m, "org.bluez.Error.InvalidArguments", "Unable to clear configuration"));
+ return r;
+}
+#endif
+
static DBusHandlerResult endpoint_handler(DBusConnection *c, DBusMessage *m, void *userdata) {
struct pa_bluetooth_discovery *y = userdata;
DBusMessage *r = NULL;
pa_log_debug("dbus: path=%s, interface=%s, member=%s", path, interface, member);
+#ifdef BLUETOOTH_APTX_SUPPORT
+ if (!pa_streq(path, A2DP_SOURCE_ENDPOINT) && !pa_streq(path, A2DP_SINK_ENDPOINT)
+ && !pa_streq(path,A2DP_APTX_SOURCE_ENDPOINT))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+#else
if (!pa_streq(path, A2DP_SOURCE_ENDPOINT) && !pa_streq(path, A2DP_SINK_ENDPOINT))
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+#endif /* BLUETOOTH_APTX_SUPPORT */
if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
const char *xml = ENDPOINT_INTROSPECT_XML;
r = endpoint_clear_configuration(c, m, userdata);
else if (dbus_message_is_method_call(m, BLUEZ_MEDIA_ENDPOINT_INTERFACE, "Release"))
r = endpoint_release(c, m, userdata);
+#ifdef __TIZEN_BT__
+ else if (dbus_message_is_method_call(m, BLUEZ_MEDIA_ENDPOINT_INTERFACE, "SuspendMedia"))
+ endpoint_suspend_media(c, m, userdata);
+#endif
else
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
case PA_BLUETOOTH_PROFILE_A2DP_SINK:
pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(y->connection), A2DP_SOURCE_ENDPOINT,
&vtable_endpoint, y));
+#ifdef BLUETOOTH_APTX_SUPPORT
+ pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(y->connection), A2DP_APTX_SOURCE_ENDPOINT,
+ &vtable_endpoint, y));
+#endif
break;
case PA_BLUETOOTH_PROFILE_A2DP_SOURCE:
pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(y->connection), A2DP_SINK_ENDPOINT,
switch(profile) {
case PA_BLUETOOTH_PROFILE_A2DP_SINK:
dbus_connection_unregister_object_path(pa_dbus_connection_get(y->connection), A2DP_SOURCE_ENDPOINT);
+#ifdef BLUETOOTH_APTX_SUPPORT
+ dbus_connection_unregister_object_path(pa_dbus_connection_get(y->connection), A2DP_APTX_SOURCE_ENDPOINT);
+#endif
break;
case PA_BLUETOOTH_PROFILE_A2DP_SOURCE:
dbus_connection_unregister_object_path(pa_dbus_connection_get(y->connection), A2DP_SINK_ENDPOINT);
goto fail;
}
- conn = pa_dbus_connection_get(y->connection);
-
+ conn = pa_dbus_connection_get(y->connection);
+#ifdef __TIZEN_BT__
+ if (dbus_bus_request_name(conn, "org.PulseAudio2", DBUS_NAME_FLAG_REPLACE_EXISTING, &err)
+ != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ pa_log_error("Failed to set D-Bus name: %s", err.message);
+ goto fail;
+ }
+#endif
/* dynamic detection of bluetooth audio devices */
if (!dbus_connection_add_filter(conn, filter_cb, y, NULL)) {
pa_log_error("Failed to add filter function");
",arg0='" BLUEZ_DEVICE_INTERFACE "'",
"type='signal',sender='" BLUEZ_SERVICE "',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'"
",arg0='" BLUEZ_MEDIA_TRANSPORT_INTERFACE "'",
+#ifdef __TIZEN_BT__
+ "type='signal',interface='org.bluez.ag_agent',member='SuspendMedia'",
+#endif
NULL) < 0) {
pa_log_error("Failed to add D-Bus matches: %s", err.message);
goto fail;
y->matches_added = true;
endpoint_init(y, PA_BLUETOOTH_PROFILE_A2DP_SINK);
+ endpoint_init(y, PA_BLUETOOTH_PROFILE_A2DP_SOURCE);
#ifndef __TIZEN_BT__
- endpoint_init(y, PA_BLUETOOTH_PROFILE_A2DP_SOURCE);
y->hf_audio_agent = hf_audio_agent_init(c);
#endif
"member='PropertiesChanged',arg0='" BLUEZ_DEVICE_INTERFACE "'",
"type='signal',sender='" BLUEZ_SERVICE "',interface='org.freedesktop.DBus.Properties',"
"member='PropertiesChanged',arg0='" BLUEZ_MEDIA_TRANSPORT_INTERFACE "'",
+#ifdef __TIZEN_BT__
+ "type='signal',interface='org.bluez.ag_agent',member='SuspendMedia'",
+#endif
NULL);
if (y->filter_added)
endpoint_done(y, PA_BLUETOOTH_PROFILE_A2DP_SINK);
-#ifndef __TIZEN_BT__
endpoint_done(y, PA_BLUETOOTH_PROFILE_A2DP_SOURCE);
-#endif
+
pa_dbus_connection_unref(y->connection);
}
uint16_t seq_num; /* Cumulative packet sequence */
uint8_t min_bitpool;
uint8_t max_bitpool;
-#ifdef __TIZEN_BT__
#ifdef BLUETOOTH_APTX_SUPPORT
pa_bool_t aptx_initialized; /* Keep track if the encoder is initialized */
void *aptx; /* aptx Codec data */
#endif
-#endif
void* buffer; /* Codec transfer buffer */
size_t buffer_size; /* Size of the buffer */
} sbc_info_t;
pa_hook_slot *device_connection_changed_slot;
pa_hook_slot *transport_state_changed_slot;
+#ifdef __TIZEN_BT__
+ pa_hook_slot *sco_state_changed_slot;
+#endif
pa_bluetooth_discovery *discovery;
pa_bluetooth_device *device;
pa_assert_not_reached();
}
-#ifdef __TIZEN_BT__
#ifdef BLUETOOTH_APTX_SUPPORT
void* (*aptx_new)(short endian);
int (*aptx_encode)(void* _state, void* _pcmL, void* _pcmR, void* _buffer);
return true;
}
#endif
-#endif
/* Run from main thread */
static void connect_ports(struct userdata *u, void *new_data, pa_direction_t direction) {
int pcmL[4],pcmR[4];
int i=0;
- const short *mybuffer;
+ const uint8_t *mybuffer;
pa_assert(u);
pa_assert(u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK);
size_t written;
ssize_t encoded;
- mybuffer=(uint8_t *)p;
+ mybuffer = (uint8_t *)p;
for (i = 0; i < 4; i += 1) {
pcmL[i] = mybuffer[2*i];
return 0;
}
+#ifdef BLUETOOTH_APTX_SUPPORT
+/* should be implemeted */
+static void bt_transport_config_a2dp_for_aptx(struct userdata *u) {
+ const pa_bluetooth_transport *t;
+ struct sbc_info *a2dp = &u->sbc_info;
+
+ t = u->transport;
+ pa_assert(t);
+
+ u->sample_spec.format = PA_SAMPLE_S16LE;
+
+ if (!a2dp->aptx_initialized) {
+ #if __BYTE_ORDER==__LITTLE_ENDIAN
+ a2dp->aptx = aptx_new(1);
+ #elif __BYTE_ORDER==__BIG_ENDIAN
+ a2dp->aptx = aptx_new(0);
+ #else
+ #error "Unknown byte order"
+ #endif
+ a2dp->aptx_initialized = true;
+ }
+
+ pa_log_debug("aptx Encoder is intialized !!");
+
+ u->write_block_size =(size_t)(u->write_link_mtu/(size_t)16) *16*4 ;
+ pa_log_info("APTX parameters block_size(%d),link_mtu(%d)",u->write_block_size,u->write_link_mtu);
+
+}
+#endif
+
/* Run from main thread */
static void transport_config(struct userdata *u) {
if (u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT || u->profile == PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY) {
} else {
sbc_info_t *sbc_info = &u->sbc_info;
a2dp_sbc_t *config;
+#ifdef BLUETOOTH_APTX_SUPPORT
+ const pa_bluetooth_transport *t;
+ a2dp_aptx_t *aptx_config;
+#endif
pa_assert(u->transport);
+#ifdef BLUETOOTH_APTX_SUPPORT
+ t = u->transport;
+ if (t->codec == A2DP_CODEC_VENDOR) {
+ aptx_config = (a2dp_aptx_t *) t->config;
+ if (aptx_config->vendor_id[0] == APTX_VENDOR_ID0 &&
+ aptx_config->vendor_id[1] == APTX_VENDOR_ID1 &&
+ aptx_config->vendor_id[2] == APTX_VENDOR_ID2 &&
+ aptx_config->vendor_id[3] == APTX_VENDOR_ID3 &&
+ aptx_config->codec_id[0] == APTX_CODEC_ID0 &&
+ aptx_config->codec_id[1] == APTX_CODEC_ID1 ){
+ pa_log("A2DP_CODEC_NON_A2DP and this is APTX Codec");
+
+ bt_transport_config_a2dp_for_aptx(u);
+ return;
+ } else {
+ pa_log("A2DP_CODEC_NON_A2DP but this is not APTX Codec");
+ return;
+ }
+ }
+#endif
+
u->sample_spec.format = PA_SAMPLE_S16LE;
config = (a2dp_sbc_t *) u->transport->config;
bool disable_timer = true;
pollfd = u->rtpoll_item ? pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL) : NULL;
-
+#ifdef __TIZEN_BT__
+ if (pollfd && (pollfd->revents & ~(POLLOUT|POLLIN))) {
+ pa_log_info("FD error: %s%s%s%s",
+ pollfd->revents & POLLERR ? "POLLERR " :"",
+ pollfd->revents & POLLHUP ? "POLLHUP " :"",
+ pollfd->revents & POLLPRI ? "POLLPRI " :"",
+ pollfd->revents & POLLNVAL ? "POLLNVAL " :"");
+ if (pollfd->revents & POLLHUP) {
+ pollfd = NULL;
+ do_write = 0;
+ pending_read_bytes = 0;
+ writable = false;
+ transport_release(u);
+ } else
+ goto fail;
+ }
+#endif
if (u->source && PA_SOURCE_IS_LINKED(u->source->thread_info.state)) {
/* We should send two blocks to the device before we expect
n_read = a2dp_process_push(u);
if (n_read < 0)
- goto io_fail;
+#ifdef __TIZEN_BT__
+ goto fail;
+#else
+ goto io_fail;
+#endif
/* We just read something, so we are supposed to write something, too */
pending_read_bytes += n_read;
}
if (writable && do_write > 0) {
- int n_written;
+ int n_written = 0;
if (u->write_index <= 0)
u->started_at = pa_rtclock_now();
#ifdef __TIZEN_BT__
if ((u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK) &&
!u->transport_suspended_by_remote) {
- if(u->sbc_info.sbc_initialized) {
- if ((n_written = a2dp_process_render(u)) < 0)
- goto io_fail;
- }
-#ifdef BLUETOOTH_APTX_SUPPORT
- else {
- if ((n_written = a2dp_aptx_process_render(u)) < 0)
- goto io_fail;
- }
-#endif
+ if(u->sbc_info.sbc_initialized) {
+ if ((n_written = a2dp_process_render(u)) < 0)
+ goto fail;
+ } else {
+ if ((n_written = a2dp_aptx_process_render(u)) < 0)
+ goto fail;
+ }
} else if ((u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK) &&
u->transport_suspended_by_remote) {
-#ifdef BLUETOOTH_APTX_SUPPORT
a2dp_process_null_render(u);
-#endif
#else
if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK ) {
if ((n_written = a2dp_process_render(u)) < 0)
#endif
} else {
if ((n_written = sco_process_render(u)) < 0)
- goto io_fail;
+#ifdef __TIZEN_BT__
+ goto fail;
+#else
+ goto io_fail;
+#endif
}
if (n_written == 0)
pa_log_debug("pa_rtpoll_run failed with: %d", ret);
goto fail;
}
+
if (ret == 0) {
pa_log_debug("IO thread shutdown requested, stopping cleanly");
transport_release(u);
goto finish;
}
+#ifndef __TIZEN_BT__
pollfd = u->rtpoll_item ? pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL) : NULL;
if (pollfd && (pollfd->revents & ~(POLLOUT|POLLIN))) {
writable = false;
transport_release(u);
+#endif
}
+
fail:
/* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
pa_log_debug("IO thread failed");
}
if (u->rtpoll) {
- pa_thread_mq_done(&u->thread_mq);
pa_rtpoll_free(u->rtpoll);
u->rtpoll = NULL;
+ pa_thread_mq_done(&u->thread_mq);
}
if (u->transport) {
static void create_card_ports(struct userdata *u, pa_hashmap *ports) {
pa_device_port *port;
pa_device_port_new_data port_data;
+
const char *name_prefix, *input_description, *output_description;
pa_assert(u);
p = PA_CARD_PROFILE_DATA(cp);
*p = PA_BLUETOOTH_PROFILE_A2DP_SINK;
-#ifndef __TIZEN_BT__
} else if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SOURCE)) {
cp = pa_card_profile_new("a2dp_source", _("High Fidelity Capture (A2DP Source)"), sizeof(pa_bluetooth_profile_t));
cp->priority = 10;
p = PA_CARD_PROFILE_DATA(cp);
*p = PA_BLUETOOTH_PROFILE_A2DP_SOURCE;
+#ifndef __TIZEN_BT__
} else if (pa_streq(uuid, PA_BLUETOOTH_UUID_HSP_HS) || pa_streq(uuid, PA_BLUETOOTH_UUID_HFP_HF)) {
/* TODO: Change this profile's name to headset_head_unit, to reflect the remote
* device's role and be consistent with the other profiles */
return PA_HOOK_OK;
}
+#ifdef __TIZEN_BT__
+void dbus_sco_open_handler(struct userdata *u, struct pa_bluetooth_transport *t)
+{
+ if (u->sink) {
+ pa_log_info("Suspending sink %s to handle the SCO connection", u->sink->name);
+
+ pa_sink *sink_null = NULL;
+ pa_sink_input *si;
+ uint32_t idx;
+
+ if (pa_sink_check_suspend(u->sink) > 0) {
+ sink_null = (pa_sink *)pa_namereg_get(u->core, "null", 0);
+
+ if (sink_null)
+ {
+ PA_IDXSET_FOREACH(si, u->core->sink_inputs, idx) {
+ pa_sink_input_move_to(si, sink_null, false);
+ }
+ }
+ }
+
+ pa_sink_suspend(u->sink, true, PA_SUSPEND_INTERNAL);
+ }
+}
+
+/* Run from main thread */
+static pa_hook_result_t sco_state_changed_cb(pa_bluetooth_discovery *y, pa_bluetooth_transport *t, struct userdata *u) {
+ pa_assert(t);
+ pa_assert(u);
+
+ if (t == u->transport && t->state <= PA_BLUETOOTH_TRANSPORT_STATE_IDLE)
+ return PA_HOOK_OK;
+
+ if (t->device == u->device)
+ dbus_sco_open_handler(u, t);
+
+ return PA_HOOK_OK;
+}
+#endif
+
/* Run from main thread */
static pa_hook_result_t transport_state_changed_cb(pa_bluetooth_discovery *y, pa_bluetooth_transport *t, struct userdata *u) {
pa_assert(t);
struct userdata *u;
const char *path;
pa_modargs *ma;
+#ifdef BLUETOOTH_APTX_SUPPORT
+ void *handle;
+#endif
pa_assert(m);
u->transport_state_changed_slot =
pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED),
PA_HOOK_NORMAL, (pa_hook_cb_t) transport_state_changed_cb, u);
+#ifdef __TIZEN_BT__
+ u->sco_state_changed_slot =
+ pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_SCO_STATE_CHANGED),
+ PA_HOOK_NORMAL, (pa_hook_cb_t) sco_state_changed_cb, u);
+#endif
if (add_card(u) < 0)
goto fail;
u->msg->parent.process_msg = device_process_msg;
u->msg->card = u->card;
+#ifdef BLUETOOTH_APTX_SUPPORT
+ handle = pa_aptx_get_handle();
+
+ if (handle) {
+ pa_log_debug("Aptx Library loaded\n");
+ pa_load_aptx_sym(handle);
+ }
+#endif
+
if (u->profile != PA_BLUETOOTH_PROFILE_OFF)
if (init_profile(u) < 0)
goto off;
if (u->transport_state_changed_slot)
pa_hook_slot_free(u->transport_state_changed_slot);
+#ifdef __TIZEN_BT__
+ if (u->sco_state_changed_slot)
+ pa_hook_slot_free(u->sco_state_changed_slot);
+#endif
if (u->sbc_info.buffer)
pa_xfree(u->sbc_info.buffer);