#define MAX_BITPOOL 64
#define MIN_BITPOOL 2U
-#define SOL_SCO 17
-#define SCO_TXBUFS 0x03
-#define SCO_RXBUFS 0x04
PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
PA_MODULE_DESCRIPTION("Bluetooth audio sink and source");
"sco_sink=<SCO over PCM sink name> "
"sco_source=<SCO over PCM source name>");
+/* TODO: not close fd when entering suspend mode in a2dp */
+
+/* TODO: BT_PCM_FLAG_NREC */
+
static const char* const valid_modargs[] = {
"name",
"card_name",
int service_write_type, service_read_type;
};
+ #define USE_SCO_OVER_PCM(u) (u->profile == PROFILE_HSP && (u->hsp.sco_sink && u->hsp.sco_source))
+
static int init_bt(struct userdata *u);
static int init_profile(struct userdata *u);
return 0;
}
- /* from IO thread */
+ /* from IO thread, except in SCO over PCM */
static int start_stream_fd(struct userdata *u) {
union {
bt_audio_msg_header_t rsp;
return -1;
}
-/* setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)); */
-/* setsockopt(u->stream_fd, SOL_SCO, SCO_SNDBUF, &period_count, sizeof(period_count)); */
-
pa_make_fd_nonblock(u->stream_fd);
pa_make_socket_low_delay(u->stream_fd);
void *d;
const void *p;
unsigned frame_count;
- int written;
+ size_t written;
uint64_t writing_at;
pa_assert(u);
writing_at = u->write_index;
do {
- int encoded;
+ ssize_t encoded;
if (!u->write_memchunk.memblock)
pa_sink_render_full(u->sink, u->block_size, &u->write_memchunk);
p = (const uint8_t*) pa_memblock_acquire(u->write_memchunk.memblock) + u->write_memchunk.index;
encoded = sbc_encode(&a2dp->sbc,
- (void*) p, u->write_memchunk.length,
+ p, u->write_memchunk.length,
d, left,
&written);
return -1;
}
- pa_assert(written >= 0);
-
pa_assert((size_t) encoded <= u->write_memchunk.length);
+ pa_assert((size_t) encoded == sbc_get_codesize(&a2dp->sbc));
+
pa_assert((size_t) written <= left);
+ pa_assert((size_t) written == sbc_get_frame_length(&a2dp->sbc));
/* pa_log_debug("SBC: encoded: %d; written: %d", encoded, written); */
frame_count++;
- } while ((uint8_t*) d - (uint8_t*) a2dp->buffer + written < (ptrdiff_t) u->link_mtu);
+ } while (((uint8_t*) d - ((uint8_t*) a2dp->buffer + sbc_get_frame_length(&a2dp->sbc))) < (ptrdiff_t) u->link_mtu);
/* write it to the fifo */
memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
return pa_sprintf_malloc("bluez_%s.%s", type, n);
}
- #define USE_SCO_OVER_PCM(u) (u->profile == PROFILE_HSP && (u->hsp.sco_sink && u->hsp.sco_source))
-
static void sco_over_pcm_state_update(struct userdata *u) {
pa_assert(u);
pa_assert(USE_SCO_OVER_PCM(u));
if ((init_bt(u) < 0) || (init_profile(u) < 0))
pa_log("Can't resume SCO over PCM");
+ start_stream_fd(u);
} else {
if (u->service_fd < 0)
return;
+ stop_stream_fd(u);
+
pa_log_debug("Closing SCO over PCM");
pa_close(u->service_fd);
u->service_fd = -1;
pa_assert(!u->rtpoll);
pa_assert(!u->rtpoll_item);
+ u->rtpoll = pa_rtpoll_new();
+ pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
+
if (USE_SCO_OVER_PCM(u)) {
+ if (start_stream_fd(u) < 0)
+ return -1;
+
pa_sink_ref(u->sink);
pa_source_ref(u->source);
+ /* FIXME: monitor stream_fd error */
return 0;
}
- u->rtpoll = pa_rtpoll_new();
- pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
-
if (!(u->thread = pa_thread_new(thread_func, u))) {
pa_log_error("Failed to create IO thread");
stop_thread(u);