Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Monday, September 22, 2014

Make sorting media files marginally easier

If you're like me, you have a hard drive with little scattered oxbow directories filled with the varied sediment of entertainment media strata.  These dark swamplands occasionally need draining and the value of each soggy log and bog frog within must be appraised.  The trick is to minimize the time required to hold one's breath.

The dominant populations one may find in such a data-wallow may include:
  • product pdf's and datasheets
  • books and reference documents
  • videos of things exploding into flames
  • good old-fashioned porn
  • music videos from YouTube
  • bad old-fashioned porn 
  • esoteric music files from atypical sources
  • graphs documenting the aggrandizement of a veiled fascism
  • cat pictures
Whether it's by lack of self-discipline or because you have a good excuse, these things tend to collect and need occasional sorting and cleanup.   Some things like video and audio tend to be tedious to sort, not only because the files take time to review, but often because their sources leave them poorly named.

Recently I felt the need to abuse myself by sorting a folder full of shit video files I wasn't in the mood to watch.  It so happened that they were mostly rips from various flash players and all had meaningless hash salads for filenames.  Because of this, manually picking through each one becomes tedious.  Tab-completion is defeated; it's difficult to even remember which filename you're trying to target.  I put together a crude script to automate the review, renaming, and categorization of the ~200 files.

#!/bin/bash

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

if [ ! -d "funnyshit" ]; then mkdir funnyshit; fi
if [ ! -d "depressingshit" ]; then mkdir depressingshit; fi
if [ ! -d "infuriatingshit" ]; then mkdir infuriatingshit; fi
if [ ! -d "junk" ]; then mkdir junk; fi

for file in $(ls -1); do 
    echo -e "\033[0;36mPlaying: $file\033[0m " 
    mplayer $file --really-quiet
    sleep 1

    whiptail --inputbox "Filename Editor\nESC to skip this file" 8 60 "$file" 2>tname
    if [ $? != 0 ]; then 
        rm tname 
        echo -e "\033[0;36mSkipping $file\033[0m" 
        continue
    fi 
    newname=$(cat tname); rm tname

    if [ $newname != $file ]; then 
        mv $file $newname
        echo -e "\033[0;36mChanged $file to $newname\033[0m" 
        file=$newname
    else
        echo -e "\033[0;36mDid not change file name\033[0m"
    fi

    whiptail --radiolist "where to put it" 15 50 8 "funnyshit" "" on "depressingshit" "" off "infuriatingshit" "" off "junk" "" off 2>tdir
    if [ $? != 0 ]; then rm tdir; break; fi
    destination=$(cat tdir); rm tdir

    echo -e "\033[0;36mMoving $file to $destination\033[0m"
    mv $file $destination/
done

IFS=$SAVEIFS

The script just blindly picks up every file in the directory and plays it.  Non-video files can be manually skipped or sorted if they're identifiable.  Video files are played with Mplayer.  Once an evaluation is made, user hits escape to terminate Mplayer, and a dialog prompts for an optional new name and a choice of output directory bins.

There are a lot of ways to make this more flexible and useful in other tasks or with other filetypes, but I hope it's obvious by now that i don't really care any more.

Monday, September 15, 2014

The mysterious shrinking terminal window

Terminator is a nice little tool for managing multiple gterm sessions within a single window.  I find the use of split screens very comfortable.  Terminator allows the creation of layout profiles to automate the setup of a particular tab/split configuration.  These can be selected with the --layout option when launching Terminator.  The problem with this is that at least under my current environment (Mint 14/XFCE), the resultant window spawns and then shrinks down as small as possible.  It's hard to describe, so maybe i should include a graphic. 

Whaaaaaat
I recall having read about this phenomenon elsewhere, though i don't recall if a solution or workaround had been revealed at the time.  Since i was issuing these commands primarily via a long, ugly session recovery script, my first hack-around solution was to use wmctrl to subsequently restore the window geometry.  This was fun to watch, but the better workaround is to just use the gnome geometry options from the start.
terminator --layout="yourlayoutname" --geometry=1280x977 
That was a pretty simple solution to a rather comical problem.

Saturday, September 13, 2014

The foolproof way to do screen capture

Years ago, i did my first screen capture experiment. I put together an ugly pair of scripts to take screenshots at infrequent intervals, capturing the essence of a slow and boring bit of work in GIMP. I surmised at the time that there are probably lots of better ways.

