domingo, 17 de noviembre de 2013

Greek Unicode and Inkscape

To get Greek letters in Inkscape:

– go into text mode
– type Ctrl+U
– type the 4-digit unicode for the desired Greek letter.
Greek letter
Lower case
Unicode
Upper case
Unicode
alpha
α
03b1
A
0391
beta
β
03b2
B
0392
gamma
γ
03b3
Γ
0393
delta
δ
03b4
Δ
0394
epsilon
ϵ
03b5
E
0395
zeta
ζ
03b6
Z
0396
eta
η
03b7
H
0397
theta
θ
03b8
Θ
0398
iota
ι
03b9
I
0399
kappa
κ
03ba
K
039a
lambda
λ
03bb
Λ
039b
mu
μ
03bc
M
039c
nu
ν
03bd
N
039d
xi
ξ
03be
Ξ
039e
omicron
o
03bf
O
039f
pi
π
03c0
Π
03a0
rho
ρ
03c1
P
03a1
sigma
σ
03c3
Σ
03a3
tau
τ
03c4
T
03a4
upsilon
υ
03c5
ϒ
03a5
phi
ϕ
03c6
Φ
03a6
chi
χ
03c7
X
03a7
psi
ψ
03c8
Ψ
03a8
omega
ω
03c9
Ω
03a9

lunes, 18 de marzo de 2013

Añadiendo columnas a nautilus

Para añadir más columnas en Nautilus al visualizar en modo lista.
sudo apt-get install python-nautilus python-mutagen python-pyexiv2 python-kaa-metadata
mkdir ~/.nautilus/python-extensions
cp bsc.py ~/.nautilus/python-extensions
#!/usr/bin/python

# this script can installed to the current user account by running the following commands:

# sudo apt-get install python-nautilus python-mutagen python-pyexiv2 python-kaa-metadata
# mkdir ~/.nautilus/python-extensions
# cp bsc.py ~/.nautilus/python-extensions
# chmod a+x ~/.nautilus/python-extensions/bsc.py

# alternatively, you can be able to place the script in:
# /usr/lib/nautilus/extensions-2.0/python/

# change log:
# geb666: original bsc.py, based on work by Giacomo Bordiga
# jmdsdf: version 2 adds extra ID3 and EXIF tag support
# jmdsdf: added better error handling for ID3 tags, added mp3 length support, distinguished
#         between exif image size and true image size
# SabreWolfy: set consistent hh:mm:ss format, fixed bug with no ID3 information 
#             throwing an unhandled exception
# jmdsdf: fixed closing file handles with mpinfo (thanks gueba)
# jmdsdf: fixed closing file handles when there's an exception (thanks Pitxyoki)
# jmdsdf: added video parsing (work based on enbeto, thanks!)
# jmdsdf: added FLAC audio parsing through kaa.metadata (thanks for the idea l-x-l)
# jmdsdf: added trackno, added mkv file support (thanks ENigma885)
# jmdsdf: added date/album for flac/video (thanks eldon.t)
# jmdsdf: added wav file support thru pyexiv2
# jmdsdf: added sample rate file support thru mutagen and kaa (thanks for the idea N'ko)
# jmdsdf: fix with tracknumber for FLAC, thanks l-x-l
# draxus: support for pdf files
 
import os
import urllib
import nautilus
# for id3 support
from mutagen.easyid3 import EasyID3
from mutagen.mp3 import MPEGInfo
# for exif support
import pyexiv2
# for reading videos. for future improvement, this can also read mp3!
import kaa.metadata
# for reading image dimensions
import Image
# for reading pdf
try:
 from pyPdf import PdfFileReader
except:
 pass

