Reusable alsa-lib part

The variable ${SNAPCRAFT_PROJECT_NAME} gets saved unexpanded into the alsa-lib binary :frowning: It does expand while it’s running the install phase of the compile, so the files do appear in the right place, just that alsa-lib can’t find them at runtime because it searches with literal ${SNAPCRAFT_PROJECT_NAME} and not the project’s name.

Just add them to the wiki here.

Snapcraft just passes the environment keyword through to snapd without replacing variables there. We probably should, please log a bug. We need to be particularly careful not to actually evaluate variables (e.g. $PATH needs to be passed through verbatim to snapd), but we should replace the $SNAPCRAFT_* variables.

This is using the variable in configflags that is the problem because autotools is seeing the input of “${SNAPCRAFT_PROJECT_NAME}” and NOT “audacity” for example.

This part will install alsa and provide a wrapper script for overriding the default configuration to force all alsa audio requests to be processed through pulseaudio thereby allowing snaps to not require the alsa plug. I plan on pushing this to github and exposing as a remote part once it’s had some more testing. The launcher script is called pulsify-alsa and can be chained with the desktop-launch script:

apps:
  example:
    command: desktop-launch pulsify-alsa $SNAP/bin/echo "example"

parts:
  alsa-lib:
    plugin: autotools
    source: http://archive.ubuntu.com/ubuntu/pool/main/a/alsa-lib/alsa-lib_1.1.3.orig.tar.bz2
    # source: ftp://ftp.alsa-project.org/pub/lib/alsa-lib-1.1.5.tar.bz2
    configflags:
    - --prefix=/usr
    - --sysconfdir=/etc
    - --libexec=/usr/lib
    - --libdir=/usr/lib
    - --localstatedir=/var
    - --with-configdir=/snap/$SNAPCRAFT_PROJECT_NAME/current/usr/share/alsa
    - --with-plugindir=/snap/$SNAPCRAFT_PROJECT_NAME/current/usr/lib/alsa-lib
    - --disable-static
    organize:
      snap/*/current/usr/lib/*: usr/lib/
    stage:
    - usr/include
    - usr/lib
    prime:
    - -usr/bin
    - -usr/include
    - -usr/lib/pkgconfig
    - -usr/share/alsa/alsa.conf
    - -usr/share/alsa/pcm
    - -usr/share/alsa/topology/broadwell

  alsa-plugins:
    after: [alsa-lib]
    plugin: autotools
    source: http://archive.ubuntu.com/ubuntu/pool/main/a/alsa-plugins/alsa-plugins_1.1.1.orig.tar.bz2
    # source: ftp://ftp.alsa-project.org/pub/plugins/alsa-plugins-1.1.5.tar.bz2
    configflags:
    - --prefix=/usr
    - --sysconfdir=/etc
    - --libexec=/usr/lib
    - --libdir=/usr/lib
    - --localstatedir=/var
    - --disable-oss
    - --disable-usbstream
    - --disable-arcamav
    - --disable-avcodec
    - --with-plugindir=/snap/$SNAPCRAFT_PROJECT_NAME/current/usr/lib/alsa-lib
    - --disable-static
    organize:
      snap/*/current/usr/lib/*: usr/lib/
    stage:
    - usr/lib
    - usr/share/alsa
    build-packages:
    - libpulse-dev
    stage-packages:
    - libpulse0

  alsa:
    plugin: nil
    after: [alsa-plugins, alsa-lib]
    prepare: |
      cat > alsa.conf <<EOF
      pcm.!default {
        type pulse
        fallback "sysdefault"
        hint {
          show on
          description "Default ALSA Output (currently PulseAudio Sound Server)"
        }
      }

      ctl.!default {
        type pulse
        fallback "sysdefault"
      }
      EOF

      cat > pulsify-alsa <<EOF
      #!/bin/bash
      if [ "\$SNAP_ARCH" == "amd64" ]; then
        ARCH="amd64-linux-gnu"
      elif [ "\$SNAP_ARCH" == "armhf" ]; then
        ARCH="arm-linux-gnueabihf"
      elif [ "\$SNAP_ARCH" == "arm64" ]; then
        ARCH="aarch64-linux-gnu"
      else
        ARCH="\$SNAP_ARCH-linux-gnu"
      fi
      export LD_LIBRARY_PATH="\$SNAP/usr/lib/alsa-lib:\$SNAP/usr/lib/\$ARCH/pulseaudio:\$LD_LIBRARY_PATH"
      export ALSA_CONFIG_PATH="\$SNAP/etc/alsa.conf"
      exec "\$@"
      EOF
    install: |
      install -m644 -D -t $SNAPCRAFT_PART_INSTALL/etc alsa.conf
      install -m755 -D -t $SNAPCRAFT_PART_INSTALL/bin pulsify-alsa

cc/ @Wimpress: this the finalised version of the code I was working on for Audacity at the Snapcraft Summit, which is a much more self-contained with everything needed included within the yaml itself - no external files.

https://media.giphy.com/media/9WYFlL64sSM2Q/giphy.gif

4 Likes

What exactly happened after this? I am trying to create a snap here using this part but it’s not working, no sound. an example game to test could be the Windows download here.

What happend after this: I created a “remote part” to contain as much of the implementation as possible. You can find it at:

There are instructions in the README.md on how to use. Note that there is still a lot of boilerplate code which is currently required due to problems with snapcraft, such as the launchpad bug #1766878

1 Like

Is it possible to call aplay directly using this workaround?

I’m following the steps in your github, and apart from that, since I need to call aplay directly I’m adding alsa-utils as a “stage-package” in my part. This is is how it looks (I’m avoiding to stage those files because otherwise the part building fails with : “Failed to stage: Parts ‘alsa-lib’ and ‘my-part’ have the following files, but with different contents”)

 my-part:
    plugin: dump
    source: foo/bar/baz
    source-type: local
    stage-packages: [alsa-utils]
    stage: 
      - -usr/lib/libasound.so
      - -usr/share/alsa/alsa.conf
      - -usr/share/alsa/cards/USB-Audio.conf
      - -usr/share/alsa/cards/aliases.conf
      - -usr/share/alsa/pcm/dmix.conf
      - -usr/share/alsa/pcm/dsnoop.conf
      - -usr/share/alsa/pcm/surround21.conf
      - -usr/share/alsa/pcm/surround40.conf
      - -usr/share/alsa/pcm/surround41.conf
      - -usr/share/alsa/pcm/surround50.conf
      - -usr/share/alsa/pcm/surround51.conf
      - -usr/share/alsa/pcm/surround71.conf
    after: [alsa, desktop-glib-only]

This build the snaps successfully, but when calling aplay from inside the snap it returns:

ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM sysdefault
aplay: main:722: audio open error: No such file or directory

Found why this was failing. Apparently having pulseaudio installed in the host is mandatory to make this work. Could you confirm this, @lucyllewy ? On the other hand, correct me if I’m mistaken but, doesn’t this completely breaks the confinement/isolation aimed by the snaps?

I created the alsa remote part for the specific purpose of enabling at least some sound functionality on an application that requires alsa. Per the rules of security the alsa plug is restricted because it enables a high level of access to the system. Therefore the alsa part is designed to redirect the audio through pulseaudio which doesn’t expose such a large hole in your system. Because of this you do need pulseaudio running on your host, which is standard on virtually all distributions.

1 Like

Ok, thanks for the explanation and for the work done in the remote part, now I understand the decision. :wink:

? can alsa-utils be added, along with your alsa-lib in one snap

I am using “Ubuntu Core 16”

You can achieve a much more compatible system with a configuration like below, to which you can add distribution-provided alsa-utils:

base: core

parts:
  alsa:
    plugin: nil
    source: https://github.com/diddledan/snapcraft-alsa.git
    override-pull: |
      cat > alsa.conf <<EOF
      pcm.!default {
        type pulse
        fallback "sysdefault"
        hint {
          show on
          description "Default ALSA Output (currently PulseAudio Sound Server)"
        }
      }
      ctl.!default {
        type pulse
        fallback "sysdefault"
      }
      EOF
    override-build: |
      install -m644 -D -t $SNAPCRAFT_PART_INSTALL/etc alsa.conf
    build-packages:
      - libasound2-dev
    stage-packages:
      - libasound2
      - libasound2-plugins
      # - alsa-utils # uncomment this to add alsa-utils

  your-app-part:
    after: [alsa]
    ...

layout:
  /etc/asound.conf:
    bind-file: $SNAP/etc/alsa.conf
  /usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib:
    bind: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib
  /usr/share/alsa/alsa.conf:
    bind-file: $SNAP/usr/share/alsa/alsa.conf
1 Like

Thanks

If my-snap needed to also provide “python module alsaaudio”
? could I stage the libs needed from alsa-lib
or should I make them build packages.

You may do either of these options.

I am looking at the alsa-utils command-aplay.wrapper

? what is the 3rd export perpose
? how was it created

#!/bin/sh
export PATH="$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/arm-linux-gnueabihf:$SNAP/usr/lib/arm-linux-gnueabihf"
export LD_LIBRARY_PATH="$SNAP/usr/lib:$SNAP/usr/lib/arm-linux-gnueabihf:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH=$SNAP_LIBRARY_PATH:$LD_LIBRARY_PATH
exec “$SNAP/usr/bin/aplay” “$@”

Hello daniel @lucyllewy

I am using your implementation of ( parts: alsa ).

It cant find a pulse lib ( and I do not have pulse audio installed locally ).
But I did notice, the snap does have this pulse lib.
? is there a way to point ALSA to my snaps libs.

$SNAP/usr/bin/aplay -v --file-type=wav $HOME/one-for-shorty.mp3

ALSA lib dlmisc.c:254:(snd1_dlobj_cache_get) Cannot open shared library /usr/lib/arm-linux-gnueabihf/alsa-lib/libasound_module_pcm_pulse.so
aplay: main:788: audio open error: No such device or address

find $SNAP -name libasound_module_pcm_pulse.so
/snap/dkentry-python3/x1/usr/lib/arm-linux-gnueabihf/alsa-lib/libasound_module_pcm_pulse.so

I do have the below in my snap

passthrough:
layout:
/etc/asound.conf:
bind-file: $SNAP/etc/alsa.conf
/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib:
bind: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib
/usr/share/alsa/alsa.conf:
bind-file: $SNAP/usr/share/alsa/alsa.conf

If you don’t have pulseaudio on your host then you want a different setup than my alsa via pulseaudio scheme.

Regarding the missing libraries, you need to ensure you’ve staged libasound2-plugins.

Yes, below is what I have in stage-packages:
stage-packages:
- libasound2
- libasound2-plugins
- alsa-utils # uncomment this to add alsa-utils

It is in my snap
ls /snap/dkentry-python3/x1/usr/lib/arm-linux-gnueabihf/alsa-lib/libasound_module_pcm_pulse.so

and the layout is putting it in
ls /usr/lib/arm-linux-gnueabihf/alsa-lib/libasound_module_pcm_pulse.so

A lot has changed on Snapcraft world, and I am trying to understand… What’s the status of this remote part as of snapcraft version 3.8 ? Should I still use or not? How do I include this in the current snapcraft.yaml scheme? @lucyllewy

Right now I have:

Failed to get part information: Cannot find the definition for part 'alsa'.

I’ve written documentation at https://snapcraft-alsa.readthedocs.io/en/latest/. You have two options:

  1. Copy the required yaml into your snapcraft.yaml manually
  2. Convert to using jsonnet to build your snapcraft.yaml and use the alsa-lib jsonnet extension. Compile your jsonnet to yaml using my sc-jsonnet utility.