天天看点

Compiling and running pulseaudio from git

A few budding developers have asked me recently about this and to make life easy, I decided to write up this guide! There are some gotchas to look out for so please read carefully!

Are we ready? OK, lets being!

The shell output shown below will include my machine's name, "Eoollo". My bash prompt also shows the current git branch thanks to the git-prompt package in Mandriva (you can enable it manually by following this guide). Note that for various reasons I wont go into in this guide, the development version of PA is currently 0.9.19, this is despite the current released version being 0.9.21. Its due to how the git tree is organised, and I'm hoping to fix this soon. Edit: Git master is now tracking PA 1.0 (not for any specific milestone of 1.0, but just because a 3-point version number is kinda annoying. Essential the version policy is now decided and all should be working fine now. There may still be a 0.9.23 based of the current stable-queue branch, but the next release from master will be 1.0.

May the Source Be With You

The first job is to clone our code repository. You first have to pick where you want to keep your development version. In the example below I've decided to use a folder under my home directory called "padev"

[[email protected] ~]$ git clone git://git.0pointer.de/pulseaudio.git padev

Cloning into padev...

remote: Counting objects: 39578, done.

remote: Compressing objects: 100% (6760/6760), done.

remote: Total 39578 (delta 32779), reused 39578 (delta 32779)

Receiving objects: 100% (39578/39578), 14.56 MiB | 1.97 MiB/s, done.

Resolving deltas: 100% (32779/32779), done.

[[email protected] ~]$

Now you should have a ~/padev/ folder containing the code.

Compile Time

Now it's time to compile the code, but before we do this, we have to prepare the checkout for compilation. Handily there is a script provided to make this easy for us.

[[email protected] ~]$ cd padev/

[[email protected] padev (master)]$ ./bootstrap.sh -V

+ case $(uname) in

++ uname

...

+ make clean

make: *** No rule to make target `clean'.  Stop.

[[email protected] padev (master)]$

There is an error about not being able to "make clean" here but you can safely ignore that.

Next we'll create a build directory. This is not mandatory, but it helps keep temporary build files etc. separate from the code in the checkout (there are special git commands to delete such files but all the same, I feel this is cleaner). After creating the build directory, we change to it and run the configure script.

[[email protected] padev (master)]$ mkdir build

[[email protected] padev (master)]$ cd build/

[[email protected] build (master)]$ ../configure --prefix=$(pwd)

checking for a BSD-compatible install... /usr/bin/install -c

checking whether build environment is sane... yes

...

config.status: executing po/stamp-it commands

---{ pulseaudio 0.9.19-562-g395da }---

prefix:                        /home/Ubuntu/padev/build

sysconfdir:                    ${prefix}/etc

localstatedir:                 ${prefix}/var

System Runtime Path:           ${prefix}/var/run/pulse

System State Path:             ${prefix}/var/lib/pulse

System Config Path:            ${prefix}/var/lib/pulse

Compiler:                      gcc -std=gnu99

CFLAGS:                        -g -O2 -Wall -W -Wextra -pipe -Wno-long-long -Winline -Wvla -Wno-overlength-strings -Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wpointer-arith -Winit-self -Wdeclaration-after-statement -Wfloat-equal -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn -Wshadow -Wendif-labels -Wcast-align -Wstrict-aliasing=2 -Wwrite-strings -Wno-unused-parameter -ffast-math -Wp,-D_FORTIFY_SOURCE=2 -fno-common -fdiagnostics-show-option -I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include

Have X11:                      yes

Enable OSS Output:             yes

Enable OSS Wrapper:            yes

Enable CoreAudio:              no

Enable Alsa:                   yes

Enable Solaris:                no

Enable GLib 2.0:               yes

Enable Gtk+ 2.0:               yes

Enable GConf:                  yes

Enable Avahi:                  yes

Enable Jack:                   yes

Enable Async DNS:              yes

Enable LIRC:                   yes

Enable DBUS:                   yes

Enable HAL:                    yes

Enable udev:                   yes

Enable HAL->udev compat:       no

Enable BlueZ:                  yes

Enable TCP Wrappers:           yes

Enable libsamplerate:          yes

Enable IPv6:                   yes

Enable OpenSSL (for Airtunes): yes

Enable tdb:                    yes

Enable gdbm:                   no

Enable simple database:        no

Enable fftw:                   yes

System User:                   pulse

System Group:                  pulse

Access Group:                  pulse-access

Enable per-user EsounD socket: yes

Force preopen:                 no

Preopened modules:             all

[[email protected] build (master)]$

You should pay particular attention to the --prefix argument passed to configure. Rather than "installing" this version of PulseAudio, we'll just run it from the source tree. This is both quicker and saves any potential conflict with your system-installed PulseAudio packages.

You should also pay attention to the table at the end which lists the available support. In order for automatic card detection to work properly with your build, you really should ensure that udev support in particular is available. If it does not print a "yes" line in the output then you probably do not have the "udev-devel" package for your distro installed.

Let's Build

OK, so you're ready to build! But not quite. Due to an upstream bug, the translations for .desktop files are not written if the destination folder does not exist, so let's create it manually

[[email protected] build (master)]$ mkdir -p src/daemon

[[email protected] build (master)]$

OK, with all the prep work done, we really do build it.

[[email protected] build (master)]$ make

echo 0.9.19-562-g395da > ../.version-t && mv ../.version-t ../.version

make  all-recursive

...

file=`echo zh_TW | sed 's,.*/,,'`.gmo \

 && rm -f $file && /usr/bin/msgfmt -o $file ../../po/zh_TW.po

make[2]: Leaving directory `/home/Ubuntu/padev/build/po'

make[2]: Entering directory `/home/Ubuntu/padev/build'

make[2]: Leaving directory `/home/Ubuntu/padev/build'

make[1]: Leaving directory `/home/Ubuntu/padev/build'

[[email protected] build (master)]$

Now that it's built successfully we can run it, but we'll do a little bit of preparation first. As ALSA currently lacks UCM (Use Case Management) (although this is due to be added soon), PulseAudio supports a fairly robust "probing" system to determine how your sound hardware works. In order to run these probes it has to know where to look for the "mixer profile" definitions. As we are running from the build tree, we'll cheat a little and use a symlink so that our development build can find the files.

[[email protected] build (master)]$ mkdir -p share/pulseaudio

[[email protected] build (master)]$ ln -s ../../../src/modules/alsa/mixer share/pulseaudio/alsa-mixer

[[email protected] build (master)]$

In order to run some test tools, we also need to manually create some symlinks that are normally done as part of the install process.

[[email protected] build (master)]$ ln -s pacat src/paplay

[[email protected] build (master)]$ ln -s pacat src/parec

[[email protected] build (master)]$

Run, Forest, Run!

Now that things are built and some symlinks are in place, we can run our nice shiny development version. You should first ensure that the system-installed PulseAudio daemon is not running. In order to do this, you should disable autospawn by doing:

echo "autospawn=no" >> ~/.pulse/client.conf

Once this is done, you should reboot. PulseAudio will likely still start when you log in to X11 by virtue of the start-pulseaudio-x11 script that is run at login, but some systems that rely on PA autospawn may not initialise correctly (e.g. under KDE knotify and kmix may start in 'ALSA mode'. This is generally not a problem, but you should be aware of the consequences.

So if your system PA has been run, simply execute:

pulseaudio -k

To kill the currently running daemon. You can then start your development version via:

[[email protected] build (master)]$ src/pulseaudio -n -F src/default.pa -p $(pwd)/src/.libs/ -vvvv

W: main.c: Couldn't canonicalize binary path, cannot self execute.

I: main.c: setrlimit(RLIMIT_NICE, (31, 31)) failed: Operation not permitted

I: main.c: setrlimit(RLIMIT_RTPRIO, (9, 9)) failed: Operation not permitted

D: core-rtclock.c: Timer slack is set to 50 us.

D: core-util.c: RealtimeKit worked.

I: core-util.c: Successfully gained nice level -11.

I: main.c: This is PulseAudio 0.9.19-562-g395da

...

This will produce a lot of debug output, so you should leave that terminal running. The command line arguments are as follows: "-n" says "do not process the (system) default.pa". This is generally only needed if you have a ~/.pulse/default.pa file, but it does no harm to include it always. "-F src/default.pa" says to "process the script src/default.pa" and "-p $(pwd)/src/.libs" tells PA where to look for it's modules (i.e. from your build tree).

Note that the state files saved by PulseAudio in ~/.pulse/ folder will very likely NOT conflict with your system PA's files. This is because our development PA build does not know the right path to look for /var/lib/dbus/machine-id. Because of this, the prefix used on files will default to the host name of your machine, not the string of apparently random numbers and letters that you may see in there already. If you cross reference, the output from cat /var/lib/dbus/machine-id will show the same number as used here. We do this to ensure we can have separate preferences for different machines when your home directory is shared over e.g. NFS - the machine-id is more stable than the hostname which is why we prefer that as a prefix.

Running a Client App

So now that everything is running, you should be able to run a client application. As the build tree comes with some utilities you can run them directly from there:

[[email protected] build (master)]$ src/paplay -vv /usr/share/sounds/ia_ora-startup.wav

Opening a playback stream with sample specification 's16le 2ch 22050Hz' and channel map 'front-left,front-right'.

Connection established.

Stream successfully created.

Buffer metrics: maxlength=4194304, tlength=176400, prebuf=174640, minreq=1764

Using sample spec 's16le 2ch 22050Hz', channel map 'front-left,front-right'.

Connected to device alsa_output.pci-0000_00_1b.0.analog-stereo (0, not suspended).

Stream started.

Stream underrun.

Playback stream drained.: 1007045 usec.

Draining connection to server.

If, however you want to run a more advanced client application, then you need to employ a little hack to tell your system to use your development version of libpulse. This is quite trivial:

[[email protected] build (master)]$ export LD_LIBRARY_PATH=$(pwd)/src/.libs

[[email protected] build (master)]$ mplayer /path/to/your/fav.mp3

...

Easy eh? That's all you need to do to run PulseAudio from git. You can now easily try out patches, write your own modules and help contribute! Happy hacking.

Some notes on Overlinking

So, just before I sign off, I thought it was best to mention overlinking. PulseAudio itself uses a shared library that is used by both client and server. This library is "libpulsecommon-0.9.x.so". Client applications should NOT link to this file directly - instead libpulse will load it in for you. This can lead to some strange results. e.g. consider the following output:

[[email protected] ~]$ ldd `which paplay` | grep pulse

    libpulse.so.0 => /usr/lib64/libpulse.so.0 (0x00007f5bd9fc7000)

    libpulsecommon-0.9.21.so => /usr/lib64/libpulsecommon-0.9.21.so (0x00007f5bd9d76000)

[[email protected] ~]$ ldd `which mplayer` | grep pulse

    libpulse.so.0 => /usr/lib64/libpulse.so.0 (0x00007f617c1f4000)

    libpulsecommon-0.9.21.so => /usr/lib64/libpulsecommon-0.9.21.so (0x00007f6175f08000)

This looks more or less the same right? Not quite. Compare this to:

[[email protected] ~]$ objdump -p `which paplay` | grep pulse

  NEEDED               libpulse.so.0

  NEEDED               libpulsecommon-0.9.21.so

  required from libpulse.so.0:

[[email protected] ~]$ objdump -p `which mplayer` | grep pulse

  NEEDED               libpulse.so.0

  required from libpulse.so.0:

So what you can see here is that my paplay really does need both, but mplayer actually only does not directly need libpulsecommon-0.9.21.so. But what does this mean to you when running things? Well, due to the fact that PulseAudio has this kind of circular dependancy internally, we cannot use the --no-undefined or --as-needed build options. This means that the PulseAudio package is Over linked. This is why the paplay utility needs libpulsecommond-0.9.21.so directly, unlike mplayer, which does not.

So if you try and use the above guide and ultimately run the system provided paplay utility, you'll find you run into problems. This is because the system libpulsecommon-0.9.21.so will be used, not your freshly compiled version (which could have a completely different version number - e.g. libpulsecommon-0.9.19.so!).

While we don't need to run the system paplay (as we have built our own version), it's easy to forget this quirk and break things. If you want to be sure, you can place a symlink in your build folder to fool the system into loading your libpulsecommon, even when the versions don't "match". As this is an overlinking problem, there is little danger in doing this hack:

[[email protected] build (master)]$ ln -s libpulsecommon-0.9.19.so src/.libs/libpulsecommon-0.9.21.so

[[email protected] build (master)]$

This puts the necessary symlink in place to make my dev build (0.9.19) replace the system build (0.9.21). This only has effect with the LD_LIBRARY_PATH variable set, so it wont interfere with anything on your system.

Depending on your your distro packages things, the problems of overlinking may be present in more than just the paplay utility. So check this out and use objdump -p to confirm the client application you want to run is linked correctly and use the symlink hack if needed.