Showing posts with label Fix. Show all posts
Showing posts with label Fix. Show all posts

Monday, June 23, 2014

Taming Pulseaudio

Taming PulseAudio

PulseAudio is a sound system for Linux.  It offers a few nice features, such as per-application volume control, hot-swapping input and output devices, and more cool stuff, all through an easy-to-use GUI.  Sounds great, but there's a catch: it's broken.  Actually, to be fair, PulseAudio isn't the only thing broken; all of Linux sound is broken.  From the pieces I've been able to glue together, here's enough of the story to understand what I'm talking about.

If you're just here for the guide, scroll down until the part after a large gap.  If you also want to know what the problems are, then you only have to skip until the end of the indented section.
Sound on Linux started with a system called OSS, or Open Sound System.  It was used not just by Linux but by BSD and I think even early versions Mac OS X.  OSS was very simplistic, to the point that only one application at a time could use sound, but it worked.  OSS's limitations could be bypassed by using a sound server.  ESD, Enlightened Sound Daemon, is one such sound server.  For a program to use ESD, the program had to be rewritten to use it.  Thus, you'd see programs coded to use both ESD and OSS as a fallback, as well as another sound server, aRts.  Three different sets of code each for different audio setups.  There had to be a better way.
The better way was ALSA.  It was conceived as a replacement for OSS, as OSS was stagnating in development or something like that.  It had everything from a brand new driver system to the ability to have multiple programs use sound at once without a sound server.  In theory, ALSA should have solved everyone's problems.  In practice, all this ended up doing is dividing the BSD and Linux communities, as ALSA was Linux-only while OSS was cross-platform.  Also, all it accomplished was adding yet another audio system for programmers to code for. 
Eventually, things progressed to the point that programs were dropping support for anything but ALSA.  The problem of Linux audio seemed to be solved, but there were two issues.  First, the BSD folks were getting upset because many of the newest and newest versions of programs weren't compatible with their system anymore.  Second, there were a few features some users wanted which ALSA couldn't provide, but a sound server could.  Third, programmers started to get really frustrated at how complicated ALSA is to code around. 
Enter PulseAudio.  PulseAudio is a sound server implemented on top of ALSA and OSS alike.  According to their wiki, it runs on Linux, Solaris, BSD, Mac OS X, and Windows 2000 and XP.  Basically, every relavent operating system can have it's sound work across all operating systems by using PulseAudio, solving the sound fragmentation issue between the open-source operating systems, and providing an allegedly-better coding experience compared to ALSA. 
What happened when ALSA replaced OSS is happening now with apps being programmed to support only PulseAudio and no longer directly use ALSA.  One such example is Skype for Linux.  Starting with version 4.3, PulseAudio is the only supported sound system.  As of writing this guide, that's the only example I can name, as currently most apps have support for both ALSA directly and PulseAudio.
In summary, PulseAudio is swinging on by to be the superhero and fix Linux's audio problems.  And yet, some programs don't want PulseAudio to save them.  One major example in my case is Wine.  Wine is a fake, fully-reprogrammed version of Windows made to be installed into Linux, BSD, or Mac OS X so that they can run Windows programs.  What this means in the realm of sound is that Wine has to write a program which translates the windows sound APIs used by windows programs into those used by the guest operating systems.  There's some holdup with getting a translation layer between PulseAudio and Windows Audio completed, meaning that Wine is one of the only major Linux programs not compatible with PulseAudio, yet fully compatible with ALSA.

The easiest way to solve PulseAudio's problems is to run PulseAudio and ALSA side-by-side.  Technically speaking, PulseAudio runs on top of ALSA and can't run without it, so they already do run side-by-side.  Practically speaking, they don't, because if PulseAudio is running, then no other program can use ALSA.  At least, that's how it works with the default configuration.  We'll be bypassing this with a custom configuration.

