Category Archives: unix

What are OSC terminal control sequences / escape codes?

Changelog for a recent release of SecureShell for Chrome
included a mention of “Support for iTerm2 OSC-9 growl notifications”. This is displayed in terminal when you’re SSHing into a machine, and this entry piqued my interest.

Turns out it’s from hterm’s changelog. And turns out hterm has a nice list of supported control sequences.

OSC are “operating system command” control sequences and there’s a few of them supported by hterm / SecureShell. I find a few super interesting (\033 being ESC in the doc linked above):

  • 0: set window title: echo -e "\033]0;This is the window title\a"
  • 9: show system notification (iTerm2 variant): echo -e "\033]9;This is the notification text\a"
  • 777: show system notification (rxvt-unicode / urxvt variant): echo -e "\033]777;notify;This is the notification title;This is the notification text\a"
  • 52: clipboard operation; hterm only supports c for copy: echo -e "\033]52;c;$(base64 <<< hello)\a"

Changing the default file manager away from Nautilus

Nautilus is opening the desktop, making the experience miserable under i3 when all you’re trying to do is ‘view files in directory’.

XFCE’s Thunar is lightweight, and it doesn’t try to create a desktop window.

To get apps such as Chrome to handle “open directory” commands using Thunar, teach xdg-mime about it:

$ sudo apt-get install thunar
$ xdg-mime query default inode/directory
$ xdg-mime default Thunar.desktop inode/directory  # yep, Thunar's desktop file is titlecased on Debian-derived systems
$ xdg-mime query default inode/directory
$ xdg-open .
...thunar opens...

This is sort-of a follow-up to my previous post on this topic. See also, Debian’s article about usage of MIME types.

But my dog does.

Migrating Prosody from text store and sqlite3 to PostgreSQL


  • You started off from the basic storage config:
    • Regular data is in filesystem.
    • mam (xep0313) message archive is in SQLite3.
  • You want to transition to using just PostgreSQL.
  • PostgreSQL version is 9.4.


# # largest version of pgsql you have
~# apt install postgresql-9.4-client

# # get lua-dbi module for pgsql
~# apt install lua-dbi-postgresql

Creating PostgreSQL user

# # PostgreSQL trusts users connecting over unix domain socket to be the
# # same as their local account.
# # Therefore, become postgres -- the admin account.
user:~$ sudo su postgres

# # run user creation
postgres:~$ createuser --interactive
# # name: prosody
# # no other administrative options

# # run postgresql client
postgres:~$ psql
-- create database

-- give the prosody user all rights on it
GRANT ALL ON DATABASE prosody TO prosody;

-- in case of connecting over network and using md5 trust,
-- set prosody account password:
ALTER ROLE prosody WITH ENCRYPTED PASSWORD 'here_some_password';

Over network?

Assuming you want to connect over the network, edit /etc/postgresql/9.4/main/pg_hba.conf. Append:

# type, database, user, address, auth method
host prosody prosody md5
  • Try to minimize your permitted netmask.
  • Can you configure a more secure auth method than md5? Do so.

Migrate data from filesystem

# # as prosody local user

prosody:$ cd prosody-hg/tools/migrator

# # overwrite the config.
prosody:$ cat > migrator.cfg.lua << _EOF
local data_path = "../../data";

