Friday, 6 February 2015

Making custom versions of packages in Ubuntu/Debian

Had to make some changes in the source code of a couple of packages on my system and decided to document the process for future reference. Surprisingly, it's way easier than I thought it would be.

As an example, suppose we want to make the default graphical viewer Eye of Gnome not jump back to the first picture after the last one in a directory (and, similarly, not jump in the opposite direction, either).

First, we need to get the source code for the program
$ mkdir eog; cd eog; apt-get source eog

Then let's install all the needed dependencies to compile the package:
$ sudo apt-get install build-dep eog

All right, time to make the changes we need. In this case, we need to slightly modify the corresponding part in eog_thumb_view_select_single() in src/eog-thumb-view.c to look like this:

        case EOG_THUMB_VIEW_SELECT_LEFT:
            gtk_tree_path_prev (path);
            break;
        case EOG_THUMB_VIEW_SELECT_RIGHT:
            if (gtk_tree_path_get_indices (path) [0] != n_items - 1)
                gtk_tree_path_next (path);
            break;

Now that we've made the changes, let's make our custom package:
$ dpkg-buildpackage -b

The program has been compiled and assembled in one neat package. All that is left is to install it, replacing the standard version:
$ sudo debi

Hooray, we have our custom version of Eye of Gnome installed and operational!

Now if I only knew a way to apply patches and rebuild the packages automatically every time they get an update..

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;}'