class ColumnExtension(nautilus.ColumnProvider, nautilus.InfoProvider):
 def __init__(self):
  pass

 def get_columns(self):
  return (
   nautilus.Column("NautilusPython::title_column","title","Title","Song title"),
   nautilus.Column("NautilusPython::album_column","album","Album","Album"),
   nautilus.Column("NautilusPython::artist_column","artist","Artist","Artist"),
   nautilus.Column("NautilusPython::tracknumber_column","tracknumber","Track","Track number"),
   nautilus.Column("NautilusPython::genre_column","genre","Genre","Genre"),
   nautilus.Column("NautilusPython::date_column","date","Date","Date"),
   nautilus.Column("NautilusPython::bitrate_column","bitrate","Bitrate","Audio Bitrate in kilo bits per second"),
   nautilus.Column("NautilusPython::samplerate_column","samplerate","Sample rate","Sample rate in Hz"),
   nautilus.Column("NautilusPython::length_column","length","Length","Length of audio"),
   nautilus.Column("NautilusPython::exif_datetime_original_column","exif_datetime_original","EXIF Dateshot ","Get the photo capture date from EXIF data"),
   nautilus.Column("NautilusPython::exif_software_column","exif_software","EXIF Software","EXIF - software used to save image"),
   nautilus.Column("NautilusPython::exif_flash_column","exif_flash","EXIF flash","EXIF - flash mode"),
   nautilus.Column("NautilusPython::exif_pixeldimensions_column","exif_pixeldimensions","EXIF Image Size","Image size - pixel dimensions as reported by EXIF data"),
   nautilus.Column("NautilusPython::pixeldimensions_column","pixeldimensions","Image Size","Image/video size - actual pixel dimensions"),
  )

 def update_file_info(self, file):
  # set defaults to blank
  file.add_string_attribute('title', '')
  file.add_string_attribute('album', '')
  file.add_string_attribute('artist', '')
  file.add_string_attribute('tracknumber', '')
  file.add_string_attribute('genre', '')
  file.add_string_attribute('date', '')
  file.add_string_attribute('bitrate', '')
  file.add_string_attribute('samplerate', '')
  file.add_string_attribute('length', '')
  file.add_string_attribute('exif_datetime_original', '')
  file.add_string_attribute('exif_software', '')
  file.add_string_attribute('exif_flash', '')
  file.add_string_attribute('exif_pixeldimensions', '')
  file.add_string_attribute('pixeldimensions', '')

  if file.get_uri_scheme() != 'file':
   return

  # strip file:// to get absolute path
  filename = urllib.unquote(file.get_uri()[7:])
  
  # mp3 handling
  if file.is_mime_type('audio/mpeg'):
   # attempt to read ID3 tag
   try:
    audio = EasyID3(filename)
    # sometimes the audio variable will not have one of these items defined, that's why
    # there is this long try / except attempt
    try: file.add_string_attribute('title', audio["title"][0])
    except: file.add_string_attribute('title', "[n/a]")
    try: file.add_string_attribute('album', audio["album"][0])
    except: file.add_string_attribute('album', "[n/a]")
    try: file.add_string_attribute('artist', audio["artist"][0])
    except: file.add_string_attribute('artist', "[n/a]")
    try: file.add_string_attribute('tracknumber', audio["tracknumber"][0])
    except: file.add_string_attribute('tracknumber', "[n/a]")
    try: file.add_string_attribute('genre', audio["genre"][0])
    except: file.add_string_attribute('genre', "[n/a]")
    try: file.add_string_attribute('date', audio["date"][0])
    except: file.add_string_attribute('date', "[n/a]")
   except:
    # [SabreWolfy] some files have no ID3 tag and will throw this exception:
    file.add_string_attribute('title', "[no ID3]")
    file.add_string_attribute('album', "[no ID3]")
    file.add_string_attribute('artist', "[no ID3]")
    file.add_string_attribute('tracknumber', "[no ID3]")
    file.add_string_attribute('genre', "[no ID3]")
    file.add_string_attribute('date', "[no ID3]")
    
   # try to read MP3 information (bitrate, length, samplerate)
   try:
    mpfile = open (filename)
    mpinfo = MPEGInfo (mpfile)
    file.add_string_attribute('bitrate', str(mpinfo.bitrate/1000) + " Kbps")
    file.add_string_attribute('samplerate', str(mpinfo.sample_rate) + " Hz")
    # [SabreWolfy] added consistent formatting of times in format hh:mm:ss
    # [SabreWolfy[ to allow for correct column sorting by length
    mp3length = "%02i:%02i:%02i" % ((int(mpinfo.length/3600)), (int(mpinfo.length/60%60)), (int(mpinfo.length%60)))
    mpfile.close()
    file.add_string_attribute('length', mp3length)
   except:
    file.add_string_attribute('bitrate', "[n/a]")
    file.add_string_attribute('length', "[n/a]")
    file.add_string_attribute('samplerate', "[n/a]")
    try:
     mpfile.close()
    except: pass
 
  # image handling
  if file.is_mime_type('image/jpeg') or file.is_mime_type('image/png') or file.is_mime_type('image/gif') or file.is_mime_type('image/bmp'):
   # EXIF handling routines
   try:
    img = pyexiv2.Image(filename)
    img.readMetadata()
    file.add_string_attribute('exif_datetime_original',str(img['Exif.Photo.DateTimeOriginal']))
    file.add_string_attribute('exif_software',str(img['Exif.Image.Software']))
    file.add_string_attribute('exif_flash',str(img['Exif.Photo.Flash']))
    file.add_string_attribute('exif_pixeldimensions',str(img['Exif.Photo.PixelXDimension'])+'x'+str(img['Exif.Photo.PixelYDimension']))
   except:
    # no exif data?
    file.add_string_attribute('exif_datetime_original',"")
    file.add_string_attribute('exif_software',"")
    file.add_string_attribute('exif_flash',"")
    file.add_string_attribute('exif_pixeldimensions',"")
   # try read image info directly
   try:
    im = Image.open(filename)
    file.add_string_attribute('pixeldimensions',str(im.size[0])+'x'+str(im.size[1]))
   except:
    file.add_string_attribute('pixeldimensions',"[image read error]")

  # video/flac handling
  if file.is_mime_type('video/x-msvideo') | file.is_mime_type('video/mpeg') | file.is_mime_type('video/x-ms-wmv') | file.is_mime_type('video/mp4') | file.is_mime_type('audio/x-flac') | file.is_mime_type('video/x-flv') | file.is_mime_type('video/x-matroska') | file.is_mime_type('audio/x-wav'):
   try:
    info=kaa.metadata.parse(filename)
    try: file.add_string_attribute('length',"%02i:%02i:%02i" % ((int(info.length/3600)), (int(info.length/60%60)), (int(info.length%60))))
    except: file.add_string_attribute('length','[n/a]')
    try: file.add_string_attribute('pixeldimensions', str(info.video[0].width) + 'x'+ str(info.video[0].height))
    except: file.add_string_attribute('pixeldimensions','[n/a]')
    try: file.add_string_attribute('bitrate',str(round(info.audio[0].bitrate/1000)))
    except: file.add_string_attribute('bitrate','[n/a]')
    try: file.add_string_attribute('samplerate',str(int(info.audio[0].samplerate))+' Hz')
    except: file.add_string_attribute('samplerate','[n/a]')
    try: file.add_string_attribute('title', info.title)
    except: file.add_string_attribute('title', '[n/a]')
    try: file.add_string_attribute('artist', info.artist)
    except: file.add_string_attribute('artist', '[n/a]')
    try: file.add_string_attribute('genre', info.genre)
    except: file.add_string_attribute('genre', '[n/a]')
    try: file.add_string_attribute('tracknumber',info.trackno)
    except: file.add_string_attribute('tracknumber', '[n/a]')
    try: file.add_string_attribute('date',info.userdate)
    except: file.add_string_attribute('date', '[n/a]')     
    try: file.add_string_attribute('album',info.album)
    except: file.add_string_attribute('album', '[n/a]')
   except:
    file.add_string_attribute('length','error')
    file.add_string_attribute('pixeldimensions','error')
    file.add_string_attribute('bitrate','error')
    file.add_string_attribute('samplerate','error')
    file.add_string_attribute('title','error')
    file.add_string_attribute('artist','error')
    file.add_string_attribute('genre','error')
    file.add_string_attribute('track','error')
    file.add_string_attribute('date','error')
    file.add_string_attribute('album','error')
  # pdf handling
  if file.is_mime_type('application/pdf'):
   try:
    f = open(filename, "rb")
    pdf = PdfFileReader(f)
    try: file.add_string_attribute('title', pdf.getDocumentInfo().title)
    except: file.add_string_attribute('title', "[n/a]")
    try: file.add_string_attribute('artist', pdf.getDocumentInfo().author)
    except: file.add_string_attribute('artist', "[n/a]")
    f.close()
   except:
    file.add_string_attribute('title', "[no info]")
    file.add_string_attribute('artist', "[no info]")
     
  self.get_columns()