input {
        type = "prosody_files";
        path = data_path;
output {
        type = "prosody_sql";
        driver = "PostgreSQL";
        database = "prosody";
        username = "prosody";
        password = "here_some_password";
        host = ""; -- this assumes network connection; migration with local user credentials was not attempted.

# # run the migrator in ~/prosody-hg/tools/migrator
prosody:$ lua prosody-migrator.lua input output

Migrate mam archive from SQLite3

# # as prosody user

prosody:~$ cd prosody-hg/data

# # Having first verified there is nothing in Prosody table...
prosody:$ sqlite3 prosody.sqlite 'SELECT COUNT(*) FROM prosody;'
# # ...drop prosody table. All its data (roster etc) was until now stored on the filesystem.
prosody:$ sqlite3 prosody.sqlite 'DROP TABLE prosody;'

# # dump and massage the sqlite3 output, piping it into psql.
# # psql authenticates as the 'prosody' user and does not require the password.
prosody:$ sqlite3 prosody.sqlite .dump | \
    grep -v 'BEGIN TRANSACTION;' | \
    grep -v sqlite_sequence | \
    awk '/CREATE TABLE/{gsub("`","\"");} 1' | \
    awk '/CREATE UNIQUE INDEX/{gsub("`","\"");} 1' | \

# # manual step 🙁
# # fix the autoincrement.
prosody:$ sqlite3 prosody.sqlite 'SELECT COUNT(*) FROM prosodyarchive;'
# # use this number + 1 in:
prosody:$ echo 'ALTER SEQUENCE prosodyarchive_sort_id_seq RESTART WITH 123456;' | psql

Update Prosody config

In prosody.cfg.lua:

storage = {
        archive2 = "sql";
sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "here_some_password", host = "" }

Getting sound and other panels in gnome-control-center outside GNOME

Missing some panels in gnome-control-center? No “Online Accounts”? No “Sound”?

Apparently, panels are defined through .desktop files in /usr/share/applications (!), and they mostly have the setting of OnlyShowIn=GNOME; or OnlyShowIn=GNOME;Unity;.

To trigger them appearing in, say, i3, xfce or similar, you need to pretend you’re actually running GNOME by exporting the XDG_CURRENT_DESKTOP variable with the value of GNOME.

XDG_CURRENT_DESKTOP=GNOME gnome-control-center

Vidalia crashing on Ubuntu 14.04 due to incorrect AppArmor profile

This has been going unfixed for years now.

For me, the fix involved adding the following into /etc/apparmor.d/usr.bin.vidalia.

/usr/share/glib-2.0/schemas/ r,
/usr/share/glib-2.0/schemas/** r,

Then, I reloaded AppArmor /etc/init.d/apparmor reload and the contraption worked. If you get asked about your Tor control password, restart tor /etc/init.d/tor restart.

A PulseAudio primer, and setting up an equalizer

Once again, some notes for my own personal reference, which may help others as well. And if something is wrong, let me know.

Written only from the user’s perspective.

What is it?

Quoting from the description:

PulseAudio is a sound system for POSIX OSes, meaning that it is a proxy for your sound applications. It allows you to do advanced operations on your sound data as it passes between your application and your hardware. Things like transferring the audio to a different machine, changing the sample format or channel count and mixing several sounds into one are easily achieved using a sound server.

PulseAudio is designed for Linux systems. It has also been ported to and tested on Solaris, FreeBSD, NetBSD, MacOS X, Windows 2000 and Windows XP.

PulseAudio is an integral part of all relevant modern Linux distributions and used in various mobile devices by multiple vendors.

It’s running as a daemon. My understanding is that it runs in userspace.

Main concepts

PulseAudio is an audio graph. It uses a variety of modules to expose sinks and sources. Sinks and sources seem to be what Apple’s Core Audio, another audio graphing system, would all be “audio units”, where there could be some inputs, and some outputs. Here, sinks seem to be intended as playback devices, and input devices such as microphones are sources.

Clients can create sink inputs.

Main tools

As a user, main CLI tools used to interact will be pactl and pacmd. I’m fine with pactl, but pacmd seems to expose more options.

To view all objects known to PulseAudio, use pactl list.

Module #0
        Name: module-device-restore
        Usage counter: n/a
       = "Lennart Poettering"
                module.description = "Automatically restore the volume/mute state of devices"
                module.version = "4.0"

Module #1
        Name: module-stream-restore
        Usage counter: n/a
       = "Lennart Poettering"
                module.description = "Automatically restore the volume/mute/device state of streams"
                module.version = "4.0"


Module #21
        Name: module-filter-apply
        Usage counter: n/a
       = "Colin Guthrie"
                module.description = "Load filter sinks automatically when needed"
                module.version = "4.0"

Sink #0
        State: SUSPENDED
        Name: alsa_output.pci-0000_05_00.1.hdmi-stereo
        Description: GF108 High Definition Audio Controller Digital Stereo (HDMI)
        Driver: module-alsa-card.c
        Sample Specification: s16le 2ch 44100Hz
        Channel Map: front-left,front-right
        Owner Module: 5
        Mute: no
        Volume: 0:  84% 1:  84%
                0: -4.39 dB 1: -4.39 dB
                balance 0.00
        Base Volume: 100%
                     0.00 dB
        Monitor Source: alsa_output.pci-0000_05_00.1.hdmi-stereo.monitor
        Latency: 0 usec, configured 0 usec
                alsa.resolution_bits = "16"
                device.api = "alsa"
       = "10de"
       = "NVIDIA Corporation"
       = "0bea"
       = "GF108 High Definition Audio Controller"
                device.string = "hdmi:2"
                device.buffering.buffer_size = "65536"
                device.buffering.fragment_size = "32768"
                device.access_mode = "mmap+timer"
       = "hdmi-stereo"
                device.profile.description = "Digital Stereo (HDMI)"
                device.description = "GF108 High Definition Audio Controller Digital Stereo (HDMI)"
                alsa.mixer_name = "Nvidia GPU 14 HDMI/DP"
                alsa.components = "HDA:10de0014,10de0101,00100100"
                module-udev-detect.discovered = "1"
                device.icon_name = "audio-card-pci"
                hdmi-output-0: HDMI / DisplayPort (priority: 5900, not available)
        Active Port: hdmi-output-0

Sink #1
        State: SUSPENDED
        Name: alsa_output.pci-0000_00_1b.0.analog-stereo
        Description: Built-in Audio Analog Stereo
Source #2
        State: SUSPENDED
        Name: alsa_input.pci-0000_00_1b.0.analog-stereo
        Description: Built-in Audio Analog Stereo
        Driver: module-alsa-card.c
        Sample Specification: s16le 2ch 44100Hz
        Channel Map: front-left,front-right

Client #5
        Driver: protocol-native.c
        Owner Module: 11
       = "GNOME Volume Control Media Keys"
                native-protocol.peer = "UNIX socket client"
                native-protocol.version = "28"
       = "org.gnome.VolumeControl"
                application.icon_name = "multimedia-volume-control"
                application.version = "1.0"
       = "30127"
                application.process.user = "ivucica"
       = "MYHOSTNAME"
                application.process.binary = "unity-settings-daemon"
                application.language = "en_US.UTF-8"
                window.x11.display = ":0"
                application.process.machine_id = "MYMACHINEID"
                application.process.session_id = "c14"

Card #1
        Name: alsa_card.pci-0000_00_1b.0
        Driver: module-alsa-card.c
        Owner Module: 6
                alsa.card = "0"
                alsa.card_name = "HDA Intel PCH"
                alsa.long_card_name = "HDA Intel PCH at 0xef340000 irq 86"
                alsa.driver_name = "snd_hda_intel"

Sink Input #0
        Driver: protocol-native.c
        Owner Module: 11
        Client: 7
        Sink: 1
        Sample Specification: s16le 2ch 44100Hz
        Channel Map: front-left,front-right
        Format: pcm, format.sample_format = "\"s16le\""  format.rate = "44100"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
        Corked: no
        Mute: no
        Volume: 0: 100% 1: 100%
                0: 0.00 dB 1: 0.00 dB
                balance 0.00
        Buffer Latency: 60408 usec
        Sink Latency: 21966 usec
        Resample method: n/a
                application.icon_name = "google-chrome"
       = "Playback"
       = "Chrome"
                native-protocol.peer = "UNIX socket client"
                native-protocol.version = "28"
       = "13436"
                application.process.user = "ivucica"
       = "MYHOSTNAME"
                application.process.binary = "chrome (deleted)"
                application.language = "en_US.UTF-8"
                window.x11.display = ":0"
                application.process.machine_id = "MYMACHINEID"
                application.process.session_id = "c14"
       = "sink-input-by-application-name:Chrome"

Using pactl list short, the output will be more ambiguous. Let’s filter it to show only sink-inputs using pactl list short sink-inputs.

0   1   7   protocol-native.c   s16le 2ch 44100Hz

Changing default output

When an app starts playing an audio stream, it gets sent to the default sink. Let’s change it to go from the current output to ‘hdmi-stereo’.

$ pactl list short sinks
0   alsa_output.pci-0000_05_00.1.hdmi-stereo    module-alsa-card.c  s16le 2ch 44100Hz   SUSPENDED
1   alsa_output.pci-0000_00_1b.0.analog-stereo  module-alsa-card.c  s16le 2ch 44100Hz   RUNNING
$ pactl set-default-sink 0

Moving existing sink inputs to another sink

If an application is already playing audio, it will not switch over to the new sink.

$ pactl list short sink-inputs
0   1   7   protocol-native.c   s16le 2ch 44100Hz
// move sink input 0 to sink 1:
$ pactl move-sink-input 0 1
// alternatively:
$ pactl move-sink-input 0 alsa_output.pci-0000_00_1b.0.analog-stereo

GUI for the above operations

One of the more lightweight GUI solutions seems to be pavucontrol.

Setting up equalizer

The modules may not be loaded. (Optionally verify with pactl list modules.)

$ pactl load module-equalizer-sink
$ pactl load module-dbus-protocol

This creates a new sink.

Upstream documentation claims the equalizer should already set itself as the default. Existing sink inputs definitely didn’t move over to the new sink. I’m using Ubuntu 14.04; YMMV.

None of the arguments mentioned by upstream docs (sink_name=equalized master=alsa_output.pci-0000_00_1b.0.analog-surround-51 set_default=true) worked for me. I would suspect they are simply post-trusty additions.

Instead, here’s my manual steps. (This could be more automated simply by using variables. Still, given that these are semi-educational notes, I’m opting for showing how to interpret outputs.)

// Find the ID of the first equalizer sink.
// If you suspect you may have more, skip everything after 'grep equalizer' and manually handle.
$ pactl list short sinks | grep equalizer | head -n1 | awk '{print $1;}'
$ pactl set-default-sink 4
$ pactl list short sink-input | awk '{print $1;}'
$ pactl move-sink-input 2 4
$ pactl move-sink-input 6 4
$ pactl move-sink-input 7 4

Adjusting equalizer settings using qpaeq

Qt PulseAudio Equalizer or qpaeq is available from PulseAudio source tree. For example, take it from a mirror on GitHub, make it executable and run it. (Before running it, of course, read through this code you’re grabbing from a random website on the Internet.)

$ wget
$ chmod 755 qpaeq
$ ./qpaeq

Dealing with issues

If something doesn’t go right, kill the PulseAudio daemon pulseaudio -k. Your desktop environment is probably going to restart it by itself. Otherwise, something like nohup pulseaudio & should probably help. Then, reload the modules.

Upstream docs also say you may want to disable tsched, for example in /etc/default/

### Automatically load driver modules depending on the hardware available
load-module module-udev-detect tsched=0
### Alternatively use the static hardware detection module (for systems that
### lack udev support)
load-module module-detect tsched=0

I’m thinking, that may be also the right place for loading the equalizer and dbus module. Although, ~/.config/pulse/ may be an even saner one. Not sure yet.

Good luck!