]> code.delx.au - pulseaudio/commitdiff
Merge commit 'coling/master'
authorLennart Poettering <lennart@poettering.net>
Tue, 30 Sep 2008 23:52:14 +0000 (01:52 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 30 Sep 2008 23:52:14 +0000 (01:52 +0200)
67 files changed:
configure.ac
man/pulse-client.conf.5.xml.in
man/pulse-daemon.conf.5.xml.in
po/LINGUAS
po/POTFILES.in
po/fr.po [new file with mode: 0644]
po/sv.po [new file with mode: 0644]
src/.gitignore
src/Makefile.am
src/daemon/daemon-conf.c
src/daemon/daemon-conf.h
src/daemon/daemon.conf.in
src/daemon/default.pa.in
src/daemon/main.c
src/daemon/system.pa.in
src/modules/alsa-util.c
src/modules/bluetooth/Makefile [new symlink]
src/modules/bluetooth/ipc.c [new file with mode: 0644]
src/modules/bluetooth/ipc.h [new file with mode: 0644]
src/modules/bluetooth/module-bluetooth-device.c [new file with mode: 0644]
src/modules/bluetooth/module-bluetooth-discover.c [new file with mode: 0644]
src/modules/bluetooth/module-bluetooth-proximity.c [moved from src/modules/module-bt-proximity.c with 99% similarity]
src/modules/bluetooth/proximity-helper.c [moved from src/modules/bt-proximity-helper.c with 100% similarity]
src/modules/bluetooth/rtp.h [new file with mode: 0644]
src/modules/bluetooth/sbc.c [new file with mode: 0644]
src/modules/bluetooth/sbc.h [new file with mode: 0644]
src/modules/bluetooth/sbc_math.h [new file with mode: 0644]
src/modules/bluetooth/sbc_tables.h [new file with mode: 0644]
src/modules/gconf/Makefile [changed from file to symlink]
src/modules/module-alsa-sink.c
src/modules/module-alsa-source.c
src/modules/module-protocol-stub.c
src/modules/module-stream-restore.c
src/modules/rtp/Makefile [changed from file to symlink]
src/pulse/client-conf.c
src/pulse/client-conf.h
src/pulse/client.conf.in
src/pulse/context.c
src/pulse/stream.c
src/pulsecore/conf-parser.c
src/pulsecore/conf-parser.h
src/pulsecore/core-util.c
src/pulsecore/core-util.h
src/pulsecore/core.c
src/pulsecore/core.h
src/pulsecore/idxset.c
src/pulsecore/lock-autospawn.c [moved from src/pulse/lock-autospawn.c with 100% similarity]
src/pulsecore/lock-autospawn.h [moved from src/pulse/lock-autospawn.h with 100% similarity]
src/pulsecore/memblock.c
src/pulsecore/memblock.h
src/pulsecore/prioq.c [new file with mode: 0644]
src/pulsecore/prioq.h [new file with mode: 0644]
src/pulsecore/proplist-util.c
src/pulsecore/protocol-native.c
src/pulsecore/resampler.c
src/pulsecore/resampler.h
src/pulsecore/sink-input.c
src/pulsecore/source-output.c
src/tests/envelope-test.c
src/tests/lock-autospawn-test.c
src/tests/mcalign-test.c
src/tests/memblock-test.c
src/tests/memblockq-test.c
src/tests/mix-test.c
src/tests/prioq-test.c [new file with mode: 0644]
src/tests/remix-test.c
src/tests/resampler-test.c

index 4a560b12db8ad6ee679f8837902a4bb8cf525f40..3c3550fbfc9839b7fbd62963db4b9fa34899730b 100644 (file)
@@ -40,11 +40,11 @@ AC_SUBST(PA_PROTOCOL_VERSION, 14)
 
 # The stable ABI for client applications, for the version info x:y:z
 # always will hold y=z
-AC_SUBST(LIBPULSE_VERSION_INFO, [5:0:5])
+AC_SUBST(LIBPULSE_VERSION_INFO, [6:0:6])
 
 # A simplified, synchronous, ABI-stable interface for client
 # applications, for the version info x:y:z always will hold y=z
-AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:1:0])
+AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [0:2:0])
 
 # The ABI-stable network browsing interface for client applications,
 # for the version info x:y:z always will hold y=z
@@ -52,12 +52,12 @@ AC_SUBST(LIBPULSE_BROWSE_VERSION_INFO, [1:1:1])
 
 # The ABI-stable GLib adapter for client applications, for the version
 # info x:y:z always will hold y=z
-AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:3:0])
+AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:4:0])
 
 # An internally used, ABI-unstable library that contains the
 # PulseAudio core, SONAMEs are bumped on every release, version info
 # suffix will always be 0:0
-AC_SUBST(LIBPULSECORE_VERSION_INFO, [6:0:0])
+AC_SUBST(LIBPULSECORE_VERSION_INFO, [7:0:0])
 
 AC_CANONICAL_HOST
 AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])
index ae8de1f80a23026212b09d3348177a95d38f45d4..26e389081a797040b3814673e2f3c0315df3e9d8 100644 (file)
@@ -31,15 +31,15 @@ USA.
 
   <description>
     <p>The PulseAudio client library reads configuration directives from
-    a file <file>~/.pulse/client.conf</file> on startup, and when that
+    a file <file>~/.pulse/client.conf</file> on startup and when that
     file doesn't exist from
     <file>@pulseconfdir@/client.conf</file>.</p>
 
     <p>The configuration file is a simple collection of variable
     declarations. If the configuration file parser encounters either ;
-    or # for it ignores the rest of the line until its end.</p>
+    or # it ignores the rest of the line until its end.</p>
 
-    <p>For the settings that take a boolean argument, the values
+    <p>For the settings that take a boolean argument the values
     <opt>true</opt>, <opt>yes</opt>, <opt>on</opt> and <opt>1</opt>
     are equivalent, resp. <opt>false</opt>, <opt>no</opt>,
     <opt>off</opt>, <opt>0</opt>.</p>
@@ -69,7 +69,7 @@ USA.
 
     <option>
       <p><opt>autospawn=</opt> Autospawn a PulseAudio daemon when
-      needed. Takes a boolean value, defaults to "no".</p>
+      needed. Takes a boolean value, defaults to "yes".</p>
     </option>
 
     <option>
@@ -81,7 +81,7 @@ USA.
     <option>
       <p><opt>extra-arguments=</opt> Extra arguments to pass to the
       PulseAudio daemon when autospawning. Defaults to
-      <opt>--log-target=syslog --exit-idle-time=5</opt>
+      <opt>--log-target=syslog</opt>
       </p>
     </option>
 
@@ -97,6 +97,15 @@ USA.
       <opt>no</opt>.</p>
     </option>
 
+    <option>
+      <p><opt>shm-size-bytes=</opt> Sets the shared memory segment
+      size for clients, in bytes. If left unspecified or is set to 0
+      it will default to some system-specific default, usually 64
+      MiB. Please note that usually there is no need to change this
+      value, unless you are running an OS kernel that does not do
+      memory overcommit.</p>
+    </option>
+
   </section>
 
   <section name="Authors">
index c2eefaa56a6552b7afc8b3af545aadcb05facb32..a516ee3f3c40d8669306e66a427af7bf5e33f734 100644 (file)
@@ -31,7 +31,7 @@ USA.
 
   <description>
     <p>The PulseAudio sound server reads configuration directives from
-    a file <file>~/.pulse/daemon.conf</file> on startup, and when that
+    a file <file>~/.pulse/daemon.conf</file> on startup and when that
     file doesn't exist from
     <file>@pulseconfdir@/daemon.conf</file>. Please note that the
     server also reads a configuration script on startup
@@ -40,9 +40,9 @@ USA.
 
     <p>The configuration file is a simple collection of variable
     declarations. If the configuration file parser encounters either ;
-    or # for it ignores the rest of the line until its end.</p>
+    or # it ignores the rest of the line until its end.</p>
 
-    <p>For the settings that take a boolean argument, the values
+    <p>For the settings that take a boolean argument the values
     <opt>true</opt>, <opt>yes</opt>, <opt>on</opt> and <opt>1</opt>
     are equivalent, resp. <opt>false</opt>, <opt>no</opt>,
     <opt>off</opt>, <opt>0</opt>.</p>
@@ -76,6 +76,11 @@ USA.
       option takes precedence.</p>
     </option>
 
+    <option>
+      <p><opt>disallow-exit=</opt> Disallow exit on user
+      request. Defaults to <opt>no</opt>.</p>
+    </option>
+
     <option>
       <p><opt>resample-method=</opt> The resampling algorithm to
       use. Use one of <opt>src-sinc-best-quality</opt>,
@@ -105,6 +110,16 @@ USA.
       matching only.</p>
     </option>
 
+    <option>
+      <p><opt>disable-lfe-remixing=</opt> When upmixing or downmixing
+      ignore LFE channels. When this option is on the output LFE
+      channel will only get a signal when an input LFE channel is
+      available as well. If no input LFE channel is available the
+      output LFE channel will always be 0. If no output LFE channel is
+      available the signal on the input LFE channel will be
+      ignored. Defaults to "on".</p>
+    </option>
+
     <option>
       <p><opt>use-pid-file=</opt> Create a PID file in
       <file>/tmp/pulse-$USER/pid</file>. Of this is enabled you may
@@ -141,6 +156,15 @@ USA.
       argument takes precedence.</p>
     </option>
 
+    <option>
+      <p><opt>shm-size-bytes=</opt> Sets the shared memory segment
+      size for the daemon, in bytes. If left unspecified or is set to 0
+      it will default to some system-specific default, usually 64
+      MiB. Please note that usually there is no need to change this
+      value, unless you are running an OS kernel that does not do
+      memory overcommit.</p>
+    </option>
+
   </section>
 
   <section name="Scheduling">
@@ -230,9 +254,17 @@ USA.
       default script file. The default behaviour is to load
       <file>~/.pulse/default.pa</file>, and if that file does not
       exist fall back to the system wide installed version
-      <file>@pulseconfdir@/default.pa</file>. If <opt>-n</opt> is
-      passed on the command line the default configuration script is
-      ignored.</p>
+      <file>@pulseconfdir@/default.pa</file>. If run in system-wide
+      mode the file <file>@pulseconfdir@/system.pa</file> is used
+      instead. If <opt>-n</opt> is passed on the command line
+      or <opt>default-script-file=</opt> is disabled the default
+      configuration script is ignored.</p>
+    </option>
+
+    <option>
+      <p><opt>default-script-file=</opt> Load the default
+      configuration script file as specified
+      in <opt>default-script-file=</opt>. Defaults to "yes".</p>
     </option>
 
   </section>
@@ -271,6 +303,9 @@ USA.
     <option>
       <p><opt>rlimit-as</opt> Defaults to -1.</p>
     </option>
+    <option>
+      <p><opt>rlimit-rss</opt> Defaults to -1.</p>
+    </option>
     <option>
       <p><opt>rlimit-core</opt> Defaults to -1.</p>
     </option>
@@ -289,6 +324,15 @@ USA.
     <option>
       <p><opt>rlimit-nproc</opt> Defaults to -1.</p>
     </option>
+    <option>
+      <p><opt>rlimit-locks</opt> Defaults to -1.</p>
+    </option>
+    <option>
+      <p><opt>rlimit-sigpending</opt> Defaults to -1.</p>
+    </option>
+    <option>
+      <p><opt>rlimit-msgqueue</opt> Defaults to -1.</p>
+    </option>
     <option>
       <p><opt>rlimit-memlock</opt> Defaults to 16 KiB. Please note
       that the JACK client libraries may require more locked
@@ -307,6 +351,9 @@ USA.
       <opt>realtime-scheduling</opt> is enabled. The JACK client
       libraries require a real-time prority of 9 by default. </p>
     </option>
+    <option>
+      <p><opt>rlimit-rttime</opt> Defaults to 1000000.</p>
+    </option>
 
   </section>
 
index 7673daa944ec436c99a79a259b7c661a54b081e6..e3f5e8f5df5b5e75d5dda749b9fa5b45cf87d20e 100644 (file)
@@ -1 +1,4 @@
 de
+el
+fr
+sv
index fa28b6a7a4ab63cac4614941c8cd6d09c148c8f9..6efb1d089d590fcbb4a3cbf0d6c47ee0f33852ec 100644 (file)
@@ -190,3 +190,4 @@ src/utils/padsp.c
 src/utils/pax11publish.c
 src/utils/pacmd.c
 src/utils/paplay.c
+src/pulsecore/lock-autospawn.c
diff --git a/po/fr.po b/po/fr.po
new file mode 100644 (file)
index 0000000..9cd91bf
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,2153 @@
+# French translation of pulseaudio.
+# Copyright (C) 2006-2008 Lennart Poettering
+# This file is distributed under the same license as the pulseaudio package.
+#
+# Robert-André Mauchin <zebob.m@pengzone.org>, 2008.
+# Michaël Ughetto <telimektar esraonline com>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pulseaudio trunk\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-09-06 06:06+0000\n"
+"PO-Revision-Date: 2008-09-06 10:49+0200\n"
+"Last-Translator: Robert-André Mauchin <zebob.m@pengzone.org>\n"
+"Language-Team: Fedora French <fedora-trans-fr@redhat.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n>1;\n"
+
+#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197
+msgid "Failed to add bind-now-loader."
+msgstr "Échec lors de l'ajout du chargeur bind-now."
+
+#: ../src/daemon/ltdl-bind-now.c:184
+msgid "Failed to find original dlopen loader."
+msgstr "Échec lors de la recherche du chargeur dlopen original."
+
+#: ../src/daemon/polkit.c:55
+#, c-format
+msgid "Cannot connect to system bus: %s"
+msgstr "Impossible de se connecter au bus système : %s"
+
+#: ../src/daemon/polkit.c:65
+#, c-format
+msgid "Cannot get caller from PID: %s"
+msgstr "Impossible d'obtenir le programme appelant à partir du PID : %s"
+
+#: ../src/daemon/polkit.c:77
+msgid "Cannot set UID on caller object."
+msgstr "Impossible de définir un UID sur l'objet appelant."
+
+#: ../src/daemon/polkit.c:82
+msgid "Failed to get CK session."
+msgstr "Échec lors de l'obtention de la session CK."
+
+#: ../src/daemon/polkit.c:90
+msgid "Cannot set UID on session object."
+msgstr "Impossible de définir l'UID sur l'objet de session."
+
+#: ../src/daemon/polkit.c:95
+msgid "Cannot allocate PolKitAction."
+msgstr "Impossible d'allouer PolKitAction."
+
+#: ../src/daemon/polkit.c:100
+msgid "Cannot set action_id"
+msgstr "Impossible de définir action_id."
+
+#: ../src/daemon/polkit.c:105
+msgid "Cannot allocate PolKitContext."
+msgstr "Impossible d'allouer PolKitContext."
+
+#: ../src/daemon/polkit.c:110
+#, c-format
+msgid "Cannot initialize PolKitContext: %s"
+msgstr "Impossible d'initialiser PolKitContext : %s"
+
+#: ../src/daemon/polkit.c:119
+#, c-format
+msgid "Could not determine whether caller is authorized: %s"
+msgstr "Impossible de déterminer si le programme appelant est autorisé : %s"
+
+#: ../src/daemon/polkit.c:139
+#, c-format
+msgid "Cannot obtain auth: %s"
+msgstr "Impossible d'obtenir l'authentification : %s"
+
+#: ../src/daemon/polkit.c:148
+#, c-format
+msgid "PolicyKit responded with '%s'"
+msgstr "PolicyKit a renvoyé « %s »"
+
+#: ../src/daemon/main.c:134
+#, c-format
+msgid "Got signal %s."
+msgstr "Signal %s obtenu."
+
+#: ../src/daemon/main.c:161
+msgid "Exiting."
+msgstr "Fermeture."
+
+#: ../src/daemon/main.c:179
+#, c-format
+msgid "Failed to find user '%s'."
+msgstr "Impossible de trouver l'utilisateur « %s »."
+
+#: ../src/daemon/main.c:184
+#, c-format
+msgid "Failed to find group '%s'."
+msgstr "Impossible de trouver le groupe « %s »."
+
+#: ../src/daemon/main.c:188
+#, c-format
+msgid "Found user '%s' (UID %lu) and group '%s' (GID %lu)."
+msgstr "Utilisateur « %s ” (UID %lu) et groupe « %s » (GID %lu) trouvé."
+
+#: ../src/daemon/main.c:193
+#, c-format
+msgid "GID of user '%s' and of group '%s' don't match."
+msgstr ""
+"Le GID de l'utilisateur « %s » et du groupe « %s » ne sont pas identiques."
+
+#: ../src/daemon/main.c:198
+#, c-format
+msgid "Home directory of user '%s' is not '%s', ignoring."
+msgstr "Le dossier personnel de l'utilisateur « %s » n'est pas « %s », ignoré."
+
+#: ../src/daemon/main.c:201 ../src/daemon/main.c:206
+#, c-format
+msgid "Failed to create '%s': %s"
+msgstr "Échec lors de la création de « %s » : %s"
+
+#: ../src/daemon/main.c:213
+#, c-format
+msgid "Failed to change group list: %s"
+msgstr "Échec lors du changement de la liste du groupe : %s"
+
+#: ../src/daemon/main.c:229
+#, c-format
+msgid "Failed to change GID: %s"
+msgstr "Échec lors du changement de GID : %s"
+
+#: ../src/daemon/main.c:245
+#, c-format
+msgid "Failed to change UID: %s"
+msgstr "Échec lors du changement d'UID : %s"
+
+#: ../src/daemon/main.c:259
+msgid "Successfully dropped root privileges."
+msgstr "Les permissions root ont été correctement abandonnées."
+
+#: ../src/daemon/main.c:267
+msgid "System wide mode unsupported on this platform."
+msgstr "Mode système étendu non pris en charge sur cette plateforme."
+
+#: ../src/daemon/main.c:285
+#, c-format
+msgid "setrlimit(%s, (%u, %u)) failed: %s"
+msgstr "setrlimit(%s, (%u, %u)) a échoué : %s"
+
+#: ../src/daemon/main.c:425
+msgid "Failed to parse command line."
+msgstr "Échec lors de l'analyse de la ligne de commande"
+
+#: ../src/daemon/main.c:441
+#, c-format
+msgid "We're in the group '%s', allowing high-priority scheduling."
+msgstr ""
+"Nous sommes dans le groupe « %s », permettant une planification à haute "
+"priorité."
+
+#: ../src/daemon/main.c:448
+#, c-format
+msgid "We're in the group '%s', allowing real-time scheduling."
+msgstr ""
+"Nous sommes dans le groupe « %s », permettant une planification en temps réel."
+
+#: ../src/daemon/main.c:456
+msgid "PolicyKit grants us acquire-high-priority privilege."
+msgstr "PolicyKit a accordé l'acquisition des permissions de haute priorité."
+
+#: ../src/daemon/main.c:459
+msgid "PolicyKit refuses acquire-high-priority privilege."
+msgstr "PolicyKit a refusé l'acquisition des permissions de haute priorité."
+
+#: ../src/daemon/main.c:464
+msgid "PolicyKit grants us acquire-real-time privilege."
+msgstr "PolicyKit a accordé l'acquisition des permissions de temps réel."
+
+#: ../src/daemon/main.c:467
+msgid "PolicyKit refuses acquire-real-time privilege."
+msgstr "PolicyKit a refusé l'acquisition des permissions de temps réel."
+
+#: ../src/daemon/main.c:479
+msgid ""
+"Called SUID root and real-time/high-priority scheduling was requested in the "
+"configuration. However, we lack the necessary priviliges:\n"
+"We are not in group '"
+msgstr ""
+"Le SUID root a été appelé et la planification à haute priorité/en temps réel "
+"demandée dans la configuration. Néanmoins nous n'avons pas les permissions "
+"nécessaires :\n"
+"nous ne somme pas dans le groupe "
+
+#: ../src/daemon/main.c:480
+msgid ""
+"' and PolicyKit refuse to grant us priviliges. Dropping SUID again.\n"
+"For enabling real-time scheduling please acquire the appropriate PolicyKit "
+"priviliges, or become a member of '"
+msgstr ""
+" et PolicyKit refuse de nous accorder les permissions. Abandon du SUID à nouveau.\n"
+"Pour activer la planification en temps réel, veuillez aquérir les permissions "
+"PolicyKit appropriées, ou devenez membre de "
+
+#: ../src/daemon/main.c:481
+msgid ""
+"', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."
+msgstr ""
+", ou augmentez les limites de ressource RLIMIT_NICE/RLIMIT_RTPRIO pour cet utilisateur."
+
+#: ../src/daemon/main.c:497
+msgid ""
+"High-priority scheduling enabled in configuration but not allowed by policy."
+msgstr ""
+"La planification à haute priorité est activée dans la configuration mais "
+"n'est pas permise par la politique."
+
+#: ../src/daemon/main.c:522
+msgid "Successfully increased RLIMIT_RTPRIO"
+msgstr "Augmentation de RLIMIT_RTPRIO réussie"
+
+#: ../src/daemon/main.c:525
+#, c-format
+msgid "RLIMIT_RTPRIO failed: %s"
+msgstr "RLIMIT_RTPRIO a échoué : %s"
+
+#: ../src/daemon/main.c:532
+msgid "Giving up CAP_NICE"
+msgstr "Abandon de CAP_NICE"
+
+#: ../src/daemon/main.c:539
+msgid ""
+"Real-time scheduling enabled in configuration but not allowed by policy."
+msgstr ""
+"La planification en temps réel est activée mais n'est pas permise par la "
+"politique."
+
+#: ../src/daemon/main.c:597
+msgid "Daemon not running"
+msgstr "Lé démon n'est pas lancé"
+
+#: ../src/daemon/main.c:599
+#, c-format
+msgid "Daemon running as PID %u"
+msgstr "Le démon est lancé avec le PID %u"
+
+#: ../src/daemon/main.c:609
+#, c-format
+msgid "Failed to kill daemon: %s"
+msgstr "Impossible de tuer le démon : %s"
+
+#: ../src/daemon/main.c:627
+msgid ""
+"This program is not intended to be run as root (unless --system is "
+"specified)."
+msgstr ""
+"Le programme n'est pas conçu pour être lancé en tant que root (sauf si --"
+"system est renseigné)."
+
+#: ../src/daemon/main.c:629
+msgid "Root priviliges required."
+msgstr "Les permissions root sont nécessaires."
+
+#: ../src/daemon/main.c:634
+msgid "--start not supported for system instances."
+msgstr "--start n'est pas pris en charge pour les instances système."
+
+#: ../src/daemon/main.c:639
+msgid "Running in system mode, but --disallow-exit not set!"
+msgstr ""
+"Le démon s'exécute en mode système, mais --disallow-exit n'est pas défini."
+
+#: ../src/daemon/main.c:642
+msgid "Running in system mode, but --disallow-module-loading not set!"
+msgstr ""
+"Le démon s'exécute en mode système, mais --disallow-module-loading n'est pas "
+"défini."
+
+#: ../src/daemon/main.c:645
+msgid "Running in system mode, forcibly disabling SHM mode!"
+msgstr "Le démon s'exécute en mode système, désactivation forcée du mode SHM."
+
+#: ../src/daemon/main.c:650
+msgid "Running in system mode, forcibly disabling exit idle time!"
+msgstr ""
+"Le démon s'exécute en mode système, désactivation forcée de la fermeture "
+"après délai d'inactivité."
+
+#: ../src/daemon/main.c:677
+msgid "Failed to acquire stdio."
+msgstr "Échec lors de l'acquisition de stdio."
+
+#: ../src/daemon/main.c:683
+#, c-format
+msgid "pipe failed: %s"
+msgstr "Échec du tube : %s"
+
+#: ../src/daemon/main.c:688
+#, c-format
+msgid "fork() failed: %s"
+msgstr "Échec de fork() : %s"
+
+#: ../src/daemon/main.c:702
+#, c-format
+msgid "read() failed: %s"
+msgstr "Échec de read() : %s"
+
+#: ../src/daemon/main.c:708
+msgid "Daemon startup failed."
+msgstr "Échec lors du démarrage du démon."
+
+#: ../src/daemon/main.c:710
+msgid "Daemon startup successful."
+msgstr "Démarrage du démon réussi."
+
+#: ../src/daemon/main.c:780
+#, c-format
+msgid "This is PulseAudio %s"
+msgstr "Pulseaudio %s"
+
+#: ../src/daemon/main.c:781
+#, c-format
+msgid "Compilation CFLAGS: %s"
+msgstr "CFLAGS de compilation : %s"
+
+#: ../src/daemon/main.c:784
+msgid "Compiled with Valgrind support: yes"
+msgstr "Compilé avec la prise en charge Valgrind : oui"
+
+#: ../src/daemon/main.c:786
+msgid "Compiled with Valgrind support: no"
+msgstr "Compilé avec la prise en charge Valgrind : non"
+
+#: ../src/daemon/main.c:790
+msgid "Optimized build: yes"
+msgstr "Construction optimisée : oui"
+
+#: ../src/daemon/main.c:792
+msgid "Optimized build: no"
+msgstr "Construction optimisée : non"
+
+#: ../src/daemon/main.c:795
+#, c-format
+msgid "Page size is %lu bytes"
+msgstr "La taille de la page est de %lu octets"
+
+#: ../src/daemon/main.c:798
+msgid "Failed to get machine ID"
+msgstr "Échec lors de l'obtention de l'ID de la machine"
+
+#: ../src/daemon/main.c:801
+#, c-format
+msgid "Machine ID is %s."
+msgstr "L'ID de la machine est %s."
+
+#: ../src/daemon/main.c:806
+#, c-format
+msgid "Using runtime directory %s."
+msgstr "Utilisation du répertoire d'exécution %s."
+
+#: ../src/daemon/main.c:811
+#, c-format
+msgid "Using state directory %s."
+msgstr "Utilisation du répertoire d'état %s."
+
+#: ../src/daemon/main.c:814
+#, c-format
+msgid "Running in system mode: %s"
+msgstr "Exécution en mode système : %s"
+
+#: ../src/daemon/main.c:829
+msgid "pa_pid_file_create() failed."
+msgstr "Échec de pa_pid_file_create()."
+
+#: ../src/daemon/main.c:841
+msgid "Fresh high-resolution timers available! Bon appetit!"
+msgstr ""
+"De nouvelles horloges à haute résolution sont disponibles ! Bon appétit !"
+
+#: ../src/daemon/main.c:843
+msgid ""
+"Dude, your kernel stinks! The chef's recommendation today is Linux with high-"
+"resolution timers enabled!"
+msgstr ""
+"Eh mec, ton noyau il pue ! La recommandation d'aujourd'hui du patron est "
+"d'activer les horloges à haute résolution sur ton Linux."
+
+#: ../src/daemon/main.c:853
+msgid "pa_core_new() failed."
+msgstr "Échec de pa_core_new()."
+
+#: ../src/daemon/main.c:913
+msgid "Failed to initialize daemon."
+msgstr "Échec lors de l'initialisation du démon"
+
+#: ../src/daemon/main.c:918
+msgid "Daemon startup without any loaded modules, refusing to work."
+msgstr "Démarrage du démon sans aucun module chargé : refus de fonctionner."
+
+#: ../src/daemon/main.c:923
+#, c-format
+msgid "Default sink name (%s) does not exist in name register."
+msgstr ""
+"Le nom de la destination par défaut (%s) n'existe pas dans le registre des "
+"noms."
+
+#: ../src/daemon/main.c:936
+msgid "Daemon startup complete."
+msgstr "Démarrage du démon effectué."
+
+#: ../src/daemon/main.c:942
+msgid "Daemon shutdown initiated."
+msgstr "Fermeture du démon initiée."
+
+#: ../src/daemon/main.c:963
+msgid "Daemon terminated."
+msgstr "Démon terminé."
+
+#: ../src/daemon/cmdline.c:117
+#, c-format
+msgid ""
+"%s [options]\n"
+"\n"
+"COMMANDS:\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"      --dump-conf                       Dump default configuration\n"
+"      --dump-modules                    Dump list of available modules\n"
+"      --dump-resample-methods           Dump available resample methods\n"
+"      --cleanup-shm                     Cleanup stale shared memory "
+"segments\n"
+"      --start                           Start the daemon if it is not "
+"running\n"
+"  -k  --kill                            Kill a running daemon\n"
+"      --check                           Check for a running daemon\n"
+"\n"
+"OPTIONS:\n"
+"      --system[=BOOL]                   Run as system-wide instance\n"
+"  -D, --daemonize[=BOOL]                Daemonize after startup\n"
+"      --fail[=BOOL]                     Quit when startup fails\n"
+"      --high-priority[=BOOL]            Try to set high nice level\n"
+"                                        (only available as root, when SUID "
+"or\n"
+"                                        with elevated RLIMIT_NICE)\n"
+"      --realtime[=BOOL]                 Try to enable realtime scheduling\n"
+"                                        (only available as root, when SUID "
+"or\n"
+"                                        with elevated RLIMIT_RTPRIO)\n"
+"      --disallow-module-loading[=BOOL]  Disallow module user requested "
+"module\n"
+"                                        loading/unloading after startup\n"
+"      --disallow-exit[=BOOL]            Disallow user requested exit\n"
+"      --exit-idle-time=SECS             Terminate the daemon when idle and "
+"this\n"
+"                                        time passed\n"
+"      --module-idle-time=SECS           Unload autoloaded modules when idle "
+"and\n"
+"                                        this time passed\n"
+"      --scache-idle-time=SECS           Unload autoloaded samples when idle "
+"and\n"
+"                                        this time passed\n"
+"      --log-level[=LEVEL]               Increase or set verbosity level\n"
+"  -v                                    Increase the verbosity level\n"
+"      --log-target={auto,syslog,stderr} Specify the log target\n"
+"  -p, --dl-search-path=PATH             Set the search path for dynamic "
+"shared\n"
+"                                        objects (plugins)\n"
+"      --resample-method=METHOD          Use the specified resampling method\n"
+"                                        (See --dump-resample-methods for\n"
+"                                        possible values)\n"
+"      --use-pid-file[=BOOL]             Create a PID file\n"
+"      --no-cpu-limit[=BOOL]             Do not install CPU load limiter on\n"
+"                                        platforms that support it.\n"
+"      --disable-shm[=BOOL]              Disable shared memory support.\n"
+"\n"
+"STARTUP SCRIPT:\n"
+"  -L, --load=\"MODULE ARGUMENTS\"         Load the specified plugin module "
+"with\n"
+"                                        the specified argument\n"
+"  -F, --file=FILENAME                   Run the specified script\n"
+"  -C                                    Open a command line on the running "
+"TTY\n"
+"                                        after startup\n"
+"\n"
+"  -n                                    Don't load default script file\n"
+msgstr ""
+"%s [options]\n"
+"\n"
+"COMMANDES :\n"
+"  -h, --help                            Affiche cette aide\n"
+"      --version                         Affiche la version\n"
+"      --dump-conf                       Affiche la configuration par défaut\n"
+"      --dump-modules                    Affiche la liste des modules "
+"disponibles\n"
+"      --dump-resample-methods           Affiche la liste des méthodes "
+"d'échantillonnage disponibles\n"
+"      --cleanup-shm                     Nettoie les segments de mémoire "
+"partagée périmés\n"
+"      --start                           Démarre le démon s'il n'est pas "
+"lancé\n"
+"  -k  --kill                            Tue un démon en cours d'exécution\n"
+"      --check                           Vérifie s'il existe un démon en "
+"cours d'exécution\n"
+"\n"
+"OPTIONS :\n"
+"      --system[=BOOL]                   Exécuter en tant qu'instance "
+"système\n"
+"  -D, --daemonize[=BOOL]                Définir en tant que démon après le "
+"démarrage\n"
+"      --fail[=BOOL]                     Quitte quand le démarrage échoue\n"
+"      --high-priority[=BOOL]            Tente de définir un niveau nice plus "
+"élevé\n"
+"                                        (seulement disponible en tant que "
+"root, avec le SUID ou\n"
+"                                        avec un RLIMIT_NICE élevé)\n"
+"      --realtime[=BOOL]                 Tente d'activer une planification en "
+"temps réel\n"
+"                                        (seulement disponible en tant que "
+"root, avec le SUID ou\n"
+"                                        ave un RLIMIT_RTPRIO élevé)\n"
+"      --disallow-module-loading[=BOOL]  Empêche les chargements/"
+"déchargements de module\n"
+"                                        demandés par l'utilisateur après le "
+"démarrage\n"
+"      --disallow-exit[=BOOL]            Empêche les fermetures demandées par "
+"l'utilisateur\n"
+"      --exit-idle-time=SECS             Termine le démon quand la durée "
+"d'inactivité \n"
+"                                        et ce temps se sont écoulés\n"
+"      --module-idle-time=SECS           Décharge les modules chargés "
+"automatiquement \n"
+"                                        quand la durée d'inactivité et ce "
+"temps se sont écoulés\n"
+"      --scache-idle-time=SECS           Décharge les échantillons chargés "
+"automatiquement \n"
+"                                        quand la durée d'inactivité et ce "
+"temps se sont écoulés\n"
+"      --log-level[=NIVEAU]              Augmente ou définit le niveau de "
+"verbosité\n"
+"  -v                                    Augmente le niveau de verbosité\n"
+"      --log-target={auto,syslog,stderr} Indique la cible du journal\n"
+"  -p, --dl-search-path=CHEMIN           Définit le chemin de recherche pour "
+"les objets dynamiques\n"
+"                                        partagés (extensions)\n"
+"      --resample-method=MÉTHODE         Utilise la méthode de "
+"rééchantillonnage indiquée\n"
+"                                        (Voir --dump-resample-methods pour\n"
+"                                        les valeurs possibles)\n"
+"      --use-pid-file[=BOOL]             Crée un fichier PID\n"
+"      --no-cpu-limit[=BOOL]             Ne pas installer de limiteur de "
+"charge CPU\n"
+"                                        sur les plateformes qui le "
+"supportent.\n"
+"      --disable-shm[=BOOL]              Désactive la prise en charge de la "
+"mémoire partagée.\n"
+"\n"
+"SCRIPT DE DÉMARRAGE :\n"
+"  -L, --load=\"PARAMÈTRES DU MODULE\"   Charge le module d'extension indiqué "
+"avec\n"
+"                                        le paramètre indiqué\n"
+"  -F, --file=NOMDEFICHIER               Exécute le script indiqué\n"
+"  -C                                    Ouvre une ligne de commande sur le "
+"TTY en cours \n"
+"                                        après le démarrage\n"
+"\n"
+"  -n                                    Ne pas charger les fichiers de "
+"scripts par défaut\n"
+
+#: ../src/daemon/cmdline.c:245
+msgid "--daemonize expects boolean argument"
+msgstr "--daemonize requiert un paramètre booléen"
+
+#: ../src/daemon/cmdline.c:252
+msgid "--fail expects boolean argument"
+msgstr "--fail requiert un paramètre booléen"
+
+#: ../src/daemon/cmdline.c:262
+msgid ""
+"--log-level expects log level argument (either numeric in range 0..4 or one "
+"of debug, info, notice, warn, error)."
+msgstr ""
+"--log-level requiert un paramètre de niveau de journal (soit numérique entre "
+"0 et 4, soit de débogage : info, notice, warn , error)."
+
+#: ../src/daemon/cmdline.c:274
+msgid "--high-priority expects boolean argument"
+msgstr "--high-priority requiert un paramètre booléen"
+
+#: ../src/daemon/cmdline.c:281
+msgid "--realtime expects boolean argument"
+msgstr "--realtime requiert un paramètre booléen"
+
+#: ../src/daemon/cmdline.c:288
+msgid "--disallow-module-loading expects boolean argument"
+msgstr "--disallow-module-loading requiert un paramètre booléen"
+
+#: ../src/daemon/cmdline.c:295
+msgid "--disallow-exit boolean argument"
+msgstr "--disallow-exit requiert un paramètre booléen"
+
+#: ../src/daemon/cmdline.c:302
+msgid "--use-pid-file expects boolean argument"
+msgstr "--use-pid-file requiert un paramètre booléen"
+
+#: ../src/daemon/cmdline.c:319
+msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'."
+msgstr "Cible du journal invalide : utilisez « syslog », « stderr » ou « auto »."
+
+#: ../src/daemon/cmdline.c:338
+#, c-format
+msgid "Invalid resample method '%s'."
+msgstr "Méthode de rééchantillonnage invalide « %s »."
+
+#: ../src/daemon/cmdline.c:345
+msgid "--system expects boolean argument"
+msgstr "--system requiert un paramètre booléen"
+
+#: ../src/daemon/cmdline.c:352
+msgid "--no-cpu-limit expects boolean argument"
+msgstr "--no-cpu-limit requiert un paramètre booléen"
+
+#: ../src/daemon/cmdline.c:359
+msgid "--disable-shm expects boolean argument"
+msgstr "--disable-shm requiert un paramètre booléen"
+
+#: ../src/daemon/dumpmodules.c:60
+#, c-format
+msgid "Name: %s\n"
+msgstr "Nom : %s\n"
+
+#: ../src/daemon/dumpmodules.c:63
+#, c-format
+msgid "No module information available\n"
+msgstr "Aucune information de module disponible\n"
+
+#: ../src/daemon/dumpmodules.c:66
+#, c-format
+msgid "Version: %s\n"
+msgstr "Version : %s\n"
+
+#: ../src/daemon/dumpmodules.c:68
+#, c-format
+msgid "Description: %s\n"
+msgstr "Description : %s\n"
+
+#: ../src/daemon/dumpmodules.c:70
+#, c-format
+msgid "Author: %s\n"
+msgstr "Auteur : %s\n"
+
+#: ../src/daemon/dumpmodules.c:72
+#, c-format
+msgid "Usage: %s\n"
+msgstr "Utilisation : %s\n"
+
+#: ../src/daemon/dumpmodules.c:73
+#, c-format
+msgid "Load Once: %s\n"
+msgstr "Chargement unique : %s\n"
+
+#: ../src/daemon/dumpmodules.c:77
+#, c-format
+msgid "Path: %s\n"
+msgstr "Chemin : %s\n"
+
+# dans les lignes suivantes [%s = nom de fichier: %u = ligne dans celui-ci]
+#: ../src/daemon/daemon-conf.c:203
+#, c-format
+msgid "[%s:%u] Invalid log target '%s'."
+msgstr "[%s:%u] Cible du journal « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:219
+#, c-format
+msgid "[%s:%u] Invalid log level '%s'."
+msgstr "[%s:%u] Niveau du journal « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:235
+#, c-format
+msgid "[%s:%u] Invalid resample method '%s'."
+msgstr "[%s:%u] Méthode de rééchantillonnage « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:258
+#, c-format
+msgid "[%s:%u] Invalid rlimit '%s'."
+msgstr "[%s:%u] rlimit « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:265
+#, c-format
+msgid "[%s:%u] rlimit not supported on this platform."
+msgstr "[%s:%u] rlimit n'est pas pris en charge sur cette plateforme."
+
+#: ../src/daemon/daemon-conf.c:281
+#, c-format
+msgid "[%s:%u] Invalid sample format '%s'."
+msgstr "[%s:%u] Format d'échantillon « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:299
+#, c-format
+msgid "[%s:%u] Invalid sample rate '%s'."
+msgstr "[%s:%u] Taux d'échantillonnage « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:317
+#, c-format
+msgid "[%s:%u] Invalid sample channels '%s'."
+msgstr "[%s:%u] Canaux d'échantillonnage « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:335
+#, c-format
+msgid "[%s:%u] Invalid number of fragments '%s'."
+msgstr "[%s:%u] Nombre de fragments « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:353
+#, c-format
+msgid "[%s:%u] Invalid fragment size '%s'."
+msgstr "[%s:%u] Taille du fragment « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:371
+#, c-format
+msgid "[%s:%u] Invalid nice level '%s'."
+msgstr "[%s:%u] Niveau de priorité (nice) « %s » invalide."
+
+#: ../src/daemon/daemon-conf.c:564
+#, c-format
+msgid "Failed to open configuration file: %s"
+msgstr "Échec lors de l'ouverture du fichier de configuration : %s"
+
+#: ../src/daemon/daemon-conf.c:638
+#, c-format
+msgid "### Read from configuration file: %s ###\n"
+msgstr "### Lecture à partir du fichier de configuration : %s ###\n"
+
+#: ../src/daemon/caps.c:62
+msgid "Dropping root priviliges."
+msgstr "Abandon des permissions root."
+
+#: ../src/daemon/caps.c:102
+msgid "Limited capabilities successfully to CAP_SYS_NICE."
+msgstr "Limitation des capacités à CAP_SYS_NICE réussie."
+
+#: ../src/pulse/channelmap.c:102
+msgid "Mono"
+msgstr "Mono"
+
+#: ../src/pulse/channelmap.c:104
+msgid "Front Center"
+msgstr "Avant centre"
+
+#: ../src/pulse/channelmap.c:105
+msgid "Front Left"
+msgstr "Avant gauche"
+
+#: ../src/pulse/channelmap.c:106
+msgid "Front Right"
+msgstr "Avant droit"
+
+#: ../src/pulse/channelmap.c:108
+msgid "Rear Center"
+msgstr "Arrière centre"
+
+#: ../src/pulse/channelmap.c:109
+msgid "Rear Left"
+msgstr "Arrière gauche"
+
+#: ../src/pulse/channelmap.c:110
+msgid "Rear Right"
+msgstr "Arrière droit"
+
+#: ../src/pulse/channelmap.c:112
+msgid "Low Frequency Emmiter"
+msgstr "Émetteur à basse fréquence"
+
+#: ../src/pulse/channelmap.c:114
+msgid "Front Left-of-center"
+msgstr "Avant à gauche du centre"
+
+#: ../src/pulse/channelmap.c:115
+msgid "Front Right-of-center"
+msgstr "Avant à droite du centre"
+
+#: ../src/pulse/channelmap.c:117
+msgid "Side Left"
+msgstr "Côté gauche"
+
+#: ../src/pulse/channelmap.c:118
+msgid "Side Right"
+msgstr "Côté droit"
+
+#: ../src/pulse/channelmap.c:120
+msgid "Auxiliary 0"
+msgstr "Auxiliaire 0"
+
+#: ../src/pulse/channelmap.c:121
+msgid "Auxiliary 1"
+msgstr "Auxiliaire 1"
+
+#: ../src/pulse/channelmap.c:122
+msgid "Auxiliary 2"
+msgstr "Auxiliaire 2"
+
+#: ../src/pulse/channelmap.c:123
+msgid "Auxiliary 3"
+msgstr "Auxiliaire 3"
+
+#: ../src/pulse/channelmap.c:124
+msgid "Auxiliary 4"
+msgstr "Auxiliaire 4"
+
+#: ../src/pulse/channelmap.c:125
+msgid "Auxiliary 5"
+msgstr "Auxiliaire 5"
+
+#: ../src/pulse/channelmap.c:126
+msgid "Auxiliary 6"
+msgstr "Auxiliaire 6"
+
+#: ../src/pulse/channelmap.c:127
+msgid "Auxiliary 7"
+msgstr "Auxiliaire 7"
+
+#: ../src/pulse/channelmap.c:128
+msgid "Auxiliary 8"
+msgstr "Auxiliaire 8"
+
+#: ../src/pulse/channelmap.c:129
+msgid "Auxiliary 9"
+msgstr "Auxiliaire 9"
+
+#: ../src/pulse/channelmap.c:130
+msgid "Auxiliary 10"
+msgstr "Auxiliaire 10"
+
+#: ../src/pulse/channelmap.c:131
+msgid "Auxiliary 11"
+msgstr "Auxiliaire 11"
+
+#: ../src/pulse/channelmap.c:132
+msgid "Auxiliary 12"
+msgstr "Auxiliaire 12"
+
+#: ../src/pulse/channelmap.c:133
+msgid "Auxiliary 13"
+msgstr "Auxiliaire 13"
+
+#: ../src/pulse/channelmap.c:134
+msgid "Auxiliary 14"
+msgstr "Auxiliaire 14"
+
+#: ../src/pulse/channelmap.c:135
+msgid "Auxiliary 15"
+msgstr "Auxiliaire 15"
+
+#: ../src/pulse/channelmap.c:136
+msgid "Auxiliary 16"
+msgstr "Auxiliaire 16"
+
+#: ../src/pulse/channelmap.c:137
+msgid "Auxiliary 17"
+msgstr "Auxiliaire 17"
+
+#: ../src/pulse/channelmap.c:138
+msgid "Auxiliary 18"
+msgstr "Auxiliaire 18"
+
+#: ../src/pulse/channelmap.c:139
+msgid "Auxiliary 19"
+msgstr "Auxiliaire 19"
+
+#: ../src/pulse/channelmap.c:140
+msgid "Auxiliary 20"
+msgstr "Auxiliaire 20"
+
+#: ../src/pulse/channelmap.c:141
+msgid "Auxiliary 21"
+msgstr "Auxiliaire 21"
+
+#: ../src/pulse/channelmap.c:142
+msgid "Auxiliary 22"
+msgstr "Auxiliaire 22"
+
+#: ../src/pulse/channelmap.c:143
+msgid "Auxiliary 23"
+msgstr "Auxiliaire 23"
+
+#: ../src/pulse/channelmap.c:144
+msgid "Auxiliary 24"
+msgstr "Auxiliaire 24"
+
+#: ../src/pulse/channelmap.c:145
+msgid "Auxiliary 25"
+msgstr "Auxiliaire 25"
+
+#: ../src/pulse/channelmap.c:146
+msgid "Auxiliary 26"
+msgstr "Auxiliaire 26"
+
+#: ../src/pulse/channelmap.c:147
+msgid "Auxiliary 27"
+msgstr "Auxiliaire 27"
+
+#: ../src/pulse/channelmap.c:148
+msgid "Auxiliary 28"
+msgstr "Auxiliaire 28"
+
+#: ../src/pulse/channelmap.c:149
+msgid "Auxiliary 29"
+msgstr "Auxiliaire 29"
+
+#: ../src/pulse/channelmap.c:150
+msgid "Auxiliary 30"
+msgstr "Auxiliaire 30"
+
+#: ../src/pulse/channelmap.c:151
+msgid "Auxiliary 31"
+msgstr "Auxiliaire 31"
+
+#: ../src/pulse/channelmap.c:153
+msgid "Top Center"
+msgstr "Centre haut"
+
+#: ../src/pulse/channelmap.c:155
+msgid "Top Front Center"
+msgstr "Avant centre haut"
+
+#: ../src/pulse/channelmap.c:156
+msgid "Top Front Left"
+msgstr "Avant gauche haut"
+
+#: ../src/pulse/channelmap.c:157
+msgid "Top Front Right"
+msgstr "Avant droit haut"
+
+#: ../src/pulse/channelmap.c:159
+msgid "Top Rear Center"
+msgstr "Arrière centre haut"
+
+#: ../src/pulse/channelmap.c:160
+msgid "Top Rear Left"
+msgstr "Arrière gauche haut"
+
+#: ../src/pulse/channelmap.c:161
+msgid "Top Rear Right"
+msgstr "Arrière droit haut"
+
+#: ../src/pulse/error.c:43
+msgid "OK"
+msgstr "OK"
+
+#: ../src/pulse/error.c:44
+msgid "Access denied"
+msgstr "Accès refusé"
+
+#: ../src/pulse/error.c:45
+msgid "Unknown command"
+msgstr "Commande inconnue"
+
+#: ../src/pulse/error.c:46
+msgid "Invalid argument"
+msgstr "Paramètre invalide"
+
+#: ../src/pulse/error.c:47
+msgid "Entity exists"
+msgstr "L'entité existe"
+
+#: ../src/pulse/error.c:48
+msgid "No such entity"
+msgstr "Aucune entité de ce type"
+
+#: ../src/pulse/error.c:49
+msgid "Connection refused"
+msgstr "Connexion refusée"
+
+#: ../src/pulse/error.c:50
+msgid "Protocol error"
+msgstr "Erreur du protocole"
+
+#: ../src/pulse/error.c:51
+msgid "Timeout"
+msgstr "Délai dépassé"
+
+#: ../src/pulse/error.c:52
+msgid "No authorization key"
+msgstr "Aucune clé d'autorisation"
+
+#: ../src/pulse/error.c:53
+msgid "Internal error"
+msgstr "Erreur interne"
+
+#: ../src/pulse/error.c:54
+msgid "Connection terminated"
+msgstr "Connexion terminée"
+
+#: ../src/pulse/error.c:55
+msgid "Entity killed"
+msgstr "L'entité a été tuée"
+
+#: ../src/pulse/error.c:56
+msgid "Invalid server"
+msgstr "Serveur invalide"
+
+#: ../src/pulse/error.c:57
+msgid "Module initalization failed"
+msgstr "Échec lors de l'initialisation du module"
+
+#: ../src/pulse/error.c:58
+msgid "Bad state"
+msgstr "État incorrect"
+
+#: ../src/pulse/error.c:59
+msgid "No data"
+msgstr "Aucune donnée"
+
+#: ../src/pulse/error.c:60
+msgid "Incompatible protocol version"
+msgstr "Version du protocole invalide"
+
+#: ../src/pulse/error.c:61
+msgid "Too large"
+msgstr "Trop grand"
+
+#: ../src/pulse/error.c:62
+msgid "Not supported"
+msgstr "Non pris en charge"
+
+#: ../src/pulse/error.c:63
+msgid "Unknown error code"
+msgstr "Code d'erreur inconnu"
+
+#: ../src/pulse/error.c:64
+msgid "No such extension"
+msgstr "Aucune extension de ce type"
+
+#: ../src/pulse/sample.c:134
+msgid "Invalid"
+msgstr "Invalide"
+
+#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100
+msgid "XOpenDisplay() failed"
+msgstr "Échec de XOpenDisplay()"
+
+#: ../src/pulse/client-conf-x11.c:78
+msgid "Failed to parse cookie data"
+msgstr "Échec lors de l'analyse des données du cookie"
+
+#: ../src/pulse/client-conf.c:117
+#, c-format
+msgid "Failed to open configuration file '%s': %s"
+msgstr "Échec lors de l'ouverture du fichier de configuration « %s » :%s"
+
+#: ../src/pulse/context.c:542
+msgid "No cookie loaded. Attempting to connect without."
+msgstr "Aucun cookie chargé. Tentative de connexion sans celui-ci."
+
+#: ../src/pulse/context.c:596
+#, c-format
+msgid "socketpair(): %s"
+msgstr "socketpair() : %s"
+
+#: ../src/pulse/context.c:610
+#, c-format
+msgid "fork(): %s"
+msgstr "fork() : %s"
+
+#: ../src/pulse/context.c:673
+#, c-format
+msgid "waitpid(): %s"
+msgstr "waitpid() : %s"
+
+#: ../src/pulse/context.c:1354
+#, c-format
+msgid "Received message for unknown extension '%s'"
+msgstr "Message reçu pour une extension inconnue « %s »"
+
+#: ../src/utils/pacat.c:93
+#, c-format
+msgid "pa_stream_write() failed: %s\n"
+msgstr "Échec de pa_stream_write() : %s\n"
+
+#: ../src/utils/pacat.c:132
+#, c-format
+msgid "pa_stream_peek() failed: %s\n"
+msgstr "Échec de pa_stream_peek() : %s\n"
+
+#: ../src/utils/pacat.c:141
+#, c-format
+msgid "Buffer overrun, dropping incoming data\n"
+msgstr "Saturation du tampon, abandon des données entrantes\n"
+
+#: ../src/utils/pacat.c:143
+#, c-format
+msgid "pa_stream_drop() failed: %s\n"
+msgstr "Échec de pa_stream_drop() : %s\n"
+
+#: ../src/utils/pacat.c:169
+#, c-format
+msgid "Stream successfully created.\n"
+msgstr "Création du flux réussie.\n"
+
+#: ../src/utils/pacat.c:172
+#, c-format
+msgid "pa_stream_get_buffer_attr() failed: %s\n"
+msgstr "Échec de pa_stream_get_buffer_attr() : %s\n"
+
+#: ../src/utils/pacat.c:176
+#, c-format
+msgid "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n"
+msgstr "Mesures du tampon : maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n"
+
+#: ../src/utils/pacat.c:179
+#, c-format
+msgid "Buffer metrics: maxlength=%u, fragsize=%u\n"
+msgstr "Mesures du tampon : maxlength=%u, fragsize=%u\n"
+
+#: ../src/utils/pacat.c:183
+#, c-format
+msgid "Using sample spec '%s', channel map '%s'.\n"
+msgstr ""
+"Utilisation de la spécification d'échantillon « %s », plan des canaux « %s ».\n"
+
+# l'espace manquant entre %s et suspended est voulu
+#: ../src/utils/pacat.c:187
+#, c-format
+msgid "Connected to device %s (%u, %ssuspended).\n"
+msgstr "Connecté au périphérique %s (%u, %ssuspendu).\n"
+
+#: ../src/utils/pacat.c:197
+#, c-format
+msgid "Stream error: %s\n"
+msgstr "Erreur du flux : %s\n"
+
+#: ../src/utils/pacat.c:207
+#, c-format
+msgid "Stream device suspended.%s \n"
+msgstr "Périphérique de flux suspendu %s \n"
+
+#: ../src/utils/pacat.c:209
+#, c-format
+msgid "Stream device resumed.%s \n"
+msgstr "Périphérique de flux repris %s \n"
+
+#: ../src/utils/pacat.c:217
+#, c-format
+msgid "Stream underrun.%s \n"
+msgstr "Flux vide %s \n"
+
+#: ../src/utils/pacat.c:224
+#, c-format
+msgid "Stream overrun.%s \n"
+msgstr "Flux saturé %s \n"
+
+#: ../src/utils/pacat.c:231
+#, c-format
+msgid "Stream started.%s \n"
+msgstr "Flux démarré %s \n"
+
+#: ../src/utils/pacat.c:238
+#, c-format
+msgid "Stream moved to device %s (%u, %ssuspended).%s \n"
+msgstr "Flux déplacé vers le périphérique %s (%u, %ssuspendu).%s \n"
+
+# suspendu ou non suspendu
+#: ../src/utils/pacat.c:238
+msgid "not "
+msgstr "non "
+
+#: ../src/utils/pacat.c:259
+#, c-format
+msgid "Connection established.%s \n"
+msgstr "Connection établie.%s \n"
+
+#: ../src/utils/pacat.c:262
+#, c-format
+msgid "pa_stream_new() failed: %s\n"
+msgstr "Échec de pa_stream_new() : %s\n"
+
+#: ../src/utils/pacat.c:287
+#, c-format
+msgid "pa_stream_connect_playback() failed: %s\n"
+msgstr "Échec de pa_stream_connect_playback() : %s\n"
+
+#: ../src/utils/pacat.c:293
+#, c-format
+msgid "pa_stream_connect_record() failed: %s\n"
+msgstr "Échec de pa_stream_connect_record() : %s\n"
+
+#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159
+#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183
+#, c-format
+msgid "Connection failure: %s\n"
+msgstr "Échec lors de la connexion : %s\n"
+
+#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75
+#, c-format
+msgid "Failed to drain stream: %s\n"
+msgstr "Échec lors du vidage du flux : %s\n"
+
+#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80
+#, c-format
+msgid "Playback stream drained.\n"
+msgstr "Flux de lecture vidé.\n"
+
+#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92
+#, c-format
+msgid "Draining connection to server.\n"
+msgstr "Vidage de la connexion au serveur.\n"
+
+#: ../src/utils/pacat.c:369
+#, c-format
+msgid "Got EOF.\n"
+msgstr "EOF obtenu.\n"
+
+#: ../src/utils/pacat.c:375
+#, c-format
+msgid "pa_stream_drain(): %s\n"
+msgstr "pa_stream_drain() : %s\n"
+
+#: ../src/utils/pacat.c:385
+#, c-format
+msgid "read() failed: %s\n"
+msgstr "Échec de read() : %s\n"
+
+#: ../src/utils/pacat.c:417
+#, c-format
+msgid "write() failed: %s\n"
+msgstr "Échec de write() : %s\n"
+
+#: ../src/utils/pacat.c:438
+#, c-format
+msgid "Got signal, exiting.\n"
+msgstr "Signal obtenu, fermeture.\n"
+
+#: ../src/utils/pacat.c:452
+#, c-format
+msgid "Failed to get latency: %s\n"
+msgstr "Échec lors de l'obtention de la latence : %s\n"
+
+#: ../src/utils/pacat.c:457
+#, c-format
+msgid "Time: %0.3f sec; Latency: %0.0f usec.  \r"
+msgstr "Durée : %0.3f s ; Latency : %0.0f µs.  \r"
+
+#: ../src/utils/pacat.c:477
+#, c-format
+msgid "pa_stream_update_timing_info() failed: %s\n"
+msgstr "Échec de pa_stream_update_timing_info() : %s\n"
+
+# downmix = par ex. convertir 5 canaux en 2 canaux
+# upmixer = par ex. convertir 2 canaux en 5 canaux
+# https://bugzilla.redhat.com/show_bug.cgi?id=460798
+#: ../src/utils/pacat.c:490
+#, c-format
+msgid ""
+"%s [options]\n"
+"\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"\n"
+"  -r, --record                          Create a connection for recording\n"
+"  -p, --playback                        Create a connection for playback\n"
+"\n"
+"  -v, --verbose                         Enable verbose operations\n"
+"\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
+"  -d, --device=DEVICE                   The name of the sink/source to "
+"connect to\n"
+"  -n, --client-name=NAME                How to call this client on the "
+"server\n"
+"      --stream-name=NAME                How to call this stream on the "
+"server\n"
+"      --volume=VOLUME                   Specify the initial (linear) volume "
+"in range 0...65536\n"
+"      --rate=SAMPLERATE                 The sample rate in Hz (defaults to "
+"44100)\n"
+"      --format=SAMPLEFORMAT             The sample type, one of s16le, "
+"s16be, u8, float32le,\n"
+"                                        float32be, ulaw, alaw (defaults to "
+"s16ne)\n"
+"      --channels=CHANNELS               The number of channels, 1 for mono, "
+"2 for stereo\n"
+"                                        (defaults to 2)\n"
+"      --channel-map=CHANNELMAP          Channel map to use instead of the "
+"default\n"
+"      --fix-format                      Take the sample format from the sink "
+"the stream is\n"
+"                                        being connected to.\n"
+"      --fix-rate                        Take the sampling rate from the sink "
+"the stream is\n"
+"                                        being connected to.\n"
+"      --fix-channels                    Take the number of channels and the "
+"channel map\n"
+"                                        from the sink the stream is being "
+"connected to.\n"
+"      --no-remix                        Don't upmix or downmix channels.\n"
+"      --no-remap                        Map channels by index instead of "
+"name.\n"
+"      --latency=BYTES                   Request the specified latency in "
+"bytes.\n"
+"      --process-time=BYTES              Request the specified process time "
+"per request in bytes.\n"
+msgstr ""
+"%s [options]\n"
+"\n"
+"  -h, --help                            Affiche cette aide\n"
+"      --version                         Affiche la version\n"
+"\n"
+"  -r, --record                          Crée une connexion pour "
+"l'enregistrement\n"
+"  -p, --playback                        Crée une connexion pour la lecture\n"
+"\n"
+"  -v, --verbose                         Active le mode verbeux\n"
+"\n"
+"  -s, --server=SERVEUR                  Le nom du serveur auquel se "
+"connecter\n"
+"  -d, --device=PÉRIPHÉRIQUE             Le nom de la destination/source à "
+"laquelle de connecter\n"
+"  -n, --client-name=NOM                 Définit le nom de ce client sur le "
+"serveur\n"
+"      --stream-name=NOM                 Définit le nom de ce flux sur le "
+"serveur\n"
+"      --volume=VOLUME                   Indique le volume initial (linéaire) "
+"entre 0 et 65536\n"
+"      --rate=TAUXDÉCHANTILLONNAGE       Le taux d'échantillonnage en Hz (par "
+"défaut 44100)\n"
+"      --format=FORMATDELÉCHANTILLON     Le type de l'échantillon, parmi : "
+"s16le, s16be, u8, float32le,\n"
+"                                        float32be, ulaw, alaw (par défaut "
+"s16ne)\n"
+"      --channels=CANAUX                 Le nombre de canaux, 1 pour mono, 2 "
+"pour stéréo\n"
+"                                        (par défaut 2)\n"
+"      --channel-map=PLANDESCANAUX       Plan des canaux à utiliser au lieu "
+"de celui par défaut\n"
+"      --fix-format                      Prend le format de l'échantillon de "
+"la destination où le flux\n"
+"                                        est en train de se connecter.\n"
+"      --fix-rate                        Prend le taux d'échantillonnage de "
+"la destination où le flux\n"
+"                                        est en train de se connecter.\n"
+"      --fix-channels                    Prend le nombre et le plan des "
+"canaux de la destination \n"
+"                                        où le flux est en train de se "
+"connecter.\n"
+"      --no-remix                        Ne pas augmenter ou diminuer le "
+"nombre de canaux par mixage.\n"
+"      --no-remap                        Créer le plan des canaux par index "
+"et non par nom.\n"
+"      --latency=OCTETS                  Demande la latence indiquée en "
+"octets.\n"
+"      --process-time=OCTETS             Demande le temps de traitement "
+"indiqué par requête en octets.\n"
+
+#: ../src/utils/pacat.c:591
+#, c-format
+msgid ""
+"pacat %s\n"
+"Compiled with libpulse %s\n"
+"Linked with libpulse %s\n"
+msgstr ""
+"pacat %s\n"
+"Compilé avec libpulse %s\n"
+"Lié avec libpulse %s\n"
+
+#: ../src/utils/pacat.c:647
+#, c-format
+msgid "Invalid channel map '%s'\n"
+msgstr "Plan des canaux invalide « %s »\n"
+
+#: ../src/utils/pacat.c:676
+#, c-format
+msgid "Invalid latency specification '%s'\n"
+msgstr "Spécification de latence invalide « %s »\n"
+
+#: ../src/utils/pacat.c:683
+#, c-format
+msgid "Invalid process time specification '%s'\n"
+msgstr "Spécification de temps de traitement invalide « %s »\n"
+
+#: ../src/utils/pacat.c:694
+#, c-format
+msgid "Invalid sample specification\n"
+msgstr "Spécification d'échantillon invalide\n"
+
+#: ../src/utils/pacat.c:699
+#, c-format
+msgid "Channel map doesn't match sample specification\n"
+msgstr ""
+"Le plan des canaux ne correspond pas à la spécification d'échantillon\n"
+
+#: ../src/utils/pacat.c:706
+#, c-format
+msgid "Opening a %s stream with sample specification '%s'.\n"
+msgstr "Ouverture d'un flux %s avec une spécification d'échantillon « %s ».\n"
+
+#: ../src/utils/pacat.c:706
+msgid "recording"
+msgstr "enregistrement"
+
+#: ../src/utils/pacat.c:706
+msgid "playback"
+msgstr "lecture"
+
+#: ../src/utils/pacat.c:714
+#, c-format
+msgid "open(): %s\n"
+msgstr "open() : %s\n"
+
+#: ../src/utils/pacat.c:719
+#, c-format
+msgid "dup2(): %s\n"
+msgstr "dup2() : %s\n"
+
+#: ../src/utils/pacat.c:729
+#, c-format
+msgid "Too many arguments.\n"
+msgstr "Trop de paramètres.\n"
+
+#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280
+#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381
+#, c-format
+msgid "pa_mainloop_new() failed.\n"
+msgstr "Échec de pa_mainloop_new().\n"
+
+#: ../src/utils/pacat.c:763
+#, c-format
+msgid "io_new() failed.\n"
+msgstr "Échec de io_new().\n"
+
+#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293
+#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396
+#, c-format
+msgid "pa_context_new() failed.\n"
+msgstr "Échec de pa_context_new().\n"
+
+#: ../src/utils/pacat.c:785
+#, c-format
+msgid "time_new() failed.\n"
+msgstr "Échec de time_new().\n"
+
+#: ../src/utils/pacat.c:792 ../src/utils/pasuspender.c:301
+#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407
+#, c-format
+msgid "pa_mainloop_run() failed.\n"
+msgstr "Échec de pa_mainloop_run().\n"
+
+#: ../src/utils/pasuspender.c:81
+#, c-format
+msgid "fork(): %s\n"
+msgstr "fork() : %s\n"
+
+#: ../src/utils/pasuspender.c:92
+#, c-format
+msgid "execvp(): %s\n"
+msgstr "execvp() : %s\n"
+
+#: ../src/utils/pasuspender.c:109
+#, c-format
+msgid "Failure to suspend: %s\n"
+msgstr "Échec lors de la suspension : %s\n"
+
+#: ../src/utils/pasuspender.c:124
+#, c-format
+msgid "Failure to resume: %s\n"
+msgstr "Échec lors de la reprise : %s\n"
+
+#: ../src/utils/pasuspender.c:147
+#, c-format
+msgid "WARNING: Sound server is not local, not suspending.\n"
+msgstr ""
+"AVERTISSEMENT : le serveur de son n'est pas local, suspension annulée.\n"
+
+#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672
+#: ../src/utils/paplay.c:191
+#, c-format
+msgid "Got SIGINT, exiting.\n"
+msgstr "SIGINT reçu, fermeture.\n"
+
+#: ../src/utils/pasuspender.c:194
+#, c-format
+msgid "WARNING: Child process terminated by signal %u\n"
+msgstr "AVERTISSEMENT : le processus fils a été terminé par le signal %u\n"
+
+#: ../src/utils/pasuspender.c:212
+#, c-format
+msgid ""
+"%s [options] ... \n"
+"\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
+"\n"
+msgstr ""
+"%s [options] ... \n"
+"\n"
+"  -h, --help                            Affiche cette aide\n"
+"      --version                         Affiche la version\n"
+"  -s, --server=SERVEUR                  Le nom du serveur auquel se "
+"connecter\n"
+"\n"
+
+#: ../src/utils/pasuspender.c:251
+#, c-format
+msgid ""
+"pasuspender %s\n"
+"Compiled with libpulse %s\n"
+"Linked with libpulse %s\n"
+msgstr ""
+"pasuspender %s\n"
+"Compilé avec libpulse %s\n"
+"Lié avec libpulse %s\n"
+
+#: ../src/utils/pactl.c:107
+#, c-format
+msgid "Failed to get statistics: %s\n"
+msgstr "Échec lors de l'obtention des statistiques : %s\n"
+
+#: ../src/utils/pactl.c:113
+#, c-format
+msgid "Currently in use: %u blocks containing %s bytes total.\n"
+msgstr "En cours d'utilisation : %u blocs contenant au total %s octets.\n"
+
+#: ../src/utils/pactl.c:116
+#, c-format
+msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n"
+msgstr ""
+"Alloué pendant l'ensemble de la durée d'exécution : %u blocs contenant au "
+"total %s octets.\n"
+
+#: ../src/utils/pactl.c:119
+#, c-format
+msgid "Sample cache size: %s\n"
+msgstr "Taille du cache de l'échantillon : %s\n"
+
+#: ../src/utils/pactl.c:128
+#, c-format
+msgid "Failed to get server information: %s\n"
+msgstr "Échec lors de l'obtention des informations du serveur : %s\n"
+
+#: ../src/utils/pactl.c:135
+#, c-format
+msgid ""
+"User name: %s\n"
+"Host Name: %s\n"
+"Server Name: %s\n"
+"Server Version: %s\n"
+"Default Sample Specification: %s\n"
+"Default Sink: %s\n"
+"Default Source: %s\n"
+"Cookie: %08x\n"
+msgstr ""
+"Nom d'utilisateur : %s\n"
+"Nom d'hôte : %s\n"
+"Nom du serveur : %s\n"
+"Version du serveur : %s\n"
+"Spécification d'échantillon par défaut : %s\n"
+"Destination par défaut : %s\n"
+"Source par défaut : %s\n"
+"Cookie : %08x\n"
+
+#: ../src/utils/pactl.c:160
+#, c-format
+msgid "Failed to get sink information: %s\n"
+msgstr "Échec lors de l'obtention des informations sur la destination : %s\n"
+
+# demander à Lennart s'il s'agit de monitor of source
+#: ../src/utils/pactl.c:176
+#, c-format
+msgid ""
+"*** Sink #%u ***\n"
+"Name: %s\n"
+"Driver: %s\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Owner Module: %u\n"
+"Volume: %s\n"
+"Monitor Source: %s\n"
+"Latency: %0.0f usec, configured %0.0f usec\n"
+"Flags: %s%s%s%s%s%s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+"*** Destination #%u ***\n"
+"Nom : %s\n"
+"Pilote : %s\n"
+"Spécification de l'échantillon : %s\n"
+"Plan des canaux : %s\n"
+"Module propriétaire : %u\n"
+"Volume : %s\n"
+"Moniteur de la source : %s\n"
+"Latence : %0.0f µs, %0.0f µs configurée \n"
+"Drapeaux : %s%s%s%s%s%s\n"
+"Propriétés :\n"
+"%s"
+
+#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371
+msgid "muted"
+msgstr "en sourdine"
+
+#: ../src/utils/pactl.c:212
+#, c-format
+msgid "Failed to get source information: %s\n"
+msgstr "Échec lors de l'obtention des informations sur la source : %s\n"
+
+#: ../src/utils/pactl.c:228
+#, c-format
+msgid ""
+"*** Source #%u ***\n"
+"Name: %s\n"
+"Driver: %s\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Owner Module: %u\n"
+"Volume: %s\n"
+"Monitor of Sink: %s\n"
+"Latency: %0.0f usec, configured %0.0f usec\n"
+"Flags: %s%s%s%s%s%s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+"*** Source #%u ***\n"
+"Nom : %s\n"
+"Pilote : %s\n"
+"Spécification de l'échantillon : %s\n"
+"Plan des canaux : %s\n"
+"Module propriétaire : %u\n"
+"Volume : %s\n"
+"Moniteur de la destination : %s\n"
+"Latence : %0.0f µs, %0.0f µs configurée \n"
+"Drapeaux : %s%s%s%s%s%s\n"
+"Propriétés :\n"
+"%s"
+
+#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322
+#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374
+#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425
+#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473
+msgid "n/a"
+msgstr "n/d"
+
+#: ../src/utils/pactl.c:263
+#, c-format
+msgid "Failed to get module information: %s\n"
+msgstr "Échec lors de l'obtention des informations du module : %s\n"
+
+#: ../src/utils/pactl.c:281
+#, c-format
+msgid ""
+"*** Module #%u ***\n"
+"Name: %s\n"
+"Argument: %s\n"
+"Usage counter: %s\n"
+"Auto unload: %s\n"
+msgstr ""
+"*** Module #%u ***\n"
+"Nom : %s\n"
+"Paramètre : %s\n"
+"Nombre d'utilisations : %s\n"
+"Déchargement automatique : %s\n"
+
+#: ../src/utils/pactl.c:298
+#, c-format
+msgid "Failed to get client information: %s\n"
+msgstr "Échec lors de l'obtention des informations du client : %s\n"
+
+#: ../src/utils/pactl.c:316
+#, c-format
+msgid ""
+"*** Client #%u ***\n"
+"Driver: %s\n"
+"Owner Module: %s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+"*** Client #%u ***\n"
+"Pilote : %s\n"
+"Module propriétaire : %s\n"
+"Propriétés :\n"
+"%s"
+
+#: ../src/utils/pactl.c:333
+#, c-format
+msgid "Failed to get sink input information: %s\n"
+msgstr ""
+"Échec lors de l'obtention des informations de l'entrée de la destination : %"
+"s\n"
+
+#: ../src/utils/pactl.c:352
+#, c-format
+msgid ""
+"*** Sink Input #%u ***\n"
+"Driver: %s\n"
+"Owner Module: %s\n"
+"Client: %s\n"
+"Sink: %u\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Volume: %s\n"
+"Buffer Latency: %0.0f usec\n"
+"Sink Latency: %0.0f usec\n"
+"Resample method: %s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+"*** Entrée de la destination #%u ***\n"
+"Pilote : %s\n"
+"Module propriétaire : %s\n"
+"Client : %s\n"
+"Destination : %u\n"
+"Spécification de l'échantillon : %s\n"
+"Plan des canaux : %s\n"
+"Volume : %s\n"
+"Latence du tampon : %0.0f µs\n"
+"Latence de la destination : %0.0f µs\n"
+"Méthode de rééchantillonnage : %s\n"
+"Propriétés :\n"
+"%s"
+
+#: ../src/utils/pactl.c:385
+#, c-format
+msgid "Failed to get source output information: %s\n"
+msgstr ""
+"Échec lors de l'obtention des informations de la sortie de la source : %s\n"
+
+#: ../src/utils/pactl.c:405
+#, c-format
+msgid ""
+"*** Source Output #%u ***\n"
+"Driver: %s\n"
+"Owner Module: %s\n"
+"Client: %s\n"
+"Source: %u\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Buffer Latency: %0.0f usec\n"
+"Source Latency: %0.0f usec\n"
+"Resample method: %s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+"*** Source Output #%u ***\n"
+"Pilote : %s\n"
+"Module propriétaire : %s\n"
+"Client : %s\n"
+"Source : %u\n"
+"Spécification de l'échantillon : %s\n"
+"Plan des canaux : %s\n"
+"Latence du tampon : %0.0f µs\n"
+"Latence de la source : %0.0f µs\n"
+"Méthode de rééchantillonnage : %s\n"
+"Propriétés :\n"
+"%s"
+
+#: ../src/utils/pactl.c:436
+#, c-format
+msgid "Failed to get sample information: %s\n"
+msgstr "Échec lors de l'obtention des informations de l'échantillon : %s\n"
+
+# Lazy ?
+# load-sample-lazy = Create a new entry in the sample cache, but don't load 
+# the sample immediately. The sample is loaded only when it is first used
+#: ../src/utils/pactl.c:455
+#, c-format
+msgid ""
+"*** Sample #%u ***\n"
+"Name: %s\n"
+"Volume: %s\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Duration: %0.1fs\n"
+"Size: %s\n"
+"Lazy: %s\n"
+"Filename: %s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+"*** Échantillon #%u ***\n"
+"Nom : %s\n"
+"Volume : %s\n"
+"Spécification de l'échantillon : %s\n"
+"Plan des canaux : %s\n"
+"Durée : %0.1f s\n"
+"Taille : %s\n"
+"Cache retardé : %s\n"
+"Nom de fichier : %s\n"
+"Propriétés :\n"
+"%s"
+
+#: ../src/utils/pactl.c:481
+#, c-format
+msgid "Failed to get autoload information: %s\n"
+msgstr ""
+"Échec lors de l'obtention des informations du chargement automatique : %s\n"
+
+#: ../src/utils/pactl.c:497
+#, c-format
+msgid ""
+"*** Autoload Entry #%u ***\n"
+"Name: %s\n"
+"Type: %s\n"
+"Module: %s\n"
+"Argument: %s\n"
+msgstr ""
+"*** Entrée de chargement automatique #%u ***\n"
+"Nom : %s\n"
+"Type : %s\n"
+"Module : %s\n"
+"Paramètre : %s\n"
+
+#: ../src/utils/pactl.c:504
+msgid "sink"
+msgstr "destination"
+
+#: ../src/utils/pactl.c:504
+msgid "source"
+msgstr "source"
+
+#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521
+#, c-format
+msgid "Failure: %s\n"
+msgstr "Échec : %s\n"
+
+#: ../src/utils/pactl.c:545
+#, c-format
+msgid "Failed to upload sample: %s\n"
+msgstr "Échec lors de l'envoi de l'échantillon : %s\n"
+
+#: ../src/utils/pactl.c:562
+#, c-format
+msgid "Premature end of file\n"
+msgstr "Fin prématurée du fichier\n"
+
+#: ../src/utils/pactl.c:678
+#, c-format
+msgid ""
+"%s [options] stat\n"
+"%s [options] list\n"
+"%s [options] exit\n"
+"%s [options] upload-sample FILENAME [NAME]\n"
+"%s [options] play-sample NAME [SINK]\n"
+"%s [options] remove-sample NAME\n"
+"%s [options] move-sink-input ID SINK\n"
+"%s [options] move-source-output ID SOURCE\n"
+"%s [options] load-module NAME [ARGS ...]\n"
+"%s [options] unload-module ID\n"
+"%s [options] suspend-sink [SINK] 1|0\n"
+"%s [options] suspend-source [SOURCE] 1|0\n"
+"\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
+"  -n, --client-name=NAME                How to call this client on the "
+"server\n"
+msgstr ""
+"%s [options] stat\n"
+"%s [options] list\n"
+"%s [options] exit\n"
+"%s [options] upload-sample NOMDEFICHIER [NOM]\n"
+"%s [options] play-sample NOM [DEST]\n"
+"%s [options] remove-sample NOM\n"
+"%s [options] move-sink-input ID DEST\n"
+"%s [options] move-source-output ID SOURCE\n"
+"%s [options] load-module NOM [PARAMS ...]\n"
+"%s [options] unload-module ID\n"
+"%s [options] suspend-sink [DEST] 1|0\n"
+"%s [options] suspend-source [SOURCE] 1|0\n"
+"\n"
+"  -h, --help                            Affiche cette aide\n"
+"      --version                         Affiche la version\n"
+"\n"
+"  -s, --server=SERVEUR                  Le nom du serveur auquel se "
+"connecter\n"
+"  -n, --client-name=NOM                 Définit le nom de ce client sur le "
+"serveur\n"
+
+#: ../src/utils/pactl.c:729
+#, c-format
+msgid ""
+"pactl %s\n"
+"Compiled with libpulse %s\n"
+"Linked with libpulse %s\n"
+msgstr ""
+"pactl %s\n"
+"Compilé avec libpulse %s\n"
+"Lié avec libpulse %s\n"
+
+#: ../src/utils/pactl.c:768
+#, c-format
+msgid "Please specify a sample file to load\n"
+msgstr "Veuillez indiquer un fichier d'échantillon à charger\n"
+
+#: ../src/utils/pactl.c:790
+#, c-format
+msgid "Failed to open sound file.\n"
+msgstr "Échec lors de l'ouverture du fichier audio.\n"
+
+#: ../src/utils/pactl.c:802
+#, c-format
+msgid "You have to specify a sample name to play\n"
+msgstr "Vous devez indiquer un nom d'échantillon à lire\n"
+
+#: ../src/utils/pactl.c:814
+#, c-format
+msgid "You have to specify a sample name to remove\n"
+msgstr "Vous devez indiquer un nom d'échantillon à supprimer\n"
+
+#: ../src/utils/pactl.c:822
+#, c-format
+msgid "You have to specify a sink input index and a sink\n"
+msgstr ""
+"Vous devez indiquer un index de sortie de destination et une destination\n"
+
+#: ../src/utils/pactl.c:831
+#, c-format
+msgid "You have to specify a source output index and a source\n"
+msgstr "Vous devez indiquer un index de sortie de source et une source\n"
+
+#: ../src/utils/pactl.c:845
+#, c-format
+msgid "You have to specify a module name and arguments.\n"
+msgstr "Vous devez indiquer un nom de module et des paramètres.\n"
+
+#: ../src/utils/pactl.c:865
+#, c-format
+msgid "You have to specify a module index\n"
+msgstr "Vous devez indiquer un index de module\n"
+
+#: ../src/utils/pactl.c:875
+#, c-format
+msgid ""
+"You may not specify more than one sink. You have to specify at least one "
+"boolean value.\n"
+msgstr ""
+"Vous ne pouvez pas indiquer plus d'une destination. Vous devez indiquer au "
+"moins une valeur booléenne.\n"
+
+#: ../src/utils/pactl.c:888
+#, c-format
+msgid ""
+"You may not specify more than one source. You have to specify at least one "
+"boolean value.\n"
+msgstr ""
+"Vous ne pouvez pas indiquer plus d'une source. Vous devez indiquer au moins "
+"une valeur booléenne.\n"
+
+#: ../src/utils/pactl.c:904
+#, c-format
+msgid "No valid command specified.\n"
+msgstr "Aucune commande valide indiquée.\n"
+
+#: ../src/utils/pax11publish.c:61
+#, c-format
+msgid ""
+"%s [-D display] [-S server] [-O sink] [-I source] [-c file]  [-d|-e|-i|-r]\n"
+"\n"
+" -d    Show current PulseAudio data attached to X11 display (default)\n"
+" -e    Export local PulseAudio data to X11 display\n"
+" -i    Import PulseAudio data from X11 display to local environment "
+"variables and cookie file.\n"
+" -r    Remove PulseAudio data from X11 display\n"
+msgstr ""
+"%s [-D visuel] [-S serveur] [-O destination] [-I source] [-c fichier]  [-d|-"
+"e|-i|-r]\n"
+"\n"
+" -d    Affiche les données PulseAudio actuelles attachées au visuel X11 (par "
+"défaut)\n"
+" -e    Exporte les données PulseAudio locales vers le visuel X11\n"
+" -i    Importe les données PulseAudio depuis le visuel X11 vers les "
+"variables de l'environnement local et le fichier de cookie.\n"
+" -r    Enlève les données PulseAudio du visuel X11\n"
+
+#: ../src/utils/pax11publish.c:94
+#, c-format
+msgid "Failed to parse command line.\n"
+msgstr "Échec lors de l'analyse de la ligne de commande.\n"
+
+#: ../src/utils/pax11publish.c:108
+#, c-format
+msgid "Server: %s\n"
+msgstr "Serveur : %s\n"
+
+#: ../src/utils/pax11publish.c:110
+#, c-format
+msgid "Source: %s\n"
+msgstr "Source : %s\n"
+
+#: ../src/utils/pax11publish.c:112
+#, c-format
+msgid "Sink: %s\n"
+msgstr "Destination : %s\n"
+
+#: ../src/utils/pax11publish.c:114
+#, c-format
+msgid "Cookie: %s\n"
+msgstr "Cookie : %s\n"
+
+#: ../src/utils/pax11publish.c:132
+#, c-format
+msgid "Failed to parse cookie data\n"
+msgstr "Échec lors de l'analyse des données du cookie\n"
+
+#: ../src/utils/pax11publish.c:137
+#, c-format
+msgid "Failed to save cookie data\n"
+msgstr "Échec lors de l'enregistrement des données du cookie\n"
+
+#: ../src/utils/pax11publish.c:152
+#, c-format
+msgid "Failed to load client configuration file.\n"
+msgstr "Échec lors du chargement du fichier de configuration du client.\n"
+
+#: ../src/utils/pax11publish.c:157
+#, c-format
+msgid "Failed to read environment configuration data.\n"
+msgstr ""
+"Échec lors de la lecture des données de configuration de l'environnement.\n"
+
+# Fully Qualified Domain Name
+#: ../src/utils/pax11publish.c:174
+#, c-format
+msgid "Failed to get FQDN.\n"
+msgstr "Échec lors de l'obtention du FQDN (« nom de domaine complet »).\n"
+
+#: ../src/utils/pax11publish.c:194
+#, c-format
+msgid "Failed to load cookie data\n"
+msgstr "Échec lors du chargement des données du cookie\n"
+
+#: ../src/utils/pax11publish.c:211
+#, c-format
+msgid "Not yet implemented.\n"
+msgstr "Pas encore implémenté.\n"
+
+#: ../src/utils/pacmd.c:64
+#, c-format
+msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s"
+msgstr "socket(PF_UNIX, SOCK_STREAM, 0) : %s"
+
+#: ../src/utils/pacmd.c:81
+#, c-format
+msgid "connect(): %s"
+msgstr "connect() : %s"
+
+#: ../src/utils/pacmd.c:89
+msgid "Failed to kill PulseAudio daemon."
+msgstr "Impossible de tuer le démon PulseAudio."
+
+#: ../src/utils/pacmd.c:97
+msgid "Daemon not responding."
+msgstr "Le démon ne répond pas."
+
+#: ../src/utils/pacmd.c:112
+#, c-format
+msgid "select(): %s"
+msgstr "select() : %s"
+
+#: ../src/utils/pacmd.c:124 ../src/utils/pacmd.c:140
+#, c-format
+msgid "read(): %s"
+msgstr "read() : %s"
+
+#: ../src/utils/pacmd.c:153 ../src/utils/pacmd.c:167
+#, c-format
+msgid "write(): %s"
+msgstr "write() : %s"
+
+#: ../src/utils/paplay.c:139
+#, c-format
+msgid "Stream successfully created\n"
+msgstr "Création du flux réussie\n"
+
+#: ../src/utils/paplay.c:144
+#, c-format
+msgid "Stream errror: %s\n"
+msgstr "Erreur du flux : %s\n"
+
+#: ../src/utils/paplay.c:165
+#, c-format
+msgid "Connection established.\n"
+msgstr "Connexion établie.\n"
+
+#: ../src/utils/paplay.c:198
+#, c-format
+msgid ""
+"%s [options] [FILE]\n"
+"\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"\n"
+"  -v, --verbose                         Enable verbose operation\n"
+"\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
+"  -d, --device=DEVICE                   The name of the sink to connect to\n"
+"  -n, --client-name=NAME                How to call this client on the "
+"server\n"
+"      --stream-name=NAME                How to call this stream on the "
+"server\n"
+"      --volume=VOLUME                   Specify the initial (linear) volume "
+"in range 0...65536\n"
+"      --channel-map=CHANNELMAP          Set the channel map to the use\n"
+msgstr ""
+"%s [options] [FICHIER]\n"
+"\n"
+"  -h, --help                            Affiche cette aide\n"
+"      --version                         Affiche la version\n"
+"\n"
+"  -v, --verbose                         Active le mode verbeux\n"
+"\n"
+"  -s, --server=SERVEUR                  Le nom du serveur auquel se "
+"connecter\n"
+"  -d, --device=PÉRIPHÉRIQUE             Le nom de la destination à laquelle "
+"se connecter\n"
+"  -n, --client-name=NOM                 Définit le nom de ce client sur le "
+"serveur\n"
+"      --stream-name=NOM                 Définit le nom de ce flux sur le "
+"serveur\n"
+"      --volume=VOLUME                   Définit le volume initial (linéaire) "
+"entre 0 et 65536\n"
+"      --channel-map=PLANDESCANAUX       Définit le plan des canaux à "
+"utiliser\n"
+
+#: ../src/utils/paplay.c:255
+#, c-format
+msgid ""
+"paplay %s\n"
+"Compiled with libpulse %s\n"
+"Linked with libpulse %s\n"
+msgstr ""
+"paplay %s\n"
+"Compilé avec libpulse %s\n"
+"Lié avec libpulse %s\n"
+
+#: ../src/utils/paplay.c:292
+#, c-format
+msgid "Invalid channel map\n"
+msgstr "Plan des canaux invalide\n"
+
+#: ../src/utils/paplay.c:314
+#, c-format
+msgid "Failed to open file '%s'\n"
+msgstr "Échec lors de l'ouverture du fichier « %s »\n"
+
+#: ../src/utils/paplay.c:350
+#, c-format
+msgid "Channel map doesn't match file.\n"
+msgstr "Le plan des canaux ne correspond pas au fichier.\n"
+
+#: ../src/utils/paplay.c:376
+#, c-format
+msgid "Using sample spec '%s'\n"
+msgstr "Utilisation de la spécification de l'échantillon « %s »\n"
diff --git a/po/sv.po b/po/sv.po
new file mode 100644 (file)
index 0000000..11f6e13
--- /dev/null
+++ b/po/sv.po
@@ -0,0 +1,1799 @@
+# Swedish translation for pulseaudio.
+# Copyright (C) 2008 Free Software Foundation, Inc.
+# This file is distributed under the same license as the pulseaudio package.
+# Daniel Nylander <po@danielnylander.se>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pulseaudio\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-09-04 19:30+0000\n"
+"PO-Revision-Date: 2008-09-05 18:24+0100\n"
+"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../src/daemon/ltdl-bind-now.c:177
+#: ../src/daemon/ltdl-bind-now.c:197
+msgid "Failed to add bind-now-loader."
+msgstr ""
+
+#: ../src/daemon/ltdl-bind-now.c:184
+msgid "Failed to find original dlopen loader."
+msgstr ""
+
+#: ../src/daemon/polkit.c:55
+#, c-format
+msgid "Cannot connect to system bus: %s"
+msgstr ""
+
+#: ../src/daemon/polkit.c:65
+#, c-format
+msgid "Cannot get caller from PID: %s"
+msgstr ""
+
+#: ../src/daemon/polkit.c:77
+msgid "Cannot set UID on caller object."
+msgstr ""
+
+#: ../src/daemon/polkit.c:82
+msgid "Failed to get CK session."
+msgstr ""
+
+#: ../src/daemon/polkit.c:90
+msgid "Cannot set UID on session object."
+msgstr ""
+
+#: ../src/daemon/polkit.c:95
+msgid "Cannot allocate PolKitAction."
+msgstr ""
+
+#: ../src/daemon/polkit.c:100
+msgid "Cannot set action_id"
+msgstr ""
+
+#: ../src/daemon/polkit.c:105
+msgid "Cannot allocate PolKitContext."
+msgstr ""
+
+#: ../src/daemon/polkit.c:110
+#, c-format
+msgid "Cannot initialize PolKitContext: %s"
+msgstr ""
+
+#: ../src/daemon/polkit.c:119
+#, c-format
+msgid "Could not determine whether caller is authorized: %s"
+msgstr ""
+
+#: ../src/daemon/polkit.c:139
+#, c-format
+msgid "Cannot obtain auth: %s"
+msgstr ""
+
+#: ../src/daemon/polkit.c:148
+#, c-format
+msgid "PolicyKit responded with '%s'"
+msgstr "PolicyKit svarade med \"%s\""
+
+#: ../src/daemon/main.c:134
+#, c-format
+msgid "Got signal %s."
+msgstr "Fick signal %s."
+
+#: ../src/daemon/main.c:161
+msgid "Exiting."
+msgstr "Avslutar."
+
+#: ../src/daemon/main.c:179
+#, c-format
+msgid "Failed to find user '%s'."
+msgstr "Misslyckades med att hitta användaren \"%s\"."
+
+#: ../src/daemon/main.c:184
+#, c-format
+msgid "Failed to find group '%s'."
+msgstr "Misslyckades med att hitta gruppen \"%s\"."
+
+#: ../src/daemon/main.c:188
+#, c-format
+msgid "Found user '%s' (UID %lu) and group '%s' (GID %lu)."
+msgstr ""
+
+#: ../src/daemon/main.c:193
+#, c-format
+msgid "GID of user '%s' and of group '%s' don't match."
+msgstr ""
+
+#: ../src/daemon/main.c:198
+#, c-format
+msgid "Home directory of user '%s' is not '%s', ignoring."
+msgstr "Hemkatalogen för användaren \"%s\" är inte \"%s\", ignorerar."
+
+#: ../src/daemon/main.c:201
+#: ../src/daemon/main.c:206
+#, c-format
+msgid "Failed to create '%s': %s"
+msgstr "Misslyckades med att skapa \"%s\": %s"
+
+#: ../src/daemon/main.c:213
+#, c-format
+msgid "Failed to change group list: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:229
+#, c-format
+msgid "Failed to change GID: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:245
+#, c-format
+msgid "Failed to change UID: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:259
+msgid "Successfully dropped root privileges."
+msgstr ""
+
+#: ../src/daemon/main.c:267
+msgid "System wide mode unsupported on this platform."
+msgstr ""
+
+#: ../src/daemon/main.c:285
+#, c-format
+msgid "setrlimit(%s, (%u, %u)) failed: %s"
+msgstr "setrlimit(%s, (%u, %u)) misslyckades: %s"
+
+#: ../src/daemon/main.c:425
+msgid "Failed to parse command line."
+msgstr ""
+
+#: ../src/daemon/main.c:441
+#, c-format
+msgid "We're in the group '%s', allowing high-priority scheduling."
+msgstr ""
+
+#: ../src/daemon/main.c:448
+#, c-format
+msgid "We're in the group '%s', allowing real-time scheduling."
+msgstr ""
+
+#: ../src/daemon/main.c:456
+msgid "PolicyKit grants us acquire-high-priority privilege."
+msgstr ""
+
+#: ../src/daemon/main.c:459
+msgid "PolicyKit refuses acquire-high-priority privilege."
+msgstr ""
+
+#: ../src/daemon/main.c:464
+msgid "PolicyKit grants us acquire-real-time privilege."
+msgstr ""
+
+#: ../src/daemon/main.c:467
+msgid "PolicyKit refuses acquire-real-time privilege."
+msgstr ""
+
+#: ../src/daemon/main.c:479
+msgid ""
+"Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n"
+"We are not in group '"
+msgstr ""
+
+#: ../src/daemon/main.c:480
+msgid ""
+"' and PolicyKit refuse to grant us priviliges. Dropping SUID again.\n"
+"For enabling real-time scheduling please acquire the appropriate PolicyKit priviliges, or become a member of '"
+msgstr ""
+
+#: ../src/daemon/main.c:481
+msgid "', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."
+msgstr ""
+
+#: ../src/daemon/main.c:497
+msgid "High-priority scheduling enabled in configuration but not allowed by policy."
+msgstr ""
+
+#: ../src/daemon/main.c:522
+msgid "Successfully increased RLIMIT_RTPRIO"
+msgstr ""
+
+#: ../src/daemon/main.c:525
+#, c-format
+msgid "RLIMIT_RTPRIO failed: %s"
+msgstr "RLIMIT_RTPRIO misslyckades: %s"
+
+#: ../src/daemon/main.c:532
+msgid "Giving up CAP_NICE"
+msgstr ""
+
+#: ../src/daemon/main.c:539
+msgid "Real-time scheduling enabled in configuration but not allowed by policy."
+msgstr ""
+
+#: ../src/daemon/main.c:597
+msgid "Daemon not running"
+msgstr ""
+
+#: ../src/daemon/main.c:599
+#, c-format
+msgid "Daemon running as PID %u"
+msgstr ""
+
+#: ../src/daemon/main.c:609
+#, c-format
+msgid "Failed to kill daemon: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:627
+msgid "This program is not intended to be run as root (unless --system is specified)."
+msgstr "Detta program är inte tänkt att köras som root (såvida inte --system har angivits)."
+
+#: ../src/daemon/main.c:629
+msgid "Root priviliges required."
+msgstr "Root-behörighet krävs."
+
+#: ../src/daemon/main.c:634
+msgid "--start not supported for system instances."
+msgstr "--start stöds inte för systeminstanser."
+
+#: ../src/daemon/main.c:639
+msgid "Running in system mode, but --disallow-exit not set!"
+msgstr ""
+
+#: ../src/daemon/main.c:642
+msgid "Running in system mode, but --disallow-module-loading not set!"
+msgstr ""
+
+#: ../src/daemon/main.c:645
+msgid "Running in system mode, forcibly disabling SHM mode!"
+msgstr ""
+
+#: ../src/daemon/main.c:650
+msgid "Running in system mode, forcibly disabling exit idle time!"
+msgstr ""
+
+#: ../src/daemon/main.c:677
+msgid "Failed to acquire stdio."
+msgstr ""
+
+#: ../src/daemon/main.c:683
+#, c-format
+msgid "pipe failed: %s"
+msgstr "pipe misslyckades: %s"
+
+#: ../src/daemon/main.c:688
+#, c-format
+msgid "fork() failed: %s"
+msgstr "fork() misslyckades: %s"
+
+#: ../src/daemon/main.c:702
+#, c-format
+msgid "read() failed: %s"
+msgstr "read() misslyckades: %s"
+
+#: ../src/daemon/main.c:708
+msgid "Daemon startup failed."
+msgstr ""
+
+#: ../src/daemon/main.c:710
+msgid "Daemon startup successful."
+msgstr ""
+
+#: ../src/daemon/main.c:780
+#, c-format
+msgid "This is PulseAudio %s"
+msgstr "Detta är PulseAudio %s"
+
+#: ../src/daemon/main.c:781
+#, c-format
+msgid "Compilation CFLAGS: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:784
+msgid "Compiled with Valgrind support: yes"
+msgstr ""
+
+#: ../src/daemon/main.c:786
+msgid "Compiled with Valgrind support: no"
+msgstr ""
+
+#: ../src/daemon/main.c:790
+msgid "Optimized build: yes"
+msgstr ""
+
+#: ../src/daemon/main.c:792
+msgid "Optimized build: no"
+msgstr ""
+
+#: ../src/daemon/main.c:795
+#, c-format
+msgid "Page size is %lu bytes"
+msgstr ""
+
+#: ../src/daemon/main.c:798
+msgid "Failed to get machine ID"
+msgstr ""
+
+#: ../src/daemon/main.c:801
+#, c-format
+msgid "Machine ID is %s."
+msgstr ""
+
+#: ../src/daemon/main.c:806
+#, c-format
+msgid "Using runtime directory %s."
+msgstr ""
+
+#: ../src/daemon/main.c:811
+#, c-format
+msgid "Using state directory %s."
+msgstr ""
+
+#: ../src/daemon/main.c:814
+#, c-format
+msgid "Running in system mode: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:829
+msgid "pa_pid_file_create() failed."
+msgstr "pa_pid_file_create() misslyckades."
+
+#: ../src/daemon/main.c:841
+msgid "Fresh high-resolution timers available! Bon appetit!"
+msgstr ""
+
+#: ../src/daemon/main.c:843
+msgid "Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"
+msgstr ""
+
+#: ../src/daemon/main.c:853
+msgid "pa_core_new() failed."
+msgstr "pa_core_new() misslyckades."
+
+#: ../src/daemon/main.c:913
+msgid "Failed to initialize daemon."
+msgstr ""
+
+#: ../src/daemon/main.c:918
+msgid "Daemon startup without any loaded modules, refusing to work."
+msgstr ""
+
+#: ../src/daemon/main.c:923
+#, c-format
+msgid "Default sink name (%s) does not exist in name register."
+msgstr ""
+
+#: ../src/daemon/main.c:936
+msgid "Daemon startup complete."
+msgstr ""
+
+#: ../src/daemon/main.c:942
+msgid "Daemon shutdown initiated."
+msgstr ""
+
+#: ../src/daemon/main.c:963
+msgid "Daemon terminated."
+msgstr ""
+
+#: ../src/daemon/cmdline.c:117
+#, c-format
+msgid ""
+"%s [options]\n"
+"\n"
+"COMMANDS:\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"      --dump-conf                       Dump default configuration\n"
+"      --dump-modules                    Dump list of available modules\n"
+"      --dump-resample-methods           Dump available resample methods\n"
+"      --cleanup-shm                     Cleanup stale shared memory segments\n"
+"      --start                           Start the daemon if it is not running\n"
+"  -k  --kill                            Kill a running daemon\n"
+"      --check                           Check for a running daemon\n"
+"\n"
+"OPTIONS:\n"
+"      --system[=BOOL]                   Run as system-wide instance\n"
+"  -D, --daemonize[=BOOL]                Daemonize after startup\n"
+"      --fail[=BOOL]                     Quit when startup fails\n"
+"      --high-priority[=BOOL]            Try to set high nice level\n"
+"                                        (only available as root, when SUID or\n"
+"                                        with elevated RLIMIT_NICE)\n"
+"      --realtime[=BOOL]                 Try to enable realtime scheduling\n"
+"                                        (only available as root, when SUID or\n"
+"                                        with elevated RLIMIT_RTPRIO)\n"
+"      --disallow-module-loading[=BOOL]  Disallow module user requested module\n"
+"                                        loading/unloading after startup\n"
+"      --disallow-exit[=BOOL]            Disallow user requested exit\n"
+"      --exit-idle-time=SECS             Terminate the daemon when idle and this\n"
+"                                        time passed\n"
+"      --module-idle-time=SECS           Unload autoloaded modules when idle and\n"
+"                                        this time passed\n"
+"      --scache-idle-time=SECS           Unload autoloaded samples when idle and\n"
+"                                        this time passed\n"
+"      --log-level[=LEVEL]               Increase or set verbosity level\n"
+"  -v                                    Increase the verbosity level\n"
+"      --log-target={auto,syslog,stderr} Specify the log target\n"
+"  -p, --dl-search-path=PATH             Set the search path for dynamic shared\n"
+"                                        objects (plugins)\n"
+"      --resample-method=METHOD          Use the specified resampling method\n"
+"                                        (See --dump-resample-methods for\n"
+"                                        possible values)\n"
+"      --use-pid-file[=BOOL]             Create a PID file\n"
+"      --no-cpu-limit[=BOOL]             Do not install CPU load limiter on\n"
+"                                        platforms that support it.\n"
+"      --disable-shm[=BOOL]              Disable shared memory support.\n"
+"\n"
+"STARTUP SCRIPT:\n"
+"  -L, --load=\"MODULE ARGUMENTS\"         Load the specified plugin module with\n"
+"                                        the specified argument\n"
+"  -F, --file=FILENAME                   Run the specified script\n"
+"  -C                                    Open a command line on the running TTY\n"
+"                                        after startup\n"
+"\n"
+"  -n                                    Don't load default script file\n"
+msgstr ""
+
+#: ../src/daemon/cmdline.c:245
+msgid "--daemonize expects boolean argument"
+msgstr "--daemonize förväntar sig ett booleskt argument"
+
+#: ../src/daemon/cmdline.c:252
+msgid "--fail expects boolean argument"
+msgstr "--fail förväntar sig ett booleskt argument"
+
+#: ../src/daemon/cmdline.c:262
+msgid "--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."
+msgstr ""
+
+#: ../src/daemon/cmdline.c:274
+msgid "--high-priority expects boolean argument"
+msgstr "--high-priority förväntar sig ett booleskt argument"
+
+#: ../src/daemon/cmdline.c:281
+msgid "--realtime expects boolean argument"
+msgstr "--realtime förväntar sig ett booleskt argument"
+
+#: ../src/daemon/cmdline.c:288
+msgid "--disallow-module-loading expects boolean argument"
+msgstr "--disallow-module-loading förväntar sig ett booleskt argument"
+
+#: ../src/daemon/cmdline.c:295
+msgid "--disallow-exit boolean argument"
+msgstr "--disallow-exit booleskt argument"
+
+#: ../src/daemon/cmdline.c:302
+msgid "--use-pid-file expects boolean argument"
+msgstr "--use-pid-file förväntar sig ett booleskt argument"
+
+#: ../src/daemon/cmdline.c:319
+msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'."
+msgstr ""
+
+#: ../src/daemon/cmdline.c:338
+#, c-format
+msgid "Invalid resample method '%s'."
+msgstr ""
+
+#: ../src/daemon/cmdline.c:345
+msgid "--system expects boolean argument"
+msgstr "--system förväntar sig ett booleskt argument"
+
+#: ../src/daemon/cmdline.c:352
+msgid "--no-cpu-limit expects boolean argument"
+msgstr "--no-cpu-limit förväntar sig ett booleskt argument"
+
+#: ../src/daemon/cmdline.c:359
+msgid "--disable-shm expects boolean argument"
+msgstr "--disable-shm förväntar sig ett booleskt argument"
+
+#: ../src/daemon/dumpmodules.c:60
+#, c-format
+msgid "Name: %s\n"
+msgstr "Namn: %s\n"
+
+#: ../src/daemon/dumpmodules.c:63
+#, c-format
+msgid "No module information available\n"
+msgstr ""
+
+#: ../src/daemon/dumpmodules.c:66
+#, c-format
+msgid "Version: %s\n"
+msgstr "Version: %s\n"
+
+#: ../src/daemon/dumpmodules.c:68
+#, c-format
+msgid "Description: %s\n"
+msgstr "Beskrivning: %s\n"
+
+#: ../src/daemon/dumpmodules.c:70
+#, c-format
+msgid "Author: %s\n"
+msgstr "Upphovsman: %s\n"
+
+#: ../src/daemon/dumpmodules.c:72
+#, c-format
+msgid "Usage: %s\n"
+msgstr "Användning: %s\n"
+
+#: ../src/daemon/dumpmodules.c:73
+#, c-format
+msgid "Load Once: %s\n"
+msgstr ""
+
+#: ../src/daemon/dumpmodules.c:77
+#, c-format
+msgid "Path: %s\n"
+msgstr "Sökväg: %s\n"
+
+#: ../src/daemon/daemon-conf.c:203
+#, c-format
+msgid "[%s:%u] Invalid log target '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:219
+#, c-format
+msgid "[%s:%u] Invalid log level '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:235
+#, c-format
+msgid "[%s:%u] Invalid resample method '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:258
+#, c-format
+msgid "[%s:%u] Invalid rlimit '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:265
+#, c-format
+msgid "[%s:%u] rlimit not supported on this platform."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:281
+#, c-format
+msgid "[%s:%u] Invalid sample format '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:299
+#, c-format
+msgid "[%s:%u] Invalid sample rate '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:317
+#, c-format
+msgid "[%s:%u] Invalid sample channels '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:335
+#, c-format
+msgid "[%s:%u] Invalid number of fragments '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:353
+#, c-format
+msgid "[%s:%u] Invalid fragment size '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:371
+#, c-format
+msgid "[%s:%u] Invalid nice level '%s'."
+msgstr ""
+
+#: ../src/daemon/daemon-conf.c:564
+#, c-format
+msgid "Failed to open configuration file: %s"
+msgstr "Misslyckades med att öppna konfigurationsfil: %s"
+
+#: ../src/daemon/daemon-conf.c:638
+#, c-format
+msgid "### Read from configuration file: %s ###\n"
+msgstr ""
+
+#: ../src/daemon/caps.c:62
+msgid "Dropping root priviliges."
+msgstr "Släpper root-behörighet."
+
+#: ../src/daemon/caps.c:102
+msgid "Limited capabilities successfully to CAP_SYS_NICE."
+msgstr ""
+
+#: ../src/pulse/channelmap.c:102
+msgid "Mono"
+msgstr "Mono"
+
+#: ../src/pulse/channelmap.c:104
+msgid "Front Center"
+msgstr "Center fram"
+
+#: ../src/pulse/channelmap.c:105
+msgid "Front Left"
+msgstr "Vänster fram"
+
+#: ../src/pulse/channelmap.c:106
+msgid "Front Right"
+msgstr "Höger fram"
+
+#: ../src/pulse/channelmap.c:108
+msgid "Rear Center"
+msgstr "Center bak"
+
+#: ../src/pulse/channelmap.c:109
+msgid "Rear Left"
+msgstr "Vänster bak"
+
+#: ../src/pulse/channelmap.c:110
+msgid "Rear Right"
+msgstr "Höger bak"
+
+#: ../src/pulse/channelmap.c:112
+msgid "Low Frequency Emmiter"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:114
+msgid "Front Left-of-center"
+msgstr "Vänster-om-center fram"
+
+#: ../src/pulse/channelmap.c:115
+msgid "Front Right-of-center"
+msgstr "Höger-om-center fram"
+
+#: ../src/pulse/channelmap.c:117
+msgid "Side Left"
+msgstr "Vänster sida"
+
+#: ../src/pulse/channelmap.c:118
+msgid "Side Right"
+msgstr "Höger sida"
+
+#: ../src/pulse/channelmap.c:120
+msgid "Auxiliary 0"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:121
+msgid "Auxiliary 1"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:122
+msgid "Auxiliary 2"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:123
+msgid "Auxiliary 3"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:124
+msgid "Auxiliary 4"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:125
+msgid "Auxiliary 5"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:126
+msgid "Auxiliary 6"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:127
+msgid "Auxiliary 7"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:128
+msgid "Auxiliary 8"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:129
+msgid "Auxiliary 9"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:130
+msgid "Auxiliary 10"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:131
+msgid "Auxiliary 11"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:132
+msgid "Auxiliary 12"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:133
+msgid "Auxiliary 13"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:134
+msgid "Auxiliary 14"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:135
+msgid "Auxiliary 15"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:136
+msgid "Auxiliary 16"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:137
+msgid "Auxiliary 17"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:138
+msgid "Auxiliary 18"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:139
+msgid "Auxiliary 19"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:140
+msgid "Auxiliary 20"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:141
+msgid "Auxiliary 21"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:142
+msgid "Auxiliary 22"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:143
+msgid "Auxiliary 23"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:144
+msgid "Auxiliary 24"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:145
+msgid "Auxiliary 25"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:146
+msgid "Auxiliary 26"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:147
+msgid "Auxiliary 27"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:148
+msgid "Auxiliary 28"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:149
+msgid "Auxiliary 29"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:150
+msgid "Auxiliary 30"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:151
+msgid "Auxiliary 31"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:153
+msgid "Top Center"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:155
+msgid "Top Front Center"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:156
+msgid "Top Front Left"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:157
+msgid "Top Front Right"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:159
+msgid "Top Rear Center"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:160
+msgid "Top Rear Left"
+msgstr ""
+
+#: ../src/pulse/channelmap.c:161
+msgid "Top Rear Right"
+msgstr ""
+
+#: ../src/pulse/error.c:43
+msgid "OK"
+msgstr "OK"
+
+#: ../src/pulse/error.c:44
+msgid "Access denied"
+msgstr "Åtkomst nekad"
+
+#: ../src/pulse/error.c:45
+msgid "Unknown command"
+msgstr "Okänt kommando"
+
+#: ../src/pulse/error.c:46
+msgid "Invalid argument"
+msgstr "Ogiltigt argument"
+
+#: ../src/pulse/error.c:47
+msgid "Entity exists"
+msgstr "Entiteten finns"
+
+#: ../src/pulse/error.c:48
+msgid "No such entity"
+msgstr "Ingen sådan entitet"
+
+#: ../src/pulse/error.c:49
+msgid "Connection refused"
+msgstr "Anslutning nekades"
+
+#: ../src/pulse/error.c:50
+msgid "Protocol error"
+msgstr "Protokollfel"
+
+#: ../src/pulse/error.c:51
+msgid "Timeout"
+msgstr "Tidsgräns nåddes"
+
+#: ../src/pulse/error.c:52
+msgid "No authorization key"
+msgstr ""
+
+#: ../src/pulse/error.c:53
+msgid "Internal error"
+msgstr "Internt fel"
+
+#: ../src/pulse/error.c:54
+msgid "Connection terminated"
+msgstr "Anslutningen terminerad"
+
+#: ../src/pulse/error.c:55
+msgid "Entity killed"
+msgstr ""
+
+#: ../src/pulse/error.c:56
+msgid "Invalid server"
+msgstr "Ogiltig server"
+
+#: ../src/pulse/error.c:57
+msgid "Module initalization failed"
+msgstr ""
+
+#: ../src/pulse/error.c:58
+msgid "Bad state"
+msgstr "Felaktigt tillstånd"
+
+#: ../src/pulse/error.c:59
+msgid "No data"
+msgstr "Inget data"
+
+#: ../src/pulse/error.c:60
+msgid "Incompatible protocol version"
+msgstr ""
+
+#: ../src/pulse/error.c:61
+msgid "Too large"
+msgstr "För stor"
+
+#: ../src/pulse/error.c:62
+msgid "Not supported"
+msgstr "Stöds inte"
+
+#: ../src/pulse/error.c:63
+msgid "Unknown error code"
+msgstr "Okänd felkod"
+
+#: ../src/pulse/error.c:64
+msgid "No such extension"
+msgstr ""
+
+#: ../src/pulse/sample.c:134
+msgid "Invalid"
+msgstr "Ogiltig"
+
+#: ../src/pulse/client-conf-x11.c:55
+#: ../src/utils/pax11publish.c:100
+msgid "XOpenDisplay() failed"
+msgstr "XOpenDisplay() misslyckades"
+
+#: ../src/pulse/client-conf-x11.c:78
+msgid "Failed to parse cookie data"
+msgstr ""
+
+#: ../src/pulse/client-conf.c:117
+#, c-format
+msgid "Failed to open configuration file '%s': %s"
+msgstr "Misslyckades med att öppna konfigurationsfilen \"%s\": %s"
+
+#: ../src/pulse/context.c:542
+msgid "No cookie loaded. Attempting to connect without."
+msgstr ""
+
+#: ../src/pulse/context.c:596
+#, c-format
+msgid "socketpair(): %s"
+msgstr "socketpair(): %s"
+
+#: ../src/pulse/context.c:610
+#, c-format
+msgid "fork(): %s"
+msgstr "fork(): %s"
+
+#: ../src/pulse/context.c:673
+#, c-format
+msgid "waitpid(): %s"
+msgstr "waitpid(): %s"
+
+#: ../src/pulse/context.c:1354
+#, c-format
+msgid "Received message for unknown extension '%s'"
+msgstr ""
+
+#: ../src/utils/pacat.c:93
+#, c-format
+msgid "pa_stream_write() failed: %s\n"
+msgstr "pa_stream_write() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:132
+#, c-format
+msgid "pa_stream_peek() failed: %s\n"
+msgstr "pa_stream_peek() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:141
+#, c-format
+msgid "Buffer overrun, dropping incoming data\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:143
+#, c-format
+msgid "pa_stream_drop() failed: %s\n"
+msgstr "pa_stream_drop() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:169
+#, c-format
+msgid "Stream successfully created.\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:172
+#, c-format
+msgid "pa_stream_get_buffer_attr() failed: %s\n"
+msgstr "pa_stream_get_buffer_attr() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:176
+#, c-format
+msgid "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:179
+#, c-format
+msgid "Buffer metrics: maxlength=%u, fragsize=%u\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:183
+#, c-format
+msgid "Using sample spec '%s', channel map '%s'.\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:187
+#, c-format
+msgid "Connected to device %s (%u, %ssuspended).\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:197
+#, c-format
+msgid "Stream error: %s\n"
+msgstr "Strömfel: %s\n"
+
+#: ../src/utils/pacat.c:207
+#, c-format
+msgid "Stream device suspended.%s \n"
+msgstr ""
+
+#: ../src/utils/pacat.c:209
+#, c-format
+msgid "Stream device resumed.%s \n"
+msgstr ""
+
+#: ../src/utils/pacat.c:217
+#, c-format
+msgid "Stream underrun.%s \n"
+msgstr ""
+
+#: ../src/utils/pacat.c:224
+#, c-format
+msgid "Stream overrun.%s \n"
+msgstr ""
+
+#: ../src/utils/pacat.c:231
+#, c-format
+msgid "Stream started.%s \n"
+msgstr ""
+
+#: ../src/utils/pacat.c:238
+#, c-format
+msgid "Stream moved to device %s (%u, %ssuspended).%s \n"
+msgstr ""
+
+#: ../src/utils/pacat.c:238
+msgid "not "
+msgstr "inte "
+
+#: ../src/utils/pacat.c:259
+#, c-format
+msgid "Connection established.%s \n"
+msgstr ""
+
+#: ../src/utils/pacat.c:262
+#, c-format
+msgid "pa_stream_new() failed: %s\n"
+msgstr "pa_stream_new() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:287
+#, c-format
+msgid "pa_stream_connect_playback() failed: %s\n"
+msgstr "pa_stream_connect_playback() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:293
+#, c-format
+msgid "pa_stream_connect_record() failed: %s\n"
+msgstr "pa_stream_connect_record() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:307
+#: ../src/utils/pasuspender.c:159
+#: ../src/utils/pactl.c:666
+#: ../src/utils/paplay.c:183
+#, c-format
+msgid "Connection failure: %s\n"
+msgstr "Anslutningsfel: %s\n"
+
+#: ../src/utils/pacat.c:328
+#: ../src/utils/paplay.c:75
+#, c-format
+msgid "Failed to drain stream: %s\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:333
+#: ../src/utils/paplay.c:80
+#, c-format
+msgid "Playback stream drained.\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:343
+#: ../src/utils/paplay.c:92
+#, c-format
+msgid "Draining connection to server.\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:369
+#, c-format
+msgid "Got EOF.\n"
+msgstr "Fick filslut.\n"
+
+#: ../src/utils/pacat.c:375
+#, c-format
+msgid "pa_stream_drain(): %s\n"
+msgstr "pa_stream_drain(): %s\n"
+
+#: ../src/utils/pacat.c:385
+#, c-format
+msgid "read() failed: %s\n"
+msgstr "read() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:417
+#, c-format
+msgid "write() failed: %s\n"
+msgstr "write() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:438
+#, c-format
+msgid "Got signal, exiting.\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:452
+#, c-format
+msgid "Failed to get latency: %s\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:457
+#, c-format
+msgid "Time: %0.3f sec; Latency: %0.0f usec.  \r"
+msgstr "Tid: %0.3f sec; Latens: %0.0f ms  \r"
+
+#: ../src/utils/pacat.c:477
+#, c-format
+msgid "pa_stream_update_timing_info() failed: %s\n"
+msgstr "pa_stream_update_timing_info() misslyckades: %s\n"
+
+#: ../src/utils/pacat.c:490
+#, c-format
+msgid ""
+"%s [options]\n"
+"\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"\n"
+"  -r, --record                          Create a connection for recording\n"
+"  -p, --playback                        Create a connection for playback\n"
+"\n"
+"  -v, --verbose                         Enable verbose operations\n"
+"\n"
+"  -s, --server=SERVER                   The name of the server to connect to\n"
+"  -d, --device=DEVICE                   The name of the sink/source to connect to\n"
+"  -n, --client-name=NAME                How to call this client on the server\n"
+"      --stream-name=NAME                How to call this stream on the server\n"
+"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
+"      --rate=SAMPLERATE                 The sample rate in Hz (defaults to 44100)\n"
+"      --format=SAMPLEFORMAT             The sample type, one of s16le, s16be, u8, float32le,\n"
+"                                        float32be, ulaw, alaw (defaults to s16ne)\n"
+"      --channels=CHANNELS               The number of channels, 1 for mono, 2 for stereo\n"
+"                                        (defaults to 2)\n"
+"      --channel-map=CHANNELMAP          Channel map to use instead of the default\n"
+"      --fix-format                      Take the sample format from the sink the stream is\n"
+"                                        being connected to.\n"
+"      --fix-rate                        Take the sampling rate from the sink the stream is\n"
+"                                        being connected to.\n"
+"      --fix-channels                    Take the number of channels and the channel map\n"
+"                                        from the sink the stream is being connected to.\n"
+"      --no-remix                        Don't upmix or downmix channels.\n"
+"      --no-remap                        Map channels by index instead of name.\n"
+"      --latency=BYTES                   Request the specified latency in bytes.\n"
+"      --process-time=BYTES              Request the specified process time per request in bytes.\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:591
+#, c-format
+msgid ""
+"pacat %s\n"
+"Compiled with libpulse %s\n"
+"Linked with libpulse %s\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:647
+#, c-format
+msgid "Invalid channel map '%s'\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:676
+#, c-format
+msgid "Invalid latency specification '%s'\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:683
+#, c-format
+msgid "Invalid process time specification '%s'\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:694
+#, c-format
+msgid "Invalid sample specification\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:699
+#, c-format
+msgid "Channel map doesn't match sample specification\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:706
+#, c-format
+msgid "Opening a %s stream with sample specification '%s'.\n"
+msgstr ""
+
+#: ../src/utils/pacat.c:706
+msgid "recording"
+msgstr ""
+
+#: ../src/utils/pacat.c:706
+msgid "playback"
+msgstr ""
+
+#: ../src/utils/pacat.c:714
+#, c-format
+msgid "open(): %s\n"
+msgstr "open(): %s\n"
+
+#: ../src/utils/pacat.c:719
+#, c-format
+msgid "dup2(): %s\n"
+msgstr "dup2(): %s\n"
+
+#: ../src/utils/pacat.c:729
+#, c-format
+msgid "Too many arguments.\n"
+msgstr "För många argument.\n"
+
+#: ../src/utils/pacat.c:742
+#: ../src/utils/pasuspender.c:280
+#: ../src/utils/pactl.c:909
+#: ../src/utils/paplay.c:381
+#, c-format
+msgid "pa_mainloop_new() failed.\n"
+msgstr "pa_mainloop_new() misslyckades.\n"
+
+#: ../src/utils/pacat.c:763
+#, c-format
+msgid "io_new() failed.\n"
+msgstr "io_new() misslyckades.\n"
+
+#: ../src/utils/pacat.c:769
+#: ../src/utils/pasuspender.c:293
+#: ../src/utils/pactl.c:923
+#: ../src/utils/paplay.c:396
+#, c-format
+msgid "pa_context_new() failed.\n"
+msgstr "pa_context_new() misslyckades.\n"
+
+#: ../src/utils/pacat.c:785
+#, c-format
+msgid "time_new() failed.\n"
+msgstr "time_new() misslyckades.\n"
+
+#: ../src/utils/pacat.c:792
+#: ../src/utils/pasuspender.c:301
+#: ../src/utils/pactl.c:931
+#: ../src/utils/paplay.c:407
+#, c-format
+msgid "pa_mainloop_run() failed.\n"
+msgstr "pa_mainloop_run() misslyckades.\n"
+
+#: ../src/utils/pasuspender.c:81
+#, c-format
+msgid "fork(): %s\n"
+msgstr "fork(): %s\n"
+
+#: ../src/utils/pasuspender.c:92
+#, c-format
+msgid "execvp(): %s\n"
+msgstr "execvp(): %s\n"
+
+#: ../src/utils/pasuspender.c:109
+#, c-format
+msgid "Failure to suspend: %s\n"
+msgstr ""
+
+#: ../src/utils/pasuspender.c:124
+#, c-format
+msgid "Failure to resume: %s\n"
+msgstr ""
+
+#: ../src/utils/pasuspender.c:147
+#, c-format
+msgid "WARNING: Sound server is not local, not suspending.\n"
+msgstr ""
+
+#: ../src/utils/pasuspender.c:176
+#: ../src/utils/pactl.c:672
+#: ../src/utils/paplay.c:191
+#, c-format
+msgid "Got SIGINT, exiting.\n"
+msgstr ""
+
+#: ../src/utils/pasuspender.c:194
+#, c-format
+msgid "WARNING: Child process terminated by signal %u\n"
+msgstr ""
+
+#: ../src/utils/pasuspender.c:212
+#, c-format
+msgid ""
+"%s [options] ... \n"
+"\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"  -s, --server=SERVER                   The name of the server to connect to\n"
+"\n"
+msgstr ""
+
+#: ../src/utils/pasuspender.c:251
+#, c-format
+msgid ""
+"pasuspender %s\n"
+"Compiled with libpulse %s\n"
+"Linked with libpulse %s\n"
+msgstr ""
+"pasuspender %s\n"
+"Kompilerad med libpulse %s\n"
+"Länkad med libpulse %s\n"
+
+#: ../src/utils/pactl.c:107
+#, c-format
+msgid "Failed to get statistics: %s\n"
+msgstr "Misslyckades med att få statistik: %s\n"
+
+#: ../src/utils/pactl.c:113
+#, c-format
+msgid "Currently in use: %u blocks containing %s bytes total.\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:116
+#, c-format
+msgid "Allocated during whole lifetime: %u blocks containing %s bytes total.\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:119
+#, c-format
+msgid "Sample cache size: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:128
+#, c-format
+msgid "Failed to get server information: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:135
+#, c-format
+msgid ""
+"User name: %s\n"
+"Host Name: %s\n"
+"Server Name: %s\n"
+"Server Version: %s\n"
+"Default Sample Specification: %s\n"
+"Default Sink: %s\n"
+"Default Source: %s\n"
+"Cookie: %08x\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:160
+#, c-format
+msgid "Failed to get sink information: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:176
+#, c-format
+msgid ""
+"*** Sink #%u ***\n"
+"Name: %s\n"
+"Driver: %s\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Owner Module: %u\n"
+"Volume: %s\n"
+"Monitor Source: %s\n"
+"Latency: %0.0f usec, configured %0.0f usec\n"
+"Flags: %s%s%s%s%s%s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+
+#: ../src/utils/pactl.c:193
+#: ../src/utils/pactl.c:371
+msgid "muted"
+msgstr "tystad"
+
+#: ../src/utils/pactl.c:212
+#, c-format
+msgid "Failed to get source information: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:228
+#, c-format
+msgid ""
+"*** Source #%u ***\n"
+"Name: %s\n"
+"Driver: %s\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Owner Module: %u\n"
+"Volume: %s\n"
+"Monitor of Sink: %s\n"
+"Latency: %0.0f usec, configured %0.0f usec\n"
+"Flags: %s%s%s%s%s%s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+
+#: ../src/utils/pactl.c:246
+#: ../src/utils/pactl.c:289
+#: ../src/utils/pactl.c:322
+#: ../src/utils/pactl.c:366
+#: ../src/utils/pactl.c:367
+#: ../src/utils/pactl.c:374
+#: ../src/utils/pactl.c:418
+#: ../src/utils/pactl.c:419
+#: ../src/utils/pactl.c:425
+#: ../src/utils/pactl.c:468
+#: ../src/utils/pactl.c:469
+#: ../src/utils/pactl.c:473
+msgid "n/a"
+msgstr ""
+
+#: ../src/utils/pactl.c:263
+#, c-format
+msgid "Failed to get module information: %s\n"
+msgstr "Misslyckades med att få modulinformation: %s\n"
+
+#: ../src/utils/pactl.c:281
+#, c-format
+msgid ""
+"*** Module #%u ***\n"
+"Name: %s\n"
+"Argument: %s\n"
+"Usage counter: %s\n"
+"Auto unload: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:298
+#, c-format
+msgid "Failed to get client information: %s\n"
+msgstr "Misslyckades med att få klientinformation: %s\n"
+
+#: ../src/utils/pactl.c:316
+#, c-format
+msgid ""
+"*** Client #%u ***\n"
+"Driver: %s\n"
+"Owner Module: %s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+
+#: ../src/utils/pactl.c:333
+#, c-format
+msgid "Failed to get sink input information: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:352
+#, c-format
+msgid ""
+"*** Sink Input #%u ***\n"
+"Driver: %s\n"
+"Owner Module: %s\n"
+"Client: %s\n"
+"Sink: %u\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Volume: %s\n"
+"Buffer Latency: %0.0f usec\n"
+"Sink Latency: %0.0f usec\n"
+"Resample method: %s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+
+#: ../src/utils/pactl.c:385
+#, c-format
+msgid "Failed to get source output information: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:405
+#, c-format
+msgid ""
+"*** Source Output #%u ***\n"
+"Driver: %s\n"
+"Owner Module: %s\n"
+"Client: %s\n"
+"Source: %u\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Buffer Latency: %0.0f usec\n"
+"Source Latency: %0.0f usec\n"
+"Resample method: %s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+
+#: ../src/utils/pactl.c:436
+#, c-format
+msgid "Failed to get sample information: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:455
+#, c-format
+msgid ""
+"*** Sample #%u ***\n"
+"Name: %s\n"
+"Volume: %s\n"
+"Sample Specification: %s\n"
+"Channel Map: %s\n"
+"Duration: %0.1fs\n"
+"Size: %s\n"
+"Lazy: %s\n"
+"Filename: %s\n"
+"Properties:\n"
+"%s"
+msgstr ""
+
+#: ../src/utils/pactl.c:481
+#, c-format
+msgid "Failed to get autoload information: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:497
+#, c-format
+msgid ""
+"*** Autoload Entry #%u ***\n"
+"Name: %s\n"
+"Type: %s\n"
+"Module: %s\n"
+"Argument: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:504
+msgid "sink"
+msgstr "sink"
+
+#: ../src/utils/pactl.c:504
+msgid "source"
+msgstr "källa"
+
+#: ../src/utils/pactl.c:511
+#: ../src/utils/pactl.c:521
+#, c-format
+msgid "Failure: %s\n"
+msgstr "Fel: %s\n"
+
+#: ../src/utils/pactl.c:545
+#, c-format
+msgid "Failed to upload sample: %s\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:562
+#, c-format
+msgid "Premature end of file\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:678
+#, c-format
+msgid ""
+"%s [options] stat\n"
+"%s [options] list\n"
+"%s [options] exit\n"
+"%s [options] upload-sample FILENAME [NAME]\n"
+"%s [options] play-sample NAME [SINK]\n"
+"%s [options] remove-sample NAME\n"
+"%s [options] move-sink-input ID SINK\n"
+"%s [options] move-source-output ID SOURCE\n"
+"%s [options] load-module NAME [ARGS ...]\n"
+"%s [options] unload-module ID\n"
+"%s [options] suspend-sink [SINK] 1|0\n"
+"%s [options] suspend-source [SOURCE] 1|0\n"
+"\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"\n"
+"  -s, --server=SERVER                   The name of the server to connect to\n"
+"  -n, --client-name=NAME                How to call this client on the server\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:729
+#, c-format
+msgid ""
+"pactl %s\n"
+"Compiled with libpulse %s\n"
+"Linked with libpulse %s\n"
+msgstr ""
+"pactl %s\n"
+"Kompilerad med libpulse %s\n"
+"Länkad med libpulse %s\n"
+
+#: ../src/utils/pactl.c:768
+#, c-format
+msgid "Please specify a sample file to load\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:790
+#, c-format
+msgid "Failed to open sound file.\n"
+msgstr "Misslyckades med att öppna ljudfil.\n"
+
+#: ../src/utils/pactl.c:802
+#, c-format
+msgid "You have to specify a sample name to play\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:814
+#, c-format
+msgid "You have to specify a sample name to remove\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:822
+#, c-format
+msgid "You have to specify a sink input index and a sink\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:831
+#, c-format
+msgid "You have to specify a source output index and a source\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:845
+#, c-format
+msgid "You have to specify a module name and arguments.\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:865
+#, c-format
+msgid "You have to specify a module index\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:875
+#, c-format
+msgid "You may not specify more than one sink. You have to specify at least one boolean value.\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:888
+#, c-format
+msgid "You may not specify more than one source. You have to specify at least one boolean value.\n"
+msgstr ""
+
+#: ../src/utils/pactl.c:904
+#, c-format
+msgid "No valid command specified.\n"
+msgstr ""
+
+#: ../src/utils/pax11publish.c:61
+#, c-format
+msgid ""
+"%s [-D display] [-S server] [-O sink] [-I source] [-c file]  [-d|-e|-i|-r]\n"
+"\n"
+" -d    Show current PulseAudio data attached to X11 display (default)\n"
+" -e    Export local PulseAudio data to X11 display\n"
+" -i    Import PulseAudio data from X11 display to local environment variables and cookie file.\n"
+" -r    Remove PulseAudio data from X11 display\n"
+msgstr ""
+
+#: ../src/utils/pax11publish.c:94
+#, c-format
+msgid "Failed to parse command line.\n"
+msgstr "Misslyckades med att tolka kommandorad.\n"
+
+#: ../src/utils/pax11publish.c:108
+#, c-format
+msgid "Server: %s\n"
+msgstr "Server: %s\n"
+
+#: ../src/utils/pax11publish.c:110
+#, c-format
+msgid "Source: %s\n"
+msgstr "Källa: %s\n"
+
+#: ../src/utils/pax11publish.c:112
+#, c-format
+msgid "Sink: %s\n"
+msgstr "Sink: %s\n"
+
+#: ../src/utils/pax11publish.c:114
+#, c-format
+msgid "Cookie: %s\n"
+msgstr "Kaka: %s\n"
+
+#: ../src/utils/pax11publish.c:132
+#, c-format
+msgid "Failed to parse cookie data\n"
+msgstr ""
+
+#: ../src/utils/pax11publish.c:137
+#, c-format
+msgid "Failed to save cookie data\n"
+msgstr ""
+
+#: ../src/utils/pax11publish.c:152
+#, c-format
+msgid "Failed to load client configuration file.\n"
+msgstr ""
+
+#: ../src/utils/pax11publish.c:157
+#, c-format
+msgid "Failed to read environment configuration data.\n"
+msgstr ""
+
+#: ../src/utils/pax11publish.c:174
+#, c-format
+msgid "Failed to get FQDN.\n"
+msgstr ""
+
+#: ../src/utils/pax11publish.c:194
+#, c-format
+msgid "Failed to load cookie data\n"
+msgstr ""
+
+#: ../src/utils/pax11publish.c:211
+#, c-format
+msgid "Not yet implemented.\n"
+msgstr "Ännu inte implementerad.\n"
+
+#: ../src/utils/pacmd.c:64
+#, c-format
+msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s"
+msgstr ""
+
+#: ../src/utils/pacmd.c:81
+#, c-format
+msgid "connect(): %s"
+msgstr "connect(): %s"
+
+#: ../src/utils/pacmd.c:89
+msgid "Failed to kill PulseAudio daemon."
+msgstr ""
+
+#: ../src/utils/pacmd.c:97
+msgid "Daemon not responding."
+msgstr ""
+
+#: ../src/utils/pacmd.c:112
+#, c-format
+msgid "select(): %s"
+msgstr "select(): %s"
+
+#: ../src/utils/pacmd.c:124
+#: ../src/utils/pacmd.c:140
+#, c-format
+msgid "read(): %s"
+msgstr "read(): %s"
+
+#: ../src/utils/pacmd.c:153
+#: ../src/utils/pacmd.c:167
+#, c-format
+msgid "write(): %s"
+msgstr "write(): %s"
+
+#: ../src/utils/paplay.c:139
+#, c-format
+msgid "Stream successfully created\n"
+msgstr ""
+
+#: ../src/utils/paplay.c:144
+#, c-format
+msgid "Stream errror: %s\n"
+msgstr ""
+
+#: ../src/utils/paplay.c:165
+#, c-format
+msgid "Connection established.\n"
+msgstr "Anslutning etablerad.\n"
+
+#: ../src/utils/paplay.c:198
+#, c-format
+msgid ""
+"%s [options] [FILE]\n"
+"\n"
+"  -h, --help                            Show this help\n"
+"      --version                         Show version\n"
+"\n"
+"  -v, --verbose                         Enable verbose operation\n"
+"\n"
+"  -s, --server=SERVER                   The name of the server to connect to\n"
+"  -d, --device=DEVICE                   The name of the sink to connect to\n"
+"  -n, --client-name=NAME                How to call this client on the server\n"
+"      --stream-name=NAME                How to call this stream on the server\n"
+"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
+"      --channel-map=CHANNELMAP          Set the channel map to the use\n"
+msgstr ""
+
+#: ../src/utils/paplay.c:255
+#, c-format
+msgid ""
+"paplay %s\n"
+"Compiled with libpulse %s\n"
+"Linked with libpulse %s\n"
+msgstr ""
+"paplay %s\n"
+"Kompilerad med libpulse %s\n"
+"Länkad med libpulse %s\n"
+
+#: ../src/utils/paplay.c:292
+#, c-format
+msgid "Invalid channel map\n"
+msgstr ""
+
+#: ../src/utils/paplay.c:314
+#, c-format
+msgid "Failed to open file '%s'\n"
+msgstr "Misslyckades med att öppna filen \"%s\"\n"
+
+#: ../src/utils/paplay.c:350
+#, c-format
+msgid "Channel map doesn't match file.\n"
+msgstr ""
+
+#: ../src/utils/paplay.c:376
+#, c-format
+msgid "Using sample spec '%s'\n"
+msgstr ""
+
index 543f4e8ec74fb0bc6881608bbf40e77025bed84e..72c38cc6a655d20bd77bf79e42196978d8aa3ab4 100644 (file)
@@ -1,3 +1,4 @@
+prioq-test
 lock-autospawn-test
 *.lo
 *.o
@@ -8,7 +9,7 @@ Makefile
 Makefile.in
 asyncmsgq-test
 asyncq-test
-bt-proximity-helper
+proximity-helper
 channelmap-test
 client.conf
 close-test
index 22e691fa038a46883e2cad6e4e37553fb0b6312f..9cbb9c70dd304867674f1b526883a90bb64f0072 100644 (file)
@@ -45,7 +45,7 @@ endif
 #     Compiler/linker flags       #
 ###################################
 
-AM_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src/modules -I$(top_builddir)/src/modules/rtp -I$(top_builddir)/src/modules/gconf
+AM_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src/modules -I$(top_builddir)/src/modules/rtp -I$(top_builddir)/src/modules/gconf -I$(top_builddir)/src/modules/bluetooth
 AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS
 AM_CFLAGS += $(LTDLINCL)
 AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) $(LIBSPEEX_CFLAGS)
@@ -62,8 +62,8 @@ AM_CFLAGS += -DPA_MACHINE_ID=\"$(localstatedir)/lib/dbus/machine-id\"
 # This cool debug trap works on i386/gcc only
 AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")'
 
-AM_LIBADD = $(PTHREAD_LIBS)
-AM_LDADD = $(PTHREAD_LIBS)
+AM_LIBADD = $(PTHREAD_LIBS) $(INTLLIBS)
+AM_LDADD = $(PTHREAD_LIBS) $(INTLLIBS)
 
 # Only required on some platforms but defined for all to avoid errors
 AM_LDFLAGS = -Wl,-no-undefined -Wl,--gc-sections
@@ -263,7 +263,8 @@ noinst_PROGRAMS = \
                proplist-test \
                rtstutter \
                stripnul \
-               lock-autospawn-test
+               lock-autospawn-test \
+               prioq-test
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -458,6 +459,11 @@ lock_autospawn_test_LDADD = $(AM_LDADD) libpulsecore.la
 lock_autospawn_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
 lock_autospawn_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
 
+prioq_test_SOURCES = tests/prioq-test.c
+prioq_test_LDADD = $(AM_LDADD) libpulsecore.la
+prioq_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
+prioq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+
 ###################################
 #         Client library          #
 ###################################
@@ -541,8 +547,7 @@ libpulse_la_SOURCES = \
                pulse/xmalloc.c pulse/xmalloc.h \
                pulse/proplist.c pulse/proplist.h \
                pulse/ext-stream-restore.c pulse/ext-stream-restore.h \
-               pulse/i18n.c pulse/i18n.h \
-               pulse/lock-autospawn.c pulse/lock-autospawn.h
+               pulse/i18n.c pulse/i18n.h
 
 # Internal stuff that is shared with libpulsecore
 libpulse_la_SOURCES += \
@@ -740,8 +745,7 @@ libpulsecore_la_SOURCES = \
                pulse/volume.c pulse/volume.h \
                pulse/xmalloc.c pulse/xmalloc.h \
                pulse/proplist.c pulse/proplist.h \
-               pulse/i18n.c pulse/i18n.h \
-               pulse/lock-autospawn.c pulse/lock-autospawn.h
+               pulse/i18n.c pulse/i18n.h
 
 # Pure core stuff (some are shared in libpulse though).
 libpulsecore_la_SOURCES += \
@@ -759,6 +763,7 @@ libpulsecore_la_SOURCES += \
                pulsecore/g711.c pulsecore/g711.h \
                pulsecore/hashmap.c pulsecore/hashmap.h \
                pulsecore/idxset.c pulsecore/idxset.h \
+               pulsecore/prioq.c pulsecore/prioq.h \
                pulsecore/log.c pulsecore/log.h \
                pulsecore/mcalign.c pulsecore/mcalign.h \
                pulsecore/memblock.c pulsecore/memblock.h \
@@ -811,6 +816,7 @@ libpulsecore_la_SOURCES += \
                pulsecore/start-child.c pulsecore/start-child.h \
                pulsecore/envelope.c pulsecore/envelope.h \
                pulsecore/proplist-util.c pulsecore/proplist-util.h \
+               pulsecore/lock-autospawn.c pulsecore/lock-autospawn.h \
                $(PA_THREAD_OBJS)
 
 if OS_IS_WIN32
@@ -1161,10 +1167,14 @@ endif
 
 if HAVE_BLUEZ
 modlibexec_LTLIBRARIES += \
-               module-bt-proximity.la
+               module-bluetooth-proximity.la \
+               module-bluetooth-discover.la \
+               libbluetooth-ipc.la \
+               libbluetooth-sbc.la \
+               module-bluetooth-device.la
 
 pulselibexec_PROGRAMS += \
-               bt-proximity-helper
+               proximity-helper
 endif
 
 # These are generated by a M4 script
@@ -1220,7 +1230,9 @@ SYMDEF_FILES = \
                modules/module-rescue-streams-symdef.h \
                modules/module-suspend-on-idle-symdef.h \
                modules/module-hal-detect-symdef.h \
-               modules/module-bt-proximity-symdef.h \
+               modules/bluetooth/module-bluetooth-proximity-symdef.h \
+               modules/bluetooth/module-bluetooth-discover-symdef.h \
+               modules/bluetooth/module-bluetooth-device-symdef.h \
                modules/gconf/module-gconf-symdef.h \
                modules/module-position-event-sounds-symdef.h \
                modules/module-console-kit-symdef.h
@@ -1232,6 +1244,7 @@ $(SYMDEF_FILES): modules/module-defs.h.m4
        $(MKDIR_P) modules
        $(MKDIR_P) modules/gconf
        $(MKDIR_P) modules/rtp
+       $(MKDIR_P) modules/bluetooth
        $(M4) -Dfname="$@" $< > $@
 
 # Simple protocol
@@ -1551,15 +1564,36 @@ gconf_helper_CFLAGS = $(AM_CFLAGS) $(GCONF_CFLAGS)
 gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 # Bluetooth proximity
-module_bt_proximity_la_SOURCES = modules/module-bt-proximity.c
-module_bt_proximity_la_LDFLAGS = -module -avoid-version
-module_bt_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la
-module_bt_proximity_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -DPA_BT_PROXIMITY_HELPER=\"$(pulselibexecdir)/bt-proximity-helper\"
-
-bt_proximity_helper_SOURCES = modules/bt-proximity-helper.c
-bt_proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_LIBS)
-bt_proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_CFLAGS)
-bt_proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
+module_bluetooth_proximity_la_SOURCES = modules/bluetooth/module-bluetooth-proximity.c
+module_bluetooth_proximity_la_LDFLAGS = -module -avoid-version
+module_bluetooth_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la
+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_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
+
+# Bluetooth sink / source
+module_bluetooth_discover_la_SOURCES = modules/bluetooth/module-bluetooth-discover.c
+module_bluetooth_discover_la_LDFLAGS = -module -avoid-version
+module_bluetooth_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la
+module_bluetooth_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
+
+libbluetooth_sbc_la_SOURCES = modules/bluetooth/sbc.c modules/bluetooth/sbc.h modules/bluetooth/sbc_tables.h modules/bluetooth/sbc_math.h
+libbluetooth_sbc_la_LDFLAGS = -avoid-version
+libbluetooth_sbc_la_LIBADD = $(AM_LIBADD)
+libbluetooth_sbc_la_CFLAGS = $(AM_CFLAGS)
+
+libbluetooth_ipc_la_SOURCES = modules/bluetooth/ipc.c modules/bluetooth/ipc.h
+libbluetooth_ipc_la_LDFLAGS = -avoid-version
+libbluetooth_ipc_la_LIBADD = $(AM_LIBADD)
+libbluetooth_ipc_la_CFLAGS = $(AM_CFLAGS)
+
+module_bluetooth_device_la_SOURCES = modules/bluetooth/module-bluetooth-device.c
+module_bluetooth_device_la_LDFLAGS = -module -avoid-version
+module_bluetooth_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la libbluetooth-ipc.la libbluetooth-sbc.la libsocket-util.la
+module_bluetooth_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 
 ###################################
 #        Some minor stuff         #
@@ -1608,7 +1642,7 @@ daemon.conf: daemon/daemon.conf.in Makefile
 install-exec-hook:
        chown root $(DESTDIR)$(bindir)/pulseaudio ; true
        chmod u+s $(DESTDIR)$(bindir)/pulseaudio
-       -chmod u+s $(DESTDIR)$(pulselibexecdir)/bt-proximity-helper
+       -chmod u+s $(DESTDIR)$(pulselibexecdir)/proximity-helper
        ln -sf pacat $(DESTDIR)$(bindir)/parec
        rm -f $(DESTDIR)$(modlibexecdir)/*.a
        rm -f $(DESTDIR)$(libdir)/libpulsedsp.a
index 40e0a170f397f86588def7d86b913afaf9cc5415..939b25d776c78a883c206da34ed1e89adf92338e 100644 (file)
@@ -76,6 +76,7 @@ static const pa_daemon_conf default_conf = {
     .log_level = PA_LOG_NOTICE,
     .resample_method = PA_RESAMPLER_AUTO,
     .disable_remixing = FALSE,
+    .disable_lfe_remixing = TRUE,
     .config_file = NULL,
     .use_pid_file = TRUE,
     .system_instance = FALSE,
@@ -83,7 +84,8 @@ static const pa_daemon_conf default_conf = {
     .disable_shm = FALSE,
     .default_n_fragments = 4,
     .default_fragment_size_msec = 25,
-    .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }
+    .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
+    .shm_size = 0
 #ifdef HAVE_SYS_RESOURCE_H
    ,.rlimit_fsize = { .value = 0, .is_set = FALSE },
     .rlimit_data = { .value = 0, .is_set = FALSE },
@@ -426,7 +428,9 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
         { "default-fragment-size-msec", parse_fragment_size_msec, NULL },
         { "nice-level",                 parse_nice_level,         NULL },
         { "disable-remixing",           pa_config_parse_bool,     NULL },
+        { "disable-lfe-remixing",       pa_config_parse_bool,     NULL },
         { "load-default-script-file",   pa_config_parse_bool,     NULL },
+        { "shm-size-bytes",             pa_config_parse_size,     NULL },
 #ifdef HAVE_SYS_RESOURCE_H
         { "rlimit-fsize",               parse_rlimit,             NULL },
         { "rlimit-data",                parse_rlimit,             NULL },
@@ -490,66 +494,68 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
     table[24].data = c;
     table[25].data = c;
     table[26].data = &c->disable_remixing;
-    table[27].data = &c->load_default_script_file;
+    table[27].data = &c->disable_lfe_remixing;
+    table[28].data = &c->load_default_script_file;
+    table[29].data = &c->shm_size;
 #ifdef HAVE_SYS_RESOURCE_H
-    table[28].data = &c->rlimit_fsize;
-    table[29].data = &c->rlimit_data;
-    table[30].data = &c->rlimit_stack;
-    table[31].data = &c->rlimit_as;
-    table[32].data = &c->rlimit_core;
-    table[33].data = &c->rlimit_nofile;
-    table[34].data = &c->rlimit_as;
+    table[30].data = &c->rlimit_fsize;
+    table[31].data = &c->rlimit_data;
+    table[32].data = &c->rlimit_stack;
+    table[33].data = &c->rlimit_as;
+    table[34].data = &c->rlimit_core;
+    table[35].data = &c->rlimit_nofile;
+    table[36].data = &c->rlimit_as;
 #ifdef RLIMIT_NPROC
-    table[35].data = &c->rlimit_nproc;
+    table[37].data = &c->rlimit_nproc;
 #endif
 
 #ifdef RLIMIT_MEMLOCK
 #ifndef RLIMIT_NPROC
 #error "Houston, we have a numbering problem!"
 #endif
-    table[36].data = &c->rlimit_memlock;
+    table[38].data = &c->rlimit_memlock;
 #endif
 
 #ifdef RLIMIT_LOCKS
 #ifndef RLIMIT_MEMLOCK
 #error "Houston, we have a numbering problem!"
 #endif
-    table[37].data = &c->rlimit_locks;
+    table[39].data = &c->rlimit_locks;
 #endif
 
 #ifdef RLIMIT_SIGPENDING
 #ifndef RLIMIT_LOCKS
 #error "Houston, we have a numbering problem!"
 #endif
-    table[38].data = &c->rlimit_sigpending;
+    table[40].data = &c->rlimit_sigpending;
 #endif
 
 #ifdef RLIMIT_MSGQUEUE
 #ifndef RLIMIT_SIGPENDING
 #error "Houston, we have a numbering problem!"
 #endif
-    table[39].data = &c->rlimit_msgqueue;
+    table[41].data = &c->rlimit_msgqueue;
 #endif
 
 #ifdef RLIMIT_NICE
 #ifndef RLIMIT_MSGQUEUE
 #error "Houston, we have a numbering problem!"
 #endif
-    table[40].data = &c->rlimit_nice;
+    table[42].data = &c->rlimit_nice;
 #endif
 
 #ifdef RLIMIT_RTPRIO
 #ifndef RLIMIT_NICE
 #error "Houston, we have a numbering problem!"
 #endif
-    table[41].data = &c->rlimit_rtprio;
+    table[43].data = &c->rlimit_rtprio;
 #endif
 
 #ifdef RLIMIT_RTTIME
 #ifndef RLIMIT_RTTIME
 #error "Houston, we have a numbering problem!"
 #endif
-    table[42].data = &c->rlimit_rttime;
+    table[44].data = &c->rlimit_rttime;
 #endif
 #endif
 
@@ -661,11 +667,13 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
     pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
     pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
     pa_strbuf_printf(s, "disable-remixing = %s\n", pa_yes_no(c->disable_remixing));
+    pa_strbuf_printf(s, "disable-lfe-remixing = %s\n", pa_yes_no(c->disable_lfe_remixing));
     pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
     pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
     pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
     pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
     pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
+    pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size);
 #ifdef HAVE_SYS_RESOURCE_H
     pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1);
     pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
index c42984f99ccca13d8455ae4240ae7d44ad831092..90329268e1cc1a1ae8844719a307cf608c6a30c7 100644 (file)
@@ -66,6 +66,7 @@ typedef struct pa_daemon_conf {
         no_cpu_limit,
         disable_shm,
         disable_remixing,
+        disable_lfe_remixing,
         load_default_script_file,
         disallow_exit;
     int exit_idle_time,
@@ -110,6 +111,7 @@ typedef struct pa_daemon_conf {
 
     unsigned default_n_fragments, default_fragment_size_msec;
     pa_sample_spec default_sample_spec;
+    size_t shm_size;
 } pa_daemon_conf;
 
 /* Allocate a new structure and fill it with sane defaults */
index 33b1d61d9a4ff3eb441da4d2efc33e8763d78824..c672d42049f9e03e0d5e833b235c8fe16f907335 100644 (file)
@@ -26,6 +26,7 @@
 ; use-pid-file = yes
 ; system-instance = no
 ; disable-shm = no
+; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
 
 ; high-priority = yes
 ; nice-level = -11
@@ -39,7 +40,7 @@
 
 ; dl-search-path = (depends on architecture)
 
-; load-defaul-script-file = yes
+; load-default-script-file = yes
 ; default-script-file = @PA_DEFAULT_CONFIG_FILE@
 
 ; log-target = auto
@@ -47,6 +48,7 @@
 
 ; resample-method = speex-float-3
 ; disable-remixing = no
+; disable-lfe-remixing = yes
 
 ; no-cpu-limit = no
 
index 5f35e3ecc1dc177b4dbe452743ad190f23eb52f0..7032038deeb0e8260d94b179a0a55b4674906beb 100755 (executable)
@@ -48,6 +48,11 @@ load-module module-hal-detect
 load-module module-detect
 .endif
 
+### Automatically load driver modules for Bluetooth hardware
+#.ifexists module-bluetooth-discover@PA_SOEXT@
+#load-module module-bluetooth-discover
+#.endif
+
 ### Load several protocols
 .ifexists module-esound-protocol-unix@PA_SOEXT@
 load-module module-esound-protocol-unix
index c8eda398d81dc6596c1f0851f26685b95fec4ce8..53f5d1938292233f0fe71a154162fd16641f3f78 100644 (file)
@@ -65,8 +65,8 @@
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
 #include <pulse/i18n.h>
-#include <pulse/lock-autospawn.h>
 
+#include <pulsecore/lock-autospawn.h>
 #include <pulsecore/winsock.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/core.h>
@@ -778,8 +778,15 @@ int main(int argc, char *argv[]) {
     pa_set_env("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
 
     pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION);
+    pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST);
     pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS);
 
+    s = pa_uname_string();
+    pa_log_debug(_("Running on host: %s"), s);
+    pa_xfree(s);
+
+    pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE);
+
 #ifdef HAVE_VALGRIND_MEMCHECK_H
     pa_log_debug(_("Compiled with Valgrind support: yes"));
 #else
@@ -792,8 +799,6 @@ int main(int argc, char *argv[]) {
     pa_log_debug(_("Optimized build: no"));
 #endif
 
-    pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE);
-
     if (!(s = pa_machine_id())) {
         pa_log(_("Failed to get machine ID"));
         goto finish;
@@ -849,7 +854,7 @@ int main(int argc, char *argv[]) {
 
     pa_assert_se(mainloop = pa_mainloop_new());
 
-    if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) {
+    if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) {
         pa_log(_("pa_core_new() failed."));
         goto finish;
     }
@@ -864,6 +869,7 @@ int main(int argc, char *argv[]) {
     c->realtime_priority = conf->realtime_priority;
     c->realtime_scheduling = !!conf->realtime_scheduling;
     c->disable_remixing = !!conf->disable_remixing;
+    c->disable_lfe_remixing = !!conf->disable_lfe_remixing;
     c->running_as_daemon = !!conf->daemonize;
     c->disallow_exit = conf->disallow_exit;
 
index f6052c4b96487f71b40ea21ba409945c64469766..27e428156abd8a52584ca25c8db21105cff72674 100755 (executable)
@@ -34,8 +34,9 @@ load-module module-esound-protocol-unix
 .endif
 load-module module-native-protocol-unix
 
-### Automatically restore the volume of playback streams
-load-module module-volume-restore
+### Automatically restore the volume of streams and devices
+load-module module-stream-restore
+load-module module-device-restore
 
 ### Automatically restore the default sink/source when changed by the user during runtime
 load-module module-default-device-restore
index 8fa405ddfddc300ad58ac077fb690474261e0235..c3eb72f5765d14121e048bb2293ec5c3cbea21ba 100644 (file)
@@ -370,11 +370,18 @@ int pa_alsa_set_hw_params(
         goto finish;
 
     if (_periods > 0) {
-        dir = 1;
+
+        /* First we pass 0 as direction to get exactly what we asked
+         * for. That this is necessary is presumably a bug in ALSA */
+
+        dir = 0;
         if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
-            dir = -1;
-            if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
-                goto finish;
+            dir = 1;
+            if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
+                dir = -1;
+                if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
+                    goto finish;
+            }
         }
     }
 
diff --git a/src/modules/bluetooth/Makefile b/src/modules/bluetooth/Makefile
new file mode 120000 (symlink)
index 0000000..efe5a33
--- /dev/null
@@ -0,0 +1 @@
+../../pulse/Makefile
\ No newline at end of file
diff --git a/src/modules/bluetooth/ipc.c b/src/modules/bluetooth/ipc.c
new file mode 100644 (file)
index 0000000..9825699
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *  This library 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.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "ipc.h"
+
+/* This table contains the string representation for messages */
+static const char *strmsg[] = {
+       "BT_GETCAPABILITIES_REQ",
+       "BT_GETCAPABILITIES_RSP",
+       "BT_SETCONFIGURATION_REQ",
+       "BT_SETCONFIGURATION_RSP",
+       "BT_STREAMSTART_REQ",
+       "BT_STREAMSTART_RSP",
+       "BT_STREAMSTOP_REQ",
+       "BT_STREAMSTOP_RSP",
+       "BT_STREAMSUSPEND_IND",
+       "BT_STREAMRESUME_IND",
+       "BT_CONTROL_REQ",
+       "BT_CONTROL_RSP",
+       "BT_CONTROL_IND",
+       "BT_STREAMFD_IND",
+};
+
+int bt_audio_service_open(void)
+{
+       int sk;
+       int err;
+       struct sockaddr_un addr = {
+               AF_UNIX, BT_IPC_SOCKET_NAME
+       };
+
+       sk = socket(PF_LOCAL, SOCK_STREAM, 0);
+       if (sk < 0) {
+               err = errno;
+               fprintf(stderr, "%s: Cannot open socket: %s (%d)\n",
+                       __FUNCTION__, strerror(err), err);
+               errno = err;
+               return -1;
+       }
+
+       if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+               err = errno;
+               fprintf(stderr, "%s: connect() failed: %s (%d)\n",
+                       __FUNCTION__, strerror(err), err);
+               close(sk);
+               errno = err;
+               return -1;
+       }
+
+       return sk;
+}
+
+int bt_audio_service_close(int sk)
+{
+       return close(sk);
+}
+
+int bt_audio_service_get_data_fd(int sk)
+{
+       char cmsg_b[CMSG_SPACE(sizeof(int))], m;
+       int err, ret;
+       struct iovec iov = { &m, sizeof(m) };
+       struct msghdr msgh;
+       struct cmsghdr *cmsg;
+
+       memset(&msgh, 0, sizeof(msgh));
+       msgh.msg_iov = &iov;
+       msgh.msg_iovlen = 1;
+       msgh.msg_control = &cmsg_b;
+       msgh.msg_controllen = CMSG_LEN(sizeof(int));
+
+       ret = (int) recvmsg(sk, &msgh, 0);
+       if (ret < 0) {
+               err = errno;
+               fprintf(stderr, "%s: Unable to receive fd: %s (%d)\n",
+                       __FUNCTION__, strerror(err), err);
+               errno = err;
+               return -1;
+       }
+
+       /* Receive auxiliary data in msgh */
+       for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
+                       cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
+               if (cmsg->cmsg_level == SOL_SOCKET
+                               && cmsg->cmsg_type == SCM_RIGHTS)
+                       return (*(int *) CMSG_DATA(cmsg));
+       }
+
+       errno = EINVAL;
+       return -1;
+}
+
+const char *bt_audio_strmsg(int type)
+{
+    if (type < 0 || (size_t) type > (sizeof(strmsg) / sizeof(strmsg[0])))
+               return NULL;
+
+       return strmsg[type];
+}
diff --git a/src/modules/bluetooth/ipc.h b/src/modules/bluetooth/ipc.h
new file mode 100644 (file)
index 0000000..ae85e72
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *  This library 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.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/*
+  Message sequence chart of streaming sequence for A2DP transport
+
+  Audio daemon                       User
+                             on snd_pcm_open
+                 <--BT_GETCAPABILITIES_REQ
+
+  BT_GETCAPABILITIES_RSP-->
+
+                        on snd_pcm_hw_params
+                <--BT_SETCONFIGURATION_REQ
+
+  BT_SETCONFIGURATION_RSP-->
+
+                       on snd_pcm_prepare
+                <--BT_STREAMSTART_REQ
+
+  <Moves to streaming state>
+  BT_STREAMSTART_RSP-->
+
+  BT_STREAMFD_IND -->
+
+                          <  streams data >
+                             ..........
+
+               on snd_pcm_drop/snd_pcm_drain
+
+                <--BT_STREAMSTOP_REQ
+
+  <Moves to open state>
+  BT_STREAMSTOP_RSP-->
+
+                       on IPC close or appl crash
+  <Moves to idle>
+
+ */
+
+#ifndef BT_AUDIOCLIENT_H
+#define BT_AUDIOCLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#define BT_AUDIO_IPC_PACKET_SIZE   128
+#define BT_IPC_SOCKET_NAME "\0/org/bluez/audio"
+
+/* Generic message header definition, except for RSP messages */
+typedef struct {
+       uint8_t msg_type;
+} __attribute__ ((packed)) bt_audio_msg_header_t;
+
+/* Generic message header definition, for all RSP messages */
+typedef struct {
+       bt_audio_msg_header_t   msg_h;
+       uint8_t                 posix_errno;
+} __attribute__ ((packed)) bt_audio_rsp_msg_header_t;
+
+/* Messages list */
+#define BT_GETCAPABILITIES_REQ         0
+#define BT_GETCAPABILITIES_RSP         1
+
+#define BT_SETCONFIGURATION_REQ                2
+#define BT_SETCONFIGURATION_RSP                3
+
+#define BT_STREAMSTART_REQ             4
+#define BT_STREAMSTART_RSP             5
+
+#define BT_STREAMSTOP_REQ              6
+#define BT_STREAMSTOP_RSP              7
+
+#define BT_STREAMSUSPEND_IND           8
+#define BT_STREAMRESUME_IND            9
+
+#define BT_CONTROL_REQ                10
+#define BT_CONTROL_RSP                11
+#define BT_CONTROL_IND                12
+
+#define BT_STREAMFD_IND                       13
+
+/* BT_GETCAPABILITIES_REQ */
+
+#define BT_CAPABILITIES_TRANSPORT_A2DP 0
+#define BT_CAPABILITIES_TRANSPORT_SCO  1
+#define BT_CAPABILITIES_TRANSPORT_ANY  2
+
+#define BT_CAPABILITIES_ACCESS_MODE_READ       1
+#define BT_CAPABILITIES_ACCESS_MODE_WRITE      2
+#define BT_CAPABILITIES_ACCESS_MODE_READWRITE  3
+
+#define BT_FLAG_AUTOCONNECT    1
+
+struct bt_getcapabilities_req {
+       bt_audio_msg_header_t   h;
+       char                    device[18];     /* Address of the remote Device */
+       uint8_t                 transport;      /* Requested transport */
+       uint8_t                 flags;          /* Requested flags */
+} __attribute__ ((packed));
+
+/* BT_GETCAPABILITIES_RSP */
+
+/**
+ * SBC Codec parameters as per A2DP profile 1.0 § 4.3
+ */
+
+#define BT_SBC_SAMPLING_FREQ_16000             (1 << 3)
+#define BT_SBC_SAMPLING_FREQ_32000             (1 << 2)
+#define BT_SBC_SAMPLING_FREQ_44100             (1 << 1)
+#define BT_SBC_SAMPLING_FREQ_48000             1
+
+#define BT_A2DP_CHANNEL_MODE_MONO              (1 << 3)
+#define BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL      (1 << 2)
+#define BT_A2DP_CHANNEL_MODE_STEREO            (1 << 1)
+#define BT_A2DP_CHANNEL_MODE_JOINT_STEREO      1
+
+#define BT_A2DP_BLOCK_LENGTH_4                 (1 << 3)
+#define BT_A2DP_BLOCK_LENGTH_8                 (1 << 2)
+#define BT_A2DP_BLOCK_LENGTH_12                        (1 << 1)
+#define BT_A2DP_BLOCK_LENGTH_16                        1
+
+#define BT_A2DP_SUBBANDS_4                     (1 << 1)
+#define BT_A2DP_SUBBANDS_8                     1
+
+#define BT_A2DP_ALLOCATION_SNR                 (1 << 1)
+#define BT_A2DP_ALLOCATION_LOUDNESS            1
+
+#define BT_MPEG_SAMPLING_FREQ_16000            (1 << 5)
+#define BT_MPEG_SAMPLING_FREQ_22050            (1 << 4)
+#define BT_MPEG_SAMPLING_FREQ_24000            (1 << 3)
+#define BT_MPEG_SAMPLING_FREQ_32000            (1 << 2)
+#define BT_MPEG_SAMPLING_FREQ_44100            (1 << 1)
+#define BT_MPEG_SAMPLING_FREQ_48000            1
+
+#define BT_MPEG_LAYER_1                                (1 << 2)
+#define BT_MPEG_LAYER_2                                (1 << 1)
+#define BT_MPEG_LAYER_3                                1
+
+typedef struct {
+       uint8_t channel_mode;
+       uint8_t frequency;
+       uint8_t allocation_method;
+       uint8_t subbands;
+       uint8_t block_length;
+       uint8_t min_bitpool;
+       uint8_t max_bitpool;
+} __attribute__ ((packed)) sbc_capabilities_t;
+
+typedef struct {
+       uint8_t channel_mode;
+       uint8_t crc;
+       uint8_t layer;
+       uint8_t frequency;
+       uint8_t mpf;
+       uint16_t bitrate;
+} __attribute__ ((packed)) mpeg_capabilities_t;
+
+struct bt_getcapabilities_rsp {
+       bt_audio_rsp_msg_header_t       rsp_h;
+       uint8_t                         transport;         /* Granted transport */
+       sbc_capabilities_t              sbc_capabilities;  /* A2DP only */
+       mpeg_capabilities_t             mpeg_capabilities; /* A2DP only */
+       uint16_t                        sampling_rate;     /* SCO only */
+} __attribute__ ((packed));
+
+/* BT_SETCONFIGURATION_REQ */
+struct bt_setconfiguration_req {
+       bt_audio_msg_header_t   h;
+       char                    device[18];             /* Address of the remote Device */
+       uint8_t                 transport;              /* Requested transport */
+       uint8_t                 access_mode;            /* Requested access mode */
+       sbc_capabilities_t      sbc_capabilities;       /* A2DP only - only one of this field
+                                                       and next one must be filled */
+       mpeg_capabilities_t     mpeg_capabilities;      /* A2DP only */
+} __attribute__ ((packed));
+
+/* BT_SETCONFIGURATION_RSP */
+struct bt_setconfiguration_rsp {
+       bt_audio_rsp_msg_header_t       rsp_h;
+       uint8_t                         transport;      /* Granted transport */
+       uint8_t                         access_mode;    /* Granted access mode */
+       uint16_t                        link_mtu;       /* Max length that transport supports */
+} __attribute__ ((packed));
+
+/* BT_STREAMSTART_REQ */
+#define BT_STREAM_ACCESS_READ          0
+#define BT_STREAM_ACCESS_WRITE         1
+#define BT_STREAM_ACCESS_READWRITE     2
+struct bt_streamstart_req {
+       bt_audio_msg_header_t   h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSTART_RSP */
+struct bt_streamstart_rsp {
+       bt_audio_rsp_msg_header_t       rsp_h;
+} __attribute__ ((packed));
+
+/* BT_STREAMFD_IND */
+/* This message is followed by one byte of data containing the stream data fd
+   as ancilliary data */
+struct bt_streamfd_ind {
+       bt_audio_msg_header_t   h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSTOP_REQ */
+struct bt_streamstop_req {
+       bt_audio_msg_header_t   h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSTOP_RSP */
+struct bt_streamstop_rsp {
+       bt_audio_rsp_msg_header_t       rsp_h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSUSPEND_IND */
+struct bt_streamsuspend_ind {
+       bt_audio_msg_header_t   h;
+} __attribute__ ((packed));
+
+/* BT_STREAMRESUME_IND */
+struct bt_streamresume_ind {
+       bt_audio_msg_header_t   h;
+} __attribute__ ((packed));
+
+/* BT_CONTROL_REQ */
+
+#define BT_CONTROL_KEY_POWER                   0x40
+#define BT_CONTROL_KEY_VOL_UP                  0x41
+#define BT_CONTROL_KEY_VOL_DOWN                        0x42
+#define BT_CONTROL_KEY_MUTE                    0x43
+#define BT_CONTROL_KEY_PLAY                    0x44
+#define BT_CONTROL_KEY_STOP                    0x45
+#define BT_CONTROL_KEY_PAUSE                   0x46
+#define BT_CONTROL_KEY_RECORD                  0x47
+#define BT_CONTROL_KEY_REWIND                  0x48
+#define BT_CONTROL_KEY_FAST_FORWARD            0x49
+#define BT_CONTROL_KEY_EJECT                   0x4A
+#define BT_CONTROL_KEY_FORWARD                 0x4B
+#define BT_CONTROL_KEY_BACKWARD                        0x4C
+
+struct bt_control_req {
+       bt_audio_msg_header_t   h;
+       uint8_t                 mode;           /* Control Mode */
+       uint8_t                 key;            /* Control Key */
+} __attribute__ ((packed));
+
+/* BT_CONTROL_RSP */
+struct bt_control_rsp {
+       bt_audio_rsp_msg_header_t       rsp_h;
+       uint8_t                         mode;   /* Control Mode */
+       uint8_t                         key;    /* Control Key */
+} __attribute__ ((packed));
+
+/* BT_CONTROL_IND */
+struct bt_control_ind {
+       bt_audio_msg_header_t   h;
+       uint8_t                 mode;           /* Control Mode */
+       uint8_t                 key;            /* Control Key */
+} __attribute__ ((packed));
+
+/* Function declaration */
+
+/* Opens a connection to the audio service: return a socket descriptor */
+int bt_audio_service_open(void);
+
+/* Closes a connection to the audio service */
+int bt_audio_service_close(int sk);
+
+/* Receives stream data file descriptor : must be called after a
+BT_STREAMFD_IND message is returned */
+int bt_audio_service_get_data_fd(int sk);
+
+/* Human readable message type string */
+const char *bt_audio_strmsg(int type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BT_AUDIOCLIENT_H */
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
new file mode 100644 (file)
index 0000000..395d54f
--- /dev/null
@@ -0,0 +1,929 @@
+/***
+    This file is part of PulseAudio.
+
+    Copyright 2008 Joao Paulo Rechi Vita
+
+    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 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 <string.h>
+#include <errno.h>
+#include <poll.h>
+#include <sys/ioctl.h>
+#include <linux/sockios.h>
+#include <arpa/inet.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
+#include <pulse/sample.h>
+#include <pulsecore/module.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/socket-util.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
+#include <pulsecore/time-smoother.h>
+#include <pulsecore/rtclock.h>
+
+#include "dbus-util.h"
+#include "module-bluetooth-device-symdef.h"
+#include "ipc.h"
+#include "sbc.h"
+#include "rtp.h"
+
+#define DEFAULT_SINK_NAME "bluetooth_sink"
+#define BUFFER_SIZE 2048
+#define MAX_BITPOOL 64
+#define MIN_BITPOOL 2U
+#define SOL_SCO 17
+#define SCO_TXBUFS 0x03
+#define SCO_RXBUFS 0x04
+
+PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
+PA_MODULE_DESCRIPTION("Bluetooth audio sink and source");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(FALSE);
+PA_MODULE_USAGE(
+        "sink_name=<name of the device> "
+        "address=<address of the device> "
+        "profile=<a2dp|hsp>");
+
+struct bt_a2dp {
+    sbc_capabilities_t sbc_capabilities;
+    sbc_t sbc;                           /* Codec data */
+    pa_bool_t sbc_initialized;           /* Keep track if the encoder is initialized */
+    size_t codesize;                     /* SBC codesize */
+    unsigned samples;                    /* Number of encoded samples */
+    uint8_t buffer[BUFFER_SIZE];         /* Codec transfer buffer */
+    size_t count;                        /* Codec transfer buffer counter */
+
+    unsigned total_samples;              /* Cumulative number of codec samples */
+    uint16_t seq_num;                    /* Cumulative packet sequence */
+    unsigned frame_count;                /* Current frames in buffer*/
+};
+
+struct userdata {
+    pa_core *core;
+    pa_module *module;
+    pa_sink *sink;
+
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+    pa_rtpoll_item *rtpoll_item;
+    pa_thread *thread;
+
+    uint64_t offset;
+    pa_smoother *smoother;
+
+    char *name;
+    char *addr;
+    char *profile;
+    pa_sample_spec ss;
+
+    int audioservice_fd;
+    int stream_fd;
+
+    uint8_t transport;
+    char *strtransport;
+    size_t link_mtu;
+    size_t block_size;
+    pa_usec_t latency;
+
+    struct bt_a2dp a2dp;
+};
+
+static const char* const valid_modargs[] = {
+    "sink_name",
+    "address",
+    "profile",
+    "rate",
+    "channels",
+    NULL
+};
+
+static int bt_audioservice_send(int sk, const bt_audio_msg_header_t *msg) {
+    int e;
+    pa_log_debug("sending %s", bt_audio_strmsg(msg->msg_type));
+    if (send(sk, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0)
+        e = 0;
+    else {
+        e = -errno;
+        pa_log_error("Error sending data to audio service: %s(%d)", pa_cstrerror(errno), errno);
+    }
+    return e;
+}
+
+static int bt_audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) {
+    int e;
+    const char *type;
+
+    pa_log_debug("trying to receive msg from audio service...");
+    if (recv(sk, inmsg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) {
+        type = bt_audio_strmsg(inmsg->msg_type);
+        if (type) {
+            pa_log_debug("Received %s", type);
+            e = 0;
+        }
+        else {
+            e = -EINVAL;
+            pa_log_error("Bogus message type %d received from audio service", inmsg->msg_type);
+        }
+    }
+    else {
+        e = -errno;
+        pa_log_error("Error receiving data from audio service: %s(%d)", pa_cstrerror(errno), errno);
+    }
+
+    return e;
+}
+
+static int bt_audioservice_expect(int sk, bt_audio_msg_header_t *rsp_hdr, int expected_type) {
+    int e = bt_audioservice_recv(sk, rsp_hdr);
+    if (e == 0) {
+        if (rsp_hdr->msg_type != expected_type) {
+            e = -EINVAL;
+            pa_log_error("Bogus message %s received while %s was expected", bt_audio_strmsg(rsp_hdr->msg_type),
+                    bt_audio_strmsg(expected_type));
+        }
+    }
+    return e;
+}
+
+static int bt_getcaps(struct userdata *u) {
+    int e;
+    union {
+        bt_audio_rsp_msg_header_t rsp_hdr;
+        struct bt_getcapabilities_req getcaps_req;
+        struct bt_getcapabilities_rsp getcaps_rsp;
+        uint8_t buf[BT_AUDIO_IPC_PACKET_SIZE];
+    } msg;
+
+    memset(msg.buf, 0, BT_AUDIO_IPC_PACKET_SIZE);
+    msg.getcaps_req.h.msg_type = BT_GETCAPABILITIES_REQ;
+    strncpy(msg.getcaps_req.device, u->addr, 18);
+    if (strcasecmp(u->profile, "a2dp") == 0)
+        msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
+    else if (strcasecmp(u->profile, "hsp") == 0)
+        msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_SCO;
+    else {
+        pa_log_error("Invalid profile argument: %s", u->profile);
+        return -1;
+    }
+    msg.getcaps_req.flags = BT_FLAG_AUTOCONNECT;
+
+    e = bt_audioservice_send(u->audioservice_fd, &msg.getcaps_req.h);
+    if (e < 0) {
+        pa_log_error("Failed to send GETCAPABILITIES_REQ");
+        return e;
+    }
+
+    e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_GETCAPABILITIES_RSP);
+    if (e < 0) {
+        pa_log_error("Failed to expect for GETCAPABILITIES_RSP");
+        return e;
+    }
+    if (msg.rsp_hdr.posix_errno != 0) {
+        pa_log_error("BT_GETCAPABILITIES failed : %s (%d)", pa_cstrerror(msg.rsp_hdr.posix_errno), msg.rsp_hdr.posix_errno);
+        return -msg.rsp_hdr.posix_errno;
+    }
+
+    if ((u->transport = msg.getcaps_rsp.transport) == BT_CAPABILITIES_TRANSPORT_A2DP)
+        u->a2dp.sbc_capabilities = msg.getcaps_rsp.sbc_capabilities;
+
+    return 0;
+}
+
+static uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
+    switch (freq) {
+        case BT_SBC_SAMPLING_FREQ_16000:
+        case BT_SBC_SAMPLING_FREQ_32000:
+            return 53;
+        case BT_SBC_SAMPLING_FREQ_44100:
+            switch (mode) {
+                case BT_A2DP_CHANNEL_MODE_MONO:
+                case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
+                    return 31;
+                case BT_A2DP_CHANNEL_MODE_STEREO:
+                case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
+                    return 53;
+                default:
+                    pa_log_warn("Invalid channel mode %u", mode);
+                    return 53;
+            }
+        case BT_SBC_SAMPLING_FREQ_48000:
+            switch (mode) {
+                case BT_A2DP_CHANNEL_MODE_MONO:
+                case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
+                    return 29;
+                case BT_A2DP_CHANNEL_MODE_STEREO:
+                case BT_A2DP_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;
+    }
+}
+
+static int bt_a2dp_init(struct userdata *u) {
+    sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities;
+    uint8_t max_bitpool, min_bitpool;
+    unsigned i;
+
+    static const struct {
+        uint32_t rate;
+        uint8_t cap;
+    } freq_table[] = {
+        { 16000U, BT_SBC_SAMPLING_FREQ_16000 },
+        { 32000U, BT_SBC_SAMPLING_FREQ_32000 },
+        { 44100U, BT_SBC_SAMPLING_FREQ_44100 },
+        { 48000U, BT_SBC_SAMPLING_FREQ_48000 }
+    };
+
+    /* Find the lowest freq that is at least as high as the requested
+     * sampling rate */
+    for (i = 0; i < PA_ELEMENTSOF(freq_table); i++)
+        if (freq_table[i].rate >= u->ss.rate || i == PA_ELEMENTSOF(freq_table)-1 ) {
+            u->ss.rate = freq_table[i].rate;
+            cap->frequency = freq_table[i].cap;
+            break;
+        }
+
+    if (u->ss.channels >= 2) {
+        if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
+            cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
+        else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
+            cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
+        else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
+            cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
+
+        u->ss.channels = 2;
+    } else {
+        if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+            cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
+    }
+
+    if (!cap->channel_mode) {
+        pa_log_error("No supported channel modes");
+        return -1;
+    }
+
+    if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
+        cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
+    else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
+        cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
+    else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
+        cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
+    else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
+        cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
+    else {
+        pa_log_error("No supported block lengths");
+        return -1;
+    }
+
+    if (cap->subbands & BT_A2DP_SUBBANDS_8)
+        cap->subbands = BT_A2DP_SUBBANDS_8;
+    else if (cap->subbands & BT_A2DP_SUBBANDS_4)
+        cap->subbands = BT_A2DP_SUBBANDS_4;
+    else {
+        pa_log_error("No supported subbands");
+        return -1;
+    }
+
+    if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
+        cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
+    else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
+        cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
+
+    min_bitpool = (uint8_t) PA_MAX(MIN_BITPOOL, cap->min_bitpool);
+    max_bitpool = (uint8_t) PA_MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool);
+
+    cap->min_bitpool = (uint8_t) min_bitpool;
+    cap->max_bitpool = (uint8_t) max_bitpool;
+
+    return 0;
+}
+
+static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
+    sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities;
+
+    if (a2dp->sbc_initialized)
+        sbc_reinit(&a2dp->sbc, 0);
+    else
+        sbc_init(&a2dp->sbc, 0);
+    a2dp->sbc_initialized = TRUE;
+
+    if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
+        a2dp->sbc.frequency = SBC_FREQ_16000;
+
+    if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
+        a2dp->sbc.frequency = SBC_FREQ_32000;
+
+    if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
+        a2dp->sbc.frequency = SBC_FREQ_44100;
+
+    if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
+        a2dp->sbc.frequency = SBC_FREQ_48000;
+
+    if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+        a2dp->sbc.mode = SBC_MODE_MONO;
+
+    if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
+        a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL;
+
+    if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
+        a2dp->sbc.mode = SBC_MODE_STEREO;
+
+    if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
+        a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
+
+    a2dp->sbc.allocation = (uint8_t) (active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS);
+
+    switch (active_capabilities.subbands) {
+        case BT_A2DP_SUBBANDS_4:
+            a2dp->sbc.subbands = SBC_SB_4;
+            break;
+        case BT_A2DP_SUBBANDS_8:
+            a2dp->sbc.subbands = SBC_SB_8;
+            break;
+    }
+
+    switch (active_capabilities.block_length) {
+        case BT_A2DP_BLOCK_LENGTH_4:
+            a2dp->sbc.blocks = SBC_BLK_4;
+            break;
+        case BT_A2DP_BLOCK_LENGTH_8:
+            a2dp->sbc.blocks = SBC_BLK_8;
+            break;
+        case BT_A2DP_BLOCK_LENGTH_12:
+            a2dp->sbc.blocks = SBC_BLK_12;
+            break;
+        case BT_A2DP_BLOCK_LENGTH_16:
+            a2dp->sbc.blocks = SBC_BLK_16;
+            break;
+    }
+
+    a2dp->sbc.bitpool = active_capabilities.max_bitpool;
+    a2dp->codesize = (uint16_t) sbc_get_codesize(&a2dp->sbc);
+    a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
+}
+
+static int bt_setconf(struct userdata *u) {
+    int e;
+    union {
+        bt_audio_rsp_msg_header_t rsp_hdr;
+        struct bt_setconfiguration_req setconf_req;
+        struct bt_setconfiguration_rsp setconf_rsp;
+        uint8_t buf[BT_AUDIO_IPC_PACKET_SIZE];
+    } msg;
+
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+        e = bt_a2dp_init(u);
+        if (e < 0) {
+            pa_log_error("a2dp_init error");
+            return e;
+        }
+        u->ss.format = PA_SAMPLE_S16LE;
+    }
+    else
+        u->ss.format = PA_SAMPLE_U8;
+
+    memset(msg.buf, 0, BT_AUDIO_IPC_PACKET_SIZE);
+    msg.setconf_req.h.msg_type = BT_SETCONFIGURATION_REQ;
+    strncpy(msg.setconf_req.device, u->addr, 18);
+    msg.setconf_req.transport = u->transport;
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
+        msg.setconf_req.sbc_capabilities = u->a2dp.sbc_capabilities;
+    msg.setconf_req.access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE;
+
+    e = bt_audioservice_send(u->audioservice_fd, &msg.setconf_req.h);
+    if (e < 0) {
+        pa_log_error("Failed to send BT_SETCONFIGURATION_REQ");
+        return e;
+    }
+
+    e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_SETCONFIGURATION_RSP);
+    if (e < 0) {
+        pa_log_error("Failed to expect BT_SETCONFIGURATION_RSP");
+        return e;
+    }
+
+    if (msg.rsp_hdr.posix_errno != 0) {
+        pa_log_error("BT_SETCONFIGURATION failed : %s(%d)", pa_cstrerror(msg.rsp_hdr.posix_errno), msg.rsp_hdr.posix_errno);
+        return -msg.rsp_hdr.posix_errno;
+    }
+
+    u->transport = msg.setconf_rsp.transport;
+    u->strtransport = (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP ? pa_xstrdup("A2DP") : pa_xstrdup("SCO"));
+    u->link_mtu = msg.setconf_rsp.link_mtu;
+
+    /* setup SBC encoder now we agree on parameters */
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+        bt_a2dp_setup(&u->a2dp);
+        u->block_size = u->a2dp.codesize;
+        pa_log_info("sbc parameters:\n\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
+                u->a2dp.sbc.allocation, u->a2dp.sbc.subbands, u->a2dp.sbc.blocks, u->a2dp.sbc.bitpool);
+    }
+    else
+        u->block_size = u->link_mtu;
+
+    return 0;
+}
+
+static int bt_getstreamfd(struct userdata *u) {
+    int e;
+//    uint32_t period_count = io->buffer_size / io->period_size;
+    union {
+        bt_audio_rsp_msg_header_t rsp_hdr;
+        struct bt_streamstart_req start_req;
+        struct bt_streamfd_ind streamfd_ind;
+        uint8_t buf[BT_AUDIO_IPC_PACKET_SIZE];
+    } msg;
+
+    memset(msg.buf, 0, BT_AUDIO_IPC_PACKET_SIZE);
+    msg.start_req.h.msg_type = BT_STREAMSTART_REQ;
+
+    e = bt_audioservice_send(u->audioservice_fd, &msg.start_req.h);
+    if (e < 0) {
+        pa_log_error("Failed to send BT_STREAMSTART_REQ");
+        return e;
+    }
+
+    e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_STREAMSTART_RSP);
+    if (e < 0) {
+        pa_log_error("Failed to expect BT_STREAMSTART_RSP");
+        return e;
+    }
+
+    if (msg.rsp_hdr.posix_errno != 0) {
+        pa_log_error("BT_START failed : %s(%d)", pa_cstrerror(msg.rsp_hdr.posix_errno), msg.rsp_hdr.posix_errno);
+        return -msg.rsp_hdr.posix_errno;
+    }
+
+    e = bt_audioservice_expect(u->audioservice_fd, &msg.streamfd_ind.h, BT_STREAMFD_IND);
+    if (e < 0) {
+        pa_log_error("Failed to expect BT_STREAMFD_IND");
+        return e;
+    }
+
+    if (u->stream_fd >= 0)
+        pa_close(u->stream_fd);
+
+    u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd);
+    if (u->stream_fd < 0) {
+        pa_log_error("Failed to get data fd: %s (%d)",pa_cstrerror(errno), errno);
+        return -errno;
+    }
+
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+        if (pa_socket_set_sndbuf(u->stream_fd, 10U*u->link_mtu) < 0) {
+            pa_log_error("Failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
+            return -errno;
+        }
+    }
+
+//   if (setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)) == 0)
+//       return 0;
+//   if (setsockopt(u->stream_fd, SOL_SCO, SO_SNDBUF, &period_count, sizeof(period_count)) == 0)
+//       return 0;
+//   /* FIXME : handle error codes */
+    pa_make_fd_nonblock(u->stream_fd);
+//    pa_make_socket_low_delay(u->stream_fd);
+
+    return 0;
+}
+
+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;
+
+    pa_log_debug("got message: %d", code);
+    switch (code) {
+
+        case PA_SINK_MESSAGE_SET_STATE:
+            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+                case PA_SINK_SUSPENDED:
+                    pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
+                    pa_smoother_pause(u->smoother, pa_rtclock_usec());
+                    break;
+                case PA_SINK_IDLE:
+                case PA_SINK_RUNNING:
+                    if (u->sink->thread_info.state == PA_SINK_SUSPENDED)
+                        pa_smoother_resume(u->smoother, pa_rtclock_usec());
+                    break;
+                case PA_SINK_UNLINKED:
+                case PA_SINK_INIT:
+                    ;
+            }
+            break;
+
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            pa_usec_t w, r;
+/*             r = pa_smoother_get(u->smoother, pa_rtclock_usec()); */
+/* /\*             w = pa_bytes_to_usec(u->offset + (uint64_t) u->memchunk.length, &u->sink->sample_spec); *\/ */
+            *((pa_usec_t*) data) = /*w > r ? w - r :*/ 0;
+            return 0;
+        }
+
+    }
+
+    return pa_sink_process_msg(o, code, data, offset, chunk);
+}
+
+static int sco_process_render(struct userdata *u) {
+    void *p;
+    int ret = 0;
+    pa_memchunk memchunk;
+
+    pa_sink_render_full(u->sink, u->block_size, &memchunk);
+
+    p = pa_memblock_acquire(memchunk.memblock);
+
+    for (;;) {
+        ssize_t l;
+
+        l = pa_loop_write(u->stream_fd, (uint8_t*) p, memchunk.length, NULL);
+        pa_log_debug("Memblock written to socket: %li bytes", (long) l);
+
+        pa_assert(l != 0);
+
+        if (l > 0) {
+            u->offset += (uint64_t) l;
+            break;
+        }
+
+        if (errno == EINTR)
+            pa_log_debug("EINTR");
+        else if (errno == EAGAIN)
+            pa_log_debug("EAGAIN");
+        else {
+            pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
+            ret = -1;
+            break;
+        }
+    }
+
+    pa_memblock_release(memchunk.memblock);
+    pa_memblock_unref(memchunk.memblock);
+
+    return ret;
+}
+
+static int a2dp_process_render(struct userdata *u) {
+    int written;
+
+    struct bt_a2dp *a2dp = &u->a2dp;
+    struct rtp_header *header = (void *) a2dp->buffer;
+    struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header));
+
+    pa_assert(u);
+
+    do {
+        /* Render some data */
+        int frame_size, encoded;
+        void *p;
+        pa_memchunk memchunk;
+
+        pa_sink_render_full(u->sink, u->block_size, &memchunk);
+
+        p = pa_memblock_acquire(memchunk.memblock);
+
+        frame_size = (uint16_t) sbc_get_frame_length(&a2dp->sbc);
+        pa_log_debug("SBC frame_size: %d", frame_size);
+
+        encoded = sbc_encode(&a2dp->sbc, p, (int) a2dp->codesize, a2dp->buffer + a2dp->count,
+                             (int) (sizeof(a2dp->buffer) - a2dp->count), &written);
+        pa_log_debug("SBC: encoded: %d; written: %d", encoded, written);
+
+        pa_memblock_release(memchunk.memblock);
+        pa_memblock_unref(memchunk.memblock);
+
+        if (encoded <= 0) {
+            pa_log_error("SBC encoding error (%d)", encoded);
+            return -1;
+        }
+
+        a2dp->count += (size_t) written;
+        a2dp->frame_count++;
+        a2dp->samples += (unsigned) encoded / frame_size;
+        a2dp->total_samples += (unsigned) encoded / frame_size;
+
+    } while (a2dp->count + (size_t) written <= u->link_mtu);
+
+    /* write it to the fifo */
+    memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
+    payload->frame_count = a2dp->frame_count;
+    header->v = 2;
+    header->pt = 1;
+    header->sequence_number = htons(a2dp->seq_num);
+    header->timestamp = htonl(a2dp->total_samples);
+    header->ssrc = htonl(1);
+
+    for (;;) {
+        ssize_t l;
+
+        l = pa_loop_write(u->stream_fd, a2dp->buffer, a2dp->count, NULL);
+        pa_log_debug("avdtp_write: requested %lu bytes; written %li bytes", (unsigned long) a2dp->count, (long) l);
+
+        pa_assert(l != 0);
+
+        if (l > 0)
+            break;
+
+        if (errno == EINTR)
+            pa_log_debug("EINTR");
+        else if (errno == EAGAIN)
+            pa_log_debug("EAGAIN");
+        else {
+            pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
+            return -1;
+        }
+    }
+
+    u->offset += a2dp->codesize*a2dp->frame_count;
+
+    /* Reset buffer of data to send */
+    a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
+    a2dp->frame_count = 0;
+    a2dp->samples = 0;
+    a2dp->seq_num++;
+
+    return 0;
+}
+
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(u);
+
+    pa_log_debug("IO Thread starting up");
+
+    if (u->core->realtime_scheduling)
+        pa_make_realtime(u->core->realtime_priority);
+
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
+
+    pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
+
+    for (;;) {
+        int ret, l;
+        struct pollfd *pollfd;
+        uint64_t n;
+        pa_usec_t usec;
+
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+            if (u->sink->thread_info.rewind_requested)
+                pa_sink_process_rewind(u->sink, 0);
+
+        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
+            if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+                if ((l = a2dp_process_render(u)) < 0)
+                    goto fail;
+            } else {
+                if ((l = sco_process_render(u)) < 0)
+                    goto fail;
+            }
+            pollfd->revents = 0;
+
+            /* feed the time smoother */
+            n = u->offset;
+            if (ioctl(u->stream_fd, SIOCOUTQ, &l) >= 0 && l > 0)
+                n -= (uint64_t) l;
+            usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
+            if (usec > u->latency)
+                usec -= u->latency;
+            else
+                usec = 0;
+            pa_smoother_put(u->smoother, pa_rtclock_usec(), usec);
+        }
+
+        /* Hmm, nothing to do. Let's sleep */
+        pa_log_debug("IO thread going to sleep");
+        pollfd->events = (short) (PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0);
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
+            pa_log_error("rtpoll_run < 0");
+            goto fail;
+        }
+        pa_log_debug("IO thread waking up");
+
+        if (ret == 0) {
+            pa_log_debug("rtpoll_run == 0");
+            goto finish;
+        }
+
+        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+        if (pollfd->revents & ~POLLOUT) {
+            pa_log_error("FIFO shutdown.");
+            goto fail;
+        }
+    }
+
+fail:
+    /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
+    pa_log_debug("IO thread failed");
+    pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
+    pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
+
+finish:
+    pa_log_debug("IO thread shutting down");
+}
+
+int pa__init(pa_module* m) {
+    int e;
+    pa_modargs *ma;
+    uint32_t channels;
+    pa_sink_new_data data;
+    struct pollfd *pollfd;
+    struct userdata *u;
+
+    pa_assert(m);
+    m->userdata = u = pa_xnew0(struct userdata, 1);
+    u->module = m;
+    u->core = m->core;
+    u->audioservice_fd = -1;
+    u->stream_fd = -1;
+    u->transport = (uint8_t) -1;
+    u->offset = 0;
+    u->latency = 0;
+    u->a2dp.sbc_initialized = FALSE;
+    u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
+    u->rtpoll = pa_rtpoll_new();
+    pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
+    u->rtpoll_item = NULL;
+    u->ss = m->core->default_sample_spec;
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log_error("Failed to parse module arguments");
+        goto fail;
+    }
+    if (!(u->name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)))) {
+        pa_log_error("Failed to get device name from module arguments");
+        goto fail;
+    }
+    if (!(u->addr = pa_xstrdup(pa_modargs_get_value(ma, "address", NULL)))) {
+        pa_log_error("Failed to get device address from module arguments");
+        goto fail;
+    }
+    if (!(u->profile = pa_xstrdup(pa_modargs_get_value(ma, "profile", NULL)))) {
+        pa_log_error("Failed to get profile from module arguments");
+        goto fail;
+    }
+    if (pa_modargs_get_value_u32(ma, "rate", &u->ss.rate) < 0) {
+        pa_log_error("Failed to get rate from module arguments");
+        goto fail;
+    }
+
+    channels = u->ss.channels;
+    if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0) {
+        pa_log_error("Failed to get channels from module arguments");
+        goto fail;
+    }
+    u->ss.channels = (uint8_t) channels;
+
+    /* connect to the bluez audio service */
+    u->audioservice_fd = bt_audio_service_open();
+    if (u->audioservice_fd <= 0) {
+        pa_log_error("Couldn't connect to bluetooth audio service");
+        goto fail;
+    }
+    pa_log_debug("Connected to the bluetooth audio service");
+
+    /* queries device capabilities */
+    e = bt_getcaps(u);
+    if (e < 0) {
+        pa_log_error("Failed to get device capabilities");
+        goto fail;
+    }
+    pa_log_debug("Got device capabilities");
+
+    /* configures the connection */
+    e = bt_setconf(u);
+    if (e < 0) {
+        pa_log_error("Failed to set config");
+        goto fail;
+    }
+    pa_log_debug("Connection to the device configured");
+
+    /* gets the device socket */
+    e = bt_getstreamfd(u);
+    if (e < 0) {
+        pa_log_error("Failed to get stream fd (%d)", e);
+        goto fail;
+    }
+    pa_log_debug("Got the device socket");
+
+    /* create sink */
+    pa_sink_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_sink_new_data_set_name(&data, u->name);
+    pa_sink_new_data_set_sample_spec(&data, &u->ss);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth %s '%s' (%s)", u->strtransport, u->name, u->addr);
+    pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_API, "bluez");
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CLASS, "sound");
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CONNECTOR, "bluetooth");
+/*     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, "headset"); /\*FIXME*\/ */
+/*     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_VENDOR_PRODUCT_ID, "product_id"); /\*FIXME*\/ */
+/*     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_SERIAL, "serial"); /\*FIXME*\/ */
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
+    pa_sink_new_data_done(&data);
+    if (!u->sink) {
+        pa_log_error("Failed to create sink");
+        goto fail;
+    }
+    u->sink->userdata = u;
+    u->sink->parent.process_msg = sink_process_msg;
+    pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
+    pa_sink_set_rtpoll(u->sink, u->rtpoll);
+
+    u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
+    pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+    pollfd->fd = u->stream_fd;
+    pollfd->events = pollfd->revents = 0;
+
+    /* start rt thread */
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log_error("Failed to create IO thread");
+        goto fail;
+    }
+    pa_sink_put(u->sink);
+
+    pa_modargs_free(ma);
+    return 0;
+
+fail:
+    if (ma)
+        pa_modargs_free(ma);
+
+    pa__done(m);
+    return -1;
+}
+
+void pa__done(pa_module *m) {
+    struct userdata *u;
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->sink)
+        pa_sink_unlink(u->sink);
+
+    if (u->thread) {
+        pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+        pa_thread_free(u->thread);
+    }
+
+    if (u->sink)
+        pa_sink_unref(u->sink);
+
+    pa_thread_mq_done(&u->thread_mq);
+
+    if (u->rtpoll_item)
+        pa_rtpoll_item_free(u->rtpoll_item);
+
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+
+    if (u->smoother)
+        pa_smoother_free(u->smoother);
+
+    pa_xfree(u->name);
+    pa_xfree(u->addr);
+    pa_xfree(u->profile);
+    pa_xfree(u->strtransport);
+
+    if (u->stream_fd >= 0)
+        pa_close(u->stream_fd);
+
+    if (u->audioservice_fd >= 0)
+        pa_close(u->audioservice_fd);
+
+    pa_xfree(u);
+}
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
new file mode 100644 (file)
index 0000000..1494431
--- /dev/null
@@ -0,0 +1,928 @@
+/***
+    This file is part of PulseAudio.
+
+    Copyright 2008 Joao Paulo Rechi Vita
+
+    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 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/module.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/llist.h>
+#include <pulsecore/core-util.h>
+
+#include "dbus-util.h"
+#include "module-bluetooth-discover-symdef.h"
+
+PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
+PA_MODULE_DESCRIPTION("Detect available bluetooth audio devices and load bluetooth audio drivers");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_USAGE("");
+
+#define HSP_HS_UUID             "00001108-0000-1000-8000-00805F9B34FB"
+#define HFP_HS_UUID             "0000111E-0000-1000-8000-00805F9B34FB"
+#define A2DP_SOURCE_UUID        "0000110A-0000-1000-8000-00805F9B34FB"
+#define A2DP_SINK_UUID          "0000110B-0000-1000-8000-00805F9B34FB"
+
+struct uuid {
+    char *uuid;
+    PA_LLIST_FIELDS(struct uuid);
+};
+
+struct device {
+    char *name;
+    char *object_path;
+    int paired;
+    struct adapter *adapter;
+    char *alias;
+    int connected;
+    PA_LLIST_HEAD(struct uuid, uuid_list);
+    char *address;
+    int class;
+    int trusted;
+    const char *audio_profile;
+    uint32_t module_index;
+    PA_LLIST_FIELDS(struct device);
+};
+
+struct adapter {
+    char *object_path;
+    char *name;
+    char *mode;
+    char *address;
+    PA_LLIST_HEAD(struct device, device_list);
+    PA_LLIST_FIELDS(struct adapter);
+};
+
+struct userdata {
+    pa_module *module;
+    pa_dbus_connection *conn;
+    PA_LLIST_HEAD(struct adapter, adapter_list);
+};
+
+static struct uuid *uuid_new(const char *uuid) {
+    struct uuid *node;
+
+    node = pa_xnew(struct uuid, 1);
+    node->uuid = pa_xstrdup(uuid);
+    PA_LLIST_INIT(struct uuid, node);
+
+    return node;
+}
+
+static void uuid_free(struct uuid *uuid) {
+    pa_assert(uuid);
+
+    pa_xfree(uuid->uuid);
+    pa_xfree(uuid);
+}
+
+static struct device *device_new(struct adapter *adapter, const char *object_path) {
+    struct device *node;
+
+    node = pa_xnew(struct device, 1);
+    node->name = NULL;
+    node->object_path = pa_xstrdup(object_path);
+    node->paired = -1;
+    node->adapter = adapter;
+    node->alias = NULL;
+    node->connected = -1;
+    PA_LLIST_HEAD_INIT(struct uuid, node->uuid_list);
+    node->address = NULL;
+    node->class = -1;
+    node->trusted = -1;
+    node->audio_profile = NULL;
+    node->module_index = PA_INVALID_INDEX;
+    PA_LLIST_INIT(struct device, node);
+
+    return node;
+}
+
+static void device_free(struct device *device) {
+    struct uuid *i;
+
+    pa_assert(device);
+
+    while ((i = device->uuid_list)) {
+        PA_LLIST_REMOVE(struct uuid, device->uuid_list, i);
+        uuid_free(i);
+    }
+
+    pa_xfree(device->name);
+    pa_xfree(device->object_path);
+    pa_xfree(device->alias);
+    pa_xfree(device->address);
+    pa_xfree(device);
+}
+
+static struct adapter *adapter_new(const char *object_path) {
+    struct adapter *node;
+
+    node = pa_xnew(struct adapter, 1);
+    node->object_path = pa_xstrdup(object_path);
+    node->mode = NULL;
+    node->address = NULL;
+    node->name = NULL;
+
+    PA_LLIST_HEAD_INIT(struct device, node->device_list);
+    PA_LLIST_INIT(struct adapter, node);
+
+    return node;
+}
+
+static void adapter_free(struct adapter *adapter) {
+    struct device *i;
+
+    pa_assert(adapter);
+
+    while ((i = adapter->device_list)) {
+        PA_LLIST_REMOVE(struct device, adapter->device_list, i);
+        device_free(i);
+    }
+
+    pa_xfree(adapter->object_path);
+    pa_xfree(adapter->mode);
+    pa_xfree(adapter->address);
+    pa_xfree(adapter->name);
+    pa_xfree(adapter);
+}
+
+static struct adapter* adapter_find(struct userdata *u, const char *path) {
+    struct adapter *i;
+
+    for (i = u->adapter_list; i; i = i->next)
+        if (pa_streq(i->object_path, path))
+            return i;
+
+    return NULL;
+}
+
+static struct device* device_find(struct userdata *u, const char *path) {
+    struct adapter *j;
+    struct device *i;
+
+    for (j = u->adapter_list; j; j = j->next)
+        for (i = j->device_list; i; i = i->next)
+            if (pa_streq(i->object_path, path))
+                return i;
+
+    return NULL;
+}
+
+static const char *yes_no_na(int b) {
+    if (b < 0)
+        return "n/a";
+
+    return pa_yes_no(b);
+}
+
+static void print_devices(struct adapter *a) {
+    struct device *i;
+
+    pa_assert(a);
+
+    for (i = a->device_list; i; i = i->next) {
+        struct uuid *j;
+
+        if (pa_streq(i->object_path, "/DEVICE_HEAD"))
+            continue;
+
+        pa_log_debug("\t[ %s ]\n"
+                     "\t\tName = %s\n"
+                     "\t\tPaired = %s\n"
+                     "\t\tAdapter = %s\n"
+                     "\t\tAlias = %s\n"
+                     "\t\tConnected = %s\n"
+                     "\t\tAudio = %s\n",
+                     i->object_path,
+                     pa_strnull(i->name),
+                     yes_no_na(i->paired),
+                     i->adapter->object_path,
+                     pa_strnull(i->alias),
+                     yes_no_na(i->connected),
+                     pa_strnull(i->audio_profile));
+
+        pa_log_debug("\t\tUUIDs = ");
+        for (j = i->uuid_list; j; j = j->next) {
+
+            if (pa_streq(j->uuid, "UUID_HEAD"))
+                continue;
+
+            pa_log_debug("\t\t         %s", j->uuid);
+        }
+
+        pa_log_debug("\t\tAddress = %s\n"
+                     "\t\tClass = 0x%x\n"
+                     "\t\tTrusted = %s",
+                     i->address,
+                     i->class,
+                     yes_no_na(i->trusted));
+    }
+}
+
+static void print_adapters(struct userdata *u) {
+    struct adapter *i;
+
+    pa_assert(u);
+
+    for (i = u->adapter_list; i; i = i->next) {
+
+        if (pa_streq(i->object_path, "/ADAPTER_HEAD"))
+            continue;
+
+        pa_log_debug(
+                "[ %s ]\n"
+                "\tName = %s\n"
+                "\tMode = %s\n"
+                "\tAddress = %s\n",
+                i->object_path,
+                pa_strnull(i->name),
+                pa_strnull(i->mode),
+                pa_strnull(i->address));
+
+        print_devices(i);
+    }
+}
+
+static const char *strip_object_path(const char *op) {
+    const char *slash;
+
+    if ((slash = strrchr(op, '/')))
+        return slash+1;
+
+    return op;
+}
+
+static void load_module_for_device(struct userdata *u, struct device *d) {
+    char *args;
+    pa_module *m;
+
+    pa_assert(u);
+    pa_assert(d);
+
+    /* Check whether we already loaded a module for this device */
+    if (d->module_index != PA_INVALID_INDEX &&
+        pa_idxset_get_by_index(u->module->core->modules, d->module_index))
+        return;
+
+    /* Check whether this is an audio device */
+    if (!d->audio_profile) {
+        pa_log_debug("Ignoring %s since it is not an audio device.", d->object_path);
+        return;
+    }
+
+    args = pa_sprintf_malloc("sink_name=%s address=%s profile=%s", strip_object_path(d->object_path), d->address, d->audio_profile);
+    m = pa_module_load(u->module->core, "module-bluetooth-device", args);
+    pa_xfree(args);
+
+    if (!m) {
+        pa_log_debug("Failed to load module for device %s", d->object_path);
+        return;
+    }
+
+    d->module_index = m->index;
+}
+
+static void load_modules(struct userdata *u) {
+    struct device *d;
+    struct adapter *a;
+
+    pa_assert(u);
+
+    for (a = u->adapter_list; a; a = a->next)
+        for (d = a->device_list; d; d = d->next)
+            load_module_for_device(u, d);
+}
+
+static int parse_adapter_property(struct userdata *u, struct adapter *a, DBusMessageIter *i) {
+    const char *key;
+    DBusMessageIter variant_i;
+
+    pa_assert(u);
+    pa_assert(a);
+    pa_assert(i);
+
+    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) {
+        pa_log("Property name not a string.");
+        return -1;
+    }
+
+    dbus_message_iter_get_basic(i, &key);
+
+    if (!dbus_message_iter_next(i)) {
+        pa_log("Property value missing");
+        return -1;
+    }
+
+    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) {
+        pa_log("Property value not a variant.");
+        return -1;
+    }
+
+    dbus_message_iter_recurse(i, &variant_i);
+
+    if (dbus_message_iter_get_arg_type(&variant_i) == DBUS_TYPE_STRING) {
+        const char *value;
+        dbus_message_iter_get_basic(&variant_i, &value);
+
+        if (pa_streq(key, "Mode")) {
+            pa_xfree(a->mode);
+            a->mode = pa_xstrdup(value);
+        } else if (pa_streq(key, "Address")) {
+            pa_xstrdup(a->address);
+            a->address = pa_xstrdup(value);
+        } else if (pa_streq(key, "Name")) {
+            pa_xfree(a->name);
+            a->name = pa_xstrdup(value);
+        }
+    }
+
+    return 0;
+}
+
+static int get_adapter_properties(struct userdata *u, struct adapter *a) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
+    DBusMessageIter arg_i, element_i;
+    int ret = -1;
+
+    pa_assert(u);
+    pa_assert(a);
+    dbus_error_init(&e);
+
+    pa_assert_se(m = dbus_message_new_method_call("org.bluez", a->object_path, "org.bluez.Adapter", "GetProperties"));
+
+    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
+    if (!r) {
+        pa_log("org.bluez.Adapter.GetProperties failed: %s", e.message);
+        goto finish;
+    }
+
+    if (!dbus_message_iter_init(r, &arg_i)) {
+        pa_log("org.bluez.Adapter.GetProperties reply has no arguments");
+        goto finish;
+    }
+
+    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+        pa_log("org.bluez.Adapter.GetProperties argument is not an array");
+        goto finish;
+    }
+
+    dbus_message_iter_recurse(&arg_i, &element_i);
+    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+
+        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
+            DBusMessageIter dict_i;
+
+            dbus_message_iter_recurse(&element_i, &dict_i);
+
+            if (parse_adapter_property(u, a, &dict_i) < 0)
+                goto finish;
+        }
+
+        if (!dbus_message_iter_next(&element_i))
+            break;
+    }
+
+    ret = 0;
+
+finish:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+
+    dbus_error_free(&e);
+
+    return ret;
+}
+
+static int detect_adapters(struct userdata *u) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
+    DBusMessageIter arg_i, element_i;
+    struct adapter *adapter_list_i;
+    int ret = -1;
+
+    pa_assert(u);
+    dbus_error_init(&e);
+
+    /* get adapters */
+    pa_assert_se(m = dbus_message_new_method_call("org.bluez", "/", "org.bluez.Manager", "ListAdapters"));
+    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
+    if (!r) {
+        pa_log("org.bluez.Manager.ListAdapters failed: %s", e.message);
+        goto finish;
+    }
+
+    if (!dbus_message_iter_init(r, &arg_i)) {
+        pa_log("org.bluez.Manager.ListAdapters reply has no arguments");
+        goto finish;
+    }
+
+    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+        pa_log("org.bluez.Manager.ListAdapters argument is not an array");
+        goto finish;
+    }
+
+    dbus_message_iter_recurse(&arg_i, &element_i);
+    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
+
+            struct adapter *node;
+            const char *value;
+
+            dbus_message_iter_get_basic(&element_i, &value);
+            node = adapter_new(value);
+            PA_LLIST_PREPEND(struct adapter, u->adapter_list, node);
+        }
+
+        if (!dbus_message_iter_next(&element_i))
+            break;
+    }
+
+    ret = 0;
+
+    /* get adapter properties */
+    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next)
+        get_adapter_properties(u, adapter_list_i);
+
+finish:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+
+    dbus_error_free(&e);
+    return ret;
+}
+
+static int parse_device_property(struct userdata *u, struct device *d, DBusMessageIter *i) {
+    const char *key;
+    DBusMessageIter variant_i;
+
+    pa_assert(u);
+    pa_assert(d);
+    pa_assert(i);
+
+    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) {
+        pa_log("Property name not a string.");
+        return -1;
+    }
+
+    dbus_message_iter_get_basic(i, &key);
+
+    if (!dbus_message_iter_next(i))  {
+        pa_log("Property value missing");
+        return -1;
+    }
+
+    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) {
+        pa_log("Property value not a variant.");
+        return -1;
+    }
+
+    dbus_message_iter_recurse(i, &variant_i);
+
+    pa_log_debug("Parsing device property %s", key);
+
+    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, "Name")) {
+                pa_xfree(d->name);
+                d->name = pa_xstrdup(value);
+            } else if (pa_streq(key, "Alias")) {
+                pa_xfree(d->alias);
+                d->alias = pa_xstrdup(value);
+            } else if (pa_streq(key, "Address")) {
+                pa_xfree(d->address);
+                d->address = pa_xstrdup(value);
+            }
+
+            break;
+        }
+
+        case DBUS_TYPE_BOOLEAN: {
+
+            dbus_bool_t value;
+            dbus_message_iter_get_basic(&variant_i, &value);
+
+            if (pa_streq(key, "Paired"))
+                d->paired = !!value;
+            else if (pa_streq(key, "Connected"))
+                d->connected = !!value;
+            else if (pa_streq(key, "Trusted"))
+                d->trusted = !!value;
+
+            break;
+        }
+
+        case DBUS_TYPE_UINT32: {
+
+            uint32_t value;
+            dbus_message_iter_get_basic(&variant_i, &value);
+
+            if (pa_streq(key, "Class"))
+                d->class = (int) 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")) {
+
+                d->audio_profile = NULL;
+
+                while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) {
+                    struct uuid *node;
+                    const char *value;
+
+                    dbus_message_iter_get_basic(&ai, &value);
+                    node = uuid_new(value);
+                    PA_LLIST_PREPEND(struct uuid, d->uuid_list, node);
+
+                    if ((strcasecmp(value, A2DP_SOURCE_UUID) == 0) ||
+                        (strcasecmp(value, A2DP_SINK_UUID) == 0))
+                        d->audio_profile = "a2dp";
+                    else if (((strcasecmp(value, HSP_HS_UUID) == 0) ||
+                              (strcasecmp(value, HFP_HS_UUID) == 0)) &&
+                             !d->audio_profile)
+                        d->audio_profile = "hsp";
+
+                    if (!dbus_message_iter_next(&ai))
+                        break;
+                }
+            }
+
+            break;
+        }
+    }
+
+    return 0;
+}
+
+static int get_device_properties(struct userdata *u, struct device *d) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
+    DBusMessageIter arg_i, element_i;
+    int ret = -1;
+
+    pa_assert(u);
+    pa_assert(d);
+
+    dbus_error_init(&e);
+
+    pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->object_path, "org.bluez.Device", "GetProperties"));
+
+    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
+    if (!r) {
+        pa_log("org.bluez.Device.GetProperties failed: %s", e.message);
+        goto finish;
+    }
+
+    if (!dbus_message_iter_init(r, &arg_i)) {
+        pa_log("org.bluez.Device.GetProperties reply has no arguments");
+        goto finish;
+    }
+
+    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+        pa_log("org.bluez.Device.GetProperties argument is not an array");
+        goto finish;
+    }
+
+    dbus_message_iter_recurse(&arg_i, &element_i);
+    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+
+        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
+            DBusMessageIter dict_i;
+
+            dbus_message_iter_recurse(&element_i, &dict_i);
+
+            if (parse_device_property(u, d, &dict_i) < 0)
+                goto finish;
+        }
+
+        if (!dbus_message_iter_next(&element_i))
+            break;
+    }
+
+    ret = 0;
+
+finish:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+
+    dbus_error_free(&e);
+
+    return ret;
+}
+
+static int detect_devices(struct userdata *u) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
+    DBusMessageIter arg_i, element_i;
+    struct adapter *adapter_list_i;
+    struct device *device_list_i;
+    const char *value;
+    int ret = -1;
+
+    pa_assert(u);
+    dbus_error_init(&e);
+
+    /* get devices of each adapter */
+    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next) {
+
+        pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "ListDevices"));
+
+        r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
+        if (!r) {
+            pa_log("org.bluez.Adapter.ListDevices failed: %s", e.message);
+            goto finish;
+        }
+
+        if (!dbus_message_iter_init(r, &arg_i)) {
+            pa_log("org.bluez.Adapter.ListDevices reply has no arguments");
+            goto finish;
+        }
+
+        if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+            pa_log("org.bluez.Adapter.ListDevices argument is not an array");
+            goto finish;
+        }
+
+        dbus_message_iter_recurse(&arg_i, &element_i);
+        while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+            if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
+                struct device *node;
+                dbus_message_iter_get_basic(&element_i, &value);
+                node = device_new(adapter_list_i, value);
+                PA_LLIST_PREPEND(struct device, adapter_list_i->device_list, node);
+            }
+
+            if (!dbus_message_iter_next(&element_i))
+                break;
+        }
+    }
+
+    /* get device properties */
+    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next)
+        for (device_list_i = adapter_list_i->device_list; device_list_i; device_list_i = device_list_i->next)
+            get_device_properties(u, device_list_i);
+
+    ret = 0;
+
+finish:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+
+    dbus_error_free(&e);
+
+    return ret;
+}
+
+static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *userdata) {
+    DBusMessageIter arg_i;
+    DBusError err;
+    const char *value;
+    struct userdata *u;
+
+    pa_assert(bus);
+    pa_assert(msg);
+    pa_assert(userdata);
+    u = userdata;
+
+    dbus_error_init(&err);
+
+    pa_log_debug("dbus: interface=%s, path=%s, member=%s\n",
+            dbus_message_get_interface(msg),
+            dbus_message_get_path(msg),
+            dbus_message_get_member(msg));
+
+    if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterAdded")) {
+
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
+            pa_log("dbus: argument is not object path");
+        else {
+            struct adapter *node;
+
+            dbus_message_iter_get_basic(&arg_i, &value);
+            pa_log_debug("hcid: adapter %s added", value);
+
+            node = adapter_new(value);
+            PA_LLIST_PREPEND(struct adapter, u->adapter_list, node);
+
+            get_adapter_properties(u, node);
+        }
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterRemoved")) {
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
+            pa_log("dbus: argument is not object path");
+        else {
+            struct adapter *a;
+
+            dbus_message_iter_get_basic(&arg_i, &value);
+            pa_log_debug("hcid: adapter %s removed", value);
+
+            if ((a = adapter_find(u, value))) {
+                PA_LLIST_REMOVE(struct adapter, u->adapter_list, a);
+                adapter_free(a);
+            }
+        }
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "PropertyChanged")) {
+
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else {
+            struct adapter *a;
+
+            if ((a = adapter_find(u, dbus_message_get_path(msg))))
+                parse_adapter_property(u, a, &arg_i);
+        }
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceCreated")) {
+
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
+            pa_log("dbus: argument is not object path");
+        else {
+            struct adapter *adapter;
+
+            if (!(adapter = adapter_find(u, dbus_message_get_path(msg))))
+                pa_log("dbus: failed to find adapter for object path");
+            else {
+                struct device *node;
+
+                dbus_message_iter_get_basic(&arg_i, &value);
+                pa_log_debug("hcid: device %s created", value);
+
+                node = device_new(adapter, value);
+                PA_LLIST_PREPEND(struct device, adapter->device_list, node);
+
+                get_device_properties(u, node);
+                load_module_for_device(u, node);
+            }
+        }
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceRemoved")) {
+
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
+            pa_log("dbus: argument is not object path");
+        else {
+            struct device *d;
+
+            dbus_message_iter_get_basic(&arg_i, &value);
+            pa_log_debug("hcid: device %s removed", value);
+
+            if ((d = device_find(u, value))) {
+                PA_LLIST_REMOVE(struct device, d->adapter->device_list, d);
+                device_free(d);
+            }
+        }
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Device", "PropertyChanged")) {
+
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else {
+            struct device *d;
+
+            if ((d = device_find(u, dbus_message_get_path(msg)))) {
+                parse_device_property(u, d, &arg_i);
+
+                /* Hmm, something changed, let's try to reconnect if we
+                 * aren't connected yet */
+                load_module_for_device(u, d);
+            }
+        }
+    }
+
+    dbus_error_free(&err);
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+void pa__done(pa_module* m) {
+    struct userdata *u;
+    struct adapter *i;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    while ((i = u->adapter_list)) {
+        PA_LLIST_REMOVE(struct adapter, u->adapter_list, i);
+        adapter_free(i);
+    }
+
+    if (u->conn)
+        pa_dbus_connection_unref(u->conn);
+
+    pa_xfree(u);
+}
+
+int pa__init(pa_module* m) {
+    DBusError err;
+    struct userdata *u;
+
+    pa_assert(m);
+    dbus_error_init(&err);
+
+    m->userdata = u = pa_xnew(struct userdata, 1);
+    u->module = m;
+    PA_LLIST_HEAD_INIT(struct adapter, u->adapter_list);
+
+    /* connect to the bus */
+    u->conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err);
+    if (dbus_error_is_set(&err) || (u->conn == NULL) ) {
+        pa_log("Failed to get D-Bus connection: %s", err.message);
+        goto fail;
+    }
+
+    /* static detection of bluetooth audio devices */
+    detect_adapters(u);
+    detect_devices(u);
+
+    print_adapters(u);
+    load_modules(u);
+
+    /* dynamic detection of bluetooth audio devices */
+    if (!dbus_connection_add_filter(pa_dbus_connection_get(u->conn), filter_cb, u, NULL)) {
+        pa_log_error("Failed to add filter function");
+        goto fail;
+    }
+
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Manager'", &err);
+    if (dbus_error_is_set(&err)) {
+        pa_log_error("Unable to subscribe to org.bluez.Manager signals: %s: %s", err.name, err.message);
+        goto fail;
+    }
+
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Adapter'", &err);
+    if (dbus_error_is_set(&err)) {
+        pa_log_error("Unable to subscribe to org.bluez.Adapter signals: %s: %s", err.name, err.message);
+        goto fail;
+    }
+
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Device'", &err);
+    if (dbus_error_is_set(&err)) {
+        pa_log_error("Unable to subscribe to org.bluez.Device signals: %s: %s", err.name, err.message);
+        goto fail;
+    }
+
+    return 0;
+
+fail:
+    dbus_error_free(&err);
+    pa__done(m);
+
+    return -1;
+}
similarity index 99%
rename from src/modules/module-bt-proximity.c
rename to src/modules/bluetooth/module-bluetooth-proximity.c
index f924c3cb4eb0d76709a36ea26cc857ea69706113..5cca36e5245f054a1b2460fdaaa1873f156bd52a 100644 (file)
@@ -44,7 +44,7 @@
 #include <pulsecore/start-child.h>
 
 #include "dbus-util.h"
-#include "module-bt-proximity-symdef.h"
+#include "module-bluetooth-proximity-symdef.h"
 
 PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("Bluetooth Proximity Volume Control");
diff --git a/src/modules/bluetooth/rtp.h b/src/modules/bluetooth/rtp.h
new file mode 100644 (file)
index 0000000..690bd43
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This library 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.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct rtp_header {
+       uint8_t cc:4;
+       uint8_t x:1;
+       uint8_t p:1;
+       uint8_t v:2;
+
+       uint8_t pt:7;
+       uint8_t m:1;
+
+       uint16_t sequence_number;
+       uint32_t timestamp;
+       uint32_t ssrc;
+       uint32_t csrc[0];
+} __attribute__ ((packed));
+
+struct rtp_payload {
+       uint8_t frame_count:4;
+       uint8_t rfa0:1;
+       uint8_t is_last_fragment:1;
+       uint8_t is_first_fragment:1;
+       uint8_t is_fragmented:1;
+} __attribute__ ((packed));
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct rtp_header {
+       uint8_t v:2;
+       uint8_t p:1;
+       uint8_t x:1;
+       uint8_t cc:4;
+
+       uint8_t m:1;
+       uint8_t pt:7;
+
+       uint16_t sequence_number;
+       uint32_t timestamp;
+       uint32_t ssrc;
+       uint32_t csrc[0];
+} __attribute__ ((packed));
+
+struct rtp_payload {
+       uint8_t is_fragmented:1;
+       uint8_t is_first_fragment:1;
+       uint8_t is_last_fragment:1;
+       uint8_t rfa0:1;
+       uint8_t frame_count:4;
+} __attribute__ ((packed));
+
+#else
+#error "Unknown byte order"
+#endif
diff --git a/src/modules/bluetooth/sbc.c b/src/modules/bluetooth/sbc.c
new file mode 100644 (file)
index 0000000..02a6143
--- /dev/null
@@ -0,0 +1,1411 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2008  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library 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.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/* todo items:
+
+  use a log2 table for byte integer scale factors calculation (sum log2 results
+  for high and low bytes) fill bitpool by 16 bits instead of one at a time in
+  bits allocation/bitpool generation port to the dsp
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "sbc_math.h"
+#include "sbc_tables.h"
+
+#include "sbc.h"
+
+#define SBC_SYNCWORD   0x9C
+
+/* This structure contains an unpacked SBC frame.
+   Yes, there is probably quite some unused space herein */
+struct sbc_frame {
+       uint8_t frequency;
+       uint8_t block_mode;
+       uint8_t blocks;
+       enum {
+               MONO            = SBC_MODE_MONO,
+               DUAL_CHANNEL    = SBC_MODE_DUAL_CHANNEL,
+               STEREO          = SBC_MODE_STEREO,
+               JOINT_STEREO    = SBC_MODE_JOINT_STEREO
+       } mode;
+       uint8_t channels;
+       enum {
+               LOUDNESS        = SBC_AM_LOUDNESS,
+               SNR             = SBC_AM_SNR
+       } allocation;
+       uint8_t subband_mode;
+       uint8_t subbands;
+       uint8_t bitpool;
+       uint8_t codesize;
+       uint8_t length;
+
+       /* bit number x set means joint stereo has been used in subband x */
+       uint8_t joint;
+
+       /* only the lower 4 bits of every element are to be used */
+       uint8_t scale_factor[2][8];
+
+       /* raw integer subband samples in the frame */
+
+       int32_t sb_sample_f[16][2][8];
+       int32_t sb_sample[16][2][8];    /* modified subband samples */
+       int16_t pcm_sample[2][16*8];    /* original pcm audio samples */
+};
+
+struct sbc_decoder_state {
+       int subbands;
+       int32_t V[2][170];
+       int offset[2][16];
+};
+
+struct sbc_encoder_state {
+       int subbands;
+       int position[2];
+       int32_t X[2][160];
+};
+
+/*
+ * Calculates the CRC-8 of the first len bits in data
+ */
+static const uint8_t crc_table[256] = {
+       0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53,
+       0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB,
+       0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E,
+       0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76,
+       0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4,
+       0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C,
+       0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19,
+       0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1,
+       0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40,
+       0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8,
+       0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D,
+       0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65,
+       0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7,
+       0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F,
+       0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A,
+       0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2,
+       0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75,
+       0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D,
+       0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8,
+       0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50,
+       0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2,
+       0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A,
+       0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F,
+       0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7,
+       0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66,
+       0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E,
+       0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB,
+       0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43,
+       0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1,
+       0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09,
+       0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C,
+       0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4
+};
+
+static uint8_t sbc_crc8(const uint8_t *data, size_t len)
+{
+       uint8_t crc = 0x0f;
+       size_t i;
+       uint8_t octet;
+
+       for (i = 0; i < len / 8; i++)
+               crc = crc_table[crc ^ data[i]];
+
+       octet = data[i];
+       for (i = 0; i < len % 8; i++) {
+               unsigned char bit = ((octet ^ crc) & 0x80) >> 7;
+
+               crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0);
+
+               octet = octet << 1;
+       }
+
+       return crc;
+}
+
+/*
+ * Code straight from the spec to calculate the bits array
+ * Takes a pointer to the frame in question, a pointer to the bits array and
+ * the sampling frequency (as 2 bit integer)
+ */
+static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8])
+{
+       uint8_t sf = frame->frequency;
+
+       if (frame->mode == MONO || frame->mode == DUAL_CHANNEL) {
+               int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice;
+               int ch, sb;
+
+               for (ch = 0; ch < frame->channels; ch++) {
+                       max_bitneed = 0;
+                       if (frame->allocation == SNR) {
+                               for (sb = 0; sb < frame->subbands; sb++) {
+                                       bitneed[ch][sb] = frame->scale_factor[ch][sb];
+                                       if (bitneed[ch][sb] > max_bitneed)
+                                               max_bitneed = bitneed[ch][sb];
+                               }
+                       } else {
+                               for (sb = 0; sb < frame->subbands; sb++) {
+                                       if (frame->scale_factor[ch][sb] == 0)
+                                               bitneed[ch][sb] = -5;
+                                       else {
+                                               if (frame->subbands == 4)
+                                                       loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
+                                               else
+                                                       loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
+                                               if (loudness > 0)
+                                                       bitneed[ch][sb] = loudness / 2;
+                                               else
+                                                       bitneed[ch][sb] = loudness;
+                                       }
+                                       if (bitneed[ch][sb] > max_bitneed)
+                                               max_bitneed = bitneed[ch][sb];
+                               }
+                       }
+
+                       bitcount = 0;
+                       slicecount = 0;
+                       bitslice = max_bitneed + 1;
+                       do {
+                               bitslice--;
+                               bitcount += slicecount;
+                               slicecount = 0;
+                               for (sb = 0; sb < frame->subbands; sb++) {
+                                       if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
+                                               slicecount++;
+                                       else if (bitneed[ch][sb] == bitslice + 1)
+                                               slicecount += 2;
+                               }
+                       } while (bitcount + slicecount < frame->bitpool);
+
+                       if (bitcount + slicecount == frame->bitpool) {
+                               bitcount += slicecount;
+                               bitslice--;
+                       }
+
+                       for (sb = 0; sb < frame->subbands; sb++) {
+                               if (bitneed[ch][sb] < bitslice + 2)
+                                       bits[ch][sb] = 0;
+                               else {
+                                       bits[ch][sb] = bitneed[ch][sb] - bitslice;
+                                       if (bits[ch][sb] > 16)
+                                               bits[ch][sb] = 16;
+                               }
+                       }
+
+                       for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) {
+                               if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) {
+                                       bits[ch][sb]++;
+                                       bitcount++;
+                               } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) {
+                                       bits[ch][sb] = 2;
+                                       bitcount += 2;
+                               }
+                       }
+
+                       for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) {
+                               if (bits[ch][sb] < 16) {
+                                       bits[ch][sb]++;
+                                       bitcount++;
+                               }
+                       }
+
+               }
+
+       } else if (frame->mode == STEREO || frame->mode == JOINT_STEREO) {
+               int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice;
+               int ch, sb;
+
+               max_bitneed = 0;
+               if (frame->allocation == SNR) {
+                       for (ch = 0; ch < 2; ch++) {
+                               for (sb = 0; sb < frame->subbands; sb++) {
+                                       bitneed[ch][sb] = frame->scale_factor[ch][sb];
+                                       if (bitneed[ch][sb] > max_bitneed)
+                                               max_bitneed = bitneed[ch][sb];
+                               }
+                       }
+               } else {
+                       for (ch = 0; ch < 2; ch++) {
+                               for (sb = 0; sb < frame->subbands; sb++) {
+                                       if (frame->scale_factor[ch][sb] == 0)
+                                               bitneed[ch][sb] = -5;
+                                       else {
+                                               if (frame->subbands == 4)
+                                                       loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
+                                               else
+                                                       loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
+                                               if (loudness > 0)
+                                                       bitneed[ch][sb] = loudness / 2;
+                                               else
+                                                       bitneed[ch][sb] = loudness;
+                                       }
+                                       if (bitneed[ch][sb] > max_bitneed)
+                                               max_bitneed = bitneed[ch][sb];
+                               }
+                       }
+               }
+
+               bitcount = 0;
+               slicecount = 0;
+               bitslice = max_bitneed + 1;
+               do {
+                       bitslice--;
+                       bitcount += slicecount;
+                       slicecount = 0;
+                       for (ch = 0; ch < 2; ch++) {
+                               for (sb = 0; sb < frame->subbands; sb++) {
+                                       if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
+                                               slicecount++;
+                                       else if (bitneed[ch][sb] == bitslice + 1)
+                                               slicecount += 2;
+                               }
+                       }
+               } while (bitcount + slicecount < frame->bitpool);
+
+               if (bitcount + slicecount == frame->bitpool) {
+                       bitcount += slicecount;
+                       bitslice--;
+               }
+
+               for (ch = 0; ch < 2; ch++) {
+                       for (sb = 0; sb < frame->subbands; sb++) {
+                               if (bitneed[ch][sb] < bitslice + 2) {
+                                       bits[ch][sb] = 0;
+                               } else {
+                                       bits[ch][sb] = bitneed[ch][sb] - bitslice;
+                                       if (bits[ch][sb] > 16)
+                                               bits[ch][sb] = 16;
+                               }
+                       }
+               }
+
+               ch = 0;
+               sb = 0;
+               while (bitcount < frame->bitpool) {
+                       if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) {
+                               bits[ch][sb]++;
+                               bitcount++;
+                       } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) {
+                               bits[ch][sb] = 2;
+                               bitcount += 2;
+                       }
+                       if (ch == 1) {
+                               ch = 0;
+                               sb++;
+                               if (sb >= frame->subbands) break;
+                       } else
+                               ch = 1;
+               }
+
+               ch = 0;
+               sb = 0;
+               while (bitcount < frame->bitpool) {
+                       if (bits[ch][sb] < 16) {
+                               bits[ch][sb]++;
+                               bitcount++;
+                       }
+                       if (ch == 1) {
+                               ch = 0;
+                               sb++;
+                               if (sb >= frame->subbands) break;
+                       } else
+                               ch = 1;
+               }
+
+       }
+
+}
+
+/*
+ * Unpacks a SBC frame at the beginning of the stream in data,
+ * which has at most len bytes into frame.
+ * Returns the length in bytes of the packed frame, or a negative
+ * value on error. The error codes are:
+ *
+ *  -1   Data stream too short
+ *  -2   Sync byte incorrect
+ *  -3   CRC8 incorrect
+ *  -4   Bitpool value out of bounds
+ */
+static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
+                               size_t len)
+{
+       int consumed;
+       /* Will copy the parts of the header that are relevant to crc
+        * calculation here */
+       uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+       int crc_pos = 0;
+       int32_t temp;
+
+       int audio_sample;
+       int ch, sb, blk, bit;   /* channel, subband, block and bit standard
+                                  counters */
+       int bits[2][8];         /* bits distribution */
+       uint32_t levels[2][8];  /* levels derived from that */
+
+       if (len < 4)
+               return -1;
+
+       if (data[0] != SBC_SYNCWORD)
+               return -2;
+
+       frame->frequency = (data[1] >> 6) & 0x03;
+
+       frame->block_mode = (data[1] >> 4) & 0x03;
+       switch (frame->block_mode) {
+       case SBC_BLK_4:
+               frame->blocks = 4;
+               break;
+       case SBC_BLK_8:
+               frame->blocks = 8;
+               break;
+       case SBC_BLK_12:
+               frame->blocks = 12;
+               break;
+       case SBC_BLK_16:
+               frame->blocks = 16;
+               break;
+       }
+
+       frame->mode = (data[1] >> 2) & 0x03;
+       switch (frame->mode) {
+       case MONO:
+               frame->channels = 1;
+               break;
+       case DUAL_CHANNEL:      /* fall-through */
+       case STEREO:
+       case JOINT_STEREO:
+               frame->channels = 2;
+               break;
+       }
+
+       frame->allocation = (data[1] >> 1) & 0x01;
+
+       frame->subband_mode = (data[1] & 0x01);
+       frame->subbands = frame->subband_mode ? 8 : 4;
+
+       frame->bitpool = data[2];
+
+       if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+                       frame->bitpool > 16 * frame->subbands)
+               return -4;
+
+       if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+                       frame->bitpool > 32 * frame->subbands)
+               return -4;
+
+       /* data[3] is crc, we're checking it later */
+
+       consumed = 32;
+
+       crc_header[0] = data[1];
+       crc_header[1] = data[2];
+       crc_pos = 16;
+
+       if (frame->mode == JOINT_STEREO) {
+               if (len * 8 < consumed + frame->subbands)
+                       return -1;
+
+               frame->joint = 0x00;
+               for (sb = 0; sb < frame->subbands - 1; sb++)
+                       frame->joint |= ((data[4] >> (7 - sb)) & 0x01) << sb;
+               if (frame->subbands == 4)
+                       crc_header[crc_pos / 8] = data[4] & 0xf0;
+               else
+                       crc_header[crc_pos / 8] = data[4];
+
+               consumed += frame->subbands;
+               crc_pos += frame->subbands;
+       }
+
+       if (len * 8 < consumed + (4 * frame->subbands * frame->channels))
+               return -1;
+
+       for (ch = 0; ch < frame->channels; ch++) {
+               for (sb = 0; sb < frame->subbands; sb++) {
+                       /* FIXME assert(consumed % 4 == 0); */
+                       frame->scale_factor[ch][sb] =
+                               (data[consumed >> 3] >> (4 - (consumed & 0x7))) & 0x0F;
+                       crc_header[crc_pos >> 3] |=
+                               frame->scale_factor[ch][sb] << (4 - (crc_pos & 0x7));
+
+                       consumed += 4;
+                       crc_pos += 4;
+               }
+       }
+
+       if (data[3] != sbc_crc8(crc_header, crc_pos))
+               return -3;
+
+       sbc_calculate_bits(frame, bits);
+
+       for (ch = 0; ch < frame->channels; ch++) {
+               for (sb = 0; sb < frame->subbands; sb++)
+                       levels[ch][sb] = (1 << bits[ch][sb]) - 1;
+       }
+
+       for (blk = 0; blk < frame->blocks; blk++) {
+               for (ch = 0; ch < frame->channels; ch++) {
+                       for (sb = 0; sb < frame->subbands; sb++) {
+                               if (levels[ch][sb] > 0) {
+                                       audio_sample = 0;
+                                       for (bit = 0; bit < bits[ch][sb]; bit++) {
+                                               if (consumed > len * 8)
+                                                       return -1;
+
+                                               if ((data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01)
+                                                       audio_sample |= 1 << (bits[ch][sb] - bit - 1);
+
+                                               consumed++;
+                                       }
+
+                                       frame->sb_sample[blk][ch][sb] =
+                                               (((audio_sample << 1) | 1) << frame->scale_factor[ch][sb]) /
+                                               levels[ch][sb] - (1 << frame->scale_factor[ch][sb]);
+                               } else
+                                       frame->sb_sample[blk][ch][sb] = 0;
+                       }
+               }
+       }
+
+       if (frame->mode == JOINT_STEREO) {
+               for (blk = 0; blk < frame->blocks; blk++) {
+                       for (sb = 0; sb < frame->subbands; sb++) {
+                               if (frame->joint & (0x01 << sb)) {
+                                       temp = frame->sb_sample[blk][0][sb] +
+                                               frame->sb_sample[blk][1][sb];
+                                       frame->sb_sample[blk][1][sb] =
+                                               frame->sb_sample[blk][0][sb] -
+                                               frame->sb_sample[blk][1][sb];
+                                       frame->sb_sample[blk][0][sb] = temp;
+                               }
+                       }
+               }
+       }
+
+       if ((consumed & 0x7) != 0)
+               consumed += 8 - (consumed & 0x7);
+
+       return consumed >> 3;
+}
+
+static void sbc_decoder_init(struct sbc_decoder_state *state,
+                               const struct sbc_frame *frame)
+{
+       int i, ch;
+
+       memset(state->V, 0, sizeof(state->V));
+       state->subbands = frame->subbands;
+
+       for (ch = 0; ch < 2; ch++)
+               for (i = 0; i < frame->subbands * 2; i++)
+                       state->offset[ch][i] = (10 * i + 10);
+}
+
+static inline void sbc_synthesize_four(struct sbc_decoder_state *state,
+                               struct sbc_frame *frame, int ch, int blk)
+{
+       int i, k, idx;
+       int32_t *v = state->V[ch];
+       int *offset = state->offset[ch];
+
+       for (i = 0; i < 8; i++) {
+               /* Shifting */
+               offset[i]--;
+               if (offset[i] < 0) {
+                       offset[i] = 79;
+                       memcpy(v + 80, v, 9 * sizeof(*v));
+               }
+
+               /* Distribute the new matrix value to the shifted position */
+               v[offset[i]] = SCALE4_STAGED1(
+                       MULA(synmatrix4[i][0], frame->sb_sample[blk][ch][0],
+                       MULA(synmatrix4[i][1], frame->sb_sample[blk][ch][1],
+                       MULA(synmatrix4[i][2], frame->sb_sample[blk][ch][2],
+                       MUL (synmatrix4[i][3], frame->sb_sample[blk][ch][3])))));
+       }
+
+       /* Compute the samples */
+       for (idx = 0, i = 0; i < 4; i++, idx += 5) {
+               k = (i + 4) & 0xf;
+
+               /* Store in output, Q0 */
+               frame->pcm_sample[ch][blk * 4 + i] = SCALE4_STAGED2(
+                       MULA(v[offset[i] + 0], sbc_proto_4_40m0[idx + 0],
+                       MULA(v[offset[k] + 1], sbc_proto_4_40m1[idx + 0],
+                       MULA(v[offset[i] + 2], sbc_proto_4_40m0[idx + 1],
+                       MULA(v[offset[k] + 3], sbc_proto_4_40m1[idx + 1],
+                       MULA(v[offset[i] + 4], sbc_proto_4_40m0[idx + 2],
+                       MULA(v[offset[k] + 5], sbc_proto_4_40m1[idx + 2],
+                       MULA(v[offset[i] + 6], sbc_proto_4_40m0[idx + 3],
+                       MULA(v[offset[k] + 7], sbc_proto_4_40m1[idx + 3],
+                       MULA(v[offset[i] + 8], sbc_proto_4_40m0[idx + 4],
+                       MUL( v[offset[k] + 9], sbc_proto_4_40m1[idx + 4])))))))))));
+       }
+}
+
+static inline void sbc_synthesize_eight(struct sbc_decoder_state *state,
+                               struct sbc_frame *frame, int ch, int blk)
+{
+       int i, j, k, idx;
+       int *offset = state->offset[ch];
+
+       for (i = 0; i < 16; i++) {
+               /* Shifting */
+               offset[i]--;
+               if (offset[i] < 0) {
+                       offset[i] = 159;
+                       for (j = 0; j < 9; j++)
+                               state->V[ch][j + 160] = state->V[ch][j];
+               }
+
+               /* Distribute the new matrix value to the shifted position */
+               state->V[ch][offset[i]] = SCALE8_STAGED1(
+                       MULA(synmatrix8[i][0], frame->sb_sample[blk][ch][0],
+                       MULA(synmatrix8[i][1], frame->sb_sample[blk][ch][1],
+                       MULA(synmatrix8[i][2], frame->sb_sample[blk][ch][2],
+                       MULA(synmatrix8[i][3], frame->sb_sample[blk][ch][3],
+                       MULA(synmatrix8[i][4], frame->sb_sample[blk][ch][4],
+                       MULA(synmatrix8[i][5], frame->sb_sample[blk][ch][5],
+                       MULA(synmatrix8[i][6], frame->sb_sample[blk][ch][6],
+                       MUL( synmatrix8[i][7], frame->sb_sample[blk][ch][7])))))))));
+       }
+
+       /* Compute the samples */
+       for (idx = 0, i = 0; i < 8; i++, idx += 5) {
+               k = (i + 8) & 0xf;
+
+               /* Store in output */
+               frame->pcm_sample[ch][blk * 8 + i] = SCALE8_STAGED2( // Q0
+                       MULA(state->V[ch][offset[i] + 0], sbc_proto_8_80m0[idx + 0],
+                       MULA(state->V[ch][offset[k] + 1], sbc_proto_8_80m1[idx + 0],
+                       MULA(state->V[ch][offset[i] + 2], sbc_proto_8_80m0[idx + 1],
+                       MULA(state->V[ch][offset[k] + 3], sbc_proto_8_80m1[idx + 1],
+                       MULA(state->V[ch][offset[i] + 4], sbc_proto_8_80m0[idx + 2],
+                       MULA(state->V[ch][offset[k] + 5], sbc_proto_8_80m1[idx + 2],
+                       MULA(state->V[ch][offset[i] + 6], sbc_proto_8_80m0[idx + 3],
+                       MULA(state->V[ch][offset[k] + 7], sbc_proto_8_80m1[idx + 3],
+                       MULA(state->V[ch][offset[i] + 8], sbc_proto_8_80m0[idx + 4],
+                       MUL( state->V[ch][offset[k] + 9], sbc_proto_8_80m1[idx + 4])))))))))));
+       }
+}
+
+static int sbc_synthesize_audio(struct sbc_decoder_state *state,
+                               struct sbc_frame *frame)
+{
+       int ch, blk;
+
+       switch (frame->subbands) {
+       case 4:
+               for (ch = 0; ch < frame->channels; ch++) {
+                       for (blk = 0; blk < frame->blocks; blk++)
+                               sbc_synthesize_four(state, frame, ch, blk);
+               }
+               return frame->blocks * 4;
+
+       case 8:
+               for (ch = 0; ch < frame->channels; ch++) {
+                       for (blk = 0; blk < frame->blocks; blk++)
+                               sbc_synthesize_eight(state, frame, ch, blk);
+               }
+               return frame->blocks * 8;
+
+       default:
+               return -EIO;
+       }
+}
+
+static void sbc_encoder_init(struct sbc_encoder_state *state,
+                               const struct sbc_frame *frame)
+{
+       memset(&state->X, 0, sizeof(state->X));
+       state->subbands = frame->subbands;
+       state->position[0] = state->position[1] = 9 * frame->subbands;
+}
+
+static inline void _sbc_analyze_four(const int32_t *in, int32_t *out)
+{
+       sbc_fixed_t t[8], s[5];
+
+       t[0] = SCALE4_STAGE1( /* Q8 */
+               MULA(_sbc_proto_4[0], in[8] - in[32], /* Q18 */
+               MUL( _sbc_proto_4[1], in[16] - in[24])));
+
+       t[1] = SCALE4_STAGE1(
+               MULA(_sbc_proto_4[2], in[1],
+               MULA(_sbc_proto_4[3], in[9],
+               MULA(_sbc_proto_4[4], in[17],
+               MULA(_sbc_proto_4[5], in[25],
+               MUL( _sbc_proto_4[6], in[33]))))));
+
+       t[2] = SCALE4_STAGE1(
+               MULA(_sbc_proto_4[7], in[2],
+               MULA(_sbc_proto_4[8], in[10],
+               MULA(_sbc_proto_4[9], in[18],
+               MULA(_sbc_proto_4[10], in[26],
+               MUL( _sbc_proto_4[11], in[34]))))));
+
+       t[3] = SCALE4_STAGE1(
+               MULA(_sbc_proto_4[12], in[3],
+               MULA(_sbc_proto_4[13], in[11],
+               MULA(_sbc_proto_4[14], in[19],
+               MULA(_sbc_proto_4[15], in[27],
+               MUL( _sbc_proto_4[16], in[35]))))));
+
+       t[4] = SCALE4_STAGE1(
+               MULA(_sbc_proto_4[17], in[4] + in[36],
+               MULA(_sbc_proto_4[18], in[12] + in[28],
+               MUL( _sbc_proto_4[19], in[20]))));
+
+       t[5] = SCALE4_STAGE1(
+               MULA(_sbc_proto_4[16], in[5],
+               MULA(_sbc_proto_4[15], in[13],
+               MULA(_sbc_proto_4[14], in[21],
+               MULA(_sbc_proto_4[13], in[29],
+               MUL( _sbc_proto_4[12], in[37]))))));
+
+       /* don't compute t[6]... this term always multiplies
+        * with cos(pi/2) = 0 */
+
+       t[7] = SCALE4_STAGE1(
+               MULA(_sbc_proto_4[6], in[7],
+               MULA(_sbc_proto_4[5], in[15],
+               MULA(_sbc_proto_4[4], in[23],
+               MULA(_sbc_proto_4[3], in[31],
+               MUL( _sbc_proto_4[2], in[39]))))));
+
+       s[0] = MUL( _anamatrix4[0], t[0] + t[4]);
+       s[1] = MUL( _anamatrix4[2], t[2]);
+       s[2] = MULA(_anamatrix4[1], t[1] + t[3],
+               MUL(_anamatrix4[3], t[5]));
+       s[3] = MULA(_anamatrix4[3], t[1] + t[3],
+               MUL(_anamatrix4[1], -t[5] + t[7]));
+       s[4] = MUL( _anamatrix4[3], t[7]);
+
+       out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2] + s[4]); /* Q0 */
+       out[1] = SCALE4_STAGE2(-s[0] + s[1] + s[3]);
+       out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]);
+       out[3] = SCALE4_STAGE2( s[0] + s[1] - s[2] - s[4]);
+}
+
+static inline void sbc_analyze_four(struct sbc_encoder_state *state,
+                               struct sbc_frame *frame, int ch, int blk)
+{
+       int32_t *x = &state->X[ch][state->position[ch]];
+       int16_t *pcm = &frame->pcm_sample[ch][blk * 4];
+
+       /* Input 4 Audio Samples */
+       x[40] = x[0] = pcm[3];
+       x[41] = x[1] = pcm[2];
+       x[42] = x[2] = pcm[1];
+       x[43] = x[3] = pcm[0];
+
+       _sbc_analyze_four(x, frame->sb_sample_f[blk][ch]);
+
+       state->position[ch] -= 4;
+       if (state->position[ch] < 0)
+               state->position[ch] = 36;
+}
+
+static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out)
+{
+       sbc_fixed_t t[8], s[8];
+
+       t[0] = SCALE8_STAGE1( /* Q10 */
+               MULA(_sbc_proto_8[0], (in[16] - in[64]), /* Q18 = Q18 * Q0 */
+               MULA(_sbc_proto_8[1], (in[32] - in[48]),
+               MULA(_sbc_proto_8[2], in[4],
+               MULA(_sbc_proto_8[3], in[20],
+               MULA(_sbc_proto_8[4], in[36],
+               MUL( _sbc_proto_8[5], in[52])))))));
+
+       t[1] = SCALE8_STAGE1(
+               MULA(_sbc_proto_8[6], in[2],
+               MULA(_sbc_proto_8[7], in[18],
+               MULA(_sbc_proto_8[8], in[34],
+               MULA(_sbc_proto_8[9], in[50],
+               MUL(_sbc_proto_8[10], in[66]))))));
+
+       t[2] = SCALE8_STAGE1(
+               MULA(_sbc_proto_8[11], in[1],
+               MULA(_sbc_proto_8[12], in[17],
+               MULA(_sbc_proto_8[13], in[33],
+               MULA(_sbc_proto_8[14], in[49],
+               MULA(_sbc_proto_8[15], in[65],
+               MULA(_sbc_proto_8[16], in[3],
+               MULA(_sbc_proto_8[17], in[19],
+               MULA(_sbc_proto_8[18], in[35],
+               MULA(_sbc_proto_8[19], in[51],
+               MUL( _sbc_proto_8[20], in[67])))))))))));
+
+       t[3] = SCALE8_STAGE1(
+               MULA( _sbc_proto_8[21], in[5],
+               MULA( _sbc_proto_8[22], in[21],
+               MULA( _sbc_proto_8[23], in[37],
+               MULA( _sbc_proto_8[24], in[53],
+               MULA( _sbc_proto_8[25], in[69],
+               MULA(-_sbc_proto_8[15], in[15],
+               MULA(-_sbc_proto_8[14], in[31],
+               MULA(-_sbc_proto_8[13], in[47],
+               MULA(-_sbc_proto_8[12], in[63],
+               MUL( -_sbc_proto_8[11], in[79])))))))))));
+
+       t[4] = SCALE8_STAGE1(
+               MULA( _sbc_proto_8[26], in[6],
+               MULA( _sbc_proto_8[27], in[22],
+               MULA( _sbc_proto_8[28], in[38],
+               MULA( _sbc_proto_8[29], in[54],
+               MULA( _sbc_proto_8[30], in[70],
+               MULA(-_sbc_proto_8[10], in[14],
+               MULA(-_sbc_proto_8[9], in[30],
+               MULA(-_sbc_proto_8[8], in[46],
+               MULA(-_sbc_proto_8[7], in[62],
+               MUL( -_sbc_proto_8[6], in[78])))))))))));
+
+       t[5] = SCALE8_STAGE1(
+               MULA( _sbc_proto_8[31], in[7],
+               MULA( _sbc_proto_8[32], in[23],
+               MULA( _sbc_proto_8[33], in[39],
+               MULA( _sbc_proto_8[34], in[55],
+               MULA( _sbc_proto_8[35], in[71],
+               MULA(-_sbc_proto_8[20], in[13],
+               MULA(-_sbc_proto_8[19], in[29],
+               MULA(-_sbc_proto_8[18], in[45],
+               MULA(-_sbc_proto_8[17], in[61],
+               MUL( -_sbc_proto_8[16], in[77])))))))))));
+
+       t[6] = SCALE8_STAGE1(
+               MULA( _sbc_proto_8[36], (in[8] + in[72]),
+               MULA( _sbc_proto_8[37], (in[24] + in[56]),
+               MULA( _sbc_proto_8[38], in[40],
+               MULA(-_sbc_proto_8[39], in[12],
+               MULA(-_sbc_proto_8[5], in[28],
+               MULA(-_sbc_proto_8[4], in[44],
+               MULA(-_sbc_proto_8[3], in[60],
+               MUL( -_sbc_proto_8[2], in[76])))))))));
+
+       t[7] = SCALE8_STAGE1(
+               MULA( _sbc_proto_8[35], in[9],
+               MULA( _sbc_proto_8[34], in[25],
+               MULA( _sbc_proto_8[33], in[41],
+               MULA( _sbc_proto_8[32], in[57],
+               MULA( _sbc_proto_8[31], in[73],
+               MULA(-_sbc_proto_8[25], in[11],
+               MULA(-_sbc_proto_8[24], in[27],
+               MULA(-_sbc_proto_8[23], in[43],
+               MULA(-_sbc_proto_8[22], in[59],
+               MUL( -_sbc_proto_8[21], in[75])))))))))));
+
+       s[0] = MULA(  _anamatrix8[0], t[0],
+               MUL(  _anamatrix8[1], t[6]));
+       s[1] = MUL(   _anamatrix8[7], t[1]);
+       s[2] = MULA(  _anamatrix8[2], t[2],
+               MULA( _anamatrix8[3], t[3],
+               MULA( _anamatrix8[4], t[5],
+               MUL(  _anamatrix8[5], t[7]))));
+       s[3] = MUL(   _anamatrix8[6], t[4]);
+       s[4] = MULA(  _anamatrix8[3], t[2],
+               MULA(-_anamatrix8[5], t[3],
+               MULA(-_anamatrix8[2], t[5],
+               MUL( -_anamatrix8[4], t[7]))));
+       s[5] = MULA(  _anamatrix8[4], t[2],
+               MULA(-_anamatrix8[2], t[3],
+               MULA( _anamatrix8[5], t[5],
+               MUL(  _anamatrix8[3], t[7]))));
+       s[6] = MULA(  _anamatrix8[1], t[0],
+               MUL( -_anamatrix8[0], t[6]));
+       s[7] = MULA(  _anamatrix8[5], t[2],
+               MULA(-_anamatrix8[4], t[3],
+               MULA( _anamatrix8[3], t[5],
+               MUL( -_anamatrix8[2], t[7]))));
+
+       out[0] = SCALE8_STAGE2( s[0] + s[1] + s[2] + s[3]);
+       out[1] = SCALE8_STAGE2( s[1] - s[3] + s[4] + s[6]);
+       out[2] = SCALE8_STAGE2( s[1] - s[3] + s[5] - s[6]);
+       out[3] = SCALE8_STAGE2(-s[0] + s[1] + s[3] + s[7]);
+       out[4] = SCALE8_STAGE2(-s[0] + s[1] + s[3] - s[7]);
+       out[5] = SCALE8_STAGE2( s[1] - s[3] - s[5] - s[6]);
+       out[6] = SCALE8_STAGE2( s[1] - s[3] - s[4] + s[6]);
+       out[7] = SCALE8_STAGE2( s[0] + s[1] - s[2] + s[3]);
+}
+
+static inline void sbc_analyze_eight(struct sbc_encoder_state *state,
+                                       struct sbc_frame *frame, int ch,
+                                       int blk)
+{
+       int32_t *x = &state->X[ch][state->position[ch]];
+       int16_t *pcm = &frame->pcm_sample[ch][blk * 8];
+
+       /* Input 8 Audio Samples */
+       x[80] = x[0] = pcm[7];
+       x[81] = x[1] = pcm[6];
+       x[82] = x[2] = pcm[5];
+       x[83] = x[3] = pcm[4];
+       x[84] = x[4] = pcm[3];
+       x[85] = x[5] = pcm[2];
+       x[86] = x[6] = pcm[1];
+       x[87] = x[7] = pcm[0];
+
+       _sbc_analyze_eight(x, frame->sb_sample_f[blk][ch]);
+
+       state->position[ch] -= 8;
+       if (state->position[ch] < 0)
+               state->position[ch] = 72;
+}
+
+static int sbc_analyze_audio(struct sbc_encoder_state *state,
+                               struct sbc_frame *frame)
+{
+       int ch, blk;
+
+       switch (frame->subbands) {
+       case 4:
+               for (ch = 0; ch < frame->channels; ch++)
+                       for (blk = 0; blk < frame->blocks; blk++)
+                               sbc_analyze_four(state, frame, ch, blk);
+               return frame->blocks * 4;
+
+       case 8:
+               for (ch = 0; ch < frame->channels; ch++)
+                       for (blk = 0; blk < frame->blocks; blk++)
+                               sbc_analyze_eight(state, frame, ch, blk);
+               return frame->blocks * 8;
+
+       default:
+               return -EIO;
+       }
+}
+
+/*
+ * Packs the SBC frame from frame into the memory at data. At most len
+ * bytes will be used, should more memory be needed an appropriate
+ * error code will be returned. Returns the length of the packed frame
+ * on success or a negative value on error.
+ *
+ * The error codes are:
+ * -1 Not enough memory reserved
+ * -2 Unsupported sampling rate
+ * -3 Unsupported number of blocks
+ * -4 Unsupported number of subbands
+ * -5 Bitpool value out of bounds
+ * -99 not implemented
+ */
+
+static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len)
+{
+       int produced;
+       /* Will copy the header parts for CRC-8 calculation here */
+       uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+       int crc_pos = 0;
+
+       uint16_t audio_sample;
+
+       int ch, sb, blk, bit;   /* channel, subband, block and bit counters */
+       int bits[2][8];         /* bits distribution */
+       int levels[2][8];       /* levels are derived from that */
+
+       u_int32_t scalefactor[2][8];    /* derived from frame->scale_factor */
+
+       data[0] = SBC_SYNCWORD;
+
+       data[1] = (frame->frequency & 0x03) << 6;
+
+       data[1] |= (frame->block_mode & 0x03) << 4;
+
+       data[1] |= (frame->mode & 0x03) << 2;
+
+       data[1] |= (frame->allocation & 0x01) << 1;
+
+       switch (frame->subbands) {
+       case 4:
+               /* Nothing to do */
+               break;
+       case 8:
+               data[1] |= 0x01;
+               break;
+       default:
+               return -4;
+               break;
+       }
+
+       data[2] = frame->bitpool;
+
+       if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+                       frame->bitpool > frame->subbands << 4)
+               return -5;
+
+       if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+                       frame->bitpool > frame->subbands << 5)
+               return -5;
+
+       /* Can't fill in crc yet */
+
+       produced = 32;
+
+       crc_header[0] = data[1];
+       crc_header[1] = data[2];
+       crc_pos = 16;
+
+       for (ch = 0; ch < frame->channels; ch++) {
+               for (sb = 0; sb < frame->subbands; sb++) {
+                       frame->scale_factor[ch][sb] = 0;
+                       scalefactor[ch][sb] = 2;
+                       for (blk = 0; blk < frame->blocks; blk++) {
+                               while (scalefactor[ch][sb] < fabs(frame->sb_sample_f[blk][ch][sb])) {
+                                       frame->scale_factor[ch][sb]++;
+                                       scalefactor[ch][sb] *= 2;
+                               }
+                       }
+               }
+       }
+
+       if (frame->mode == JOINT_STEREO) {
+               /* like frame->sb_sample but joint stereo */
+               int32_t sb_sample_j[16][2];
+               /* scalefactor and scale_factor in joint case */
+               u_int32_t scalefactor_j[2];
+               uint8_t scale_factor_j[2];
+
+               frame->joint = 0;
+
+               for (sb = 0; sb < frame->subbands - 1; sb++) {
+                       scale_factor_j[0] = 0;
+                       scalefactor_j[0] = 2;
+                       scale_factor_j[1] = 0;
+                       scalefactor_j[1] = 2;
+
+                       for (blk = 0; blk < frame->blocks; blk++) {
+                               /* Calculate joint stereo signal */
+                               sb_sample_j[blk][0] =
+                                       (frame->sb_sample_f[blk][0][sb] +
+                                               frame->sb_sample_f[blk][1][sb]) >> 1;
+                               sb_sample_j[blk][1] =
+                                       (frame->sb_sample_f[blk][0][sb] -
+                                               frame->sb_sample_f[blk][1][sb]) >> 1;
+
+                               /* calculate scale_factor_j and scalefactor_j for joint case */
+                               while (scalefactor_j[0] < fabs(sb_sample_j[blk][0])) {
+                                       scale_factor_j[0]++;
+                                       scalefactor_j[0] *= 2;
+                               }
+                               while (scalefactor_j[1] < fabs(sb_sample_j[blk][1])) {
+                                       scale_factor_j[1]++;
+                                       scalefactor_j[1] *= 2;
+                               }
+                       }
+
+                       /* decide whether to join this subband */
+                       if ((scalefactor[0][sb] + scalefactor[1][sb]) >
+                                       (scalefactor_j[0] + scalefactor_j[1]) ) {
+                               /* use joint stereo for this subband */
+                               frame->joint |= 1 << sb;
+                               frame->scale_factor[0][sb] = scale_factor_j[0];
+                               frame->scale_factor[1][sb] = scale_factor_j[1];
+                               scalefactor[0][sb] = scalefactor_j[0];
+                               scalefactor[1][sb] = scalefactor_j[1];
+                               for (blk = 0; blk < frame->blocks; blk++) {
+                                       frame->sb_sample_f[blk][0][sb] =
+                                                       sb_sample_j[blk][0];
+                                       frame->sb_sample_f[blk][1][sb] =
+                                                       sb_sample_j[blk][1];
+                               }
+                       }
+               }
+
+               data[4] = 0;
+               for (sb = 0; sb < frame->subbands - 1; sb++)
+                       data[4] |= ((frame->joint >> sb) & 0x01) << (frame->subbands - 1 - sb);
+
+               crc_header[crc_pos >> 3] = data[4];
+
+               produced += frame->subbands;
+               crc_pos += frame->subbands;
+       }
+
+       for (ch = 0; ch < frame->channels; ch++) {
+               for (sb = 0; sb < frame->subbands; sb++) {
+                       data[produced >> 3] <<= 4;
+                       crc_header[crc_pos >> 3] <<= 4;
+                       data[produced >> 3] |= frame->scale_factor[ch][sb] & 0x0F;
+                       crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] & 0x0F;
+
+                       produced += 4;
+                       crc_pos += 4;
+               }
+       }
+
+       /* align the last crc byte */
+       if (crc_pos % 8)
+               crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8);
+
+       data[3] = sbc_crc8(crc_header, crc_pos);
+
+       sbc_calculate_bits(frame, bits);
+
+       for (ch = 0; ch < frame->channels; ch++) {
+               for (sb = 0; sb < frame->subbands; sb++)
+                       levels[ch][sb] = (1 << bits[ch][sb]) - 1;
+       }
+
+       for (blk = 0; blk < frame->blocks; blk++) {
+               for (ch = 0; ch < frame->channels; ch++) {
+                       for (sb = 0; sb < frame->subbands; sb++) {
+                               if (levels[ch][sb] > 0) {
+                                       audio_sample =
+                                               (uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >>
+                                                                       (frame->scale_factor[ch][sb] + 1)) +
+                                                               levels[ch][sb]) >> 1);
+                                       audio_sample <<= 16 - bits[ch][sb];
+                                       for (bit = 0; bit < bits[ch][sb]; bit++) {
+                                               data[produced >> 3] <<= 1;
+                                               if (audio_sample & 0x8000)
+                                                       data[produced >> 3] |= 0x1;
+                                               audio_sample <<= 1;
+                                               produced++;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /* align the last byte */
+       if (produced % 8) {
+               data[produced >> 3] <<= 8 - (produced % 8);
+       }
+
+       return (produced + 7) >> 3;
+}
+
+struct sbc_priv {
+       int init;
+       struct sbc_frame frame;
+       struct sbc_decoder_state dec_state;
+       struct sbc_encoder_state enc_state;
+};
+
+static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
+{
+       sbc->frequency = SBC_FREQ_44100;
+       sbc->mode = SBC_MODE_STEREO;
+       sbc->subbands = SBC_SB_8;
+       sbc->blocks = SBC_BLK_16;
+       sbc->bitpool = 32;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+       sbc->endian = SBC_LE;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+       sbc->endian = SBC_BE;
+#else
+#error "Unknown byte order"
+#endif
+}
+
+int sbc_init(sbc_t *sbc, unsigned long flags)
+{
+       if (!sbc)
+               return -EIO;
+
+       memset(sbc, 0, sizeof(sbc_t));
+
+       sbc->priv = malloc(sizeof(struct sbc_priv));
+       if (!sbc->priv)
+               return -ENOMEM;
+
+       memset(sbc->priv, 0, sizeof(struct sbc_priv));
+
+       sbc_set_defaults(sbc, flags);
+
+       return 0;
+}
+
+int sbc_parse(sbc_t *sbc, void *input, int input_len)
+{
+       return sbc_decode(sbc, input, input_len, NULL, 0, NULL);
+}
+
+int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,
+               int output_len, int *written)
+{
+       struct sbc_priv *priv;
+       char *ptr;
+       int i, ch, framelen, samples;
+
+       if (!sbc && !input)
+               return -EIO;
+
+       priv = sbc->priv;
+
+       framelen = sbc_unpack_frame(input, &priv->frame, input_len);
+
+       if (!priv->init) {
+               sbc_decoder_init(&priv->dec_state, &priv->frame);
+               priv->init = 1;
+
+               sbc->frequency = priv->frame.frequency;
+               sbc->mode = priv->frame.mode;
+               sbc->subbands = priv->frame.subband_mode;
+               sbc->blocks = priv->frame.block_mode;
+               sbc->allocation = priv->frame.allocation;
+               sbc->bitpool = priv->frame.bitpool;
+
+               priv->frame.codesize = sbc_get_codesize(sbc);
+               priv->frame.length = sbc_get_frame_length(sbc);
+       }
+
+       if (!output)
+               return framelen;
+
+       if (written)
+               *written = 0;
+
+       samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame);
+
+       ptr = output;
+
+       if (output_len < samples * priv->frame.channels * 2)
+               samples = output_len / (priv->frame.channels * 2);
+
+       for (i = 0; i < samples; i++) {
+               for (ch = 0; ch < priv->frame.channels; ch++) {
+                       int16_t s;
+                       s = priv->frame.pcm_sample[ch][i];
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+                       if (sbc->endian == SBC_BE) {
+#elif __BYTE_ORDER == __BIG_ENDIAN
+                       if (sbc->endian == SBC_LE) {
+#else
+#error "Unknown byte order"
+#endif
+                               *ptr++ = (s & 0xff00) >> 8;
+                               *ptr++ = (s & 0x00ff);
+                       } else {
+                               *ptr++ = (s & 0x00ff);
+                               *ptr++ = (s & 0xff00) >> 8;
+                       }
+               }
+       }
+
+       if (written)
+               *written = samples * priv->frame.channels * 2;
+
+       return framelen;
+}
+
+int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output,
+               int output_len, int *written)
+{
+       struct sbc_priv *priv;
+       char *ptr;
+       int i, ch, framelen, samples;
+
+       if (!sbc && !input)
+               return -EIO;
+
+       priv = sbc->priv;
+
+       if (written)
+               *written = 0;
+
+       if (!priv->init) {
+               priv->frame.frequency = sbc->frequency;
+               priv->frame.mode = sbc->mode;
+               priv->frame.channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+               priv->frame.allocation = sbc->allocation;
+               priv->frame.subband_mode = sbc->subbands;
+               priv->frame.subbands = sbc->subbands ? 8 : 4;
+               priv->frame.block_mode = sbc->blocks;
+               priv->frame.blocks = 4 + (sbc->blocks * 4);
+               priv->frame.bitpool = sbc->bitpool;
+               priv->frame.codesize = sbc_get_codesize(sbc);
+               priv->frame.length = sbc_get_frame_length(sbc);
+
+               sbc_encoder_init(&priv->enc_state, &priv->frame);
+               priv->init = 1;
+       }
+
+       /* input must be large enough to encode a complete frame */
+       if (input_len < priv->frame.codesize)
+               return 0;
+
+       /* output must be large enough to receive the encoded frame */
+       if (!output || output_len < priv->frame.length)
+               return -ENOSPC;
+
+       ptr = input;
+
+       for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) {
+               for (ch = 0; ch < priv->frame.channels; ch++) {
+                       int16_t s;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+                       if (sbc->endian == SBC_BE)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+                       if (sbc->endian == SBC_LE)
+#else
+#error "Unknown byte order"
+#endif
+                               s = (ptr[0] & 0xff) << 8 | (ptr[1] & 0xff);
+                       else
+                               s = (ptr[0] & 0xff) | (ptr[1] & 0xff) << 8;
+                       ptr += 2;
+                       priv->frame.pcm_sample[ch][i] = s;
+               }
+       }
+
+       samples = sbc_analyze_audio(&priv->enc_state, &priv->frame);
+
+       framelen = sbc_pack_frame(output, &priv->frame, output_len);
+
+       if (written)
+               *written = framelen;
+
+       return samples * priv->frame.channels * 2;
+}
+
+void sbc_finish(sbc_t *sbc)
+{
+       if (!sbc)
+               return;
+
+       if (sbc->priv)
+               free(sbc->priv);
+
+       memset(sbc, 0, sizeof(sbc_t));
+}
+
+int sbc_get_frame_length(sbc_t *sbc)
+{
+       int ret;
+       uint8_t subbands, channels, blocks, joint;
+       struct sbc_priv *priv;
+
+       priv = sbc->priv;
+       if (!priv->init) {
+               subbands = sbc->subbands ? 8 : 4;
+               blocks = 4 + (sbc->blocks * 4);
+               channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+               joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0;
+       } else {
+               subbands = priv->frame.subbands;
+               blocks = priv->frame.blocks;
+               channels = priv->frame.channels;
+               joint = priv->frame.joint;
+       }
+
+       ret = 4 + (4 * subbands * channels) / 8;
+
+       /* This term is not always evenly divide so we round it up */
+       if (channels == 1)
+               ret += ((blocks * channels * sbc->bitpool) + 7) / 8;
+       else
+               ret += (((joint ? subbands : 0) + blocks * sbc->bitpool) + 7)
+                       / 8;
+
+       return ret;
+}
+
+int sbc_get_frame_duration(sbc_t *sbc)
+{
+       uint8_t subbands, blocks;
+       uint16_t frequency;
+       struct sbc_priv *priv;
+
+       priv = sbc->priv;
+       if (!priv->init) {
+               subbands = sbc->subbands ? 8 : 4;
+               blocks = 4 + (sbc->blocks * 4);
+       } else {
+               subbands = priv->frame.subbands;
+               blocks = priv->frame.blocks;
+       }
+
+       switch (sbc->frequency) {
+       case SBC_FREQ_16000:
+               frequency = 16000;
+               break;
+
+       case SBC_FREQ_32000:
+               frequency = 32000;
+               break;
+
+       case SBC_FREQ_44100:
+               frequency = 44100;
+               break;
+
+       case SBC_FREQ_48000:
+               frequency = 48000;
+               break;
+       default:
+               return 0;
+       }
+
+       return (1000000 * blocks * subbands) / frequency;
+}
+
+int sbc_get_codesize(sbc_t *sbc)
+{
+       uint8_t subbands, channels, blocks;
+       struct sbc_priv *priv;
+
+       priv = sbc->priv;
+       if (!priv->init) {
+               subbands = sbc->subbands ? 8 : 4;
+               blocks = 4 + (sbc->blocks * 4);
+               channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+       } else {
+               subbands = priv->frame.subbands;
+               blocks = priv->frame.blocks;
+               channels = priv->frame.channels;
+       }
+
+       return subbands * blocks * channels * 2;
+}
+
+int sbc_reinit(sbc_t *sbc, unsigned long flags)
+{
+       struct sbc_priv *priv;
+
+       if (!sbc || !sbc->priv)
+               return -EIO;
+
+       priv = sbc->priv;
+
+       if (priv->init == 1)
+               memset(sbc->priv, 0, sizeof(struct sbc_priv));
+
+       sbc_set_defaults(sbc, flags);
+
+       return 0;
+}
diff --git a/src/modules/bluetooth/sbc.h b/src/modules/bluetooth/sbc.h
new file mode 100644 (file)
index 0000000..ab47e32
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library 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.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __SBC_H
+#define __SBC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/* sampling frequency */
+#define SBC_FREQ_16000         0x00
+#define SBC_FREQ_32000         0x01
+#define SBC_FREQ_44100         0x02
+#define SBC_FREQ_48000         0x03
+
+/* blocks */
+#define SBC_BLK_4              0x00
+#define SBC_BLK_8              0x01
+#define SBC_BLK_12             0x02
+#define SBC_BLK_16             0x03
+
+/* channel mode */
+#define SBC_MODE_MONO          0x00
+#define SBC_MODE_DUAL_CHANNEL  0x01
+#define SBC_MODE_STEREO                0x02
+#define SBC_MODE_JOINT_STEREO  0x03
+
+/* allocation method */
+#define SBC_AM_LOUDNESS                0x00
+#define SBC_AM_SNR             0x01
+
+/* subbands */
+#define SBC_SB_4               0x00
+#define SBC_SB_8               0x01
+
+/* Data endianess */
+#define SBC_LE                 0x00
+#define SBC_BE                 0x01
+
+struct sbc_struct {
+       unsigned long flags;
+
+       uint8_t frequency;
+       uint8_t blocks;
+       uint8_t subbands;
+       uint8_t mode;
+       uint8_t allocation;
+       uint8_t bitpool;
+       uint8_t endian;
+
+       void *priv;
+};
+
+typedef struct sbc_struct sbc_t;
+
+int sbc_init(sbc_t *sbc, unsigned long flags);
+int sbc_reinit(sbc_t *sbc, unsigned long flags);
+int sbc_parse(sbc_t *sbc, void *input, int input_len);
+int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,
+               int output_len, int *len);
+int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output,
+               int output_len, int *written);
+int sbc_get_frame_length(sbc_t *sbc);
+int sbc_get_frame_duration(sbc_t *sbc);
+int sbc_get_codesize(sbc_t *sbc);
+void sbc_finish(sbc_t *sbc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SBC_H */
diff --git a/src/modules/bluetooth/sbc_math.h b/src/modules/bluetooth/sbc_math.h
new file mode 100644 (file)
index 0000000..b3d87a6
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2008  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library 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.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define fabs(x) ((x) < 0 ? -(x) : (x))
+/* C does not provide an explicit arithmetic shift right but this will
+   always be correct and every compiler *should* generate optimal code */
+#define ASR(val, bits) ((-2 >> 1 == -1) ? \
+                ((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits)))
+
+#define SCALE_PROTO4_TBL       15
+#define SCALE_ANA4_TBL         17
+#define SCALE_PROTO8_TBL       16
+#define SCALE_ANA8_TBL         17
+#define SCALE_SPROTO4_TBL      12
+#define SCALE_SPROTO8_TBL      14
+#define SCALE_NPROTO4_TBL      11
+#define SCALE_NPROTO8_TBL      11
+#define SCALE4_STAGE1_BITS     15
+#define SCALE4_STAGE2_BITS     16
+#define SCALE4_STAGED1_BITS    15
+#define SCALE4_STAGED2_BITS    16
+#define SCALE8_STAGE1_BITS     15
+#define SCALE8_STAGE2_BITS     15
+#define SCALE8_STAGED1_BITS    15
+#define SCALE8_STAGED2_BITS    16
+
+typedef int32_t sbc_fixed_t;
+
+#define SCALE4_STAGE1(src)  ASR(src, SCALE4_STAGE1_BITS)
+#define SCALE4_STAGE2(src)  ASR(src, SCALE4_STAGE2_BITS)
+#define SCALE4_STAGED1(src) ASR(src, SCALE4_STAGED1_BITS)
+#define SCALE4_STAGED2(src) ASR(src, SCALE4_STAGED2_BITS)
+#define SCALE8_STAGE1(src)  ASR(src, SCALE8_STAGE1_BITS)
+#define SCALE8_STAGE2(src)  ASR(src, SCALE8_STAGE2_BITS)
+#define SCALE8_STAGED1(src) ASR(src, SCALE8_STAGED1_BITS)
+#define SCALE8_STAGED2(src) ASR(src, SCALE8_STAGED2_BITS)
+
+#define SBC_FIXED_0(val) { val = 0; }
+#define MUL(a, b)        ((a) * (b))
+#ifdef __arm__
+#define MULA(a, b, res) ({                             \
+               int tmp = res;                  \
+               __asm__(                                \
+                       "mla %0, %2, %3, %0"            \
+                       : "=&r" (tmp)                   \
+                       : "0" (tmp), "r" (a), "r" (b)); \
+               tmp; })
+#else
+#define MULA(a, b, res)  ((a) * (b) + (res))
+#endif
diff --git a/src/modules/bluetooth/sbc_tables.h b/src/modules/bluetooth/sbc_tables.h
new file mode 100644 (file)
index 0000000..7ac4e68
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk@ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley@xmission.com>
+ *
+ *
+ *  This library 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.
+ *
+ *  This library 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/* A2DP specification: Appendix B, page 69 */
+static const int sbc_offset4[4][4] = {
+       { -1, 0, 0, 0 },
+       { -2, 0, 0, 1 },
+       { -2, 0, 0, 1 },
+       { -2, 0, 0, 1 }
+};
+
+/* A2DP specification: Appendix B, page 69 */
+static const int sbc_offset8[4][8] = {
+       { -2, 0, 0, 0, 0, 0, 0, 1 },
+       { -3, 0, 0, 0, 0, 0, 1, 2 },
+       { -4, 0, 0, 0, 0, 0, 1, 2 },
+       { -4, 0, 0, 0, 0, 0, 1, 2 }
+};
+
+#define SP4(val) ASR(val, SCALE_PROTO4_TBL)
+#define SA4(val) ASR(val, SCALE_ANA4_TBL)
+#define SP8(val) ASR(val, SCALE_PROTO8_TBL)
+#define SA8(val) ASR(val, SCALE_ANA8_TBL)
+#define SS4(val) ASR(val, SCALE_SPROTO4_TBL)
+#define SS8(val) ASR(val, SCALE_SPROTO8_TBL)
+#define SN4(val) ASR(val, SCALE_NPROTO4_TBL)
+#define SN8(val) ASR(val, SCALE_NPROTO8_TBL)
+
+static const int32_t _sbc_proto_4[20] = {
+       SP4(0x02cb3e8c), SP4(0x22b63dc0), SP4(0x002329cc), SP4(0x053b7548),
+       SP4(0x31eab940), SP4(0xec1f5e60), SP4(0xff3773a8), SP4(0x0061c5a7),
+       SP4(0x07646680), SP4(0x3f239480), SP4(0xf89f23a8), SP4(0x007a4737),
+       SP4(0x00b32807), SP4(0x083ddc80), SP4(0x4825e480), SP4(0x0191e578),
+       SP4(0x00ff11ca), SP4(0x00fb7991), SP4(0x069fdc58), SP4(0x4b584000)
+};
+
+static const int32_t _anamatrix4[4] = {
+       SA4(0x2d413cc0), SA4(0x3b20d780), SA4(0x40000000), SA4(0x187de2a0)
+};
+
+static const int32_t _sbc_proto_8[40] = {
+       SP8(0x02e5cd20), SP8(0x22d0c200), SP8(0x006bfe27), SP8(0x07808930),
+       SP8(0x3f1c8800), SP8(0xf8810d70), SP8(0x002cfdc6), SP8(0x055acf28),
+       SP8(0x31f566c0), SP8(0xebfe57e0), SP8(0xff27c437), SP8(0x001485cc),
+       SP8(0x041c6e58), SP8(0x2a7cfa80), SP8(0xe4c4a240), SP8(0xfe359e4c),
+       SP8(0x0048b1f8), SP8(0x0686ce30), SP8(0x38eec5c0), SP8(0xf2a1b9f0),
+       SP8(0xffe8904a), SP8(0x0095698a), SP8(0x0824a480), SP8(0x443b3c00),
+       SP8(0xfd7badc8), SP8(0x00d3e2d9), SP8(0x00c183d2), SP8(0x084e1950),
+       SP8(0x4810d800), SP8(0x017f43fe), SP8(0x01056dd8), SP8(0x00e9cb9f),
+       SP8(0x07d7d090), SP8(0x4a708980), SP8(0x0488fae8), SP8(0x0113bd20),
+       SP8(0x0107b1a8), SP8(0x069fb3c0), SP8(0x4b3db200), SP8(0x00763f48)
+};
+
+static const int32_t sbc_proto_4_40m0[] = {
+       SS4(0x00000000), SS4(0xffa6982f), SS4(0xfba93848), SS4(0x0456c7b8),
+       SS4(0x005967d1), SS4(0xfffb9ac7), SS4(0xff589157), SS4(0xf9c2a8d8),
+       SS4(0x027c1434), SS4(0x0019118b), SS4(0xfff3c74c), SS4(0xff137330),
+       SS4(0xf81b8d70), SS4(0x00ec1b8b), SS4(0xfff0b71a), SS4(0xffe99b00),
+       SS4(0xfef84470), SS4(0xf6fb4370), SS4(0xffcdc351), SS4(0xffe01dc7)
+};
+
+static const int32_t sbc_proto_4_40m1[] = {
+       SS4(0xffe090ce), SS4(0xff2c0475), SS4(0xf694f800), SS4(0xff2c0475),
+       SS4(0xffe090ce), SS4(0xffe01dc7), SS4(0xffcdc351), SS4(0xf6fb4370),
+       SS4(0xfef84470), SS4(0xffe99b00), SS4(0xfff0b71a), SS4(0x00ec1b8b),
+       SS4(0xf81b8d70), SS4(0xff137330), SS4(0xfff3c74c), SS4(0x0019118b),
+       SS4(0x027c1434), SS4(0xf9c2a8d8), SS4(0xff589157), SS4(0xfffb9ac7)
+};
+
+static const int32_t sbc_proto_8_80m0[] = {
+       SS8(0x00000000), SS8(0xfe8d1970), SS8(0xee979f00), SS8(0x11686100),
+       SS8(0x0172e690), SS8(0xfff5bd1a), SS8(0xfdf1c8d4), SS8(0xeac182c0),
+       SS8(0x0d9daee0), SS8(0x00e530da), SS8(0xffe9811d), SS8(0xfd52986c),
+       SS8(0xe7054ca0), SS8(0x0a00d410), SS8(0x006c1de4), SS8(0xffdba705),
+       SS8(0xfcbc98e8), SS8(0xe3889d20), SS8(0x06af2308), SS8(0x000bb7db),
+       SS8(0xffca00ed), SS8(0xfc3fbb68), SS8(0xe071bc00), SS8(0x03bf7948),
+       SS8(0xffc4e05c), SS8(0xffb54b3b), SS8(0xfbedadc0), SS8(0xdde26200),
+       SS8(0x0142291c), SS8(0xff960e94), SS8(0xff9f3e17), SS8(0xfbd8f358),
+       SS8(0xdbf79400), SS8(0xff405e01), SS8(0xff7d4914), SS8(0xff8b1a31),
+       SS8(0xfc1417b8), SS8(0xdac7bb40), SS8(0xfdbb828c), SS8(0xff762170)
+};
+
+static const int32_t sbc_proto_8_80m1[] = {
+       SS8(0xff7c272c), SS8(0xfcb02620), SS8(0xda612700), SS8(0xfcb02620),
+       SS8(0xff7c272c), SS8(0xff762170), SS8(0xfdbb828c), SS8(0xdac7bb40),
+       SS8(0xfc1417b8), SS8(0xff8b1a31), SS8(0xff7d4914), SS8(0xff405e01),
+       SS8(0xdbf79400), SS8(0xfbd8f358), SS8(0xff9f3e17), SS8(0xff960e94),
+       SS8(0x0142291c), SS8(0xdde26200), SS8(0xfbedadc0), SS8(0xffb54b3b),
+       SS8(0xffc4e05c), SS8(0x03bf7948), SS8(0xe071bc00), SS8(0xfc3fbb68),
+       SS8(0xffca00ed), SS8(0x000bb7db), SS8(0x06af2308), SS8(0xe3889d20),
+       SS8(0xfcbc98e8), SS8(0xffdba705), SS8(0x006c1de4), SS8(0x0a00d410),
+       SS8(0xe7054ca0), SS8(0xfd52986c), SS8(0xffe9811d), SS8(0x00e530da),
+       SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a)
+};
+
+static const int32_t _anamatrix8[8] = {
+       SA8(0x3b20d780), SA8(0x187de2a0), SA8(0x3ec52f80), SA8(0x3536cc40),
+       SA8(0x238e7680), SA8(0x0c7c5c20), SA8(0x2d413cc0), SA8(0x40000000)
+};
+
+static const int32_t synmatrix4[8][4] = {
+       { SN4(0x05a82798), SN4(0xfa57d868), SN4(0xfa57d868), SN4(0x05a82798) },
+       { SN4(0x030fbc54), SN4(0xf89be510), SN4(0x07641af0), SN4(0xfcf043ac) },
+       { SN4(0x00000000), SN4(0x00000000), SN4(0x00000000), SN4(0x00000000) },
+       { SN4(0xfcf043ac), SN4(0x07641af0), SN4(0xf89be510), SN4(0x030fbc54) },
+       { SN4(0xfa57d868), SN4(0x05a82798), SN4(0x05a82798), SN4(0xfa57d868) },
+       { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) },
+       { SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000) },
+       { SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) }
+};
+
+static const int32_t synmatrix8[16][8] = {
+       { SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798),
+         SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798) },
+       { SN8(0x0471ced0), SN8(0xf8275a10), SN8(0x018f8b84), SN8(0x06a6d988),
+         SN8(0xf9592678), SN8(0xfe70747c), SN8(0x07d8a5f0), SN8(0xfb8e3130) },
+       { SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac),
+         SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54) },
+       { SN8(0x018f8b84), SN8(0xfb8e3130), SN8(0x06a6d988), SN8(0xf8275a10),
+         SN8(0x07d8a5f0), SN8(0xf9592678), SN8(0x0471ced0), SN8(0xfe70747c) },
+       { SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000),
+         SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000) },
+       { SN8(0xfe70747c), SN8(0x0471ced0), SN8(0xf9592678), SN8(0x07d8a5f0),
+         SN8(0xf8275a10), SN8(0x06a6d988), SN8(0xfb8e3130), SN8(0x018f8b84) },
+       { SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54),
+         SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac) },
+       { SN8(0xfb8e3130), SN8(0x07d8a5f0), SN8(0xfe70747c), SN8(0xf9592678),
+         SN8(0x06a6d988), SN8(0x018f8b84), SN8(0xf8275a10), SN8(0x0471ced0) },
+       { SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868),
+         SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868) },
+       { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
+         SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) },
+       { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
+         SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
+       { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
+         SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
+       { SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000),
+         SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000) },
+       { SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
+         SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
+       { SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
+         SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
+       { SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
+         SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) }
+};
deleted file mode 100644 (file)
index 316beb72d1ef7a228503fc1ef0550d4fa77e0dff..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# This is a dirty trick just to ease compilation with emacs
-#
-# This file is not intended to be distributed or anything
-#
-# So: don't touch it, even better ignore it!
-
-all:
-       $(MAKE) -C ../..
-
-clean:
-       $(MAKE) -C ../.. clean
-
-.PHONY: all clean
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..efe5a3361d1c12d8943d6e6bca7af217a4211781
--- /dev/null
@@ -0,0 +1 @@
+../../pulse/Makefile
\ No newline at end of file
index 6f0d783026ab9bc476834c6088df58759286d691..30d4d3aa21d82c238ca5ce120d300476f423ec3e 100644 (file)
@@ -623,7 +623,11 @@ static int unsuspend(struct userdata *u) {
     pa_log_info("Trying resume...");
 
     snd_config_update_free_global();
-    if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
+    if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK,
+                            /*SND_PCM_NONBLOCK|*/
+                            SND_PCM_NO_AUTO_RESAMPLE|
+                            SND_PCM_NO_AUTO_CHANNELS|
+                            SND_PCM_NO_AUTO_FORMAT)) < 0) {
         pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err));
         goto fail;
     }
@@ -650,7 +654,9 @@ static int unsuspend(struct userdata *u) {
     }
 
     if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
-        pa_log_warn("Resume failed, couldn't restore original fragment settings.");
+        pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
+                    (unsigned long) u->nfragments, (unsigned long) u->fragment_size,
+                    (unsigned long) nfrags, period_size * u->frame_size);
         goto fail;
     }
 
@@ -1130,7 +1136,7 @@ static void thread_func(void *userdata) {
             pa_rtpoll_set_timer_disabled(u->rtpoll);
 
         /* Hmm, nothing to do. Let's sleep */
-        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
         if (ret == 0)
@@ -1150,7 +1156,7 @@ static void thread_func(void *userdata) {
                 goto fail;
             }
 
-            if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
+            if (revents & (POLLERR|POLLNVAL|POLLHUP|POLLPRI)) {
                 if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0)
                     goto fail;
 
@@ -1159,7 +1165,7 @@ static void thread_func(void *userdata) {
             }
 
             if (revents && u->use_tsched)
-                pa_log_debug("Wakeup from ALSA! (%i)", revents);
+                pa_log_debug("Wakeup from ALSA!%s%s", (revents & POLLIN) ? " INPUT" : "", (revents & POLLOUT) ? " OUTPUT" : "");
         }
     }
 
index fca05006170553db8ad32ed2a9741c08130b7eef..d0a22db774a450794dc41d8a719ed5387247c893 100644 (file)
@@ -565,7 +565,12 @@ static int unsuspend(struct userdata *u) {
     pa_log_info("Trying resume...");
 
     snd_config_update_free_global();
-    if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
+
+    if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE,
+                            /*SND_PCM_NONBLOCK|*/
+                            SND_PCM_NO_AUTO_RESAMPLE|
+                            SND_PCM_NO_AUTO_CHANNELS|
+                            SND_PCM_NO_AUTO_FORMAT)) < 0) {
         pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err));
         goto fail;
     }
@@ -592,7 +597,9 @@ static int unsuspend(struct userdata *u) {
     }
 
     if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
-        pa_log_warn("Resume failed, couldn't restore original fragment settings.");
+        pa_log_warn("Resume failed, couldn't restore original fragment settings. (Old: %lu*%lu, New %lu*%lu)",
+                    (unsigned long) u->nfragments, (unsigned long) u->fragment_size,
+                    (unsigned long) nfrags, period_size * u->frame_size);
         goto fail;
     }
 
@@ -964,7 +971,7 @@ static void thread_func(void *userdata) {
             pa_rtpoll_set_timer_disabled(u->rtpoll);
 
         /* Hmm, nothing to do. Let's sleep */
-        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
         if (ret == 0)
@@ -984,7 +991,7 @@ static void thread_func(void *userdata) {
                 goto fail;
             }
 
-            if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
+            if (revents & (POLLERR|POLLNVAL|POLLHUP|POLLPRI)) {
                 if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0)
                     goto fail;
 
@@ -992,7 +999,7 @@ static void thread_func(void *userdata) {
             }
 
             if (revents && u->use_tsched)
-                pa_log_debug("Wakeup from ALSA! (%i)", revents);
+                pa_log_debug("Wakeup from ALSA!%s%s", (revents & POLLIN) ? " INPUT" : "", (revents & POLLOUT) ? " OUTPUT" : "");
         }
     }
 
index 0e98b1c3e5196ade4b4bfd0f90394bf79e64c3b4..aefd4020fe1500294d7708f777afa9754f9cc62d 100644 (file)
 #  include <pulsecore/esound.h>
 #  define TCPWRAP_SERVICE "esound"
 #  define IPV4_PORT ESD_DEFAULT_PORT
-#  define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", "auth-cookie", "auth-cookie-enabled"
+#  define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", "auth-cookie", "auth-cookie-enabled",
 
 #  ifdef USE_TCP_SOCKETS
 #    include "module-esound-protocol-tcp-symdef.h"
index 47f5d83680a79a892558ede6fed73d170a5de48b..fe79291e6de31780d282061875300eac4b593aed 100644 (file)
@@ -377,7 +377,7 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
                 pa_log_info("Restoring device for stream %s.", name);
                 new_data->source = s;
             } else
-                pa_log_info("Not restroing device for stream %s, because already set", name);
+                pa_log_info("Not restoring device for stream %s, because already set", name);
         }
 
         pa_xfree(e);
deleted file mode 100644 (file)
index 316beb72d1ef7a228503fc1ef0550d4fa77e0dff..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# This is a dirty trick just to ease compilation with emacs
-#
-# This file is not intended to be distributed or anything
-#
-# So: don't touch it, even better ignore it!
-
-all:
-       $(MAKE) -C ../..
-
-clean:
-       $(MAKE) -C ../.. clean
-
-.PHONY: all clean
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..efe5a3361d1c12d8943d6e6bca7af217a4211781
--- /dev/null
@@ -0,0 +1 @@
+../../pulse/Makefile
\ No newline at end of file
index 739ef1610aae0e8674a02d4092429fb54f070891..58d64642adfb5c3dc6945d4dfbe709b376cfaa13 100644 (file)
@@ -61,6 +61,7 @@ static const pa_client_conf default_conf = {
     .disable_shm = FALSE,
     .cookie_file = NULL,
     .cookie_valid = FALSE,
+    .shm_size = 0
 };
 
 pa_client_conf *pa_client_conf_new(void) {
@@ -99,6 +100,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
         { "autospawn",              pa_config_parse_bool,    NULL },
         { "cookie-file",            pa_config_parse_string,  NULL },
         { "disable-shm",            pa_config_parse_bool,    NULL },
+        { "shm-size-bytes",         pa_config_parse_size,    NULL },
         { NULL,                     NULL,                    NULL },
     };
 
@@ -110,6 +112,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
     table[5].data = &c->autospawn;
     table[6].data = &c->cookie_file;
     table[7].data = &c->disable_shm;
+    table[8].data = &c->shm_size;
 
     if (filename) {
 
index 699279aaba161a4e6efd62913a1c54571588a905..4eac467ea6518115d5206355612e022dbeb371c4 100644 (file)
@@ -31,6 +31,7 @@ typedef struct pa_client_conf {
     pa_bool_t autospawn, disable_shm;
     uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
     pa_bool_t cookie_valid; /* non-zero, when cookie is valid */
+    size_t shm_size;
 } pa_client_conf;
 
 /* Create a new configuration data object and reset it to defaults */
index 8339d6514aeb294e3992c126150ce5d448485391..579bcc2046fc16665df5130498bb4d43ac1ac4a9 100644 (file)
@@ -30,3 +30,4 @@
 ; cookie-file =
 
 ; disable-shm = no
+; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
index 154e5faf6e4b82297f0d722a9f554260e04e8807..3145d9c80ccdd18ca96c6da6c23faa03b8700bd2 100644 (file)
@@ -174,10 +174,10 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
     pa_client_conf_load(c->conf, NULL);
     pa_client_conf_env(c->conf);
 
-    if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm))) {
+    if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm, c->conf->shm_size))) {
 
         if (!c->conf->disable_shm)
-            c->mempool = pa_mempool_new(FALSE);
+            c->mempool = pa_mempool_new(FALSE, c->conf->shm_size);
 
         if (!c->mempool) {
             context_free(c);
index d0c7d67e52ba65aee4751ee780aa7dfd643aba94..ababe17695bcac30d52d90c6cfb65035314f16a7 100644 (file)
@@ -86,7 +86,7 @@ pa_stream *pa_stream_new_with_proplist(
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID);
-    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE || ss->format != PA_SAMPLE_S32NE), PA_ERR_NOTSUPPORTED);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE && ss->format != PA_SAMPLE_S32BE), PA_ERR_NOTSUPPORTED);
     PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID);
     PA_CHECK_VALIDITY_RETURN_NULL(c, name || (p && pa_proplist_contains(p, PA_PROP_MEDIA_NAME)), PA_ERR_INVALID);
 
@@ -557,7 +557,7 @@ void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag,
     request_auto_timing_update(s, TRUE);
 
     if (s->started_callback)
-        s->started_callback(s, s->suspended_userdata);
+        s->started_callback(s, s->started_userdata);
 
 finish:
     pa_context_unref(c);
@@ -1851,7 +1851,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
     if (s->context->version >= 13) {
         pa_proplist *p = pa_proplist_new();
 
-        pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
+        pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
         o = pa_stream_proplist_update(s, PA_UPDATE_REPLACE, p, cb, userdata);
         pa_proplist_free(p);
     } else {
index 6b0e1d5670812e010c3eb087ccdedfef30bf1c05..58ceab9171162309dc10810b066253332fb3e353 100644 (file)
@@ -166,6 +166,24 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue,
     return 0;
 }
 
+int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+    size_t *i = data;
+    uint32_t k;
+
+    pa_assert(filename);
+    pa_assert(lvalue);
+    pa_assert(rvalue);
+    pa_assert(data);
+
+    if (pa_atou(rvalue, &k) < 0) {
+        pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
+        return -1;
+    }
+
+    *i = (size_t) k;
+    return 0;
+}
+
 int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     int k;
     pa_bool_t *b = data;
index 7eb1fae2251c89e5389bd3cf35a76e036823606a..a5174fce95e17af3cf533bef6f5c2b0e2562aa45 100644 (file)
@@ -39,8 +39,9 @@ typedef struct pa_config_item {
  * NULL */
 int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata);
 
-/* Generic parsers for integers, booleans and strings */
+/* Generic parsers for integers, size_t, booleans and strings */
 int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
+int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
 int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
 int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
 
index ad00f4f43519c4904fcb3e45e625470fe014ddbc..0bc5cb405d0ca95b0ea15055e524f1dcbba2a58c 100644 (file)
@@ -42,6 +42,7 @@
 #include <dirent.h>
 #include <regex.h>
 #include <langinfo.h>
+#include <sys/utsname.h>
 
 #ifdef HAVE_STRTOF_L
 #include <locale.h>
@@ -1314,31 +1315,43 @@ static char* make_random_dir(mode_t m) {
         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
         "0123456789";
 
-    char fn[24] = "/tmp/pulse-";
+    const char *tmpdir;
+    char *fn;
+    size_t pathlen;
 
-    fn[sizeof(fn)-1] = 0;
+    if (!(tmpdir = getenv("TMPDIR")))
+        if (!(tmpdir = getenv("TMP")))
+            if (!(tmpdir = getenv("TEMP")))
+                tmpdir = getenv("TEMPDIR");
+
+    if (!tmpdir || !pa_is_path_absolute(tmpdir))
+        tmpdir = "/tmp";
+
+    fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
+    pathlen = strlen(fn);
 
     for (;;) {
-        unsigned i;
+        size_t i;
         int r;
         mode_t u;
         int saved_errno;
 
-        for (i = 11; i < sizeof(fn)-1; i++)
+        for (i = pathlen - 12; i < pathlen; i++)
             fn[i] = table[rand() % (sizeof(table)-1)];
 
         u = umask((~m) & 0777);
         r = mkdir(fn, m);
+
         saved_errno = errno;
         umask(u);
+        errno = saved_errno;
 
         if (r >= 0)
-            return pa_xstrdup(fn);
-
-        errno = saved_errno;
+            return fn;
 
         if (errno != EEXIST) {
             pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
+            pa_xfree(fn);
             return NULL;
         }
     }
@@ -1369,6 +1382,7 @@ static int make_random_dir_and_link(mode_t m, const char *k) {
 char *pa_get_runtime_dir(void) {
     char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
     struct stat st;
+    mode_t m;
 
     /* The runtime directory shall contain dynamic data that needs NOT
      * to be kept accross reboots and is usuallly private to the user,
@@ -1377,10 +1391,9 @@ char *pa_get_runtime_dir(void) {
      * this directory, we link it to a random subdir in /tmp, if it
      * was not explicitly configured. */
 
-    if ((d = getenv("PULSE_RUNTIME_PATH"))) {
-        mode_t m;
+    m = pa_in_system_mode() ? 0755U : 0700U;
 
-        m = pa_in_system_mode() ? 0755U : 0700U;
+    if ((d = getenv("PULSE_RUNTIME_PATH"))) {
 
         if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0)  {
             pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
@@ -1393,6 +1406,11 @@ char *pa_get_runtime_dir(void) {
     if (!(d = get_pulse_home()))
         goto fail;
 
+    if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0)  {
+        pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
+        goto fail;
+    }
+
     if (!(mid = pa_machine_id())) {
         pa_xfree(d);
         goto fail;
@@ -2333,7 +2351,7 @@ int pa_reset_sigs(int except, ...) {
 int pa_reset_sigsv(const int except[]) {
     int sig;
 
-    for (sig = 1; sig < _NSIG; sig++) {
+    for (sig = 1; sig < NSIG; sig++) {
         pa_bool_t reset = TRUE;
 
         switch (sig) {
@@ -2445,5 +2463,12 @@ char *pa_machine_id(void) {
     /* If no hostname was set we use the POSIX hostid. It's usually
      * the IPv4 address.  Mit not be that stable. */
     return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
+}
+
+char *pa_uname_string(void) {
+    struct utsname u;
+
+    pa_assert_se(uname(&u) == 0);
 
+    return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
 }
index c9e307f5da131ea2efb5ee691ed5a5cb02c7a83d..df8ce3f85c95e2b6815b3879e69e107f1c6d28b9 100644 (file)
@@ -191,5 +191,6 @@ pa_bool_t pa_in_system_mode(void);
 #define pa_streq(a,b) (!strcmp((a),(b)))
 
 char *pa_machine_id(void);
+char *pa_uname_string(void);
 
 #endif
index 6f8a292984b6e0e13b94010b28a36f870f122bd9..5761bbc73fb302d8e88d64d54543f5a606a98d69 100644 (file)
@@ -66,7 +66,7 @@ static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t o
 
 static void core_free(pa_object *o);
 
-pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
+pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) {
     pa_core* c;
     pa_mempool *pool;
     int j;
@@ -74,14 +74,14 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     pa_assert(m);
 
     if (shared) {
-        if (!(pool = pa_mempool_new(shared))) {
+        if (!(pool = pa_mempool_new(shared, shm_size))) {
             pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool.");
-            shared = 0;
+            shared = FALSE;
         }
     }
 
     if (!shared) {
-        if (!(pool = pa_mempool_new(shared))) {
+        if (!(pool = pa_mempool_new(shared, shm_size))) {
             pa_log("pa_mempool_new() failed.");
             return NULL;
         }
@@ -138,6 +138,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     c->realtime_scheduling = FALSE;
     c->realtime_priority = 5;
     c->disable_remixing = FALSE;
+    c->disable_lfe_remixing = FALSE;
 
     for (j = 0; j < PA_CORE_HOOK_MAX; j++)
         pa_hook_init(&c->hooks[j], c);
index eb7684185a2348243a3cf0d6d0e95e31dea9d950..39559082632cfe30a9cf352e46148f04d7fd068b 100644 (file)
@@ -124,6 +124,7 @@ struct pa_core {
     pa_bool_t running_as_daemon:1;
     pa_bool_t realtime_scheduling:1;
     pa_bool_t disable_remixing:1;
+    pa_bool_t disable_lfe_remixing:1;
 
     pa_resample_method_t resample_method;
     int realtime_priority;
@@ -140,7 +141,7 @@ enum {
     PA_CORE_MESSAGE_MAX
 };
 
-pa_core* pa_core_new(pa_mainloop_api *m, int shared);
+pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size);
 
 /* Check whether noone is connected to this core */
 void pa_core_check_idle(pa_core *c);
index b6423efd1e612a0cb79797ae8c316952af589179..24a28db74aa48104c76e6bfc798a39d666ac7efc 100644 (file)
@@ -80,7 +80,7 @@ unsigned pa_idxset_trivial_hash_func(const void *p) {
 }
 
 int pa_idxset_trivial_compare_func(const void *a, const void *b) {
-    return a != b;
+    return a < b ? -1 : (a > b ? 1 : 0);
 }
 
 pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) {
@@ -318,8 +318,7 @@ void* pa_idxset_rrobin(pa_idxset *s, uint32_t *idx) {
 
     hash = *idx % NBUCKETS;
 
-    if (!(e = index_scan(s, hash, *idx)))
-        return NULL;
+    e = index_scan(s, hash, *idx);
 
     if (e && e->iterate_next)
         e = e->iterate_next;
index 6d12acdca66a98e3e5301633cbd3dd920679cd5e..400a4e1e03a2c4084db32a2ca31068ae9a335ad7 100644 (file)
@@ -680,8 +680,9 @@ static void memblock_replace_import(pa_memblock *b) {
         pa_mutex_unlock(seg->import->mutex);
 }
 
-pa_mempool* pa_mempool_new(pa_bool_t shared) {
+pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) {
     pa_mempool *p;
+    char t1[64], t2[64];
 
     p = pa_xnew(pa_mempool, 1);
 
@@ -692,13 +693,26 @@ pa_mempool* pa_mempool_new(pa_bool_t shared) {
     if (p->block_size < PA_PAGE_SIZE)
         p->block_size = PA_PAGE_SIZE;
 
-    p->n_blocks = PA_MEMPOOL_SLOTS_MAX;
+    if (size <= 0)
+        p->n_blocks = PA_MEMPOOL_SLOTS_MAX;
+    else {
+        p->n_blocks = (unsigned) (size / p->block_size);
+
+        if (p->n_blocks < 2)
+            p->n_blocks = 2;
+    }
 
     if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) {
         pa_xfree(p);
         return NULL;
     }
 
+    pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s",
+                 p->memory.shared ? "shared" : "private",
+                 p->n_blocks,
+                 pa_bytes_snprint(t1, sizeof(t1), (unsigned) p->block_size),
+                 pa_bytes_snprint(t2, sizeof(t2), (unsigned) (p->n_blocks * p->block_size)));
+
     memset(&p->stat, 0, sizeof(p->stat));
     pa_atomic_store(&p->n_init, 0);
 
index efe55b0289fa6d827f448b2fa982cc0198e42c3c..b1eab2a9645edc4383182b4622a701f27badb5a8 100644 (file)
@@ -117,7 +117,7 @@ pa_mempool * pa_memblock_get_pool(pa_memblock *b);
 pa_memblock *pa_memblock_will_need(pa_memblock *b);
 
 /* The memory block manager */
-pa_mempool* pa_mempool_new(pa_bool_t shared);
+pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size);
 void pa_mempool_free(pa_mempool *p);
 const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p);
 void pa_mempool_vacuum(pa_mempool *p);
diff --git a/src/pulsecore/prioq.c b/src/pulsecore/prioq.c
new file mode 100644 (file)
index 0000000..693dc51
--- /dev/null
@@ -0,0 +1,256 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2008 Lennart Poettering
+
+  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 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/xmalloc.h>
+
+#include <pulsecore/flist.h>
+
+#include "prioq.h"
+
+struct pa_prioq_item {
+    void *value;
+    unsigned idx;
+};
+
+struct pa_prioq {
+    pa_prioq_item **items;
+    unsigned n_items;
+    unsigned n_allocated;
+    pa_compare_func_t compare_func;
+};
+
+PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
+
+pa_prioq *pa_prioq_new(pa_compare_func_t compare_func) {
+
+    pa_prioq *q;
+
+    q = pa_xnew(pa_prioq, 1);
+    q->compare_func = compare_func;
+    q->n_items = 0;
+    q->n_allocated = 64;
+    q->items = pa_xnew(pa_prioq_item*, q->n_allocated);
+
+    return q;
+}
+
+void pa_prioq_free(pa_prioq *q, pa_free2_cb_t free_cb, void *userdata) {
+    pa_prioq_item **i, **e;
+
+    pa_assert(q);
+
+    for (i = q->items, e = q->items + q->n_items; i < e; i++) {
+
+        if (!*i)
+            continue;
+
+        if (free_cb)
+            free_cb((*i)->value, userdata);
+
+        pa_xfree(*i);
+    }
+
+    pa_xfree(q->items);
+    pa_xfree(q);
+}
+
+static void shuffle_up(pa_prioq *q, pa_prioq_item *i) {
+    unsigned j;
+
+    pa_assert(q);
+    pa_assert(i);
+
+    j = i->idx;
+
+    while (j > 0) {
+        unsigned k;
+
+        k = (j-1)/2;
+
+        if (q->compare_func(q->items[k]->value, i->value) < 0)
+            break;
+
+        q->items[k]->idx = j;
+        q->items[j] = q->items[k];
+
+        j = k;
+    }
+
+    i->idx = j;
+    q->items[j] = i;
+
+}
+
+pa_prioq_item* pa_prioq_put(pa_prioq *q, void *p) {
+    pa_prioq_item *i;
+
+    pa_assert(q);
+
+    if (q->n_items >= q->n_allocated) {
+        q->n_allocated = PA_MAX(q->n_items+1, q->n_allocated)*2;
+        q->items = pa_xrealloc(q->items, sizeof(pa_prioq_item*) * q->n_allocated);
+    }
+
+    if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
+        i = pa_xnew(pa_prioq_item, 1);
+
+    i->value = p;
+    i->idx = q->n_items++;
+
+    shuffle_up(q, i);
+
+    return i;
+}
+
+void* pa_prioq_peek(pa_prioq *q) {
+    pa_assert(q);
+
+    if (q->n_items <= 0)
+        return NULL;
+
+    return q->items[0]->value;
+}
+
+void* pa_prioq_pop(pa_prioq *q){
+    pa_assert(q);
+
+    if (q->n_items <= 0)
+        return NULL;
+
+    return pa_prioq_remove(q, q->items[0]);
+}
+
+static void swap(pa_prioq *q, unsigned j, unsigned k) {
+    pa_prioq_item *t;
+
+    pa_assert(q);
+    pa_assert(j < q->n_items);
+    pa_assert(k < q->n_items);
+
+    pa_assert(q->items[j]->idx == j);
+    pa_assert(q->items[k]->idx == k);
+
+    t = q->items[j];
+
+    q->items[j]->idx = k;
+    q->items[j] = q->items[k];
+
+    q->items[k]->idx = j;
+    q->items[k] = t;
+}
+
+static void shuffle_down(pa_prioq *q, unsigned idx) {
+
+    pa_assert(q);
+    pa_assert(idx < q->n_items);
+
+    for (;;) {
+        unsigned j, k, s;
+
+        k = (idx+1)*2; /* right child */
+        j = k-1;       /* left child */
+
+        if (j >= q->n_items)
+            break;
+
+        if (q->compare_func(q->items[j]->value, q->items[idx]->value) < 0)
+
+            /* So our left child is smaller than we are, let's
+             * remember this fact */
+            s = j;
+        else
+            s = idx;
+
+        if (k < q->n_items &&
+            q->compare_func(q->items[k]->value, q->items[s]->value) < 0)
+
+            /* So our right child is smaller than we are, let's
+             * remember this fact */
+            s = k;
+
+        /* s now points to the smallest of the three items */
+
+        if (s == idx)
+            /* No swap necessary, we're done */
+            break;
+
+        swap(q, idx, s);
+        idx = s;
+    }
+}
+
+void* pa_prioq_remove(pa_prioq *q, pa_prioq_item *i) {
+    void *p;
+
+    pa_assert(q);
+    pa_assert(i);
+    pa_assert(q->n_items >= 1);
+
+    p = i->value;
+
+    if (q->n_items-1 == i->idx) {
+        /* We are the last entry, so let's just remove us and good */
+        q->n_items--;
+
+    } else {
+
+        /* We are not the last entry, we need to replace ourselves
+         * with the last node and reshuffle */
+
+        q->items[i->idx] = q->items[q->n_items-1];
+        q->items[i->idx]->idx = i->idx;
+        q->n_items--;
+
+        shuffle_down(q, i->idx);
+    }
+
+    if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
+        pa_xfree(i);
+
+    return p;
+}
+
+unsigned pa_prioq_size(pa_prioq *q) {
+    pa_assert(q);
+
+    return q->n_items;
+}
+
+pa_bool_t pa_prioq_isempty(pa_prioq *q) {
+    pa_assert(q);
+
+    return q->n_items == 0;
+}
+
+void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i) {
+    pa_assert(q);
+    pa_assert(i);
+
+    /* This will move the entry down as far as necessary */
+    shuffle_down(q, i->idx);
+
+    /* And this will move the entry up as far as necessary */
+    shuffle_up(q, i);
+}
diff --git a/src/pulsecore/prioq.h b/src/pulsecore/prioq.h
new file mode 100644 (file)
index 0000000..fd3550b
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef foopulsecoreprioqhfoo
+#define foopulsecoreprioqhfoo
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2008 Lennart Poettering
+
+  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
+  Lesser 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.
+***/
+
+#include <inttypes.h>
+
+#include <pulsecore/macro.h>
+#include <pulsecore/idxset.h>
+
+/* A heap-based priority queue. Removal and insertion is O(log
+ * n). Removal can happen a the top or at any position referenced by a
+ * pa_prioq_item.  */
+
+typedef struct pa_prioq pa_prioq;
+typedef struct pa_prioq_item pa_prioq_item;
+
+/* Instantiate a new prioq with the specified comparison functions */
+pa_prioq* pa_prioq_new(pa_compare_func_t compare_func);
+
+/* Free the prioq. When the prioq is not empty the specified function is called for every entry contained */
+void pa_prioq_free(pa_prioq *q, pa_free2_cb_t free_cb, void *userdata);
+
+/* Store a new item in the prioq. */
+pa_prioq_item* pa_prioq_put(pa_prioq *q, void* data);
+
+/* Get the item on the top of the queue, but don't remove it from the queue*/
+void* pa_prioq_peek(pa_prioq*q);
+
+/* Get the item on the top of the queue, and remove it from thq queue */
+void* pa_prioq_pop(pa_prioq*q);
+
+/* Remove an arbitrary from theq prioq, returning it's data */
+void* pa_prioq_remove(pa_prioq*q, pa_prioq_item *i);
+
+/* The priority of an item was modified. Adjustthe queue to that */
+void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i);
+
+/* Return the current number of items in the prioq */
+unsigned pa_prioq_size(pa_prioq*s);
+
+/* Return TRUE of the prioq is empty */
+pa_bool_t pa_prioq_isempty(pa_prioq *s);
+
+#endif
index 6005775ed1779c3efea7d9c06938930d5d2cbe5a..4d505f57bee5250e4d859cd75c36d0fae46f03e5 100644 (file)
@@ -37,7 +37,7 @@
 
 void pa_init_proplist(pa_proplist *p) {
     int a, b;
-#ifndef HAVE_DECL_ENVIRON
+#if !HAVE_DECL_ENVIRON
     extern char **environ;
 #endif
     char **e;
index 6ccee571413ed5639ec0830201d21a269f5e47df..5c6dbf44d44206939b6ec1e1e188c7ee0676aae8 100644 (file)
@@ -2192,6 +2192,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
         if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
             do_shm = FALSE;
 
+#ifdef HAVE_CREDS
     if (do_shm) {
         /* Only enable SHM if both sides are owned by the same
          * user. This is a security measure because otherwise data
@@ -2201,6 +2202,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
         if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
             do_shm = FALSE;
     }
+#endif
 
     pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
     pa_pstream_enable_shm(c->pstream, do_shm);
index 45cd68c1cf051c20181ec05331274677f306fb0f..b2d512c8de256dddda06e4c6cc4aabcfd621cf82 100644 (file)
@@ -716,7 +716,11 @@ static void calc_map_table(pa_resampler *r) {
                  * channels for LFE. */
 
                 for (ic = 0; ic < r->i_ss.channels; ic++) {
-                    r->map_table[oc][ic] = 1.0f / (float) r->i_ss.channels;
+
+                    if (!(r->flags & PA_RESAMPLER_NO_LFE))
+                        r->map_table[oc][ic] = 1.0f / (float) r->i_ss.channels;
+                    else
+                        r->map_table[oc][ic] = 0;
 
                     /* Please note that a channel connected to LFE
                      * doesn't really count as connected. */
@@ -851,7 +855,7 @@ static void calc_map_table(pa_resampler *r) {
             }
         }
 
-        if (ic_unconnected_lfe > 0) {
+        if (ic_unconnected_lfe > 0 && !(r->flags & PA_RESAMPLER_NO_LFE)) {
 
             /* OK, so there is an unconnected LFE channel. Let's mix
              * it into all channels, with factor 0.375 */
@@ -1414,40 +1418,46 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
         unsigned j;
 
         j = ((r->peaks.o_counter * r->i_ss.rate) / r->o_ss.rate);
-        j = j > r->peaks.i_counter ? j - r->peaks.i_counter : 0;
 
-        if (j >= in_n_frames)
-            break;
+        if (j > r->peaks.i_counter)
+            j -= r->peaks.i_counter;
+        else
+            j = 0;
 
         pa_assert(o_index * fz < pa_memblock_get_length(output->memblock));
 
         if (r->work_format == PA_SAMPLE_S16NE) {
             unsigned i, c;
-            int16_t *s = (int16_t*) ((uint8_t*) src + fz * j);
+            int16_t *s = (int16_t*) ((uint8_t*) src + fz * start);
             int16_t *d = (int16_t*) ((uint8_t*) dst + fz * o_index);
 
-            for (i = start; i <= j; i++)
+            for (i = start; i <= j && i < in_n_frames; i++)
+
                 for (c = 0; c < r->o_ss.channels; c++, s++) {
                     int16_t n;
 
                     n = (int16_t) (*s < 0 ? -*s : *s);
 
-                    if (n > r->peaks.max_i[c])
+                    if (PA_UNLIKELY(n > r->peaks.max_i[c]))
                         r->peaks.max_i[c] = n;
                 }
 
+            if (i >= in_n_frames)
+                break;
+
             for (c = 0; c < r->o_ss.channels; c++, d++) {
-                 *d = r->peaks.max_i[c];
-                 r->peaks.max_i[c] = 0;
+                *d = r->peaks.max_i[c];
+                r->peaks.max_i[c] = 0;
             }
+
         } else {
             unsigned i, c;
-            float *s = (float*) ((uint8_t*) src + fz * j);
+            float *s = (float*) ((uint8_t*) src + fz * start);
             float *d = (float*) ((uint8_t*) dst + fz * o_index);
 
             pa_assert(r->work_format == PA_SAMPLE_FLOAT32NE);
 
-            for (i = start; i <= j; i++)
+            for (i = start; i <= j && i < in_n_frames; i++)
                 for (c = 0; c < r->o_ss.channels; c++, s++) {
                     float n = fabsf(*s);
 
@@ -1455,13 +1465,16 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
                         r->peaks.max_f[c] = n;
                 }
 
+            if (i >= in_n_frames)
+                break;
+
             for (c = 0; c < r->o_ss.channels; c++, d++) {
                 *d = r->peaks.max_f[c];
                 r->peaks.max_f[c] = 0;
             }
         }
 
-        start = j+1;
+        start = j;
     }
 
     pa_memblock_release(input->memblock);
index 5e302a9b953112dfa30696e873447bce8bf37fdc..87110cc2dd90d5527e6007d205ff929332d494f3 100644 (file)
@@ -49,9 +49,10 @@ typedef enum pa_resample_method {
 } pa_resample_method_t;
 
 typedef enum pa_resample_flags {
-    PA_RESAMPLER_VARIABLE_RATE = 1,
-    PA_RESAMPLER_NO_REMAP = 2,  /* implies NO_REMIX */
-    PA_RESAMPLER_NO_REMIX = 4
+    PA_RESAMPLER_VARIABLE_RATE = 0x0001U,
+    PA_RESAMPLER_NO_REMAP      = 0x0002U,  /* implies NO_REMIX */
+    PA_RESAMPLER_NO_REMIX      = 0x0004U,
+    PA_RESAMPLER_NO_LFE        = 0x0008U
 } pa_resample_flags_t;
 
 pa_resampler* pa_resampler_new(
index 7d80242f44ea5e0eb6ac85f36b51528a1f62f3a1..326a7e2ce1651c6ace61eacffff0701805e99848 100644 (file)
@@ -201,7 +201,8 @@ pa_sink_input* pa_sink_input_new(
                       data->resample_method,
                       ((flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
                       ((flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
-                      (core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
+                      (core->disable_remixing || (flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
+                      (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
             pa_log_warn("Unsupported resampling operation.");
             return NULL;
         }
index 5df950a87d22e7e7b5281af2ce012382f210b45d..d76f6e4e94bda85889b046a4dcd7e4aa4e121383 100644 (file)
@@ -171,7 +171,8 @@ pa_source_output* pa_source_output_new(
                       data->resample_method,
                       ((flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
                       ((flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
-                      (core->disable_remixing || (flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) {
+                      (core->disable_remixing || (flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
+                      (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
             pa_log_warn("Unsupported resampling operation.");
             return NULL;
         }
index d71eff1c1a32031519868bf8e2405f7acd6c9757..4a72f5a3f624a5bbe9d84b3a03848dae2f2364d2 100644 (file)
@@ -205,7 +205,7 @@ int main(int argc, char *argv[]) {
     oil_init();
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    pa_assert_se(pool = pa_mempool_new(FALSE));
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
     pa_assert_se(envelope = pa_envelope_new(&ss));
 
     block = generate_block(pool, &ss);
index cb3dc87c847b5ec81effedd2a02562548409f77c..80cfda6aa6e4520279968ed9ffabe9003afcebe4 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <pulsecore/macro.h>
 #include <pulsecore/thread.h>
-#include <pulse/lock-autospawn.h>
+#include <pulsecore/lock-autospawn.h>
 #include <pulse/util.h>
 
 static void thread_func(void*k) {
index c066582233d62fe9ed39cf6ee3f9f8a46432f1a6..92e3e14e32b86d8bae95b096ecbd97dee44d17cb 100644 (file)
@@ -41,7 +41,7 @@ int main(int argc, char *argv[]) {
     pa_mcalign *a;
     pa_memchunk c;
 
-    p = pa_mempool_new(0);
+    p = pa_mempool_new(FALSE, 0);
 
     a = pa_mcalign_new(11);
 
index 6da1b1e9f14dc0a6717312656c270246302412ca..37b5b403a31d458d072c18fc0f6da6de49bafee3 100644 (file)
@@ -78,9 +78,9 @@ int main(int argc, char *argv[]) {
 
     const char txt[] = "This is a test!";
 
-    pool_a = pa_mempool_new(1);
-    pool_b = pa_mempool_new(1);
-    pool_c = pa_mempool_new(1);
+    pool_a = pa_mempool_new(TRUE, 0);
+    pool_b = pa_mempool_new(TRUE, 0);
+    pool_c = pa_mempool_new(TRUE, 0);
 
     pa_mempool_get_shm_id(pool_a, &id_a);
     pa_mempool_get_shm_id(pool_b, &id_b);
index 7bf992a19e18042d3b84858fbe177ccc036864f3..c53945b44c02b1d83b1a287f157db3a1aa6cb29b 100644 (file)
@@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
 
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    p = pa_mempool_new(0);
+    p = pa_mempool_new(FALSE, 0);
 
     silence.memblock = pa_memblock_new_fixed(p, (char*)  "__", 2, 1);
     assert(silence.memblock);
index 544121fde54cd47107b0ad294cab4064b10797df..759d7690d79149d3455f5406d3f73df6c03250e5 100644 (file)
@@ -201,7 +201,7 @@ int main(int argc, char *argv[]) {
     oil_init();
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    pa_assert_se(pool = pa_mempool_new(FALSE));
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
 
     a.channels = 1;
     a.rate = 44100;
diff --git a/src/tests/prioq-test.c b/src/tests/prioq-test.c
new file mode 100644 (file)
index 0000000..120b512
--- /dev/null
@@ -0,0 +1,44 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulsecore/prioq.h>
+#include <pulsecore/macro.h>
+
+#define N 1024
+
+int main(int argc, char *argv[]) {
+    pa_prioq *q;
+    unsigned i;
+
+    srand(0);
+
+    q = pa_prioq_new(pa_idxset_trivial_compare_func);
+
+    /* Fill in 1024 */
+    for (i = 0; i < N; i++)
+        pa_prioq_put(q, PA_UINT_TO_PTR((unsigned) rand()));
+
+    /* Remove half of it again */
+    for (i = 0; i < N/2; i++){
+        unsigned u = PA_PTR_TO_UINT(pa_prioq_pop(q));
+        pa_log("%16u", u);
+    }
+
+    pa_log("Refilling");
+
+    /* Fill in another 1024 */
+    for (i = 0; i < N; i++)
+        pa_prioq_put(q, PA_UINT_TO_PTR((unsigned) rand()));
+
+
+    /* Remove everything */
+    while (!pa_prioq_isempty(q)) {
+        unsigned u = PA_PTR_TO_UINT(pa_prioq_pop(q));
+        pa_log("%16u", u);
+    }
+
+    pa_prioq_free(q, NULL, NULL);
+
+    return 0;
+}
index 4777c150958b838e0aacf7e8b724d2d5a9c54945..3538d7d4664297b7d77135ba078bcc349be38270 100644 (file)
@@ -58,7 +58,7 @@ int main(int argc, char *argv[]) {
     oil_init();
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    pa_assert_se(pool = pa_mempool_new(FALSE));
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
 
     for (i = 0; maps[i].channels > 0; i++)
         for (j = 0; maps[j].channels > 0; j++) {
index 6959127b5a032b527dd9e55ae496d5bb780c26b9..2d59186760b70c545ac889073362edfd6df41fa1 100644 (file)
@@ -201,7 +201,7 @@ int main(int argc, char *argv[]) {
     oil_init();
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    pa_assert_se(pool = pa_mempool_new(FALSE));
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
 
     a.channels = b.channels = 1;
     a.rate = b.rate = 44100;