fuente: http://pastebin.com/WxspTtvL

viernes, 23 de noviembre de 2012

Ficheros de datos en paquete Python

Estructura para un proyecto de python, con algunos archivos de datos necesarios para la aplicación:
Para que todos los ficheros de datos se añadan al paquete de python és necesario indicar en el setup.py que deseamos añadir estos. Teniendo en cuenta una distribución de los directorios como la anterior, el programa setup.py quedaría de la siguiente manera:

#!/usr/bin/python

from setuptools import setup, find_packages
setup(
 name='mypkg',
 version='0.0.2',
 author='Miquel Perello Nieto',
 author_email='perello.nieto@gmail.com',
 url='perellonieto.com',
 packages = find_packages('src'),  # include all packages under src
 package_dir = {'':'src'},   # tell distutils packages are under src

 package_data = {
  # If any package contains *.txt files, include them:
  '': ['*.txt'],
  # And include any *.dat files found in the 'data' subdirectory
  # of the 'mypkg' package, also:
  'mypkg': ['data/*.dat'],
  }
    )



Resolviendo dependencias circulares en c++ con forward declaration

El problema de las dependencias circulares aparece en el momento en que dos clases distintas tienen una instancia o hacen referencia a la otra en su declaración.

Como ejemplo estas dos clases, las cuales tienen un puntero a una instancia de la otra:

