diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/modules/bluetooth/bluetooth-util.c | 15 | ||||
| -rw-r--r-- | src/modules/bluetooth/module-bluetooth-device.c | 57 | ||||
| -rw-r--r-- | src/modules/bluetooth/module-bluetooth-discover.c | 2 | ||||
| -rw-r--r-- | src/modules/bluetooth/module-bluetooth-proximity.c | 4 | ||||
| -rw-r--r-- | src/modules/bluetooth/sbc.c | 14 | ||||
| -rw-r--r-- | src/modules/bluetooth/sbc.h | 22 | ||||
| -rw-r--r-- | src/modules/module-hal-detect.c | 3 | ||||
| -rw-r--r-- | src/pulsecore/sink.c | 2 | 
8 files changed, 74 insertions, 45 deletions
| diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index dfd3a306..912697e6 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -114,15 +114,14 @@ void pa_bluetooth_device_free(pa_bluetooth_device *d) {  static pa_bool_t device_is_loaded(pa_bluetooth_device *d) {      pa_assert(d); -    return d->device_info_valid && d->audio_sink_info_valid && d->headset_info_valid; +    return d->device_info_valid && (d->audio_sink_info_valid || d->headset_info_valid);  }  static pa_bool_t device_is_audio(pa_bluetooth_device *d) {      pa_assert(d);      pa_assert(d->device_info_valid); -    pa_assert(d->audio_sink_info_valid); -    pa_assert(d->headset_info_valid); +    pa_assert(d->audio_sink_info_valid || d->headset_info_valid);      return d->device_info_valid > 0 &&          (d->audio_sink_info_valid > 0 || d->headset_info_valid > 0); @@ -604,7 +603,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us              pa_bluetooth_device_free(d);          } -        return DBUS_HANDLER_RESULT_HANDLED; +        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;      } else if (dbus_message_is_signal(m, "org.bluez.Adapter", "DeviceCreated")) {          const char *path; @@ -617,7 +616,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us          pa_log_debug("Device %s created", path);          found_device(y, path); -        return DBUS_HANDLER_RESULT_HANDLED; +        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;      } else if (dbus_message_is_signal(m, "org.bluez.Manager", "AdapterAdded")) {          const char *path; @@ -630,7 +629,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us          pa_log_debug("Adapter %s created", path);          found_adapter(y, path); -        return DBUS_HANDLER_RESULT_HANDLED; +        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;      } else if (dbus_message_is_signal(m, "org.bluez.Headset", "PropertyChanged") ||                 dbus_message_is_signal(m, "org.bluez.AudioSink", "PropertyChanged") || @@ -653,17 +652,19 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us              } else if (dbus_message_has_interface(m, "org.bluez.Headset")) {                  if (parse_audio_property(y, &d->headset_connected, &arg_i) < 0)                      goto fail; +		d->headset_info_valid = 1;              }  else if (dbus_message_has_interface(m, "org.bluez.AudioSink")) {                  if (parse_audio_property(y, &d->audio_sink_connected, &arg_i) < 0)                      goto fail; +		d->audio_sink_info_valid = 1;              }              pa_assert_se(y->mode == MODE_DISCOVER);              run_callback(y, d, TRUE);          } -        return DBUS_HANDLER_RESULT_HANDLED; +        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;      }  fail: diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 495bc82f..1b61a6fc 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -57,9 +57,6 @@  #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"); @@ -78,6 +75,10 @@ PA_MODULE_USAGE(          "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", @@ -160,6 +161,8 @@ struct userdata {      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); @@ -653,7 +656,7 @@ static int set_conf(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; @@ -689,9 +692,6 @@ static int start_stream_fd(struct userdata *u) {          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); @@ -700,6 +700,9 @@ static int start_stream_fd(struct userdata *u) {      pollfd->fd = u->stream_fd;      pollfd->events = pollfd->revents = 0; +    u->read_index = 0; +    u->write_index = 0; +      return 0;  } @@ -873,7 +876,7 @@ static int hsp_process_render(struct userdata *u) {          pa_assert(l != 0);          if (l < 0) { -            if (errno == EINTR) +            if (errno == EINTR || errno == EAGAIN)                  continue;              else {                  pa_log_error("Failed to write data to SCO socket: %s", pa_cstrerror(errno)); @@ -918,7 +921,7 @@ static int hsp_process_push(struct userdata *u) {          pa_memblock_release(memchunk.memblock);          if (l <= 0) { -            if (l < 0 && errno == EINTR) +            if (l < 0 && (errno == EINTR || errno == EAGAIN))                  continue;              else {                  pa_log_error("Failed to read data from SCO socket: %s", l < 0 ? pa_cstrerror(errno) : "EOF"); @@ -948,7 +951,7 @@ static int a2dp_process_render(struct userdata *u) {      void *d;      const void *p;      unsigned frame_count; -    int written; +    size_t written;      uint64_t writing_at;      pa_assert(u); @@ -974,14 +977,14 @@ static int a2dp_process_render(struct userdata *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); @@ -996,10 +999,11 @@ static int a2dp_process_render(struct userdata *u) {              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); */ @@ -1018,7 +1022,7 @@ static int a2dp_process_render(struct userdata *u) {          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)); @@ -1041,7 +1045,7 @@ static int a2dp_process_render(struct userdata *u) {          pa_assert(l != 0);          if (l < 0) { -            if (errno == EINTR) +            if (errno == EINTR || errno == EAGAIN)                  continue;              else {                  pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno)); @@ -1123,6 +1127,8 @@ static void thread_func(void *userdata) {                  }                  if (writable && do_write) { +                    if (u->write_index == 0) +                        u->started_at = pa_rtclock_usec();                      if (u->profile == PROFILE_A2DP) {                          if (a2dp_process_render(u) < 0) @@ -1159,8 +1165,8 @@ static void thread_func(void *userdata) {          /* Hmm, nothing to do. Let's sleep */          if (pollfd) -            pollfd->events = (short) (((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state) && !writable) ? POLLOUT : 0) | -                                      (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state) ? POLLIN : 0)); +            pollfd->events = (short) (((u->sink && PA_SINK_IS_LINKED(u->sink->thread_info.state) && !writable) ? POLLOUT : 0) | +                                      (u->source && PA_SOURCE_IS_LINKED(u->source->thread_info.state) ? POLLIN : 0));          if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)              goto fail; @@ -1354,8 +1360,6 @@ static char *get_name(const char *type, pa_modargs *ma, const char *device_id, p      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)); @@ -1370,11 +1374,14 @@ static void sco_over_pcm_state_update(struct userdata *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; @@ -1624,15 +1631,19 @@ static int start_thread(struct userdata *u) {      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); diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c index 521a9127..4586d8ca 100644 --- a/src/modules/bluetooth/module-bluetooth-discover.c +++ b/src/modules/bluetooth/module-bluetooth-discover.c @@ -75,7 +75,7 @@ static void load_module_for_device(struct userdata *u, pa_bluetooth_device *d, p              /* Oh, awesome, a new device has shown up and been connected! */ -            args = pa_sprintf_malloc("address=\"%s\" path=\"%s\"", d->address, d->path); +            args = pa_sprintf_malloc("address=\"%s\" path=\"%s\" profile=\"%s\"", d->address, d->path, d->headset_connected ? "hsp" : "a2dp");              if (pa_modargs_get_value(u->modargs, "sco_sink", NULL) &&                  pa_modargs_get_value(u->modargs, "sco_source", NULL)) { diff --git a/src/modules/bluetooth/module-bluetooth-proximity.c b/src/modules/bluetooth/module-bluetooth-proximity.c index a3b525ee..c8d7b4d9 100644 --- a/src/modules/bluetooth/module-bluetooth-proximity.c +++ b/src/modules/bluetooth/module-bluetooth-proximity.c @@ -302,7 +302,7 @@ static DBusHandlerResult filter_func(DBusConnection *connection, DBusMessage *m,          bonding_new(u, a); -        return DBUS_HANDLER_RESULT_HANDLED; +        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;      } else if (dbus_message_is_signal(m, "org.bluez.Adapter", "BondingRemoved")) { @@ -315,7 +315,7 @@ static DBusHandlerResult filter_func(DBusConnection *connection, DBusMessage *m,          bonding_remove(u, a); -        return DBUS_HANDLER_RESULT_HANDLED; +        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;      }  finish: diff --git a/src/modules/bluetooth/sbc.c b/src/modules/bluetooth/sbc.c index a33ed571..6fa54796 100644 --- a/src/modules/bluetooth/sbc.c +++ b/src/modules/bluetooth/sbc.c @@ -1044,8 +1044,10 @@ int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,  	return framelen;  } -int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, -		int output_len, int *written) +ssize_t sbc_encode(sbc_t *sbc, +               const void *input, size_t input_len, +               void *output, size_t output_len, +               size_t *written)  {  	struct sbc_priv *priv;  	int framelen, samples; @@ -1133,9 +1135,9 @@ void sbc_finish(sbc_t *sbc)  	memset(sbc, 0, sizeof(sbc_t));  } -int sbc_get_frame_length(sbc_t *sbc) +size_t sbc_get_frame_length(sbc_t *sbc)  { -	int ret; +	size_t ret;  	uint8_t subbands, channels, blocks, joint;  	struct sbc_priv *priv; @@ -1164,7 +1166,7 @@ int sbc_get_frame_length(sbc_t *sbc)  	return ret;  } -int sbc_get_frame_duration(sbc_t *sbc) +unsigned sbc_get_frame_duration(sbc_t *sbc)  {  	uint8_t subbands, blocks;  	uint16_t frequency; @@ -1202,7 +1204,7 @@ int sbc_get_frame_duration(sbc_t *sbc)  	return (1000000 * blocks * subbands) / frequency;  } -uint16_t sbc_get_codesize(sbc_t *sbc) +size_t sbc_get_codesize(sbc_t *sbc)  {  	uint16_t subbands, channels, blocks;  	struct sbc_priv *priv; diff --git a/src/modules/bluetooth/sbc.h b/src/modules/bluetooth/sbc.h index f9d506bc..25a12885 100644 --- a/src/modules/bluetooth/sbc.h +++ b/src/modules/bluetooth/sbc.h @@ -31,6 +31,7 @@ extern "C" {  #endif  #include <stdint.h> +#include <sys/types.h>  /* sampling frequency */  #define SBC_FREQ_16000		0x00 @@ -84,11 +85,22 @@ int sbc_reinit(sbc_t *sbc, unsigned long flags);  int sbc_parse(sbc_t *sbc, void *input, int input_len);  int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,  		int output_len, int *len); -int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output, -		int output_len, int *written); -int sbc_get_frame_length(sbc_t *sbc); -int sbc_get_frame_duration(sbc_t *sbc); -uint16_t sbc_get_codesize(sbc_t *sbc); + +/* Encodes ONE input block into ONE output block */ +ssize_t sbc_encode(sbc_t *sbc, +               const void *input, size_t input_len, +               void *output, size_t output_len, +               size_t *written); + +/* Returns the output block size in bytes */ +size_t sbc_get_frame_length(sbc_t *sbc); + +/* Returns the time one input/output block takes to play in msec*/ +unsigned sbc_get_frame_duration(sbc_t *sbc); + +/* Returns the input block size in bytes */ +size_t sbc_get_codesize(sbc_t *sbc); +  const char *sbc_get_implementation_info(sbc_t *sbc);  void sbc_finish(sbc_t *sbc); diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c index fe601100..9b0d71c9 100644 --- a/src/modules/module-hal-detect.c +++ b/src/modules/module-hal-detect.c @@ -452,7 +452,8 @@ static void device_added_cb(LibHalContext *context, const char *udi) {  finish:      if (dbus_error_is_set(&error)) { -        pa_log_error("D-Bus error while parsing HAL data: %s: %s", error.name, error.message); +        if (!dbus_error_has_name(&error, "org.freedesktop.Hal.NoSuchProperty")) +            pa_log_error("D-Bus error while parsing HAL data: %s: %s", error.name, error.message);          dbus_error_free(&error);      }  } diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index ff8700c7..c725595f 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -1921,6 +1921,8 @@ pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink) {              t = "phone";          else if (pa_streq(ff, "portable"))              t = "multimedia-player"; +        else if (pa_streq(ff, "tv")) +            t = "video-display";      }      if (!t) | 
