Dell XPS13/XPS15 white noise via audio

Just a quick post to make a copy of a script that I’d rather not lose. By default, the XPS15 has a fairly quiet white noise hiss when using headphones without any sound playing. Someone linked me to this script and I wanted to reproduce it here just in case I need it in future.

Save it as white-noise-fix.py and run with sudo python white-noise-fix.py.

#!/usr/bin/env python

import os
import struct
from fcntl import ioctl

def __ioctl_val(val):
  # workaround for OverFlow bug in python 2.4
  if val & 0x80000000:
    return -((val^0xffffffff)+1)
  return val

IOCTL_INFO = __ioctl_val(0x80dc4801)
IOCTL_PVERSION = __ioctl_val(0x80044810)
IOCTL_VERB_WRITE = __ioctl_val(0xc0084811)

def set(nid, verb, param):
  verb = (nid << 24) | (verb << 8) | param
  res = ioctl(FD, IOCTL_VERB_WRITE, struct.pack('II', verb, 0))  

FD = os.open("/dev/snd/hwC1D0", os.O_RDONLY)
info = struct.pack('Ii64s80si64s', 0, 0, '', '', 0, '')
res = ioctl(FD, IOCTL_INFO, info)
name = struct.unpack('Ii64s80si64s', res)[3]
if not name.startswith('HDA Codec'):
  raise IOError, "unknown HDA hwdep interface"
res = ioctl(FD, IOCTL_PVERSION, struct.pack('I', 0))
version = struct.unpack('I', res)
if version < 0x00010000:    # 1.0.0
  raise IOError, "unknown HDA hwdep version"

# initialization sequence starts here...

set(0x0c, 0x300, 0x5180) # 0x0c035180 (SET_AMP_GAIN_MUTE)
set(0x0c, 0x300, 0x6180) # 0x0c036180 (SET_AMP_GAIN_MUTE)

os.close(FD)

xmonad: Bind XF86Audio keys with EZConfig

I used to just run gnome-settings-daemon to handle my media keys, but as of Ubuntu 14.10 it’s stopped working. I figured that it was about time that I managed them properly by binding keys in my Xmonad config.

myBindings =
    [ ("<XF86AudioMute>"  , spawn "amixer -q -D pulse sset Master toggle")
    , ("<XF86AudioRaiseVolume>"  , spawn "amixer -q -D pulse sset Master 10%+ unmute")
    , ("<XF86AudioLowerVolume>"  , spawn "amixer -q -D pulse sset Master 10%- unmute")
    , ("<XF86AudioPlay>"  , spawn "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause")
    ]

There are other bindings in there too, but these are the ones we’re interested in. We use amixer to set the volume on our audio device. It’s all fairly straightforward, but you might have to work out what your output device is called if you have multiple. For me, it was called Master (which is the default).

As a little bonus, I even managed to get the play/pause button to control Spotify via dbus. To achive this, we use dbus-send and send the PlayPause command

dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause

Extract keys using JQ

This is probably something very specific to my use case, but I was working with some JSON that looked something like this:

{
  "something": {
    "Identifying Key": [
      {
        "foo": "a.b.c",
        "bar": "First Three"
      },
      {
        "foo": "a.b.d",
        "bar": "Second Three"
      }
    ],
    "Another Key": [
      {
        "foo": "z.b.c",
        "bar": "First Three, Take Two"
      },
      {
        "foo": "z.b.d",
        "bar": "Second Three, Take Two"
      }
    ]
  }
}

From this, I wanted to extract everything before the first period in every instance of the foo key. Like I said, very specific use case.

To do it, I built the following jq expression.

cat data.json | jq -r '.something | map(.[].foo | split(".")[0]) | unique | join("\n")'

Breaking that down:

# Select the top level namespace
cat data.json | jq -r '.something'

# Map over everything as key => value
cat data.json | jq -r '.something | map(.)'

# From each of those elements, step in to each array
cat data.json | jq -r '.something | map(.[])'

# And extract the foo key
cat data.json | jq -r '.something | map(.[].foo)'

# Inside the map, use "split" to split the string on a "."
cat data.json | jq -r '.something | map(.[].foo | split("."))'

# And only select the first element in the returned arrays
cat data.json | jq -r '.something | map(.[].foo | split(".")[0])'

# We only want to know about unique keys
cat data.json | jq -r '.something | map(.[].foo | split(".")[0]) | unique'

# And we want it as a string, not an array
cat data.json | jq -r '.something | map(.[].foo | split(".")[0]) | unique | join("\n")'

And with that, I have a unique list of values extracted from a specific key in an object. As I mentioned, it’s very specific to my use case but it might help someone in the future