Fast forward to recent months. I was trying to demonstrate the use of Matlab to encode images and text into audio spectra. I needed more typical framerates and i wanted companion audio, so i figured that it was the time to search for that "better way". In Mint 14, i had a lot of options suggested by forums and by software sources:
  • Istanbul -- Ogg video desktop recorder 
  • RecordMyDesktop -- Another desktop recorder 
  • Kazam -- Yet another 
  • VLC -- has a mode for capturing the desktop 
Unfortunately, none of these programs actually worked properly. Kazam crashes and often produces corrupted output. Istanbul produces choppy output if it actually saves anything at all. RMD and VLC are similarly broken on my system. IIRC, parts of the bugginess comes from particular ogg or python library versions, and perhaps things work differently on a more up-to-date system. I don't care. They're broken on mine.

Since none of these tools capture audio correctly anyway, i cut my losses and decided to capture video only.
ffmpeg -f x11grab -r 25 -s 1280x1024 -i :0.0 -sameq bullshit.mp4
... of course, you can do it with avconv instead of ffmpeg:
avconv -f x11grab -r 25 -s 1280x1024 -i :0.0 -same_quant bullshit.mp4
It's simple, it works, and it's faster and more flexible than some of the other options.

Friday, September 12, 2014

Open documents in an application on a different X display

When running multihead with separate servers for each screen (Zaphod mode, not Xinerama), there comes occasional need to launch applications on a display other than the one currently in use.  This comes up in various tasks:
  • Launch an app on screen A from a panel launcher on screen B
  • Place application windows on various screens with a session recovery script
  • Open a URL in a web browser from an application on a different screen
It's the third task which is the solution to a problem I encountered when setting up Thunderbird.  Unless Thunderbird is on the same X display as the browser, It will fail with the error

Firefox is already running, but is not responding. To open a new window, you must first close the existing Firefox process, or restart your system.
YOU BROKE IT, MILLIE!

I mention Thunderbird, but this could be Evolution or some other app. The target application doesn't have to be a web browser either.  In fact, if your browser and mail client are on different screens, the browser won't be able to open mailto links in the mail client either.  In these cases, the core of the solution is to temporarily change the $DISPLAY environment variable.
#!/bin/bash
# allows thunderbird to pass URLs to a browser on a different $DISPLAY

cdisp=$DISPLAY
DISPLAY=:0
palemoon $1
DISPLAY=$cdisp
Change the executable name and display numbers to suit. 

For Thunderbird specifically, enabling the use of this script requires changing the attachment handler settings.  Since there is no way to add new entries in the Attachments section of the Preferences dialog (on TB 24), open about:config and set network.protocol-handler.warn-external.http and network.protocol-handler.warn-external.https to TRUE. This forces a user dialog when a link of either type is clicked. Select the new script in both cases. Once successful, the dialog shouldn't pop up again. The resultant settings generated by these actions are visible/editable in the Attachments section of the Preferences dialog. 

It's worth noting that applying these methods to Firefox will open the URL in the existing Firefox session. If you expect to open a new Firefox window on another screen, you're pretty much shit out of luck as far as i know. There are certainly some dodgy workarounds, though.

Thursday, September 11, 2014

Selectively Invert workspaces for readability

UPDATE October 2019: The script has been updated for multirow operation, better window identification, and reduced execution time.

In my recent experiences dealing with the rapid progression of cataracts and vision loss, I had to make a lot of adjustments to my computing environment to accommodate for the diffusion.  In my sight, bright regions in the field of view bleed over dark areas and obscure them extremely effectively.  The diffusion averages the brightness of the entire visual field, nearly eliminating local contrast.  This pretty much means that the thin black lines of text on a white background disappear.  White characters on a dark background bleed as well, but the impact on readability is much smaller.

OH GOD THE BRIGHTNESS

I do understand that other individuals with cataracts claim different experiences regarding contrast preference; perhaps it is the differences in the types of cataract structure that explains those things.  Regardless, my overall goal is to control bright areas of my workspace and enforce a relatively high contrast light-on-dark regime. 

This new quest covered the normal bases:
  • GTK 2/3 theme
  • QT4 color settings
  • Desktop wallpaper
  • Custom user styles for Firefox/Stylish