What's going wrong here is that PulseAudio, by default, does two very stupid things while attempting to be smart.  The first is grabbing complete, exclusive control of your sound card, done by attempting an automatic detection of all sound devices in your computer.  The proper fix is to modify PulseAudio's code to NEVER take exclusive control of auto-detected devices; instead we'll just edit settings to work around this problem.  The second stupid thing PulseAudio does is an attempt to work around this first problem.  PulseAudio includes an "ALSA compatibility layer", which from here on out will be referred to as a hijacker.  What this does is attempt to make any program which tries to use ALSA use PulseAudio instead through a translation layer.  Except this translation layer is just imperfect enough to cause migraines.  The proper fix is to fix the translation layer, but considering it hasn't been done yet, I doubt it'll ever be done; instead we'll be nuking the thing.  Speaking of which, let's get on to that guide.



This is a guide for allowing programs to play sound through ALSA and PulseAudio simultaneously.  Apps supporting PulseAudio will play sound through PulseAudio and apps not supporting PulseAudio will play through ALSA, bypassing any problems caused by certain programs such as Wine not supporting PulseAudio.  It was written for Lubuntu 14.04, but should translate well into any Ubuntu-derived or Debian-derived distribution of Linux, and shouldn't be too far off from what you're supposed to be doing in other distributions.

STEP 0: Install Pulseaudio.
A. Open a Terminal.
B. sudo apt-get install pulseaudio

STEP 1: Secure a program which can use both PulseAudio and ALSA by user choice.
One such example is the audio player Audacious.
A. Open a Terminal.
B. sudo apt-get install audacious

STEP 2: Configure your program to use ALSA and try to play a sound.
If you're using Audacious, the preferences menu makes this really easy.  Once set to ALSA, try to play a sound.  The program should throw up an error message.  If it somehow works, double check to see if it's configured for ALSA.  If it is, then PulseAudio's ALSA hijacker is active, a hijacker which needs to be crushed.

STEP 3: Disable PulseAudio's ALSA hijacker.
A. Open a terminal.
B. cd /usr/share/alsa/alsa.conf.d
C. sudo rm *pulse*
Now, reopen your test program and try again in ALSA mode.  Now it should be throwing up that error message.

STEP 4: Edit Pulseaudio's Configuration.
A. Check if ~/.config/pulse/default.pa exists.
If it does, open it with a text editor.
If it doesn't, open /etc/pulse/default.pa, and save it as ~/.config/pulse/default.pa.
B. Around line 44, you'll see something like this:
### Load audio drivers statically
### (it's probably better to not load these drivers manually, but instead
### use module-udev-detect -- see below -- for doing this automatically)
#load-module module-alsa-sink
#load-module module-alsa-source device=hw:1,0
#load-module module-oss device="/dev/dsp" sink_name=output source_name=input
#load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
#load-module module-null-sink
That comment block is full of crap.  Uncomment the two lines related to ALSA by deleting the # at the front.  Also, remove the device=whatever parts of the lines you uncommented if they're present.
NOTE: If you're using a custom .asoundrc, this may or may not work as-is, but it should get you on the right track. If you're not or you have no idea what I mean by .asoundrc, ignore this; you're fine.
C. Save.

STEP 5: Restart Pulseaudio.
A. Open a terminal
B. pulseaudio -k

STEP 6: Try out your test program.
Your program sould be perfectly able to play sound when configured for both ALSA and PulseAudio.

Congratulations, you just made PulseAudio infinitely better!  The one downside is that ALSA-only programs can't use PulseAudio's cool features, but at least they'll be able to play sound, something they couldn't do before!

Thursday, April 14, 2011

Okay, WTF SDL?!

Linux gaming is one of those things that you just don't see.  Part of it is the wrongly perceived lack of profitability, and another part of it is the Free Software Fanatics Foundation (who are so for free software, that some of them come off as against the right of developers to make closed-source software).  However, there are rare occasions where a game for Linux actually gets released, and in this case, three at once with one preordered so that you'll receive it in the future when it's finished.  But there's a problem with all three of the currently-released games mentioned above: SDL.

SDL is a cross-platform multimedia framework.  In layman's terms: games use it because it does a lot of work for the developers, such as video and sound processing, as well as obtaining and analyzing user input from keyboards, mice, controllers, and other things like that.  Generally, it does a very good job of doing this, but there's one MASSIVE flaw in it:  It has a nasty habit of ensuring that alt-tab and other very useful keyboard shortcuts don't and can't work while playing a game in Linux.

