Mianzhi Wang

Ph.D. in Electrical Engineering

Setting Up WSL with Graphics and Audio


What is Windows Subsystem for Linux (WSL)?

Window Subsystem for Linux (WSL) is an optional feature of Windows 10. It enables running unmodified Linux binaries in Windows without creating a virtual machine. It implements a compatibility layer that translates Linux system calls to Windows system calls. Basically, it is like a "wine" on Windows for Linux executables. Therefore, WSL can be very convenient if you need to run some Linux only program in a Windows development environment. You no longer need the overhead to boot up a virtual machine (or even worse, switching between Windows and Linux on a dual boot system).

While many Linux programs runs fine under WSL, it does have its limitations:

  • Because not all system calls have been implemented, not all Linux programs will run flawlessly under WSL. You can track the updates of WSL by following the WSL blog. You can also check this community maintained list of programs that work (and those that don't) under the WSL.

  • Not all hardware resources are available in WSL. For instance, you cannot access GPUs in WSL. Consequently, numerical computations in WSL can only be done on CPU (actually CPU performance is pretty good in WSL). You can upvote for GPU support here.

  • Disk IO is slower compared with native Linux installations. As a result, compilations feel slower in WSL. Having a SSD may alleviate this issue, but the overall disk performance is not good enough.

Despite the above limitations, WSL is still a very helpful add-on to Windows 10. The WSL team definitely put a lot of hard work into it.

Installation

For reference, I have the Windows Fall Creators Updated installed, and I will use the Ubuntu distro as an example. If you use a different distro, you may need some additional tweaks.

After the Windows 10 Fall Creators Update, WSL is out of beta and the installation is much easier. To enable WSL, you just need to turn on Windows Subsystem for Linux among Windows Features, and install your preferred distro from the Windows Store. A more detailed guide can be found on MSDN.

Accessing Windows Files

Accessing Windows files from WSL is quite straightforward. By default, all your drives are mounted automatically. For instance, the Users folder under C:\ can be accessed via /mnt/c/Users (note that casing matters under Linux).

Important: The Linux file system is stored in the LocalState folder of the Ubuntu app (the full path should look like %LocalAppData%\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState). While you can browser these files in Windows Explorer, do not make any modifications to them. Doing so may case loss of data under WSL, because these files contain additional attributes for interoperability which Windows Explorer may not understand.

Tweaking the Color Scheme

The default color scheme of Windows Console (cmd.exe) is not that great. Since the Fall Creators Update, Windows Console is give more love and a lot of improvements have been made. However, changing the color scheme using the default settings panel is still not an enjoyable experience. Luckily, the Windows Console team introduced the Windows Console Colortool recently, making changing color schemes much easier. It supports iTerm2 color scheme files, and you can find a bunch of nice color schemes here.

Running X Applications

WSL does not natively support graphics. Nevertheless, it is possible to run a X server on Windows and run X applications as clients under WSL. I am using VcXsrv as the X server. You may also use Xming or Cygwin/X. After installation, simply start the X server on Windows using the default settings. Under WSL, since we are connecting to an X server on the local machine, simply run export DISPLAY=:0.0 (you can add it to your .bashrc). Now you can use matplotlib (assuming that you have relevant packages installed) as shown in the screenshot below.

Note: Apparently, you can go even further by running Xfce 4 under WSL. However, not all graphics applications run flawlessly. Firefox and GNU Octave work fine for me.

Enabling Audio

WSL does not natively support audio devices. If you start Firefox under WSL, you will not hear anything. Neither will audio players work. Usually, audio support under WSL is unnecessary because Windows already provides better support for your music/video needs. If, for whatever reason, you want to hear audio playing under WSL, there is a way to do it. You will need to set up PulseAudio both under both Windows and WSL.

Setting Up PulseAudio on Windows

Setting up PulseAudio on Windows is quite straightforward:

  1. Download the pre-built binary package from the PulseAudio website.

  2. Extract the files to the location you prefer. You should see four folders named bin, etc, lib, and share.

  3. Edit the configuration files in etc. In default.pa, find the line starting with #load-module module-native-protocol-tcp and change it into:

     load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1
    

    In daemon.conf, find the line starting with ; exit-idle-time = 20 and change it to exit-idle-time = -1 to turn off idle timer.

  4. Run pulseaudio.exe under the bin folder in cmd (or powershell).

Setting Up PulseAudio in WSL

Setting up PulseAudio under WSL requires more work. If you already installed the pulseaudio software package, you will need to uninstall it (apt-get purge pulseaudio) first, because it will not work, and you are likely to see the following error message:

Assertion 'pthread_mutex_unlock(&m->mutex) == 0' failed at pulsecore/mutex-posix.c:108, function pa_mutex_unlock(). Aborting.

To install a version of PulseAudio that is compatible with WSL, you can either build it from source, or use PPA.

Install via PPA

Simply Add this PPA and install the patched version of PulseAudio. See this Github issue for more details.

Build from Source

  1. Assuming that you have build-essential installed, install at least following additional packages:

    • pkg-config
    • intltool
    • libtool
    • libsndfile1-dev
    • libjson-c-dev
  2. Download the source code of PulseAudio 8.0 from the official website. I chose version 8.0 here because Ubuntu 16.04 ships with this version and I failed to get later versions working under my setup.

  3. Unpack the source code and apply the one-line patch to src/pulsecore/mutex-posix.c. Find the following lines

    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    

    add #undef HAVE_PTHREAD_PRIO_INHERIT after them.

  4. Configure with the following options:

    CFLAGS="$CFLAGS -g -O0" ./configure     \
        --disable-bluez4                    \
        --disable-bluez5                    \
        --disable-rpath                     \
        --disable-asyncns                   \
        --disable-udev                      \
        --disable-systemd-daemon            \
        --without-caps                      \
        --enable-force-preopen
    

    Run make && make install. This will install PulseAudio to /usr/local/.

For more details, refer to the discussion mentioned above, this gist, and this automatic installation script.

After installing PulseAudio correctly, run export PULSE_SERVER=tcp:localhost to configure PulseAudio to run over TCP (you can also edit the PulseAudio configuration file). You should now be able to use cmus to play audio files. Here is a screenshot of Firefox Quantum playing YouTube videos with sound:

Now you should have set up WSL will both graphics and audio. Have fun playing with it 🎉