... but still, there are things that can't be properly themed.  Wine applications, as well as certain things like virtual machines and Matlab/Simulink all appear as horrible fuzzy bright rectangles of pain.  What the hell does one do about those?

If i could invert an individual window's colors, that would be sufficient.  The only method i can recall to do this is with Compiz, and that's not going to happen for various reasons.  Under Mint 14/XFCE, the only thing i could think to do is invert the entire X display.  Since i normally run these offending applications maximized, the amount of remaining bright area is mostly restricted to the xfce4-panel area at the top.  Inverting the entire display can be done with xcalib, but unless one wants to get blinded every time the workspace is switched, the application of the screen inversion should be automated.

#!/bin/bash

# This is an ad-hoc replacement for wm-specific workspace switching (ctrl-alt-left, ctrl-alt-right, ctrl-alt-number)
# Script conditionally inverts X display on workspaces containing offending windows
# Helps to enforce dark, hi-contrast UI despite unthemeable windows (virtual machines, wine apps, etc)
# Works best when applications are run full-screen
# directional usage: switchworkspace left|right|up|down
# explicit usage: switchworkspace workspacenumber

# this version is about 5% faster than the old 1-D version
# and does not invoke gamma enforcement and inversion checks at endpoints

# specify the workspace/pager layout
nwsx=3 # number of columns
nwsy=3 # number of rows


current=$(wmctrl -d | sed -n 's/^\([0-9]\+\) *\*.*/\1/p')

if [ $1 ]; then
 ex='^[0-9]+$'
 if ! [[ $1 =~ $ex ]]; then
  # argument is not a number
  if [ $1 == "right" ] || [ $1 == "left" ]; then
   if [ $1 == "right" ]; then
    if [ $(($current % $nwsx)) == $(($nwsx-1)) ]; then
     exit
    else
     target=$(($current+1))
    fi
   elif [ $1 == "left" ]; then
    if [ $(($current % $nwsx)) == 0 ]; then
     exit
    else
     target=$(($current-1))
    fi
   fi
  elif [ $1 == "up" ] || [ $1 == "down" ]; then
   if [ $1 == "down" ]; then
    if [ $(($current / $nwsx)) == $(($nwsy-1)) ]; then
     exit
    else
     target=$(($current+$nwsx))
    fi
   elif [ $1 == "up" ]; then
    if [ $(($current / $nwsx)) == 0 ]; then
     exit
    else
     target=$(($current-$nwsx))
    fi
   fi
  else
   echo "unknown direction"
   exit
  fi
 else
  # argument is numeric
  total=$(wmctrl -d | wc -l)
  if [ $1 -gt $total ]; then
   target=$(($total-1))
  elif [ $1 -lt 1 ]; then
   target=0
  else
   target=$(($1-1))
  fi
  
  if [ $current == $target ]; then exit; fi
 fi 
else
 echo "must specify a workspace number or direction (right/left/up/down)"
 exit
fi


# add other applications by window title keyword or window class
# if multiple windows match, all corresponding desktops will be affected
winlist=$(wmctrl -lx)
inv[0]=$(echo "$winlist" | grep "XFramePeer.com-mathworks-util-PostVMInit" | cut -d \  -f 3)
inv[1]=$(echo "$winlist" | grep "XFramePeer.MATLAB" | cut -d \  -f 3)
inv[2]=$(echo "$winlist" | grep "eagle.exe." | cut -d \  -f 3)
inv[3]=$(echo "$winlist" | grep "scad3.exe." | cut -d \  -f 3)
inv[4]=$(echo "$winlist" | grep "femm.exe." | cut -d \  -f 3)


function contains {
 case "${inv[@]}" in  *"$1"*) 
  echo 1 
  return 1 ;; 
 esac
 echo 0
}

wmctrl -s $target

A=$(contains $target)
B=$(contains $current)

#echo $current $target $A $B

if [ $A == 1 ] && [ $B != 1 ]; then

 xcalib -i -a
elif  [ $A == 1 ] && [ $B == 1 ]; then
 return
else
 xcalib -clear

 # i have gamma presets for each of my two monitors
 # issuing 'xcalib -clear' will reset the gamma to 1.00
 # so i'll need to reassert my preference depending on the active display
 # you might not need this
 # when running this from a terminal, $DISPLAY may be ":0" depending on what's happened during its session
 thisdisp=$(echo $DISPLAY)
 #echo $thisdisp
 if [ "$thisdisp" == ":0.0" ]; then
  xgamma -quiet -gamma 0.87
 else
  xgamma -quiet -gamma 1.2
 fi