The reason for this is a massive programming oversight.  It's related to the programming function SDL_WM_GrabInput.  What this does is "grabs" the mouse.  It's referred to that because it takes the mouse and holds on to it like a child, saying, "you can't have it!  It's mine!"  Only there's a good reason that it's doing that; this makes sure that the mouse doesn't go flying out of the game window or runs into an invisible edge.  This is especially important in First-Person Shooters, where you could be turning to aim at an enemy, and suddenly stop because your hidden mouse cursor hit the edge of the screen, leading to the enemy humiliatingly cherry-tapping you to death.  So, how is something related to the mouse somehow blocking Alt-Tab from working?  That's the oversight I'm referring to.  SDL on Windows and Mac (and probably others) only grabs the mouse when using that function, but SDL on Linux also grabs the keyboard, so that other applications, such as, you know, THE PART OF THE DESKTOP ENVIRONMENT THAT CONTROLS KEYBOARD SHORTCUTS, can't use it.  Unlike with grabbing the mouse, there is no logical reason to grab the keyboard.  In addition, this is a massive inconsistency in the cross-platform implementation of the command.

Thank God SDL is open-source, because the only solution is to edit the source code.  Thankfully for you, I've already done this for you.  You can download a precompiled 32-bit binary build, it's source code, and a patch file from my age-old GameFront account that somehow is still valid.  The following instructions are for people masochistic enough to want to do it completely themselves:

  1. Download SDL's source code from here and extract it somewhere easy like the desktop.
  2. Open a folder view to the source code directory.
  3. Browse to src/video/x11/
  4. Open SDL_x11wm.c
  5. Scroll down to function X11_GrabInputNoLock
  6. Comment the two lines below this comment "/* Now grab the keyboard */"
    1. To do this, just type // in front of them.
  7. Verify that your changes match this image, except without the obvious image edits I did.
  8. Navigate to the main SDL directory.
  9. Open a terminal here.
  10. Type in ./configure.
    1. ONLY IF YOU GET ERRORS: generally those errors will be a missing something error.  These can be resolved by downloading the necessary files through your distribution's package manager.  So do that, then go back to step 9 and keep trying it until it doesn't give you an error.
  11. IF YOU DIDN'T GET ANY ERRORS WITH STEP 10: Type in make
  12. In your terminal, type in make install. 
    1. IF YOU GET A PERMISSIONS ERROR: look up how to run a command as root on your distribution.  For most, it should be as simple as typing in sudo in front of it, like this:
      sudo make install
    2. IF YOU GET A COMPILING ERROR: You're screwed.  Sorry.  Maybe you can ask around somewhere, but don't expect any help from me.
This hacked version of SDL is now installed.  However, you may not be finished yet.  If any game comes with its own SDL binaries, you will have to delete them to proceed.  If they still don't work right, then follow these instructions:
  1. Open a folder view to the main SDL directory
  2. Navigate to the "build" directory.
  3. Navigate to the ".libs" directory.
    1. IF YOU DON'T SEE ".libs": Tell your file browser to show hidden files and folders.
      1. In Nautilus (GNOME), this can be done by pressing ctrl+H
      2. In Dolphin (KDE), I think (unsure) this can be done by pressing ctrl+.  Or maybe alt+.  I don't remember.
  4. Copy and paste "libSDL-1.2.so.0.11.3" somewhere easy like the desktop.
    1. IF YOU CAN'T FIND THAT EXACT FILE: It's probably the file with the most similar name.  A newer or otherwise modified source code may produce one with a different file name.
  5. Rename the file to "libSDL-1.2.so.0"
  6. Copy and paste "libSDL-1.2.so.0" into the game's binary directory, where the included SDL binaries were.
Your games should now work without the massive flaw.

If you benefited from this, please share this link around.  I want to actually help people who have this issue, and not just myself.  Feel free to package up my hacked SDL and share it.  I really don't care what you do with it.  I don't care if I don't get any credit for it.  I just want to help.   Just be sure to keep the LGPL license, so that SDL's developers don't get mad at anybody.

    Copyright Notice:

    All text (unless otherwise attributed) is copyright (C) 2011-2014 Joel "iLag" Hammond and licensed under the CC BY-SA 3.0 License.
    Creative Commons License