Sunday, February 12, 2012

Alsa: multiple output, multiple sound cards, multiple users

I had some difficulties setting up alsa as I wanted, because I encountered some troubles:
  • when more than one application was playing sound, the first one played nicely but the others wasn't playing at all, complaining about a "busy resource"
  • solved this one, I had to setup the whole thing to work with two sound cards at the same time
  • eventually, I wanted to enable concurrent sound for multiple users
Alsa Wiki's guides were useful only for a few things, but none of them gave me the whole solution. So after a deep digging, I ended up with this config:
pcm.USBmic {
    type hw
    card CNF8215
}

ctl.USBmic {
    type hw
    card CNF8215
}

pcm.internal {
    type hw
    card SB
}

ctl.internal {
    type hw
    card SB
}

pcm.wireless {
    type hw
    card Transceiver
}

ctl.wireless {
    type hw
    card Transceiver
}

pcm.internalDmixed {
   type dmix
   ipc_key 1024
   ipc_key_add_uid false
   ipc_perm 0666
   slave {
       pcm "internal"
       period_time 0
       period_size 2048
       channels 4
    }
    bindings {
       0 0
       1 1
       2 2
       3 3
    }
}

pcm.wirelessDmixed {
   type dmix
   ipc_key 2048
   ipc_key_add_uid false
   ipc_perm 0666
   slave {
       pcm "wireless"
       period_time 0
       period_size 2048
       channels 2
    }
    bindings {
       0 0
       1 1
    }
}

pcm.both {
    type route;
    slave.pcm {
        type multi;
        slaves.a.pcm "wirelessDmixed";
        slaves.b.pcm "internalDmixed";
        slaves.a.channels 2;
        slaves.b.channels 4;
        bindings.0.slave a;
        bindings.0.channel 0;
        bindings.1.slave a;
        bindings.1.channel 1;
      
        bindings.2.slave b;
        bindings.2.channel 0;
        bindings.3.slave b;
        bindings.3.channel 1;
        bindings.4.slave b;
        bindings.4.channel 2;
        bindings.5.slave b;
        bindings.5.channel 3;
    }
  
    ttable.0.0 1;
    ttable.1.1 1;
  
    ttable.0.2 1;
    ttable.1.3 1;
    ttable.2.4 1;
    ttable.3.5 1;
}

pcm.!default {
        type plug
        slave {
                pcm both
        }
}

ctl.!default {
        type hw
        card SB
}

How does this strange thing work? Let's look at it step by step:

Why Slackware and why this blog?

Slackware because it's:
  • lightweight
  • stable
  • highly configurable
  • hard to understand, which is useful to learn how to use linux. :)
At the moment I'm using 13.37, the last version, by the advice of Davide Bianchi (and if you never heard of him, go read the Tales from the Machine Room).

Why this blog? Because sometimes I discover a nice solution for a problem which is hard to find online, or I write a useful script, and a blog is a nice way to keep a handbook always accessible, from anywhere and by anyone. So let's cut the chatter and begin with the useful stuff! :)