fi


The script is relatively simple and a bit of effort did go into making it quick.  An array of workspace numbers is created by searching for specific WM_CLASS strings in the window list.  When switching workspaces with this script, the inversion state of the display is altered to correspond to the workspace contents.

Two workspaces: Terminator (normal), Matlab/Simulink (inverted)

Just add appropriate window title keywords and set your preferred wrapping behavior in the script.  Reassign the appropriate keybindings (Ctrl-Alt-Left, Ctrl-Alt-Right) so they execute this script instead of the inbuilt window manager functions.  Script accepts one parameter, either "prev" or "next".

Wednesday, September 10, 2014

Classics: Enable third button chord for a mouse

Three-button emulation used to be a necessity in a world of two-button mice.  In today's world of many-buttoned mice, a lot of people don't even deal with button chording anymore.  While some people like myself are simply accustomed or more comfortable with the chords, i can certainly imagine that the ubiquity of shitty loose mouse wheels might lead someone to a similar conclusion in the modern era.  Where to start?  What do i use?  Use xinput.

List your devices and find the right device name:
delicious@bacon:~/bin$ xinput | grep pointer
⎡ Virtual core pointer                        id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                  id=4    [slave  pointer  (2)]
⎜   ↳ Kensington      Kensington Expert Mouse     id=8    [slave  pointer  (2)]
⎜   ↳ Wacom Graphire3 stylus                      id=9    [slave  pointer  (2)]
⎜   ↳ Wacom Graphire3 eraser                      id=11    [slave  pointer  (2)]
⎜   ↳ Wacom Graphire3 cursor                      id=12    [slave  pointer  (2)]

List the device properties:
delicious@bacon:~/bin$ xinput --list-props "Kensington      Kensington Expert Mouse"
Device 'Kensington      Kensington Expert Mouse':
    Device Enabled (146):    1
    Coordinate Transformation Matrix (148):    1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
    Device Accel Profile (268):    0
    Device Accel Constant Deceleration (269):    1.000000
    Device Accel Adaptive Deceleration (270):    1.000000
    Device Accel Velocity Scaling (271):    10.000000
    Device Product ID (262):    1149, 4128
    Device Node (263):    "/dev/input/event3"
    Evdev Axis Inversion (272):    0, 0
    Evdev Axes Swap (274):    0
    Axis Labels (275):    "Rel X" (156), "Rel Y" (157), "Rel Vert Wheel" (267)
    Button Labels (276):    "Button Left" (149), "Button Middle" (150), "Button Right" (151), "Button Wheel Up" (152), "Button Wheel Down" (153), "Button Horiz Wheel Left" (154), "Button Horiz Wheel Right" (155), "Button Side" (266), "Button Unknown" (265), "Button Unknown" (265), "Button Unknown" (265), "Button Unknown" (265)
    Evdev Middle Button Emulation (277):    0

    Evdev Middle Button Timeout (278):    50
    Evdev Third Button Emulation (279):    0
    Evdev Third Button Emulation Timeout (280):    1000
    Evdev Third Button Emulation Button (281):    3
    Evdev Third Button Emulation Threshold (282):    20
    Evdev Wheel Emulation (283):    0
    Evdev Wheel Emulation Axes (284):    0, 0, 4, 5
    Evdev Wheel Emulation Inertia (285):    10
    Evdev Wheel Emulation Timeout (286):    200
    Evdev Wheel Emulation Button (287):    4
    Evdev Drag Lock Buttons (288):    0

We're looking for middle button emulation here, but notice that there are a lot of things that can be configured here.  From this, we could remap the buttons entirely, change acceleration, flip axes, even change the way the mouse maps to the total display area in a multihead system.  ... but since all we're after is this one thing, let's set that.  From the xinput manual:
--set-prop [--type=atom|float|int] [--format=8|16|32] device property value [...]
therefore:
xinput --set-prop --type=int --format=8 "Kensington      Kensington Expert Mouse" 277 1
Check the property status for the change.  Of course, these settings won't last through a session change, so stick it in a startup events script or something.  If this doesn't work, i would recommend getting angry and maybe exploring the nuances of your most creative swears.