class_a.h

#ifndef CLASS_A_H_
#define CLASS_A_H_

#include "class_b.h"

class ClassB; // Commenting this line compilation will fail

class ClassA
{
public:
 ClassA();

private:
 ClassB * b;
};

class_b.h

#ifndef CLASS_B_H_
#define CLASS_B_H_

#include "class_a.h"

class ClassA; // Commenting this line compilation will fail

class ClassB
{
public:
 ClassB();

private:
 ClassA * a;
};

En este caso hasta que una de las clases no haya sido totalmente interpretada por el compilador, éste no podrá interpretar la otra. Lo que hace que el compilador se queje de no conocer el objeto.

Para solucionar este problema se debe indicar al compilador en ClassB que ClassA es una clase, y lo mismo para la ClassA. A esta declaración "anticipada" se la llama "Forward declaration" (ver Wikipedia: Forward declaration).

En el código de arriba este problema está solucionado, pero si quereis reproducir el error comentar la linia que esta indicada.

Aqui teneis el resto de ficheros necesarios para hacer una prueba:

main.cpp

#include "class_a.h"
#include "class_b.h"

int main()
{
 ClassA a;
 ClassB b;

 return 0;
}

class_a.cpp

#include "class_a.h"
#include "cstdio"

ClassA::ClassA() {
 printf("Creating ClassA object\n");
}

class_b.cpp

#include "class_b.h"
#include "cstdio"

ClassB::ClassB() {
 printf("Creating ClassB object\n");
}

Para compilarlo todo:

Makefile

all: main

main: main.o class_a.o class_b.o
 g++ -o main main.o class_a.o class_b.o

main.o: main.cpp
 g++ -c main.cpp

class_a.o: class_a.cpp
 g++ -c class_a.cpp
 
class_b.o: class_b.cpp
 g++ -c class_b.cpp

clean: 
 rm -f *.o main

