Re: [pulseaudio-discuss] [PATCHv2 19/60] build: Make the build of bluetooth modules BlueZ 4 specific

2013-08-16 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:53 -0300, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  configure.ac| 28 
  src/Makefile.am | 23 ++-
  2 files changed, 30 insertions(+), 21 deletions(-)
 
 diff --git a/configure.ac b/configure.ac
 index 616a990..1c023dd 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -981,21 +981,25 @@ AX_DEFINE_DIR(PA_MACHINE_ID_FALLBACK, 
 PA_MACHINE_ID_FALLBACK,
  
   BlueZ support (optional, dependent on D-Bus) 
  
 -AC_ARG_ENABLE([bluez],
 -AS_HELP_STRING([--disable-bluez],[Disable optional BlueZ support]))
 +AC_ARG_ENABLE([bluez4],
 +AS_HELP_STRING([--disable-bluez4],[Disable optional BlueZ 4 support]))
  
 -AS_IF([test x$enable_bluez != xno],
 -[PKG_CHECK_MODULES(BLUEZ, [ bluez = 4.99 ], HAVE_BLUEZ=1, 
 HAVE_BLUEZ=0)],
 -HAVE_BLUEZ=0)
 -AS_IF([test x$enable_bluez != xno],
 +AS_IF([test x$enable_bluez4 != xno],
 +[PKG_CHECK_MODULES(BLUEZ_4, [ bluez = 4.99 bluez  5.0 ], 
 HAVE_BLUEZ_4=1, HAVE_BLUEZ_4=0)],
 +HAVE_BLUEZ_4=0)

This disables bluez4 support if bluez5 version of the .pc file is
installed. I thought earlier that bluez5 wouldn't install the file at
all, but I learned today that it does install it if bluez is built with
--enable-library. Let's not have the PKG_CHECK_MODULES check at all,
since we aren't using libbluetooth. Support for both versions shall be
built by default, regardless of the installed .pc file version.

 +AS_IF([test x$enable_bluez4 != xno],
  [PKG_CHECK_MODULES(SBC, [ sbc = 1.0 ], HAVE_SBC=1, HAVE_SBC=0)],
  HAVE_SBC=0)
 -AS_IF([test x$HAVE_SBC != x1], HAVE_BLUEZ=0)
 -AS_IF([test x$HAVE_DBUS != x1], HAVE_BLUEZ=0)
 +AS_IF([test x$HAVE_SBC != x1], HAVE_BLUEZ_4=0)
 +AS_IF([test x$HAVE_DBUS != x1], HAVE_BLUEZ_4=0)
  
 -AS_IF([test x$enable_bluez = xyes  test x$HAVE_BLUEZ = x0],
 -[AC_MSG_ERROR([*** BLUEZ support not found (requires BlueZ, sbc, and 
 D-Bus)])])
 +AS_IF([test x$enable_bluez4 = xyes  test x$HAVE_BLUEZ_4 = x0],
 +[AC_MSG_ERROR([*** BLUEZ 4 support not found (requires bluez = 4.99 and 
  5.0, sbc, and D-Bus)])])
  
 +AC_SUBST(HAVE_BLUEZ_4)
 +AM_CONDITIONAL([HAVE_BLUEZ_4], [test x$HAVE_BLUEZ_4 = x1])
 +
 +AS_IF([test x$HAVE_BLUEZ_4 = x1], HAVE_BLUEZ=1)
  AC_SUBST(HAVE_BLUEZ)
  AM_CONDITIONAL([HAVE_BLUEZ], [test x$HAVE_BLUEZ = x1])
  
 @@ -1389,7 +1393,7 @@ AS_IF([test x$HAVE_XEN = x1], ENABLE_XEN=yes, 
 ENABLE_XEN=no)
  AS_IF([test x$HAVE_DBUS = x1], ENABLE_DBUS=yes, ENABLE_DBUS=no)
  AS_IF([test x$HAVE_UDEV = x1], ENABLE_UDEV=yes, ENABLE_UDEV=no)
  AS_IF([test x$HAVE_SYSTEMD = x1], ENABLE_SYSTEMD=yes, ENABLE_SYSTEMD=no)
 -AS_IF([test x$HAVE_BLUEZ = x1], ENABLE_BLUEZ=yes, ENABLE_BLUEZ=no)
 +AS_IF([test x$HAVE_BLUEZ_4 = x1], ENABLE_BLUEZ_4=yes, ENABLE_BLUEZ_4=no)
  AS_IF([test x$HAVE_HAL_COMPAT = x1], ENABLE_HAL_COMPAT=yes, 
 ENABLE_HAL_COMPAT=no)
  AS_IF([test x$HAVE_TCPWRAP = x1], ENABLE_TCPWRAP=yes, ENABLE_TCPWRAP=no)
  AS_IF([test x$HAVE_LIBSAMPLERATE = x1], ENABLE_LIBSAMPLERATE=yes, 
 ENABLE_LIBSAMPLERATE=no)
 @@ -1440,7 +1444,7 @@ echo 
  Enable LIRC:   ${ENABLE_LIRC}
  Enable Xen PV driver:  ${ENABLE_XEN}
  Enable D-Bus:  ${ENABLE_DBUS}
 -  Enable BlueZ:${ENABLE_BLUEZ}
 +  Enable BlueZ 4:  ${ENABLE_BLUEZ_4}
  Enable udev:   ${ENABLE_UDEV}
Enable HAL-udev compat: ${ENABLE_HAL_COMPAT}
  Enable systemd login:  ${ENABLE_SYSTEMD}
 diff --git a/src/Makefile.am b/src/Makefile.am
 index ff37877..0e94725 100644
 --- a/src/Makefile.am
 +++ b/src/Makefile.am
 @@ -1320,8 +1320,12 @@ endif
  
  if HAVE_BLUEZ
  modlibexec_LTLIBRARIES += \
 + module-bluetooth-policy.la
 +endif
 +
 +if HAVE_BLUEZ_4
 +modlibexec_LTLIBRARIES += \
   module-bluetooth-proximity.la \
 - module-bluetooth-policy.la \
   libbluez4-util.la \
   module-bluez4-discover.la \
   module-bluez4-device.la
 @@ -2012,10 +2016,16 @@ module_bluetooth_proximity_la_LIBADD = 
 $(MODULE_LIBADD) $(DBUS_LIBS)
  module_bluetooth_proximity_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) 
 -DPA_BT_PROXIMITY_HELPER=\$(pulselibexecdir)/proximity-helper\
  
  proximity_helper_SOURCES = modules/bluetooth/proximity-helper.c
 -proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_LIBS)
 -proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_CFLAGS)
 +proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_4_LIBS)
 +proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_4_CFLAGS)

Uh, so we do use libbluetooth after all.

I did some investigation, and it seems that module-bluetooth-proximity
uses BlueZ 3 APIs, meaning that it hasn't worked for a while. Nobody has
complained, so nobody is using the module. Let's remove the proximity
code.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org

Re: [pulseaudio-discuss] [PATCH] bluetooth: Remove module-bluetooth-proximity

2013-08-16 Thread Tanu Kaskinen
On Fri, 2013-08-16 at 09:30 -0300, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 module-bluetooth-proximity has not worked for quite a while, since it
 uses pre-BlueZ4 APIs. Nobody complained since then, which is a good
 indication that it doesn't have much users. Even the original commit
 message refers to it more as a toy than as something of great use: add
 new fun module that automatically mutes your audio devices when you
 leave with your bluetooth phone, and unmutes when you come back
 
 Removing it we completely remove the dependency on libbluetooth.
 ---
  LICENSE|  20 +-
  po/POTFILES.in |   2 -
  src/.gitignore |   1 -
  src/Makefile.am|  20 -
  src/modules/bluetooth/module-bluetooth-proximity.c | 480 
 -
  src/modules/bluetooth/proximity-helper.c   | 202 -
  6 files changed, 10 insertions(+), 715 deletions(-)
  delete mode 100644 src/modules/bluetooth/module-bluetooth-proximity.c
  delete mode 100644 src/modules/bluetooth/proximity-helper.c

Thanks, pushed to the bluez5 branch.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 21/60] bluetooth: Create stub for module-bluez5-discover

