Sunday 16 November 2014

Source-compiled Wine with ALSA output plays static in Pulseaudio under Ubuntu.

PULSE_LATENCY_MSEC=30 wine
# =1 works in some cases, doesn't on others
http://arunraghavan.net/2013/08/pulseaudio-4-0-and-skype/

Friday 5 September 2014

Index project with ctags and cscope with a single button press in emacs.


I should probably comment on the madness happening below, but I'm too tired at the moment, and, more importantly, I don't think anyone needs it anyway.

The short and messy description is that you press f9 and both ctags and cscope databases are built for your project. Pretty convenient.

To make it work with the project of your choice, you need to describe your project in the known-projects list (it's already filled with some examples).

The first part is a list of directories that designate the root of the project (so that you can run the command from any internal dir).

The second part is a blacklist that contains names and paths that should not be indexed, e.g. you would want to blacklist the huge test collection in GCC which will inflate your database tremendously and add an incredible amount of duplicated names, or the equally humongous Linux driver collection (unless you're a driver developer, duh).

1-2 auxiliary subroutines may have been copied from various places on the Internet. The code may hang your editor if you have cyclic links. Also, I can't program in elisp, although that must be strikingly obvious without me saying that.

;; Define the core dir trappings and blacklisted directories here
(setq known-projects '((("gcc" "config" "libgcc" "libiberty") ("/testsuite/" "/test/" "/build/"))
               (("mono" "mcs" "eglib" "docs" "tools") ())
               (("DROD" "DRODLib" "DRODUtil") ())
               (("arch" "drivers" "include" "kernel") ("/drivers/")) ; Linux
 

               (("README" "INSTALL") ("/.pc/")) ; Generic software project #1 (e.g. emacs)
               (("README") ("/.pc/")) ; Generic software project #2.
               ((".") ())          ; Oh well, let's at least index the current dir
               ))              ; if everything else fails.

(defun index-project () (interactive)
  (defun dump-vars-to-file (varlist filename)
    "simplistic dumping of variables in VARLIST to a file FILENAME"
    (save-excursion
      (let ((buf (find-file-noselect filename)))
    (set-buffer buf)
    (erase-buffer)
    (loop for var in varlist do
          (princ (concat var "\n") buf))
    (save-buffer)
    (kill-buffer))))
 
  (defun lookup-project (projects)
    (let ((lookup-failed t) (blacklist nil) (remaining-trappings nil) (lookup-path nil) (project nil))
      (while (and (consp projects) lookup-failed)
    (setq lookup-path buffer-file-name)
    (setq project (pop projects))
    ; (message "Trying project %s" project)
    (while (and (> (string-width lookup-path) 1) lookup-failed)
      ;; For some reason (file-exists-p "main.c/.") = t!
      (when lookup-failed
        (setq lookup-path (replace-regexp-in-string "/[^/]*$" "" lookup-path)))
      ; (message "Trying path %s" lookup-path)
      (setq lookup-failed nil)
      (setq remaining-trappings (nth 0 project))
      (setq blacklist (nth 1 project))
      (while (and (consp remaining-trappings) (not lookup-failed))
        (if (not (file-exists-p (concat lookup-path "/" (pop remaining-trappings))))
        (setq lookup-failed t)))))
      (when lookup-failed (setq lookup-path nil) (setq blacklist nil))
      (list lookup-path blacklist)))

  (let ((project-info (lookup-project known-projects))
    (project-root nil) (project-blacklist nil))

    (setq project-root (nth 0 project-info))
    (setq project-blacklist (nth 1 project-info))

    (message "Project found at %s. Scanning files... (excliding %s)" project-root project-blacklist)

    (when project-root
      (defun is-path-blacklisted (path blacklist)
    (while (and blacklist (not (string-match (car blacklist) path))) (pop blacklist))
    (if blacklist t nil))

      (defun build-cscope-database (root blacklist)
    (setq dirs (list root)) ;; "/usr/include/")) ; I found it to add too much clutter, better add some individual files instead.
    (setq files '())
    (while dirs
      (setq dir (pop dirs))
      (setq ls (directory-files dir))
      (while ls
        (setq file (pop ls))
        (setq file-path (concat dir "/" file))
        (unless (is-path-blacklisted file-path blacklist)
          (if (file-accessible-directory-p file-path)
          (unless (or (string= file ".") (string= file "..")) (add-to-list 'dirs file-path))
        (if (and (file-readable-p file-path) (string-match "\\.\\(c\\|cpp\\|h\\|hpp\\|vala\\|def\\)$" file-path))
            (add-to-list 'files file-path))))))
    ;; Append some commonly used header files. Uncomment the "/usr/include" line above
    ;; and remove/comment this one if you want to see them all their multitude instead
    ;; of this selectivity.
    (dolist (header '("stdio.h" "stdlib.h" "stdarg.h" "ctype.h" "string.h" "math.h" "dlfcn.h"
              "sys/types.h" "sys/time.h" "unistd.h" "assert.h" "limits.h" "poll.h"
              "libgen.h" "signal.h" "fcntl.h"
              "bits/stdio2.h" "bits/string2.h"
              "X11/Xos.h" "X11/Xlib.h" "X11/Xfuncproto.h" "X11/Xatom.h" "X11/Xproto.h"
              "X11/extensions/Xrandr.h" "X11/extensions/shape.h" "X11/cursorfont.h"
              "X11/extensions/XInput2.h" "X11/X.h"
              "boost/bind.hpp" "boost/foreach.hpp"
              "sys/wait.h" "sys/types.h" "sys/stat.h"
              "glib-2.0/glib/gspawn.h" "glib-2.0/glib/gslice.h" "glib-2.0/glib/gmacros.h"
              "glib-2.0/gobject/gobject.h" "glib-2.0/gobject/gtype.h"
              ))
      (add-to-list 'files (concat "/usr/include/" header)))
    files)

      (dump-vars-to-file (build-cscope-database project-root project-blacklist)
             (concat project-root "/" cscope-index-file))

      (message "Processing...")
      (cscope-set-initial-directory project-root)
      (with-temp-buffer (shell-command (concat "cd " project-root "; cscope -b; ctags -eL " cscope-index-file) t)) ; with-temp-buffer is needed to hide output
      (setq tags-file-name (concat project-root "/TAGS"))
      (message "Done processing")))
)

(global-set-key (kbd "<f9>") 'index-project)

Sunday 29 June 2014

Play all songs whose names match a regular expression.


#!/bin/sh
locate -0i --regex "($*).*\.(mp3|mpe?g|avi|mkv|ogg|au|m4a|flac)$" | xargs -0 nohup vlc >/dev/null 2>&1 &

Replace vlc with the player of your choice, save as /usr/local/bin/lplay, make it executable with 'sudo chmod +x /usr/local/bin/lplay' - et voila, you can do pretty complex music queries without amarok or any other bulky and buggy music player, provided there is enough information in their file names.

Since locale uses its own pre-built file database, this will be much faster than using "find" that actually traverses the entire file system.

Examples:
$ lplay music/j-pop
# play your J-Pop collection
$ lplay '風|wind|kaze'
# play everything that has the word or kanji "wind" in it

$ lplay 'bob.*dylan'
# play all Bob Dylan's songs

P.S.
Alternatviely, you can filter out audio/video files by their headers instead of using their extensions. It will give more refined results (you may be surprised how many games keep video and music in standard formats with non-standard extensions!), but will be slower, especially for general queries that have a lot of hits that are not music/video files.
locate -0i --regex "$*" | xargs -0 file -0 | grep -Eia 'audio|video' | cut -d '' -f1 | xargs -d\\n nohup vlc >/dev/null 2>&1 &

Tuesday 10 June 2014

Don't show Steam in KDE4 task manager when minimized to tray.

Open /usr/share/applications/steam.desktop and replace line:
Exec=/usr/bin/steam %U
with (for Steam installed from Valve package):
Exec=sh -c "STEAM_FRAME_FORCE_CLOSE=1 /usr/bin/steam %U"
or (for Steam installed from Ubuntu repo):
Exec=sh -c "STEAM_FRAME_FORCE_CLOSE=1 /usr/games/steam %U"

Or just launch it from console as:
$ STEAM_FRAME_FORCE_CLOSE=1 /usr/bin/steam

(solution based on a post from https://github.com/ValveSoftware/steam-for-linux/issues/1025)

Tuesday 6 May 2014

Baloo a shit

A truly deserving successor of nedopuk that reeks of shit just as much.
Gee, let's force a mostly meaningless and redundant feature on the users' head. And let's fucking lie that they won't even notice the performance impact as the reason for enabling it. Surely they won't! Because really, who would notice something that hogs 100% of I/O and quadruples loading times! I didn't mean to sign for an alpha when I decided to use a mainstream Linux distro or KDE!
Oh, and there is no official way to disable it.

Saturday 3 May 2014

Capturing video in Ubuntu 14.04

(Disclamer: never captured video before, must be missing a whole lot of things and optimizations).

The following line will capture 1920x1080 screen at 30 frames per second and is suitable for taking video game footage.

avconv -f x11grab -r 30 -s hd1080 -i :0.0 -f pulse -name 'screencap -> system audio' -i alsa_output.pci-0000_00_1b.0.analog-stereo.monitor -map 0 -map 1  -codec:v libx264 -pre:v lossless_ultrafast -codec:a libmp3lame -threads auto -y captured.avi

If audio & video are out of sync, chances are you have run into yet another bug in Ubuntu.

http://askubuntu.com/questions/336747/audio-and-video-auto-of-sync-when-streaming
https://github.com/MaartenBaert/ssr/issues/16

To fix that, set the 2 following values in  /etc/pulse/daemon.conf:
does storing
default-sample-rate = 44100
alternate-sample-rate = 44100
To get window geometry if you're capturing a window, you can use xwininfo and then change the resolution (-s WxH) and offset (-i :0.0+x_off,y_off) accordingly.

Expect that 1 minute of stream will hog roughly 1GB with these settings for 1080p.

When the capture is done, compress & (optionally)cut:
avconv -i captured.avi -ss FROM_TIME -t LENGTH -vcodec libx264 -pre:v veryslow -acodec libmp3lame result.avi

So why is GNU/Linux not a popular platform for gaming and streaming? Anyone?

Update as of August 22, 2014 (still needs some polish):

The following line allows for real-time capture AND encoding. The line gives a 50 MB/min output and looks like a full replacement to the old one.
avconv -f x11grab -s hd1080 -i :0.0 -f pulse -name 'screencap -> system audio' -i alsa_output.pci-0000_00_1b.0.analog-stereo.monitor -map 0 -map 1  -codec:v libx264 -pre:v ultrafast -codec:a libmp3lame -af asyncts -threads auto -y captured.mkv

add -filter:v scale=960:-1 (or whatever size you prefer) to record downscaled video. Reduces video size and some CPU power (obviously) at the cost of lower resolution.

Seems like the -r parameter specified earlier may actually cause audio/video desync when the encoder cannot keep up with the input. If there is still desync, try loading the game and THEN starting the capture (still don't know what's causing this).

Update as of May 05, 2015:

OBS now natively supports Linux. The up-to-date version that I tried was a bit buggy, but it was still a great improvement over what I had been dealing with before. One small caveat is that it needs ffmpeg instead of avconv, and those two hate each other with passion. It IS possible to install ffmpeg locally in your home directory (without removing avconv) and make OBS use it from there, though you'll probably need to compile ffmpeg and OBS manually to do that (which is fairly straightforward regardless, I must add).

Show packages that are newer than those from rep info

apt-show-versions | grep newer|awk '{print $1;}'

Friday 21 February 2014

Convenient keyboard layout switching for 3 or more languages in Linux.

I'm using four different keyboard layouts at a semi-regular basis. Switching between them used to be a headache until I came up with the idea of assigning each language a separate key shorcut consisting of a home row character + the Windows(Meta) key.

Since each layout has a separate shortcut, I no longer need to remember what locale I'm currently using and then count how many times I need to press the universal switch key in order to switch to the desired language. In addition, I don't have to move my fingers from the home row except for the pinky to reach the Windows key.

I implemented my scheme on Linux using ibus as the input method framework, xbindkeys as the keyboard shortcut manager and xbindkeysrc-config for config creation.

After installing these components you need to make a config file for xbindkeys (~/.xbindkeysrc) that would define the keyboard shortcuts and locales. Mine turned out to be as follows:
#Japanese
# The new ibus version does not switch from Cyrillic to Japanese for some reason, so we have to switch to English first.
# Replace "anthy" with "mozc-jp" if you're using Mozc.
"ibus engine xkb:us::eng; ibus engine anthy"
m:0x40 + c:44

#English
"ibus engine xkb:us::eng"
m:0x40 + c:45

#Russian
"ibus engine xkb:ru::rus"
m:0x40 + c:46

#Ukrainian
"ibus engine xkb:ua::ukr"
m:0x40 + c:32

#French
"ibus engine xkb:fr::fra"
m:0x40 + c:47
"ibus engine ..." is the console command that makes ibus switch the current layout. Using keycodes is necessary since the same physical keys may represent different characters in different locales.

<LWin+k>Layout switching became easy!
<LWin+j>入力言語の切り替えは簡単になりました!
<LWin+l>Переключение языков стало простым!
<LWin+;>Changement de langue est devenu très simple!

P.S. I think the same result should be achievable in Windows using the AutoHotkey tool, though I haven't looked into it.

Saturday 4 January 2014

Running applications so that they wouldn't close when you close the console

Nohup.

But since it litters nohup.outs everywhere let's make a custom shortcut script for launching it:

#!/bin/sh
nohup "$@" >/dev/null 2>&1 &

Just save it as nh into a bin dir and you can use it:

$ nh wine 2hu.exe
$ nh vlc reincarnation.mp3
$ exit

And applications keep on running! Why did I not bother learning about this useful command earlier?