Classics: Disable Caps Lock key

The web contains a rich history of ways to disable the Caps Lock key in linux.  In my experience a lot of these methods don't actually work anymore.  Although i do recognize that a lot of users are more interested in remapping or modifying Caps Lock functionality, I'm only out to disable that damn button.

Ways which i have found that work:

  • setxkbmap -option caps:none
  • setxkbmap -option ctrl:nocaps
  • xmodmap -e 'keycode 66 = '

Ways (among others) which i found did not work:
  • xmodmap -e "remove lock = Caps_Lock"
  • xmodmap -e "clear Lock"
Using the setxkbmap method seems to be much more flexible, but directly mapping the keycode to nothing worked fine for my purposes. 

Audacious: copy current selection to next playlist

Audacious has two different layout options.  One is the familiar classic winamp/xmms style, whereas the other is a more featureful gtk UI.  Under Audacious 3.2.3, the gtk UI exhibits severe memory leaks.  Although newer versions of Audacious have had this problem fixed, they do not run on my current system without other more spectacular usability failures.  Until such a time as i upgrade, I'm stuck using the classic UI under 3.2.3.  I'm okay with that.  I guess i still carry a torch for good old xmms anyway.

Then there's the problem at hand: manipulating playlists in the classic UI is cumbersome as hell.  I only have two playlists: one which contains all files, and one in the background which contains favorites.  I want to easily copy a song i like from one to the other without a bunch of menus or keymashing.

I wrote a simple script based on xdotool:
#!/bin/bash
# this script externally issues commands required to copy tracks 
# from the main playlist to the secondary "favorites" playlist
# without invoking the GTK UI with bad memory leaks
# using windowactivate instead of windowfocus causes cross-$DISPLAY bugginess

xdotool search --screen 1 --name "Audacious Playlist" windowfocus; 
sleep 0.1; xdotool key Ctrl+c
sleep 0.1; xdotool key Tab
sleep 0.1; xdotool key Ctrl+v
sleep 0.1; xdotool key Shift+Tab


I then stuck it in a panel launcher on the same X display.  Now all i need to do is select the songs and click the panel button. I suppose one could use a global keybinding instead.

Make an application stay on top by default

Certain applications such as a calculator have typical use patterns which indicate window behavior settings contrary to the norm.  A calculator application like gcalctool is often used alongside work being performed in other windows. In these cases, i prefer the window mode to be set such that it stays on top of all other windows.  This way i can go back and forth between the calculator and other work without the results of my calculations disappearing under a stack of other windows.  This is only more of a hassle since i have the window manager set to auto-focus and auto-raise windows.  Since the application may be opened and closed often, efforts to manually set window modes are usually wasted.

wmctrl can be used to set the mode flags of a window (among a bunch of other things).
For gcalctool:
#!/bin/bash

gcalctool &
sleep 1
wmctrl -r "Calculator" -b add,above


For xzoom magnifier:
#!/bin/bash

xzoom &
sleep 1
wmctrl -r "xzoom x2" -b add,above,sticky


this time, including the sticky flag

Fix black missing window decorations in xfwm4

This is one of many problems i seem to have a problem discussing with anyone due to the growing rarity of Zaphod X configurations. In my configuration, i have three screens on different xorg servers (no xnest).  Using Mint14 and XFCE, when i log into my desktop environment, there are no window decorations (title bars, buttons, frames) drawn for the windows on displays :0.1 or :0.2. Only the first display (:0) has any window decorations; everything else is black.

Left: Everything is fine.  Right: Windeco's are missing


In my case, going to the Window Manager settings dialog and cycling between themes was sufficient to fix the issue.  If GTK settings are altered, the fix will need to be re-applied.  In order to simplify and automate this workaround, I  slapped a script together that uses xfconf-query to cycle to a different xfwm4 theme and back:

#!/bin/bash
# resets the xfwm4 window decoration theme
# this is a workaround to help enforce drawing on secondary $DISPLAYs

xfconf-query -c xfwm4 -p /general/theme -s Tgc
sleep 0.5
xfconf-query -c xfwm4 -p /general/theme -s Next

Stick this script wherever is convenient for your session startup needs.  I use it in a session template script, but there are more conventional places to put it.