2013-08-16 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:53 -0300, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  src/Makefile.am| 12 +++
  src/modules/bluetooth/module-bluez5-discover.c | 43 
 ++
  2 files changed, 55 insertions(+)
  create mode 100644 src/modules/bluetooth/module-bluez5-discover.c

 +int pa__init(pa_module* m) {
 +void pa__done(pa_module* m) {

Cosmetic: should be pa_module *m. I'll fix this myself.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 23/60] bluetooth: Track org.bluez for BlueZ 5

2013-08-16 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  src/modules/bluetooth/bluez5-util.c | 94 
 +
  1 file changed, 94 insertions(+)
 
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index 0f23bff..d60f63c 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -69,6 +151,18 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery 
 *y) {
  if (PA_REFCNT_DEC(y)  0)
  return;
  
 +if (y-connection) {
 +pa_dbus_remove_matches(pa_dbus_connection_get(y-connection),
 +
 type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged'
 +,arg0=' BLUEZ_SERVICE ',
 +NULL);

The match rules should only be removed if they have been added, so you
need to keep track of that. There can be multiple instances of the same
match rule, so if bluez5-util removes a match rule that it hasn't added,
it may remove someone else's match rule (a real example is bluez4-util,
because it tracks org.bluez name owner too).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 27/60] bluetooth: Create pa_bluetooth_transport for BlueZ 5 support

2013-08-16 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 Create the pa_bluetooth_transport structure to store information about
 the bluetooth transport and utility functions to manipulate this
 structure. The acquire() and release() operations are function pointers
 in the pa_bluetooth_transport structure to make possible for different
 transport backends to provide different implementations of these
 operations. Thre is also a userdata field for the transport backend
 provide data for the acquire/release functions.
 ---
  src/modules/bluetooth/bluez5-util.c | 145 
 
  src/modules/bluetooth/bluez5-util.h |  43 +++
  2 files changed, 188 insertions(+)
 
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index 1972a92..69eb759 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -36,6 +36,7 @@
  #include bluez5-util.h
  
  #define BLUEZ_SERVICE org.bluez
 +#define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE .MediaTransport1
  
  struct pa_bluetooth_discovery {
  PA_REFCNT_DECLARE;
 @@ -45,8 +46,131 @@ struct pa_bluetooth_discovery {
  bool filter_added;
  pa_hook hooks[PA_BLUETOOTH_HOOK_MAX];
  pa_hashmap *devices;
 +pa_hashmap *transports;
  };
  
 +pa_bluetooth_transport *pa_bluetooth_transport_new(pa_bluetooth_device *d, 
 const char *owner, const char *path,
 +  
 pa_bluetooth_profile_t p, const uint8_t *config, size_t size) {

Unaligned parameter list.

There is some precedence for wrapping long parameter lists like this:

pa_bluetooth_transport *pa_bluetooth_transport_new(
pa_bluetooth_device *d,
const char *owner,
const char *path,
pa_bluetooth_profile_t p,
const uint8_t *config,
size_t size) {

 +pa_bluetooth_transport *t;
 +
 +t = pa_xnew0(pa_bluetooth_transport, 1);
 +t-device = d;
 +t-owner = pa_xstrdup(owner);
 +t-path = pa_xstrdup(path);
 +t-profile = p;
 +t-config_size = size;
 +
 +if (size  0) {
 +t-config = pa_xnew(uint8_t, size);
 +memcpy(t-config, config, size);
 +}
 +
 +pa_assert_se(pa_hashmap_put(d-discovery-transports, t-path, t) = 0);
 +
 +return t;
 +}
 +
 +static void transport_state_changed(pa_bluetooth_transport *t, 
 pa_bluetooth_transport_state_t state) {
 +bool old_any_connected;
 +
 +if (t-state == state)
 +return;
 +
 +old_any_connected = 
 pa_bluetooth_device_any_transport_connected(t-device);
 +
 +pa_log_debug(Transport %s state changed from %d to %d, t-path, 
 t-state, state);

Human-readable states, please.

 +
 +t-state = state;
 +
 pa_hook_fire(t-device-discovery-hooks[PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED],
  t);
 +
 +if (old_any_connected != 
 pa_bluetooth_device_any_transport_connected(t-device))

undefined reference to `pa_bluetooth_device_any_transport_connected'

 +
 pa_hook_fire(t-device-discovery-hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED],
  t-device);
 +}
 +
 +void pa_bluetooth_transport_put(pa_bluetooth_transport *t) {
 +transport_state_changed(t, PA_BLUETOOTH_TRANSPORT_STATE_IDLE);
 +}
 +
 +void pa_bluetooth_transport_free(pa_bluetooth_transport *t) {
 +pa_assert(t);
 +
 +pa_hashmap_remove(t-device-discovery-transports, t-path);
 +pa_xfree(t-owner);
 +pa_xfree(t-path);
 +pa_xfree(t-config);
 +pa_xfree(t);
 +}
 +
 +static int bluez5_transport_acquire_cb(pa_bluetooth_transport *t, bool 
 optional, size_t *imtu, size_t *omtu) {
 +DBusMessage *m, *r;
 +DBusError err;
 +int ret;
 +uint16_t i, o;
 +const char *method = optional ? TryAcquire : Acquire;
 +
 +pa_assert(t);
 +pa_assert(t-device);
 +pa_assert(t-device-discovery);
 +
 +pa_assert_se(m = dbus_message_new_method_call(t-owner, t-path, 
 BLUEZ_MEDIA_TRANSPORT_INTERFACE, method));
 +
 +dbus_error_init(err);
 +
 +r = 
 dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(t-device-discovery-connection),
  m, -1, err);
 +if (!r) {
 +if (optional  pa_streq(err.name, org.bluez.Error.NotAvailable))
 +pa_log_info(Failed optional acquire of unavailable transport 
 %s, t-path);
 +else
 +pa_log_error(Transport %s() failed for transport %s (%s), 
 method, t-path, err.message);
 +
 +dbus_error_free(err);
 +return -1;
 +}
 +
 +if (!dbus_message_get_args(r, err, DBUS_TYPE_UNIX_FD, ret, 
 DBUS_TYPE_UINT16, i, DBUS_TYPE_UINT16, o,
 +   DBUS_TYPE_INVALID)) {
 +pa_log_error(Failed to parse %s() reply: %s, method, err.message);
 +dbus_error_free(err);
 +ret = -1;
 +goto finish;
 +}
 +
 +if (imtu)
 +*imtu = i;
 +
 +if (omtu)
 +*omtu = o;
 +
 +finish:
 +

Re: [pulseaudio-discuss] [PATCHv2 27/60] bluetooth: Create pa_bluetooth_transport for BlueZ 5 support

2013-08-18 Thread Tanu Kaskinen
On Fri, 2013-08-16 at 18:32 +0300, Tanu Kaskinen wrote:
 On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
   static void device_free(pa_bluetooth_device *d) {
  +unsigned i;
  +
   pa_assert(d);
   
  +for (i = 0; i  PA_BLUETOOTH_PROFILE_COUNT; i++) {
  +pa_bluetooth_transport *t;
  +
  +if (!(t = d-transports[i]))
  +continue;
  +
  +d-transports[i] = NULL;
  +transport_state_changed(t, 
  PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED);
  +/* TODO: check if there is no risk of calling
  + * transport_connection_changed_cb() when the transport is already 
  freed */
  +pa_bluetooth_transport_free(t);
 
 IMO pa_bluetooth_transport_free() should be called by the transport
 code, because the backend also creates the transport. The backend may
 need a callback for getting notified about the device going away. Or
 perhaps there should be pa_bluetooth_transport_kill(), with a kill()
 callback in the backend. This would be similar to how sink inputs are
 killed if the sink they're connected to goes away.
 
 If the backend is responsible for calling pa_bluetooth_transport_free(),
 the core should still ensure that t-device is set to NULL and that the
 transport is removed from discovery-transports (feel free to create
 pa_bluetooth_transport_unlink() for this purpose, if you want).

I'll add that it would be good to have the bluez transport backend in a
separate file, so that there would be clear separation with the
bluetooth core code and the transport backends.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 25/60] bluetooth: Create pa_bluetooth_device for BlueZ 5 support

2013-08-18 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
 +struct pa_bluetooth_device {
 +pa_bluetooth_discovery *discovery;
 +
 +int device_info_valid;  /* 0: no results yet; 1: good results; -1: 
 bad results ... */
 +
 +/* Device information */
 +char *path;
 +char *alias;
 +char *remote;
 +char *local;

I now noticed that you create adapter objects in later patches. I think
the local address should be stored in pa_bluetooth_adapter, and
pa_bluetooth_device should point to to the adapter object.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 31/60] bluetooth: Implement org.bluez.MediaEndpoint1.SelectConfiguration()

2013-08-18 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  src/Makefile.am |   3 +-
  src/modules/bluetooth/bluez5-util.c | 156 
 +++-
  2 files changed, 156 insertions(+), 3 deletions(-)
 
 diff --git a/src/Makefile.am b/src/Makefile.am
 index ff8bb42..3759b3c 100644
 --- a/src/Makefile.am
 +++ b/src/Makefile.am
 @@ -2055,7 +2055,8 @@ module_bluez4_device_la_CFLAGS = $(AM_CFLAGS) 
 $(DBUS_CFLAGS) $(SBC_CFLAGS)
  # Bluetooth BlueZ 5 sink / source
  libbluez5_util_la_SOURCES = \
   modules/bluetooth/bluez5-util.c \
 - modules/bluetooth/bluez5-util.h
 + modules/bluetooth/bluez5-util.h \
 + modules/bluetooth/a2dp-codecs.h
  libbluez5_util_la_LDFLAGS = -avoid-version
  libbluez5_util_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS)
  libbluez5_util_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index d0428a9..1194503 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -361,6 +361,51 @@ fail:
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  }
  
 +static uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode) {

You didn't respond to my previous comment: I think this function should
have a comment explaining on what basis the return values are chosen. As
it stands, they're just random numbers to me.

 +
 +switch (freq) {
 +case SBC_SAMPLING_FREQ_16000:
 +case SBC_SAMPLING_FREQ_32000:
 +return 53;
 +
 +case SBC_SAMPLING_FREQ_44100:
 +
 +switch (mode) {
 +case SBC_CHANNEL_MODE_MONO:
 +case SBC_CHANNEL_MODE_DUAL_CHANNEL:
 +return 31;
 +
 +case SBC_CHANNEL_MODE_STEREO:
 +case SBC_CHANNEL_MODE_JOINT_STEREO:
 +return 53;
 +
 +default:
 +pa_log_warn(Invalid channel mode %u, mode);
 +return 53;
 +}
 +
 +case SBC_SAMPLING_FREQ_48000:
 +
 +switch (mode) {
 +case SBC_CHANNEL_MODE_MONO:
 +case SBC_CHANNEL_MODE_DUAL_CHANNEL:
 +return 29;
 +
 +case SBC_CHANNEL_MODE_STEREO:
 +case SBC_CHANNEL_MODE_JOINT_STEREO:
 +return 51;
 +
 +default:
 +pa_log_warn(Invalid channel mode %u, mode);
 +return 51;
 +}
 +
 +default:
 +pa_log_warn(Invalid sampling freq %u, freq);
 +return 53;
 +}
 +}
 +
  const char *pa_bluetooth_profile_to_string(pa_bluetooth_profile_t profile) {
  switch(profile) {
  case PROFILE_A2DP_SINK:
 @@ -536,11 +581,118 @@ fail2:
  }
  
  static DBusMessage *endpoint_select_configuration(DBusConnection *conn, 
 DBusMessage *m, void *userdata) {
 +pa_bluetooth_discovery *y = userdata;
 +a2dp_sbc_t *cap, config;
 +uint8_t *pconf = (uint8_t *) config;
 +int i, size;
  DBusMessage *r;
 +DBusError err;
  
 -pa_assert_se(r = dbus_message_new_error(m, 
 BLUEZ_MEDIA_ENDPOINT_INTERFACE .Error.NotImplemented,
 -Method not implemented));
 +static const struct {
 +uint32_t rate;
 +uint8_t cap;
 +} freq_table[] = {
 +{ 16000U, SBC_SAMPLING_FREQ_16000 },
 +{ 32000U, SBC_SAMPLING_FREQ_32000 },
 +{ 44100U, SBC_SAMPLING_FREQ_44100 },
 +{ 48000U, SBC_SAMPLING_FREQ_48000 }
 +};
 +
 +dbus_error_init(err);
 +
 +if (!dbus_message_get_args(m, err, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
 cap, size, DBUS_TYPE_INVALID)) {

Passing cap may cause alignment issues when accessing cap later. A byte
array pointer should be passed instead, and the memory should be copied
to an a2dp_sbc_t variable.

 +pa_log_error(Endpoint SelectConfiguration(): %s, err.message);
 +dbus_error_free(err);
 +goto fail;
 +}
 +
 +if (size != sizeof(config)) {
 +pa_log_error(Capabilities array has invalid size);
 +goto fail;
 +}
  
 +pa_zero(config);
 +
 +/* Find the lowest freq that is at least as high as the requested 
 sampling rate */
 +for (i = 0; (unsigned) i  PA_ELEMENTSOF(freq_table); i++)
 +if (freq_table[i].rate = y-core-default_sample_spec.rate  
 (cap-frequency  freq_table[i].cap)) {
 +config.frequency = freq_table[i].cap;
 +break;
 +}
 +
 +if ((unsigned) i == PA_ELEMENTSOF(freq_table)) {
 +for (--i; i = 0; i--) {
 +if (cap-frequency  freq_table[i].cap) {
 +config.frequency = freq_table[i].cap;
 +break;
 +}
 +}
 +
 +if (i  0) {
 +pa_log_error(Not suitable sample rate);
 +goto fail;
 +   

Re: [pulseaudio-discuss] [PATCHv2 32/60] bluetooth: Implement org.bluez.MediaEndpoint1.ClearConfiguration()

2013-08-18 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  src/modules/bluetooth/bluez5-util.c | 28 ++--
  1 file changed, 26 insertions(+), 2 deletions(-)
 
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index 1194503..1d98174 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -697,11 +697,35 @@ fail:
  }
  
  static DBusMessage *endpoint_clear_configuration(DBusConnection *conn, 
 DBusMessage *m, void *userdata) {
 +pa_bluetooth_discovery *y = userdata;
 +pa_bluetooth_transport *t;
  DBusMessage *r;
 +DBusError err;
 +const char *path;
  
 -pa_assert_se(r = dbus_message_new_error(m, 
 BLUEZ_MEDIA_ENDPOINT_INTERFACE .Error.NotImplemented,
 -Method not implemented));
 +dbus_error_init(err);
  
 +if (!dbus_message_get_args(m, err, DBUS_TYPE_OBJECT_PATH, path, 
 DBUS_TYPE_INVALID)) {
 +pa_log_error(Endpoint ClearConfiguration(): %s, err.message);
 +dbus_error_free(err);
 +goto fail;
 +}
 +
 +if ((t = pa_hashmap_get(y-transports, path))) {
 +pa_log_debug(Clearing transport %s profile %s, t-path, 
 pa_bluetooth_profile_to_string(t-profile));
 +transport_state_changed(t, 
 PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED);
 +t-device-transports[t-profile] = NULL;
 +/* TODO: check if there is no risk of calling
 + * transport_connection_changed_cb() when the transport is already 
 freed */
 +pa_bluetooth_transport_free(t);

Similar to what I said about device_free(), the core code shouldn't call
pa_bluetooth_transport_free() here either. I think
pa_bluetooth_transport should have a configuration_cleared() callback,
and the transport backend can then call pa_bluetooth_transport_free() if
it wants.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 37/60] bluetooth: Parse BlueZ 5 adapter properties

2013-08-18 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
 +static int parse_adapter_properties(pa_bluetooth_discovery *y, const char 
 *adapter, DBusMessageIter *i) {
 +DBusMessageIter element_i;
 +
 +pa_assert(y);
 +pa_assert(adapter);
 +
 +dbus_message_iter_recurse(i, element_i);
 +
 +while (dbus_message_iter_get_arg_type(element_i) == 
 DBUS_TYPE_DICT_ENTRY) {
 +DBusMessageIter dict_i, variant_i;
 +const char *key;
 +
 +dbus_message_iter_recurse(element_i, dict_i);
 +
 +key = check_variant_property(dict_i);
 +if (key == NULL) {
 +pa_log_error(Received invalid property for adapter %s, 
 adapter);
 +return -1;
 +}
 +
 +dbus_message_iter_recurse(dict_i, variant_i);
 +
 +if (dbus_message_iter_get_arg_type(variant_i) == DBUS_TYPE_STRING 
  pa_streq(key, Address)) {
 +char *value;
 +pa_bluetooth_adapter *a = pa_xnew(pa_bluetooth_adapter, 1);
 +
 +dbus_message_iter_get_basic(variant_i, value);
 +a-path = pa_xstrdup(adapter);
 +a-address = pa_xstrdup(value);
 +pa_hashmap_put(y-adapters, a-path, a);

This leaks pa_bluetooth_adapter objects if bluetoothd sends duplicate
addresses. pa_bluetooth_adapter creation should be handled in the same
way as pa_bluetooth_device creation.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 39/60] bluetooth: Parse BlueZ 5 device properties

2013-08-18 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 This code is based on previous work by Mikel Astiz.
 ---
  src/modules/bluetooth/bluez5-util.c | 150 
 +++-
  src/modules/bluetooth/bluez5-util.h |   1 +
  2 files changed, 150 insertions(+), 1 deletion(-)
 
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index 1118bd0..94e3c35 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -282,6 +282,7 @@ static pa_bluetooth_device* 
 device_create(pa_bluetooth_discovery *y, const char
  d = pa_xnew0(pa_bluetooth_device, 1);
  d-discovery = y;
  d-path = pa_xstrdup(path);
 +d-uuids = pa_hashmap_new(pa_idxset_string_hash_func, 
 pa_idxset_string_compare_func);
  
  pa_hashmap_put(y-devices, d-path, d);
  
 @@ -336,6 +337,9 @@ static void device_free(pa_bluetooth_device *d) {
  pa_bluetooth_transport_free(t);
  }
  
 +if (d-uuids)
 +pa_hashmap_free(d-uuids, NULL);
 +
  d-discovery = NULL;
  pa_xfree(d-path);
  pa_xfree(d-alias);
 @@ -379,6 +383,145 @@ static void adapter_remove_all(pa_bluetooth_discovery 
 *y) {
  }
  }
  
 +static int parse_device_property(pa_bluetooth_device *d, DBusMessageIter *i, 
 bool is_property_change) {
 +const char *key;
 +DBusMessageIter variant_i;
 +
 +pa_assert(d);
 +
 +key = check_variant_property(i);
 +if (key == NULL) {
 +pa_log_error(Received invalid property for device %s, d-path);
 +return -1;
 +}
 +
 +dbus_message_iter_recurse(i, variant_i);
 +
 +switch (dbus_message_iter_get_arg_type(variant_i)) {
 +
 +case DBUS_TYPE_STRING: {
 +const char *value;
 +dbus_message_iter_get_basic(variant_i, value);
 +
 +if (pa_streq(key, Alias)) {
 +pa_xfree(d-alias);
 +d-alias = pa_xstrdup(value);
 +pa_log_debug(%s: %s, key, value);
 +} else if (pa_streq(key, Address)) {
 +if (is_property_change) {
 +pa_log_error(Device property 'Address' expected to be 
 constant but changed for %s, d-path);
 +return -1;
 +}
 +
 +if (d-remote) {
 +pa_log_error(Device %s: Received a duplicate 'Address' 
 property., d-path);
 +return -1;
 +}
 +
 +d-remote = pa_xstrdup(value);
 +pa_log_debug(%s: %s, key, value);
 +}
 +
 +break;
 +}
 +
 +case DBUS_TYPE_OBJECT_PATH: {
 +const char *value;
 +dbus_message_iter_get_basic(variant_i, value);
 +
 +if (pa_streq(key, Adapter)) {
 +pa_bluetooth_adapter *a;
 +
 +if (is_property_change) {
 +pa_log_error(Device property 'Adapter' expected to be 
 constant but changed for %s, d-path);
 +return -1;
 +}
 +
 +if (d-local) {
 +pa_log_error(Device %s: Received a duplicate 'Adapter' 
 property., d-path);
 +return -1;
 +}
 +
 +a = pa_hashmap_get(d-discovery-adapters, value);
 +d-local = pa_xstrdup(a-address);

There's no guarantee that a is non-NULL. bluetoothd may send a bogus
adapter path, or since the initial information about adapters and
devices is sent in the same message, it's possible that we haven't yet
parsed the adapter object information.

This is a bit hairy situation, because we don't know whether we will see
the referenced adapter later or not, if it's missing at this point. I
think we will have to save the adapter path here, and attempt to resolve
it to a pa_bluetooth_adapter pointer after all interfaces have been
parsed.

 +pa_log_debug(%s: %s, key, value);
 +}
 +
 +break;
 +}
 +
 +case DBUS_TYPE_UINT32: {
 +uint32_t value;
 +dbus_message_iter_get_basic(variant_i, value);
 +
 +if (pa_streq(key, Class)) {
 +d-class_of_device = (int) value;

Why is class_of_device signed if the Class property is unsigned? I would
understand it if uninitialized class was signalled with a negative
value, but that doesn't seem to be done either.

 +pa_log_debug(%s: %d, key, value);
 +}
 +
 +break;
 +}
 +
 +case DBUS_TYPE_ARRAY: {
 +DBusMessageIter ai;
 +dbus_message_iter_recurse(variant_i, ai);
 +
 +if (dbus_message_iter_get_arg_type(ai) == DBUS_TYPE_STRING  
 pa_streq(key, UUIDs)) {
 +/* bluetoothd never removes UUIDs from a device object so 
 there
 + * is no need to handle it here. */
 +while 

Re: [pulseaudio-discuss] [PATCHv2 44/60] bluetooth: Get BlueZ 5 device object

2013-08-18 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 Get the remote device information stored in pa_bluetooth_discovery. This
 also creates the mandatory parameter 'path' for module-bluez5-device,
 which is used to inform the object path of the remote device in BlueZ on
 the module load.
 ---
  src/modules/bluetooth/module-bluez5-device.c | 65 
 
  1 file changed, 65 insertions(+)
 
 diff --git a/src/modules/bluetooth/module-bluez5-device.c 
 b/src/modules/bluetooth/module-bluez5-device.c
 index 890f7e4..c1c3477 100644
 --- a/src/modules/bluetooth/module-bluez5-device.c
 +++ b/src/modules/bluetooth/module-bluez5-device.c
 @@ -25,6 +25,7 @@
  #endif
  
  #include pulsecore/module.h
 +#include pulsecore/modargs.h
  
  #include bluez5-util.h
  
 @@ -34,10 +35,74 @@ PA_MODULE_AUTHOR(João Paulo Rechi Vita);
  PA_MODULE_DESCRIPTION(BlueZ 5 Bluetooth audio sink and source);
  PA_MODULE_VERSION(PACKAGE_VERSION);
  PA_MODULE_LOAD_ONCE(false);
 +PA_MODULE_USAGE(path=device object path);
 +
 +static const char* const valid_modargs[] = {
 +path,
 +NULL
 +};
 +
 +struct userdata {
 +pa_module *module;
 +pa_core *core;
 +pa_modargs *modargs;

The modargs field is not needed in userdata.

 +
 +pa_bluetooth_discovery *discovery;
 +pa_bluetooth_device *device;
 +};
  
  int pa__init(pa_module* m) {
 +struct userdata *u;
 +pa_modargs *ma;
 +const char *path;
 +
 +pa_assert(m);
 +
 +if (!(ma = pa_modargs_new(m-argument, valid_modargs))) {
 +pa_log_error(Failed to parse module arguments);
 +goto fail;
 +}
 +
 +if (!(path = pa_modargs_get_value(ma, path, NULL))) {
 +pa_log_error(Failed to get device path from module arguments);
 +goto fail;
 +}

ma is leaked if parsing the path argument fails.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 27/60] bluetooth: Create pa_bluetooth_transport for BlueZ 5 support

2013-08-20 Thread Tanu Kaskinen
On Mon, 2013-08-19 at 13:44 -0300, João Paulo Rechi Vita wrote:
 On Fri, Aug 16, 2013 at 12:32 PM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
  From: João Paulo Rechi Vita jprv...@openbossa.org
 
  Create the pa_bluetooth_transport structure to store information about
  the bluetooth transport and utility functions to manipulate this
  structure. The acquire() and release() operations are function pointers
  in the pa_bluetooth_transport structure to make possible for different
  transport backends to provide different implementations of these
  operations. Thre is also a userdata field for the transport backend
  provide data for the acquire/release functions.
  ---
   src/modules/bluetooth/bluez5-util.c | 145 
  
   src/modules/bluetooth/bluez5-util.h |  43 +++
   2 files changed, 188 insertions(+)
 
  diff --git a/src/modules/bluetooth/bluez5-util.c 
  b/src/modules/bluetooth/bluez5-util.c
  index 1972a92..69eb759 100644
  --- a/src/modules/bluetooth/bluez5-util.c
  +++ b/src/modules/bluetooth/bluez5-util.c
  @@ -36,6 +36,7 @@
   #include bluez5-util.h
 
   #define BLUEZ_SERVICE org.bluez
  +#define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE .MediaTransport1
 
   struct pa_bluetooth_discovery {
   PA_REFCNT_DECLARE;
  @@ -45,8 +46,131 @@ struct pa_bluetooth_discovery {
   bool filter_added;
   pa_hook hooks[PA_BLUETOOTH_HOOK_MAX];
   pa_hashmap *devices;
  +pa_hashmap *transports;
   };
 
  +pa_bluetooth_transport *pa_bluetooth_transport_new(pa_bluetooth_device 
  *d, const char *owner, const char *path,
  +  
  pa_bluetooth_profile_t p, const uint8_t *config, size_t size) {
 
  Unaligned parameter list.
 
  There is some precedence for wrapping long parameter lists like this:
 
  pa_bluetooth_transport *pa_bluetooth_transport_new(
  pa_bluetooth_device *d,
  const char *owner,
  const char *path,
  pa_bluetooth_profile_t p,
  const uint8_t *config,
  size_t size) {
 
 
 Ok. Maybe we should add this to the official coding style guidelines
 in the wiki, although I personally dislike having the function
 parameters aligned in the same level as the function implementation.
 My preference would be to have them aligned after the opening
 parenthesis.

The parameters in my suggestion aren't aligned in the same level as the
function implementation - the indentation for the parameters is 8
spaces, while the function implementation is indented by 4 spaces.

I'll discuss with Arun and David about standardizing this or some other
style.

   static void device_free(pa_bluetooth_device *d) {
  +unsigned i;
  +
   pa_assert(d);
 
  +for (i = 0; i  PA_BLUETOOTH_PROFILE_COUNT; i++) {
  +pa_bluetooth_transport *t;
  +
  +if (!(t = d-transports[i]))
  +continue;
  +
  +d-transports[i] = NULL;
  +transport_state_changed(t, 
  PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED);
  +/* TODO: check if there is no risk of calling
  + * transport_connection_changed_cb() when the transport is 
  already freed */
  +pa_bluetooth_transport_free(t);
 
  IMO pa_bluetooth_transport_free() should be called by the transport
  code, because the backend also creates the transport. The backend may
  need a callback for getting notified about the device going away. Or
  perhaps there should be pa_bluetooth_transport_kill(), with a kill()
  callback in the backend. This would be similar to how sink inputs are
  killed if the sink they're connected to goes away.
 
  If the backend is responsible for calling pa_bluetooth_transport_free(),
  the core should still ensure that t-device is set to NULL and that the
  transport is removed from discovery-transports (feel free to create
  pa_bluetooth_transport_unlink() for this purpose, if you want).
 
 
 I'll answer this comment in the next message in this thread due to the
 additional comment in that message.
 
  As for the TODO item, I don't know what it means. There is no
  transport_connection_changed_cb() function.
 
 
 transport_connection_changed_cb() is the callback in
 module-bluez5-device for the hook
 PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED, which is fired by the
 transport_state_changed() call right before the TODO line. Depending
 on the way hook callbacks are called by the mainloop t may be already
 freed by the pa_bluetooth_transport_free() call after the TODO line.

Ok, so you mean transport_state_changed_cb(), not
transport_connection_changed_cb(). If I understood correctly, you worry
that the hook callbacks might get called asynchronously. Don't worry,
they're always synchronous.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio

Re: [pulseaudio-discuss] [PATCHv2 30/60] bluetooth: Implement org.bluez.MediaEndpoint1.SetConfiguration()

2013-08-20 Thread Tanu Kaskinen
On Mon, 2013-08-19 at 13:57 -0300, João Paulo Rechi Vita wrote:
 On Sun, Aug 18, 2013 at 6:03 AM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
  From: João Paulo Rechi Vita jprv...@openbossa.org
 
  ---
   src/modules/bluetooth/bluez5-util.c | 171 
  +++-
   src/modules/bluetooth/bluez5-util.h |   5 ++
   2 files changed, 174 insertions(+), 2 deletions(-)
 
  diff --git a/src/modules/bluetooth/bluez5-util.c 
  b/src/modules/bluetooth/bluez5-util.c
  index 9687997..d0428a9 100644
  --- a/src/modules/bluetooth/bluez5-util.c
  +++ b/src/modules/bluetooth/bluez5-util.c
  @@ -33,6 +33,8 @@
   #include pulsecore/refcnt.h
   #include pulsecore/shared.h
 
  +#include a2dp-codecs.h
  +
   #include bluez5-util.h
 
   #define BLUEZ_SERVICE org.bluez
  @@ -359,12 +361,177 @@ fail:
   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
  +const char *pa_bluetooth_profile_to_string(pa_bluetooth_profile_t 
  profile) {
  +switch(profile) {
  +case PROFILE_A2DP_SINK:
  +return a2dp_sink;
  +case PROFILE_A2DP_SOURCE:
  +return a2dp_source;
  +case PROFILE_OFF:
  +return off;
  +}
  +
  +return NULL;
  +}
  +
   static DBusMessage *endpoint_set_configuration(DBusConnection *conn, 
  DBusMessage *m, void *userdata) {
  +pa_bluetooth_discovery *y = userdata;
  +pa_bluetooth_device *d;
  +pa_bluetooth_transport *t;
  +const char *sender, *path, *endpoint_path, *dev_path = NULL, *uuid = 
  NULL;
  +uint8_t *config = NULL;
 
  config should be marked as const, because it will point to memory owned
  by the DBusMessage object.
 
 
 Ok.
 
  +int size = 0;
  +pa_bluetooth_profile_t p = PROFILE_OFF;
  +DBusMessageIter args, props;
   DBusMessage *r;
 
  -pa_assert_se(r = dbus_message_new_error(m, 
  BLUEZ_MEDIA_ENDPOINT_INTERFACE .Error.NotImplemented,
  -Method not implemented));
  +if (!dbus_message_iter_init(m, args) || 
  !pa_streq(dbus_message_get_signature(m), oa{sv})) {
  +pa_log_error(Invalid signature for method SetConfiguration());
  +goto fail2;
  +}
  +
  +dbus_message_iter_get_basic(args, path);
  +
  +if (pa_hashmap_get(y-transports, path)) {
  +pa_log_error(Endpoint SetConfiguration(): Transport %s is 
  already configured., path);
  +goto fail2;
  +}
  +
  +pa_assert_se(dbus_message_iter_next(args));
  +
  +dbus_message_iter_recurse(args, props);
  +if (dbus_message_iter_get_arg_type(props) != DBUS_TYPE_DICT_ENTRY)
  +goto fail;
  +
  +/* Read transport properties */
  +while (dbus_message_iter_get_arg_type(props) == 
  DBUS_TYPE_DICT_ENTRY) {
  +const char *key;
  +DBusMessageIter value, entry;
  +int var;
  +
  +dbus_message_iter_recurse(props, entry);
  +dbus_message_iter_get_basic(entry, key);
  +
  +dbus_message_iter_next(entry);
  +dbus_message_iter_recurse(entry, value);
  +
  +var = dbus_message_iter_get_arg_type(value);
  +
  +if (pa_streq(key, UUID)) {
  +if (var != DBUS_TYPE_STRING) {
  +pa_log_error(Property %s of wrong type %c, key, 
  (char)var);
  +goto fail;
  +}
  +
  +dbus_message_iter_get_basic(value, uuid);
  +} else if (pa_streq(key, Device)) {
  +if (var != DBUS_TYPE_OBJECT_PATH) {
  +pa_log_error(Property %s of wrong type %c, key, 
  (char)var);
  +goto fail;
  +}
  +
  +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);
  +goto fail;
  +}
  +
  +dbus_message_iter_recurse(value, array);
  +var = dbus_message_iter_get_arg_type(array);
  +if (var != DBUS_TYPE_BYTE) {
  +pa_log_error(%s is an array of wrong type %c, key, 
  (char)var);
  +goto fail;
  +}
  +
  +dbus_message_iter_get_fixed_array(array, config, size);
  +c = (a2dp_sbc_t *) config;
 
  You should check that the config size is what you expect it to be.
 
  Also, casting the byte array to an a2dp_sbc_t pointer seems hazardous
  from memory alignment point of view. I think it would be best to copy
  the config to a real a2dp_sbc_t variable before accessing the config.
 
 
 Why it is hazardous? The BlueZ' media API documentation explicitly
 states that we should the binary blob as-is. From doc/media-api.txt:
 Configuration blob, it is used as it is so the size and byte order
 must match.. Additionally, the a2dp_sbc_t

Re: [pulseaudio-discuss] [PATCH] module-tunnel-sink-new: add a rewrite of module-tunnel using libpulse

2013-08-20 Thread Tanu Kaskinen
On Mon, 2013-08-19 at 07:41 +0200, Alexander Couzens wrote:
 Old module-tunnel shares duplicated functionality with libpulse because
 it is implementing pulse protocol again.
 module-tunnel-sink-new uses libpulse to connect to the remote server
 
 Signed-off-by: Alexander Couzens lyn...@fe80.eu
 ---
  src/Makefile.am  |   6 +
  src/modules/module-tunnel-sink-new.c | 526 
 +++
  2 files changed, 532 insertions(+)
  create mode 100644 src/modules/module-tunnel-sink-new.c
 
 diff --git a/src/Makefile.am b/src/Makefile.am
 index 6de6e96..27477e9 100644
 --- a/src/Makefile.am
 +++ b/src/Makefile.am
 @@ -1097,6 +1097,7 @@ modlibexec_LTLIBRARIES += \
   module-remap-sink.la \
   module-remap-source.la \
   module-ladspa-sink.la \
 + module-tunnel-sink-new.la \
   module-tunnel-sink.la \
   module-tunnel-source.la \
   module-position-event-sounds.la \
 @@ -1368,6 +1369,7 @@ SYMDEF_FILES = \
   module-ladspa-sink-symdef.h \
   module-equalizer-sink-symdef.h \
   module-match-symdef.h \
 + module-tunnel-sink-new-symdef.h \
   module-tunnel-sink-symdef.h \
   module-tunnel-source-symdef.h \
   module-null-sink-symdef.h \
 @@ -1638,6 +1640,10 @@ module_match_la_SOURCES = modules/module-match.c
  module_match_la_LDFLAGS = $(MODULE_LDFLAGS)
  module_match_la_LIBADD = $(MODULE_LIBADD)
  
 +module_tunnel_sink_new_la_SOURCES = modules/module-tunnel-sink-new.c
 +module_tunnel_sink_new_la_LDFLAGS = $(MODULE_LDFLAGS)
 +module_tunnel_sink_new_la_LIBADD = $(MODULE_LIBADD)
 +
  module_tunnel_sink_la_SOURCES = modules/module-tunnel.c
  module_tunnel_sink_la_CFLAGS = -DTUNNEL_SINK=1 $(AM_CFLAGS)
  module_tunnel_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
 diff --git a/src/modules/module-tunnel-sink-new.c 
 b/src/modules/module-tunnel-sink-new.c
 new file mode 100644
 index 000..18448c2
 --- /dev/null
 +++ b/src/modules/module-tunnel-sink-new.c
 @@ -0,0 +1,526 @@
 +/***
 +This file is part of PulseAudio.
 +
 +Copyright 2013 Alexander Couzens
 +
 +PulseAudio is free software; you can redistribute it and/or modify
 +it under the terms of the GNU Lesser General Public License as published
 +by the Free Software Foundation; either version 2.1 of the License,
 +or (at your option) any later version.
 +
 +PulseAudio is distributed in the hope that it will be useful, but
 +WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 +General Public License for more details.
 +
 +You should have received a copy of the GNU Lesser General Public License
 +along with PulseAudio; if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 +USA.
 +***/
 +
 +#ifdef HAVE_CONFIG_H
 +#include config.h
 +#endif
 +
 +#include pulse/context.h
 +#include pulse/timeval.h
 +#include pulse/xmalloc.h
 +#include pulse/stream.h
 +#include pulse/mainloop.h
 +#include pulse/introspect.h
 +#include pulse/error.h
 +
 +#include pulsecore/core.h
 +#include pulsecore/core-util.h
 +#include pulsecore/i18n.h
 +#include pulsecore/sink.h
 +#include pulsecore/modargs.h
 +#include pulsecore/log.h
 +#include pulsecore/thread.h
 +#include pulsecore/thread-mq.h
 +#include pulsecore/poll.h
 +#include pulsecore/proplist-util.h
 +
 +#include module-tunnel-sink-new-symdef.h
 +
 +PA_MODULE_AUTHOR(Alexander Couzens);
 +PA_MODULE_DESCRIPTION(Create a network sink which connects via a stream to 
 a remote PulseAudio server);
 +PA_MODULE_VERSION(PACKAGE_VERSION);
 +PA_MODULE_LOAD_ONCE(false);
 +PA_MODULE_USAGE(
 +server=address 
 +sink=name of the remote sink 
 +sink_name=name for the local sink 
 +sink_properties=properties for the local sink 
 +format=sample format 
 +channels=number of channels 
 +rate=sample rate 
 +channel_map=channel map
 +);
 +
 +#define TUNNEL_THREAD_FAILED_MAINLOOP 1
 +
 +static void stream_state_cb(pa_stream *stream, void *userdata);
 +static void stream_buffer_attr_cb(pa_stream *stream, void *userdata);
 +static void context_state_cb(pa_context *c, void *userdata);
 +static void sink_update_requested_latency_cb(pa_sink *s);
 +
 +struct userdata {
 +pa_module *module;
 +pa_sink *sink;
 +pa_thread *thread;
 +pa_thread_mq thread_mq;
 +pa_mainloop *thread_mainloop;
 +pa_mainloop_api *thread_mainloop_api;
 +
 +pa_context *context;
 +pa_stream *stream;
 +
 +pa_buffer_attr bufferattr;

I think you don't really need this field in userdata.

 +
 +bool connected;
 +
 +char *remote_server;
 +char *remote_sink_name;
 +};
 +
 +static const char* const valid_modargs[] = {
 +sink_name,
 +sink_properties,
 +server,
 +sink,
 +format,
 +channels,
 +

Re: [pulseaudio-discuss] [PATCH] add module-tunnel-sink-new v4

2013-08-20 Thread Tanu Kaskinen
On Mon, 2013-08-19 at 07:30 +0200, Alexander Couzens wrote:
 I hope i did'nt forget too much.

Not much, but something. I recommend copying my review to a text file,
and removing those pieces of feedback that you have addressed. When the
file is empty, you know you have addressed everything.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 1/2] client-conf-x11|client-conf: refactor cookie loaders

2013-08-20 Thread Tanu Kaskinen
client-conf is sufficient for the commit prefix, instead of
client-conf-x11|client-conf. (Sorry, I know there's no way for you to
know what the prefix should be, other than trial and error...)

On Tue, 2013-08-13 at 11:36 +0200, Alexander Couzens wrote:
 Signed-off-by: Alexander Couzens lyn...@fe80.eu
 ---
  src/pulse/client-conf-x11.c | 12 +---
  src/pulse/client-conf.c | 33 ++---
  src/pulse/client-conf.h |  5 -
  3 files changed, 35 insertions(+), 15 deletions(-)
 
 diff --git a/src/pulse/client-conf-x11.c b/src/pulse/client-conf-x11.c
 index 99265c5..f520619 100644
 --- a/src/pulse/client-conf-x11.c
 +++ b/src/pulse/client-conf-x11.c
 @@ -91,20 +91,10 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char 
 *dname) {
  }
  
  if (pa_x11_get_prop(xcb, screen, PULSE_COOKIE, t, sizeof(t))) {
 -uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
 -
 -if (pa_parsehex(t, cookie, sizeof(cookie)) != sizeof(cookie)) {
 +if(pa_client_conf_load_cookie_from_hex(c, t)  0) {

Missing space after if.

  pa_log(_(Failed to parse cookie data));
  goto finish;
  }
 -
 -pa_assert(sizeof(cookie) == sizeof(c-cookie));
 -memcpy(c-cookie, cookie, sizeof(cookie));
 -
 -c-cookie_valid = true;
 -
 -pa_xfree(c-cookie_file);
 -c-cookie_file = NULL;
  }
  
  ret = 0;
 diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c
 index 8301981..f881751 100644
 --- a/src/pulse/client-conf.c
 +++ b/src/pulse/client-conf.c
 @@ -66,6 +66,8 @@ static const pa_client_conf default_conf = {
  .auto_connect_display = false
  };
  
 +static int pa_client_conf_parse_cookie_file(pa_client_conf* c);
 +
  pa_client_conf *pa_client_conf_new(void) {
  pa_client_conf *c = pa_xmemdup(default_conf, sizeof(default_conf));
  
 @@ -130,7 +132,7 @@ int pa_client_conf_load(pa_client_conf *c, const char 
 *filename) {
  r = f ? pa_config_parse(fn, f, table, NULL, NULL) : 0;
  
  if (!r)
 -r = pa_client_conf_load_cookie(c);
 +r = pa_client_conf_parse_cookie_file(c);
  
  finish:
  pa_xfree(fn);
 @@ -171,13 +173,13 @@ int pa_client_conf_env(pa_client_conf *c) {
  pa_xfree(c-cookie_file);
  c-cookie_file = pa_xstrdup(e);
  
 -return pa_client_conf_load_cookie(c);
 +return pa_client_conf_parse_cookie_file(c);

You could use pa_client_conf_load_cookie_from_file() here.

  }
  
  return 0;
  }
  
 -int pa_client_conf_load_cookie(pa_client_conf* c) {
 +static int pa_client_conf_parse_cookie_file(pa_client_conf* c) {

Static functions shouldn't be prefixed, so the function name should be
parse_cookie_file.

  int k;
  
  pa_assert(c);
 @@ -203,3 +205,28 @@ int pa_client_conf_load_cookie(pa_client_conf* c) {
  c-cookie_valid = true;
  return 0;
  }
 +
 +int pa_client_conf_load_cookie_from_hex(pa_client_conf* c, const char 
 *cookie_in_hex) {
 +uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
 +
 +if (pa_parsehex(cookie_in_hex, cookie, sizeof(cookie)) != 
 sizeof(cookie)) {
 +pa_log(_(Failed to parse cookie data));
 +return -PA_ERR_INVALID;
 +}
 +
 +pa_assert(sizeof(cookie) == sizeof(c-cookie));
 +memcpy(c-cookie, cookie, sizeof(cookie));
 +
 +c-cookie_valid = true;
 +
 +pa_xfree(c-cookie_file);
 +c-cookie_file = NULL;
 +
 +return 0;
 +}
 +
 +int pa_client_conf_load_cookie_from_file(pa_client_conf *c, const char 
 *cookie_file_path) {
 +pa_xfree(c-cookie_file);
 +c-cookie_file = pa_xstrdup(cookie_file_path);
 +return pa_client_conf_parse_cookie_file(c);
 +}
 diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h
 index 9c509f7..7b9c0c1 100644
 --- a/src/pulse/client-conf.h
 +++ b/src/pulse/client-conf.h
 @@ -49,6 +49,9 @@ int pa_client_conf_load(pa_client_conf *c, const char 
 *filename);
  int pa_client_conf_env(pa_client_conf *c);
  
  /* Load cookie data from c-cookie_file into c-cookie */
 -int pa_client_conf_load_cookie(pa_client_conf* c);
 +int pa_client_conf_load_cookie_from_file(pa_client_conf* c, const char* 
 cookie_file_path);

The comment above the function needs to be updated too.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 2/2] context: add cookie loaders + setter

2013-08-20 Thread Tanu Kaskinen
On Tue, 2013-08-13 at 11:41 +0200, Alexander Couzens wrote:
 I'm not sure if these 3 seperate calls for cookie loading are better than 
 creating a pa_context_get_conf() call and
 operating on it.

I think it's better to keep pa_client_conf as a private interface.

 
 Signed-off-by: Alexander Couzens lyn...@fe80.eu
 ---
  src/pulse/context.c | 15 +++
  src/pulse/context.h |  9 +
  2 files changed, 24 insertions(+)
 
 diff --git a/src/pulse/context.c b/src/pulse/context.c
 index 1ba2672..654284e 100644
 --- a/src/pulse/context.c
 +++ b/src/pulse/context.c
 @@ -1448,3 +1448,18 @@ size_t pa_context_get_tile_size(pa_context *c, const 
 pa_sample_spec *ss) {
  mbs = PA_ROUND_DOWN(pa_mempool_block_size_max(c-mempool), fs);
  return PA_MAX(mbs, fs);
  }
 +
 +int pa_context_set_cookie(pa_context *c, uint8_t *cookie, size_t 
 cookie_size) {

The pointers should be checked with pa_assert(). And there should be
some sanity checks:

PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
PA_CHECK_VALIDITY(c, c-state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);

(The same goes for the other functions.)

 +if(cookie_size != PA_NATIVE_COOKIE_LENGTH)

Missing space after if.

 +return -PA_ERR_INVALID;
 +memcpy(c-conf-cookie, cookie, cookie_size);

c-conf-cookie_valid should be set to true. Or actually, there should
be pa_client_conf_set_cookie() that sets the cookie_valid field -
modifying the pa_client_conf state should be done from client-conf.c
only.

 +return 0;
 +}
 +
 +int pa_context_load_cookie_from_hex(pa_context *c, const char 
 *cookie_as_hex) {
 +return pa_client_conf_load_cookie_from_hex(c-conf, cookie_as_hex);
 +}
 +
 +int pa_context_load_cookie_file(pa_context *c, const char *cookie_file_path) 
 {
 +return pa_client_conf_load_cookie_from_file(c-conf, cookie_file_path);
 +}
 diff --git a/src/pulse/context.h b/src/pulse/context.h
 index 6e615f6..20fa1ff 100644
 --- a/src/pulse/context.h
 +++ b/src/pulse/context.h
 @@ -280,6 +280,15 @@ void pa_context_rttime_restart(pa_context *c, 
 pa_time_event *e, pa_usec_t usec);
   * pa_stream_get_sample_spec(ss)); \since 0.9.20 */
  size_t pa_context_get_tile_size(pa_context *c, const pa_sample_spec *ss);
  
 +/** Set the authentication cookie */

The documentation is missing a \since 5.0 tag, and explanation about
what the cookie size should be.

We need to expose the cookie size to clients somehow. A simple #define
should be good enough. The problem with a #define in the public API is
that it can't be changed without breaking compatibility, but I don't
think we can change the cookie size anyway without breaking
compatibility between old server and new libpulse or vice versa.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] module-tunnel-sink-new: add a rewrite of module-tunnel using libpulse

2013-08-21 Thread Tanu Kaskinen
On Wed, 2013-08-21 at 13:58 +0200, Alexander Couzens wrote:
 Old module-tunnel shares duplicated functionality with libpulse because
 it is implementing pulse protocol again. It is also not
 as much tested as libpulse it.
 
 Signed-off-by: Alexander Couzens lyn...@fe80.eu
 ---
  src/Makefile.am  |   6 +
  src/modules/module-tunnel-sink-new.c | 546 
 +++
  2 files changed, 552 insertions(+)
  create mode 100644 src/modules/module-tunnel-sink-new.c

Still some small issues, but they are trivial enough for me to fix them
myself. Patch applied, thank you!

 +static void thread_func(void *userdata) {
 +struct userdata *u = userdata;
 +pa_proplist *proplist;
 +pa_assert(u);
 +
 +pa_log_debug(Thread starting up);
 +pa_thread_mq_install(u-thread_mq);
 +
 +proplist = tunnel_new_proplist(u);
 +u-context = pa_context_new_with_proplist(u-thread_mainloop_api,
 +  PulseAudio,
 +  proplist);
 +pa_proplist_free(proplist);
 +
 +if (!u-context) {
 +pa_log(Failed to create libpulse context);
 +goto fail;
 +}
 +
 +pa_context_set_state_callback(u-context, context_state_cb, u);
 +if (pa_context_connect(u-context,
 +   u-remote_server,
 +   PA_CONTEXT_NOAUTOSPAWN,
 +   NULL)  0) {
 +pa_log(Failed to connect libpulse context);
 +goto fail;
 +}
 +
 +for (;;) {
 +int ret;
 +const void *p;
 +pa_memchunk memchunk;
 +
 +size_t writable = 0;
 +
 +if (pa_mainloop_iterate(u-thread_mainloop, 1, ret)  0) {
 +if (ret == 0)
 +goto finish;
 +else
 +goto fail;
 +}
 +
 +if (PA_UNLIKELY(u-sink-thread_info.rewind_requested))
 +pa_sink_process_rewind(u-sink, 0);
 +
 +if (u-connected 
 +pa_stream_get_state(u-stream) == PA_STREAM_READY 
 +PA_SINK_IS_LINKED(u-sink-thread_info.state)) {
 +/* TODO: use IS_RUNNING and cork the stream when sink is not 
 running */

The stream should be corked only if the sink is suspended. The sink can
be idle or running, and in both cases the stream should stay uncorked.

 +static void stream_state_cb(pa_stream *stream, void *userdata) {
 +struct userdata *u = userdata;
 +
 +pa_assert(u);
 +
 +switch (pa_stream_get_state(stream)) {
 +case PA_STREAM_FAILED:
 +pa_log_error(Stream failed.);
 +u-connected = false;
 +u-thread_mainloop_api-quit(u-thread_mainloop_api, 
 TUNNEL_THREAD_FAILED_MAINLOOP);
 +break;
 +case PA_STREAM_TERMINATED:
 +pa_log_debug(Stream terminated.);
 +break;
 +case PA_STREAM_READY:
 +/* only call our requested_latency_cb when request_latency 
 changed between PA_CONNECTING - PA_STREAM_READY
 + * otherwhise we would deny servers response to bufferattr 
 (which defines latency) */

Comments should be wrapped at 80 characters.

 +if (u-update_stream_bufferattr_after_connect)
 +sink_update_requested_latency_cb(u-sink);

There should be an else section that updates the sink max_request to
match the tlength that the server assigned.

 +static void sink_update_requested_latency_cb(pa_sink *s) {
 +struct userdata *u;
 +pa_operation *operation;
 +size_t nbytes;
 +pa_usec_t block_usec;
 +pa_buffer_attr bufferattr;
 +
 +pa_sink_assert_ref(s);
 +pa_assert_se(u = s-userdata);
 +
 +block_usec = pa_sink_get_requested_latency_within_thread(s);
 +if (block_usec == (pa_usec_t) -1)
 +block_usec = s-thread_info.max_latency;
 +
 +nbytes = pa_usec_to_bytes(block_usec, s-sample_spec);
 +pa_sink_set_max_request_within_thread(s, nbytes);
 +
 +if (u-stream) {
 +switch (pa_stream_get_state(u-stream)) {
 +case PA_STREAM_READY:

One level of indentation is missing.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] source-output: Get the correct source for direct_on_input streams

2013-08-21 Thread Tanu Kaskinen
On Wed, 2013-08-14 at 16:58 +0300, Tanu Kaskinen wrote:
 If a capture stream captures from a single sink input (so the capture
 stream is a so called direct on input stream), then it needs to
 connect to the monitor source of the sink to which the sink input is
 connected. Previously the correct source was not figured out
 automatically, causing the capture stream creation to fail.
 ---
  src/pulsecore/source-output.c | 14 +++---
  1 file changed, 11 insertions(+), 3 deletions(-)
 
 diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
 index 66a33bd..fafc226 100644
 --- a/src/pulsecore/source-output.c
 +++ b/src/pulsecore/source-output.c
 @@ -255,9 +255,17 @@ int pa_source_output_new(
  pa_return_val_if_fail(!data-driver || pa_utf8_valid(data-driver), 
 -PA_ERR_INVALID);
  
  if (!data-source) {
 -pa_source *source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE);
 -pa_return_val_if_fail(source, -PA_ERR_NOENTITY);
 -pa_source_output_new_data_set_source(data, source, false);
 +pa_source *source;
 +
 +if (data-direct_on_input) {
 +source = data-direct_on_input-sink-monitor_source;
 +pa_return_val_if_fail(source, -PA_ERR_INVALID);
 +pa_source_output_new_data_set_source(data, source, false);
 +} else {
 +source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE);
 +pa_return_val_if_fail(source, -PA_ERR_NOENTITY);
 +pa_source_output_new_data_set_source(data, source, false);
 +}
  }
  
  /* Routing's done, we have a source. Now let's fix the format and set up 
 the

No feedback received, I have now applied this patch.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 60/60] bluetooth: Revive module-bluetooth-discover

2013-08-22 Thread Tanu Kaskinen
On Mon, 2013-08-19 at 12:54 +0300, Tanu Kaskinen wrote:
 On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
  +static bool exists(const char *filename) {
  +const char *paths, *state = NULL;
  +char *p, *pathname;
  +bool result;
  +
  +if (!(paths = lt_dlgetsearchpath()))
 
 undefined reference to `lt_dlgetsearchpath'
 
 Does this compile on your machine?

Apparently this works on some machines and not on others. On my machine
this is required to make the linking work:

-module_bluetooth_discover_la_LIBADD = $(MODULE_LIBADD)
+module_bluetooth_discover_la_LIBADD = $(MODULE_LIBADD) $(LIBLTDL)

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Low latency audio in-out application

2013-08-26 Thread Tanu Kaskinen
On Mon, 2013-08-26 at 13:31 +0200, Svein Seldal wrote:
 Hi
 
 I'm working on using a [dedicated] linux box for an audio filtering use. 
 My intentions is to take stereo audio in, process it, and play the 
 result on audio out (all on the same sound device). The catch is that 
 this app requires as low latency as possible to be usable in the field 
 (40ms)
 
 Since pulseaudio is conveniently available on desktops, I wrote a simple 
 pulse app which opens two streams, one record and one playback and 
 filter the audio between them.
 
 In the current design, I clock everything by using a record stream read 
 CB. The read callback takes the available data, process it, and write it 
 asynch to the playback stream without using playback write CB. This 
 works, but with significant latency (200ms).
 
 However, when I start to adjust the latency settings on either streams, 
 I get underrun errors. Apparently, even though the two streams originate 
 from the same wordclock, they expect/deliver data at varying intervals. 
 But having a floating buffer inbetween adds further delay.
 
 Does anyone have ideas of what other approaches would be best for this 
 app? E.g. clock it from the playback write CB and asynchronously read 
 data from record?
 
 IMHO it would be nice if playback and record streams could be 
 syncronized, not just playback streams. It would make things very much 
 simpler when record deliver x number of bytes, the playback wants the 
 same x number of bytes. Perhaps PA offers this already?

No, PA doesn't offer that. Reading and writing to the sound card is
handled completely separately, from different threads, so there's no
read/write synchronization in the server either.

You said that you use a dedicated box for the processing, so using the
default sound server doesn't sound like a hard requirement. In that case
I recommend using JACK, it's designed for this kind of use cases.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Low latency audio in-out application

2013-08-27 Thread Tanu Kaskinen
On Mon, 2013-08-26 at 15:04 +0200, Svein Seldal wrote:
 On 08/26/2013 02:36 PM, Tanu Kaskinen wrote:
  No, PA doesn't offer that. Reading and writing to the sound card is
  handled completely separately, from different threads, so there's no
  read/write synchronization in the server either.
 
  You said that you use a dedicated box for the processing, so using the
  default sound server doesn't sound like a hard requirement. In that case
  I recommend using JACK, it's designed for this kind of use cases.
 
 Thanks
 
 Too bad. Using PA is convenient, as it's already integrated into most 
 distros. And I am apparently misinterpreting the PA claim Good low 
 latency behaviour -- but I guess that this depending on the definition 
 of low latency...
 
 Dedicated box means that this PC is a prototype for some real-world HW 
 DSP device which the software will later be moved to. Working on a linux 
 application clearly helps development, debugging and observability.

 Perhaps it's best to approach ALSA directly for the lowest latency. Have 
 I understood it correctly that PA emulates ALSA, so I need to disable PA 
 for that particular sound device before I can access it directly?

Yes, it's a good idea to make sure that PulseAudio doesn't try to open
the sound card when you are using it (the ALSA emulation doesn't have
anything to do with this, though). The easiest way to do this is to
switch the card profile to Off with pavucontrol (in the Configuration
tab).

 OOI: What use has the synchronize stream argument in stream playback?

You can start/stop multiple streams at exactly the same time. I'm not
aware of any real-world uses for that feature, though...

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH v2 1/3] source: Fix monitor source rate changing

2013-08-27 Thread Tanu Kaskinen
When a sink changes its sample rate, also the monitor source rate
needs to be changed. In order to determine whether a source supports
rate changing, the code checks if the update_rate() callback is set,
but monitor sources don't have that callback set, so the old code
always failed to change the monitor source rate.

This patch fixes the monitor source rate changing by handling monitor
sources as a special case in pa_source_update_rate(): if the source is
a monitor source, then the update_rate() callback is not required.

BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=66424
---
 src/pulsecore/source.c | 20 ++--
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 5cb6b73..c692511 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -972,14 +972,12 @@ bool pa_source_update_rate(pa_source *s, uint32_t rate, 
bool passthrough) {
 uint32_t desired_rate = rate;
 uint32_t default_rate = s-default_sample_rate;
 uint32_t alternate_rate = s-alternate_sample_rate;
-uint32_t idx;
-pa_source_output *o;
 bool use_alternate = false;
 
 if (rate == s-sample_spec.rate)
 return true;
 
-if (!s-update_rate)
+if (!s-update_rate  !s-monitor_of)
 return false;
 
 if (PA_UNLIKELY(default_rate == alternate_rate  !passthrough)) {
@@ -1027,14 +1025,24 @@ bool pa_source_update_rate(pa_source *s, uint32_t rate, 
bool passthrough) {
 pa_log_debug(Suspending source %s due to changing the sample rate., 
s-name);
 pa_source_suspend(s, true, PA_SUSPEND_INTERNAL);
 
-if (s-update_rate(s, desired_rate) == true) {
-pa_log_info(Changed sampling rate successfully );
+if (s-update_rate)
+ret = s-update_rate(s, desired_rate);
+else {
+/* This is a monitor source. */
+s-sample_spec.rate = desired_rate;
+ret = true;
+}
+
+if (ret) {
+uint32_t idx;
+pa_source_output *o;
 
 PA_IDXSET_FOREACH(o, s-outputs, idx) {
 if (o-state == PA_SOURCE_OUTPUT_CORKED)
 pa_source_output_update_rate(o);
 }
-ret = true;
+
+pa_log_info(Changed sampling rate successfully);
 }
 
 pa_source_suspend(s, false, PA_SUSPEND_INTERNAL);
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH v2 3/3] sink, source: Fix error reporting style for rate updates

2013-08-27 Thread Tanu Kaskinen
---
 src/modules/alsa/alsa-sink.c   |  8 
 src/modules/alsa/alsa-source.c |  8 
 src/pulsecore/sink-input.c |  4 ++--
 src/pulsecore/sink.c   | 24 
 src/pulsecore/sink.h   |  4 ++--
 src/pulsecore/source-output.c  |  4 ++--
 src/pulsecore/source.c | 26 +-
 src/pulsecore/source.h |  4 ++--
 8 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index f910d19..6e60646 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1593,7 +1593,7 @@ static bool sink_set_formats(pa_sink *s, pa_idxset 
*formats) {
 return true;
 }
 
-static bool sink_update_rate_cb(pa_sink *s, uint32_t rate) {
+static int sink_update_rate_cb(pa_sink *s, uint32_t rate) {
 struct userdata *u = s-userdata;
 int i;
 bool supported = false;
@@ -1609,16 +1609,16 @@ static bool sink_update_rate_cb(pa_sink *s, uint32_t 
rate) {
 
 if (!supported) {
 pa_log_info(Sink does not support sample rate of %d Hz, rate);
-return false;
+return -1;
 }
 
 if (!PA_SINK_IS_OPENED(s-state)) {
 pa_log_info(Updating rate for device %s, new rate is 
%d,u-device_name, rate);
 u-sink-sample_spec.rate = rate;
-return true;
+return 0;
 }
 
-return false;
+return -1;
 }
 
 static int process_rewind(struct userdata *u) {
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index faf8965..78125b1 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1401,7 +1401,7 @@ static void source_update_requested_latency_cb(pa_source 
*s) {
 update_sw_params(u);
 }
 
-static bool source_update_rate_cb(pa_source *s, uint32_t rate) {
+static int source_update_rate_cb(pa_source *s, uint32_t rate) {
 struct userdata *u = s-userdata;
 int i;
 bool supported = false;
@@ -1417,16 +1417,16 @@ static bool source_update_rate_cb(pa_source *s, 
uint32_t rate) {
 
 if (!supported) {
 pa_log_info(Source does not support sample rate of %d Hz, rate);
-return false;
+return -1;
 }
 
 if (!PA_SOURCE_IS_OPENED(s-state)) {
 pa_log_info(Updating rate for device %s, new rate is %d, 
u-device_name, rate);
 u-source-sample_spec.rate = rate;
-return true;
+return 0;
 }
 
-return false;
+return -1;
 }
 
 static void thread_func(void *userdata) {
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index a275715..b5e8a0b 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -426,7 +426,7 @@ int pa_sink_input_new(
module-suspend-on-idle can resume a sink */
 
 pa_log_info(Trying to change sample rate);
-if (pa_sink_update_rate(data-sink, data-sample_spec.rate, 
pa_sink_input_new_data_is_passthrough(data)) == true)
+if (pa_sink_update_rate(data-sink, data-sample_spec.rate, 
pa_sink_input_new_data_is_passthrough(data)) = 0)
 pa_log_info(Rate changed to %u Hz, data-sink-sample_spec.rate);
 }
 
@@ -1829,7 +1829,7 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink 
*dest, bool save) {
SINK_INPUT_MOVE_FINISH hook */
 
 pa_log_info(Trying to change sample rate);
-if (pa_sink_update_rate(dest, i-sample_spec.rate, 
pa_sink_input_is_passthrough(i)) == true)
+if (pa_sink_update_rate(dest, i-sample_spec.rate, 
pa_sink_input_is_passthrough(i)) = 0)
 pa_log_info(Rate changed to %u Hz, dest-sample_spec.rate);
 }
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index bc8a3fd..de8c82e 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1377,8 +1377,8 @@ void pa_sink_render_full(pa_sink *s, size_t length, 
pa_memchunk *result) {
 }
 
 /* Called from main thread */
-bool pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
-bool ret = false;
+int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
+int ret = -1;
 uint32_t desired_rate = rate;
 uint32_t default_rate = s-default_sample_rate;
 uint32_t alternate_rate = s-alternate_sample_rate;
@@ -1387,32 +1387,32 @@ bool pa_sink_update_rate(pa_sink *s, uint32_t rate, 
bool passthrough) {
 bool use_alternate = false;
 
 if (rate == s-sample_spec.rate)
-return true;
+return 0;
 
 if (!s-update_rate)
-return false;
+return -1;
 
 if (PA_UNLIKELY(default_rate == alternate_rate  !passthrough)) {
 pa_log_debug(Default and alternate sample rates are the same.);
-return false;
+return -1;
 }
 
 if (PA_SINK_IS_RUNNING(s-state)) {
 pa_log_info(Cannot update rate, SINK_IS_RUNNING, will keep using %u 
Hz,
 s-sample_spec.rate);
-return false;
+return -1;
 }
 
 if (s-monitor_source) {
 if 

[pulseaudio-discuss] [PATCH v2 2/3] source: When updating a monitor source's rate, update the sink rate too

2013-08-27 Thread Tanu Kaskinen
If the sink rate is not updated, then the monitor source will appear
to have a different rate than the sink, but in reality there's never
any resampling done when moving data from the sink to the monitor
source, so it's a lie that the monitor source has a different rate.
The result of lying is that clients that capture from the monitor
source will have streams that run too fast or slow.
---
 src/pulsecore/source.c | 34 --
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index c692511..5e59a40 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -991,6 +991,13 @@ bool pa_source_update_rate(pa_source *s, uint32_t rate, 
bool passthrough) {
 return false;
 }
 
+if (s-monitor_of) {
+if (PA_SINK_IS_RUNNING(s-monitor_of-state)) {
+pa_log_info(Cannot update rate, this is a monitor source and the 
sink is running.);
+return false;
+}
+}
+
 if (PA_UNLIKELY (desired_rate  8000 ||
  desired_rate  PA_RATE_MAX))
 return false;
@@ -1029,8 +1036,31 @@ bool pa_source_update_rate(pa_source *s, uint32_t rate, 
bool passthrough) {
 ret = s-update_rate(s, desired_rate);
 else {
 /* This is a monitor source. */
-s-sample_spec.rate = desired_rate;
-ret = true;
+
+/* XXX: This code is written with non-passthrough streams in mind. I
+ * have no idea whether the behaviour with passthrough streams is
+ * sensible. */
+if (!passthrough) {
+uint32_t old_rate = s-sample_spec.rate;
+
+s-sample_spec.rate = desired_rate;
+ret = pa_sink_update_rate(s-monitor_of, desired_rate, false);
+
+if (!ret) {
+/* Changing the sink rate failed, roll back the old rate for
+ * the monitor source. Why did we set the source rate before
+ * calling pa_sink_update_rate(), you may ask. The reason is
+ * that pa_sink_update_rate() tries to update the monitor
+ * source rate, but we are already in the process of updating
+ * the monitor source rate, so there's a risk of entering an
+ * infinite loop. Setting the source rate before calling
+ * pa_sink_update_rate() makes the rate == s-sample_spec.rate
+ * check in the beginning of this function return early, so we
+ * avoid looping. */
+s-sample_spec.rate = old_rate;
+}
+} else
+ret = false;
 }
 
 if (ret) {
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH] resampler: Never return zero for max block size

2013-08-28 Thread Tanu Kaskinen
With very low input sample rates the memory pool max block size may
not be big enough, in which case we should return the size of one
frame. Returning zero caused crashing.

BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=68616
---
 src/pulsecore/resampler.c | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 5599035..4480823 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -534,7 +534,23 @@ size_t pa_resampler_max_block_size(pa_resampler *r) {
 if (r-remap_buf_contains_leftover_data)
 frames -= r-remap_buf.length / (r-w_sz * r-o_ss.channels);
 
-return ((uint64_t) frames * r-i_ss.rate / max_ss.rate) * r-i_fz;
+block_size_max = ((uint64_t) frames * r-i_ss.rate / max_ss.rate) * 
r-i_fz;
+
+if (block_size_max  0)
+return block_size_max;
+else
+/* A single input frame may result in so much output that it doesn't
+ * fit in one standard memblock (e.g. converting 1 Hz to 44100 Hz). In
+ * this case the max block size will be set to one frame, and some
+ * memory will be probably be allocated with malloc() instead of using
+ * the memory pool.
+ *
+ * XXX: Should we support this case at all? We could also refuse to
+ * create resamplers whose max block size would exceed the memory pool
+ * block size. In this case also updating the resampler rate should
+ * fail if the new rate would cause an excessive max block size (in
+ * which case the stream would probably have to be killed). */
+return r-i_fz;
 }
 
 void pa_resampler_reset(pa_resampler *r) {
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] suspend-on-idle: Allow disabling suspending for specific devices

2013-08-30 Thread Tanu Kaskinen
On Fri, 2013-08-30 at 08:16 +0200, David Henningsson wrote:
 On 08/29/2013 04:36 PM, Tanu Kaskinen wrote:
  Sometimes it would be nice to disable module-suspend-on-idle for
  specific devices. For me the use case is to keep a HDMI sink running
  all the time to avoid loss of audio when starting to play a stream to
  the device (the HDMI receiver eats a bit from the beginning of the
  stream when the device is opened). This is arguably a hacky solution
  to the problem, but on the other hand, I think it's very sensible to
  interpret negative timeout in the module-suspend-on-idle.timeout
  property as disabling the suspending altogher. This is also how the
  exit-idle-time configuration option behaves (negative value disables
  automatic exiting).
 
 Didn't Arun have another solution for a similar problem? Like a sink
 ALWAYS_RUNNING flag or something.

Yes, he did. That patch was not merged, and I don't know if Arun plans
to still work on it.

Regardless of Arun's solution, I think it makes sense to support
negative value for the module-suspend-on-idle.timeout property to be
consistent with other timeout parameters.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 31/60] bluetooth: Implement org.bluez.MediaEndpoint1.SelectConfiguration()

2013-09-04 Thread Tanu Kaskinen
On Tue, 2013-09-03 at 21:18 -0300, João Paulo Rechi Vita wrote:
 On Sun, Aug 18, 2013 at 6:37 AM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
   static DBusMessage *endpoint_select_configuration(DBusConnection *conn, 
  DBusMessage *m, void *userdata) {
  +pa_bluetooth_discovery *y = userdata;
  +a2dp_sbc_t *cap, config;
  +uint8_t *pconf = (uint8_t *) config;
  +int i, size;
   DBusMessage *r;
  +DBusError err;
 
  -pa_assert_se(r = dbus_message_new_error(m, 
  BLUEZ_MEDIA_ENDPOINT_INTERFACE .Error.NotImplemented,
  -Method not implemented));
  +static const struct {
  +uint32_t rate;
  +uint8_t cap;
  +} freq_table[] = {
  +{ 16000U, SBC_SAMPLING_FREQ_16000 },
  +{ 32000U, SBC_SAMPLING_FREQ_32000 },
  +{ 44100U, SBC_SAMPLING_FREQ_44100 },
  +{ 48000U, SBC_SAMPLING_FREQ_48000 }
  +};
  +
  +dbus_error_init(err);
  +
  +if (!dbus_message_get_args(m, err, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
  cap, size, DBUS_TYPE_INVALID)) {
 
  Passing cap may cause alignment issues when accessing cap later. A byte
  array pointer should be passed instead, and the memory should be copied
  to an a2dp_sbc_t variable.
 
 
 In my understanding this is the same case of your previous comment in
 enpoint_set_configuration(): a2dp_sbc_t is 1-byte aligned (packed and
 has only uint8_t fields), so there shouldn't be any problem. Or am I
 missing something?

No, you're not missing anything. My mistake.

  +pa_log_error(Endpoint SelectConfiguration(): %s, err.message);
  +dbus_error_free(err);
  +goto fail;
  +}
  +
  +if (size != sizeof(config)) {
  +pa_log_error(Capabilities array has invalid size);
  +goto fail;
  +}
 
  +pa_zero(config);
  +
  +/* Find the lowest freq that is at least as high as the requested 
  sampling rate */
  +for (i = 0; (unsigned) i  PA_ELEMENTSOF(freq_table); i++)
  +if (freq_table[i].rate = y-core-default_sample_spec.rate  
  (cap-frequency  freq_table[i].cap)) {
  +config.frequency = freq_table[i].cap;
  +break;
  +}
  +
  +if ((unsigned) i == PA_ELEMENTSOF(freq_table)) {
  +for (--i; i = 0; i--) {
  +if (cap-frequency  freq_table[i].cap) {
  +config.frequency = freq_table[i].cap;
  +break;
  +}
  +}
  +
  +if (i  0) {
  +pa_log_error(Not suitable sample rate);
  +goto fail;
  +}
  +}
  +
  +pa_assert((unsigned) i  PA_ELEMENTSOF(freq_table));
  +
  +if (y-core-default_sample_spec.channels = 1) {
  +if (cap-channel_mode  SBC_CHANNEL_MODE_MONO)
  +config.channel_mode = SBC_CHANNEL_MODE_MONO;
  +}
  +
  +if (y-core-default_sample_spec.channels = 2) {
  +if (cap-channel_mode  SBC_CHANNEL_MODE_JOINT_STEREO)
  +config.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO;
  +else if (cap-channel_mode  SBC_CHANNEL_MODE_STEREO)
  +config.channel_mode = SBC_CHANNEL_MODE_STEREO;
  +else if (cap-channel_mode  SBC_CHANNEL_MODE_DUAL_CHANNEL)
  +config.channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL;
  +else if (cap-channel_mode  SBC_CHANNEL_MODE_MONO) {
  +config.channel_mode = SBC_CHANNEL_MODE_MONO;
  +} else {
  +pa_log_error(No supported channel modes);
  +goto fail;
  +}
  +}
 
  You didn't address my earlier complaint: If
  default_sample_spec.channels is 1, but cap doesn't contain
  SBC_CHANNEL_MODE_MONO, then config.channel_mode is left uninitialized
  (well, it's initialized to zero in the beginning). I believe this is not
  what you intended.
 
 
 Yes, I think it is better to return an error to the caller here.

There's no need to return an error, we should allow any of the
two-channel modes even if default_sample_spec.channels is 1.

  I also said that if default_sample_spec is 2 and cap only contains
  SBC_CHANNEL_MODE_MONO, then the negotiation fails. It seems that that
  complaint was bogus, though, so you're right to ignore that bit.
 
 
 Sorry, I didn't understand the second part of your comment. If
 default_sample_spec.channels == 2 and cap-channel_mode has only
 SBC_CHANNEL_MODE_MONO, then config.channel_mode will receive
 SBC_CHANNEL_MODE_MONO.

Yes, this is what I meant by the complaint being bogus, so your code is
fine on this part.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 32/60] bluetooth: Implement org.bluez.MediaEndpoint1.ClearConfiguration()

2013-09-04 Thread Tanu Kaskinen
On Wed, 2013-09-04 at 15:17 -0300, João Paulo Rechi Vita wrote:
 On Sun, Aug 18, 2013 at 8:15 AM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
  From: João Paulo Rechi Vita jprv...@openbossa.org
 
  ---
   src/modules/bluetooth/bluez5-util.c | 28 ++--
   1 file changed, 26 insertions(+), 2 deletions(-)
 
  diff --git a/src/modules/bluetooth/bluez5-util.c 
  b/src/modules/bluetooth/bluez5-util.c
  index 1194503..1d98174 100644
  --- a/src/modules/bluetooth/bluez5-util.c
  +++ b/src/modules/bluetooth/bluez5-util.c
  @@ -697,11 +697,35 @@ fail:
   }
 
   static DBusMessage *endpoint_clear_configuration(DBusConnection *conn, 
  DBusMessage *m, void *userdata) {
  +pa_bluetooth_discovery *y = userdata;
  +pa_bluetooth_transport *t;
   DBusMessage *r;
  +DBusError err;
  +const char *path;
 
  -pa_assert_se(r = dbus_message_new_error(m, 
  BLUEZ_MEDIA_ENDPOINT_INTERFACE .Error.NotImplemented,
  -Method not implemented));
  +dbus_error_init(err);
 
  +if (!dbus_message_get_args(m, err, DBUS_TYPE_OBJECT_PATH, path, 
  DBUS_TYPE_INVALID)) {
  +pa_log_error(Endpoint ClearConfiguration(): %s, err.message);
  +dbus_error_free(err);
  +goto fail;
  +}
  +
  +if ((t = pa_hashmap_get(y-transports, path))) {
  +pa_log_debug(Clearing transport %s profile %s, t-path, 
  pa_bluetooth_profile_to_string(t-profile));
  +transport_state_changed(t, 
  PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED);
  +t-device-transports[t-profile] = NULL;
  +/* TODO: check if there is no risk of calling
  + * transport_connection_changed_cb() when the transport is 
  already freed */
  +pa_bluetooth_transport_free(t);
 
  Similar to what I said about device_free(), the core code shouldn't call
  pa_bluetooth_transport_free() here either. I think
  pa_bluetooth_transport should have a configuration_cleared() callback,
  and the transport backend can then call pa_bluetooth_transport_free() if
  it wants.
 
 
 All endpoint methods on the D-Bus interface are specific to the BlueZ
 transport-backend, so it's not the core calling
 pa_bluetooth_transport_free(). If we ever decide to separate the BlueZ
 5 transport backend to a different file, the endpoint functions should
 be moved altogether.

OK. What would you think about moving

t-device-transports[t-profile] = NULL;

to transport_state_changed()? Writing to pa_bluetooth_device variables
should ideally be done by the core, so if endpoint_clear_configuration()
is backend code, then this line is likely in the wrong place.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] card-restore: Watch for profiles added after card creation.

2013-09-08 Thread Tanu Kaskinen
On Thu, 2013-07-25 at 16:39 +0200, poljar (Damir Jelić) wrote:
 This patch adds the ability to restore profiles if they are added after
 card creation.
 
 Adding profiles after card creation mainly happens for bluetooth cards.
 
 Buglink: https://bugs.freedesktop.org/show_bug.cgi?id=65349
 ---
  src/modules/module-card-restore.c | 29 +
  1 file changed, 25 insertions(+), 4 deletions(-)

Applied, thanks! I fixed a small issue pointed out below.

 +static pa_hook_result_t card_profile_added_callback(pa_core *c, 
 pa_card_profile *profile, struct userdata *u) {
 +struct entry *entry;
 +
 +pa_assert(profile);
 +
 +if (!(entry = entry_read(u, profile-card-name)))
 +return PA_HOOK_OK;
 +
 +if (pa_safe_streq(entry-profile, profile-name)) {
 +pa_card_set_profile(profile-card, profile-name, true);
 +pa_log_info(Restored profile '%s' for card %s., profile-name, 
 profile-card-name);

pa_card_set_profile() can fail, in which case the log message shouldn't
be printed.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] tunnel-source-new: counterpart to module-tunnel-sink-new

2013-09-13 Thread Tanu Kaskinen
On Thu, 2013-09-12 at 14:01 +0200, Alexander Couzens wrote:
 The old tunnel module duplicates functionality that is in libpulse,
 due to implementing the native protocol, and the protocol code in
 the old tunnel module tends to get broken every now and then, because
 people forget to update the tunnel module protocol implementation
 when changing the native protocol. module-tunnel-source-new avoids this
 problem by using libpulse to communicate with the remote server.
 ---
  src/Makefile.am|   6 +
  src/modules/module-tunnel-source-new.c | 552 
 +
  2 files changed, 558 insertions(+)
  create mode 100644 src/modules/module-tunnel-source-new.c

Thanks, patch applied with a couple of changes (see below).

 +/* called from io context to read samples from the stream into our source */
 +static void read_new_samples(struct userdata *u) {
 +const void *p;
 +size_t readable = 0;
 +pa_memchunk memchunk;
 +
 +pa_assert(u);
 +u-new_data = false;
 +
 +pa_memchunk_reset(memchunk);
 +
 +if (PA_UNLIKELY(!u-connected || pa_stream_get_state(u-stream) != 
 PA_STREAM_READY))
 +return;
 +
 +readable = pa_stream_readable_size(u-stream);
 +while (PA_LIKELY(readable  0)) {

This PA_LIKELY doesn't do any good. The normal pattern is to evaluate
the condition twice: on the first pass the condition will evaluate to
true and on the second pass it will evaluate to false.

 +size_t read = 0;
 +if (PA_UNLIKELY(pa_stream_peek(u-stream, p, read) != 0)) {
 +pa_log(pa_stream_peek() failed: %s, 
 pa_strerror(pa_context_errno(u-context)));
 +u-thread_mainloop_api-quit(u-thread_mainloop_api, 
 TUNNEL_THREAD_FAILED_MAINLOOP);
 +return;
 +}
 +
 +if (PA_LIKELY(p)) {
 +/* we have valid data */
 +memchunk.memblock = 
 pa_memblock_new_fixed(u-module-core-mempool, (void *) p, read, true);
 +memchunk.length = read;
 +memchunk.index = 0;
 +
 +pa_source_post(u-source, memchunk);
 +pa_memblock_unref_fixed(memchunk.memblock);
 +pa_stream_drop(u-stream);
 +
 +readable -= read;
 +} else /* if (!p  read  0) */ {
 +/* we have a hole. generate silence */
 +pa_silence_memchunk_get(
 +u-module-core-silence_cache,
 +u-module-core-mempool,
 +memchunk,
 +u-source-sample_spec,
 +read);

I think this is not safe to call from the IO thread. The silence cache
doesn't seem to be thread safe, so it's only useful in the main thread.
We can use the memblock in u-source-silence instead.

There's no guarantee that either the memchunk returned by
pa_silence_memchunk_get() or the memblock in u-source-silence is large
enough. If it's not large enough, I think we can just call
pa_source_post() in a loop using the same memblock multiple times.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] suspend-on-idle: Allow disabling suspending for specific devices

2013-09-13 Thread Tanu Kaskinen
On Fri, 2013-09-13 at 13:20 +0530, Arun Raghavan wrote:
 On Fri, 2013-08-30 at 15:11 +0200, David Henningsson wrote:
  On 08/30/2013 09:28 AM, Tanu Kaskinen wrote:
   On Fri, 2013-08-30 at 08:16 +0200, David Henningsson wrote:
   On 08/29/2013 04:36 PM, Tanu Kaskinen wrote:
   Sometimes it would be nice to disable module-suspend-on-idle for
   specific devices. For me the use case is to keep a HDMI sink running
   all the time to avoid loss of audio when starting to play a stream to
   the device (the HDMI receiver eats a bit from the beginning of the
   stream when the device is opened). This is arguably a hacky solution
   to the problem, but on the other hand, I think it's very sensible to
   interpret negative timeout in the module-suspend-on-idle.timeout
   property as disabling the suspending altogher. This is also how the
   exit-idle-time configuration option behaves (negative value disables
   automatic exiting).
  
   Didn't Arun have another solution for a similar problem? Like a sink
   ALWAYS_RUNNING flag or something.
   
   Yes, he did. That patch was not merged, and I don't know if Arun plans
   to still work on it.
   
   Regardless of Arun's solution, I think it makes sense to support
   negative value for the module-suspend-on-idle.timeout property to be
   consistent with other timeout parameters.
   
  
  Hmm, it looks like there already is a module-suspend-on-idle.timeout
  property and you're just improving its functionality. Then I would
  typically prefer this over a new sink flag.
  
  Even better if the module-suspend-on-idle.timeout was documented though...
  
  Arun, would this solve your problem as well? Would it be possible for
  the two of you to synchronise your efforts?
 
 Tanu and I discussed this on IRC. I don't think we should use this
 property to do what I was trying to with ALWAYS_RUNNING - the module
 parameters is mechanism, and the always-running-ness is policy. Don't
 want to mix the two.
 
 That said, I've no objection to what the patch is trying to do, per se
 (i.e. extend/standardise the semantics of a device property that we
 already support).

OK, patch pushed.

For the record, I agree with Arun in that this property shouldn't be
used in the hardware description files (UCM or alsa-mixer files). I
didn't quite understand Arun's explanation about mechanism vs. policy.
My reason for disliking the property is that it's specific to
module-suspend-on-idle, while idle suspending not recommended is a
hardware property that shouldn't be tied to any particular module.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCHv2 44/60] bluetooth: Get BlueZ 5 device object

2013-09-14 Thread Tanu Kaskinen
On Fri, 2013-09-13 at 17:45 -0300, João Paulo Rechi Vita wrote:
 On Sun, Aug 18, 2013 at 10:37 AM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Tue, 2013-08-13 at 01:54 -0300, jprv...@gmail.com wrote:
  From: João Paulo Rechi Vita jprv...@openbossa.org
 
  Get the remote device information stored in pa_bluetooth_discovery. This
  also creates the mandatory parameter 'path' for module-bluez5-device,
  which is used to inform the object path of the remote device in BlueZ on
  the module load.
  ---
   src/modules/bluetooth/module-bluez5-device.c | 65 
  
   1 file changed, 65 insertions(+)
 
  diff --git a/src/modules/bluetooth/module-bluez5-device.c 
  b/src/modules/bluetooth/module-bluez5-device.c
  index 890f7e4..c1c3477 100644
  --- a/src/modules/bluetooth/module-bluez5-device.c
  +++ b/src/modules/bluetooth/module-bluez5-device.c
  @@ -25,6 +25,7 @@
   #endif
 
   #include pulsecore/module.h
  +#include pulsecore/modargs.h
 
   #include bluez5-util.h
 
  @@ -34,10 +35,74 @@ PA_MODULE_AUTHOR(João Paulo Rechi Vita);
   PA_MODULE_DESCRIPTION(BlueZ 5 Bluetooth audio sink and source);
   PA_MODULE_VERSION(PACKAGE_VERSION);
   PA_MODULE_LOAD_ONCE(false);
  +PA_MODULE_USAGE(path=device object path);
  +
  +static const char* const valid_modargs[] = {
  +path,
  +NULL
  +};
  +
  +struct userdata {
  +pa_module *module;
  +pa_core *core;
  +pa_modargs *modargs;
 
  The modargs field is not needed in userdata.
 
 
 How am I supposed to free it in pa__done() then? I don't keep the
 pointer to modargs anywhere else.

You only need the modargs in pa__init(), so you can free it in
pa__init().

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] An raop2 support

2013-09-19 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 23:09 -0500, Hajime Fujita wrote:
 Hi Tanu,
 
 Thank you so much for your advice.
 
 Tanu Kaskinen wrote:
  On Sun, 2013-09-15 at 00:24 -0500, Hajime Fujita wrote:
  For those who are interested in raop2 experiments,
 
  As Matthias pointed out [1], current volume calculation is incorrect.
  https://bugs.freedesktop.org/show_bug.cgi?id=42804#c43
 
  I have uploaded a patch which calculates volume in more reasonable way.
  https://github.com/hfujita/pulseaudio-raop2/commit/69f3ce883dfb93eb7b24f98b9664e14071672475
 
  First I have to confess that this is the first time for me to deal with
  the unit 'dB', so maybe I'm doing totally stupid. I'd be very happy if I
  could have any suggestions from who is more experienced in this field.
 
  I started looking at pa_raop_client_set_volume() in
  src/modules/raop/raop_client.c. It was using pa_sw_volume_to_dB to
  calculate dB from a linear scale.
  
  Correction: pa_volume_t doesn't use a linear scale, it uses a cubic
  scale (see pa_sw_volume_from_linear() and pa_sw_volume_to_linear()).
 
 I see. I should have noticed some comments about cubic scale.
 http://cgit.freedesktop.org/pulseaudio/pulseaudio/tree/src/pulse/volume.c#n251
 
  
  Then I learned from code reading that pa_sw_volume_to_dB essentially
  calculates the following:
20 * log10((v/MAXVOLUME)^3) = 60 * log10(v/MAXVOLUME)
  This does not fit into the volume scale which RAOP is expecting, where
  -30.0 db is a kind of minimum [2].
 
  [2]: http://git.zx2c4.com/Airtunes2/about/#id29
 
  Also I looked at packet dumps from iPad and guessed how it calculated dB
  from a linear scale. It looked like iPad was using the following formula.
db = 10 * log10(volume/MAXVOLUME/30)
  So for the time being I decided to follow this way.
  
  The way to convert pa_volume_t to dB is to use pa_sw_volume_to_dB().
  Doing anything else means that the result is not dB, it's something
  different.
  
  The way to handle this is to ensure that the volume that is given to
  pa_raop_client_set_volume() is never outside the supported range. In
  module-raop-sink.c there's sink_set_volume_cb(), which calls
  pa_raop_client_set_volume(). In sink_set_volume_cb() there's this line:
  
  pa_cvolume_set(hw, s-sample_spec.channels, v);
  
  Before that line you should check what dB value v corresponds to, and if
  it's outside the supported range, then you should modify v to fall into
  the supported range. Any modification that you make to v will be
  compensated with software volume, so the modifications shouldn't affect
  the resulting volume at all, assuming that the RAOP device actually
  attenuates the signal by the dB amount that you send to it.
  
 
 According to your advice, I inserted an adjustment to v before
 pa_cvolume_set. Here's the patch.
 https://github.com/hfujita/pulseaudio-raop2/commit/c6337c0fef7710ee20b42ed3fb87ec12910ce35a
 
 Adjustment goes like this (pa_raop_client_adjust_volume()):
   adj(v) = v * (1 - minv/maxv) + minv;
 where pa_sw_volume_to_dB(minv) = -30.0,
 and pa_sw_volume_to_dB(maxv) = 0.0
 
 The idea is that when the original v is 0, adj(0) = minv. And when the
 original v is maxv, adj(maxv) = maxv;
 
 Does this make sense?

The idea was to simply adjust v to -30 dB if the original v is less than
that. There's no need to do any complicated calculations.

 As you noted, this also affects the software volume, and in my
 environment, the actual volume (volume heard from the speaker) may be
 way too small.

What do you mean by way too small? The maximum volume will be the same
as before, but the minimum volume will be quieter than before. With the
original code you complained that you need to keep the volume at rather
low levels, so extending the scale towards low volumes should help with
this.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Best Case Latency

2013-09-19 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 04:28 +1000, Patrick Shirkey wrote:
 Hi,
 
 Can someone shed some light on the best case and typical latency that
 Pulse provides for standard operations?

What do you mean by standard operations? I'd estimate volume changes
etc. normally (on an ALSA sink) have a few millisecond latency (best
case 0.5 ms audio buffer + scheduling latency).

 Also how that is affected by using jack-sink assuming jack is set to the
 lowest possible latency that a device can handle?

When jackd asks for N frames from PulseAudio, pulseaudio will render N
frames. There's no extra buffering done in the Jack sink, so volume
changes etc. will have latency that is roughly the same as the normal
Jack client latency.

If by standard operations you meant the stream latency that PulseAudio
clients see (in which case standard operations is a strange way to say
it, IMO), then that depends on what the clients request. If they let
PulseAudio choose, the latency is typically 2 seconds. If they want
minimal latency, with infinite CPU power I think the lower bound is
maybe a couple of milliseconds, but since computers don't have infinite
CPU power, the practical limit is some tens of milliseconds based on
what I've heard (the exact limit naturally depends on how beefy the CPU
is).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] An raop2 support

2013-09-20 Thread Tanu Kaskinen
On Thu, 2013-09-19 at 22:47 -0500, Hajime Fujita wrote:
 Hi Tanu,
 
 Tanu Kaskinen wrote:
  On Wed, 2013-09-18 at 23:09 -0500, Hajime Fujita wrote:
  Hi Tanu,
 
  Thank you so much for your advice.
 
  Tanu Kaskinen wrote:
  On Sun, 2013-09-15 at 00:24 -0500, Hajime Fujita wrote:
  For those who are interested in raop2 experiments,
 
  As Matthias pointed out [1], current volume calculation is incorrect.
  https://bugs.freedesktop.org/show_bug.cgi?id=42804#c43
 
  I have uploaded a patch which calculates volume in more reasonable way.
  https://github.com/hfujita/pulseaudio-raop2/commit/69f3ce883dfb93eb7b24f98b9664e14071672475
 
  First I have to confess that this is the first time for me to deal with
  the unit 'dB', so maybe I'm doing totally stupid. I'd be very happy if I
  could have any suggestions from who is more experienced in this field.
 
  I started looking at pa_raop_client_set_volume() in
  src/modules/raop/raop_client.c. It was using pa_sw_volume_to_dB to
  calculate dB from a linear scale.
 
  Correction: pa_volume_t doesn't use a linear scale, it uses a cubic
  scale (see pa_sw_volume_from_linear() and pa_sw_volume_to_linear()).
 
  I see. I should have noticed some comments about cubic scale.
  http://cgit.freedesktop.org/pulseaudio/pulseaudio/tree/src/pulse/volume.c#n251
 
 
  Then I learned from code reading that pa_sw_volume_to_dB essentially
  calculates the following:
20 * log10((v/MAXVOLUME)^3) = 60 * log10(v/MAXVOLUME)
  This does not fit into the volume scale which RAOP is expecting, where
  -30.0 db is a kind of minimum [2].
 
  [2]: http://git.zx2c4.com/Airtunes2/about/#id29
 
  Also I looked at packet dumps from iPad and guessed how it calculated dB
  from a linear scale. It looked like iPad was using the following formula.
db = 10 * log10(volume/MAXVOLUME/30)
  So for the time being I decided to follow this way.
 
  The way to convert pa_volume_t to dB is to use pa_sw_volume_to_dB().
  Doing anything else means that the result is not dB, it's something
  different.
 
  The way to handle this is to ensure that the volume that is given to
  pa_raop_client_set_volume() is never outside the supported range. In
  module-raop-sink.c there's sink_set_volume_cb(), which calls
  pa_raop_client_set_volume(). In sink_set_volume_cb() there's this line:
 
  pa_cvolume_set(hw, s-sample_spec.channels, v);
 
  Before that line you should check what dB value v corresponds to, and if
  it's outside the supported range, then you should modify v to fall into
  the supported range. Any modification that you make to v will be
  compensated with software volume, so the modifications shouldn't affect
  the resulting volume at all, assuming that the RAOP device actually
  attenuates the signal by the dB amount that you send to it.
 
 
  According to your advice, I inserted an adjustment to v before
  pa_cvolume_set. Here's the patch.
  https://github.com/hfujita/pulseaudio-raop2/commit/c6337c0fef7710ee20b42ed3fb87ec12910ce35a
 
  Adjustment goes like this (pa_raop_client_adjust_volume()):
adj(v) = v * (1 - minv/maxv) + minv;
  where pa_sw_volume_to_dB(minv) = -30.0,
  and pa_sw_volume_to_dB(maxv) = 0.0
 
  The idea is that when the original v is 0, adj(0) = minv. And when the
  original v is maxv, adj(maxv) = maxv;
 
  Does this make sense?
  
  The idea was to simply adjust v to -30 dB if the original v is less than
  that. There's no need to do any complicated calculations.
 
 Do you mean something like
   v = max(minv, v); /* where minv corresponds to -30.0dB */ ?

Yes.

 If I do that, resulted volume will be almost muted in the range of 0% =
 v = 31%, then suddenly goes up beyond 31%. (31% is where dB becomes -30.0)
 I was afraid that this was not an intuitive behavior to users.

It sounds like the RAOP device doesn't apply the attenuation as it
should. Could you verify this? If you don't apply any software volume
(set s-soft_volume to PA_VOLUME_NORM), and you tell the RAOP device to
use volume -30.0, do you get very quiet (but not silent) audio? And if
you then tell the RAOP device to use volume -29.9, do you get much
louder audio? This shouldn't happen. A change of 0.1 dB should have very
small effect.

  As you noted, this also affects the software volume, and in my
  environment, the actual volume (volume heard from the speaker) may be
  way too small.
  
  What do you mean by way too small? The maximum volume will be the same
  as before, but the minimum volume will be quieter than before. With the
  original code you complained that you need to keep the volume at rather
  low levels, so extending the scale towards low volumes should help with
  this.
 
 Well, this could be just my personal feeling. Since it was a bit loud
 before (however it was almost the same volume level as iPad), this time
 I felt it was way too small.
 
 I wonder if it makes sense to 1) adjust v as
   adj(v) = v * (1 - minv/maxv) + minv;
 and 2) use the original v for pa_cvolume_set(), then 3) use adj(v

Re: [pulseaudio-discuss] [PATCH] sink: Increase max sink inputs per sink

2013-09-20 Thread Tanu Kaskinen
On Fri, 2013-09-20 at 09:29 +0200, David Henningsson wrote:
 On 09/20/2013 05:44 AM, Arun Raghavan wrote:
  We're hitting the 32 sink-input limit quite often with increasing use of
  PA by web browsers, so let's increase this limit.
 
 Does this increase the risk of us being the target of attacks; i e, if a
 web browser deliberately starts 255 streams, would we risk getting
 killed by using too much rtprio cpu time?

Even with the limit being at 32 it's possible to do a DoS attack by
creating streams with many channels and a high sample rate. As far as I
can see, raising the limit doesn't create any new threats.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 1/3] hashmap: Add a key+value iterator

2013-09-20 Thread Tanu Kaskinen
On Fri, 2013-09-20 at 17:27 +0530, Arun Raghavan wrote:
 ---
  src/pulsecore/hashmap.h | 4 
  1 file changed, 4 insertions(+)
 
 diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h
 index ae030ed..e42732a 100644
 --- a/src/pulsecore/hashmap.h
 +++ b/src/pulsecore/hashmap.h
 @@ -85,6 +85,10 @@ void* pa_hashmap_last(pa_hashmap *h);
  #define PA_HASHMAP_FOREACH(e, h, state) \
  for ((state) = NULL, (e) = pa_hashmap_iterate((h), (state), NULL); (e); 
 (e) = pa_hashmap_iterate((h), (state), NULL))
  
 +/* A macro to ease itration through all key, value pairs */
 +#define PA_HASHMAP_FOREACH_KV(k, e, h, state) \
 +for ((state) = NULL, (e) = pa_hashmap_iterate((h), (state), (const void 
 **) (k)); (e); (e) = pa_hashmap_iterate((h), (state), (const void **) (k)))

Are the (const void **) casts really needed?

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 1/3] hashmap: Add a key+value iterator

2013-09-20 Thread Tanu Kaskinen
On Fri, 2013-09-20 at 17:55 +0530, Arun Raghavan wrote:
 On Fri, 2013-09-20 at 15:13 +0300, Tanu Kaskinen wrote:
  On Fri, 2013-09-20 at 17:27 +0530, Arun Raghavan wrote:
   ---
src/pulsecore/hashmap.h | 4 
1 file changed, 4 insertions(+)
   
   diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h
   index ae030ed..e42732a 100644
   --- a/src/pulsecore/hashmap.h
   +++ b/src/pulsecore/hashmap.h
   @@ -85,6 +85,10 @@ void* pa_hashmap_last(pa_hashmap *h);
#define PA_HASHMAP_FOREACH(e, h, state) \
for ((state) = NULL, (e) = pa_hashmap_iterate((h), (state), NULL); 
   (e); (e) = pa_hashmap_iterate((h), (state), NULL))

   +/* A macro to ease itration through all key, value pairs */
   +#define PA_HASHMAP_FOREACH_KV(k, e, h, state) \
   +for ((state) = NULL, (e) = pa_hashmap_iterate((h), (state), (const 
   void **) (k)); (e); (e) = pa_hashmap_iterate((h), (state), (const void 
   **) (k)))
  
  Are the (const void **) casts really needed?
 
 Yes, the compiler complains about casts from (const type **) to (const
 void **).

Ok. Silly compiler.

I noticed that this casting is not done anywhere in the current code
base, but on closer look it turned out that in every case the original
type is const void ** anyway.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 2/3] device-port: Add mechanism to free implementation data

2013-09-20 Thread Tanu Kaskinen
On Fri, 2013-09-20 at 17:56 +0530, Arun Raghavan wrote:
 On Fri, 2013-09-20 at 15:21 +0300, Tanu Kaskinen wrote:
  On Fri, 2013-09-20 at 17:27 +0530, Arun Raghavan wrote:
   This will be needed if the implementation data stores pointers to
   additional data that needs to be freed as well.
   ---
src/pulsecore/device-port.c | 3 +++
src/pulsecore/device-port.h | 3 +++
2 files changed, 6 insertions(+)
   
   diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
   index 0b65d5c..ac2c95e 100644
   --- a/src/pulsecore/device-port.c
   +++ b/src/pulsecore/device-port.c
   @@ -94,6 +94,9 @@ static void device_port_free(pa_object *o) {
pa_assert(p);
pa_assert(pa_device_port_refcnt(p) == 0);

   +if (p-impl_free)
   +p-impl_free(p);
   +
if (p-proplist)
pa_proplist_free(p-proplist);

   diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h
   index b10d554..b5e80a5 100644
   --- a/src/pulsecore/device-port.h
   +++ b/src/pulsecore/device-port.h
   @@ -54,6 +54,9 @@ struct pa_device_port {
pa_direction_t direction;
int64_t latency_offset;

   +/* Free the extra implementation specific data. Called before other 
   members are freed. */
   +void (*impl_free)(pa_device_port *port);
   +
/* .. followed by some implementation specific data */
};

  
  It's sad that this is needed, but ack. (I have probably said this
  earlier: I'd like ports to not require refcounting, in which case they
  would probably be always owned by cards.)
 
 In which case the card would have to have a way to check what kind of
 implementation-specific data is there and call the appropriate free
 function. Doable, but not the prettiest, imo.

If you mean that pulsecore/card.c would know what kind of data the alsa
card is storing in the port, I don't see how that would be doable. But
that wasn't my idea anyway. If cards always owned the ports,
pa_device_port could have a userdata pointer set by the alsa card, and
the alsa card could free the extra port data at the same time when it
frees the pa_card object.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 08/41] bluetooth: Implement org.bluez.MediaEndpoint1.SetConfiguration()

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  src/modules/bluetooth/bluez5-util.c | 176 
 +++-
  src/modules/bluetooth/bluez5-util.h |   5 +
  2 files changed, 179 insertions(+), 2 deletions(-)
 
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index 983f707..b0d3864 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -33,6 +33,8 @@
  #include pulsecore/refcnt.h
  #include pulsecore/shared.h
  
 +#include a2dp-codecs.h
 +
  #include bluez5-util.h
  
  #define BLUEZ_SERVICE org.bluez
 @@ -406,12 +408,182 @@ fail:
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  }
  
 +const char *pa_bluetooth_profile_to_string(pa_bluetooth_profile_t profile) {
 +switch(profile) {
 +case PA_BLUETOOTH_PROFILE_A2DP_SINK:
 +return a2dp_sink;
 +case PA_BLUETOOTH_PROFILE_A2DP_SOURCE:
 +return a2dp_source;
 +case PA_BLUETOOTH_PROFILE_OFF:
 +return off;
 +}
 +
 +return NULL;
 +}
 +
  static DBusMessage *endpoint_set_configuration(DBusConnection *conn, 
 DBusMessage *m, void *userdata) {
 +pa_bluetooth_discovery *y = userdata;
 +pa_bluetooth_device *d;
 +pa_bluetooth_transport *t;
 +const char *sender, *path, *endpoint_path, *dev_path = NULL, *uuid = 
 NULL;
 +const uint8_t *config = NULL;
 +int size = 0;
 +pa_bluetooth_profile_t p = PA_BLUETOOTH_PROFILE_OFF;
 +DBusMessageIter args, props;
  DBusMessage *r;
  
 -pa_assert_se(r = dbus_message_new_error(m, 
 BLUEZ_MEDIA_ENDPOINT_INTERFACE .Error.NotImplemented,
 -Method not implemented));
 +if (!dbus_message_iter_init(m, args) || 
 !pa_streq(dbus_message_get_signature(m), oa{sv})) {
 +pa_log_error(Invalid signature for method SetConfiguration());
 +goto fail2;
 +}
 +
 +dbus_message_iter_get_basic(args, path);
 +
 +if (pa_hashmap_get(y-transports, path)) {
 +pa_log_error(Endpoint SetConfiguration(): Transport %s is already 
 configured., path);
 +goto fail2;
 +}
 +
 +pa_assert_se(dbus_message_iter_next(args));
 +
 +dbus_message_iter_recurse(args, props);
 +if (dbus_message_iter_get_arg_type(props) != DBUS_TYPE_DICT_ENTRY)
 +goto fail;
 +
 +/* Read transport properties */
 +while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
 +const char *key;
 +DBusMessageIter value, entry;
 +int var;
 +
 +dbus_message_iter_recurse(props, entry);
 +dbus_message_iter_get_basic(entry, key);
 +
 +dbus_message_iter_next(entry);
 +dbus_message_iter_recurse(entry, value);
 +
 +var = dbus_message_iter_get_arg_type(value);
 +
 +if (pa_streq(key, UUID)) {
 +if (var != DBUS_TYPE_STRING) {
 +pa_log_error(Property %s of wrong type %c, key, (char)var);
 +goto fail;
 +}
 +
 +dbus_message_iter_get_basic(value, uuid);
 +
 +endpoint_path = dbus_message_get_path(m);
 +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)) {
 +if (pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK))
 +p = PA_BLUETOOTH_PROFILE_A2DP_SOURCE;
 +}
 +
 +if (p == PA_BLUETOOTH_PROFILE_OFF) {
 +pa_log_error(UUID %s of transport %s incompatible with 
 endpoint %s, uuid, path, endpoint_path);
 +goto fail;
 +}
 +} else if (pa_streq(key, Device)) {
 +if (var != DBUS_TYPE_OBJECT_PATH) {
 +pa_log_error(Property %s of wrong type %c, key, (char)var);
 +goto fail;
 +}
 +
 +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);
 +goto fail;
 +}
 +
 +dbus_message_iter_recurse(value, array);
 +var = dbus_message_iter_get_arg_type(array);
 +if (var != DBUS_TYPE_BYTE) {
 +pa_log_error(%s is an array of wrong type %c, key, 
 (char)var);
 +goto fail;
 +}
 +
 +dbus_message_iter_get_fixed_array(array, config, size);
 +if (size != sizeof(a2dp_sbc_t)) {
 +pa_log_error(Properties array of invalid size);

Properties array is not very accurate choice of words. Configuration
array or Configuration blob would be better.

 +

Re: [pulseaudio-discuss] [PATCH v4 09/41] bluetooth: Implement org.bluez.MediaEndpoint1.SelectConfiguration()

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
  static DBusMessage *endpoint_select_configuration(DBusConnection *conn, 
 DBusMessage *m, void *userdata) {
 +pa_bluetooth_discovery *y = userdata;
 +a2dp_sbc_t *cap, config;
 +uint8_t *pconf = (uint8_t *) config;
 +int i, size;
  DBusMessage *r;
 +DBusError err;
  
 -pa_assert_se(r = dbus_message_new_error(m, 
 BLUEZ_MEDIA_ENDPOINT_INTERFACE .Error.NotImplemented,
 -Method not implemented));
 +static const struct {
 +uint32_t rate;
 +uint8_t cap;
 +} freq_table[] = {
 +{ 16000U, SBC_SAMPLING_FREQ_16000 },
 +{ 32000U, SBC_SAMPLING_FREQ_32000 },
 +{ 44100U, SBC_SAMPLING_FREQ_44100 },
 +{ 48000U, SBC_SAMPLING_FREQ_48000 }
 +};
 +
 +dbus_error_init(err);
 +
 +if (!dbus_message_get_args(m, err, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
 cap, size, DBUS_TYPE_INVALID)) {
 +pa_log_error(Endpoint SelectConfiguration(): %s, err.message);
 +dbus_error_free(err);
 +goto fail;
 +}
 +
 +if (size != sizeof(config)) {
 +pa_log_error(Capabilities array has invalid size);
 +goto fail;
 +}
 +
 +pa_zero(config);
 +
 +/* Find the lowest freq that is at least as high as the requested 
 sampling rate */
 +for (i = 0; (unsigned) i  PA_ELEMENTSOF(freq_table); i++)
 +if (freq_table[i].rate = y-core-default_sample_spec.rate  
 (cap-frequency  freq_table[i].cap)) {
 +config.frequency = freq_table[i].cap;
 +break;
 +}
  
 +if ((unsigned) i == PA_ELEMENTSOF(freq_table)) {
 +for (--i; i = 0; i--) {
 +if (cap-frequency  freq_table[i].cap) {
 +config.frequency = freq_table[i].cap;
 +break;
 +}
 +}
 +
 +if (i  0) {
 +pa_log_error(Not suitable sample rate);
 +goto fail;
 +}
 +}
 +
 +pa_assert((unsigned) i  PA_ELEMENTSOF(freq_table));
 +
 +if (y-core-default_sample_spec.channels = 1)
 +if (cap-channel_mode  SBC_CHANNEL_MODE_MONO)
 +config.channel_mode = SBC_CHANNEL_MODE_MONO;

You forgot to fix this code. The problem still exists that if
default_sample_spec.channels is 1 and the cap-channel_mode doesn't
contain SBC_CHANNEL_MODE_MONO, then config.channel_mode is left
uninitialized.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 13/41] bluetooth: Handle InterfacesAdded and InterfacesRemoved

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 This code is based on previous work by Mikel Astiz.
 ---
  src/modules/bluetooth/bluez5-util.c | 55 
 +
  1 file changed, 55 insertions(+)
 
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index f5d4300..bf4a046 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -38,6 +38,7 @@
  #include bluez5-util.h
  
  #define BLUEZ_SERVICE org.bluez
 +#define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE .Device1
  #define BLUEZ_MEDIA_ENDPOINT_INTERFACE BLUEZ_SERVICE .MediaEndpoint1
  #define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE .MediaTransport1
  
 @@ -476,6 +477,53 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, 
 DBusMessage *m, void *us
  }
  
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 +} else if (dbus_message_is_signal(m, 
 org.freedesktop.DBus.ObjectManager, InterfacesAdded)) {
 +DBusMessageIter arg_i;
 +
 +if (!y-objects_listed)
 +return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; /* No reply received 
 yet from GetManagedObjects */
 +
 +if (!dbus_message_iter_init(m, arg_i) || 
 !pa_streq(dbus_message_get_signature(m), oa{sa{sv}})) {
 +pa_log_error(Invalid signature found in InterfacesAdded);
 +goto fail;
 +}
 +
 +/* TODO: parse interfaces and properties */
 +
 +return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 +} else if (dbus_message_is_signal(m, 
 org.freedesktop.DBus.ObjectManager, InterfacesRemoved)) {
 +const char *p;
 +DBusMessageIter arg_i;
 +DBusMessageIter element_i;
 +
 +if (!y-objects_listed)
 +return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; /* No reply received 
 yet from GetManagedObjects */
 +
 +if (!dbus_message_iter_init(m, arg_i) || 
 !pa_streq(dbus_message_get_signature(m), oas)) {
 +pa_log_error(Invalid signature found in InterfacesRemoved);
 +goto fail;
 +}
 +
 +dbus_message_iter_get_basic(arg_i, p);
 +
 +pa_assert_se(dbus_message_iter_next(arg_i));
 +pa_assert(dbus_message_iter_get_arg_type(arg_i) == DBUS_TYPE_ARRAY);
 +
 +dbus_message_iter_recurse(arg_i, element_i);
 +
 +while (dbus_message_iter_get_arg_type(element_i) == 
 DBUS_TYPE_STRING) {
 +const char *iface;
 +
 +dbus_message_iter_get_basic(element_i, iface);
 +
 +if (pa_streq(iface, BLUEZ_DEVICE_INTERFACE))
 +device_remove(y, p);
 +
 +dbus_message_iter_next(element_i);
 +}

This code handles only device removal, but I suppose adapter removal
should be handled too?

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 14/41] bluetooth: Parse BlueZ 5 D-Bus interfaces

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 Parse the arguments of the InterfacesAdded signal and the
 GetManagedObjects() reply.
 
 This code is based on previous work by Mikel Astiz.
 ---
  src/modules/bluetooth/bluez5-util.c | 72 
 +++--
  1 file changed, 70 insertions(+), 2 deletions(-)
 
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index bf4a046..7f0a7ec 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -38,6 +38,7 @@
  #include bluez5-util.h
  
  #define BLUEZ_SERVICE org.bluez
 +#define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE .Adapter1
  #define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE .Device1
  #define BLUEZ_MEDIA_ENDPOINT_INTERFACE BLUEZ_SERVICE .MediaEndpoint1
  #define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE .MediaTransport1
 @@ -379,6 +380,73 @@ static void adapter_remove_all(pa_bluetooth_discovery 
 *y) {
  }
  }
  
 +static void parse_interfaces_and_properties(pa_bluetooth_discovery *y, 
 DBusMessageIter *dict_i) {
 +DBusMessageIter element_i;
 +const char *path;
 +
 +pa_assert(dbus_message_iter_get_arg_type(dict_i) == 
 DBUS_TYPE_OBJECT_PATH);
 +dbus_message_iter_get_basic(dict_i, path);
 +
 +pa_assert_se(dbus_message_iter_next(dict_i));
 +pa_assert(dbus_message_iter_get_arg_type(dict_i) == DBUS_TYPE_ARRAY);
 +
 +dbus_message_iter_recurse(dict_i, element_i);
 +
 +while (dbus_message_iter_get_arg_type(element_i) == 
 DBUS_TYPE_DICT_ENTRY) {
 +DBusMessageIter iface_i;
 +const char *interface;
 +
 +dbus_message_iter_recurse(element_i, iface_i);
 +
 +pa_assert(dbus_message_iter_get_arg_type(iface_i) == 
 DBUS_TYPE_STRING);
 +dbus_message_iter_get_basic(iface_i, interface);
 +
 +pa_assert_se(dbus_message_iter_next(iface_i));
 +pa_assert(dbus_message_iter_get_arg_type(iface_i) == 
 DBUS_TYPE_ARRAY);
 +
 +if (pa_streq(interface, BLUEZ_ADAPTER_INTERFACE)) {
 +pa_bluetooth_adapter *a;
 +
 +if ((a = pa_hashmap_get(y-adapters, path))) {
 +pa_log_error(Found duplicated D-Bus path for device %s, 
 path);
 +return;
 +} else
 +a = adapter_create(y, path);
 +
 +pa_log_debug(Adapter %s found, path);
 +
 +/* TODO: parse adapter properties and register endpoints */
 +
 +} else if (pa_streq(interface, BLUEZ_DEVICE_INTERFACE)) {
 +pa_bluetooth_device *d;
 +
 +if ((d = pa_hashmap_get(y-devices, path))) {
 +if (d-device_info_valid == 1) {
 +pa_log_error(Found duplicated D-Bus path for device 
 %s, path);
 +return;
 +}
 +
 +if (d-device_info_valid == -1) {
 +pa_log_notice(Device %s was known before but had 
 invalid information, reseting, path);
 +d-device_info_valid = 0;

Didn't we agree that the device shouldn't be reset? If the device is
reset, the device properties should be reset too, otherwise the old
property values can leak to the new initialization. But as discussed
last round, resetting the property values is error prone, so if the
device initialization fails once, then the device should stay
uninitialized forever. We don't need to resurrect failed devices.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 15/41] bluetooth: Parse BlueZ 5 adapter properties

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
  static void parse_interfaces_and_properties(pa_bluetooth_discovery *y, 
 DBusMessageIter *dict_i) {
  DBusMessageIter element_i;
  const char *path;
 @@ -415,7 +474,8 @@ static void 
 parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa
  
  pa_log_debug(Adapter %s found, path);
  
 -/* TODO: parse adapter properties and register endpoints */
 +parse_adapter_properties(a, iface_i, false);

If parsing fails, or if the Address property is missing, the adapter
should be marked as invalid.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 16/41] bluetooth: Register endpoints with BlueZ 5 adapter

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  src/modules/bluetooth/bluez5-util.c | 82 
 -
  1 file changed, 81 insertions(+), 1 deletion(-)
 
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index 4bc5967..03c73c9 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -40,9 +40,12 @@
  #define BLUEZ_SERVICE org.bluez
  #define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE .Adapter1
  #define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE .Device1
 +#define BLUEZ_MEDIA_INTERFACE BLUEZ_SERVICE .Media1
  #define BLUEZ_MEDIA_ENDPOINT_INTERFACE BLUEZ_SERVICE .MediaEndpoint1
  #define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE .MediaTransport1
  
 +#define BLUEZ_ERROR_NOT_SUPPORTED org.bluez.Error.NotSupported
 +
  #define A2DP_SOURCE_ENDPOINT /MediaEndpoint/A2DPSource
  #define A2DP_SINK_ENDPOINT /MediaEndpoint/A2DPSink
  
 @@ -439,6 +442,81 @@ static int parse_adapter_properties(pa_bluetooth_adapter 
 *a, DBusMessageIter *i,
  return 0;
  }
  
 +static void register_endpoint_reply(DBusPendingCall *pending, void 
 *userdata) {
 +DBusMessage *r;
 +pa_dbus_pending *p;
 +pa_bluetooth_discovery *y;
 +char *endpoint;
 +
 +pa_assert(pending);
 +pa_assert_se(p = userdata);
 +pa_assert_se(y = p-context_data);
 +pa_assert_se(endpoint = p-call_data);
 +pa_assert_se(r = dbus_pending_call_steal_reply(pending));
 +
 +if (dbus_message_is_error(r, DBUS_ERROR_SERVICE_UNKNOWN)) {
 +pa_log_debug(Bluetooth daemon is apparently not available);
 +device_remove_all(y);

Adapters should be removed too. I think there should be a function that
takes care of clearing everything, so that it's not necessary to
remember to remove both devices and adapters everywhere where we notice
that bluetoothd is non-functional.

 +goto finish;
 +}
 +
 +if (dbus_message_is_error(r, BLUEZ_ERROR_NOT_SUPPORTED)) {
 +pa_log_info(Couldn't register endpoint %s because it is disabled in 
 BlueZ, endpoint);
 +goto finish;
 +}
 +
 +if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
 +pa_log_error(org.bluez.Media.RegisterEndpoint() failed: %s: %s, 
 dbus_message_get_error_name(r),
 + pa_dbus_get_error_message(r));

The log message uses wrong interface name (Media instead of Media1).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 15/41] bluetooth: Parse BlueZ 5 adapter properties

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 +static int parse_adapter_properties(pa_bluetooth_adapter *a, DBusMessageIter 
 *i, bool is_property_change) {
 +DBusMessageIter element_i;
 +
 +pa_assert(a);
 +
 +dbus_message_iter_recurse(i, element_i);
 +
 +while (dbus_message_iter_get_arg_type(element_i) == 
 DBUS_TYPE_DICT_ENTRY) {
 +DBusMessageIter dict_i, variant_i;
 +const char *key;
 +
 +dbus_message_iter_recurse(element_i, dict_i);
 +
 +key = check_variant_property(dict_i);
 +if (key == NULL) {
 +pa_log_error(Received invalid property for adapter %s, 
 a-path);
 +return -1;
 +}
 +
 +dbus_message_iter_recurse(dict_i, variant_i);
 +
 +if (dbus_message_iter_get_arg_type(variant_i) == DBUS_TYPE_STRING 
  pa_streq(key, Address)) {
 +char *value;
 +
 +dbus_message_iter_get_basic(variant_i, value);
 +a-address = pa_xstrdup(value);
 +}

Can the Address property change? If not, it should be checked if
is_property_change is true, and if it is, then complain loudly. If it
can change, then the old address should be freed before assigning the
new address.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 14/41] bluetooth: Parse BlueZ 5 D-Bus interfaces

2013-09-21 Thread Tanu Kaskinen
On Sat, 2013-09-21 at 14:02 +0300, Tanu Kaskinen wrote:
 On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
  From: João Paulo Rechi Vita jprv...@openbossa.org
  
  Parse the arguments of the InterfacesAdded signal and the
  GetManagedObjects() reply.
  
  This code is based on previous work by Mikel Astiz.
  ---
   src/modules/bluetooth/bluez5-util.c | 72 
  +++--
   1 file changed, 70 insertions(+), 2 deletions(-)
  
  diff --git a/src/modules/bluetooth/bluez5-util.c 
  b/src/modules/bluetooth/bluez5-util.c
  index bf4a046..7f0a7ec 100644
  --- a/src/modules/bluetooth/bluez5-util.c
  +++ b/src/modules/bluetooth/bluez5-util.c
  @@ -38,6 +38,7 @@
   #include bluez5-util.h
   
   #define BLUEZ_SERVICE org.bluez
  +#define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE .Adapter1
   #define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE .Device1
   #define BLUEZ_MEDIA_ENDPOINT_INTERFACE BLUEZ_SERVICE .MediaEndpoint1
   #define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE .MediaTransport1
  @@ -379,6 +380,73 @@ static void adapter_remove_all(pa_bluetooth_discovery 
  *y) {
   }
   }
   
  +static void parse_interfaces_and_properties(pa_bluetooth_discovery *y, 
  DBusMessageIter *dict_i) {
  +DBusMessageIter element_i;
  +const char *path;
  +
  +pa_assert(dbus_message_iter_get_arg_type(dict_i) == 
  DBUS_TYPE_OBJECT_PATH);
  +dbus_message_iter_get_basic(dict_i, path);
  +
  +pa_assert_se(dbus_message_iter_next(dict_i));
  +pa_assert(dbus_message_iter_get_arg_type(dict_i) == DBUS_TYPE_ARRAY);
  +
  +dbus_message_iter_recurse(dict_i, element_i);
  +
  +while (dbus_message_iter_get_arg_type(element_i) == 
  DBUS_TYPE_DICT_ENTRY) {
  +DBusMessageIter iface_i;
  +const char *interface;
  +
  +dbus_message_iter_recurse(element_i, iface_i);
  +
  +pa_assert(dbus_message_iter_get_arg_type(iface_i) == 
  DBUS_TYPE_STRING);
  +dbus_message_iter_get_basic(iface_i, interface);
  +
  +pa_assert_se(dbus_message_iter_next(iface_i));
  +pa_assert(dbus_message_iter_get_arg_type(iface_i) == 
  DBUS_TYPE_ARRAY);
  +
  +if (pa_streq(interface, BLUEZ_ADAPTER_INTERFACE)) {
  +pa_bluetooth_adapter *a;
  +
  +if ((a = pa_hashmap_get(y-adapters, path))) {
  +pa_log_error(Found duplicated D-Bus path for device %s, 
  path);
  +return;
  +} else
  +a = adapter_create(y, path);
  +
  +pa_log_debug(Adapter %s found, path);
  +
  +/* TODO: parse adapter properties and register endpoints */
  +
  +} else if (pa_streq(interface, BLUEZ_DEVICE_INTERFACE)) {
  +pa_bluetooth_device *d;
  +
  +if ((d = pa_hashmap_get(y-devices, path))) {
  +if (d-device_info_valid == 1) {
  +pa_log_error(Found duplicated D-Bus path for device 
  %s, path);
  +return;
  +}
  +
  +if (d-device_info_valid == -1) {
  +pa_log_notice(Device %s was known before but had 
  invalid information, reseting, path);
  +d-device_info_valid = 0;
 
 Didn't we agree that the device shouldn't be reset? If the device is
 reset, the device properties should be reset too, otherwise the old
 property values can leak to the new initialization. But as discussed
 last round, resetting the property values is error prone, so if the
 device initialization fails once, then the device should stay
 uninitialized forever. We don't need to resurrect failed devices.

Never mind, I see you fixed this in a later patch (it would have been
good to fix it already in this patch, but no big deal).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 18/41] bluetooth: Parse BlueZ 5 device properties

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 This code is based on previous work by Mikel Astiz.
 ---
  src/modules/bluetooth/bluez5-util.c | 164 
 ++--
  src/modules/bluetooth/bluez5-util.h |   6 ++
  2 files changed, 161 insertions(+), 9 deletions(-)
 
 diff --git a/src/modules/bluetooth/bluez5-util.c 
 b/src/modules/bluetooth/bluez5-util.c
 index 7fc7d50..49d5c38 100644
 --- a/src/modules/bluetooth/bluez5-util.c
 +++ b/src/modules/bluetooth/bluez5-util.c
 @@ -297,6 +297,7 @@ static pa_bluetooth_device* 
 device_create(pa_bluetooth_discovery *y, const char
  d = pa_xnew0(pa_bluetooth_device, 1);
  d-discovery = y;
  d-path = pa_xstrdup(path);
 +d-uuids = pa_hashmap_new(pa_idxset_string_hash_func, 
 pa_idxset_string_compare_func);
  
  pa_hashmap_put(y-devices, d-path, d);
  
 @@ -348,6 +349,9 @@ static void device_free(pa_bluetooth_device *d) {
  pa_bluetooth_transport_free(t);
  }
  
 +if (d-uuids)
 +pa_hashmap_free(d-uuids, NULL);

The hashmap is not necessarily empty, so this leaks the contained uuid
strings.

The hashmap interface changed recently, and now the correct way to deal
with this is to call pa_hashmap_new_full(), and provide a free callback
for the value (since the key is the same object as the value, don't
provide free callbacks for both the value and the key, otherwise there
will be double freeing).

 +
  d-discovery = NULL;
  d-adapter = NULL;
  pa_xfree(d-path);
 @@ -408,6 +412,144 @@ static void adapter_remove_all(pa_bluetooth_discovery 
 *y) {
  }
  }
  
 +static void parse_device_property(pa_bluetooth_device *d, DBusMessageIter 
 *i, bool is_property_change) {
 +const char *key;
 +DBusMessageIter variant_i;
 +
 +pa_assert(d);
 +
 +key = check_variant_property(i);
 +if (key == NULL) {
 +pa_log_error(Received invalid property for device %s, d-path);
 +return;
 +}
 +
 +dbus_message_iter_recurse(i, variant_i);
 +
 +switch (dbus_message_iter_get_arg_type(variant_i)) {
 +
 +case DBUS_TYPE_STRING: {
 +const char *value;
 +dbus_message_iter_get_basic(variant_i, value);
 +
 +if (pa_streq(key, Alias)) {
 +pa_xfree(d-alias);
 +d-alias = pa_xstrdup(value);
 +pa_log_debug(%s: %s, key, value);
 +} else if (pa_streq(key, Address)) {
 +if (is_property_change) {
 +pa_log_warn(Device property 'Address' expected to be 
 constant but changed for %s, ignoring, d-path);
 +return;
 +}
 +
 +if (d-address) {
 +pa_log_warn(Device %s: Received a duplicate 'Address' 
 property, ignoring, d-path);
 +return;
 +}
 +
 +d-address = pa_xstrdup(value);
 +pa_log_debug(%s: %s, key, value);
 +}
 +
 +break;
 +}
 +
 +case DBUS_TYPE_OBJECT_PATH: {
 +const char *value;
 +dbus_message_iter_get_basic(variant_i, value);
 +
 +if (pa_streq(key, Adapter)) {
 +
 +if (is_property_change) {
 +pa_log_warn(Device property 'Adapter' expected to be 
 constant but changed for %s, ignoring, d-path);
 +return;
 +}
 +
 +if (d-adapter) {
 +pa_log_warn(Device %s: Received a duplicate 'Adapter' 
 property, ignoring, d-path);
 +return;
 +}
 +
 +d-adapter = pa_hashmap_get(d-discovery-adapters, value);
 +if (!d-adapter) {
 +pa_log_warn(Device %s: 'Adapter' property references an 
 unknown adapter %s., d-path, value);

This is normal behaviour, no need to log anything, especially not at the
warning level.

 +d-_adapter_path = pa_xstrdup(value);
 +break;

Does it really make sense to break here? The only thing this skips is
the line that logs the property key and value, and I don't see any
reason to skip that.

 +}
 +
 +pa_log_debug(%s: %s, key, value);
 +}
 +
 +break;
 +}
 +
 +case DBUS_TYPE_UINT32: {
 +uint32_t value;
 +dbus_message_iter_get_basic(variant_i, value);
 +
 +if (pa_streq(key, Class)) {
 +d-class_of_device = value;
 +pa_log_debug(%s: %d, key, value);
 +}
 +
 +break;
 +}
 +
 +case DBUS_TYPE_ARRAY: {
 +DBusMessageIter ai;
 +dbus_message_iter_recurse(variant_i, ai);
 +
 +if (dbus_message_iter_get_arg_type(ai) == DBUS_TYPE_STRING  
 pa_streq(key, UUIDs)) {
 +/* bluetoothd never removes UUIDs from a device object so 
 there
 + 

Re: [pulseaudio-discuss] [PATCH v4 34/41] bluetooth: Process sink messages for BlueZ 5 cards

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  src/modules/bluetooth/module-bluez5-device.c | 75 
 
  1 file changed, 75 insertions(+)
 
 diff --git a/src/modules/bluetooth/module-bluez5-device.c 
 b/src/modules/bluetooth/module-bluez5-device.c
 index 4f2fbd8..31088b7 100644
 --- a/src/modules/bluetooth/module-bluez5-device.c
 +++ b/src/modules/bluetooth/module-bluez5-device.c
 @@ -700,6 +700,80 @@ static int add_source(struct userdata *u) {
  return 0;
  }
  
 +/* Run from IO thread */
 +static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t 
 offset, pa_memchunk *chunk) {
 +struct userdata *u = PA_SINK(o)-userdata;
 +bool failed = false;
 +int r;
 +
 +pa_assert(u-sink == PA_SINK(o));
 +pa_assert(u-transport);
 +
 +switch (code) {
 +
 +case PA_SINK_MESSAGE_SET_STATE:
 +
 +switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
 +
 +case PA_SINK_SUSPENDED:
 +/* Ignore if transition is 
 PA_SINK_INIT-PA_SINK_SUSPENDED */
 +if (!PA_SINK_IS_OPENED(u-sink-thread_info.state))
 +break;
 +
 +/* Stop the device if the source is suspended as well */
 +if (!u-source || u-source-state == 
 PA_SOURCE_SUSPENDED)
 +/* We deliberately ignore whether stopping
 + * actually worked. Since the stream_fd is
 + * closed it doesn't really matter */
 +transport_release(u);
 +
 +break;
 +
 +case PA_SINK_IDLE:
 +case PA_SINK_RUNNING:
 +if (u-sink-thread_info.state != PA_SINK_SUSPENDED)
 +break;
 +
 +/* Resume the device if the source was suspended as well 
 */
 +if (!u-source || 
 !PA_SOURCE_IS_OPENED(u-source-thread_info.state)) {
 +if (transport_acquire(u, false)  0)
 +failed = true;
 +else
 +setup_stream(u);
 +}
 +
 +break;
 +
 +case PA_SINK_UNLINKED:
 +case PA_SINK_INIT:
 +case PA_SINK_INVALID_STATE:
 +break;
 +}
 +
 +break;
 +
 +case PA_SINK_MESSAGE_GET_LATENCY: {
 +pa_usec_t wi, ri;
 +
 +if (u-read_smoother) {
 +ri = pa_smoother_get(u-read_smoother, pa_rtclock_now());
 +wi = pa_bytes_to_usec(u-write_index + u-write_block_size, 
 u-sample_spec);
 +} else {
 +ri = pa_rtclock_now() - u-started_at;
 +wi = pa_bytes_to_usec(u-write_index, u-sample_spec);
 +}
 +
 +*((pa_usec_t*) data) = FIXED_LATENCY_PLAYBACK_A2DP + wi - ri  0 
 ? FIXED_LATENCY_PLAYBACK_A2DP + wi - ri : 0;

The compiler treats the result of FIXED_LATENCY_PLAYBACK_A2DP + wi -
ri as an unsigned integer, so it's never negative, and thus the
comparison to 0 doesn't work as intended.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 35/41] bluetooth: Process source messages for BlueZ 5 cards

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  src/modules/bluetooth/module-bluez5-device.c | 77 
 
  1 file changed, 77 insertions(+)
 
 diff --git a/src/modules/bluetooth/module-bluez5-device.c 
 b/src/modules/bluetooth/module-bluez5-device.c
 index 31088b7..d9e1fc6 100644
 --- a/src/modules/bluetooth/module-bluez5-device.c
 +++ b/src/modules/bluetooth/module-bluez5-device.c
 @@ -660,6 +660,82 @@ static void setup_stream(struct userdata *u) {
  u-read_smoother = pa_smoother_new(PA_USEC_PER_SEC, 
 2*PA_USEC_PER_SEC, true, true, 10, pa_rtclock_now(), true);
  }
  
 +/* Run from IO thread */
 +static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t 
 offset, pa_memchunk *chunk) {
 +struct userdata *u = PA_SOURCE(o)-userdata;
 +bool failed = false;
 +int r;
 +
 +pa_assert(u-source == PA_SOURCE(o));
 +pa_assert(u-transport);
 +
 +switch (code) {
 +
 +case PA_SOURCE_MESSAGE_SET_STATE:
 +
 +switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
 +
 +case PA_SOURCE_SUSPENDED:
 +/* Ignore if transition is 
 PA_SOURCE_INIT-PA_SOURCE_SUSPENDED */
 +if (!PA_SOURCE_IS_OPENED(u-source-thread_info.state))
 +break;
 +
 +/* Stop the device if the sink is suspended as well */
 +if (!u-sink || u-sink-state == PA_SINK_SUSPENDED)
 +transport_release(u);
 +
 +if (u-read_smoother)
 +pa_smoother_pause(u-read_smoother, 
 pa_rtclock_now());
 +
 +break;
 +
 +case PA_SOURCE_IDLE:
 +case PA_SOURCE_RUNNING:
 +if (u-source-thread_info.state != PA_SOURCE_SUSPENDED)
 +break;
 +
 +/* Resume the device if the sink was suspended as well */
 +if (!u-sink || 
 !PA_SINK_IS_OPENED(u-sink-thread_info.state)) {
 +if (transport_acquire(u, false)  0)
 +failed = true;
 +else
 +setup_stream(u);
 +}
 +
 +/* We don't resume the smoother here. Instead we
 + * wait until the first packet arrives */
 +
 +break;
 +
 +case PA_SOURCE_UNLINKED:
 +case PA_SOURCE_INIT:
 +case PA_SOURCE_INVALID_STATE:
 +break;
 +}
 +
 +break;
 +
 +case PA_SOURCE_MESSAGE_GET_LATENCY: {
 +pa_usec_t wi, ri;
 +
 +if (u-read_smoother) {
 +wi = pa_smoother_get(u-read_smoother, pa_rtclock_now());
 +ri = pa_bytes_to_usec(u-read_index, u-sample_spec);
 +
 +*((pa_usec_t*) data) = FIXED_LATENCY_PLAYBACK_A2DP + wi - ri 
  0 ? FIXED_LATENCY_PLAYBACK_A2DP + wi - ri : 0;

The same complaint as with the sink: the comparison to 0 doesn't work.
Also, the constant should be FIXED_LATENCY_RECORD_A2DP, not
FIXED_LATENCY_PLAYBACK_A2DP.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 36/41] bluetooth: Handle changes to BlueZ 5 transports state

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 ---
  src/modules/bluetooth/module-bluez5-device.c | 78 
 
  1 file changed, 78 insertions(+)
 
 diff --git a/src/modules/bluetooth/module-bluez5-device.c 
 b/src/modules/bluetooth/module-bluez5-device.c
 index d9e1fc6..2eaeb77 100644
 --- a/src/modules/bluetooth/module-bluez5-device.c
 +++ b/src/modules/bluetooth/module-bluez5-device.c
 @@ -97,6 +97,7 @@ struct userdata {
  pa_core *core;
  
  pa_hook_slot *device_connection_changed_slot;
 +pa_hook_slot *transport_state_changed_slot;
  
  pa_bluetooth_discovery *discovery;
  pa_bluetooth_device *device;
 @@ -1670,6 +1671,62 @@ static int add_card(struct userdata *u) {
  }
  
  /* Run from main thread */
 +static void handle_transport_state_change(struct userdata *u, struct 
 pa_bluetooth_transport *t) {
 +bool acquire = false;
 +bool release = false;
 +pa_card_profile *cp;
 +pa_device_port *port;
 +
 +pa_assert(u);
 +pa_assert(t);
 +
 +/* Update profile availability */
 +if (!(cp = pa_hashmap_get(u-card-profiles, 
 pa_bluetooth_profile_to_string(t-profile
 +return;
 +pa_card_profile_set_available(cp, 
 transport_state_to_availability(t-state));
 +
 +/* Update port availability */
 +pa_assert_se(port = pa_hashmap_get(u-card-ports, u-output_port_name));
 +pa_device_port_set_available(port, get_port_availability(u, 
 PA_DIRECTION_OUTPUT));
 +pa_assert_se(port = pa_hashmap_get(u-card-ports, u-input_port_name));
 +pa_device_port_set_available(port, get_port_availability(u, 
 PA_DIRECTION_INPUT));
 +
 +/* Acquire or release transport as needed */
 +acquire = (t-state == PA_BLUETOOTH_TRANSPORT_STATE_PLAYING  
 u-profile == t-profile);
 +release = (t-state != PA_BLUETOOTH_TRANSPORT_STATE_PLAYING  
 u-profile == t-profile);
 +
 +if (acquire  transport_acquire(u, true) = 0) {
 +if (u-source) {
 +pa_log_debug(Resuming source %s because its transport state 
 changed to playing, u-source-name);
 +pa_source_suspend(u-source, false, 
 PA_SUSPEND_IDLE|PA_SUSPEND_USER);

This is now the third time I ask you to add the following comment:

/* We remove the IDLE suspend cause, because otherwise module-loopback
doesn't uncork its streams. FIXME: Messing with the IDLE suspend cause
here is wrong, the correct way to handle this would probably be to
uncork the loopback streams not only when the other end is unsuspended,
but also when the other end's suspend cause changes to IDLE only
(currently there's no notification mechanism for suspend cause changes,
though). */

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 38/41] bluetooth: Fail to load driver is discovery module is not loaded

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 For quite some time now the device driver module doesn't work well
 without the discovery module, so for the BlueZ 5 support we'll prevent
 the device driver module to be loaded if the discovery module is not
 loaded.

No reaction to my previous feedback:
http://thread.gmane.org/gmane.comp.audio.pulseaudio.general/17959/focus=18071

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 39/41] module: Create pa_module_exists()

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 This new function checks if a certain module name is available in the
 system.
 ---
  src/pulsecore/module.c | 49 +
  src/pulsecore/module.h |  2 ++
  2 files changed, 51 insertions(+)
 
 diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
 index 16582b3..bc53f07 100644
 --- a/src/pulsecore/module.c
 +++ b/src/pulsecore/module.c
 @@ -28,6 +28,7 @@
  #include stdlib.h
  #include string.h
  #include errno.h
 +#include ltdl.h
  
  #include pulse/xmalloc.h
  #include pulse/proplist.h
 @@ -47,6 +48,54 @@
  #define PA_SYMBOL_GET_N_USED pa__get_n_used
  #define PA_SYMBOL_GET_DEPRECATE pa__get_deprecated
  
 +bool pa_module_exists(const char *name) {
 +const char *paths, *state = NULL;
 +char *p, *pathname;
 +bool result;
 +
 +pa_assert(name);
 +
 +if (name[0] == PA_PATH_SEP_CHAR) {
 +result = access(name, F_OK) == 0 ? true : false;
 +pa_log_debug(Checking for existence of '%s': %s, name, result ? 
 success : failure);
 +if (result)
 +return true;
 +}
 +
 +if (!(paths = lt_dlgetsearchpath()))
 +return false;
 +
 +/* strip .so from the end of name, if present */
 +p = rindex(name, '.');
 +if (p  pa_streq(p, .so))

Use PA_SOEXT instead of hardcoding .so.

 +p[0] = 0;
 +
 +while ((p = pa_split(paths, :, state))) {
 +pathname = pa_sprintf_malloc(%s PA_PATH_SEP %s.so, p, name);

Use PA_SOEXT also here...

 +result = access(pathname, F_OK) == 0 ? true : false;
 +pa_log_debug(Checking for existence of '%s': %s, pathname, result 
 ? success : failure);
 +pa_xfree(pathname);
 +pa_xfree(p);
 +if (result)
 +return true;
 +}
 +
 +state = NULL;
 +if (PA_UNLIKELY(pa_run_from_build_tree())) {
 +while ((p = pa_split(paths, :, state))) {
 +pathname = pa_sprintf_malloc(%s PA_PATH_SEP .libs 
 PA_PATH_SEP %s.so, p, name);

...and here.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 39/41] module: Create pa_module_exists()

2013-09-21 Thread Tanu Kaskinen
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 From: João Paulo Rechi Vita jprv...@openbossa.org
 
 This new function checks if a certain module name is available in the
 system.
 ---
  src/pulsecore/module.c | 49 +
  src/pulsecore/module.h |  2 ++
  2 files changed, 51 insertions(+)
 
 diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
 index 16582b3..bc53f07 100644
 --- a/src/pulsecore/module.c
 +++ b/src/pulsecore/module.c
 @@ -28,6 +28,7 @@
  #include stdlib.h
  #include string.h
  #include errno.h
 +#include ltdl.h
  
  #include pulse/xmalloc.h
  #include pulse/proplist.h
 @@ -47,6 +48,54 @@
  #define PA_SYMBOL_GET_N_USED pa__get_n_used
  #define PA_SYMBOL_GET_DEPRECATE pa__get_deprecated
  
 +bool pa_module_exists(const char *name) {
 +const char *paths, *state = NULL;
 +char *p, *pathname;
 +bool result;
 +
 +pa_assert(name);
 +
 +if (name[0] == PA_PATH_SEP_CHAR) {
 +result = access(name, F_OK) == 0 ? true : false;
 +pa_log_debug(Checking for existence of '%s': %s, name, result ? 
 success : failure);
 +if (result)
 +return true;
 +}
 +
 +if (!(paths = lt_dlgetsearchpath()))
 +return false;
 +
 +/* strip .so from the end of name, if present */
 +p = rindex(name, '.');
 +if (p  pa_streq(p, .so))
 +p[0] = 0;

This modifies the original string - you shouldn't do that.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Best Case Latency

2013-09-21 Thread Tanu Kaskinen
On Thu, 2013-09-19 at 23:54 +1000, Patrick Shirkey wrote:
 On Thu, September 19, 2013 6:52 pm, Patrick Shirkey wrote:
 
  On Thu, September 19, 2013 6:42 pm, Tanu Kaskinen wrote:
  On Wed, 2013-09-18 at 04:28 +1000, Patrick Shirkey wrote:
  Hi,
  Can someone shed some light on the best case and typical latency that
 Pulse provides for standard operations?
  What do you mean by standard operations? I'd estimate volume changes
 etc. normally (on an ALSA sink) have a few millisecond latency (best
 case 0.5 ms audio buffer + scheduling latency).
 
  Just a normal round trip signal flow, for example : PA (in) -
 audacity
  (in) - audacity (out) - pa (out)
 
 
  Also how that is affected by using jack-sink assuming jack is set to the
  lowest possible latency that a device can handle?
  When jackd asks for N frames from PulseAudio, pulseaudio will render N
 frames. There's no extra buffering done in the Jack sink, so volume
 changes etc. will have latency that is roughly the same as the normal
 Jack client latency.
 
  Do you have an suggestions on how to get an accurate measurement?
 
 
 
 I'm using this method:
 
   jack_delay - pa_source - audacity - pa_sink - jack_delay
 
 jack is set to 64/48000/2
 
 Using audacity with 0 internal latency and in pass through mode I see the
 following results. It starts out as 10.667ms and after a few seconds it
 climbs up to 70.667 ms.
 
 I see similar results with ecasound instead of audacity using the
 following chain:
 
 jack_delay - pa_source - ecasound - pa_sink - jack_delay
 
 ecasound -f:32,2,48000 -b:64 -i alsa -o alsa
 
 In that case it starts at 60.000 ms and climbs upto 572.000 ms after a few
 seconds of running the test.
 
 Full console logs here:
 
 http://boosthardware.com/pa-jack-latency.txt
 
 This appears to be caused by PA adding more buffer on a regular basis. Any
 thoughts on why this is happening and how to stop it?

PulseAudio doesn't increase the buffering on the fly (well, some small
adjustments are done with ALSA, but you're using JACK, so that's
irrelevant). If the source produces audio faster than the sink consumes
it, then I guess the buffer might accumulate in the PulseAudio client
(audacity/ecasound). I think one reason for the source running faster
could be that the sink side is experiencing underruns, which causes
silence to be sent to jack_delay every now and then, and this silence is
not compensated by dropping a matching amount of data from the PA
client.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 09/41] bluetooth: Implement org.bluez.MediaEndpoint1.SelectConfiguration()

2013-09-21 Thread Tanu Kaskinen
On Sat, 2013-09-21 at 13:30 -0500, João Paulo Rechi Vita wrote:
 On Sat, Sep 21, 2013 at 5:16 AM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
   static DBusMessage *endpoint_select_configuration(DBusConnection *conn, 
  DBusMessage *m, void *userdata) {
  +pa_bluetooth_discovery *y = userdata;
  +a2dp_sbc_t *cap, config;
  +uint8_t *pconf = (uint8_t *) config;
  +int i, size;
   DBusMessage *r;
  +DBusError err;
 
  -pa_assert_se(r = dbus_message_new_error(m, 
  BLUEZ_MEDIA_ENDPOINT_INTERFACE .Error.NotImplemented,
  -Method not implemented));
  +static const struct {
  +uint32_t rate;
  +uint8_t cap;
  +} freq_table[] = {
  +{ 16000U, SBC_SAMPLING_FREQ_16000 },
  +{ 32000U, SBC_SAMPLING_FREQ_32000 },
  +{ 44100U, SBC_SAMPLING_FREQ_44100 },
  +{ 48000U, SBC_SAMPLING_FREQ_48000 }
  +};
  +
  +dbus_error_init(err);
  +
  +if (!dbus_message_get_args(m, err, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
  cap, size, DBUS_TYPE_INVALID)) {
  +pa_log_error(Endpoint SelectConfiguration(): %s, err.message);
  +dbus_error_free(err);
  +goto fail;
  +}
  +
  +if (size != sizeof(config)) {
  +pa_log_error(Capabilities array has invalid size);
  +goto fail;
  +}
  +
  +pa_zero(config);
  +
  +/* Find the lowest freq that is at least as high as the requested 
  sampling rate */
  +for (i = 0; (unsigned) i  PA_ELEMENTSOF(freq_table); i++)
  +if (freq_table[i].rate = y-core-default_sample_spec.rate  
  (cap-frequency  freq_table[i].cap)) {
  +config.frequency = freq_table[i].cap;
  +break;
  +}
 
  +if ((unsigned) i == PA_ELEMENTSOF(freq_table)) {
  +for (--i; i = 0; i--) {
  +if (cap-frequency  freq_table[i].cap) {
  +config.frequency = freq_table[i].cap;
  +break;
  +}
  +}
  +
  +if (i  0) {
  +pa_log_error(Not suitable sample rate);
  +goto fail;
  +}
  +}
  +
  +pa_assert((unsigned) i  PA_ELEMENTSOF(freq_table));
  +
  +if (y-core-default_sample_spec.channels = 1)
  +if (cap-channel_mode  SBC_CHANNEL_MODE_MONO)
  +config.channel_mode = SBC_CHANNEL_MODE_MONO;
 
  You forgot to fix this code. The problem still exists that if
  default_sample_spec.channels is 1 and the cap-channel_mode doesn't
  contain SBC_CHANNEL_MODE_MONO, then config.channel_mode is left
  uninitialized.
 
 
 No, I didn't, but I may have misunderstood you. Re-reading it new
 trying to give another interpretation, it seems you suggest that we
 don't differentiate between (y-core-default_sample_spec.channels =
 1) and (y-core-default_sample_spec.channels = 2), but I don't think
 that's what you meant. Can you please explain how we should
 differentiate those two cases?

There are four modes we support: mono, and three stereo modes. We should
always allow any any of those modes. Depending on
default_sample_spec.channels, we should either prefer the mono mode or
the stereo modes, but if the device doesn't support our preferred mode,
we should fall back to a mode that the device supports. In your code
that fallback is implemented when default_sample_spec.channels = 2, but
not if default_sample_spec.channels == 1.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 16/41] bluetooth: Register endpoints with BlueZ 5 adapter

2013-09-21 Thread Tanu Kaskinen
On Sat, 2013-09-21 at 14:17 -0500, João Paulo Rechi Vita wrote:
 On Sat, Sep 21, 2013 at 7:44 AM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
  From: João Paulo Rechi Vita jprv...@openbossa.org
 
  ---
   src/modules/bluetooth/bluez5-util.c | 82 
  -
   1 file changed, 81 insertions(+), 1 deletion(-)
 
  diff --git a/src/modules/bluetooth/bluez5-util.c 
  b/src/modules/bluetooth/bluez5-util.c
  index 4bc5967..03c73c9 100644
  --- a/src/modules/bluetooth/bluez5-util.c
  +++ b/src/modules/bluetooth/bluez5-util.c
  @@ -40,9 +40,12 @@
   #define BLUEZ_SERVICE org.bluez
   #define BLUEZ_ADAPTER_INTERFACE BLUEZ_SERVICE .Adapter1
   #define BLUEZ_DEVICE_INTERFACE BLUEZ_SERVICE .Device1
  +#define BLUEZ_MEDIA_INTERFACE BLUEZ_SERVICE .Media1
   #define BLUEZ_MEDIA_ENDPOINT_INTERFACE BLUEZ_SERVICE .MediaEndpoint1
   #define BLUEZ_MEDIA_TRANSPORT_INTERFACE BLUEZ_SERVICE .MediaTransport1
 
  +#define BLUEZ_ERROR_NOT_SUPPORTED org.bluez.Error.NotSupported
  +
   #define A2DP_SOURCE_ENDPOINT /MediaEndpoint/A2DPSource
   #define A2DP_SINK_ENDPOINT /MediaEndpoint/A2DPSink
 
  @@ -439,6 +442,81 @@ static int 
  parse_adapter_properties(pa_bluetooth_adapter *a, DBusMessageIter *i,
   return 0;
   }
 
  +static void register_endpoint_reply(DBusPendingCall *pending, void 
  *userdata) {
  +DBusMessage *r;
  +pa_dbus_pending *p;
  +pa_bluetooth_discovery *y;
  +char *endpoint;
  +
  +pa_assert(pending);
  +pa_assert_se(p = userdata);
  +pa_assert_se(y = p-context_data);
  +pa_assert_se(endpoint = p-call_data);
  +pa_assert_se(r = dbus_pending_call_steal_reply(pending));
  +
  +if (dbus_message_is_error(r, DBUS_ERROR_SERVICE_UNKNOWN)) {
  +pa_log_debug(Bluetooth daemon is apparently not available);
  +device_remove_all(y);
 
  Adapters should be removed too. I think there should be a function that
  takes care of clearing everything, so that it's not necessary to
  remember to remove both devices and adapters everywhere where we notice
  that bluetoothd is non-functional.
 
 
 We use device_remove_all and adapter_remove_all independently in
 pa_done, and I don't like the idea of having one function that simply
 wrap to functions together.

Why? The log message says: Bluetooth daemon is apparently not
available. The thing to do in that situation is to clear all state, and
if clearing all state takes several steps (as it does) and if the same
clearing needs to be done in multiple places (as it does), then a helper
function seems like the obvious choice.

However, it looks to me that checking for DBUS_ERROR_SERVICE_UNKNOWN
here is pretty pointless. We shouldn't receive that error as long as
there's an owner for the org.bluez name, and when the owner of the name
goes away, we get a notification about that and do the cleanup at that
point.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 15/41] bluetooth: Parse BlueZ 5 adapter properties

2013-09-21 Thread Tanu Kaskinen
On Sat, 2013-09-21 at 15:56 -0500, João Paulo Rechi Vita wrote:
 On Sat, Sep 21, 2013 at 7:51 AM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
  +static int parse_adapter_properties(pa_bluetooth_adapter *a, 
  DBusMessageIter *i, bool is_property_change) {
  +DBusMessageIter element_i;
  +
  +pa_assert(a);
  +
  +dbus_message_iter_recurse(i, element_i);
  +
  +while (dbus_message_iter_get_arg_type(element_i) == 
  DBUS_TYPE_DICT_ENTRY) {
  +DBusMessageIter dict_i, variant_i;
  +const char *key;
  +
  +dbus_message_iter_recurse(element_i, dict_i);
  +
  +key = check_variant_property(dict_i);
  +if (key == NULL) {
  +pa_log_error(Received invalid property for adapter %s, 
  a-path);
  +return -1;
  +}
  +
  +dbus_message_iter_recurse(dict_i, variant_i);
  +
  +if (dbus_message_iter_get_arg_type(variant_i) == 
  DBUS_TYPE_STRING  pa_streq(key, Address)) {
  +char *value;
  +
  +dbus_message_iter_get_basic(variant_i, value);
  +a-address = pa_xstrdup(value);
  +}
 
  Can the Address property change? If not, it should be checked if
  is_property_change is true, and if it is, then complain loudly. If it
  can change, then the old address should be freed before assigning the
  new address.
 
 The address property should not change, I'm adding those checks.

There should also be check that a-address is not already set (which it
can be, if the received properties contain duplicate Address entries).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Best Case Latency

2013-09-22 Thread Tanu Kaskinen
On Sun, 2013-09-22 at 02:30 +1000, Patrick Shirkey wrote:
 On Sun, September 22, 2013 1:55 am, Tanu Kaskinen wrote:
  PulseAudio doesn't increase the buffering on the fly (well, some small
  adjustments are done with ALSA, but you're using JACK, so that's
  irrelevant). If the source produces audio faster than the sink consumes
  it, then I guess the buffer might accumulate in the PulseAudio client
  (audacity/ecasound). I think one reason for the source running faster
  could be that the sink side is experiencing underruns, which causes
  silence to be sent to jack_delay every now and then, and this silence is
  not compensated by dropping a matching amount of data from the PA
  client.
 
 
 That seems like a reasonable explanation. The device I am using is an
 onboard hda_intel and I am seeing a lot of xruns in the jack console
 messages.
 
 From the perspective of an ignorant user this appears to be a sort of bug
 in that the audio stream is being delivered to the speakers but not to
 jack_delay. Although ears can be deceiving I don't hear any obvious
 dropouts.
 
 Can you think of a way to mitigate this issue when using both jack and pa
 at the same time?
 
 I am seeing this issue with both 64 frames/period and 1024 . I usually run
 with 1024 on JACK and that stable for me albeit I don't ever try to record
 to jack apps with the onboard mic.
 
 However, I use skype via PA regularly and it usually provides semi decent
 quality for phone conversations (without jack running).
 
 I tried using the skype call testing service with jack+pa. I can hear my
 voice and there are no obvious artefacts.
 
 The end goal here is to find a way to accurately measure the round trip
 latency when both JACK and PA are in use and figure out a robust method to
 achieve the lowest latency possible while PA is connected to JACK .
 Ideally I would like to measure the latency between each node in the
 graph.
 
 Does the PA API allow for obtaining latency measurements between nodes in
 the graph? Could I spin up a tool to gather that data for testing/QA
 purposes? By combining that info with jack_delay and a couple of other
 system metrics I might be able to gain some useful insight into tweaking
 the system to provide better performance other than installing a realtime
 kernel and setting the priorities with rtirq. That's assuming that there
 is anything that can be done to either PA or JACK to make it perform
 better.

If you want to get the minimum latency of this path:

jack_delay - pulseaudio - application - pulseaudio - jack_delay

then you should use an application that reports underruns and lets you
control the latency that the application requests from pulseaudio. Then
you can tune the application latency to find the point where you start
to get underruns. You should also know the maximum internal buffer size
of the application. You probably need to write that application
yourself.

pa_stream_get_latency() gives you an estimate of the latency between the
hardware and your application. pa_stream_get_timing_info() gives some
more details about how that latency is split between different parts in
pulseaudio.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 1/4] alsa: Add extcon (Android switch) jack detection

2013-09-22 Thread Tanu Kaskinen
On Fri, 2013-09-20 at 09:41 -0500, João Paulo Rechi Vita wrote:
 On Thu, Sep 19, 2013 at 4:53 PM, David Henningsson
 david.hennings...@canonical.com wrote:
  On 09/19/2013 01:17 PM, Damir Jelić wrote:
  Sorry if I'm a little bit annoying here but I'd like to keep our from
  now on with as little style inconsistency as possible. I haven't done
  any proper review/testing on this, just a quick coding style check.
 
  Sorry if I'm even more annoying here ;-) but perhaps you haven't heard
  my personal view on this matter.
 
  I totally disagree. I would instead like to keep our coding style rules
  to a bare minimum to keep the code decently readable. Anything else is
  just an additional road block towards what's important: spending as much
  time as possible fixing bugs and implementing new features, rather than
  spending time complying to coding style rules.
 
  So; for the opening bracket on newline - I think our current coding
  style is wrong and should be changed for functions, and I always forget
  that we have this odd style here. You're okay to comment on that,
  because it is in our coding style rules, but I would appreciate more, as
  you say, any proper review/testing, rather than a simple coding style
  check. You focus on what looks good on the surface, but what really
  matters is real code quality - i e, whether the code is going to solve
  our users' problems without causing annoying bugs, or not.
 
  If you're really lazy you can use my sed script to fix this issues (well
  the opening bracket on newline issues at least).[2]
 
  For the stuff that's *not* in the coding style wiki page, I'm even
  lazier. If you prefer a different style than I happen to write, feel
  free to run your scripts every six months or so and submit a patch for
  it, and I won't complain if somebody else reviews and commit it. (Well,
  unless it severely decreases readability somehow.)
 
 
 The problem with commits that only fix coding style is that it screws
 up history, making things like 'git blame' much harder, so I think we
 should avoid that as much as possible. The only way to avoid it is
 trying to have clear coding style rules and trying to adhere to them
 as much as possible. OTOH, I agree with David that there are some more
 important stuff for time to be spent on than spending time dealing
 with coding style.
 
 The only solution I know that would help is to have some coding style
 checker that would help us on finding problems with the coding style.
 This tool should be available in the repository, so anyone sending
 patches can check style before submitting patches, but this should
 also be checked by the maintainer before committing the code upstream.
 If any coding style problem is found at this later point, it's ok IMO
 that the maintainer fixes the coding style problems by himself
 (amending to the original commit) so we don't add an additional
 peer-review roundtrip.
 
 What do you guys think?

A style checker script would be great. On another topic: I want a
pony ;)

It seems that at least a mass conversion the current code base to the
new style is getting quite a lot of opposition, so that's probably not
going to happen. Then there's the question that should we keep
complaining about style violations with the curly braces. Should
contributors be allowed to put the curly braces where they want, and
inconsistencies would be fixed later if the lines in question are
modified as part of some other patch? The curly brace issue is such that
inconsistency wouldn't bother me much.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Best Case Latency

2013-09-23 Thread Tanu Kaskinen
On Sun, 2013-09-22 at 20:03 +1000, Patrick Shirkey wrote:
 On Sun, September 22, 2013 4:37 pm, Tanu Kaskinen wrote:
  If you want to get the minimum latency of this path:
 
  jack_delay - pulseaudio - application - pulseaudio - jack_delay
 
  then you should use an application that reports underruns and lets you
  control the latency that the application requests from pulseaudio. Then
  you can tune the application latency to find the point where you start
  to get underruns. You should also know the maximum internal buffer size
  of the application. You probably need to write that application
  yourself.
 
 
 I am using ecasound which reports underruns and allows me to set the
 internal buffer. I have it set to 64 frames/period for this test.
 
 It does report occasional underruns but over a 6 hour period I had about
 20. Based on that info it leads me to PA sink as the bottle neck. Do you
 have any suggestions about how I can rule that out?

The audio is accumulating in some buffer, and the JACK sink in
PulseAudio doesn't have any buffer, so it's not the sink. It could be
some other buffer in PulseAudio, or it could be a buffer in ecasound.

Saying that ecasound is configured with 64 frames/period isn't terribly
informative, because I don't know how ecasound handles the transfer from
the input to the output. Does it push the data immediately to the output
when it gets something from the input, or are both directions callback
based? If the former, then the data can accumulate in the stream buffer
in PA, and if the latter, then there has to be an intermediate buffer
between the input and the output in ecasound, and the data can
accumulate there.

  pa_stream_get_latency() gives you an estimate of the latency between the
  hardware and your application. pa_stream_get_timing_info() gives some
  more details about how that latency is split between different parts in
  pulseaudio.
 
 
 Can you or anyone else recommend an example app that I can use as a
 reference for this code?

No. And anyway, if you want to really measure the latency (detect when a
signal pulse arrives at a measurement point), these functions are
useless (except for checking that is PulseAudio reporting the latency
correctly or not, which would actually be quite interesting
information).

 I am thinking of building an app that will let me gather latency data from
 both PA and JACK. I would like it to measure the timing of a signal pulse
 as it is transferred between each node in the graph. It would communicate
 with both JACK and PA at the same time. Do you see any insurmountable
 blockers to achieving that goal from a technical perspective in regards to
 PA?

So you would generate a pulse in a jack client, and detect it in a PA
client, and then detect it again in a jack client? No, I don't see any
obstacles to doing that.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] alsa: Turn one assertion into two

2013-09-23 Thread Tanu Kaskinen
On Mon, 2013-09-23 at 09:55 +0200, David Henningsson wrote:
 According to coding style, one should have one assertion per line
 and not combine assertions.
 
 Signed-off-by: David Henningsson david.hennings...@canonical.com
 ---
  src/modules/alsa/module-alsa-card.c |4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/src/modules/alsa/module-alsa-card.c 
 b/src/modules/alsa/module-alsa-card.c
 index 96e88e5..be982ed 100644
 --- a/src/modules/alsa/module-alsa-card.c
 +++ b/src/modules/alsa/module-alsa-card.c
 @@ -378,8 +378,8 @@ static int report_jack_state(snd_hctl_elem_t *elem, 
 unsigned int mask) {
  pa_assert(port);
  }
  else {
 -pa_assert(jack-path  jack-path-port);
 -port = jack-path-port;
 +pa_assert(jack-path);
 +pa_assert_se(port = jack-path-port);
  }
  report_port_state(port, u);
  }

Ack.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Suggested coding style change for functions

2013-09-23 Thread Tanu Kaskinen
On Mon, 2013-09-23 at 10:21 +0200, David Henningsson wrote:
 On 09/20/2013 11:23 AM, Peter Meerwald wrote:
  I think both coding styles are sane and I suggest to NOT convert to a new 
  style
  
  the 'other projects' is Gnome?
 
 Gnome, Linux Kernel, FluidSynth (as mentioned previously).
 
  there is not the ONE style and it really depends on your personal 
  situation which styles you work more often with -- what's good for one 
  contributer might not be for another
 
 Out of curiousity, do you know any bigger open source projects that do
 the no newline style? I don't think I've ever seen one except for
 PulseAudio.

Quoting the CODING_STYLE file of systemd:

- Try to use this:

  void foo() {
  }

  instead of this:

  void foo()
  {
  }

  But it's OK if you don't.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v4 09/41] bluetooth: Implement org.bluez.MediaEndpoint1.SelectConfiguration()

2013-09-24 Thread Tanu Kaskinen
On Mon, 2013-09-23 at 08:39 -0500, João Paulo Rechi Vita wrote:
 On Sun, Sep 22, 2013 at 12:19 AM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Sat, 2013-09-21 at 13:30 -0500, João Paulo Rechi Vita wrote:
  On Sat, Sep 21, 2013 at 5:16 AM, Tanu Kaskinen
  tanu.kaski...@linux.intel.com wrote:
   On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
static DBusMessage *endpoint_select_configuration(DBusConnection 
   *conn, DBusMessage *m, void *userdata) {
   +pa_bluetooth_discovery *y = userdata;
   +a2dp_sbc_t *cap, config;
   +uint8_t *pconf = (uint8_t *) config;
   +int i, size;
DBusMessage *r;
   +DBusError err;
  
   -pa_assert_se(r = dbus_message_new_error(m, 
   BLUEZ_MEDIA_ENDPOINT_INTERFACE .Error.NotImplemented,
   -Method not implemented));
   +static const struct {
   +uint32_t rate;
   +uint8_t cap;
   +} freq_table[] = {
   +{ 16000U, SBC_SAMPLING_FREQ_16000 },
   +{ 32000U, SBC_SAMPLING_FREQ_32000 },
   +{ 44100U, SBC_SAMPLING_FREQ_44100 },
   +{ 48000U, SBC_SAMPLING_FREQ_48000 }
   +};
   +
   +dbus_error_init(err);
   +
   +if (!dbus_message_get_args(m, err, DBUS_TYPE_ARRAY, 
   DBUS_TYPE_BYTE, cap, size, DBUS_TYPE_INVALID)) {
   +pa_log_error(Endpoint SelectConfiguration(): %s, 
   err.message);
   +dbus_error_free(err);
   +goto fail;
   +}
   +
   +if (size != sizeof(config)) {
   +pa_log_error(Capabilities array has invalid size);
   +goto fail;
   +}
   +
   +pa_zero(config);
   +
   +/* Find the lowest freq that is at least as high as the requested 
   sampling rate */
   +for (i = 0; (unsigned) i  PA_ELEMENTSOF(freq_table); i++)
   +if (freq_table[i].rate = y-core-default_sample_spec.rate  
   (cap-frequency  freq_table[i].cap)) {
   +config.frequency = freq_table[i].cap;
   +break;
   +}
  
   +if ((unsigned) i == PA_ELEMENTSOF(freq_table)) {
   +for (--i; i = 0; i--) {
   +if (cap-frequency  freq_table[i].cap) {
   +config.frequency = freq_table[i].cap;
   +break;
   +}
   +}
   +
   +if (i  0) {
   +pa_log_error(Not suitable sample rate);
   +goto fail;
   +}
   +}
   +
   +pa_assert((unsigned) i  PA_ELEMENTSOF(freq_table));
   +
   +if (y-core-default_sample_spec.channels = 1)
   +if (cap-channel_mode  SBC_CHANNEL_MODE_MONO)
   +config.channel_mode = SBC_CHANNEL_MODE_MONO;
  
   You forgot to fix this code. The problem still exists that if
   default_sample_spec.channels is 1 and the cap-channel_mode doesn't
   contain SBC_CHANNEL_MODE_MONO, then config.channel_mode is left
   uninitialized.
  
 
  No, I didn't, but I may have misunderstood you. Re-reading it new
  trying to give another interpretation, it seems you suggest that we
  don't differentiate between (y-core-default_sample_spec.channels =
  1) and (y-core-default_sample_spec.channels = 2), but I don't think
  that's what you meant. Can you please explain how we should
  differentiate those two cases?
 
  There are four modes we support: mono, and three stereo modes. We should
  always allow any any of those modes. Depending on
  default_sample_spec.channels, we should either prefer the mono mode or
  the stereo modes, but if the device doesn't support our preferred mode,
  we should fall back to a mode that the device supports. In your code
  that fallback is implemented when default_sample_spec.channels = 2, but
  not if default_sample_spec.channels == 1.
 
 
 Ok, and what preference order we should use between the stereo modes
 for default_sample_spec.channels == 1? (I'm assuming mono is the 1st
 preference in this case).

Yes, mono is the first preferred mode. I don't have any idea about the
ordering of the different stereo modes, except that the ordering should
be the same for both default_sample_spec.channels == 1 and
default_sample_spec.channels == 2, unless you know some reason to use
different ordering.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Best Case Latency

2013-09-25 Thread Tanu Kaskinen
On Wed, 2013-09-25 at 23:35 +1000, Patrick Shirkey wrote:
 On Tue, September 24, 2013 10:33 pm, Patrick Shirkey wrote:
 
  On Mon, September 23, 2013 6:11 pm, Tanu Kaskinen wrote:
  The audio is accumulating in some buffer, and the JACK sink in
  PulseAudio doesn't have any buffer, so it's not the sink. It could be
  some other buffer in PulseAudio, or it could be a buffer in ecasound.
 
  Saying that ecasound is configured with 64 frames/period isn't terribly
  informative, because I don't know how ecasound handles the transfer from
  the input to the output. Does it push the data immediately to the output
  when it gets something from the input, or are both directions callback
  based? If the former, then the data can accumulate in the stream buffer
  in PA, and if the latter, then there has to be an intermediate buffer
  between the input and the output in ecasound, and the data can
  accumulate there.
 
 
  I've asked for some more details on the ecasound list.
 
  If the PA stream buffer is kicking in, Is there any way I can verify if it
  is happening? is there anything I can do to minimise that affect?
 
 
 I had verification from the ecasound developer Kai Vehmanen that ecasound
 does not have an internal buffer that could be affecting the latency in
 this way. It just buffers 64 frames and if it can't keep up it will drop
 data and report an underun. In my tests there were just a few underruns
 over several hours so it appears safe to rule out ecasound.
 
 Does anyone have any suggestions for testing the PA Stream Buffer to check
 if it is a bottleneck in my test environment?

Sorry, forgot to reply earlier. Yes, you can check the stream buffer
with pactl list sink-inputs. The Buffer Latency field shows the
amount of audio in the stream buffer (not yet written to the sink). The
Sink Latency field shows the latency of the sink. The sum of these two
values is the full server-side latency for the stream. In addition to
the server-side latency, there's the transport latency between the
client and the server (very low for local streams).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Best Case Latency

2013-09-27 Thread Tanu Kaskinen
On Fri, 2013-09-27 at 19:26 +1000, Patrick Shirkey wrote:
 On Thu, September 26, 2013 2:27 am, Tanu Kaskinen wrote:
  Sorry, forgot to reply earlier. Yes, you can check the stream buffer
  with pactl list sink-inputs. The Buffer Latency field shows the
  amount of audio in the stream buffer (not yet written to the sink). The
  Sink Latency field shows the latency of the sink. The sum of these two
  values is the full server-side latency for the stream. In addition to
  the server-side latency, there's the transport latency between the
  client and the server (very low for local streams).
 
 
 Thanks for that info. Polling the output I see the results fluctuate over
 time in much the same way that the results from jack_iodelay fluctuate. I
 haven't tried to correlate them yet but here's a snapshot to give you a
 better idea of what is happening on this machine.

The latency stays around 10 ms. You complained earlier that the latency
would grow to several hundreds of milliseconds, but this shows no such
behaviour, so the problem is somewhere else than in the playback stream
inside pulseaudio.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v5 39/39] bluetooth: Revive module-bluetooth-discover

2013-09-27 Thread Tanu Kaskinen
On Tue, 2013-09-24 at 16:16 -0700, Fox, Kevin M wrote:
 Is there a reason that the struct is:
 +struct userdata {
 +pa_module *bluez5_module;
 +pa_module *bluez4_module;
 +};
 
 and not:
 +struct userdata {
 +pa_module *bluez_module;
 +};
 
 The code might be cleaner looking with the latter struct.

Yes, there is a reason for the code being how it is. We want
module-bluetooth-discover to load two modules, if support for both
bluez4 and bluez5 is compiled in, but in your suggestion only one module
can be loaded.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Best Case Latency

2013-09-27 Thread Tanu Kaskinen
On Fri, 2013-09-27 at 23:31 +1000, Patrick Shirkey wrote:
 On Fri, September 27, 2013 10:52 pm, Tanu Kaskinen wrote:
  On Fri, 2013-09-27 at 19:26 +1000, Patrick Shirkey wrote:
  On Thu, September 26, 2013 2:27 am, Tanu Kaskinen wrote:
   Sorry, forgot to reply earlier. Yes, you can check the stream buffer
   with pactl list sink-inputs. The Buffer Latency field shows the
   amount of audio in the stream buffer (not yet written to the sink).
  The
   Sink Latency field shows the latency of the sink. The sum of these
  two
   values is the full server-side latency for the stream. In addition to
   the server-side latency, there's the transport latency between the
   client and the server (very low for local streams).
  
 
  Thanks for that info. Polling the output I see the results fluctuate
  over
  time in much the same way that the results from jack_iodelay fluctuate.
  I
  haven't tried to correlate them yet but here's a snapshot to give you a
  better idea of what is happening on this machine.
 
  The latency stays around 10 ms. You complained earlier that the latency
  would grow to several hundreds of milliseconds, but this shows no such
  behaviour, so the problem is somewhere else than in the playback stream
  inside pulseaudio.
 
 
 It may seem like I am complaining but I am not trying to come across that
 way.

I guess that was a bad choice of words from my part. You were reporting
undesirable behaviour, which I referred to as complaining. I used it as
a neutral word, not as in whining or anything like that.

 I am trying to get hard data on the real world latency performance
 using the combination of JACK + PA to allow a bunch of people including
 some of your colleagues at Intel to attempt to make a professional
 business decision about the best way to integrate them (or not) for mobile
 platforms. IMO it is best to run them with the method that I am testing
 and fix any issues that might not have been ironed out yet but others are
 suggesting they should be used interchangeably. That opens up a can of
 works that may be a lot more effort to implement both in terms of
 resources and politically for various reasons so I am reluctant to follow
 that path unless all options with combining JACK + PA have been
 categorically shown to be infeasible or impractical (or both).

Sorry, I couldn't really follow what you're saying, but I won't go into
detail, since I believe this is not relevant for solving the latency
mystery.

 At the moment I'm trying to pin down the cause of the consistent and
 reproducible but fluctuating latency results that I see with this machine.
 I am doing this in order to get the hard data I need to present the JACK +
 PA solution as the better method.

One of the unclear things is what other method you are comparing the
JACK + PA solution.

 So far I cannot point the finger at any
 specific process or bottleneck. Given that I am apparently the only person
 in the world who has the time and/or motivation to run these tests we are
 working with the small dataset that I can provide. All your feedback is
 crucial and very useful as I do not have the complete overview of PA
 codebase like yourself or others on this list.
 
 To recap, I have tested with two jack graphs.
 
 1: jack_delay - pa - ecasound - pa - jack_delay
 
 The latency starts low and then consistently climbs (see below).
 
 2: jack_delay - pa - ecasound - pa - system_out - system_in -
 jack_delay
 
 The latency jumps around from anything between 4ms to 1300ms. It might
 also go lower but I didn't see that yet.
 
 - Here's an interesting snapshot for consideration captured just now while
 running graph 1. The latency captured while polling with pactl list
 sink-inputs is the same as the previous snapshot (approx 10ms).
 
 ex.
   Buffer Latency: 8000 usec
   Sink Latency: 3166 usec
 
 However, jack_delay reports the following data. Where you see ?? that
 indicates a dropout in the audio stream so jack_delay was not able to make
 a real measurement so guessed.

What do you mean by dropout? An xrun reported by jackd? Note that
there are several different kinds of underruns and overruns that can
occur. One kind is the case where jackd is late to read/write to the
sound card (alsa). Another kind is when pulseaudio is late to read/write
to jackd (I'm not sure if this will always translate also to alsa level
under/overruns too). Third kind is when ecasound is late to read/write
to pulseaudio (this is what I'll refer to as stream under/overruns,
and these are invisible to the jack domain). Do you get logs about each
of these? I don't remember if the alsa compatibility layer forwards the
stream under/overrun notifications to the alsa application - IIRC there
were problems when those were reported and there were different problems
when those were not reported, and I don't remember what the current code
does.

I don't know if distinguishing between the different kinds of
under/overruns is really important at this point

Re: [pulseaudio-discuss] [PATCH v4 15/41] bluetooth: Parse BlueZ 5 adapter properties

2013-09-28 Thread Tanu Kaskinen
On Thu, 2013-09-26 at 14:11 -0300, João Paulo Rechi Vita wrote:
 On Wed, Sep 25, 2013 at 7:33 AM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Tue, 2013-09-24 at 19:19 -0300, João Paulo Rechi Vita wrote:
  On Sun, Sep 22, 2013 at 2:38 AM, Tanu Kaskinen
  tanu.kaski...@linux.intel.com wrote:
   On Sat, 2013-09-21 at 16:12 -0500, João Paulo Rechi Vita wrote:
   On Sat, Sep 21, 2013 at 6:12 AM, Tanu Kaskinen
   tanu.kaski...@linux.intel.com wrote:
On Wed, 2013-09-18 at 16:17 -0500, jprv...@gmail.com wrote:
 static void parse_interfaces_and_properties(pa_bluetooth_discovery 
*y, DBusMessageIter *dict_i) {
 DBusMessageIter element_i;
 const char *path;
@@ -415,7 +474,8 @@ static void 
parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa
   
 pa_log_debug(Adapter %s found, path);
   
-/* TODO: parse adapter properties and register 
endpoints */
+parse_adapter_properties(a, iface_i, false);
   
If parsing fails, or if the Address property is missing, the adapter
should be marked as invalid.
   
  
   We don't need to add a adapter_info_valid field, just not registering
   as an endpoint with that adapter should be enough.
  
   I don't think that's enough. Devices can point to adapters, so devices
   that point to invalid adapters should be marked as invalid too. I think
   an info_valid field also for adapters is the way to go.
  
 
  There is no problem if devices point to invalid adapters, since we
  have not registered as endpoints we'll never receive transports for
  these devices, so nothing will happen.
 
  pa_bluetooth_discovery_get_device_by_address() will crash if a device
  points to an adapter with NULL address.
 
  Actually, marking a device invalid if the adapter is invalid isn't
  sufficient to fix pa_bluetooth_discovery_get_device_by_address(). The
  function should check d-device_info_valid before trying to access
  d-adapter.
 
 
 Ok, that's a problem in pa_bluetooth_discovery_get_device_by_address()
 then. Fixing it leaves no other problems related to the adapter being
 invalid, right?

Seems so, with the current code. However, logically it doesn't make
sense to treat devices as valid if their adapter is invalid. Future code
can easily have bugs due to this, if adapters ever become more important
(right now the adapter usage is very limited: we track the adapters only
to be able to look up devices based on the local/remote address pair).

I think it would be good to have the adapter_info_valid field, and to
treat devices with an invalid address as invalid themselves, but if you
don't want to do that, feel free to leave the code as it is.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v5 09/39] bluetooth: Create a function to remove only one adapter object

2013-09-28 Thread Tanu Kaskinen
On Tue, 2013-09-24 at 19:45 -0300, jprv...@gmail.com wrote:
 @@ -371,11 +398,8 @@ static void adapter_remove_all(pa_bluetooth_discovery 
 *y) {
  
  /* When this function is called all devices have already been freed */
  
 -while ((a = pa_hashmap_steal_first(y-adapters))) {
 -pa_xfree(a-path);
 -pa_xfree(a-address);
 -pa_xfree(a);
 -}
 +while ((a = pa_hashmap_steal_first(y-adapters)))
 +adapter_free(a);

pa_hashmap_remove_all() can be used here (the hashmap initialization
needs to be changed so that adapter_free is passed to
pa_hashmap_new_full()). Actually, the whole adapter_remove_all()
function is now redundant, because it's effectively just an alias for
pa_hashmap_remove_all().

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v5 12/39] bluetooth: Parse BlueZ 5 adapter properties

2013-09-28 Thread Tanu Kaskinen
On Tue, 2013-09-24 at 19:45 -0300, jprv...@gmail.com wrote:
 +static void parse_adapter_properties(pa_bluetooth_adapter *a, 
 DBusMessageIter *i, bool is_property_change) {
 +DBusMessageIter element_i;
 +
 +pa_assert(a);
 +
 +dbus_message_iter_recurse(i, element_i);
 +
 +while (dbus_message_iter_get_arg_type(element_i) == 
 DBUS_TYPE_DICT_ENTRY) {
 +DBusMessageIter dict_i, variant_i;
 +const char *key;
 +
 +dbus_message_iter_recurse(element_i, dict_i);
 +
 +key = check_variant_property(dict_i);
 +if (key == NULL) {
 +pa_log_error(Received invalid property for adapter %s, 
 a-path);
 +return;
 +}
 +
 +dbus_message_iter_recurse(dict_i, variant_i);
 +
 +if (dbus_message_iter_get_arg_type(variant_i) == DBUS_TYPE_STRING 
  pa_streq(key, Address)) {
 +char *value;

The type should be const char *.

 +
 +if (is_property_change) {
 +pa_log_warn(Adapter property 'Address' expected to be 
 constant but changed for %s, ignoring, a-path);
 +return;
 +}
 +
 +if (a-address) {
 +pa_log_warn(Adapter %s received a duplicate 'Address' 
 property, ignoring, a-path);
 +return;
 +}
 +
 +dbus_message_iter_get_basic(variant_i, value);
 +a-address = pa_xstrdup(value);
 +}
 +
 +dbus_message_iter_next(element_i);
 +}
 +}
 +
  static void parse_interfaces_and_properties(pa_bluetooth_discovery *y, 
 DBusMessageIter *dict_i) {
  DBusMessageIter element_i;
  const char *path;
 @@ -439,7 +506,11 @@ static void 
 parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa
  
  pa_log_debug(Adapter %s found, path);
  
 -/* TODO: parse adapter properties and register endpoints */
 +parse_adapter_properties(a, iface_i, false);
 +if (!a-address)
 +return;

(Note to self: there is an ongoing discussion about whether there should
be an adapter_info_valid field. Depending on the conclusion of the
discussion, this code may change in v6.)

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v5 16/39] bluetooth: Protect from a misbehaving bluetoothd

2013-09-29 Thread Tanu Kaskinen
On Tue, 2013-09-24 at 19:45 -0300, jprv...@gmail.com wrote:
 @@ -745,6 +748,15 @@ static void 
 parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa
  dbus_message_iter_next(element_i);
  }
  
 +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) {
 +pa_log_error(Device %s is child of nonexistent adapter %s, 
 d-path, d-adapter_path);
 +d-device_info_valid = -1;
 +}
 +}

As discussed, the DEVICE_CONNECTION_CHANGED hook should be fired after
parsing the device properties (I'm mentioning this just to make sure
that I remember to check this in v6).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH v5 36/39] bluetooth: Fail to load driver if discovery module is not loaded

2013-09-29 Thread Tanu Kaskinen
On Tue, 2013-09-24 at 19:45 -0300, jprv...@gmail.com wrote:
 diff --git a/src/modules/bluetooth/module-bluez5-device.c 
 b/src/modules/bluetooth/module-bluez5-device.c
 index 36d7174..013cce5 100644
 --- a/src/modules/bluetooth/module-bluez5-device.c
 +++ b/src/modules/bluetooth/module-bluez5-device.c
 @@ -39,6 +39,7 @@
  #include pulsecore/modargs.h
  #include pulsecore/poll.h
  #include pulsecore/rtpoll.h
 +#include pulsecore/shared.h
  #include pulsecore/socket-util.h
  #include pulsecore/thread.h
  #include pulsecore/thread-mq.h
 @@ -1792,8 +1793,12 @@ int pa__init(pa_module* m) {
  goto fail;
  }
  
 -if (!(u-discovery = pa_bluetooth_discovery_get(m-core)))
 +if ((u-discovery = pa_shared_get(u-core, bluetooth-discovery)))
 +pa_bluetooth_discovery_ref(u-discovery);
 +else {
 +pa_log_error(module-bluez5-discover doesn't seem to be loaded, 
 refusing to load module-bluez5-device);
  goto fail;
 +}

(Note to self: there is ongoing discussion about this:
http://thread.gmane.org/gmane.comp.audio.pulseaudio.general/17959/focus=18491)

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 0/5] Bluetooth polishing

2013-09-29 Thread Tanu Kaskinen
Here are some small fixes to issues that I found while reviewing the
big Bluetooth patch set from João.

Tanu Kaskinen (5):
  bluetooth: Remove adapter_remove_all()
  bluetooth: Fix variable constness
  bluetooth: Fix notifying about new devices
  bluetooth: Remove device_remove_all()
  bluetooth: Set device_info_valid to -1 when the device's adapter
disappears

 src/modules/bluetooth/bluez5-util.c | 79 +++--
 1 file changed, 41 insertions(+), 38 deletions(-)

-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 2/5] bluetooth: Fix variable constness

2013-09-29 Thread Tanu Kaskinen
The string points to memory inside a DBusMessage, so we don't own the string.
---
 src/modules/bluetooth/bluez5-util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/modules/bluetooth/bluez5-util.c 
b/src/modules/bluetooth/bluez5-util.c
index 2be15d8..eaff4b1 100644
--- a/src/modules/bluetooth/bluez5-util.c
+++ b/src/modules/bluetooth/bluez5-util.c
@@ -651,7 +651,7 @@ static void parse_adapter_properties(pa_bluetooth_adapter 
*a, DBusMessageIter *i
 dbus_message_iter_recurse(dict_i, variant_i);
 
 if (dbus_message_iter_get_arg_type(variant_i) == DBUS_TYPE_STRING  
pa_streq(key, Address)) {
-char *value;
+const char *value;
 
 if (is_property_change) {
 pa_log_warn(Adapter property 'Address' expected to be 
constant but changed for %s, ignoring, a-path);
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 4/5] bluetooth: Remove device_remove_all()

2013-09-29 Thread Tanu Kaskinen
The function did two things: set device_info_valid to -1 and called
device_free() for each device in the hashmap. Setting
device_info_valid to -1 was unnecessary. The main purpose of that was
to fire DEVICE_CONNECTION_CHANGED as a side effect, but that hook is
fired anyway in device_free(), as a side effect of removing all
transports. Calling device_free() can be delegated to pa_hashmap, when
freeing or emptying it.
---
 src/modules/bluetooth/bluez5-util.c | 20 
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/src/modules/bluetooth/bluez5-util.c 
b/src/modules/bluetooth/bluez5-util.c
index c7e934e..591ea50 100644
--- a/src/modules/bluetooth/bluez5-util.c
+++ b/src/modules/bluetooth/bluez5-util.c
@@ -454,17 +454,6 @@ static void set_device_info_valid(pa_bluetooth_device 
*device, int valid) {
 
pa_hook_fire(device-discovery-hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED],
 device);
 }
 
-static void device_remove_all(pa_bluetooth_discovery *y) {
-pa_bluetooth_device *d;
-
-pa_assert(y);
-
-while ((d = pa_hashmap_steal_first(y-devices))) {
-set_device_info_valid(d, -1);
-device_free(d);
-   }
-}
-
 static pa_bluetooth_adapter* adapter_create(pa_bluetooth_discovery *y, const 
char *path) {
 pa_bluetooth_adapter *a;
 
@@ -928,7 +917,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, 
DBusMessage *m, void *us
 if (pa_streq(name, BLUEZ_SERVICE)) {
 if (old_owner  *old_owner) {
 pa_log_debug(Bluetooth daemon disappeared);
-device_remove_all(y);
+pa_hashmap_remove_all(y-devices);
 pa_hashmap_remove_all(y-adapters);
 y-objects_listed = false;
 }
@@ -1533,7 +1522,8 @@ pa_bluetooth_discovery* 
pa_bluetooth_discovery_get(pa_core *c) {
 y-core = c;
 y-adapters = pa_hashmap_new_full(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func, NULL,
   (pa_free_cb_t) adapter_free);
-y-devices = pa_hashmap_new(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func);
+y-devices = pa_hashmap_new_full(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func, NULL,
+ (pa_free_cb_t) device_free);
 y-transports = pa_hashmap_new(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func);
 PA_LLIST_HEAD_INIT(pa_dbus_pending, y-pending);
 
@@ -1608,10 +1598,8 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery 
*y) {
 
 pa_dbus_free_pending_list(y-pending);
 
-if (y-devices) {
-device_remove_all(y);
+if (y-devices)
 pa_hashmap_free(y-devices);
-}
 
 if (y-adapters)
 pa_hashmap_free(y-adapters);
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 3/5] bluetooth: Fix notifying about new devices

2013-09-29 Thread Tanu Kaskinen
Normally devices are created and their properties are parsed before
creating any transports for the device, and the
DEVICE_CONNECTION_CHANGED hook is fired when the first transport is
created. It's possible, however, that a transport is created before
the device that it belongs to, and in this case
DEVICE_CONNECTION_CHANGED should be fired when the properties have
been successfully parsed for the device. The old code didn't fire the
hook at this situation, and this patch fixes that.
---
 src/modules/bluetooth/bluez5-util.c | 43 +
 1 file changed, 34 insertions(+), 9 deletions(-)

diff --git a/src/modules/bluetooth/bluez5-util.c 
b/src/modules/bluetooth/bluez5-util.c
index eaff4b1..c7e934e 100644
--- a/src/modules/bluetooth/bluez5-util.c
+++ b/src/modules/bluetooth/bluez5-util.c
@@ -438,14 +438,29 @@ static void device_remove(pa_bluetooth_discovery *y, 
const char *path) {
 }
 }
 
+static void set_device_info_valid(pa_bluetooth_device *device, int valid) {
+bool old_any_connected;
+
+pa_assert(device);
+pa_assert(valid == -1 || valid == 0 || valid == 1);
+
+if (valid == device-device_info_valid)
+return;
+
+old_any_connected = pa_bluetooth_device_any_transport_connected(device);
+device-device_info_valid = valid;
+
+if (pa_bluetooth_device_any_transport_connected(device) != 
old_any_connected)
+
pa_hook_fire(device-discovery-hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED],
 device);
+}
+
 static void device_remove_all(pa_bluetooth_discovery *y) {
 pa_bluetooth_device *d;
 
 pa_assert(y);
 
 while ((d = pa_hashmap_steal_first(y-devices))) {
-d-device_info_valid = -1;
-pa_hook_fire(y-hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED], 
d);
+set_device_info_valid(d, -1);
 device_free(d);
}
 }
@@ -607,7 +622,6 @@ static void parse_device_property(pa_bluetooth_device *d, 
DBusMessageIter *i, bo
 
 static int parse_device_properties(pa_bluetooth_device *d, DBusMessageIter *i, 
bool is_property_change) {
 DBusMessageIter element_i;
-int ret = 0;
 
 dbus_message_iter_recurse(i, element_i);
 
@@ -621,12 +635,17 @@ static int parse_device_properties(pa_bluetooth_device 
*d, DBusMessageIter *i, b
 
 if (!d-address || !d-adapter_path || !d-alias) {
 pa_log_error(Non-optional information missing for device %s, 
d-path);
-d-device_info_valid = -1;
+set_device_info_valid(d, -1);
 return -1;
 }
 
-d-device_info_valid = 1;
-return ret;
+if (!is_property_change  d-adapter)
+set_device_info_valid(d, 1);
+
+/* If d-adapter is NULL, device_info_valid will be left as 0, and updated
+ * after all interfaces have been parsed. */
+
+return 0;
 }
 
 static void parse_adapter_properties(pa_bluetooth_adapter *a, DBusMessageIter 
*i, bool is_property_change) {
@@ -804,14 +823,20 @@ static void 
parse_interfaces_and_properties(pa_bluetooth_discovery *y, DBusMessa
 dbus_message_iter_next(element_i);
 }
 
-PA_HASHMAP_FOREACH(d, y-devices, state)
+PA_HASHMAP_FOREACH(d, y-devices, state) {
+if (d-device_info_valid != 0)
+continue;
+
 if (!d-adapter  d-adapter_path) {
 d-adapter = pa_hashmap_get(d-discovery-adapters, 
d-adapter_path);
+
 if (!d-adapter) {
 pa_log_error(Device %s is child of nonexistent adapter %s, 
d-path, d-adapter_path);
-d-device_info_valid = -1;
-}
+set_device_info_valid(d, -1);
+} else
+set_device_info_valid(d, 1);
 }
+}
 
 return;
 }
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 5/5] bluetooth: Set device_info_valid to -1 when the device's adapter disappears

2013-09-29 Thread Tanu Kaskinen
When parsing device properties, missing adapter will result in
device_info_valid being set to -1. It is then logical that if the
adapter goes missing at a later point, device_info_valid gets set to
-1.
---
 src/modules/bluetooth/bluez5-util.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/modules/bluetooth/bluez5-util.c 
b/src/modules/bluetooth/bluez5-util.c
index 591ea50..3408b2c 100644
--- a/src/modules/bluetooth/bluez5-util.c
+++ b/src/modules/bluetooth/bluez5-util.c
@@ -477,8 +477,10 @@ static void adapter_free(pa_bluetooth_adapter *a) {
 pa_assert(a-discovery);
 
 PA_HASHMAP_FOREACH(d, a-discovery-devices, state)
-if (d-adapter == a)
+if (d-adapter == a) {
+set_device_info_valid(d, -1);
 d-adapter = NULL;
+}
 
 pa_xfree(a-path);
 pa_xfree(a-address);
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 1/5] bluetooth: Remove adapter_remove_all()

2013-09-29 Thread Tanu Kaskinen
The function was redundant, because all it did was call adapter_free()
for each adapter in the hashmap, and that can be delegated to
pa_hashmap when freeing or emptying it.
---
 src/modules/bluetooth/bluez5-util.c | 20 
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/src/modules/bluetooth/bluez5-util.c 
b/src/modules/bluetooth/bluez5-util.c
index 225e5c8..2be15d8 100644
--- a/src/modules/bluetooth/bluez5-util.c
+++ b/src/modules/bluetooth/bluez5-util.c
@@ -492,17 +492,6 @@ static void adapter_remove(pa_bluetooth_discovery *y, 
const char *path) {
 }
 }
 
-static void adapter_remove_all(pa_bluetooth_discovery *y) {
-pa_bluetooth_adapter *a;
-
-pa_assert(y);
-
-/* When this function is called all devices have already been freed */
-
-while ((a = pa_hashmap_steal_first(y-adapters)))
-adapter_free(a);
-}
-
 static void parse_device_property(pa_bluetooth_device *d, DBusMessageIter *i, 
bool is_property_change) {
 const char *key;
 DBusMessageIter variant_i;
@@ -915,7 +904,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, 
DBusMessage *m, void *us
 if (old_owner  *old_owner) {
 pa_log_debug(Bluetooth daemon disappeared);
 device_remove_all(y);
-adapter_remove_all(y);
+pa_hashmap_remove_all(y-adapters);
 y-objects_listed = false;
 }
 
@@ -1517,7 +1506,8 @@ pa_bluetooth_discovery* 
pa_bluetooth_discovery_get(pa_core *c) {
 y = pa_xnew0(pa_bluetooth_discovery, 1);
 PA_REFCNT_INIT(y);
 y-core = c;
-y-adapters = pa_hashmap_new(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func);
+y-adapters = pa_hashmap_new_full(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func, NULL,
+  (pa_free_cb_t) adapter_free);
 y-devices = pa_hashmap_new(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func);
 y-transports = pa_hashmap_new(pa_idxset_string_hash_func, 
pa_idxset_string_compare_func);
 PA_LLIST_HEAD_INIT(pa_dbus_pending, y-pending);
@@ -1598,10 +1588,8 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery 
*y) {
 pa_hashmap_free(y-devices);
 }
 
-if (y-adapters) {
-adapter_remove_all(y);
+if (y-adapters)
 pa_hashmap_free(y-adapters);
-}
 
 if (y-transports) {
 pa_assert(pa_hashmap_isempty(y-transports));
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 1/3] hashmap: Add a key+value iterator

2013-09-29 Thread Tanu Kaskinen
On Fri, 2013-09-20 at 17:27 +0530, Arun Raghavan wrote:
 ---
  src/pulsecore/hashmap.h | 4 
  1 file changed, 4 insertions(+)
 
 diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h
 index ae030ed..e42732a 100644
 --- a/src/pulsecore/hashmap.h
 +++ b/src/pulsecore/hashmap.h
 @@ -85,6 +85,10 @@ void* pa_hashmap_last(pa_hashmap *h);
  #define PA_HASHMAP_FOREACH(e, h, state) \
  for ((state) = NULL, (e) = pa_hashmap_iterate((h), (state), NULL); (e); 
 (e) = pa_hashmap_iterate((h), (state), NULL))
  
 +/* A macro to ease itration through all key, value pairs */
 +#define PA_HASHMAP_FOREACH_KV(k, e, h, state) \
 +for ((state) = NULL, (e) = pa_hashmap_iterate((h), (state), (const void 
 **) (k)); (e); (e) = pa_hashmap_iterate((h), (state), (const void **) (k)))
 +
  /* A macro to ease iteration through all entries, backwards */
  #define PA_HASHMAP_FOREACH_BACKWARDS(e, h, state) \
  for ((state) = NULL, (e) = pa_hashmap_iterate_backwards((h), (state), 
 NULL); (e); (e) = pa_hashmap_iterate_backwards((h), (state), NULL))

I applied this patch (I need the macro myself).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] default/system.pa: Do not load module-dbus-protocol

2013-09-30 Thread Tanu Kaskinen
On Fri, 2013-09-27 at 10:32 +0200, David Henningsson wrote:
 The author of this module, Tanu Kaskinen, has said that this module
 is not suitable for general use. Also, it is still causing crashes
 on card removal (see bug 69871).
 
 Qpaeq, and possibly other tools, use this module - but they can load
 the module manually if they still wish to use it.
 
 Signed-off-by: David Henningsson david.hennings...@canonical.com
 ---
  src/daemon/default.pa.in |7 ---
  src/daemon/system.pa.in  |5 -
  2 files changed, 12 deletions(-)
 
 diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
 index f50d929..4e77ae9 100755
 --- a/src/daemon/default.pa.in
 +++ b/src/daemon/default.pa.in
 @@ -171,13 +171,6 @@ load-module module-filter-heuristics
  load-module module-filter-apply
  ])dnl
  
 -ifelse(@HAVE_DBUS@, 1, [dnl
 -### Load DBus protocol
 -.ifexists module-dbus-protocol@PA_SOEXT@
 -load-module module-dbus-protocol
 -.endif
 -])dnl
 -
  ifelse(@HAVE_X11@, 1, [dnl
  # X11 modules should not be started from default.pa so that one daemon
  # can be shared by multiple sessions.
 diff --git a/src/daemon/system.pa.in b/src/daemon/system.pa.in
 index e881a12..6da880e 100755
 --- a/src/daemon/system.pa.in
 +++ b/src/daemon/system.pa.in
 @@ -52,11 +52,6 @@ load-module module-device-restore
  ### that look up the default sink/source get the right value
  load-module module-default-device-restore
  
 -.ifexists module-dbus-protocol@PA_SOEXT@
 -### If you want to allow TCP connections, set access to remote or 
 local,remote.
 -load-module module-dbus-protocol access=local
 -.endif
 -
  ### Automatically move streams to the default sink if the sink they are
  ### connected to dies, similar for sources
  load-module module-rescue-streams

Looks good to me.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Using nodes as the primary routing mechanism

2013-10-01 Thread Tanu Kaskinen
On Tue, 2013-10-01 at 13:12 +0200, David Henningsson wrote:
 On 09/23/2013 11:50 AM, Tanu Kaskinen wrote:
  Hi all,
  
  With nodes, there will be two routing layers: the higher-level node
  layer and the lower-level layer with sink inputs, sinks etc. The user
  will be able to still use the old move sink input interface, but what
  to do if the user tries to move a sink input that has a node to a sink
  that doesn't have a node? From the node layer point of view the sink
  input is not routed anywhere. Normally, if a sink input node is not
  routed anywhere, the routing system will connect the sink input to a
  private null sink (the null sink is dynamically created for the sink
  input, is not used for anything else, and doesn't have a node). However,
  in this case the sink input should not be connected to the null sink,
  but to the sink that the user specified. Respecting the user choice
  would require some extra complexity in the routing system.
  
  My proposal is to avoid this complexity by not allowing the user to
  route sink inputs with a node to sinks without a node, and also by
  completely preventing the user from controlling the routing of sink
  inputs that don't have a node. This would mean that we can map all valid
  sink input move requests to node operations, because both the sink input
  and the target sink would always have a node.
  
  A consequence of this proposal would be that I should implement a node
  for every sink and sink input in the current code base, including
  monitors and loopbacks etc., because otherwise there would be
  regressions for users. I was originally hoping that I could postpone
  that work for some later time (or in the best case, avoid that work
  completely). For example, I was planning not to implement nodes for the
  streams of module-loopback, but if I don't do that, then there will be a
  regression: it was previously possible for users to move the sink input
  and source output of module-loopback, but without nodes for the sink
  input and source output that wouldn't be possible. This wouldn't mean
  that every loopback would have to have nodes for the streams: loopbacks
  created by the routing system itself don't need nodes, but
  module-loopback instances loaded by users do need nodes.
  
  In conclusion: I'm proposing that nodes will be the primary routing
  mechanism, and the old non-node-aware routing interfaces will be
  implemented on top of the node interfaces, not side-by-side. Operations
  where the translation can't be done will simply fail. Regressions can be
  avoided by creating nodes for all entities that were user-routable
  before.
  
 
 Sorry for the late answer. The plan you're now suggesting is more in
 line with what I thought originally, and also, I think it is a better
 architecture.
 
 This also turns the node routing layer into a more complete graph as
 nodes can be both input and output nodes. If a sink is a node, then it
 would both be able to take audio from its sink inputs, as well as give
 audio to its monitors, i e, both an input and output node. Is that a
 correct understanding?

I did not plan to allow dual-direction nodes. If you want to represent
sinks as dual-direction nodes in a UI, I'm fine with adding information
to the nodes that allows the UI to do the correlation. I'm less
enthusiastic about doing the merging in the core. That said, I don't
have better arguments for this than that allowing dual-direction nodes
may cause complications, and I don't have good examples of such
complications at this point, so I may change my opinion.

I have bad example, though: what's the type and owner of the node, if
it covers both a sink and a monitor source? This is a bad example,
because the current system with a single type and owner is broken
anyway. A headset output on a typical phone can belong to two domains:
the pulse domain and a dsp domain. In the pulse domain the headset
output is owned by a port, but in the dsp domain there's no sink (the
audio comes directly from the cellular modem without pulseaudio ever
seeing the audio samples), and therefore no port either, so the node
type and owner is domain-dependent, that is, whoever wants to know the
type or owner must ask that through an interface to which the caller
provides the domain. It's not much of a leap then to make the type and
owner also direction-dependent: just add a direction parameter to the
pa_node_get_owner() function.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Using nodes as the primary routing mechanism

2013-10-01 Thread Tanu Kaskinen
On Tue, 2013-10-01 at 15:09 +0200, David Henningsson wrote:
 On 10/01/2013 02:51 PM, Tanu Kaskinen wrote:
  I did not plan to allow dual-direction nodes. If you want to represent
  sinks as dual-direction nodes in a UI, I'm fine with adding information
  to the nodes that allows the UI to do the correlation. I'm less
  enthusiastic about doing the merging in the core. That said, I don't
  have better arguments for this than that allowing dual-direction nodes
  may cause complications, and I don't have good examples of such
  complications at this point, so I may change my opinion.
 
 So a filter sink, which both consumes and produces audio data, would
 then have two nodes instead, one for input and one for output? Could you
 elaborate on this, i e, how these two nodes (belonging to the same
 filter sink) are connected to each other?

The filter sink creates a sink and a sink input as before, and requests
that a node is created for both. There's no need to explicitly connect
those two nodes - they will be connected by the fact that the filter
sink forwards the audio from the sink to its sink input, as it has
always done.

To allow a nice graph in a UI, the sink input node can indicate with an
extra pointer that it's really part of the same node as the sink node
and vice versa.

I do see the point of dual-direction nodes, and I'm starting to think
the idea should be tried out before committing to the solution of adding
the extra pointers between e.g. filter sinks and their sink inputs.

I added Janos to CC, in case he has some opinions about this.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 4/5] bluetooth: Remove device_remove_all()

2013-10-02 Thread Tanu Kaskinen
On Tue, 2013-10-01 at 10:43 -0300, João Paulo Rechi Vita wrote:
 Ack. Same question about testing applies here, and I should have made
 it more generic, actually: Do you have audio devices to be able to
 test these changes?

Devices aren't a problem (I have two A2DP/HFP headsets and one HFP-only
headset), but I haven't yet installed BlueZ 5. So, these patches have
not been tested.

What would you recommend as an easy-to-use GUI to replace the Gnome
Bluetooth applet, which will inevitably break if I replace BlueZ 4 with
BlueZ 5? (I don't have the newest Gnome version yet, and I'm not going
to install Gnome from source.)

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 3/5] bluetooth: Fix notifying about new devices

2013-10-02 Thread Tanu Kaskinen
On Tue, 2013-10-01 at 10:34 -0300, João Paulo Rechi Vita wrote:
 On Sun, Sep 29, 2013 at 12:49 PM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  Normally devices are created and their properties are parsed before
  creating any transports for the device, and the
  DEVICE_CONNECTION_CHANGED hook is fired when the first transport is
  created. It's possible, however, that a transport is created before
  the device that it belongs to, and in this case
  DEVICE_CONNECTION_CHANGED should be fired when the properties have
  been successfully parsed for the device. The old code didn't fire the
  hook at this situation, and this patch fixes that.
  ---
   src/modules/bluetooth/bluez5-util.c | 43 
  +
   1 file changed, 34 insertions(+), 9 deletions(-)
 
  diff --git a/src/modules/bluetooth/bluez5-util.c 
  b/src/modules/bluetooth/bluez5-util.c
  index eaff4b1..c7e934e 100644
  --- a/src/modules/bluetooth/bluez5-util.c
  +++ b/src/modules/bluetooth/bluez5-util.c
  @@ -438,14 +438,29 @@ static void device_remove(pa_bluetooth_discovery *y, 
  const char *path) {
   }
   }
 
  +static void set_device_info_valid(pa_bluetooth_device *device, int valid) {
  +bool old_any_connected;
  +
  +pa_assert(device);
  +pa_assert(valid == -1 || valid == 0 || valid == 1);
  +
  +if (valid == device-device_info_valid)
  +return;
  +
  +old_any_connected = 
  pa_bluetooth_device_any_transport_connected(device);
  +device-device_info_valid = valid;
  +
  +if (pa_bluetooth_device_any_transport_connected(device) != 
  old_any_connected)
  +
  pa_hook_fire(device-discovery-hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED],
   device);
  +}
  +
 
 I like the idea of having a helper function here. But wouldn't be
 better to factor the occurences of device-device_info_valid = X
 into set_device_info_valid() in one commit and the
 DEVICE_CONNECTION_CHANGED hook fire, together with the respective
 checks, in a separate commit? I think they are two different
 modifications, so the would belong to separate commits, making the
 history cleaner and easier to read. If for some reason you don't want
 to separate them it's ok for me (just please explain me why you think
 so).

Good point, I'll update the patches.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Best Case Latency

2013-10-03 Thread Tanu Kaskinen
On Thu, 2013-10-03 at 02:33 +1000, Patrick Shirkey wrote:
 On Thu, October 3, 2013 12:14 am, Tanu Kaskinen wrote:
  On Tue, 2013-10-01 at 00:38 +1000, Patrick Shirkey wrote:
  On Sat, September 28, 2013 3:12 am, Patrick Shirkey wrote:
  
   On Sat, September 28, 2013 12:53 am, Tanu Kaskinen wrote:
   I don't remember if the alsa compatibility layer forwards the
   stream under/overrun notifications to the alsa application - IIRC
  there
   were problems when those were reported and there were different
   problems
   when those were not reported, and I don't remember what the current
   code
   does.
  
 
  This seems like it would be a good place to verify.
 
  Looking at the pulse alsa plugin source, it seems that stream overflow
  events (the recording direction) are not reported. Underflows (the
  playback direction) are reported by default (configurable in asoundrc).
  Overflows are pretty unlikely, since the maximum stream buffer length
  appears to be configured to 4 MB.
 
 
 I see the following sprinkled in /var/log/messages
 
 Sep 30 12:19:02 xxx pulseaudio[28845]: [pulseaudio] ratelimit.c: 1997
 events suppressed
 Sep 30 12:19:02 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 
 snip
 
 Sep 30 21:40:04 xxx pulseaudio[28845]: [jack-source] ratelimit.c: 41
 events suppressed
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Sep 30 21:40:04 xxx pulseaudio[28845]: [jack-source] asyncq.c: q overrun,
 queuing locally
 
 snip
 
 Oct  1 09:53:30 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] ratelimit.c: 2291
 events suppressed
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
 queuing locally
 Oct  1 10:01:42 xxx pulseaudio[28845]: [pulseaudio] ratelimit.c: 2321
 events suppressed

That doesn't look healthy. The message is printed when
pa_asyncmsgq_post() is called and the message queue is full. The message
queue can store 256 messages before this starts to happen, so some queue
consumer is having serious trouble keeping up with the producer. It
would be nice to know which pa_asyncmsgq_post() call this is (you could
set a breakpoint on the line that prints q overrun, and then get a
backtrace).

  Also does anyone know why the PA Stream Buffer is hovering around 10ms?
  That number doesn't appear to match the 64 frames/period that JACK is
  set
  to so it would be useful to verify that it is calculated correctly
  and/or
  if it can be lowered.
 
  You can see in the pulseaudio log, when a stream is created, what
  memblockq parameters the client requests and what are the final
  parameters.
 
  According to pcm_pulse.c, the requested stream buffer length (tlength in
  the memblockq parameters) should be
 
  io-buffer_size * pcm-frame_size;
 
  I don't know how io-buffer_size is calculated, but I'd expect that to
  be based on the period number and size provided by you (number of
  periods * period size).
 
  2 (periods) * 64 (frames per period) * 4 (bytes per frame) / 48
  (frames/millisecond) equals 10.67 milliseconds, so it looks like the
  reported latency of 10 milliseconds for playback is what you'd expect.
 
 
 Thanks

Re: [pulseaudio-discuss] Best Case Latency

2013-10-03 Thread Tanu Kaskinen
On Thu, 2013-10-03 at 18:20 +1000, Patrick Shirkey wrote:
 On Thu, October 3, 2013 5:14 pm, Tanu Kaskinen wrote:
  On Thu, 2013-10-03 at 02:33 +1000, Patrick Shirkey wrote:
  I see the following sprinkled in /var/log/messages
 
  Sep 30 12:19:02 xxx pulseaudio[28845]: [pulseaudio] ratelimit.c: 1997
  events suppressed
  Sep 30 12:19:02 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
 
  snip
 
  Sep 30 21:40:04 xxx pulseaudio[28845]: [jack-source] ratelimit.c: 41
  events suppressed
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Sep 30 21:40:04 xxx pulseaudio[28845]: [jack-source] asyncq.c: q
  overrun,
  queuing locally
 
  snip
 
  Oct  1 09:53:30 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] ratelimit.c: 2291
  events suppressed
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:20 xxx pulseaudio[28845]: [pulseaudio] asyncq.c: q overrun,
  queuing locally
  Oct  1 10:01:42 xxx pulseaudio[28845]: [pulseaudio] ratelimit.c: 2321
  events suppressed
 
  That doesn't look healthy. The message is printed when
  pa_asyncmsgq_post() is called and the message queue is full. The message
  queue can store 256 messages before this starts to happen, so some queue
  consumer is having serious trouble keeping up with the producer. It
  would be nice to know which pa_asyncmsgq_post() call this is (you could
  set a breakpoint on the line that prints q overrun, and then get a
  backtrace).
 
 
 Sorry, if this is dense but how do I set a breakpoint on this line in PA
 while it is running?

Have you used gdb before? You can either start pulseaudio in gdb, or
connect gdb to a running pulseaudio instance. The latter can be done
with command gdb pulseaudio $PID_OF_RUNNING_PULSEAUDIO. See man gdb.
Either approach requires debug symbols to be available. If building from
source is not a problem, then I recommend building and installing[1] the
latest pulseaudio from git, which is the distro independent way of
getting the debug symbols.

Once you're in the gdb prompt, run this command (the line number refers
to the current code in the master branch, adjust the line number as
necessary if you use some other version):

break async.c:211

If you connected to a running pulseaudio, continue the execution with
this command:

continue

If you started pulseaudio in gdb, start the execution with this command:

run

[1] 
http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/PulseAudioFromGit/

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH] simple: Improve pa_simple_read() documentation

2013-10-03 Thread Tanu Kaskinen
There was a question in IRC about whether pa_simple_read() blocks or
not. It's already documented on the simple API overview page, but it's
good to say it also in the function reference. As a bonus, I added
some words about the error handling as well.
---
 src/pulse/simple.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/pulse/simple.h b/src/pulse/simple.h
index 0fab8ee..4a8162b 100644
--- a/src/pulse/simple.h
+++ b/src/pulse/simple.h
@@ -137,7 +137,10 @@ int pa_simple_write(pa_simple *s, const void *data, size_t 
bytes, int *error);
 /** Wait until all data already written is played by the daemon. */
 int pa_simple_drain(pa_simple *s, int *error);
 
-/** Read some data from the server. */
+/** Read some data from the server. This function blocks until \a bytes amount
+ * of data has been received from the server, or until an error occurs.
+ * Returns a negative value on failure. If \a error is non-NULL, the error code
+ * is stored in it. */
 int pa_simple_read(pa_simple *s, void *data, size_t bytes, int *error);
 
 /** Return the playback latency. */
-- 
1.8.4.rc3

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] connect pulse to jack - headless

2013-10-04 Thread Tanu Kaskinen
On Fri, 2013-10-04 at 19:15 +1000, Patrick Shirkey wrote:
 Hi,
 
 Can anyone point me to instructions for connecting pulse to jack in
 headless mode?
 
 I can run jack like this:
 
 eval dbus-launch --auto-syntax
 
 export
 DBUS_SESSION_BUS_ADDRESS='unix:abstract=/tmp/dbus-UBmwIyooQF,guid=86f4d04e50ca1406a4b7f215524db419'
 DBUS_SESSION_BUS_PID=6293; jackd -d alsa -r48000 -p64 -n2
 
 But how do I get PA to run and connect to the same dbus session?
 
 pulseaudio -D runs but does not connect to jack

Having DBUS_SESSION_BUS_ADDRESS set to the same value in pulseaudio's
environment should work.

I don't know if DBUS_SESSION_BUS_PID is important at all, but it
shouldn't hurt to set that variable too.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH v2] simple: Improve pa_simple_read() documentation

2013-10-04 Thread Tanu Kaskinen
From: Tanu Kaskinen ta...@iki.fi

There was a question in IRC about whether pa_simple_read() blocks or
not. It's already documented on the simple API overview page, but it's
good to say it also in the function reference. As a bonus, I added
some additional details to the documentation too.
---
 src/pulse/simple.h | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/pulse/simple.h b/src/pulse/simple.h
index 0fab8ee..2224766 100644
--- a/src/pulse/simple.h
+++ b/src/pulse/simple.h
@@ -137,8 +137,17 @@ int pa_simple_write(pa_simple *s, const void *data, size_t 
bytes, int *error);
 /** Wait until all data already written is played by the daemon. */
 int pa_simple_drain(pa_simple *s, int *error);
 
-/** Read some data from the server. */
-int pa_simple_read(pa_simple *s, void *data, size_t bytes, int *error);
+/** Read some data from the server. This function blocks until \a bytes amount
+ * of data has been received from the server, or until an error occurs.
+ * Returns a negative value on failure. */
+int pa_simple_read(
+pa_simple *s, /** The connection object. */
+void *data,   /** A pointer to a buffer. */
+size_t bytes, /** The number of bytes to read. */
+int *error
+/** A pointer where the error code is stored when the function returns
+ * a negative value. It is OK to pass NULL here. */
+);
 
 /** Return the playback latency. */
 pa_usec_t pa_simple_get_latency(pa_simple *s, int *error);
-- 
1.8.1.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 2/2] tunnel-sink-new: use *_new-style for thread_mq init

2013-10-04 Thread Tanu Kaskinen
On Mon, 2013-09-16 at 13:06 +0200, Alexander Couzens wrote:
 @@ -528,11 +529,14 @@ void pa__done(pa_module *m) {
  pa_sink_unlink(u-sink);
  
  if (u-thread) {
 -pa_asyncmsgq_send(u-thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 
 0, NULL);
 +pa_asyncmsgq_send(u-thread_mq-inq, NULL, PA_MESSAGE_SHUTDOWN, 
 NULL, 0, NULL);
  pa_thread_free(u-thread);
  }
  
 -pa_thread_mq_done(u-thread_mq);
 +if (u-thread_mq) {
 +pa_thread_mq_done(u-thread_mq);
 +pa_xfree(u-thread);

This should be u-thread_mq, not u-thread.

Otherwise looks good, I pushed now this and the other (1/2) patch.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Best Case Latency

2013-10-07 Thread Tanu Kaskinen

On Fri, 2013-10-04 at 21:49 +1000, Patrick Shirkey wrote:
 On Thu, October 3, 2013 11:41 pm, Thomas Martitz wrote:
  Am 03.10.2013 10:20, schrieb Patrick Shirkey:
  On Thu, October 3, 2013 5:14 pm, Tanu Kaskinen wrote:
 
  That doesn't look healthy. The message is printed when
  pa_asyncmsgq_post() is called and the message queue is full. The
  message
  queue can store 256 messages before this starts to happen, so some
  queue
  consumer is having serious trouble keeping up with the producer. It
  would be nice to know which pa_asyncmsgq_post() call this is (you could
  set a breakpoint on the line that prints q overrun, and then get a
  backtrace).
 
  Sorry, if this is dense but how do I set a breakpoint on this line in PA
  while it is running?
 
  $ gdb --pid=$(pidof pulseaudio)
 
  If you're on debian you need to install debug symbols ($ sudo apt-get
  install pulseaudio-dbg). For other distros I can't help. Compiling from
  source in debug mode of course also works.
 
 
 Thanks. FYI, installing pulseaudio-dbg hosed my NVIDIA video driver
 which was a bit confusing.
 
 Looking at /var/log/messages I spotted this when starting PA:
 
 
 Oct  4 17:30:49 xxx pulseaudio[6571]: [pulseaudio] sink.c: Default and
 alternate sample rates are the same.
 Oct  4 17:30:49 xxx pulseaudio[6571]: [pulseaudio] module-jack-sink.c:
 JACK error Cannot use real-time scheduling (RR/5)(1: Operation not
 permitted)
 Oct  4 17:30:49 xxx pulseaudio[6571]: [pulseaudio] module-jack-sink.c:
 JACK error JackClient::AcquireSelfRealTime error
 Oct  4 17:30:49 xxx pulseaudio[6571]: [pulseaudio] source.c: Default and
 alternate sample rates are the same.
 Oct  4 17:30:49 xxx pulseaudio[6571]: [pulseaudio] module-jack-source.c:
 JACK error Cannot use real-time scheduling (RR/5)(1: Operation not
 permitted)
 Oct  4 17:30:49 xxx pulseaudio[6571]: [pulseaudio] module-jack-source.c:
 JACK error JackClient::AcquireSelfRealTime error
 
 
 - Not sure why it is being printed twice.

Once for the sink and once for the source.

 I have enabled realtime in
 /etc/pulse/daemon.conf and jack is running in realtime mode so not sure
 why PA is unhappy. It could be a bug that is already fixed though.

It's not really PA that is unhappy. The JACK error foo messages come
from libjack. If you are able to run jackd with RT scheduling, under the
same user that you're running pulseaudio, I don't know what could be the
problem. Pulseaudio limits the realtime priority that it can use
(configured with the rlimit-rtprio option in daemon.conf), but if I
understand the log message correctly, libjack tries to use priority 5,
which shouldn't be a problem, because the default priority that
pulseaudio limits itself is 9.

 - I'm running pulseaudio 4.0 in debian  pulseaudio-dbg:amd64/unstable
 4.0-6+b1
 
 - Here's the backtrace based on the line number that Tanu provided. Not
 sure if I nailed it though.
 
 (gdb) break asyncq.c:211
 Breakpoint 1 at 0x7f4d4572ff90: file pulsecore/asyncq.c, line 211.
 (gdb) continue
 Continuing.
 [Switching to Thread 0x7f4d39b2b700 (LWP 6686)]
 
 Breakpoint 1, 0x7f4d4572ff90 in pa_asyncq_post () from
 /usr/lib/libpulsecore-4.0.so
 (gdb) bt
 #0  0x7f4d4572ff90 in pa_asyncq_post () from /usr/lib/libpulsecore-4.0.so
 #1  0x7f4d4572ee7b in pa_asyncmsgq_post () at pulsecore/asyncmsgq.c:137
 #2  0x7f4d3bf374f3 in source_output_push_cb () at
 pulsecore/protocol-native.c:1832
 #3  0x7f4d4576d3b3 in pa_source_output_push () at
 pulsecore/source-output.c:822
 #4  0x7f4d45773e5b in pa_source_post () at pulsecore/source.c:935
 #5  0x7f4d39baf820 in source_process_msg () at
 modules/jack/module-jack-source.c:115
 #6  0x7f4d4574d084 in asyncmsgq_read_work () from
 /usr/lib/libpulsecore-4.0.so
 #7  0x7f4d4574c607 in pa_rtpoll_run () from /usr/lib/libpulsecore-4.0.so
 #8  0x7f4d39baf953 in thread_func () at
 modules/jack/module-jack-source.c:201
 #9  0x7f4d454f5d08 in ?? () from
 /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-4.0.so
 #10 0x7f4d449fae0e in start_thread () from
 /lib/x86_64-linux-gnu/libpthread.so.0
 #11 0x7f4d4402593d in clone () from /lib/x86_64-linux-gnu/libc.so.6

Ok, so this happens when the native protocol tries to send a block of
audio from the jack source thread to the main thread. My guess is that
the main thread is not getting enough CPU time to deal with all the
incoming audio (it's not RT scheduled).

This could very well cause growing latency. If the jack source pushes
audio blocks to the message queue faster than the main thread reads
those blocks, then that message queue becomes a significant (and
constantly growing?) audio buffer.

What to do? I don't know. Currently there's no upper limit for how long
the message queue can grow (so this is effectively also a memory leak
problem), and no way to query the queue length. Even if there was a
maximum length for the queue, what should be done if that maximum length
is exceeded? Perhaps the native protocol should

Re: [pulseaudio-discuss] [PATCH v5 39/39] bluetooth: Revive module-bluetooth-discover

2013-10-08 Thread Tanu Kaskinen
On Tue, 2013-10-08 at 11:19 -0300, João Paulo Rechi Vita wrote:
 On Sun, Sep 29, 2013 at 1:39 PM, Tanu Kaskinen
 tanu.kaski...@linux.intel.com wrote:
  On Tue, 2013-09-24 at 19:45 -0300, jprv...@gmail.com wrote:
  +void pa__done(pa_module* m) {
  +struct userdata *u;
  +
  +pa_assert(m);
  +
  +if (!(u = m-userdata))
  +return;
  +
  +if (u-bluez5_module)
  +pa_module_unload(m-core, u-bluez5_module, true);
  +
  +if (u-bluez4_module)
  +pa_module_unload(m-core, u-bluez4_module, true);
 
  This crashes when shutting down the daemon, because when the daemon
  unloads all modules, module-bluez*-discover gets unloaded before
  module-bluetooth-discover, so the y-bluez5_module and u-bluez4_module
  pointers become stale. I see two ways of fixing this: add a hook that is
  fired when modules are unloaded and use that hook in
  module-bluetooth-discover to drop the reference to the unloaded module,
  or unload module-bluetooth-discover immediately after loading
  module-bluez5-discover and module-bluez4-discover. The second solution
  is of course much simpler, but I proposed that already earlier, and you
  didn't like that.
 
 
 It doesn't crash (and that's what I'm experiencing here) because
 pa_module_unload() will look for that module pointer in its internal
 hash of modules before trying to unload it. I agree we are left with a
 stale pointer, but as long as we don't dereference it, we should be
 fine.

pa_module_unload() dereferences the pointer already before

if (!(m = pa_idxset_remove_by_data(c-modules, m, NULL)))
return;

which I think you are referring to as the safeguard. The line that
crashes is this:

if (m-core-disallow_module_loading  !force)

It doesn't crash always, because m-core is a random address that may or
may not be possible to dereference (it was 0 when I debugged this).

When this line doesn't crash, I get an assertion about pa_core.shared
not being empty when pa_core is freed. I hope that's another symptom of
this same bug (I looked at the code and the management of pa_core.shared
seemed correct).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] sndfile-util: fix format for 24bit depth wav files

2013-10-09 Thread Tanu Kaskinen
On Mon, 2013-10-07 at 09:43 -0700, Kiran Krishnappa wrote:
 PA_SAMPLE_24NE generated in pa_sndfile_read_sample_spec is not
 handled in pa_sndfile_readf_function. paplay used to get aborted
 for 24bit depth wav files

How does paplay now behave? I suppose it still isn't able to play 24bit
files, so does it exit cleanly?

 ---
  src/pulsecore/sndfile-util.c |3 +++
  1 file changed, 3 insertions(+)
 
 diff --git a/src/pulsecore/sndfile-util.c b/src/pulsecore/sndfile-util.c
 index 0820ee4..46689af 100644
 --- a/src/pulsecore/sndfile-util.c
 +++ b/src/pulsecore/sndfile-util.c
 @@ -386,6 +386,9 @@ pa_sndfile_readf_t pa_sndfile_readf_function(const 
 pa_sample_spec *ss) {
  case PA_SAMPLE_ALAW:
  return NULL;
  
 +case PA_SAMPLE_S24NE:
 +return NULL;


I'd prefer the case to be grouped together with ULAW and ALAW, since in
all of the three cases the end result is the same: return NULL.

Also, this same problem is in pa_sndfile_writef_function(). In the bug
report there is a parecord command that triggers a crash in
pa_sndfile_writef_function(). If you could fix also
pa_sndfile_writef_function() and test how parecord behaves after that,
your patch will go in sooner (if you don't do this, I'll do the changes
and testing myself when I have time).

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] sndfile-util: fix format for 24bit depth wav files

2013-10-12 Thread Tanu Kaskinen
On Thu, 2013-10-10 at 20:01 -0700, Kiran Krishnappa wrote:
 Hi,
 
 I tested both paplay and parecord for 24bit files. Looks to be working fine
 now.

How can it be working fine, if the read/write functions don't exist for
24-bit files?

I looked at the code, and it seems that if the read/write functions
haven't been set, pacat treats the files as raw PCM data. This is not
good, because the user requested wav files, not raw files. If wav files
are treated as raw files, then the wav header will be played to the
speakers, and when recording, the wav header will be missing from the
output file. If getting the read/write function fails, pacat should
print an error message and exit.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 0/2] Conditional defining of _FORTIFY_SOURCE

2013-10-12 Thread Tanu Kaskinen
I switched to Fedora, and the system headers complained to me about
defining _FORTIFY_SOURCE when compiling without optimizations. I
don't know how other Fedora users have managed to live with this all
these years...

Tanu Kaskinen (2):
  build-sys: Don't define _FORTIFY_SOURCE when building with -O0
  build-sys: Print CPPFLAGS in configure

 configure.ac | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

-- 
1.8.3.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 1/2] build-sys: Don't define _FORTIFY_SOURCE when building with -O0

2013-10-12 Thread Tanu Kaskinen
---
 configure.ac | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 42cb8b8..e2465e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -165,12 +165,17 @@ esac
  Compiler flags 
 
 AX_APPEND_COMPILE_FLAGS(
-[-Wall -W -Wextra -pipe -Wno-long-long -Wno-overlength-strings 
-Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare 
-Wformat-security -Wmissing-include-dirs -Wformat-nonliteral 
-Wold-style-definition -Wpointer-arith -Winit-self 
-Wdeclaration-after-statement -Wfloat-equal -Wmissing-prototypes 
-Wstrict-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn 
-Wshadow -Wendif-labels -Wcast-align -Wstrict-aliasing -Wwrite-strings 
-Wno-unused-parameter -ffast-math -Wp,-D_FORTIFY_SOURCE=2 -fno-common 
-fdiagnostics-show-option],
+[-Wall -W -Wextra -pipe -Wno-long-long -Wno-overlength-strings 
-Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare 
-Wformat-security -Wmissing-include-dirs -Wformat-nonliteral 
-Wold-style-definition -Wpointer-arith -Winit-self 
-Wdeclaration-after-statement -Wfloat-equal -Wmissing-prototypes 
-Wstrict-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn 
-Wshadow -Wendif-labels -Wcast-align -Wstrict-aliasing -Wwrite-strings 
-Wno-unused-parameter -ffast-math -fno-common -fdiagnostics-show-option],
 [], [-pedantic -Werror])
 
 # Only enable fastpath asserts when doing a debug build, e.g. from 
bootstrap.sh.
 AS_CASE([ $CFLAGS ], [* -O0 *], [], [AX_APPEND_FLAG([-DFASTPATH], 
[CPPFLAGS])])
 
+# Only set _FORTIFY_SOURCE when optimizations are enabled. If optimizations
+# are disabled, _FORTIFY_SOURCE doesn't do anything, and causes tons of
+# warnings during compiling on some distributions (at least Fedora).
+AS_CASE([ $CFLAGS ], [* -O0 *], [], 
[AX_APPEND_FLAG([-D_FORTIFY_SOURCE=2], [CPPFLAGS])])
+
 
  Linker flags 
 
-- 
1.8.3.1

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] sndfile-util: fix format for 24bit depth wav files

2013-10-12 Thread Tanu Kaskinen
[Added pulseaudio-discuss back to CC.]

On Sat, 2013-10-12 at 09:31 -0700, Kiran Krishnappa wrote:
 Ok. I got it. I didn't think much about wav file header. Just played 24 bit
 file and also recorded 24 bit file, there were no aborts and when I played
 24bit file, it couldn't make out difference. I will understand wav format
 and sndfile API's and try to give proper patch.

Actually, it looks like I was wrong. I assumed that falling back to
sf_read_raw() and sf_write_raw() would mean that the wav header wouldn't
be handled correctly, but after reading the API documentation for those
functions, I believe that was an invalid assumption. So, your patch
should be fine. I'll apply it.

-- 
Tanu

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


<    4   5   6   7   8   9   10   11   12   13   >