<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1938427166284563435</id><updated>2011-07-29T01:38:12.394-07:00</updated><category term='gext'/><category term='diseño'/><category term='python'/><category term='pruebas'/><category term='xlib'/><category term='noticias'/><category term='librería'/><title type='text'>Proyecto Gexter</title><subtitle type='html'>Blog dedicado al proyecto Gexter, una herramienta libre para la creación y edición de screencasts.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gexter-project.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gexter-project.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Oscar Aceña</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1938427166284563435.post-3751147752084747090</id><published>2009-12-11T05:15:00.000-08:00</published><updated>2009-12-12T11:44:27.732-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='gext'/><category scheme='http://www.blogger.com/atom/ns#' term='pruebas'/><category scheme='http://www.blogger.com/atom/ns#' term='librería'/><title type='text'>Pruebas con Gext</title><content type='html'>¡Hola!&lt;br /&gt;&lt;br /&gt;He avanzado algo en la librería Gext, sobre todo en la parte relacionada con el módulo Mouse, así que me gustaría poner un vídeo muy sencillo de Gext en acción (y de paso pruebo las posibilidades para empotrar vídeo aquí, con &lt;a href="http://flowplayer.org/"&gt;Flowplayer&lt;/a&gt;, GPL v3.0).&lt;br /&gt;&lt;br /&gt;El guión es muy sencillo, simplemente crea una carpeta en el escritorio, la mueve de sitio y la borra. Para ello, ha sido necesario usar los movimientos relativos y absolutos, los clicks (izquierdo y derecho) y el Drag &amp;amp; Drop. El script en python (&lt;a href="https://forja.rediris.es/plugins/scmsvn/viewcvs.php/*checkout*/examples/gext/mouse.py?content-type=text%2Fplain&amp;amp;rev=14&amp;amp;root=cusl4-gexter"&gt;mouse.py&lt;/a&gt;) se encuentra en la &lt;a href="https://forja.rediris.es/plugins/scmsvn/viewcvs.php/examples/?root=cusl4-gexter"&gt;carpeta de ejemplos&lt;/a&gt; del repositorio. El vídeo lo he grabado con &lt;a href="http://recordmydesktop.sourceforge.net/about.php"&gt;gtk-recordmydesktop&lt;/a&gt;, habilitando la opción &lt;i&gt;--no-frame&lt;/i&gt; para poder usar el DnD.&lt;br /&gt;&lt;br /&gt;&lt;script src="http://cusl4-gexter.forja.rediris.es/flowplayer/flowplayer-3.1.4.min.js"&gt;&lt;/script&gt;&lt;a href="http://cusl4-gexter.forja.rediris.es/videos/gext01.flv"    style="display:block;width:566px;height:400px;border: 1px solid #aaa"    id="gext01"&gt;&lt;/a&gt;&lt;script language="JavaScript"&gt;    flowplayer("gext01",              "http://cusl4-gexter.forja.rediris.es/flowplayer/flowplayer-3.1.5.swf",              { clip: { autoPlay: false, autoBuffering: true } }); &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Aquí os dejo. ¡Saludos!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1938427166284563435-3751147752084747090?l=gexter-project.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gexter-project.blogspot.com/feeds/3751147752084747090/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://gexter-project.blogspot.com/2009/12/pruebas-con-gext.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/3751147752084747090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/3751147752084747090'/><link rel='alternate' type='text/html' href='http://gexter-project.blogspot.com/2009/12/pruebas-con-gext.html' title='Pruebas con Gext'/><author><name>Oscar Aceña</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1938427166284563435.post-8028163437097559519</id><published>2009-12-01T11:23:00.000-08:00</published><updated>2009-12-01T11:26:50.424-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xlib'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='gext'/><title type='text'>python-xlib: emulando el teclado</title><content type='html'>&lt;span title="¡Hola!"&gt;Salut!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En el pasado &lt;i&gt;post&lt;/i&gt; nos quedamos a medias. Vimos como hacer algunas cosillas con el ratón, pero no hicimos nada con el teclado. Intentémoslo ahora.&lt;br /&gt;&lt;br /&gt;Con la misma función, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;fake_input()&lt;/span&gt;, es posible enviar eventos del teclado. Cambiamos el &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ButtonPress/ButtonRelease&lt;/span&gt; por &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;KeyPress/KeyRelease&lt;/span&gt;, y como parámetro, el código de la tecla que queremos. He te aquí el problema. ¿Qué es ese "código" y de donde lo sacamos?&lt;br /&gt;&lt;br /&gt;Sería interesante disponer de documentación sobre esto, pero esta es bastante escasa. Así que nos toca ver el código fuente o los ejemplos que encontremos. Tampoco es que haya muchos... pero algunos si que hay. En mi búsqueda me encontré con &lt;a href="http://hoopajoo.net/projects/xautomation.html"&gt;xautomation&lt;/a&gt;, una herramienta de la que puedo sacar muchas cosas :p&lt;br /&gt;&lt;br /&gt;Viendo su código, se puede deducir que a la función &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;fake_input()&lt;/span&gt; es necesario pasarle un &lt;i&gt;keycode&lt;/i&gt;, que a su vez, se obtiene a partir de un &lt;i&gt;keysym&lt;/i&gt;. Dos conceptos nuevos que tendremos que definir. Al parecer, los &lt;i&gt;keycodes&lt;/i&gt; están en un rango bastante reducido (hay menos de 255), por lo que deduzco que tienen una correspondencia (casi) directa con una tecla del teclado (esto, posiblemente no sea así, pero vamos a asumir que sí). Hay un método de la clase &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Display&lt;/span&gt; que hace la conversión entre un &lt;i&gt;keysym&lt;/i&gt; y un &lt;i&gt;keycode&lt;/i&gt;. Y en el módulo &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;XK&lt;/span&gt; hay un montón de &lt;i&gt;keysyms&lt;/i&gt; definidos (por ejemplo, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;XK_colon, XK_plus o XK_space)&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Deduzco que, por un lado tenemos un número asociado al caracter que queremos pulsar, y por otro, la tecla a la que se corresponde con la distribución del teclado  actual (Spain, USA, etc). Por ejemplo, si quiero introducir el caracter '.', primero tengo que identificar su &lt;i&gt;keysym&lt;/i&gt;. Al parecer, es el 46, o &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;XK_period&lt;/span&gt; (y además, se corresponde con el valor ASCII para el punto). Ahora, tenemos que traducir este &lt;i&gt;keysym&lt;/i&gt; al valor de la tecla correspondiente, usando &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Display.keysym_to_keycode()&lt;/span&gt;. Y el valor retornado es el que podemos usar en &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;fake_input()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Supongo que todo este jaleo es conveniente para dar soporte a múltiples distribuciones de teclados, así como a diferentes juegos de caracteres. Veamos un ejemplo, el clásico 'Hello World!', que tiene un poco de todo.&lt;br /&gt;&lt;br /&gt;&lt;pre class="python" name="code"&gt;from Xlib.display import Display&lt;br /&gt;from Xlib.ext import xtest&lt;br /&gt;from Xlib import X, XK&lt;br /&gt;&lt;br /&gt;d = Display()&lt;br /&gt;msg = "Hello World!"&lt;br /&gt;&lt;br /&gt;for c in msg:&lt;br /&gt;    keysym = XK.string_to_keysym(c)&lt;br /&gt;    keycode = d.keysym_to_keycode(keysym)&lt;br /&gt;&lt;br /&gt;    xtest.fake_input(d, X.KeyPress, keycode)&lt;br /&gt;    xtest.fake_input(d, X.KeyRelease, keycode)&lt;br /&gt;&lt;br /&gt;d.flush()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;He usado una función de &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;XK&lt;/span&gt; que hace la traducción desde una cadena a un &lt;i&gt;keysym&lt;/i&gt; (por ejemplo, convierte la cadena "space" al keysym &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;XK_space&lt;/span&gt;). Lo probamos pero no muestra el resultado esperado, sino: 'helloworld' ¿Qué ha pasado con el espacio, las mayúsculas y el símbolo de admiración? Bien, vayamos por partes. Es normal que no se muestren las mayúsculas porque realmente no son la pulsación de una tecla, sino dos (el 'Bloq Mayus' se puede considerar como el uso repetido de 'Shift'). Tendremos que tenerlo en cuenta. Lo mismo pasa con la admiración. El caso del espacio es diferente. La función &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;string_to_keysym()&lt;/span&gt; sólo reconoce las cadenas que tengan una correspondencia directa con algún atributo del módulo &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;XK&lt;/span&gt;. Es decir, lo que necesitamos es el nombre del &lt;i&gt;keysym&lt;/i&gt; sin el prefijo &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;XK_&lt;/span&gt;. En este caso, habrá que "traducir" ese espacio, ' ', a la cadena 'space'. Haciendo los cambios oportunos, tendríamos:&lt;br /&gt;&lt;br /&gt;&lt;pre class="python" name="code"&gt;from Xlib.display import Display&lt;br /&gt;from Xlib.ext import xtest&lt;br /&gt;from Xlib import X, XK&lt;br /&gt;&lt;br /&gt;d = Display()&lt;br /&gt;msg = "Hello World!"&lt;br /&gt;shift = d.keysym_to_keycode(XK.XK_Shift_L)&lt;br /&gt;&lt;br /&gt;for c in msg:&lt;br /&gt;    if   c == ' ': c = "space"&lt;br /&gt;    elif c == '!': c = "exclam"&lt;br /&gt;    keysym = XK.string_to_keysym(c)&lt;br /&gt;    keycode = d.keysym_to_keycode(keysym)&lt;br /&gt;&lt;br /&gt;    if c in ["H","W", "exclam"]:&lt;br /&gt;        xtest.fake_input(d, X.KeyPress, shift)&lt;br /&gt;&lt;br /&gt;    xtest.fake_input(d, X.KeyPress, keycode)&lt;br /&gt;    xtest.fake_input(d, X.KeyRelease, keycode)&lt;br /&gt;&lt;br /&gt;    if c in ["H","W", "exclam"]:&lt;br /&gt;        xtest.fake_input(d, X.KeyRelease, shift)&lt;br /&gt;&lt;br /&gt;    d.flush()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Se nos ha complicado un poco el código. Como veis, la estrategia es pulsar la tecla SHIFT antes de cada caracter 'especial'. Además, es necesario convertir los símbolos a nombres válidos para &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;XK&lt;/span&gt;. Dentro de &lt;i&gt;gext&lt;/i&gt;, haremos todas estas conversiones, para que introducir cualquier texto sea lo más sencillo posible.&lt;br /&gt;&lt;br /&gt;Espero no haberte aburrido mucho ;) Nos vemos en la siguiente entrada.&lt;br /&gt;Happy hacking!&lt;br /&gt;&lt;br /&gt;&lt;span title="¡Adiós!"&gt;Au revoir!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1938427166284563435-8028163437097559519?l=gexter-project.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gexter-project.blogspot.com/feeds/8028163437097559519/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://gexter-project.blogspot.com/2009/12/python-xlib-emulando-el-teclado.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/8028163437097559519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/8028163437097559519'/><link rel='alternate' type='text/html' href='http://gexter-project.blogspot.com/2009/12/python-xlib-emulando-el-teclado.html' title='python-xlib: emulando el teclado'/><author><name>Oscar Aceña</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1938427166284563435.post-638565734197823154</id><published>2009-11-26T07:53:00.000-08:00</published><updated>2009-11-26T08:02:42.447-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xlib'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Gext: python xlib</title><content type='html'>Nĭmen hăo!&lt;br /&gt;&lt;br /&gt;Para llevar a cabo lo descrito en el &lt;i&gt;post&lt;/i&gt; anterior, he pensado en utilizar la implementación de &lt;a href="http://es.wikipedia.org/wiki/Xlib"&gt;Xlib&lt;/a&gt; en Python, llamada &lt;a href="http://python-xlib.sourceforge.net/"&gt;python-xlib&lt;/a&gt;. Aunque no tiene un desarrollo continuado, creo que me servirá para lo que quiero hacer. El hecho de que esté escrita íntegramente en Python me supone una ventaja, para cotillear su código ;) Además, tiene también varias extensiones portadas. En concreto, la que me interesa es XTEST, que tiene algunos mecanismos para manipular la entrada.&lt;br /&gt;&lt;br /&gt;Vamos a hacer algunas pruebas. Para seguirme, tendrás que tener instalado el paquete python-xlib. Esto depende de tu distribución. Por ejemplo, para &lt;a href="http://www.debian.org/index.es.html"&gt;Debian&lt;/a&gt; (y derivados como &lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt;), el paquete está en los repositorios oficiales, con lo que un simple &lt;br /&gt;&lt;pre&gt;# apt-get install python-xlib&lt;/pre&gt;lo soluciona.&lt;br /&gt;Empecemos por lo fácil, vamos a intentar mover el ratón... sin tocarlo :D . Abre una consola Python (a mi me gusta &lt;a href="http://ipython.scipy.org/moin/Documentation"&gt;ipython&lt;/a&gt;), o escríbelo en un fichero y lo ejecutas, como quieras. Primero pongo el código, y luego vemos que hace.&lt;br /&gt;&lt;br /&gt;&lt;pre class="python" name="code"&gt;from Xlib.display import Display&lt;br /&gt;&lt;br /&gt;d = Display()&lt;br /&gt;r = d.screen().root&lt;br /&gt;for i in range(200):&lt;br /&gt;    r.warp_pointer(i, i)&lt;br /&gt;    d.sync()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Sencillo, ¿verdad? Desgranemoslo. En primer lugar, importar la clase &lt;i&gt;Display&lt;/i&gt;. Un display para Xlib es una estación de trabajo, es decir, un monitor, un teclado y un ratón (esto es muy simplista, porque puede haber muchas combinaciones diferentes, por ejemplo, dos o más monitores, o una tableta digitalizadora, etc.). Tenemos en cuenta que X es un servidor, y nosotros actuamos como clientes. Al crear un objeto &lt;i&gt;Display&lt;/i&gt;, realmente lo que hacemos es conectarnos al servidor.&lt;br /&gt;&lt;br /&gt;De este servidor, obtenemos el screen, un objeto complejo del que nos interesa principamente la ventana raíz, &lt;i&gt;root&lt;/i&gt;. A esta ventana le podemos decir que mueva el ratón, con &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;warp_pointer()&lt;/span&gt;. Hasta que no hacemos un &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sync() &lt;/span&gt;en el &lt;i&gt;Display&lt;/i&gt;, no se envían las acciones al servidor, y por tanto es como si no hiciéramos nada. Para mejorar el efecto, en vez de movernos a un punto, lo que hacemos es desplazarnos por una recta. Para eso es el bucle.&lt;br /&gt;&lt;br /&gt;Si lo ejecutas, deberías ver que el ratón se mueve a la esquina superior izquierda (el punto (0,0) de la ventana raíz), y se desplaza 200 &lt;i&gt;píxels&lt;/i&gt; en los ejes x e y, con pasos de 1 &lt;i&gt;pixel&lt;/i&gt;. &lt;br /&gt;&lt;br /&gt;Hacer click es un poco más complejo. Para ello, necesitamos la extensión XTEST. Usaremos una función llamada &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;fake_input()&lt;/span&gt;, que simula la pulsación de una tecla, tanto del ratón como del teclado. Veamos el código para pulsar el botón derecho del ratón:&lt;br /&gt;&lt;br /&gt;&lt;pre class="python" name="code"&gt;from Xlib.ext import xtest&lt;br /&gt;from Xlib import X&lt;br /&gt;&lt;br /&gt;xtest.fake_input(d, X.ButtonPress, 3)&lt;br /&gt;xtest.fake_input(d, X.ButtonRelease, 3)&lt;br /&gt;d.sync()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Importamos los módulos correspondientes: xtest y X (para los eventos que generaremos). Como veis, se usa el mismo display, 'd', que habíamos creado antes (la misma conexión). Le indicamos qué evento queremos que mande al servidor, en este caso primero un &lt;i&gt;ButtonPress&lt;/i&gt; y luego un &lt;i&gt;ButtonRelease&lt;/i&gt;, y los datos relacionados con el evento, que aquí es el número del botón que queremos pulsar. Al hacer de nuevo un &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sync()&lt;/span&gt;, lo envía todo al servidor X, y dependiendo de donde esté el puntero del ratón, deberíamos ver un menú contextual, o algo así :D&lt;br /&gt;&lt;br /&gt;¿Queréis probar el teclado? Bueno, pues eso creo que será en otro post, porque es un poco lioso :P .&lt;br /&gt;&lt;br /&gt;Zàijiàn!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1938427166284563435-638565734197823154?l=gexter-project.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gexter-project.blogspot.com/feeds/638565734197823154/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://gexter-project.blogspot.com/2009/11/gext-python-xlib.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/638565734197823154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/638565734197823154'/><link rel='alternate' type='text/html' href='http://gexter-project.blogspot.com/2009/11/gext-python-xlib.html' title='Gext: python xlib'/><author><name>Oscar Aceña</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1938427166284563435.post-8446467229269689121</id><published>2009-11-25T00:01:00.000-08:00</published><updated>2009-11-25T01:14:34.102-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='diseño'/><category scheme='http://www.blogger.com/atom/ns#' term='gext'/><category scheme='http://www.blogger.com/atom/ns#' term='librería'/><title type='text'>Sobre Gext (la librería)</title><content type='html'>¡Hola!&lt;br /&gt;&lt;br /&gt;Como veis, últimamente estoy más animado para avanzar con el proyecto, aunque sólo sea pensar (porque la fase de desarrollo todavía no está oficialmente abierta). Este &lt;i&gt;post&lt;/i&gt; va sobre la librería que comentábamos en el anterior.&lt;br /&gt;&lt;br /&gt;Me he dado cuenta de que tanto el editor como el compilador son sólo accesorios. Lo único imprescindible es la librería. Me explico: el objetivo final será un &lt;i&gt;script&lt;/i&gt;, generado con el compilador a partir de un proyecto creado con el editor. Pues bien, ese &lt;i&gt;script&lt;/i&gt; se puede escribir a mano (obviamente, no quiero que eso sea siempre así, pero para probar la librería es válido). Por lo que la parte por la que empezaré será esa: gext. &lt;br /&gt;&lt;br /&gt;Según lo tengo pensado, una de las funciones principales será la de emular el comportamiento humano, es decir, generar eventos del teclado y del ratón. Actualmente, la mayoría de los sistemas a los que va dirigida esta aplicación sólo cuenta con un dispositivo de cada tipo (si esto cambia, ya veremos :D). Por ello, intuitivamente, tendremos dos objetos, uno para el teclado y otro para el ratón (sendos &lt;a href="http://es.wikipedia.org/wiki/Singleton"&gt;singletones&lt;/a&gt; ;) ). Estos objetos tendrán una interfaz que permita controlar los dispositivos &lt;i&gt;programáticamente&lt;/i&gt;. Por ejemplo, para el ratón, se debería poder mover, pulsar el botón derecho, soltarlo (con soporte para todos los botones posibles, claro :D), obtener su posición, etc. Y para el teclado idem.&lt;br /&gt;&lt;br /&gt;Me atrevería a esbozar las interfaces aquí mismo. Veamos. La del ratón:&lt;br /&gt;&lt;pre class="python" name="code"&gt;class Mouse:&lt;br /&gt;    def getPosition(self):&lt;br /&gt;        pass&lt;br /&gt; &lt;br /&gt;    def moveTo(self, x, y, abs=True):&lt;br /&gt;        pass&lt;br /&gt;&lt;br /&gt;    def pressButton(self, button):&lt;br /&gt;        pass&lt;br /&gt;&lt;br /&gt;    def releaseButton(self, button):&lt;br /&gt;        pass&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Las argumentos &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;x&lt;span style="font-family: inherit; font-size: x-small;"&gt; &lt;/span&gt;&lt;/span&gt;e y son enteros que indican la posición, y &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;abs&lt;/span&gt; especifica si el movimiento es absoluto (desde la posición 0,0 de la ventana &lt;i&gt;root&lt;/i&gt;), o relativo a la posición actual del ratón. Button es un entero que indica el número de botón a pulsar. Se pueden añadir algunos métodos para simplificar ciertas tareas comunes, por ejemplo, un &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;leftClick&lt;/span&gt;(), o un &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dragTo&lt;/span&gt;(). La del teclado, podría ser algo así:&lt;br /&gt;&lt;pre class="python" name="code"&gt;class Keyboard:&lt;br /&gt;    def pressKey(self, key):&lt;br /&gt;        pass&lt;br /&gt;&lt;br /&gt;    def releaseKey(self, key):&lt;br /&gt;        pass&lt;br /&gt;&lt;/pre&gt;De nuevo, también añadiré algunos métodos para tareas comunes. En este caso, es muy frecuente querer introducir muchos caracteres seguidos, en vez de ir uno por uno. Para ello, algo como &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;generateKeyEvents&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;(&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;seq&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;)&lt;/span&gt; sería útil, donde &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;seq&lt;/span&gt; es una cadena de texto.&lt;br /&gt;&lt;br /&gt;Bueno, creo que por hoy, ya tengo bastante :D . ¡Hasta el siguiente post!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1938427166284563435-8446467229269689121?l=gexter-project.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gexter-project.blogspot.com/feeds/8446467229269689121/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://gexter-project.blogspot.com/2009/11/sobre-gext-la-libreria.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/8446467229269689121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/8446467229269689121'/><link rel='alternate' type='text/html' href='http://gexter-project.blogspot.com/2009/11/sobre-gext-la-libreria.html' title='Sobre Gext (la librería)'/><author><name>Oscar Aceña</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1938427166284563435.post-8406482847965429342</id><published>2009-11-24T09:41:00.000-08:00</published><updated>2009-11-24T09:41:48.392-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='diseño'/><title type='text'>Partes del proyecto</title><content type='html'>Hola de nuevo.&lt;br /&gt;&lt;br /&gt;Según el planteamiento del post anterior, gexter no va a ser una sola herramienta, sino un conjunto de ellas. A primera vista, veo como mínimo tres entidades completamente diferenciadas.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;El editor de secuencias. Con el se crean realmente los &lt;i&gt;screencasts&lt;/i&gt;, especificando la secuencia de acciones, opciónes de configuración, gestión de proyectos, etc.&lt;/li&gt;&lt;li&gt;Librería. Será un módulo que englobe todo lo necesario para poder lanzar los scripts que ejecuten las acciones.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Compilador, algo sencillo que tome como entrada un fichero de proyecto de gexter y produzca un script en Python autosuficiente (lo que quiere decir que no depende del editor), para ejecutar en cualquier parte.&lt;/li&gt;&lt;/ol&gt;¿Nombres? Buena cuestión. Nunca he sido demasiado bueno en este campo ;) Pero bueno, alguno tienen que tener: la librería será "gext", (una ola de imaginación), el compilador podría ser "gexta" (uff, quizá este cambie), y el editor se va a quedar con "gexter". Bueno, divide y vencerás... a ver si es cierto ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1938427166284563435-8406482847965429342?l=gexter-project.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gexter-project.blogspot.com/feeds/8406482847965429342/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://gexter-project.blogspot.com/2009/11/partes-del-proyecto.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/8406482847965429342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/8406482847965429342'/><link rel='alternate' type='text/html' href='http://gexter-project.blogspot.com/2009/11/partes-del-proyecto.html' title='Partes del proyecto'/><author><name>Oscar Aceña</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1938427166284563435.post-6663842485554188173</id><published>2009-11-23T11:06:00.000-08:00</published><updated>2009-11-23T11:06:50.154-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='diseño'/><title type='text'>Entrando en materia</title><content type='html'>¡Hola a todos!&lt;br /&gt;&lt;br /&gt;Creo que es hora de ir impezando con el proyecto. Y lo mejor para empezar es contar de que va todo esto ;) &lt;br /&gt;&lt;br /&gt;Muchas veces me he encontrado en la necesidad de explicar paso a paso como hacer determinada tarea en GNU/Linux. Y en esas ocasiones, he pensado: "Si tuviera un video para enseñarselo, sería genial". Otras veces, el problema ha sido diferente: añadir una nueva característica a la interfaz gráfica de una aplicación, o un nuevo plugin a cierta web, y tener que ejecutar los mismos pasos una y otra vez para probarla. Exasperante. &lt;br /&gt;&lt;br /&gt;Para estas ocasiones (y otras), podemos usar software que nos ayude. Tanto para crear rápidamente un vídeo como para automatizar las pruebas de una interfaz gráfica. Aunque parece que no tiene nada que ver, pero ciertamente comparten mucho ámbito del problema. Si nos ponemos a buscar herramientas para esto, encontramos algunas. La mayoría privativas, algunas otras libres. Pero casi todas adolecen de algo. Por ejemplo, encontré &lt;a href="http://www.sandklef.com/xnee/"&gt;xnee&lt;/a&gt;. Promete bastante, pero está basado en una extensión de X (RECORD) que hace varios meses que no funciona (por lo que no he podido probarlo). Además, resuelve uno de los problemas (la automatización), pero no todos. &lt;br /&gt;&lt;br /&gt;Otra librería que se usa para esto mismo es &lt;a href="http://ldtp.freedesktop.org/wiki/"&gt;LDTP&lt;/a&gt;. Está dedicada a la automatización de pruebas para interfaces gráficas. Promete mucho, pero usa las librerías de &lt;b&gt;accesibilidad&lt;/b&gt; para la introspección de widgets. No es que tenga nada en contra de ellas, pero son bastante intrusivas, y algunas veces me he encontrado con problemas (especialmente con la combinación python (GIL) + Gtk (no thread-safe) + LDTP). &lt;br /&gt;&lt;br /&gt;Por otro lado, están las herraminetas para grabar el screencast (como &lt;a href="http://recordmydesktop.sourceforge.net/about.php"&gt;recordmydesktop&lt;/a&gt;, &lt;a href="http://recordmydesktop.sourceforge.net/about.php"&gt;istambul&lt;/a&gt;, etc.). Estas  se especializan en otra tarea (la de grabar), pero no dan la posibilidad de añadir "objetos visuales" al vídeo (como cuadros de texto, zoom, sobreado, etc.). &lt;br /&gt;&lt;br /&gt;Tendríamos que combinar varias de estas herramientas, creando algunos scripts ad-hoc, para nuestra tarea. Si bien se podría hacer (yo me encontré en la necesidad de hacerlo alguna vez, cosa que, de hecho, fué la clave para iniciar este proyecto), no es nada cómodo. &lt;br /&gt;&lt;br /&gt;Es por eso por lo que nace el proyecto &lt;b&gt;&lt;i&gt;Gexter&lt;/i&gt;&lt;/b&gt;. Pretende ser un software completo, que permita realizar las siguientes tareas, de una forma visual y sencilla:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Automatizar pruebas de interfaces gráficas (GUI).&lt;/li&gt;&lt;li&gt;Grabar en vídeo el resultado de la automatización.&lt;/li&gt;&lt;li&gt;Añadir elementos visuales para destacar ciertos objetos/zonas, tales como cajas de texto, sombreado, zoom, control de temas, etc.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Poder editar individualmente cada grupo de acciones, navegar a través del flujo de eventos, etc.&lt;/li&gt;&lt;li&gt;Generar &lt;i&gt;scripts&lt;/i&gt; autónomos, para lanzar sin necesidad de disponer de la herramienta completa, o conocer su funcionamiento.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Soporte para audio, ya sea directo u &lt;i&gt;off-line. &lt;/i&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Y muchas más cosas que ahora mismo no sé, pero que se me ocurrirán :P Por supuesto, no pretendo reinventar la rueda. Si veo que LDTP o recordmydesktop me sirven, los utilizaré, ya que son grandes proyectos muy válidos. El objetivo es más bien aunar todos los esfuerzos (siempre que se pueda).&lt;br /&gt;&lt;br /&gt;Las herramientas que voy a emplear serán muy dispares, pues es muy amplio el conjunto de problemas a resolver. Pero una cosa sí tengo clara: utilizaré &lt;a href="http://www.python.org/"&gt;Python,&lt;/a&gt; que tiene una gran cantidad de módulos muy útiles, aunque no descarto realizar partes en otros lenguajes (con sus &lt;i&gt;binddings&lt;/i&gt; asociados).&lt;br /&gt;&lt;br /&gt;De momento, poco más. Ya se me van ocurriendo ideas sobre el diseño, y problemas que estas presentan. Así que pronto escribiré sobre esto.&lt;br /&gt;&lt;br /&gt;¡Saludos a todos!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1938427166284563435-6663842485554188173?l=gexter-project.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gexter-project.blogspot.com/feeds/6663842485554188173/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://gexter-project.blogspot.com/2009/11/entrando-en-materia.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/6663842485554188173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/6663842485554188173'/><link rel='alternate' type='text/html' href='http://gexter-project.blogspot.com/2009/11/entrando-en-materia.html' title='Entrando en materia'/><author><name>Oscar Aceña</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1938427166284563435.post-6352418288613820759</id><published>2009-11-20T04:16:00.000-08:00</published><updated>2009-11-20T04:16:18.992-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='noticias'/><title type='text'>Proyecto aceptado</title><content type='html'>¡Buenas noticias!&lt;br /&gt;&lt;br /&gt;¡Me han aceptado en el III Concurso de Software Libre! Eso quiere decir, que ya puedo empezar a pensar en como hacer esto ;) Así pues, manos a la obra.&lt;br /&gt;&lt;br /&gt;Saludos.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1938427166284563435-6352418288613820759?l=gexter-project.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gexter-project.blogspot.com/feeds/6352418288613820759/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://gexter-project.blogspot.com/2009/11/proyecto-aceptado.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/6352418288613820759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/6352418288613820759'/><link rel='alternate' type='text/html' href='http://gexter-project.blogspot.com/2009/11/proyecto-aceptado.html' title='Proyecto aceptado'/><author><name>Oscar Aceña</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1938427166284563435.post-3066575326268624087</id><published>2009-09-04T09:12:00.000-07:00</published><updated>2009-09-04T09:24:08.749-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='noticias'/><title type='text'>¡Bienvenidos!</title><content type='html'>Este blog esta dedicado al proyecto Gexter, una herramienta libre (con licencia &lt;a href="http://www.gnu.org/licenses/gpl-3.0.html" target="_blank"&gt;GPLv3&lt;/a&gt;) que permite la creación y edición de &lt;a href="http://es.wikipedia.org/wiki/Screencast" target="_blank"&gt;screencast&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tanto este blog como el proyecto entero han sido creados para participar en el &lt;a href="http://ceslcam.com/concurso/" target="_blank"&gt;III Concurso de Software Libre&lt;/a&gt;, al que todavía no me puedo apuntar, pero que ya tengo ganas :D&lt;br /&gt;&lt;br /&gt;Tengo muchas ideas que pueden encajar bien, así como otros muchos problemas que resolver. Espero que este blog sea el "centro de mando", desde donde contaré decisiones de diseño, problemas (resueltos o sin resolver), así como documentación, screencasts (:P) y todo lo necesario para poder usarlo.&lt;br /&gt;&lt;br /&gt;Si al final sale algo útil, y encuentras algún bug al usarlo, o crees interesante alguna nueva funcionalidad, ¡cualquier comentario es bienvenido!&lt;br /&gt;&lt;br /&gt;Gracias por tu interés y tiempo. ¡Nos vemos en el siguiente post!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1938427166284563435-3066575326268624087?l=gexter-project.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gexter-project.blogspot.com/feeds/3066575326268624087/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://gexter-project.blogspot.com/2009/09/bienvenidos.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/3066575326268624087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1938427166284563435/posts/default/3066575326268624087'/><link rel='alternate' type='text/html' href='http://gexter-project.blogspot.com/2009/09/bienvenidos.html' title='¡Bienvenidos!'/><author><name>Oscar Aceña</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
