mirror of
https://github.com/balkian/dotfiles.git
synced 2024-11-21 11:42:28 +00:00
Removed personal-scripts submodule
To make my life a bit easier
This commit is contained in:
commit
d8f23e0276
10
.gitmodules
vendored
10
.gitmodules
vendored
@ -1,10 +1,10 @@
|
|||||||
[submodule "vim/bundle/vundle"]
|
[submodule "vim/bundle/vundle"]
|
||||||
path = vim/bundle/vundle
|
path = vim/bundle/vundle
|
||||||
url = git@github.com:gmarik/vundle.git
|
url = https://github.com/gmarik/vundle.git
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "oh-my-zsh"]
|
[submodule "oh-my-zsh"]
|
||||||
path = oh-my-zsh
|
path = oh-my-zsh
|
||||||
url = git@github.com:balkian/oh-my-zsh.git
|
url = https://github.com/balkian/oh-my-zsh.git
|
||||||
[submodule "bin"]
|
[submodule "i3-wm-scripts"]
|
||||||
path = bin
|
path = bin/i3-wm-scripts
|
||||||
url = https://github.com/balkian/personal-scripts.git
|
url = https://github.com/yiuin/i3-wm-scripts.git
|
||||||
|
1
bin
1
bin
@ -1 +0,0 @@
|
|||||||
Subproject commit 405a3e196bcabeb9a49abddea0ffbea7c44f850a
|
|
2
bin/README
Normal file
2
bin/README
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Here I will be posting my personal scripts (either written by me or found on the internet).
|
||||||
|
Feel free to use them and email me if you have any comment or question.
|
125
bin/bashrc
Normal file
125
bin/bashrc
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# ~/.bashrc: executed by bash(1) for non-login shells.
|
||||||
|
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
|
||||||
|
# for examples
|
||||||
|
|
||||||
|
# If not running interactively, don't do anything
|
||||||
|
[ -z "$PS1" ] && return
|
||||||
|
|
||||||
|
# don't put duplicate lines in the history. See bash(1) for more options
|
||||||
|
# ... or force ignoredups and ignorespace
|
||||||
|
HISTCONTROL=ignoredups:ignorespace
|
||||||
|
|
||||||
|
# append to the history file, don't overwrite it
|
||||||
|
shopt -s histappend
|
||||||
|
|
||||||
|
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
|
||||||
|
HISTSIZE=1000
|
||||||
|
HISTFILESIZE=2000
|
||||||
|
|
||||||
|
# check the window size after each command and, if necessary,
|
||||||
|
# update the values of LINES and COLUMNS.
|
||||||
|
shopt -s checkwinsize
|
||||||
|
|
||||||
|
# make less more friendly for non-text input files, see lesspipe(1)
|
||||||
|
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
|
||||||
|
|
||||||
|
# set variable identifying the chroot you work in (used in the prompt below)
|
||||||
|
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
|
||||||
|
debian_chroot=$(cat /etc/debian_chroot)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set a fancy prompt (non-color, unless we know we "want" color)
|
||||||
|
case "$TERM" in
|
||||||
|
xterm-color) color_prompt=yes;;
|
||||||
|
xterm) color_prompt=yes;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# uncomment for a colored prompt, if the terminal has the capability; turned
|
||||||
|
# off by default to not distract the user: the focus in a terminal window
|
||||||
|
# should be on the output of commands, not on the prompt
|
||||||
|
force_color_prompt=yes
|
||||||
|
|
||||||
|
if [ -n "$force_color_prompt" ]; then
|
||||||
|
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
|
||||||
|
# We have color support; assume it's compliant with Ecma-48
|
||||||
|
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
|
||||||
|
# a case would tend to support setf rather than setaf.)
|
||||||
|
color_prompt=yes
|
||||||
|
else
|
||||||
|
color_prompt=
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$color_prompt" = yes ]; then
|
||||||
|
export PROMPT_COMMAND='PS1="\\[\033[1;\`if [[ \$? = "0" ]]; then echo "32m\\]"; else echo "31m\\]"; fi\`[\!]\\[\033[0m\]\u@\h \W: "'
|
||||||
|
else
|
||||||
|
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset color_prompt force_color_prompt
|
||||||
|
|
||||||
|
# If this is an xterm set the title to user@host:dir
|
||||||
|
case "$TERM" in
|
||||||
|
xterm*|rxvt*)
|
||||||
|
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# enable color support of ls and also add handy aliases
|
||||||
|
if [ -x /usr/bin/dircolors ]; then
|
||||||
|
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
|
||||||
|
alias ls='ls --color=auto'
|
||||||
|
#alias dir='dir --color=auto'
|
||||||
|
#alias vdir='vdir --color=auto'
|
||||||
|
|
||||||
|
alias grep='grep --color=auto'
|
||||||
|
alias fgrep='fgrep --color=auto'
|
||||||
|
alias egrep='egrep --color=auto'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# some more ls aliases
|
||||||
|
alias ll='ls -alhF'
|
||||||
|
alias la='ls -A'
|
||||||
|
alias l='ls -CF'
|
||||||
|
|
||||||
|
# Add an "alert" alias for long running commands. Use like so:
|
||||||
|
# sleep 10; alert
|
||||||
|
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
|
||||||
|
|
||||||
|
# Alias definitions.
|
||||||
|
# You may want to put all your additions into a separate file like
|
||||||
|
# ~/.bash_aliases, instead of adding them here directly.
|
||||||
|
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
|
||||||
|
|
||||||
|
if [ -f ~/.bash_aliases ]; then
|
||||||
|
. ~/.bash_aliases
|
||||||
|
fi
|
||||||
|
|
||||||
|
# enable programmable completion features (you don't need to enable
|
||||||
|
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
|
||||||
|
# sources /etc/bash.bashrc).
|
||||||
|
if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
|
||||||
|
. /etc/bash_completion
|
||||||
|
fi
|
||||||
|
export CDPATH=~:/media/Datos:/home/balkian
|
||||||
|
|
||||||
|
if [ "$TERM" = "linux" ]; then
|
||||||
|
alias logout="clear && logout && exit"
|
||||||
|
else
|
||||||
|
alias logout="exit 0"
|
||||||
|
fi
|
||||||
|
export PYTHONSTARTUP=/home/$USER/.pythonrc
|
||||||
|
export PATH=$PATH:/var/lib/gems/1.8/bin
|
||||||
|
|
||||||
|
setWindowTitle() {
|
||||||
|
echo -ne "\e]2;$*\a"
|
||||||
|
}
|
||||||
|
updateWindowTitle() {
|
||||||
|
setWindowTitle "${HOSTNAME%%.*}:${PWD/$HOME/~}"
|
||||||
|
}
|
||||||
|
PROMPT_COMMAND=$PROMPT_COMMAND updateWindowTitle
|
||||||
|
|
||||||
|
function findHere() { ex=$1; shift; grep -R $* $ex .;}
|
||||||
|
|
20
bin/change-xfce4-alt-tab.sh
Executable file
20
bin/change-xfce4-alt-tab.sh
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# @balkian
|
||||||
|
# Changes the behaviour of the window cycling in xfce4
|
||||||
|
#
|
||||||
|
# Extracted from: http://askubuntu.com/questions/136052/cycle-windows-over-all-workspaces-in-xfce-while-being-able-to-cycle-over-one-wo
|
||||||
|
#
|
||||||
|
|
||||||
|
OLD_VALUE=$(xfconf-query -c xfwm4 -p /general/cycle_workspaces)
|
||||||
|
|
||||||
|
if [ $OLD_VALUE == "true" ]; then
|
||||||
|
echo 'will now disable workspace cycling'
|
||||||
|
NEW_VALUE="false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $OLD_VALUE == "false" ]; then
|
||||||
|
echo 'will now turn on workspace cycling'
|
||||||
|
NEW_VALUE="true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
xfconf-query -c xfwm4 -p /general/cycle_workspaces -s $NEW_VALUE
|
12
bin/changedisplay.sh
Executable file
12
bin/changedisplay.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Author: Andrew Martin
|
||||||
|
# Credit: http://ubuntuforums.org/showthread.php?t=1309247
|
||||||
|
echo "Enter the primary display from the following:" # prompt for the display
|
||||||
|
xrandr --prop | grep "[^dis]connected" | cut --delimiter=" " -f1 # query connected monitors
|
||||||
|
|
||||||
|
read choice # read the users's choice of monitor
|
||||||
|
|
||||||
|
xrandr --output $choice --primary # set the primary monitor
|
||||||
|
|
||||||
|
|
||||||
|
|
13
bin/cpcuevana.sh
Executable file
13
bin/cpcuevana.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Script to copy Cuevana files to your home directory.
|
||||||
|
# Tested only with one cuevana instance at a time.
|
||||||
|
# @author: balkian
|
||||||
|
|
||||||
|
destfile="$HOME/VideoCuevana$$"
|
||||||
|
info=($(lsof -c /npview/i | grep -i /tmp/flash | awk '{print $2; print $9}'))
|
||||||
|
dir="/proc/${info[0]}/fd"
|
||||||
|
file=${info[1]}
|
||||||
|
#echo "pid" $pid
|
||||||
|
#echo "file" $file
|
||||||
|
fdn=$(ls -l $dir | grep $file | awk '{print $8}')
|
||||||
|
cp $dir/$fdn $destfile && echo "Video copied successfully to $destfile." && echo "Enjoy"
|
27
bin/dmenu.sh
Executable file
27
bin/dmenu.sh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#http://unix.stackexchange.com/questions/50539/inconsistent-behaviour-of-wmctrl-i-a-win
|
||||||
|
|
||||||
|
# source dmenu config file if it exists
|
||||||
|
if [ -f $HOME/.dmenurc ]; then
|
||||||
|
. $HOME/.dmenurc
|
||||||
|
else
|
||||||
|
DMENU='dmenu -i'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# get list of all windows, and their count
|
||||||
|
wmctrl_output=$(wmctrl -lx)
|
||||||
|
win_count=$(echo "$wmctrl_output" | wc -l)
|
||||||
|
# get rid of the hostname and the number in the 2nd column
|
||||||
|
hostname=$(uname -n)
|
||||||
|
win_list=$(echo "$wmctrl_output" | \
|
||||||
|
sed -r -e 's/[^@]'$hostname'//' | \
|
||||||
|
sed -r -e 's/ [0-9][0-9]? / /')
|
||||||
|
|
||||||
|
# select a window ($target) and extract its id ($target_id)
|
||||||
|
target=$(echo "$win_list" | $DMENU -l $win_count -p "Switch to: ")
|
||||||
|
target_id=$(echo "$target" | cut -d' ' -f1)
|
||||||
|
|
||||||
|
# switch to target window
|
||||||
|
cmd="wmctrl -i -a \"$target_id\""
|
||||||
|
eval "$cmd"
|
||||||
|
|
1
bin/dual-monitor
Symbolic link
1
bin/dual-monitor
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
dual-monitor.sputnik
|
1
bin/dual-monitor.sputnik
Executable file
1
bin/dual-monitor.sputnik
Executable file
@ -0,0 +1 @@
|
|||||||
|
xrandr --auto --output eDP1 --primary --right-of DP1
|
5
bin/elecciones.sh
Executable file
5
bin/elecciones.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cd /tmp
|
||||||
|
wget http://www3.upm.es/elecciones/resultados/#1 -O resultados
|
||||||
|
|
||||||
|
|
41
bin/flasher.sh
Executable file
41
bin/flasher.sh
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Script to copy/link Cuevana files to your home directory or play them with your default video player.
|
||||||
|
# Tested only with one cuevana instance at a time.
|
||||||
|
# The video can be played, but it's deleted when the flash player is closed (unless you copied it).
|
||||||
|
# @author: balkian
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
PLAYER=parole;
|
||||||
|
else
|
||||||
|
PLAYER=$1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
destfile="$HOME/VideoCuevana$$"
|
||||||
|
# PID1=$(pgrep -f flash)
|
||||||
|
# info=($(lsof -p $PID1 | grep -i /tmp/flash | awk '{print $2; print $9}'))
|
||||||
|
# dir="/proc/${info[0]}/fd"
|
||||||
|
# file=${info[1]}
|
||||||
|
# #echo "pid" $pid
|
||||||
|
# #echo "file" $file
|
||||||
|
# fdn=$(ls -l $dir | grep $file | awk '{print $9}')
|
||||||
|
files=$(sudo lsof 2>/dev/null | grep "Pepper Data" | awk '{gsub(/[a-z]/,"",$4);print "/proc/"$2"/fd/"$4}' | uniq -u)
|
||||||
|
|
||||||
|
echo "Files:" $files
|
||||||
|
for file in $files; do
|
||||||
|
|
||||||
|
sel=$(zenity --list --radiolist --text "Select action for: $file" --column "pick" --column "Option" TRUE "play" FALSE "copy" FALSE "link")
|
||||||
|
case $sel in
|
||||||
|
play)
|
||||||
|
sudo $PLAYER $file
|
||||||
|
;;
|
||||||
|
link)
|
||||||
|
sudo ln -s $file $destfile && echo "Video linked successfully to $destfile." && echo "Enjoy"
|
||||||
|
sudo chown $USER:$USER $destfile
|
||||||
|
;;
|
||||||
|
copy)
|
||||||
|
sudo cp $file $destfile && echo "Video copied successfully to $destfile." && echo "Enjoy"
|
||||||
|
sudo chown $USER:$USER $destfile
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
done;
|
2
bin/gnome-terminal
Executable file
2
bin/gnome-terminal
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
one-window 'gnome-terminal' 'xdotool windowfocus $WID & xdotool key ctrl+shift+t'
|
70
bin/goear.sh
Executable file
70
bin/goear.sh
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
#bin/bash
|
||||||
|
resultado=/tmp/resultado
|
||||||
|
canciones=/tmp/canciones
|
||||||
|
enlaces=/tmp/enlaces
|
||||||
|
titulos=/tmp/titulos
|
||||||
|
#Pedimos al usuario el titulo de la canción.
|
||||||
|
echo "Introduce el título de la canción o del artista:"
|
||||||
|
read TITULO
|
||||||
|
|
||||||
|
if [ ! -d "goear" ]
|
||||||
|
then
|
||||||
|
mkdir goear
|
||||||
|
fi
|
||||||
|
#Descargamos el PHP correspondiente al título.
|
||||||
|
wget http://goear.com/search.php?q="$TITULO" -O $resultado
|
||||||
|
|
||||||
|
#La línea 130 contiene todos los enlaces a goear... de risa pero bueno.
|
||||||
|
head -130 $resultado | tail -1 > $canciones
|
||||||
|
|
||||||
|
#Mediante ER, obtenemos una lista de canciones y una lista de enlaces.
|
||||||
|
egrep -o 'listen/......./[^"]*' $canciones > $enlaces
|
||||||
|
egrep -o '"Escuchar[^"]*' $canciones > $titulos
|
||||||
|
|
||||||
|
#Mostramos al usuario los que ha encontrado en la primera página.
|
||||||
|
Linea=1
|
||||||
|
cat $titulos | while read line;
|
||||||
|
do {
|
||||||
|
echo $Linea: ${line:9}
|
||||||
|
let 'Linea += 1'
|
||||||
|
}
|
||||||
|
done
|
||||||
|
|
||||||
|
#Si no encuentra nada, sale.
|
||||||
|
CONDICION=`wc -l $titulos | awk '{print $1}'`
|
||||||
|
if [ $CONDICION == 0 ]; then
|
||||||
|
echo "No hay resultados. Prueba buscando otra cosa."
|
||||||
|
rm $resultado $canciones $enlaces $titulos
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
#Leemos qué canción quiere el usuario bajarse.
|
||||||
|
echo "¿Cuál te quieres bajar? Indica el número:"
|
||||||
|
read NUMERO
|
||||||
|
|
||||||
|
#Concatenamos http://www.goear.com con el contenido de aBajar.txt.
|
||||||
|
#PD: Alguien sabe hacerlo de manera más sencilla?
|
||||||
|
GOEAR=http://www.goear.com/
|
||||||
|
aBajar=`head -$NUMERO $enlaces | tail -1`
|
||||||
|
for LISTEN in $aBajar
|
||||||
|
do
|
||||||
|
ENLACE=${GOEAR}${LISTEN}
|
||||||
|
done
|
||||||
|
echo $ENLACE
|
||||||
|
|
||||||
|
#A partir de aquí el script no es mío, pero es muy sencillo de leer.
|
||||||
|
fileid=`echo $ENLACE | cut -d '/' -f 5`
|
||||||
|
xmlurl="http://www.goear.com/tracker758.php?f="$fileid
|
||||||
|
infoline=`wget -qO- $xmlurl | grep ".mp3"`
|
||||||
|
mp3url=`echo $infoline | cut -d '"' -f6`
|
||||||
|
artist=`echo $infoline | cut -d '"' -f10`
|
||||||
|
title=`echo $infoline | cut -d '"' -f12`
|
||||||
|
filename=goear/"$artist-$title.mp3"
|
||||||
|
wget $mp3url -O "$filename"
|
||||||
|
rm $resultado $canciones $enlaces $titulos
|
||||||
|
|
||||||
|
echo "¿Quieres reproducirla?[Y/n]"
|
||||||
|
read RES
|
||||||
|
if [ -z "$RES" -o "$RES" = "Y" -o "$RES" = "y" ];then
|
||||||
|
mplayer "$filename";
|
||||||
|
fi;
|
5
bin/i3-one-instance
Executable file
5
bin/i3-one-instance
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
python2 $HOME/.bin/i3-wm-scripts/nextmatch.py $*
|
||||||
|
if [ $? -gt 0 ]; then
|
||||||
|
$* & sleep 0.1 && python2 $HOME/.bin/i3-wm-scripts/nextmatch.py $*
|
||||||
|
fi
|
11
bin/i3-one-tmux
Executable file
11
bin/i3-one-tmux
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/zsh
|
||||||
|
python2 $HOME/.bin/i3-wm-scripts/nextmatch.py urxvt
|
||||||
|
if [ $? -gt 0 ]; then
|
||||||
|
urxvt & sleep 0.1 && python2 $HOME/.bin/i3-wm-scripts/nextmatch.py urxvt
|
||||||
|
fi
|
||||||
|
if [ "$#" -gt 0 ]; then
|
||||||
|
eval "tmux neww"
|
||||||
|
sleep 0.2
|
||||||
|
xdotool type "$*"
|
||||||
|
xdotool key Return
|
||||||
|
fi
|
1
bin/i3-wm-scripts
Submodule
1
bin/i3-wm-scripts
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 477335215dd1fff4f23b82afbb92e7ad1bd4552e
|
BIN
bin/icon_spotify.png
Normal file
BIN
bin/icon_spotify.png
Normal file
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
24
bin/one-instance
Executable file
24
bin/one-instance
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ "x$1" != "x" ]
|
||||||
|
then
|
||||||
|
pgrep -l -u "$USER" -f "$1" | egrep -v "/bin/bash|/bin/sh" | grep -vq "$$"
|
||||||
|
if [ $? == "0" ]
|
||||||
|
then
|
||||||
|
WID=`xdotool search --class $1 | head -1`
|
||||||
|
wmctrl -i -a $WID
|
||||||
|
if [ "x$2" != "x" ]
|
||||||
|
then
|
||||||
|
eval "$2"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "x$3" == "x" ]
|
||||||
|
then
|
||||||
|
/usr/bin/$1
|
||||||
|
else
|
||||||
|
eval "$3"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Usage: one-instance program-name [extra action]"
|
||||||
|
fi
|
||||||
|
|
27
bin/one-instance (copy)
Executable file
27
bin/one-instance (copy)
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ "x$1" != "x" ]
|
||||||
|
then
|
||||||
|
pgrep -fx $1 1> /dev/null
|
||||||
|
if [ $? == "0" ]
|
||||||
|
then
|
||||||
|
echo "running"
|
||||||
|
ps aux | grep terminator > /home/balkian/LOG
|
||||||
|
WID=`xdotool search --class $1 | head -1`
|
||||||
|
wmctrl -i -a $WID
|
||||||
|
if [ "x$2" != "x" ]
|
||||||
|
then
|
||||||
|
eval "$2"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "x$3" == "x" ]
|
||||||
|
then
|
||||||
|
echo "not running"
|
||||||
|
/usr/bin/$1
|
||||||
|
else
|
||||||
|
eval "$3"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Usage: one-instance program-name [extra action]"
|
||||||
|
fi
|
||||||
|
|
10
bin/one-terminator.sh
Executable file
10
bin/one-terminator.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
pgrep -u "$USER" gnome-terminal | grep -qv "$$"
|
||||||
|
if [ "$?" == "0" ]; then
|
||||||
|
WID=`xdotool search --class "terminator" | head -1`
|
||||||
|
xdotool windowfocus $WID
|
||||||
|
xdotool key ctrl+shift+t
|
||||||
|
#wmctrl -i -a $WID
|
||||||
|
else
|
||||||
|
/usr/bin/gnome-terminal
|
||||||
|
fi
|
27
bin/one-tmux
Executable file
27
bin/one-tmux
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
TERMINAL_EMULATOR='urxvt'
|
||||||
|
tab=1
|
||||||
|
pgrep -l -u "$USER" -f "$TERMINAL_EMULATOR" | egrep -v "/bin/zsh|/bin/bash|/bin/sh" | grep -vq "$$"
|
||||||
|
if [ $? != "0" ]
|
||||||
|
then
|
||||||
|
/usr/bin/$TERMINAL_EMULATOR &
|
||||||
|
sleep 1
|
||||||
|
tab=0
|
||||||
|
fi
|
||||||
|
WID=`xdotool search --class $TERMINAL_EMULATOR | tail -1`
|
||||||
|
wmctrl -i -a $WID
|
||||||
|
if [ "x$1" != "x" ]
|
||||||
|
then
|
||||||
|
if [ "x$1" == "xhelp" ]
|
||||||
|
then
|
||||||
|
echo "Usage: $0 [command-in-new-window]"
|
||||||
|
else
|
||||||
|
if [ $tab == 1 ]
|
||||||
|
then
|
||||||
|
eval "tmux neww"
|
||||||
|
sleep 0.2
|
||||||
|
fi
|
||||||
|
xdotool type "$*"
|
||||||
|
xdotool key Return
|
||||||
|
fi
|
||||||
|
fi
|
2
bin/play-europa.sh
Executable file
2
bin/play-europa.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
rtmpdump --live --quiet --buffer 3000 -r rtmp://antena3fms35geobloqueolivefs.fplive.net/antena3fms35geobloqueolive-live/ --playpath stream-europafm | mplayer -vo null -idle -
|
2
bin/play-hitfm.sh
Executable file
2
bin/play-hitfm.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
mplayer -vo null -idle http://ice.5.c3.audiovideoweb.com:8000/4c3ice5500
|
2
bin/play-kiss.sh
Executable file
2
bin/play-kiss.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
rtmpdump --live --quiet --buffer 3000 -r rtmp://kissfm.es.flash3.glb.ipercast.net/kissfm.es-live --playpath aac.stream | mplayer -vo null -idle -
|
2
bin/play-m80.sh
Executable file
2
bin/play-m80.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
curl -s http://4633.live.streamtheworld.com/M80RADIOAAC | mplayer -vo null -idle -
|
36
bin/playlist-radios.xml
Normal file
36
bin/playlist-radios.xml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<playlist xmlns="http://xspf.org/ns/0/" xmlns:vlc="http://www.videolan.org/vlc/playlist/ns/0/" version="1">
|
||||||
|
<title>Playlist</title>
|
||||||
|
<trackList>
|
||||||
|
<track>
|
||||||
|
<location>rtmp://antena3fms35geobloqueolivefs.fplive.net/antena3fms35geobloqueolive-live/stream-europafm</location>
|
||||||
|
<title>EuropaFM</title>
|
||||||
|
<extension application="http://www.videolan.org/vlc/playlist/0">
|
||||||
|
<vlc:id>0</vlc:id>
|
||||||
|
<vlc:option>network-caching=1000</vlc:option>
|
||||||
|
</extension>
|
||||||
|
</track>
|
||||||
|
<track>
|
||||||
|
<location>http://4633.live.streamtheworld.com:80/M80RADIO_SC</location>
|
||||||
|
<title>M80 Radio</title>
|
||||||
|
<duration>125287770</duration>
|
||||||
|
<extension application="http://www.videolan.org/vlc/playlist/0">
|
||||||
|
<vlc:id>1</vlc:id>
|
||||||
|
<vlc:option>network-caching=1000</vlc:option>
|
||||||
|
</extension>
|
||||||
|
</track>
|
||||||
|
<track>
|
||||||
|
<location>rtmp://kissfm.es.flash3.glb.ipercast.net/kissfm.es-live/aac.stream</location>
|
||||||
|
<title>KISSFM</title>
|
||||||
|
<extension application="http://www.videolan.org/vlc/playlist/0">
|
||||||
|
<vlc:id>2</vlc:id>
|
||||||
|
<vlc:option>network-caching=1000</vlc:option>
|
||||||
|
</extension>
|
||||||
|
</track>
|
||||||
|
</trackList>
|
||||||
|
<extension application="http://www.videolan.org/vlc/playlist/0">
|
||||||
|
<vlc:item tid="0"/>
|
||||||
|
<vlc:item tid="1"/>
|
||||||
|
<vlc:item tid="2"/>
|
||||||
|
</extension>
|
||||||
|
</playlist>
|
10
bin/replace-accented.sh
Executable file
10
bin/replace-accented.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Note: input should end with a newline
|
||||||
|
|
||||||
|
LINES=''
|
||||||
|
while read LINE; do
|
||||||
|
echo $LINE | sed 's/á/a/g' | sed 's/Á/A/g' | sed 's/é/e/g' | sed 's/É/E/g' | sed 's/í/i/g' | sed 's/Í/I/g' | sed 's/ó/o/g' | sed 's/Ó/O/g' | sed 's/ú/u/g' | sed 's/Ú/U/g' | sed 's/ñ/n/g' | sed 's/Ñ/N/g' | sed 's/ü/u/g' | sed 's/Ü/U/g'
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
1
bin/single-monitor
Symbolic link
1
bin/single-monitor
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
single-monitor.sputnik
|
1
bin/single-monitor.sputnik
Executable file
1
bin/single-monitor.sputnik
Executable file
@ -0,0 +1 @@
|
|||||||
|
xrandr --auto --output eDP1 --primary --output DP1 --off
|
417
bin/spotify-notify.py
Normal file
417
bin/spotify-notify.py
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# Spotify-notify
|
||||||
|
#
|
||||||
|
# v0.6d (28th aug 11)
|
||||||
|
# by JonW (jon.neverwinter@gmail.com)
|
||||||
|
# patched 20110907 by Jansen Price (sumpygump@gmail.com)
|
||||||
|
# patched 20120729 by Jansen Price (sumpygump@gmail.com) and brandl.matthaeus
|
||||||
|
#
|
||||||
|
# Original by SveinT (sveint@gmail.com)
|
||||||
|
# up to v0.5.2 (27th jan 11)
|
||||||
|
|
||||||
|
|
||||||
|
import dbus
|
||||||
|
|
||||||
|
import gobject, gtk, os, tempfile, sys, time, re, indicate, urllib2
|
||||||
|
from optparse import OptionParser
|
||||||
|
from subprocess import *
|
||||||
|
|
||||||
|
# The url to use when fetching spotify track information.
|
||||||
|
SPOTIFY_OPEN_URL = "http://open.spotify.com/track/"
|
||||||
|
|
||||||
|
# The path to this application's directory.
|
||||||
|
APPLICATION_DIR = sys.path[0] + "/"
|
||||||
|
|
||||||
|
# The file path to spotify. If empty, it will try to auto detect.
|
||||||
|
SPOTIFY_PROCESS_NAME = 'spotify'
|
||||||
|
|
||||||
|
# How often to check if spotify has been closed (in milliseconds).
|
||||||
|
SPOTIFY_CLOSED_CHECK = 20000
|
||||||
|
|
||||||
|
class SpotifyNotify():
|
||||||
|
|
||||||
|
spotifyPath = ''
|
||||||
|
|
||||||
|
tryToReconnect = False
|
||||||
|
|
||||||
|
tmpfile = False
|
||||||
|
|
||||||
|
def __init__(self, debugger):
|
||||||
|
self.debug = debugger
|
||||||
|
self.spotifyservice = False
|
||||||
|
|
||||||
|
self.prev = 0
|
||||||
|
self.new = False
|
||||||
|
self.prevMeta = {}
|
||||||
|
self.notifyid = 0
|
||||||
|
|
||||||
|
self.connect()
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if SpotifyNotify and SpotifyNotify.tmpfile:
|
||||||
|
SpotifyNotify.tmpfile.close()
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.debug.out("Connecting to spotify.")
|
||||||
|
self.bus = dbus.Bus(dbus.Bus.TYPE_SESSION)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.spotifyservice = self.bus.get_object(
|
||||||
|
'com.spotify.qt',
|
||||||
|
'/org/mpris/MediaPlayer2'
|
||||||
|
)
|
||||||
|
SpotifyNotify.tryToReconnect = False
|
||||||
|
except Exception, e:
|
||||||
|
self.spotifyservice = False
|
||||||
|
self.debug.out("Failed to connect.")
|
||||||
|
self.debug.out(e)
|
||||||
|
|
||||||
|
def executeCommand(self, key):
|
||||||
|
if not key:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.connect()
|
||||||
|
self.debug.out("Running command: {0}".format(key))
|
||||||
|
self.cmd = self.spotifyservice.get_dbus_method(key, 'org.mpris.MediaPlayer2.Player')
|
||||||
|
self.cmd()
|
||||||
|
|
||||||
|
def pollChange(self):
|
||||||
|
try:
|
||||||
|
self.spotifyservice = self.bus.get_object('com.spotify.qt', '/')
|
||||||
|
self.cmd = self.spotifyservice.get_dbus_method(
|
||||||
|
'GetMetadata',
|
||||||
|
'org.freedesktop.MediaPlayer2'
|
||||||
|
)
|
||||||
|
self.new = self.cmd()
|
||||||
|
except Exception, e:
|
||||||
|
self.debug.out('Spotify service not connected.')
|
||||||
|
SpotifyNotify.tryToReconnect = True
|
||||||
|
|
||||||
|
if (self.prev != self.new):
|
||||||
|
self.trackChange(self.new)
|
||||||
|
self.prev = self.new
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def trackChange(self, *trackChange):
|
||||||
|
if not trackChange[0]:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.prev = trackChange[0]
|
||||||
|
|
||||||
|
trackInfo = {}
|
||||||
|
trackMap = {
|
||||||
|
'artist' : 'xesam:artist',
|
||||||
|
'album' : 'xesam:album',
|
||||||
|
'title' : 'xesam:title',
|
||||||
|
'year' : 'xesam:contentCreated',
|
||||||
|
'trackhash' : 'mpris:trackid',
|
||||||
|
'arturl' : 'mpris:artUrl'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch the track information for the notification window.
|
||||||
|
for key in trackMap:
|
||||||
|
if not trackMap[key] in trackChange[0]:
|
||||||
|
continue
|
||||||
|
piece = trackChange[0][trackMap[key]]
|
||||||
|
if key == 'year':
|
||||||
|
piece = str(piece[:4])
|
||||||
|
elif isinstance(piece, list):
|
||||||
|
piece = ", ".join(piece)
|
||||||
|
|
||||||
|
if not isinstance(piece, str):
|
||||||
|
piece = str(piece)
|
||||||
|
|
||||||
|
trackInfo[key] = piece.encode('utf-8')
|
||||||
|
|
||||||
|
if not self.prevMeta\
|
||||||
|
or not SpotifyNotify.tmpfile\
|
||||||
|
or 'iconfilename' not in self.prevMeta\
|
||||||
|
or self.prevMeta['artist'] != trackInfo['artist']\
|
||||||
|
or self.prevMeta['album'] != trackInfo['album']:
|
||||||
|
trackInfo['iconfilename'] = self.retrieveCoverImage(trackInfo)
|
||||||
|
|
||||||
|
cover_image = ''
|
||||||
|
|
||||||
|
if 'iconfilename' in trackInfo:
|
||||||
|
cover_image = trackInfo['iconfilename']
|
||||||
|
elif 'iconfilename' in self.prevMeta:
|
||||||
|
cover_image = self.prevMeta['iconfilename']
|
||||||
|
trackInfo['iconfilename'] = cover_image
|
||||||
|
|
||||||
|
if cover_image == '':
|
||||||
|
cover_image = APPLICATION_DIR + 'icon_spotify.png'
|
||||||
|
|
||||||
|
self.prevMeta = trackInfo
|
||||||
|
|
||||||
|
# Connect to notification interface on DBUS.
|
||||||
|
self.notifyservice = self.bus.get_object(
|
||||||
|
'org.freedesktop.Notifications',
|
||||||
|
'/org/freedesktop/Notifications'
|
||||||
|
)
|
||||||
|
self.notifyservice = dbus.Interface(
|
||||||
|
self.notifyservice,
|
||||||
|
"org.freedesktop.Notifications"
|
||||||
|
)
|
||||||
|
notifyText = "{0}\n{1}".format(
|
||||||
|
trackInfo['title'],
|
||||||
|
trackInfo['album']
|
||||||
|
)
|
||||||
|
if len(trackInfo['year']) > 0:
|
||||||
|
notifyText += " ({0})".format(trackInfo['year'])
|
||||||
|
|
||||||
|
# Send track change information to stdout
|
||||||
|
print "Changing track : {0} | {1} | {2} ({3})".format(
|
||||||
|
trackInfo['artist'],
|
||||||
|
trackInfo['title'],
|
||||||
|
trackInfo['album'],
|
||||||
|
trackInfo['year']
|
||||||
|
)
|
||||||
|
|
||||||
|
# The second param is the replace id, so get the notify id back,
|
||||||
|
# store it, and send it as the replacement on the next call.
|
||||||
|
self.notifyid = self.notifyservice.Notify(
|
||||||
|
"Spotify-notify",
|
||||||
|
self.notifyid,
|
||||||
|
cover_image,
|
||||||
|
trackInfo['artist'],
|
||||||
|
notifyText,
|
||||||
|
[],
|
||||||
|
{},
|
||||||
|
2000
|
||||||
|
)
|
||||||
|
|
||||||
|
def retrieveCoverImage(self, trackInfo):
|
||||||
|
if 'arturl' in trackInfo:
|
||||||
|
self.debug.out("Simply retrieving image from {0}".format(trackInfo['arturl']))
|
||||||
|
iconfilename = self.fetchCoverImage(trackInfo['arturl'])
|
||||||
|
else:
|
||||||
|
#if (trackInfo['trackhash'][0:14] == 'spotify:local:'):
|
||||||
|
# self.debug.out("Track is a local file. No art available.")
|
||||||
|
# return ''
|
||||||
|
|
||||||
|
self.debug.out("Attempting to fetch image from spotify")
|
||||||
|
iconfilename = self.fetchCoverImageSpotify(
|
||||||
|
trackInfo['artist'],
|
||||||
|
trackInfo['album'],
|
||||||
|
trackInfo['trackhash']
|
||||||
|
)
|
||||||
|
return iconfilename
|
||||||
|
|
||||||
|
def fetchCoverImageSpotify(self, artist, album, trackhash):
|
||||||
|
try:
|
||||||
|
trackid = trackhash.split(":")[2]
|
||||||
|
url = SPOTIFY_OPEN_URL + trackid
|
||||||
|
tracksite = urllib2.urlopen(url).read()
|
||||||
|
|
||||||
|
# Attempt to get the image url from the open graph image meta tag.
|
||||||
|
imageurl = False
|
||||||
|
metaMatch = re.search(
|
||||||
|
'<meta\s[^\>]*property\s*=\s*["\']og:image["\'][^\>]*/?>',
|
||||||
|
tracksite
|
||||||
|
)
|
||||||
|
if metaMatch:
|
||||||
|
contentMatch = re.search(
|
||||||
|
'content\s*=\s*["\']([^\"\']*)["\']',
|
||||||
|
metaMatch.group(0)
|
||||||
|
)
|
||||||
|
if contentMatch:
|
||||||
|
imageurl = contentMatch.group(1)
|
||||||
|
|
||||||
|
if not imageurl:
|
||||||
|
self.debug.out("No cover available.")
|
||||||
|
raise()
|
||||||
|
|
||||||
|
return self.fetchCoverImage(imageurl)
|
||||||
|
except Exception, e:
|
||||||
|
self.debug.out("Couldn't fetch cover image.")
|
||||||
|
self.debug.out(e)
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def fetchCoverImage(self, url):
|
||||||
|
# Close the temporary image file, we are going to make a new one.
|
||||||
|
if SpotifyNotify.tmpfile:
|
||||||
|
SpotifyNotify.tmpfile.close()
|
||||||
|
SpotifyNotify.tmpfile = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
SpotifyNotify.tmpfile = tempfile.NamedTemporaryFile()
|
||||||
|
tmpfilename = SpotifyNotify.tmpfile.name
|
||||||
|
self.debug.out("Album art tmp filepath: {0}".format(tmpfilename))
|
||||||
|
|
||||||
|
coverfile = urllib2.urlopen(url)
|
||||||
|
SpotifyNotify.tmpfile.write(coverfile.read())
|
||||||
|
SpotifyNotify.tmpfile.flush()
|
||||||
|
return tmpfilename
|
||||||
|
except Exception, e:
|
||||||
|
self.debug.out("Couldn't fetch cover image.")
|
||||||
|
self.debug.out(e)
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def startSpotify(Debug):
|
||||||
|
if not SpotifyNotify.spotifyPath:
|
||||||
|
Debug.out("No spotify process identifier found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
ident = SpotifyNotify.spotifyPath
|
||||||
|
Debug.out("Looking for spotify as: {0}".format(ident))
|
||||||
|
|
||||||
|
procs = SpotifyNotify.checkForProcess(
|
||||||
|
'ps x | grep "{0}" | grep -v grep'.format(ident),
|
||||||
|
Debug
|
||||||
|
)
|
||||||
|
if len(procs):
|
||||||
|
Debug.out("Spotify process found as: {0}".format(" ".join(procs[0])))
|
||||||
|
return
|
||||||
|
|
||||||
|
Debug.out("Starting new Spotify now.")
|
||||||
|
|
||||||
|
FNULL = open('/dev/null', 'w')
|
||||||
|
spid = Popen([ident], stdout=FNULL, stderr=FNULL).pid
|
||||||
|
if spid:
|
||||||
|
Debug.out("Spotify started, pid: {0}.".format(spid))
|
||||||
|
else:
|
||||||
|
Debug.out("Spotify could not be started.")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def checkForClosedSpotify(SN, Debug):
|
||||||
|
if not SpotifyNotify.spotifyPath:
|
||||||
|
Debug.out("No spotify process identifier found.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
ident = SpotifyNotify.spotifyPath
|
||||||
|
Debug.out("Looking for spotify as: {0}".format(ident))
|
||||||
|
|
||||||
|
procs = SpotifyNotify.checkForProcess(
|
||||||
|
'ps x | grep "{0}" | grep -v grep'.format(ident),
|
||||||
|
Debug
|
||||||
|
)
|
||||||
|
if len(procs):
|
||||||
|
Debug.out("Spotify process found as: {0}".format(" ".join(procs[0])))
|
||||||
|
|
||||||
|
if (SpotifyNotify.tryToReconnect):
|
||||||
|
SN.connect()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
if SpotifyNotify.tmpfile:
|
||||||
|
SpotifyNotify.tmpfile.close()
|
||||||
|
|
||||||
|
Debug.out("Spotify has been closed, therefore I die.")
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def preventDuplicate(Debug):
|
||||||
|
mypid = os.getpid()
|
||||||
|
Debug.out("My pid: {0}".format(mypid))
|
||||||
|
|
||||||
|
proc = SpotifyNotify.checkForProcess('ps -p {0}'.format(mypid), Debug)
|
||||||
|
if not proc[0][3]:
|
||||||
|
return
|
||||||
|
|
||||||
|
process = proc[0][3]
|
||||||
|
search = 'ps -C {0}'.format(process)
|
||||||
|
|
||||||
|
Debug.out("Looking for other processes named: {0}".format(process).strip())
|
||||||
|
|
||||||
|
if process == 'python':
|
||||||
|
if not sys.argv[0]:
|
||||||
|
Debug.out("Process started using python, cannot determine script name.")
|
||||||
|
return
|
||||||
|
|
||||||
|
search = 'ps ax | grep "python {0}" | grep -v grep'.format(sys.argv[0])
|
||||||
|
|
||||||
|
for line in SpotifyNotify.checkForProcess(search, Debug):
|
||||||
|
if int(line[0]) != mypid:
|
||||||
|
print("This program was already running.")
|
||||||
|
Debug.out("I am a duplicate. I shall end myself. ({0})".format(" ".join(line)))
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def checkForProcess(proc, Debug):
|
||||||
|
output = []
|
||||||
|
|
||||||
|
for line in Popen(proc, shell=True, stdout=PIPE).stdout:
|
||||||
|
fields = line.split()
|
||||||
|
if not fields[0].isdigit():
|
||||||
|
continue
|
||||||
|
|
||||||
|
output.append(fields)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
class DebugMe():
|
||||||
|
def __init__(self, toggle):
|
||||||
|
if toggle:
|
||||||
|
self.output = True
|
||||||
|
else:
|
||||||
|
self.output = False
|
||||||
|
|
||||||
|
def out(self, msg):
|
||||||
|
if not self.output:
|
||||||
|
return
|
||||||
|
|
||||||
|
print(">> {0}".format(msg))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'-a',
|
||||||
|
'--action',
|
||||||
|
dest = 'action',
|
||||||
|
default = None,
|
||||||
|
type = 'choice',
|
||||||
|
choices = ['playPause', 'play', 'pause', 'next', 'previous'],
|
||||||
|
help = 'Music player actions (playPause/play/pause/next/previous).'
|
||||||
|
)
|
||||||
|
parser.add_option(
|
||||||
|
'-n',
|
||||||
|
'--skip_notify',
|
||||||
|
dest = 'skipNotify',
|
||||||
|
action = 'store_true',
|
||||||
|
default = False,
|
||||||
|
help = 'Song change notifications will be turned off.'
|
||||||
|
)
|
||||||
|
parser.add_option(
|
||||||
|
'-d',
|
||||||
|
'--debug',
|
||||||
|
dest = 'debug',
|
||||||
|
action = 'store_true',
|
||||||
|
default = False,
|
||||||
|
help = 'Debug messages will be displayed.'
|
||||||
|
)
|
||||||
|
|
||||||
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
Debug = DebugMe(options.debug)
|
||||||
|
print("Spotify-notify v0.6")
|
||||||
|
|
||||||
|
if SPOTIFY_PROCESS_NAME:
|
||||||
|
SpotifyNotify.spotifyPath = SPOTIFY_PROCESS_NAME
|
||||||
|
else:
|
||||||
|
print "Spotify is not running"
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
SN = SpotifyNotify(Debug)
|
||||||
|
|
||||||
|
if options.action:
|
||||||
|
action = options.action
|
||||||
|
action = action[0:1].upper() + action[1:]
|
||||||
|
SN.executeCommand(action)
|
||||||
|
|
||||||
|
SpotifyNotify.preventDuplicate(Debug)
|
||||||
|
|
||||||
|
try:
|
||||||
|
indicateserver = indicate.indicate_server_ref_default()
|
||||||
|
indicateserver.set_type("music.spotify")
|
||||||
|
indicateserver.set_desktop_file("/usr/share/applications/spotify.desktop")
|
||||||
|
indicateserver.show()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
SN.pollChange()
|
||||||
|
print "Done"
|
||||||
|
|
420
bin/spotify-remote.py
Executable file
420
bin/spotify-remote.py
Executable file
@ -0,0 +1,420 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
Spoify-remote
|
||||||
|
Modified version of Spotify-notify that runs once when invoked instead of looping.
|
||||||
|
v0.6d (28th aug 11)
|
||||||
|
by JonW (jon.neverwinter@gmail.com)
|
||||||
|
patched 20110907 by Jansen Price (sumpygump@gmail.com)
|
||||||
|
patched 20120729 by Jansen Price (sumpygump@gmail.com) and brandl.matthaeus
|
||||||
|
modified 20130405 by Fernando Sánchez (balkian@gmail.com)
|
||||||
|
|
||||||
|
Original by SveinT (sveint@gmail.com)
|
||||||
|
up to v0.5.2 (27th jan 11)
|
||||||
|
'''
|
||||||
|
|
||||||
|
import dbus
|
||||||
|
|
||||||
|
import gobject, gtk, os, tempfile, sys, time, re, indicate, urllib2
|
||||||
|
from optparse import OptionParser
|
||||||
|
from subprocess import *
|
||||||
|
|
||||||
|
# The url to use when fetching spotify track information.
|
||||||
|
SPOTIFY_OPEN_URL = "http://open.spotify.com/track/"
|
||||||
|
|
||||||
|
# The path to this application's directory.
|
||||||
|
APPLICATION_DIR = sys.path[0] + "/"
|
||||||
|
|
||||||
|
# The file path to spotify. If empty, it will try to auto detect.
|
||||||
|
SPOTIFY_PROCESS_NAME = 'spotify'
|
||||||
|
|
||||||
|
# How often to check if spotify has been closed (in milliseconds).
|
||||||
|
SPOTIFY_CLOSED_CHECK = 20000
|
||||||
|
|
||||||
|
class SpotifyNotify():
|
||||||
|
|
||||||
|
spotifyPath = ''
|
||||||
|
|
||||||
|
tryToReconnect = False
|
||||||
|
|
||||||
|
tmpfile = False
|
||||||
|
|
||||||
|
def __init__(self, debugger):
|
||||||
|
self.debug = debugger
|
||||||
|
self.spotifyservice = False
|
||||||
|
|
||||||
|
self.prev = 0
|
||||||
|
self.new = False
|
||||||
|
self.prevMeta = {}
|
||||||
|
self.notifyid = 0
|
||||||
|
|
||||||
|
self.connect()
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if SpotifyNotify and SpotifyNotify.tmpfile:
|
||||||
|
SpotifyNotify.tmpfile.close()
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.debug.out("Connecting to spotify.")
|
||||||
|
self.bus = dbus.Bus(dbus.Bus.TYPE_SESSION)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.spotifyservice = self.bus.get_object(
|
||||||
|
'com.spotify.qt',
|
||||||
|
'/org/mpris/MediaPlayer2'
|
||||||
|
)
|
||||||
|
SpotifyNotify.tryToReconnect = False
|
||||||
|
except Exception, e:
|
||||||
|
self.spotifyservice = False
|
||||||
|
self.debug.out("Failed to connect.")
|
||||||
|
self.debug.out(e)
|
||||||
|
|
||||||
|
def executeCommand(self, key):
|
||||||
|
if not key:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.connect()
|
||||||
|
self.debug.out("Running command: {0}".format(key))
|
||||||
|
self.cmd = self.spotifyservice.get_dbus_method(key, 'org.mpris.MediaPlayer2.Player')
|
||||||
|
self.cmd()
|
||||||
|
|
||||||
|
def pollChange(self):
|
||||||
|
try:
|
||||||
|
self.spotifyservice = self.bus.get_object('com.spotify.qt', '/')
|
||||||
|
self.cmd = self.spotifyservice.get_dbus_method(
|
||||||
|
'GetMetadata',
|
||||||
|
'org.freedesktop.MediaPlayer2'
|
||||||
|
)
|
||||||
|
self.new = self.cmd()
|
||||||
|
except Exception, e:
|
||||||
|
self.debug.out('Spotify service not connected.')
|
||||||
|
SpotifyNotify.tryToReconnect = True
|
||||||
|
|
||||||
|
if (self.prev != self.new):
|
||||||
|
self.trackChange(self.new)
|
||||||
|
self.prev = self.new
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def trackChange(self, *trackChange):
|
||||||
|
if not trackChange[0]:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.prev = trackChange[0]
|
||||||
|
|
||||||
|
trackInfo = {}
|
||||||
|
trackMap = {
|
||||||
|
'artist' : 'xesam:artist',
|
||||||
|
'album' : 'xesam:album',
|
||||||
|
'title' : 'xesam:title',
|
||||||
|
'year' : 'xesam:contentCreated',
|
||||||
|
'trackhash' : 'mpris:trackid',
|
||||||
|
'arturl' : 'mpris:artUrl'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch the track information for the notification window.
|
||||||
|
for key in trackMap:
|
||||||
|
if not trackMap[key] in trackChange[0]:
|
||||||
|
continue
|
||||||
|
piece = trackChange[0][trackMap[key]]
|
||||||
|
if key == 'year':
|
||||||
|
piece = str(piece[:4])
|
||||||
|
elif isinstance(piece, list):
|
||||||
|
piece = ", ".join(piece)
|
||||||
|
|
||||||
|
if not isinstance(piece, str):
|
||||||
|
piece = str(piece)
|
||||||
|
|
||||||
|
trackInfo[key] = piece.encode('utf-8')
|
||||||
|
|
||||||
|
if not self.prevMeta\
|
||||||
|
or not SpotifyNotify.tmpfile\
|
||||||
|
or 'iconfilename' not in self.prevMeta\
|
||||||
|
or self.prevMeta['artist'] != trackInfo['artist']\
|
||||||
|
or self.prevMeta['album'] != trackInfo['album']:
|
||||||
|
trackInfo['iconfilename'] = self.retrieveCoverImage(trackInfo)
|
||||||
|
|
||||||
|
cover_image = ''
|
||||||
|
|
||||||
|
if 'iconfilename' in trackInfo:
|
||||||
|
cover_image = trackInfo['iconfilename']
|
||||||
|
elif 'iconfilename' in self.prevMeta:
|
||||||
|
cover_image = self.prevMeta['iconfilename']
|
||||||
|
trackInfo['iconfilename'] = cover_image
|
||||||
|
|
||||||
|
if cover_image == '':
|
||||||
|
cover_image = APPLICATION_DIR + 'icon_spotify.png'
|
||||||
|
|
||||||
|
self.prevMeta = trackInfo
|
||||||
|
|
||||||
|
# Connect to notification interface on DBUS.
|
||||||
|
self.notifyservice = self.bus.get_object(
|
||||||
|
'org.freedesktop.Notifications',
|
||||||
|
'/org/freedesktop/Notifications'
|
||||||
|
)
|
||||||
|
self.notifyservice = dbus.Interface(
|
||||||
|
self.notifyservice,
|
||||||
|
"org.freedesktop.Notifications"
|
||||||
|
)
|
||||||
|
notifyText = "{0}\n{1}".format(
|
||||||
|
trackInfo['title'],
|
||||||
|
trackInfo['album']
|
||||||
|
)
|
||||||
|
if len(trackInfo['year']) > 0:
|
||||||
|
notifyText += " ({0})".format(trackInfo['year'])
|
||||||
|
|
||||||
|
# Send track change information to stdout
|
||||||
|
print "Changing track : {0} | {1} | {2} ({3})".format(
|
||||||
|
trackInfo['artist'],
|
||||||
|
trackInfo['title'],
|
||||||
|
trackInfo['album'],
|
||||||
|
trackInfo['year']
|
||||||
|
)
|
||||||
|
|
||||||
|
# The second param is the replace id, so get the notify id back,
|
||||||
|
# store it, and send it as the replacement on the next call.
|
||||||
|
self.notifyid = self.notifyservice.Notify(
|
||||||
|
"Spotify-notify",
|
||||||
|
self.notifyid,
|
||||||
|
cover_image,
|
||||||
|
trackInfo['artist'],
|
||||||
|
notifyText,
|
||||||
|
[],
|
||||||
|
{},
|
||||||
|
2000
|
||||||
|
)
|
||||||
|
|
||||||
|
def retrieveCoverImage(self, trackInfo):
|
||||||
|
if 'arturl' in trackInfo:
|
||||||
|
self.debug.out("Simply retrieving image from {0}".format(trackInfo['arturl']))
|
||||||
|
iconfilename = self.fetchCoverImage(trackInfo['arturl'])
|
||||||
|
else:
|
||||||
|
#if (trackInfo['trackhash'][0:14] == 'spotify:local:'):
|
||||||
|
# self.debug.out("Track is a local file. No art available.")
|
||||||
|
# return ''
|
||||||
|
|
||||||
|
self.debug.out("Attempting to fetch image from spotify")
|
||||||
|
iconfilename = self.fetchCoverImageSpotify(
|
||||||
|
trackInfo['artist'],
|
||||||
|
trackInfo['album'],
|
||||||
|
trackInfo['trackhash']
|
||||||
|
)
|
||||||
|
return iconfilename
|
||||||
|
|
||||||
|
def fetchCoverImageSpotify(self, artist, album, trackhash):
|
||||||
|
try:
|
||||||
|
trackid = trackhash.split(":")[2]
|
||||||
|
url = SPOTIFY_OPEN_URL + trackid
|
||||||
|
tracksite = urllib2.urlopen(url).read()
|
||||||
|
|
||||||
|
# Attempt to get the image url from the open graph image meta tag.
|
||||||
|
imageurl = False
|
||||||
|
metaMatch = re.search(
|
||||||
|
'<meta\s[^\>]*property\s*=\s*["\']og:image["\'][^\>]*/?>',
|
||||||
|
tracksite
|
||||||
|
)
|
||||||
|
if metaMatch:
|
||||||
|
contentMatch = re.search(
|
||||||
|
'content\s*=\s*["\']([^\"\']*)["\']',
|
||||||
|
metaMatch.group(0)
|
||||||
|
)
|
||||||
|
if contentMatch:
|
||||||
|
imageurl = contentMatch.group(1)
|
||||||
|
|
||||||
|
if not imageurl:
|
||||||
|
self.debug.out("No cover available.")
|
||||||
|
raise()
|
||||||
|
|
||||||
|
return self.fetchCoverImage(imageurl)
|
||||||
|
except Exception, e:
|
||||||
|
self.debug.out("Couldn't fetch cover image.")
|
||||||
|
self.debug.out(e)
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def fetchCoverImage(self, url):
|
||||||
|
# Close the temporary image file, we are going to make a new one.
|
||||||
|
if SpotifyNotify.tmpfile:
|
||||||
|
SpotifyNotify.tmpfile.close()
|
||||||
|
SpotifyNotify.tmpfile = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
SpotifyNotify.tmpfile = tempfile.NamedTemporaryFile()
|
||||||
|
tmpfilename = SpotifyNotify.tmpfile.name
|
||||||
|
self.debug.out("Album art tmp filepath: {0}".format(tmpfilename))
|
||||||
|
|
||||||
|
coverfile = urllib2.urlopen(url)
|
||||||
|
SpotifyNotify.tmpfile.write(coverfile.read())
|
||||||
|
SpotifyNotify.tmpfile.flush()
|
||||||
|
return tmpfilename
|
||||||
|
except Exception, e:
|
||||||
|
self.debug.out("Couldn't fetch cover image.")
|
||||||
|
self.debug.out(e)
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def startSpotify(Debug):
|
||||||
|
if not SpotifyNotify.spotifyPath:
|
||||||
|
Debug.out("No spotify process identifier found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
ident = SpotifyNotify.spotifyPath
|
||||||
|
Debug.out("Looking for spotify as: {0}".format(ident))
|
||||||
|
|
||||||
|
procs = SpotifyNotify.checkForProcess(
|
||||||
|
'ps x | grep "{0}" | grep -v grep'.format(ident),
|
||||||
|
Debug
|
||||||
|
)
|
||||||
|
if len(procs):
|
||||||
|
Debug.out("Spotify process found as: {0}".format(" ".join(procs[0])))
|
||||||
|
return
|
||||||
|
|
||||||
|
Debug.out("Starting new Spotify now.")
|
||||||
|
|
||||||
|
FNULL = open('/dev/null', 'w')
|
||||||
|
spid = Popen([ident], stdout=FNULL, stderr=FNULL).pid
|
||||||
|
if spid:
|
||||||
|
Debug.out("Spotify started, pid: {0}.".format(spid))
|
||||||
|
else:
|
||||||
|
Debug.out("Spotify could not be started.")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def checkForClosedSpotify(SN, Debug):
|
||||||
|
if not SpotifyNotify.spotifyPath:
|
||||||
|
Debug.out("No spotify process identifier found.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
ident = SpotifyNotify.spotifyPath
|
||||||
|
Debug.out("Looking for spotify as: {0}".format(ident))
|
||||||
|
|
||||||
|
procs = SpotifyNotify.checkForProcess(
|
||||||
|
'ps x | grep "{0}" | grep -v grep'.format(ident),
|
||||||
|
Debug
|
||||||
|
)
|
||||||
|
if len(procs):
|
||||||
|
Debug.out("Spotify process found as: {0}".format(" ".join(procs[0])))
|
||||||
|
|
||||||
|
if (SpotifyNotify.tryToReconnect):
|
||||||
|
SN.connect()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
if SpotifyNotify.tmpfile:
|
||||||
|
SpotifyNotify.tmpfile.close()
|
||||||
|
|
||||||
|
Debug.out("Spotify has been closed, therefore I die.")
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def preventDuplicate(Debug):
|
||||||
|
mypid = os.getpid()
|
||||||
|
Debug.out("My pid: {0}".format(mypid))
|
||||||
|
|
||||||
|
proc = SpotifyNotify.checkForProcess('ps -p {0}'.format(mypid), Debug)
|
||||||
|
if not proc[0][3]:
|
||||||
|
return
|
||||||
|
|
||||||
|
process = proc[0][3]
|
||||||
|
search = 'ps -C {0}'.format(process)
|
||||||
|
|
||||||
|
Debug.out("Looking for other processes named: {0}".format(process).strip())
|
||||||
|
|
||||||
|
if process == 'python':
|
||||||
|
if not sys.argv[0]:
|
||||||
|
Debug.out("Process started using python, cannot determine script name.")
|
||||||
|
return
|
||||||
|
|
||||||
|
search = 'ps ax | grep "python {0}" | grep -v grep'.format(sys.argv[0])
|
||||||
|
|
||||||
|
for line in SpotifyNotify.checkForProcess(search, Debug):
|
||||||
|
if int(line[0]) != mypid:
|
||||||
|
print("This program was already running.")
|
||||||
|
Debug.out("I am a duplicate. I shall end myself. ({0})".format(" ".join(line)))
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def checkForProcess(proc, Debug):
|
||||||
|
output = []
|
||||||
|
|
||||||
|
for line in Popen(proc, shell=True, stdout=PIPE).stdout:
|
||||||
|
fields = line.split()
|
||||||
|
if not fields[0].isdigit():
|
||||||
|
continue
|
||||||
|
|
||||||
|
output.append(fields)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
class DebugMe():
|
||||||
|
def __init__(self, toggle):
|
||||||
|
if toggle:
|
||||||
|
self.output = True
|
||||||
|
else:
|
||||||
|
self.output = False
|
||||||
|
|
||||||
|
def out(self, msg):
|
||||||
|
if not self.output:
|
||||||
|
return
|
||||||
|
|
||||||
|
print(">> {0}".format(msg))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'-a',
|
||||||
|
'--action',
|
||||||
|
dest = 'action',
|
||||||
|
default = None,
|
||||||
|
type = 'choice',
|
||||||
|
choices = ['playPause', 'play', 'pause', 'next', 'previous'],
|
||||||
|
help = 'Music player actions (playPause/play/pause/next/previous).'
|
||||||
|
)
|
||||||
|
parser.add_option(
|
||||||
|
'-n',
|
||||||
|
'--skip_notify',
|
||||||
|
dest = 'skipNotify',
|
||||||
|
action = 'store_true',
|
||||||
|
default = False,
|
||||||
|
help = 'Song change notifications will be turned off.'
|
||||||
|
)
|
||||||
|
parser.add_option(
|
||||||
|
'-d',
|
||||||
|
'--debug',
|
||||||
|
dest = 'debug',
|
||||||
|
action = 'store_true',
|
||||||
|
default = False,
|
||||||
|
help = 'Debug messages will be displayed.'
|
||||||
|
)
|
||||||
|
|
||||||
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
Debug = DebugMe(options.debug)
|
||||||
|
print("Spotify-notify v0.6")
|
||||||
|
|
||||||
|
if SPOTIFY_PROCESS_NAME:
|
||||||
|
SpotifyNotify.spotifyPath = SPOTIFY_PROCESS_NAME
|
||||||
|
else:
|
||||||
|
print "Spotify is not running"
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
SN = SpotifyNotify(Debug)
|
||||||
|
|
||||||
|
if options.action:
|
||||||
|
action = options.action
|
||||||
|
action = action[0:1].upper() + action[1:]
|
||||||
|
SN.executeCommand(action)
|
||||||
|
|
||||||
|
SpotifyNotify.preventDuplicate(Debug)
|
||||||
|
|
||||||
|
try:
|
||||||
|
indicateserver = indicate.indicate_server_ref_default()
|
||||||
|
indicateserver.set_type("music.spotify")
|
||||||
|
indicateserver.set_desktop_file("/usr/share/applications/spotify.desktop")
|
||||||
|
indicateserver.show()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
SN.pollChange()
|
||||||
|
print "Done"
|
||||||
|
|
114
bin/spotify-remote.sh
Executable file
114
bin/spotify-remote.sh
Executable file
@ -0,0 +1,114 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Extracted from: http://ubuntuforums.org/showthread.php?t=1797848
|
||||||
|
# User: azzid
|
||||||
|
# Modified by Balkian
|
||||||
|
# Collect DBUS_SESSION_BUS_ADDRESS from running process
|
||||||
|
function set_dbus_adress
|
||||||
|
{
|
||||||
|
USER=$1
|
||||||
|
PROCESS=$2
|
||||||
|
PID=`pgrep -o -u $USER $PROCESS`
|
||||||
|
ENVIRON=/proc/$PID/environ
|
||||||
|
|
||||||
|
if [ -e $ENVIRON ]
|
||||||
|
then
|
||||||
|
export `grep -z DBUS_SESSION_BUS_ADDRESS $ENVIRON`
|
||||||
|
else
|
||||||
|
echo "Unable to set DBUS_SESSION_BUS_ADDRESS."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function spotify_cmd
|
||||||
|
{
|
||||||
|
dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.$1 1> /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
function spotify_query
|
||||||
|
{
|
||||||
|
qdbus org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get org.mpris.MediaPlayer2.Player PlaybackStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
function spotify_metadata
|
||||||
|
{
|
||||||
|
qdbus com.spotify.qt / org.freedesktop.MediaPlayer2.GetMetadata
|
||||||
|
}
|
||||||
|
|
||||||
|
function spotify_notify
|
||||||
|
{
|
||||||
|
metadata=`spotify_metadata`
|
||||||
|
echo "Metadata: $metadata"
|
||||||
|
title=`echo "$metadata" | grep title | cut -d' ' -f2-`
|
||||||
|
artist=`echo "$metadata" | grep artist | cut -d' ' -f2-`
|
||||||
|
image=`echo "$metadata" | grep artUrl | cut -d' ' -f3`
|
||||||
|
wget $image -O /tmp/image
|
||||||
|
echo "notifying $title"
|
||||||
|
notify-send "$artist" "$title" --icon=/tmp/image
|
||||||
|
}
|
||||||
|
|
||||||
|
function quit_message
|
||||||
|
{
|
||||||
|
echo "Usage: `basename $0` {play|pause|playpause|next|previous|stop|playstatus|<spotify URI>}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Count arguments, must be 1
|
||||||
|
if [ "$#" -ne "1" ]
|
||||||
|
then
|
||||||
|
echo -e "You must supply exactly one argument!\n"
|
||||||
|
quit_message
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if DBUS_SESSION is set
|
||||||
|
if [ -z $DBUS_SESSION_BUS_ADDRESS ]
|
||||||
|
then
|
||||||
|
#echo "DBUS_SESSION_BUS_ADDRESS not set. Guessing."
|
||||||
|
set_dbus_adress `whoami` spotify
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
play)
|
||||||
|
spotify_cmd Play
|
||||||
|
spotify_notify
|
||||||
|
;;
|
||||||
|
pause)
|
||||||
|
spotify_cmd Pause
|
||||||
|
spotify_notify
|
||||||
|
;;
|
||||||
|
playpause)
|
||||||
|
spotify_cmd PlayPause
|
||||||
|
spotify_notify
|
||||||
|
;;
|
||||||
|
next)
|
||||||
|
spotify_cmd Next
|
||||||
|
spotify_notify
|
||||||
|
;;
|
||||||
|
previous)
|
||||||
|
spotify_cmd Previous
|
||||||
|
spotify_notify
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
spotify_cmd Stop
|
||||||
|
spotify_notify
|
||||||
|
;;
|
||||||
|
spotify:user:*)
|
||||||
|
spotify_cmd "OpenUri string:$1"
|
||||||
|
spotify_cmd Play
|
||||||
|
spotify_notify
|
||||||
|
;;
|
||||||
|
spotify:*:*)
|
||||||
|
spotify_cmd "OpenUri string:$1"
|
||||||
|
;;
|
||||||
|
playstatus)
|
||||||
|
spotify_query
|
||||||
|
;;
|
||||||
|
metadata)
|
||||||
|
spotify_metadata;
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "Bad argument.\n"
|
||||||
|
quit_message
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
17
bin/start-eclipse.sh
Normal file
17
bin/start-eclipse.sh
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cd $(dirname $(dirname $0))
|
||||||
|
eclipse/eclipse -vm jre1.6.0_20/bin/ || failed=1
|
||||||
|
if [ $failed -eq 1 ]; then
|
||||||
|
|
||||||
|
zenity --warning --title "Error executing eclipse's launcher" --text "Eclipse couldn't be found in $(pwd), please, modify $0 script to point to the right location" || exit
|
||||||
|
file=$(zenity --file-selection --title "Select the right executable");
|
||||||
|
vm=$(zenity --file-selection --title "Select virtual machine");
|
||||||
|
|
||||||
|
echo $file;
|
||||||
|
if [ -n "$file" ]; then
|
||||||
|
if [ -n "$vm" ]; then
|
||||||
|
virt=" -vm $vm";
|
||||||
|
fi
|
||||||
|
$file $virt
|
||||||
|
fi
|
||||||
|
fi
|
2
bin/terminator
Executable file
2
bin/terminator
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
one-window "terminator" "xdotool windowfocus \$WID & xdotool key ctrl+shift+t;" "/usr/bin/terminator $*"
|
65
bin/tmux-zoom.sh
Executable file
65
bin/tmux-zoom.sh
Executable file
@ -0,0 +1,65 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2012 Juan Ignacio Pumarino, jipumarino@gmail.com
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
# a copy of this software and associated documentation files (the
|
||||||
|
# "Software"), to deal in the Software without restriction, including
|
||||||
|
# without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
# permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
# the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
# Instructions
|
||||||
|
# ------------
|
||||||
|
#
|
||||||
|
# 1. Install this script and give it execute permission somewhere in your PATH.
|
||||||
|
# For example:
|
||||||
|
#
|
||||||
|
# $ mkdir -p ~/bin
|
||||||
|
# $ wget https://raw.github.com/jipumarino/tmux-zoom/master/tmux-zoom.sh -O ~/bin/tmux-zoom.sh
|
||||||
|
# $ chmod +x ~/bin/tmux-zoom.sh
|
||||||
|
#
|
||||||
|
# 2. Add a shortcut in your ~/.tmux.conf file:
|
||||||
|
#
|
||||||
|
# bind C-k run "tmux-zoom.sh"
|
||||||
|
#
|
||||||
|
# 3. When using this shortcut, the current tmux pane will open in a new window by itself.
|
||||||
|
# Running it again in the zoomed window will return it to its original pane. You can have
|
||||||
|
# as many zoomed windows as you want.
|
||||||
|
|
||||||
|
current=$(tmux display-message -p '#W-#I-#P')
|
||||||
|
list=$(tmux list-window)
|
||||||
|
|
||||||
|
[[ "$current" =~ ^(.*)-([0-9]+)-([0-9]+) ]]
|
||||||
|
current_window=${BASH_REMATCH[1]}
|
||||||
|
current_pane=${BASH_REMATCH[2]}-${BASH_REMATCH[3]}
|
||||||
|
new_zoom_window=ZOOM-$current_pane
|
||||||
|
|
||||||
|
if [[ $current_window =~ ZOOM-([0-9]+)-([0-9+]) ]]; then
|
||||||
|
if [ "$(tmux list-panes | wc -l)" -gt 1 ]; then
|
||||||
|
tmux display-message "other panes exist"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
old_zoom_window=ZOOM-${BASH_REMATCH[1]}-${BASH_REMATCH[2]}
|
||||||
|
tmux select-window -t ${BASH_REMATCH[1]} \; select-pane -t ${BASH_REMATCH[2]} \; swap-pane -s $old_zoom_window.0 \; kill-window -t $old_zoom_window
|
||||||
|
elif [[ $list =~ $new_zoom_window ]]; then
|
||||||
|
tmux select-window -t $new_zoom_window
|
||||||
|
else
|
||||||
|
if [ "$(tmux list-panes | wc -l)" -eq 1 ]; then
|
||||||
|
tmux display-message "already zoomed"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
tmux new-window -d -n $new_zoom_window \; swap-pane -s $new_zoom_window.0 \; select-window -t $new_zoom_window
|
||||||
|
fi
|
63
bin/unlock-livebox.py
Normal file
63
bin/unlock-livebox.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import telnetlib, time
|
||||||
|
|
||||||
|
# Poner esto a 0 para deshabilitar las opciones del menú
|
||||||
|
# o a 1 para habilitarlas
|
||||||
|
HABILITAR = 1;
|
||||||
|
|
||||||
|
tn = telnetlib.Telnet ( "192.168.1.1" );
|
||||||
|
tn.read_until("login: ");
|
||||||
|
tn.write("LBV2techno\n");
|
||||||
|
tn.read_until("Password: ");
|
||||||
|
tn.write("1901b95ae4295d613abf9eabae0b9d40\n");
|
||||||
|
for i in `range(1,3)`:
|
||||||
|
tn.write("\n");
|
||||||
|
tn.write("rg_conf_set wbm/settings/pages/backuprestore %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/pages/vpn %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/pages/fax %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/pages/log %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/pages/licence %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/pages/community %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/pages/visio %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/pages/livezoom %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/pages/hsiab %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/network/dhcp %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/network/ftlock %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/network/ftlock %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/network/tvrouted %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/services/professionnal %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/services/rtcphone %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/services/universal_phone %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/services/wifipushbutton %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/services/msgwaiting %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/test/sipdev %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/test/fmdev %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/network/h323 %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("rg_conf_set wbm/settings/services/wpspushbutton %i\n" % HABILITAR);
|
||||||
|
tn.read_until("Returned 0");
|
||||||
|
tn.write("save\n");
|
||||||
|
time.sleep(2);
|
||||||
|
tn.write("reboot\n");
|
2
bin/volume-down.sh
Executable file
2
bin/volume-down.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
pacmd dump|awk --non-decimal-data '$1~/set-sink-volume/{system ("pacmd "$1" "$2" "$3-1000)}'
|
2
bin/volume-toggle-mute.sh
Executable file
2
bin/volume-toggle-mute.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
pacmd dump|awk --non-decimal-data '$1~/set-sink-mute/{system ("pacmd "$1" "$2" "($3=="yes"?"no":"yes"))}'
|
2
bin/volume-up.sh
Executable file
2
bin/volume-up.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
pacmd dump|awk --non-decimal-data '$1~/set-sink-volume/{system ("pacmd "$1" "$2" "$3+1000)}'
|
194
bin/winfuncs.sh
Executable file
194
bin/winfuncs.sh
Executable file
@ -0,0 +1,194 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Extracted from:http://forum.xfce.org/viewtopic.php?id=6841 ¡
|
||||||
|
#todo:
|
||||||
|
# cancel for tile functions
|
||||||
|
# determine what windows are maximized and re-max after the "window select" function
|
||||||
|
# determine what windows are non-resizable by the user so that the script doesn't resize them
|
||||||
|
# cascade also shaded windows
|
||||||
|
|
||||||
|
# which workspace we're on
|
||||||
|
function get_workspace {
|
||||||
|
if [[ "$DTOP" == "" ]] ; then
|
||||||
|
DTOP=`xdotool get_desktop`
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_desktop {
|
||||||
|
xwininfo -id "$*" | grep '"Desktop"'
|
||||||
|
return "$?"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_visible_window_ids {
|
||||||
|
if (( ${#WDOWS[@]} == 0 )) ; then
|
||||||
|
WDOWS=(`xdotool search --desktop $DTOP --onlyvisible "" 2>/dev/null`)
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_desktop_dim {
|
||||||
|
#desktop dimensions
|
||||||
|
if (( ${#DIM[@]} == 0 )) ; then
|
||||||
|
DIM=(`wmctrl -d | egrep "^0" | sed 's/.*DG: \([0-9]*x[0-9]*\).*/\1/g' | sed 's/x/ /g'`)
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function win_showdesktop {
|
||||||
|
get_workspace
|
||||||
|
get_visible_window_ids
|
||||||
|
|
||||||
|
command="search --desktop $DTOP \"\""
|
||||||
|
|
||||||
|
if (( ${#WDOWS[@]} > 0 )) ; then
|
||||||
|
command="$command windowminimize %@"
|
||||||
|
else
|
||||||
|
command="$command windowraise %@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$command" | xdotool -
|
||||||
|
}
|
||||||
|
|
||||||
|
function win_tile_two {
|
||||||
|
get_desktop_dim
|
||||||
|
wid1=`xdotool selectwindow 2>/dev/null`
|
||||||
|
|
||||||
|
is_desktop "$wid1" && return
|
||||||
|
|
||||||
|
wid2=`xdotool selectwindow 2>/dev/null`
|
||||||
|
|
||||||
|
is_desktop "$wid2" && return
|
||||||
|
|
||||||
|
half_w=`expr ${DIM[0]} / 2`
|
||||||
|
|
||||||
|
commands="windowsize $wid1 $half_w ${DIM[1]}"
|
||||||
|
commands="$commands windowsize $wid2 $half_w ${DIM[1]}"
|
||||||
|
commands="$commands windowmove $wid1 0 0"
|
||||||
|
commands="$commands windowmove $wid2 $half_w 0"
|
||||||
|
commands="$commands windowraise $wid1"
|
||||||
|
commands="$commands windowraise $wid2"
|
||||||
|
|
||||||
|
wmctrl -i -r $wid1 -b remove,maximized_vert,maximized_horz
|
||||||
|
wmctrl -i -r $wid2 -b remove,maximized_vert,maximized_horz
|
||||||
|
|
||||||
|
echo "$commands" | xdotool -
|
||||||
|
}
|
||||||
|
|
||||||
|
function win_tile {
|
||||||
|
get_workspace
|
||||||
|
get_visible_window_ids
|
||||||
|
|
||||||
|
(( ${#WDOWS[@]} < 1 )) && return;
|
||||||
|
|
||||||
|
get_desktop_dim
|
||||||
|
|
||||||
|
# determine how many rows and columns we need
|
||||||
|
cols=`echo "sqrt(${#WDOWS[@]})" | bc`
|
||||||
|
rows=$cols
|
||||||
|
wins=`expr $rows \* $cols`
|
||||||
|
|
||||||
|
if (( "$wins" < "${#WDOWS[@]}" )) ; then
|
||||||
|
cols=`expr $cols + 1`
|
||||||
|
wins=`expr $rows \* $cols`
|
||||||
|
if (( "$wins" < "${#WDOWS[@]}" )) ; then
|
||||||
|
rows=`expr $rows + 1`
|
||||||
|
wins=`expr $rows \* $cols`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
(( $cols < 1 )) && cols=1;
|
||||||
|
(( $rows < 1 )) && rows=1;
|
||||||
|
|
||||||
|
win_w=`expr ${DIM[0]} / $cols`
|
||||||
|
win_h=`expr ${DIM[1]} / $rows`
|
||||||
|
|
||||||
|
# do tiling
|
||||||
|
x=0; y=0; commands=""
|
||||||
|
for window in ${WDOWS[@]} ; do
|
||||||
|
wmctrl -i -r $window -b remove,maximized_vert,maximized_horz
|
||||||
|
|
||||||
|
commands="$commands windowsize $window $win_w $win_h"
|
||||||
|
commands="$commands windowmove $window `expr $x \* $win_w` `expr $y \* $win_h`"
|
||||||
|
|
||||||
|
x=`expr $x + 1`
|
||||||
|
if (( $x > `expr $cols - 1` )) ; then
|
||||||
|
x=0
|
||||||
|
y=`expr $y + 1`
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$commands" | xdotool -
|
||||||
|
}
|
||||||
|
|
||||||
|
function win_cascade {
|
||||||
|
get_workspace
|
||||||
|
get_visible_window_ids
|
||||||
|
|
||||||
|
(( ${#WDOWS[@]} < 1 )) && return;
|
||||||
|
|
||||||
|
x=0; y=0; commands=""
|
||||||
|
for window in ${WDOWS[@]} ; do
|
||||||
|
wmctrl -i -r $window -b remove,maximized_vert,maximized_horz
|
||||||
|
|
||||||
|
commands="$commands windowsize $window 640 480"
|
||||||
|
commands="$commands windowmove $window $x $y"
|
||||||
|
|
||||||
|
x=`expr $x + 22`
|
||||||
|
y=`expr $y + 22`
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$commands" | xdotool -
|
||||||
|
}
|
||||||
|
|
||||||
|
function win_select {
|
||||||
|
get_workspace
|
||||||
|
get_visible_window_ids
|
||||||
|
|
||||||
|
(( ${#WDOWS[@]} < 1 )) && return;
|
||||||
|
|
||||||
|
# store window positions and widths
|
||||||
|
i=0
|
||||||
|
for window in ${WDOWS[@]} ; do
|
||||||
|
GEO=`xdotool getwindowgeometry $window | grep Geometry | sed 's/.* \([0-9].*\)/\1/g'`;
|
||||||
|
height[$i]=`echo $GEO | sed 's/\(.*\)x.*/\1/g'`
|
||||||
|
width[$i]=`echo $GEO | sed 's/.*x\(.*\)/\1/g'`
|
||||||
|
|
||||||
|
# ( xwininfo gives position not ignoring titlebars and borders, unlike xdotool )
|
||||||
|
POS=(`xwininfo -stats -id $window | grep 'geometry ' | sed 's/.*[-+]\([0-9]*[-+][0-9*]\)/\1/g' | sed 's/[+-]/ /g'`)
|
||||||
|
posx[$i]=${POS[0]}
|
||||||
|
posy[$i]=${POS[1]}
|
||||||
|
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
|
||||||
|
# tile windows
|
||||||
|
win_tile
|
||||||
|
|
||||||
|
# select a window
|
||||||
|
wid=`xdotool selectwindow 2>/dev/null`
|
||||||
|
|
||||||
|
is_desktop "$wid" && return
|
||||||
|
|
||||||
|
# restore window positions and widths
|
||||||
|
i=0; commands=""
|
||||||
|
for (( i=0; $i<${#WDOWS[@]}; i++ )) ; do
|
||||||
|
commands="$commands windowsize ${WDOWS[i]} ${height[$i]} ${width[$i]}"
|
||||||
|
commands="$commands windowmove ${WDOWS[i]} ${posx[$i]} ${posy[$i]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
commands="$commands windowraise $wid"
|
||||||
|
|
||||||
|
echo "$commands" | xdotool -
|
||||||
|
}
|
||||||
|
|
||||||
|
for command in ${@} ; do
|
||||||
|
if [[ "$command" == "tile" ]] ; then
|
||||||
|
win_tile
|
||||||
|
elif [[ "$command" == "select" ]] ; then
|
||||||
|
win_select
|
||||||
|
elif [[ "$command" == "tiletwo" ]] ; then
|
||||||
|
win_tile_two
|
||||||
|
elif [[ "$command" == "cascade" ]] ; then
|
||||||
|
win_cascade
|
||||||
|
elif [[ "$command" == "showdesktop" ]] ; then
|
||||||
|
win_showdesktop
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
Loading…
Reference in New Issue
Block a user