Ver explicación más detallada en la fuente : Stackoverflow

miércoles, 26 de septiembre de 2012

Dependencias proyecto Python


Para ver las dependencias de nuestro proyecto python, nos podemos ayudar de la erramineta snakefood, el qual nos puede crear de forma textual o en formato visual todas las dependencias de nuestro proyecto.

sudo apt-get install snakefood
 Una vez instalado se puede generar una grafica en formato ps con el siguiente comando:

sfood myproject | sfood-graph | dot -Tps > graph.ps
donde myproject es el directorio de tu proyecto.

Ejemplo de un trozo de grafica:


 fuente: http://furius.ca/snakefood/

Iconos del panel de gnome en movimiento

Ya me ha ocurrido varias veces que el panel superior de gnome; aun teniendo todos los iconos bloqueados; de vez en cuando me los desordenaba. Puede ser que fuera al cambiar la resolución de la pantalla, o al tener un monitor suplementario conectado al portatil.

Por lo que he visto buscando información, este problema fué solucionado en la ultima versión del panel, cuando este fue portado a GTK3, pero no se ha solucionado para las versiones antiguas. Así que he encontrado un script que hizo "bojo42", el qual bloquea el panel entero y lo desbloquea cuando queramos.

Lo suyo es guardar este script en algun lugar (por ejemplo en nuestro home "/home/USER/.gnome2_panel_block_down).
Darle permiso de ejecución.
Añadir en el panel de gnome un lanzador personalizado.
Poner como comando este mismo script.
Una vez hecho esto solo es cuestion de bloquear y desbloquear el panel con un simple click.



#!/bin/sh

### Config
NOTIFY=on #(on/off)
LOCK_TITLE="Panel Lock Down"
LOCK_MSG="Locking the GNOME panel"
UNLOCK_TITLE="Panel Lock Down"
UNLOCK_MSG="Unlocking the GNOME panel"
LOCK_ICON="/usr/share/icons/hicolor/48x48/apps/gdu-encrypted-lock.png"
UNLOCK_ICON="/usr/share/icons/hicolor/48x48/apps/gdu-encrypted-unlock.png"

### Dependency checking
if [ -z "$(which gconftool-2)" ]; then
 if [ -n "$(which gconftool-2)" ]; then
  zenity --warning --text "Error. No binary found for gconftool-2!" --title "Panel Lock Down"
 else
  echo "Panel Lock Down: Error. No binary found for gconftool-2!"
 fi
 exit 1
fi
if [ "$NOTIFY" = "on" ] && [ -z "$(which notify-send)" ]; then
 SCRIPT_LOCATION="$(pwd)/$(basename $0)"
 if [ -n "$(which zenity)" ]; then
  zenity --warning --text "Notifcations failed! Please install the libnotify-bin package or disable notifications in $SCRIPT_LOCATION" --title "Panel Lock Down"
 else
  echo "Panel Lock Down: Notifcations failed! Please install the libnotify-bin package or disable notifications in $SCRIPT_LOCATION"
 fi
 NOTIFY="off"
fi

### Main
if [ "$(gconftool-2 -g /apps/panel/global/locked_down)" = "true" ]; then
 [ "$NOTIFY" = "on" ] && notify-send -i $UNLOCK_ICON "$UNLOCK_TITLE" "$UNLOCK_MSG"
 gconftool-2 -s /apps/panel/global/locked_down --type=bool false
elif [ "$(gconftool-2 -g /apps/panel/global/locked_down)" = "false" ]; then
 [ "$NOTIFY" = "on" ] && notify-send -i $LOCK_ICON "$LOCK_TITLE" "$LOCK_MSG"
 gconftool-2 -s /apps/panel/global/locked_down --type=bool true
else
 if [ -n "$(which zenity)" ]; then
  zenity --warning --text "Error. Undefined state of global panel lock down!" --title "Panel Lock Down"
 else
  echo 'Panel Lock Down: Error. Undefined state of global panel lock down!'
 fi
 exit 1
fi