Sábado 25 de marzo de 2017

Asociación LiGNUx: La beta final de Ubuntu 17.04 Zesty Zapus ya esta disponible
David González

David González
Blog Bitix

Ejemplo de JNI, usar código en C desde Java

Para tareas muy específicas que requieran alto rendimiento, baja latencia, tiempo real o haya restricciones de tiempo el lenguaje Java y la JVM pueden mostrar algunas limitaciones obligando a escribir alguna sección crítica de un programa en un lenguaje nativo como C o C++. Para hacer posible la integración entre Java y C existe en Java la API JNI. En este artículo mostraré como realizar un programa Java que emite el mensaje Hola Mundo desde una biblioteca compartida en C y usando JNI.

Java
SVG
Linux

Nunca hasta ahora había tenido necesidad de crear un programa que no estuviese completamente escrito en el lenguaje Java. La API de Java ofrece multitud de clases para cualquier funcionalidad que necesitemos desde estructuras de datos hasta algoritmos de búsqueda o criptografía. También porque el rendimiento de un programa en Java es suficiente y similar a un programa equivalente escrito en C o C++ gracias a las optimizaciones que implementa la máquina virtual de Java o JVM aún siendo los programas Java compilados a una representación intermedia de bytecode independiente de la arquitectura de procesador y sistema operativo en archivos de extensión class y posteriormente interpretados y traducidos a la arquitectura de ejecución, lo que le proporciona a Java la conocida frase “Write once, run anywhere”.

Sin embargo, en casos que se necesita un alto rendimiento para tareas muy específicas o evitar las imposiciones de la máquina virtual como las paradas que realiza para el recolector de basura una solución es escribir esa funcionalidad crítica en lenguaje C, C++ e incluso en Go. El caso de necesidad que me he encontrado es acceder a un sensor de temperatura DHT11 del kit de iniciación a la electrónica para la Raspberry Pi para leer de él la temperatura y humedad. La forma que tiene el sensor DHT11 de proporcionar los datos tiene restricciones de tiempo, cuando se le requieren los valores envía 80 bits de datos donde un pulso de 27μs significa un 0 y un pulso de más de ese tiempo hasta 70μs significa un 1. Estas restricciones de tiempo del sensor y el hecho de que es en una modesta en potencia Raspberry Pi 1 donde lo usaré hace que Java no sea capaz de leer correctamente los valores del sensor.

Acceder desde Java a código nativo en C requiere usar Java Native Interface o por sus siglas JNI. Lo primero que hay que realizar es crear una clase que declare los métodos que serán implementados de forma nativa declarando estos métodos usando la palabra reservada native y que serán enlazados por la JVM cargando una librería compartida con System.loadLibrary(). Creada la clase Java se ha de generar el archivo de cabecera .h propia del lenguaje C con el programa de utilidad del JDK javah. Con el archivo de cabecera se implementa la función y se crea una librería compartida en GNU/Linux usando el compilador gcc. Con la librería compartida se puede iniciar el programa Java. Si la biblioteca compartida no se encuentra se lanzará una excepción del tipo UnsatisfiedLinkError.

Excepción UnsatisfiedLinkError cuando no se encuentra la librería de código nativo

Algunas otras necesidades para hacer uso de JNI son:

  • Acceder a características dependientes de la plataforma necesitadas por la aplicación que no están soportadas en la librería estándar de Java.
  • Ya hay una librería escrita en otro lenguaje y se quiere hacer accesible a código Java a través de JNI.
  • Se quiere implementar una pequeña parte de código crítico en un lenguaje de bajo nivel como ensamblador.

Desde los métodos de código nativo se puede:

  • Crear, inspeccionar y actualizar objetos Java (incluyendo arrays y strings).
  • Llamar a métodos Java.
  • Capturar y lanzar excepciones.
  • Cargar y obtener información de clases.
  • Realizar validación de tipos en tiempo de ejecución.

Los comandos para generar el archivo de cabecera de C y compilarlo con el código nativo en una librería compartida con gcc son:

La cabecera usa varias definiciones de tipos definidas en los archivos jni.h y el archivo que variará según el sistema operativo jni_md.h. En la estructura JNIEnv con múltiples funciones de integración en C y Java, también varias definiciones de los tipos Java para usarlos en C como jobject, jstring, jint, jboolean, jlong, jdouble, jchar, etc.

El programa que emite el mensaje Hello World! desde código nativo en C debe cargar y enlazar la librería de código nativo con el código de la clase Java. Esto se muestra en el bloque de inicialización static de la clase, en este caso usándo el método System.load(), la librería de código nativo de extensión .so en GNU/Linux como en este caso al construirse el proyecto se incluye en el archivo .jar del artefacto resultante se extráe al directorio temporal y se carga desde esa ubicación temporal. En el programa se llama al método print implementado en código nativo y en el código C se usa la función printf de la librería stdio para emitir el mensaje:

La librería compartida para un sistema amd64 la he compilado en mi equipo de escritorio y para la versión arm en la Raspberry Pi e incluido en el directorio src/main/resources de código fuente del ejemplo.

Mensaje en la terminal emitido desde código nativo en un sistema amd64 y ARM

Ente ejemplo usa Java 8 y requiere instalar el compilador gcc para compilar la librería con código nativo. Gradle ofrece soporte para compilar código nativo con su plugin, sin embargo, he preferido usar y conocer los comandos javah y gcc sin usar Gradle. En el siguiente artículo mostraré el ejemplo del sensor DHT11 usando JNI y código nativo en C llamando a métodos de un objeto Java desde código C.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradlew executeJniHelloWorldLocal.

Baltasar Ortega

Baltasar Ortega
KDE Blog

Lanzada la beta de KDE Aplicaciones 17.04

Nos acercamos a abril, el primer mes del año elegido para que el equipo de desarrollo de KDE haga el lanzamiento de su gran revisión de sus aplicaciones. Pero antes de este gran actualización siempre hay que probar. Por eso me complace anunciar que ha sido lanzada la beta de KDE Aplicaciones 17.04. ¡Esto no para! ¡KDE Rocks!

Lanzada la beta de KDE Aplicaciones 17.04

El pasado 24 de marzo el equipo de desarrollo de la Comunidad KDE anunció la beta de KDE Aplicaciones 17.04, otro paso más en la evolución de su ecosistema de programas que tiene dos objetivos fundamentales: seguir mejorando las aplicaciones KDE y continuar la migración de más aplicaciones al entorno de trabajo Qt5/KF5.

Tras un trabajo que se inició el mismo día que se lanzó KDE Aplicaciones 16.08, los desarrolladores han estado trabajando de forma silenciosa pero coordinada y constante preparando las nuevas funcionalidades que nos esperan en agosto

Ahora es el momento de congelar las funcionalidades y las dependencias, y que el equipo de desarrollo (y todas aquellas personas que así lo deseen) se centren en corregir errores y pulir las aplicaciones.

Más información: KDE.org

Pruébalo y reporta errores

Lanzada la beta de KDE Aplicaciones 17.04Todas las tareas dentro del mundo del Software Libre son importantes: desarrollar, traducir, empaquetar, diseñar, promocionar, etc. Pero hay una que se suele pasar por alto y de la que solo nos acordamos cuando las cosas no nos funcionan como debería: buscar errores.

Desde el blog te animo a que tú seas una de las personas responsables del éxito del nuevo lanzamiento de las aplicaciones de KDE. Para ello debes participar en la tarea de buscar y reportar errores, algo básico para que los desarrolladores los solucionen para que el despegue de KDE Aplicaciones 16.04 esté bien pulido. Debéis pensar que en muchas ocasiones los errores existen porque no le han aparecido al grupo de desarrolladores ya que no se han dado las circunstancias para que lo hagan.

Para ello debes instalarte esta beta y comunicar los errores que salgan en bugs.kde.org, tal y como expliqué en su día en esta entrada del blog.

Viernes 24 de marzo de 2017

Asociación LiGNUx: Gnome-Keyring y sus problemas fuera de Gnome
Miguel Parada

Miguel Parada
Ubuntizando.com

¿Cómo manipular imágenes usando el terminal?

Para manipular las propiedades de una imagen no es necesario disponer de aplicaciones especiales de diseño gráfico. En GNU/Linux el

Para leer completa esta publicación haz click sobre el título
Miguel Parada

Miguel Parada
Ubuntizando.com

Raspberry Pi ya es el ordenador más vendido del mundo

¿Sabías que el ordenador más vendido de la historia fue el mítico Commodore 64? Y digo fue porque Raspberry Pi

Para leer completa esta publicación haz click sobre el título
Miguel Parada

Miguel Parada
Ubuntizando.com

¿Cómo elegir un hosting WordPress económico que se ajuste a nuestras necesidades?

Esta semana un amigo me preguntaba cuál era la mejor oferta disponible dado que últimamente estoy todo el día “en

Para leer completa esta publicación haz click sobre el título

Jueves 23 de marzo de 2017

Baltasar Ortega

Baltasar Ortega
KDE Blog

KDE Blog llega a su noveno aniversario

Los años no pasan, vuelan. KDE Blog  llega a su noveno aniversario este 2017, lo que significa que he compartido mis conocimientos y experiencias sobre KDE y GNU/Linux en forma de más de 4200 artículos. Un aniversario que me gusta también compartir con vosotros porque este blog se ha convertido en uno de los pilares de mi vida y considero a los lectores como amigos virtuales.

KDE Blog llega a su noveno aniversario

KDE Blog llega a su noveno aniversarioEn 2008, tras unos años disfrutando del mundo del Software Libre, consideré que le debía devolver algo de lo que me había dado. De esta forma pensé que la única forma con la que podía ayudar a este mundo del conocimiento libren era mediante la creación de un blog que ayudara a la difusión de las bondades del mismo.

Y eso que no me consideraba un experto, ni mucho menos, simplemente pensé que al no ser un experto y trabajar como docente me convertía en una persona ideal para poder explicar a otros novatos como yo cómo hacer cosas con Software Libre al tiempo que dejaba plasmadas mis soluciones a mis problemas de una forma pública.

Así que el 24 de marzo de 2008 nació KDE Blog. Fue un parto sencillo, me bastó comentarlo con mi compañero virtual Daniel Moreno, que me proporcionó el alojamiento, reunr  unas cuantas entradas cuya finalidad era introducir a los lectores en el mundo GNU/Linux y el valor suficiente para salir de mi zona de confort y empezar a publicar de forma diaria noticias sobre KDE y sus distribuciones. Y quiero destacar “mi obligación” de publicar de forma diaria una entrada ya que fue la forma de crear un hábito en mi trabajo y que este proyecto no muriera.

Declaración de intenciones de KDE Blog

[24 de marzo de 2008]
Hola a todos y todas: Hoy se inaugura KDE Blog un nuevo blog en el inmenso e infinito mundo de los blogs. El objetivo de este blog es múltiple: ayudar a los principiantes en el mundo Linux, informar sobre el mundo KDE, (el entorno de escritorio de bajo Linux) y fomentar el uso del Software Libre.

A lo largo de estos 8 años he ido publicando entradas conmemorativas que podéis seguir en la siguiente etiqueta y este año no he querido ser menos. Pero no me voy a repetir, así que os remito a la entrada del año pasado para leer el resumen de las entradas anteriores, y este año me dedicaré a repasar mi año como humilde profeta del Conocimiento Compartido.

Mi año como activista del Software Libre

Desde hace un tiempo, mi resumen anual no lo hago el 31 de diciembre sino que he decidido hacerlo en marzo, para celebrar el aniversario del blog. En esta ocasión he decidido dividir el resumen en tres apartados: el blog, mi entorno y KDE España.

Mi actividad virtual con el blog.

KDE blog cuadradoEste año no ha sido de los peores en cuanto a tiempo disponible. Tal y como anticipé el año pasado, poco a poco estoy recuperando ese tiempo delante del PC necesario para hacer artículos de una calidad decente.

De esta forma, un año más he conseguido mantener el ritmo de una entrada diaria, incluso teniendo durante mucho tiempo unos artículos en la recamara para sacarlos en tiempos más duros. Ha ayudado mucho el hecho de que este año hay asido prolífico en noticias sobre KDE: el 20 aniversario de KDE, los múltiples eventos del Softwae Libre, la aparición de KDE Slimbook, mi participación más activa en KDE España, decenas de actualizaciones, etc.

Ah, casi se me olvida, el blog tuvo su reconocimiento con el Premio al mejor medio de los Open Awards 2016 en la OpenExpo 2016, al cual este año no he podido presentarme por motivos de causa mayor.

Mi actividad en mi entorno

Respecto a este aspecto sigo teniendo dos frentes: mi entorno como persona y mi papel como organizador de las Jornades Lliures de la UNED de Vila-real.

Cada día que pasa soy un poco más abierto en mi promoción con el Software Libre. A nivel laboral defiendo todos los días y a todos los miembros de la Comunidad Educativa (alumnos, profesores, familias, instituciones, etc) la Comunidad GNU/Linux y KDE: sus distribuciones, sus aplicaciones, sus formatos libres, etc. Reivindicando las libertades para los usuarios y las ventajas para la sociedad.

De esta forma, sigue aumentando el número de usuarios que utilizan distribuciones Linux a mi alrededor. Quizá sea el momento de dar otro paso y ser más activo para con las personas qu todavía no se deciden.

No obstante las V Jornadas y Talleres Libres, no están siendo satisfactorias. Las razones son la baja asistencia de público y algunas ponencias canceladas.

Finalmente está pesando más la falta de promoción e innovación que las ganas de continuar. Así que , me estoy pensando muy seriamente coger una año sabático con esta iniciativa. Creo que necesito un grupo de personas para seguir adelante ya que no veo los resultados esperados.

Mi actividad con KDE España

En esta  ocasión creo que mi actividad con la asociación está llena de logros, en parte por el gran grupo de personas que la forma y que siempre están dispuestas a colaborar en mejorarla.

Dentro de KDE España tengo dos funciones ya que además de ser el coordinador del Grupo de Comunicación, este año he recibido el encargo de ser el Secretario, lo cual implica atender a ciertos encargos organizativos como la gestión de miembros y redactar las actas de las reuniones.

Además, mi implicación en los Podcast de KDE España es muy activa, tanto como organizador de las mismas como participante en todas las emisiones. Se trata de un medio que resulta muy atractivo y que engancha.

No quisiera desaprovechar la entrada para animaros a seguirnos en cualquiera de las siguientes redes donde KDE España estamos presentes:

Además, aprovecho para invitaros también a ver o escuchar los podcast que solemos hacer mensualmente algunos miembros de la Comunidad KDE España en la que hablamos de diversos temas relacionados con el Software Libre y que ya ha llegado a su tercera temporada.

Por último, invitaros al próximo Akademy-es y Akademy que se celebará en Almería y que promete ser otro gran evento al cual espero poder asistir.

 Renovación de votos

Y siguiendo la tradición quiero hacer público mi idea sobre la marcha del blog y de mi compromiso con el Software Libre para el próximo año y anunciar que:

  • KDE Blog sigue teniendo cuerda para muchos años,
  • Sigo estando cada día un poco más ilusionado con el proyecto KDE y en su difusión, empiezo a pensar en que cada vez está más cerca en el momento en que quiera convertir a Castellón, como provincia, en un referente del Software Libre como es Barcelona, A Coruña, Bilbao o Málaga.
  • Sigo abierto a todo tipo de colaboraciones (¿quieres ayudar a publicar en el blog? ¿Encargarte de la parte social? ¿Mejorar las entradas? Mándame un correo [bortega@kde_espana.org] y hablamos)
  • Y para finalizar decir que me siento orgulloso de pertenecer a un movimiento cuyo objetivo es compartir su conocimiento en pro de una evolución más rápida de la humanidad, que se concreta en pertenecer a una Asociación de Software Libre como KDE España.

Así que:

¡Muchísimas gracias a todos por seguirme y nos vemos en Akademy-es de Almería!

Lingua Franca: una nueva versión de Heuristica

Este artículo es parte de la serie Recomendando fuentes tipográficas Hoy toca a una nueva versión de la fuente Heuristica que si bien ha sido pensada para lingüistas puede utilizarse en otros ámbitos: Lingua Franca Esta fuente, desarrollada por Andreas Nolda, es muy parecida a otra de la que hablamos en estas páginas hace ya […]
Asociación LiGNUx: Tutorial para instalar la versión de mantenimiento del kernel Linux 4.10.5

Webminal, aprende a manejar la consola de Linux sin esfuerzo

¿Eres de los que piensa en Linux y sólo ve la consola?, ¿te da miedo dar el paso porque no sabes dónde aprender los comandos más básicos?, ¿te aburren los manuales de quinientas páginas?. Si has respondido a cualquiera de estas preguntas que si, este artículo es para ti, no dejes de leer. Y es que hoy os traemos una nueva forma de aprender los comandos de linux, pero mucho más
Baltasar Ortega

Baltasar Ortega
KDE Blog

Curso de Audacity de Podcast Linux #01 Graba y edita tu voz

A raíz de presentaros hace unos días el curso de Audacity de Podcast Linux, pensé que no estaría de más dar la mayor publicidad posible a este proyecto De esta forma me he decidido realizar una entrada en el blog promoviendo cada uno de los capítulos que ha creado el gran Juan Febles. Así pues, bienvenidos al episodio del Curso de Audacity de Podcast Linux #01 Graba y edita tu voz con el que se inicia esta más que interesante serie.

Curso de Audacity de Podcast Linux #01 Graba y edita tu voz

Curso de Audacity de Podcast Linux #01 Graba y edita tu vozEn el primer capítulo del curso de Audacity, que Juan ha titulado “Graba y edita tu voz” se nos plantean las bases del proyecto, explicando el nacimiento del mismo, así como las fuentes en las que se ha basado para realizar el mismo, que no son otras que el Curso básico de Audacity de 9 decibelios realizado por David Arribas y la serie de vídeos titulada Manuel Audacity del gran Juan Luis Fernández Gallo, conocido como Jenofonte.

También en este episodio nos recomienda el tipo de micrófonos más adecuado para la realización de podcast, que para él son los dinámicos, y explica las conexiones de su micrófono actual. Del mismo modo, nos explica los consejos básicas para realizar un correcto registro de nuestra voz: ambiente de grabación, distancia y posición respecto al micrófono, disminuir eco gracias a estanterías con libros, espumas amortiguadoras de sonidos explosivos, etc.

Tras esas explicaciones, Juan se encarga de mostrarnos las partes básicas de Audacity como el medidor de decibelios o el registro de su propia voz en forma de onda sonora. Posteriormente nos muestra algunos retoques que realiza sobre dicha grabación: eliminación del  ruido de ambiente, realzar las zonas más bajas gracias Chris’s Dynamic Compressor, ecualizar un poco su voz y limitar las zonas con alta intensidad sonora.

 

Sin más, os dejo disfrutar de la visualización del vídeo:

Más información: Curso de Audacity de Podcast Linux #01 Graba y edita tu voz

Miércoles 22 de marzo de 2017

BlogDRAKE: La magia sigue viva

Lunes 20 de marzo de 2017

Pedro L. Lucas

Pedro L. Lucas
Cartas de Linux

Off-topic: El cambio climático y lo que no hacemos por evitarlo

Me gustaría enseñaros un vídeo que muestra la evolución del CO2 en la atmósfera durante un año. Evidentemente es una simulación por ordenador, pero tiene algunas cuestiones interesantes:

  • Durante los meses de primavera y verano, la fotosíntesis se ve favorecida, se puede ver muy claramente la absorción del CO2 por parte de los árboles (el efecto es espectacular).
  • La mayoría de los países desarrollados parece que estén ardiendo del CO2 que emiten.
  • El modelo también muestra la evolución del CO (no CO2), un gas altamente perjudicial.

El vídeo está en inglés, pero se viendo las leyendas de la parte inferior se puede entender la evolución del CO2:

Todos sabemos que el CO2 es uno de los responsables del efecto invernadero, pero no el único:

Basado en el vídeo anterior, hay otro que ofrece más información:

Vamos hacer unos números. He buscado por Internet la cantidad de CO2 que absorbe un árbol en un año y obtengo que es del orden de 10 kg de CO2 al año por término medio. Aunque esta cifra varía mucho en función del tamaño del árbol y su etapa de crecimiento.

Supongamos que un ordenador gaste al año del orden de 200 kWh. En la producción de esos 200 kWh se emiten 130 kg de CO2. Por lo tanto, se necesitan 13 árboles para compensar el CO2 que emite un ordenador.

¿Y un coche que haga 20000 km al año? Según este enlace, emite unas 3 toneladas de CO2, aunque según otros sitios las emisiones podrían ser de 2’5 toneladas anuales. Serían necesarios de 250 a 300 árboles para compensar sus emisiones anuales.

En hacer esos 20000 km un tren emite del orden 250 kg de CO2 por pasajero. Por lo que se necesitarían 25 árboles para neutralizar sus emisiones.

¿Y en la fabricación? En fabricar un teléfono móvil se generan gran cantidad de contaminantes. Se estima, por ejemplo, que en la fabricación de cada unidad de iPhone 6 se generan 80kg de CO2, en el transporte hasta la tienda unos 3kg y en su reciclaje 1kg. El usuario se estima que sólo emitirá del orden de 10kg de CO2 por usarlo. En general en los aparatos electrónicos, se contamina más al fabricarlos que lo que el usuario contaminará debido a su uso.

¿Cuántos árboles hay en el mundo? Se estima que hay del orden de 3 billones de árboles. 15 mil millones de ellos son talados cada año.

¿Cuántos coches hay en el mundo? Se estiman que unos mil millones.

Y ahora hago la siguiente cuenta si cada coche hiciera 20000km anuales, emitiendo 3000kg de CO2 al año, emitirán 3.000.000.000.000kg de CO2 al año, los árboles absorben 30.000.000.000.000kg de CO2 al año. Es decir que sólo con los coches estamos contrarrestando la absorción de un décimo del CO2 por parte de los árboles. La cosa preocupa un poco pues a parte de los coches CO2 producen las fábricas, las centrales térmicas, la mayoría de las calefacciones, los seres vivos,…

En esta guerra coches vs árboles, van ganando los coches claramente, como muestra el siguiente vídeo de la evolución del CO2 en la serie temporal:

Está claro que algo estamos haciendo mal, pero… ¿qué hacemos por evitarlo? Yo prácticamente nada. Tengo muchos buenos propósitos, pero si he de hacer un trayecto por ocio, en el cual el tiempo que tarde me da igual, cogeré el coche. Tengo las tres bolsitas de basura para reciclar, pero en mi entono soy de los únicos. A veces por pequeños gestos, como el de guardar un plástico en el bolsillo para tirarlo en su contenedor correspondiente, hacen que me tilden de friki (sí, me ha sucedido).

Tal vez habría que decir basta y cambiar ciertas costumbres: Limitar el uso del coche y no usarlo si hay una alternativa menos contaminante. Usar los aparatos electrónicos hasta que literalmente revienten y no dejarse guiar por modas absurdas que intentan obligarnos a cambiar de móvil cada dos años (por ejemplo). Reusar todo lo que se pueda reusar, como los envases. Reciclar cuando algo llegue al final de su vida útil. Ahorrar energía (apagar la luz y otros dispositivos cuando  no se usen)…

Me temo que sólo tengo buenas intenciones y volveré a coger el coche, comprar el móvil de última generación, o tirar el papelito al suelo mientras digo: ¡Qué sucias están las calles y este ayuntamiento no limpia!

Termino con unas palabras que se atribuyen a los Indios Cris del Canadá: “Cuando hayáis talado el último árbol, matado el último animal y contaminado el último río os daréis cuenta de que el dinero no se come… “


BlogDRAKE: 3 de mis imagenes estaran en Mageia 6

Domingo 19 de marzo de 2017

David González

David González
Blog Bitix

Introducción y ejemplo de cluster de contenedores con Docker Swarm

Las funcionalidades de Docker Swarm están incorporadas en Docker para gestionar clusters de nodos con contenedores de los servicios que deseemos. En artículo comentaré algunas de las propiedades de networkning distribuido incorporado en Docker, como crear un cluster de nodos Docker usando VirtualBox con máquinas virtuales para simular múltiples máquinas junto con como lanzar un servicio en el cluster que en este caso consistirá en un servidor web nginx.

Docker

En artículos anteriores de la serie sobre Docker comentaba varias de las herramientas de Docker como Docker Compose, Dockerfile o Docker Machine con ejemplos de como usarlo en local. Una de las herramientas que me quedaba por investigar era Docker Swarm para crear clusters de nodos para contenedores Docker en un entorno de producción. A partir de la versión 1.12 de Docker se han incorporado varias características a Docker para usaar contenedores de forma distribuida y que a pesar de la complejidad subjacente que debe haber es realmente simple usarlo.

Una de las características es el networking que hace trasnparente la comunicación en red distribuida que se hace entre los nodos y los contenedores de esos nodos. Además permite crear redes por software para que los contenedores conectados a esas redes se comuniquen de forma privada. Otra característica interesante de Docker Swarm es que se encarga de monitorizar el estado de los servicios recreando contendores si alguno deja de funcionar. También a través del denominado routing mesh da igual al nodo del cluster por el que se acceda y da igual en que nodo esté el contenedor que Docker Swarm con esta propiedad se encargará de hacer llegar la petición al contenedor. Además, a lo que en Docker Swarm se denomina servicio se realiza balanceo de carga entre la instancias del mismo que haya en el cluster y al servicio se le asigna un DNS y dirección IP por el que puede ser accedido por otros servicios.

En el siguiente ejemplo para crear el cluster de nodos Docker usaré Docker Machine para crear las máquinas de los nodos en máquinas virtuales de VirtualBox aunque su funcionamiento es similar si usásemos la nube de Amazon EC2, Digital Ocean u otros.

El siguiente script crea primeramente varios nodos cada uno en una máquina virtual, luego establece el nodo 01 como manager y los nodos 02 y 03 como workers usando un token para unirlos al cluster según su rol. Los nodos manager se encargan de mantener el estado del cluster y los que a través de ellos los comandos de los servicios deben ser lanzados, en un entorno de producción posiblemente tendríamos 3 nodos manager para soportar tolerancia a fallos. Finalmente, se obtiene lista los nodos del cluster. El comando docker-machine env node-01 permite establecer el entorno contra el que el comando docker lanzará las operaciones como si de la máquina local se tratase.

Una vez creado los nodos es cuando podemos empezar a crear servicios en el cluster. Los servicios son una definición de los contenedores de Docker que queremos que el cluster ejecute. En el ejemplo definiré el servicio de un servidor web nginx, primeramente crearé una red por software en el cluster a la que los servicios pueden conectarse que en el ejemplo (aunque para este no es necesario) utilizaré para hacer una consulta DNS con la herramienta drill para ver el nombre de dominio y dirección IP que asigna Docker Swarm al servicio del servidor web. Con docker service create se crean los servicios, algunos de los parámetros del comando son el nombre del servicio que queremos asignarle, los puertos que expone en este caso el 80 y 443 en el host para que sea accesible desde fuera del cluster, la redes a las que está conectado y finalmente la imagen del contenedor del servicio que en este caso será la versión de nginx con Alpine para Docker. Se pueden listar los servicios que contiene el cluster con docker service ls y los procesos de cada nodo donde podemos ver en que nodos se está ejecutando los contenedores con docker ps.

Una de las propiedades interesantes del networking de Docker Swarm es que ofrece incorporado balanceo de carga, esto es, si el servicio de nginx del ejemplo estuviese formado por dos instancias las peticiones se distribuirían entre las instancias usando el método round-robin. Otra característica interesante si se observa el ejemplo con detalle es que da igual el nodo al que hagamos la petición que la respuesta se obtendrá igualmente, esto es, aunque la petición se haga al nodo 01 y realmente el contenedor del servidor nginx se esté ejecutando en el nodo 02 la petición se realizará correctamente gracias al routing mesh del neworking de Docker Swarm, esto es gracias a que cada servicio tiene asignada una dirección IP, como se ha visto anteriormente en la salida del comando drill.

En este vídeo de asciinema se ve en funcionamiento todos los anteriores comandos. Y en la aplicación de VirtualBox estarán las máquinas virtuales de cada uno de los nodos que crea el ejemplo. En el vídeo se aprecia que el servicio de nginx se está ejecutando en el nodo 02 cuando se listan los procesos de Docker de cada nodo con docker ps, nótese sin embargo que al hacer un petición HTTP a cualquiera de los nodos se devuelve la página de inicio de nginx ya que gracias al routing mesh de Docker Swarm la petición se redirige de forma transparente para el cliente y el servicio al nodo donde realmente se está ejecutando el contenedor de nginx.

<noscript><a href="https://asciinema.org/a/107868" target="_blank"><img src="https://asciinema.org/a/107868.png" width="734" /></a></noscript> Introducción y ejemplo de cluster de contenedores con Docker Swarm
Máquinas virtuales de los nodos del cluster de Docker Swarm

Los comandos para eliminar un servicio del cluster y eliminar completamente el cluster son los siguientes.

Un libro que me ha gustado mucho y que recomiendo leer sobre Docker Swarm es The Devops 2.1 Toolkit que lo explica detalladamente y todo el libro está orientado a como usarlo en un entorno de producción. Un libro más introductorio que también he leído y que está bastante bien es Docker in Action.

Finalmente, quizás si estás usando GNU/Linux y VirtualBox como yo al crear los nodos con el comando docker-machine te produzca el siguiente error (quizá se corrija en futuras versiones de Docker o VirtualBox).

La solución que he encontrado para que funcione es asignar una dirección IP al adaptador puente solo-anfitrión y levantar la interfaz que usa Docker para comunicarse con las máquinas virtuales previamente a crear el nodo. En Arch Linux con los siguientes comandos.

Se puede definir un conjunto de servicios como una unidad en un archivo en stacks de forma similar a como es posible hacer con Docker Compose cosa que mostraré en otro artículo.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub.

David González

David González
Blog Bitix

Controlar un display LCD 1602 para mostrar texto con la Raspberry Pi y Java

Raspberry Pi
Java

Uno de los motivos por los que compré el kit de iniciación a la electrónica para la Raspberry Pi, además de cacharrear un poco, era en concreto controlar el display LCD de 16 columnas y 2 filas. En el kit el display viene con un adaptador con el bus de comunicación I2C. El display se puede usar sin este bus pero requiere utilizar muchos más pines GPIO de datos de los limitados 17 que ofrece la Raspberry Pi 1 y los 26 de las Raspberry Pi B+, 2 y 3. Controlar el display con I2C requiere únicamente 2 pines, por contra sin usar I2C requiere un número significativamente mayor 4 u 8 pines.

El display 1602 con su adaptador para el bus I2C que viene con el kit ya incorporado en la parte trasera es el siguiente.

Display LCD 1602 y adaptador bus I2C

El esquema de conexionado para controlar el display requiere usar los pines de la Raspberry Pi SDA y SDL además de un pin para proporcionar un voltaje de 5V y otro pin para la tierra. El pin SDA es el número 2 según la numeración de pines de la Raspberry Pi y el SDL es el 5. El pin SDA es utilizado en el bus I2C para transmitir los datos y el SDL para la señal de reloj o sincronización. Utilizando la placa de extensión wiringPi de 26 pines los pines SDA y SDL se encuentran identificados por su nombre y el de la placa de extensión de 40 pines que viene con el kit de iniciación también, deberemos identificar estos pines y realizar las conexiones adecuadamente.

Cableado en la breadboard

Hay que emplear varios cables macho-macho y hembra-hembra para conectar a los pines del adaptador I2C del display a los pines del voltaje de 5V, tierra, SDA y SDL de la placa de pruebas sin soldadura.

Unión cables macho-hembra

El siguiente paso será activar el bus I2C en la Raspberry Pi que por defecto está desactivado. Esto requiere añadir unos parámetros en la configuración de arranque y cargar unos módulos del kernel que finalmente crearán un dispositivo tal que en /dev/i2c-0 o /dev/i2c-0. Si instalamos el paquete i2c-tools podremos detectar el display en el bus I2C, en la captura de pantalla en la dirección 27 que hay que usar al construir la instancia del controlador del display. Estos cambios en la configuración de inicio requieren reiniciar la Raspberry Pi. En un sistema con la distribución Arch Linux ARM los cambios son los siguientes.

Detectción del display 1602 en el bus I2C

Según la especificación del display 1602 este componente soporta varios comandos para controlarlo, algunos son para limpiar el texto, cambiar la dirección de escritura, añadir caracteres personalizados y emitir texto en la línea o posición del display que queramos. No es simple el controlar el display a bajo nivel ya que hay que trabajar en momentos con binario y usar bytes, por ello para el ejemplo usaré la librería diozero que ya trae una implementación de controlador con funciones de alto nivel I2CLcd que en versiones más recientes de la librería ha sido renombrada a HD44780Lcd mucho más cómoda que enviar bytes a bajo nivel al bus I2C, el código fuente de la clase HD44780Lcd está disponible y podemos verlo si hay curiosidad.

En mi caso con la Raspberry Pi 1 he tenido que utilizar la versión 0.9 de la librería diozero porque la 0.8 me generaba un stacktrace de una excepción java.lang.UnsupportedOperationException. Obtener esta versión de la librería como aún era de desarrollo y no estaba publicada en Maven Central la he descargado de un google drive que ha creado el autor y usado en Gradle como una dependencia del sistema de ficheros. Como librería subyacente de diozero para controlar los pines GPIO he usado pigpio.

En el ejemplo mostraré un texto en cada una de las lineas del display y usaré una de las funciones del para mostrar caracteres personalizados con los que es posible crear emojis o caracteres nuevos. El controlador de diozero ya contiene una buena colección de caracteres personalizados que definen el patrón de 5x8 puntos que siguen, los nombres de estos caracteres personalizados están en la clase interna Characters de HD44780Lcd aunque también podemos definir nuevos. El ejemplo es el siguiente donde se muestra el uso de los métodos setText y setCharacter, también el constructor donde hay que indicar la dirección asignada al dispositivo en el bus I2C que siendo la 27 corresponde con el valor definido en una constante. Pero también hay otros métodos como clear, cursorOff y cursorOn para apagar y encender el cursor, displayOff displayOn para apgar y encender el display y createChar para crear nuevos caracteres definidos como una array de 8 posiciones donde cada byte indica los pixeles encendidos de cada fila del caracter de 5x8 y con setCharacter para emitir uno de los 8 posibles que se pueden usar al mismo tiempo. Además de estos también hay otros pocos métodos más relacionados con el cursor.

Mensaje en LCD 1602

Pudiendo mostrar mensajes en display es posible mostrar cualquier información que un programa sea capaz de capturar como temperatura y humedad del correspondiente sensor en el mismo kit, estado de un pulsador, espacio disponible en el disco del sistema, y memoria libre, uptime del sistema, fecha y hora, … cualquier cosa que se nos ocurra.

El ejemplo parece simple, y el programa Java lo es, pero requiere conocer varias cosas que en internet está dispersas como activar el bus I2C o conocer la librería diozero para controlar el display que simplifica enormemente el código y nos evita comunicarnos a más bajo nivel con el display, realizar las conexiones eléctricas también requiere algo de conocimiento. Averiguar todo esto me costó una buena cantidad de tiempo.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradlew executeLcd.

Jueves 16 de marzo de 2017

Gaspar Fernández

Gaspar Fernández
Poesía Binaria

Cómo recuperar pestañas perdidas en Google Chrome

En Internet hay dos tipos de personas: esos que como mucho tienen tres pestañas abiertas a la vez, y parece que les cuesta dinero tener pestañas abiertas. Y los que, como yo, abrimos una pestaña, la dejamos pa’ luego, descubrimos algo interesante y lo abrimos, o incluso mientras buscamos información abrimos todas las entradas del buscador en pestañas para ir mirándolas poco a poco. Total, al final te juntas (sin exagerar) con unas 500 pestañas. Afortunadamente, los navegadores modernos gestionan esto de forma más o menos eficiente.

Acumulando pestañas

Por si las moscas, ya que Chrome/Chromium tiene todo abierto a la vez y muchas veces el sistema no se suspende automáticamente porque alguna página lo prohíbe, yo utilizo la extensión The Great Suspender que se encarga de suspender pestañas que no uso tras un tiempo sin hacerles caso. Esto es sólo para liberar memoria y recursos del ordenador.

Reabriendo pestañas

De la misma manera que se puede abrir una pestaña cerrada recientemente haciendo click con el botón derecho en la pestaña y luego “Volver a abrir pestaña cerrada” o pulsando Control + Mayúscula + T podemos abrir todas las pestañas que teníamos en la ventana cuando la cerramos. Por lo que si hemos cerrado accidentalmente el navegador podemos volver a tener todo abierto con esta combinación de teclas.

Chrome también nos permite guardar en marcadores todas las pestañas que tenemos abiertas con (Control + Mayúscula + D), que nos puede venir muy bien.

Que automáticamente restaure las pestañas

Si entramos en la configuración de Chrome, veremos en las primeras opciones cómo queremos que el navegador se presente ante nosotros, en Iniciar Sesión / Al abrir el navegador… podemos marcar “Abrir todo como estaba antes de cerrar”, tal y como aparece en la foto. Esto puede variar ligeramente con la versión.

Pero a veces hay problemas…

Pero a veces podemos tener serios problemas cuando tienes muchas pestañas abiertas, se cierra la ventana por algún problema (o porque tuviste un accidente, que un error humano no lo podemos descartar) y cuando arrancamos de nuevo el navegador no se restauran las pestañas. Cuando ya no sabes ni qué tenías abierto pero que seguro que era interesante y tarde o temprano echarías en falta (y que no la encuentras en el historial porque tienes demasiadas cosas). Aquella pestaña que abriste hace meses y no le has hecho ni caso pero ahora se vuelve una gran pérdida en tu corazón.

Todavía no está todo perdido. ¡No hagas nada! ¡No toques nada!. Este navegador guarda una copia de la sesión anterior en los archivos de usuario. Para ello, dependiendo de tu sistema operativo encontrarás los archivos en un sitio u otro. Más o menos:

  • GNU/Linux: /home/usuario/.config/{chrome}/Default ({chrome} lo pongo entre llaves porque puede ser “chrome” / “chromium” o “google chrome”
  • Mac OS X: Users/usuario/Library/Application Support/Google/Chrome/Default
  • Windows 7, 8.1 y 10: C:\Users\\AppData\Local\Google\Chrome\User Data\Default

Allí encontramos algunos archivos:

  • Current Session
  • Current Tabs
  • Last Session
  • Last Tabs

Estos archivos están en formato binario, aunque las direcciones de las pestañas abiertas se pueden leer perfectamente, si tienes GNU/Linux o cualquier Unix, puedes utilizar strings para ver su contenido (seguro que para Windows encontramos también alguna herramienta):

strings Current\ Session
http://www.bodurov.com/JsonFormatter/
https://colorlib.com/polygon/metis/

Pero estos ficheros también podemos copiarlos fuera (por seguridad, ya lo veremos), o machacar Current Session con Last Session y Current Tabs con Last Tabs. Para asegurarnos de que todo va bien, es recomendable, antes de cerrar el navegador hacer una copia de seguridad de todos:

cp Current\ Session{,.backup}
cp Current\ Tabs{,.backup}
cp Last\ Session{,.backup}
cp Last\ Tabs{,.backup}

Ahora tendremos Current Session y Current Session.backup , Current Tabs y Current Tabs.backup y así con los demás. Ahora, cerramos el navegador, que seguramente reescriba los archivos (pero no las copias de seguridad que hemos hecho).
Ahora copiamos Last Session.backup en Last Session (y en Current Session también si queremos) y hacemos lo mismo con Last Tabs.backup:

cp Last\ Session.backup Current\ Session
cp Last\ Session.backup Last\ Session
cp Last\ Tabs.backup Current\ Tabs
cp Last\ Tabs.backup Last\ Tabs

Ahora podemos volver a abrir el navegador normalmente y si es necesario restaurar las pestañas. ¡Espero que las hayas podido recuperar!

Copias de seguridad periódicas de las pestañas

Si dejas abierto mucho tiempo el navegador y tienes largas sesiones de navegación que pueden durar incluso días. No estaría mal tener una copia de seguridad periódica de estas pestañas. Que se realice automáticamente cada cierto tiempo, para ello puedes hacer un cron con este script:

1
2
3
4
5
#!/bin/bash

cd /home/usuario/.config/chromium/Default/
tar cvjpf /home/usuario/Chromebackups/chrometabs_20170302_22_32_52.tar.bz2 "Current Session" "Current Tabs" "Last Session" "Last Tabs"
find -mtime +30 -exec rm {} +

Cambiando los directorios de usuario y de chrome y ejecutándolo un par de veces al día podemos tener por seguro que no perderemos muchas pestañas. Con el script anterior estaremos guardando un mes de pestañas en el tiempo (la última línea de find se encarga de borrar los que sean muy antiguos).

The post Cómo recuperar pestañas perdidas en Google Chrome appeared first on Poesía Binaria.

Las fuentes «STIX Two»

Este artículo es parte de la serie Recomendando fuentes tipográficas El proyecto STIX (Scientific and Technical Information eXchange) nació hace ya varios años como una colaboración entre American Mathematical Society (AMS), American Institute of Physics (AIP), American Physical Society (APS), American Chemical Society (ACS), Institute of Electrical and Electronic Engineers (IEEE) y Elsevier para satisfacer […]

Alpha Litebook tu portátil Linux como si estuvieras en Macbook

A día de hoy, todos sabemos ya que si Linux no está mucho más extendido es por la falta de integración de este sistema operativo en los ordenadores que nos venden en nuestro día a día. Normalmente si vamos a una tienda a comprar un ordenador de sobremesa o un portátil, no nos ofrecerán ninguno de los dos con Linux como sistema operativo integrado, a no ser que vayamos a una tienda

Lunes 13 de marzo de 2017

Gaspar Fernández

Gaspar Fernández
Poesía Binaria

Experimento: Creando un nuevo efecto de imagen para el secuenciador de vídeo de Blender (VSE) con código fuente


Lo que pongo aquí es solo un experimento. Como dije en mi anterior post, me encanta Blender para hacer montajes de vídeo y para mí, es el mejor editor de vídeo disponible para GNU/Linux. Aunque tiene un pequeño defecto, bueno, muy grande… apenas tiene efectos para los vídeos, por lo que si quieres algún efecto que no sea un crossfade, una corrección de color, o un blur, vas a tener que hacerlo de otra forma y eso implica exportar vídeo y luego importarlo cuando esté hecho. Con el gran inconveniente de que si el efecto no ha quedado exactamente como quieres, si de verdad te quedan ganas para modificarlo tienes que repetir el proceso.

Me gustan los efectos, y quiero hacer pruebas, porque no había mirado mucho el código fuente de Blender, me parece una bestia, tiene muchas cosas, y partes que se han quedado un poco viejas, como es el VSE (Video Sequence Editor), el módulo de Blender que más utilizo. Así que, ¿por qué no empezar a crear algunos efectos?

Construyendo Blender

Lo malo de todo esto, es que al contrario que con programas privativos, Blender no soporta plugins para efectos. Lo hizo en el pasado, pero por razones que no llego a comprender (supongo que relacionadas con el mantenimiento, con que nadie quiso hacerse cargo del módulo y con que tal vez les reportaban muchos fallos sobre efectos cuando el fallo no estaba en Blender, sino en el que realizaba el propio efecto). Lo malo, es que si queremos incluir un nuevo efecto en Blender, debemos recompilar nuestra versión de Blender. No tarda mucho, pero tiene algunas dependencias algo pesadas. Una vez que lo has hecho, las siguientes compilaciones no tardarán mucho, ya que sólo compila el código nuevo (lo que hacemos nosotros).

Bueno, he dicho que Blender no tiene API… ¡claro que tiene! Lo malo es que es una API en Python, y personalmente (que lo he probado), efectos que renderizan a 25fps hechos en C, van a 0.3fps hechos en Python. Es cierto que no he utilizado ninguna de las fantásticas bibliotecas de imagen digital disponibles para Python, pero de todas formas hay que hacer que el vídeo se exporte a Python, y sólo lo he conseguido hacer con alguna guarrada que me da vergüenza mencionar aquí…

Lo primero es decargarte el código fuente de la página principal o del git oficial de Blender (git://git.blender.org/blender.git). Si vas a compartir lo que haces con la comunidad, te recomiendo utilizar git para poder enviar parches y demás.

El caso es que si queremos compilar Blender, necesitamos un entorno de compilación GCC, y las siguientes bibliotecas con sus cabeceras para programación: python, numpy, libx11, libjpeg, libpng, boost, ffmpeg, libopencolorio, libilm, libopenexr y algunas más. Las encuentras todas en blender/build_files/build_environment/install_deps.sh

Antes de meterme con código

Si echas un vistazo por encima al código parece muchísimo, ¡ pero no es tanto ! Como es un programa tan grande, en muchos archivos, para que sepamos qué tenemos que tocar. Como no puedo decir la línea exacta ya que este programa se modifica a menudo he decidido poner unas cuantas líneas, o funciones completas a modo de referencia. Cuando lo que nos afecta es lo referente a CUSTOM_EFFECT.

¡Empezamos con la aventura!

Botón en la interfaz

Lo primero, es que desde la interfaz podamos añadir un nuevo efecto. Que cuando estemos en el secuenciador, pulsando Shift+A -> Effect aparezca nuestro efecto en el menú, para eso, tenemos que editar

Para eso, editamos el archivo source/blender/makesdna/DNA_sequence_types.h y añadimos una nueva constante con nuestro effecto. Mi efecto se llamará CUSTOMEFFECT, además, incrementamos SEQ_TYPE_MAX. En mi caso, la cosa queda más o menos así (cerca de la línea 500, en la versión 2.78c):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
enum {
    SEQ_TYPE_IMAGE       = 0,
    SEQ_TYPE_META        = 1,
    SEQ_TYPE_SCENE       = 2,
    SEQ_TYPE_MOVIE       = 3,
    SEQ_TYPE_SOUND_RAM   = 4,
    SEQ_TYPE_SOUND_HD    = 5,
    SEQ_TYPE_MOVIECLIP   = 6,
    SEQ_TYPE_MASK        = 7,

    SEQ_TYPE_EFFECT      = 8,
    SEQ_TYPE_CROSS       = 8,
    SEQ_TYPE_ADD         = 9,
    SEQ_TYPE_SUB         = 10,
    SEQ_TYPE_ALPHAOVER   = 11,
    SEQ_TYPE_ALPHAUNDER  = 12,
    SEQ_TYPE_GAMCROSS    = 13,
    SEQ_TYPE_MUL         = 14,
    SEQ_TYPE_OVERDROP    = 15,
    /* SEQ_TYPE_PLUGIN      = 24, */ /* Deprecated */
    SEQ_TYPE_WIPE        = 25,
    SEQ_TYPE_GLOW        = 26,
    SEQ_TYPE_TRANSFORM   = 27,
    SEQ_TYPE_COLOR       = 28,
    SEQ_TYPE_SPEED       = 29,
    SEQ_TYPE_MULTICAM    = 30,
    SEQ_TYPE_ADJUSTMENT  = 31,
    SEQ_TYPE_GAUSSIAN_BLUR = 40,
    SEQ_TYPE_TEXT = 41,
    SEQ_TYPE_CUSTOMEFFECT = 42,

    SEQ_TYPE_MAX  = 42
};

Nuestro efecto, tendrá el índice 42, aunque no nos importa mucho la posición que ocupe. Ahora vamos al archivo source/blender/editors/space_sequencer/sequencer_edit.c, metemos el mismo efecto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
EnumPropertyItem sequencer_prop_effect_types[] = {
    {SEQ_TYPE_CROSS, "CROSS", 0, "Crossfade", "Crossfade effect strip type"},
    {SEQ_TYPE_ADD, "ADD", 0, "Add", "Add effect strip type"},
    {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", "Subtract effect strip type"},
    {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", "Alpha Over effect strip type"},
    {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", "Alpha Under effect strip type"},
    {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", "Gamma Cross effect strip type"},
    {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", "Multiply effect strip type"},
    {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Alpha Over Drop", "Alpha Over Drop effect strip type"},
    {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", "Wipe effect strip type"},
    {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
    {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
    {SEQ_TYPE_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
    {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
    {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
    {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
    {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
    {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
    {SEQ_TYPE_CUSTOMEFFECT, "CUSTOMEFFECT", 0, "Custom Effect", "Create a strip with customized effect" },
    {0, NULL, 0, NULL, NULL}
};

Dentro de cada elemento del array tendremos:

  • Índice, para lo que cogemos un valor de nuestro enum de antes. Será de uso interno,
  • String clave, será una cadena en clave, que manejaremos desde Python para referirnos al efecto.
  • El 0 siguiente indica que no hay icono asociado, por ahora no tenemos iconos
  • Luego el nombre del efecto, para mostrarlo
  • Por último, la descripción del efecto

Ahora en el archivo source/blender/makesrna/intern/rna_sequencer_api.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
{
    StructRNA *srna;
    PropertyRNA *parm;
    FunctionRNA *func;

    static EnumPropertyItem seq_effect_items[] = {
        {SEQ_TYPE_CROSS, "CROSS", 0, "Cross", ""},
        {SEQ_TYPE_ADD, "ADD", 0, "Add", ""},
        {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", ""},
        {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", ""},
        {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", ""},
        {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", ""},
        {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", ""},
        {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Over Drop", ""},
        {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", ""},
        {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", ""},
        {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", ""},
        {SEQ_TYPE_COLOR, "COLOR", 0, "Color", ""},
        {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", ""},
        {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
        {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
        {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
        {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
        {SEQ_TYPE_CUSTOMEFFECT, "CUSTOM_EFFECT", 0, "Custom Effect", "" },
        {0, NULL, 0, NULL, NULL}
    };

Seguimos con la interfaz de Python. Para que el elemento aparezca en el menú debemos incluir lo siguiente en el archivo release/scripts/startup/bl_ui/space_sequencer.py (añadir la última línea, más o menos alrededor de la línea 380, blender 2.78c):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class SEQUENCER_MT_add_effect(Menu):
    bl_label = "Effect Strip..."

    def draw(self, context):
        layout = self.layout

        layout.operator_context = 'INVOKE_REGION_WIN'

        layout.operator("sequencer.effect_strip_add", text="Add").type = 'ADD'
        layout.operator("sequencer.effect_strip_add", text="Subtract").type = 'SUBTRACT'
        layout.operator("sequencer.effect_strip_add", text="Alpha Over").type = 'ALPHA_OVER'
        layout.operator("sequencer.effect_strip_add", text="Alpha Under").type = 'ALPHA_UNDER'
        layout.operator("sequencer.effect_strip_add", text="Cross").type = 'CROSS'
        layout.operator("sequencer.effect_strip_add", text="Gamma Cross").type = 'GAMMA_CROSS'
        layout.operator("sequencer.effect_strip_add", text="Gaussian Blur").type = 'GAUSSIAN_BLUR'
        layout.operator("sequencer.effect_strip_add", text="Multiply").type = 'MULTIPLY'
        layout.operator("sequencer.effect_strip_add", text="Over Drop").type = 'OVER_DROP'
        layout.operator("sequencer.effect_strip_add", text="Wipe").type = 'WIPE'
        layout.operator("sequencer.effect_strip_add", text="Glow").type = 'GLOW'
        layout.operator("sequencer.effect_strip_add", text="Text").type = 'TEXT'
        layout.operator("sequencer.effect_strip_add", text="Transform").type = 'TRANSFORM'
        layout.operator("sequencer.effect_strip_add", text="Color").type = 'COLOR'
        layout.operator("sequencer.effect_strip_add", text="Speed Control").type = 'SPEED'
        layout.operator("sequencer.effect_strip_add", text="Multicam Selector").type = 'MULTICAM'
        layout.operator("sequencer.effect_strip_add", text="Adjustment Layer").type = 'ADJUSTMENT'
        layout.operator("sequencer.effect_strip_add", text="Custom Effect").type = 'CUSTOM_EFFECT'

Ahora definimos el color del elemento una vez lo pongamos en la línea de tiempo. Para ello en source/blender/editors/space_sequencer/sequencer_draw.c vamos a la función color3ubv_from_seq() donde, dentro del case, dejamos algo como esto (es aproximado, podemos definirle el color si queremos, pero yo me he basado en el color de otros elementos parecidos):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
        /* effects */
        case SEQ_TYPE_TRANSFORM:
        case SEQ_TYPE_SPEED:
        case SEQ_TYPE_ADD:
        case SEQ_TYPE_SUB:
        case SEQ_TYPE_MUL:
        case SEQ_TYPE_ALPHAOVER:
        case SEQ_TYPE_ALPHAUNDER:
        case SEQ_TYPE_OVERDROP:
        case SEQ_TYPE_GLOW:
        case SEQ_TYPE_MULTICAM:
        case SEQ_TYPE_ADJUSTMENT:
        case SEQ_TYPE_GAUSSIAN_BLUR:
        case SEQ_TYPE_CUSTOMEFFECT:
            UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);

            /* slightly offset hue to distinguish different effects */
            if      (seq->type == SEQ_TYPE_ADD)           rgb_byte_set_hue_float_offset(col, 0.04);
            else if (seq->type == SEQ_TYPE_SUB)           rgb_byte_set_hue_float_offset(col, 0.08);
            else if (seq->type == SEQ_TYPE_MUL)           rgb_byte_set_hue_float_offset(col, 0.12);
            else if (seq->type == SEQ_TYPE_ALPHAOVER)     rgb_byte_set_hue_float_offset(col, 0.16);
            else if (seq->type == SEQ_TYPE_ALPHAUNDER)    rgb_byte_set_hue_float_offset(col, 0.20);
            else if (seq->type == SEQ_TYPE_OVERDROP)      rgb_byte_set_hue_float_offset(col, 0.24);
            else if (seq->type == SEQ_TYPE_GLOW)          rgb_byte_set_hue_float_offset(col, 0.28);
            else if (seq->type == SEQ_TYPE_TRANSFORM)     rgb_byte_set_hue_float_offset(col, 0.36);
            else if (seq->type == SEQ_TYPE_MULTICAM)      rgb_byte_set_hue_float_offset(col, 0.32);
            else if (seq->type == SEQ_TYPE_ADJUSTMENT)    rgb_byte_set_hue_float_offset(col, 0.40);
            else if (seq->type == SEQ_TYPE_GAUSSIAN_BLUR) rgb_byte_set_hue_float_offset(col, 0.42);
            else if (seq->type == SEQ_TYPE_CUSTOMEFFECT)  rgb_byte_set_hue_float_offset(col, 0.52);
            break;

Si compilamos y ejecutamos Blender, seguramente nuestro efecto aparezca y lo podremos añadir, pero no hará nada, sólo soltar errores por la consola.

Definiendo algunas propiedades

Debemos definir antes de continuar algunas propiedades básicas del strip. En source/blender/makesrna/intern/rna_sequencer.c haremos varias modificaciones. Primero, en la función rna_def_sequence() (alrededor de la línea 1380), volvemos a meter nuestro efecto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
static void rna_def_sequence(BlenderRNA *brna)
{
    StructRNA *srna;
    PropertyRNA *prop;

    static const EnumPropertyItem seq_type_items[] = {
        {SEQ_TYPE_IMAGE, "IMAGE", 0, "Image", ""},
        {SEQ_TYPE_META, "META", 0, "Meta", ""},
        {SEQ_TYPE_SCENE, "SCENE", 0, "Scene", ""},
        {SEQ_TYPE_MOVIE, "MOVIE", 0, "Movie", ""},
        {SEQ_TYPE_MOVIECLIP, "MOVIECLIP", 0, "Clip", ""},
        {SEQ_TYPE_MASK, "MASK", 0, "Mask", ""},
        {SEQ_TYPE_SOUND_RAM, "SOUND", 0, "Sound", ""},
        {SEQ_TYPE_CROSS, "CROSS", 0, "Cross", ""},
        {SEQ_TYPE_ADD, "ADD", 0, "Add", ""},
        {SEQ_TYPE_SUB, "SUBTRACT", 0, "Subtract", ""},
        {SEQ_TYPE_ALPHAOVER, "ALPHA_OVER", 0, "Alpha Over", ""},
        {SEQ_TYPE_ALPHAUNDER, "ALPHA_UNDER", 0, "Alpha Under", ""},
        {SEQ_TYPE_GAMCROSS, "GAMMA_CROSS", 0, "Gamma Cross", ""},
        {SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", ""},
        {SEQ_TYPE_OVERDROP, "OVER_DROP", 0, "Over Drop", ""},
        {SEQ_TYPE_WIPE, "WIPE", 0, "Wipe", ""},
        {SEQ_TYPE_GLOW, "GLOW", 0, "Glow", ""},
        {SEQ_TYPE_TRANSFORM, "TRANSFORM", 0, "Transform", ""},
        {SEQ_TYPE_COLOR, "COLOR", 0, "Color", ""},
        {SEQ_TYPE_SPEED, "SPEED", 0, "Speed", ""},
        {SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
        {SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
        {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
        {SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
        {SEQ_TYPE_CUSTOMEFFECT, "CUSTOM_EFFECT", 0, "Custom Effect", "" },             
        {0, NULL, 0, NULL, NULL}
    };

Luego en la línea 2390 más o menos modificamos la estructura def_effects añadiendo la definición de nuestro nuevo efecto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
static EffectInfo def_effects[] = {
    {"AddSequence", "Add Sequence", "Add Sequence", NULL, 2},
    {"AdjustmentSequence", "Adjustment Layer Sequence",
     "Sequence strip to perform filter adjustments to layers below", rna_def_input, 0},
    {"AlphaOverSequence", "Alpha Over Sequence", "Alpha Over Sequence", NULL, 2},
    {"AlphaUnderSequence", "Alpha Under Sequence", "Alpha Under Sequence", NULL, 2},
    {"ColorSequence", "Color Sequence",
     "Sequence strip creating an image filled with a single color", rna_def_solid_color, 0},
    {"CrossSequence", "Cross Sequence", "Cross Sequence", NULL, 2},
    {"GammaCrossSequence", "Gamma Cross Sequence", "Gamma Cross Sequence", NULL, 2},
    {"GlowSequence", "Glow Sequence", "Sequence strip creating a glow effect", rna_def_glow, 1},
    {"MulticamSequence", "Multicam Select Sequence", "Sequence strip to perform multicam editing",
     rna_def_multicam, 0},
    {"MultiplySequence", "Multiply Sequence", "Multiply Sequence", NULL, 2},
    {"OverDropSequence", "Over Drop Sequence", "Over Drop Sequence", NULL, 2},
    {"SpeedControlSequence", "SpeedControl Sequence",
     "Sequence strip to control the speed of other strips", rna_def_speed_control, 1},
    {"SubtractSequence", "Subtract Sequence", "Subtract Sequence", NULL, 2},
    {"TransformSequence", "Transform Sequence",
     "Sequence strip applying affine transformations to other strips", rna_def_transform, 1},
    {"WipeSequence", "Wipe Sequence", "Sequence strip creating a wipe transition",
     rna_def_wipe, 2},
    {"GaussianBlurSequence", "Gaussian Blur Sequence", "Sequence strip creating a gaussian blur",
     rna_def_gaussian_blur, 1},
    {"TextSequence", "Text Sequence", "Sequence strip creating text",
     rna_def_text, 0},
    {"CustomEffectSequence", "Custom Effect Sequence", "Sequence strip creating custom effects",
     rna_def_custom_effect, 1},
    {"", "", "", NULL, 0}
};

Donde, el 1 que acompaña la declaración del efecto es el número de entradas que necesitamos. Al aplicarse sobre otro strip, necesitamos un 1 aquí. Si fuera un generador, sería 0 y una transición tendría 2.

Ahora, junto con los demás efectos (línea 2100 más o menos), creamos la función rna_def_customeffect donde definiremos los parámetros que se podrán tocar de nuestro efecto, que luego tendremos que vincular con Python, que no se nos olvide:

1
2
3
4
5
6
7
8
9
10
static void rna_def_custom_effect(StructRNA *srna)
{
    PropertyRNA *prop;

    RNA_def_struct_sdna_from(srna, "CustomEffectVars", "effectdata");
    prop = RNA_def_property(srna, "property", PROP_FLOAT, PROP_UNSIGNED);
    RNA_def_property_ui_text(prop, "One property", "One float prop for practising");
    RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1);
    RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}

Y añadimos nuestro efecto a la función rna_sequence_refine():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
static StructRNA *rna_Sequence_refine(struct PointerRNA *ptr)
{
    Sequence *seq = (Sequence *)ptr->data;

    switch (seq->type) {
        case SEQ_TYPE_IMAGE:
            return &RNA_ImageSequence;
        case SEQ_TYPE_META:
            return &RNA_MetaSequence;
        case SEQ_TYPE_SCENE:
            return &RNA_SceneSequence;
        case SEQ_TYPE_MOVIE:
            return &RNA_MovieSequence;
        case SEQ_TYPE_MOVIECLIP:
            return &RNA_MovieClipSequence;
        case SEQ_TYPE_MASK:
            return &RNA_MaskSequence;
        case SEQ_TYPE_SOUND_RAM:
            return &RNA_SoundSequence;
        case SEQ_TYPE_CROSS:
            return &RNA_CrossSequence;
        case SEQ_TYPE_ADD:
            return &RNA_AddSequence;
        case SEQ_TYPE_SUB:
            return &RNA_SubtractSequence;
        case SEQ_TYPE_ALPHAOVER:
            return &RNA_AlphaOverSequence;
        case SEQ_TYPE_ALPHAUNDER:
            return &RNA_AlphaUnderSequence;
        case SEQ_TYPE_GAMCROSS:
            return &RNA_GammaCrossSequence;
        case SEQ_TYPE_MUL:
            return &RNA_MultiplySequence;
        case SEQ_TYPE_OVERDROP:
            return &RNA_OverDropSequence;
        case SEQ_TYPE_MULTICAM:
            return &RNA_MulticamSequence;
        case SEQ_TYPE_ADJUSTMENT:
            return &RNA_AdjustmentSequence;
        case SEQ_TYPE_WIPE:
            return &RNA_WipeSequence;
        case SEQ_TYPE_GLOW:
            return &RNA_GlowSequence;
        case SEQ_TYPE_TRANSFORM:
            return &RNA_TransformSequence;
        case SEQ_TYPE_COLOR:
            return &RNA_ColorSequence;
        case SEQ_TYPE_SPEED:
            return &RNA_SpeedControlSequence;
        case SEQ_TYPE_GAUSSIAN_BLUR:
            return &RNA_GaussianBlurSequence;
        case SEQ_TYPE_TEXT:
            return &RNA_TextSequence;
        case SEQ_TYPE_CUSTOM_EFFECT:
            return &RNA_CustomEffectSequence;
        default:
            return &RNA_Sequence;
    }
}

Por último en source/blender/makesrna/RNA_access.h metemos esta línea, más o menos en la 280:

1
extern StructRNA RNA_CustomEffectSequence;

Insertamos las propiedades de nuestro efecto

Por ahora sólo estoy metiendo una, y no hace nada, sólo estar ahí, pero me sirve como plantilla para futuros efectos. Antes de que se nos olvide, vamos a añadirla desde la interfaz de Python. En el archivo en el archivo release/scripts/startup/bl_ui/space_sequencer.py en la clase CLASS_PT_EFFECT(), al final del todo añadimos nuestro efecto:

1
2
3
4
5
6
7
8
9
10
11
12
         col = layout.column(align=True)
        if strip.type == 'SPEED':
            col.prop(strip, "multiply_speed")
        elif strip.type in {'CROSS', 'GAMMA_CROSS', 'WIPE', 'ALPHA_OVER', 'ALPHA_UNDER', 'OVER_DROP'}:
            col.prop(strip, "use_default_fade", "Default fade")
            if not strip.use_default_fade:
                col.prop(strip, "effect_fader", text="Effect fader")
        elif strip.type == 'GAUSSIAN_BLUR':
            col.prop(strip, "size_x")
            col.prop(strip, "size_y")
        elif strip.type == 'CUSTOM_EFFECT':
            col.prop(strip, 'property')

Ahora declaramos las propiedades de nuestro efecto. Para ello en el archivo source/blender/makesdna/DNA_sequence_types.h insertamos lo sigueinte (cerca de la 290, junto con los demás efectos, ya los veréis):

1
2
3
typedef struct CustomEffectVars {
    float property;
} CustomEffectVars;

Mi propiedad se llamaba property, porque soy muy original, pero aquí pondremos las que necesitemos. Podremos poner arrays de char para cadenas de caracteres, char, short para flags, enteros y float, por ejemplo, los colores van en float. Podríamos poner otros tipos de variable, pero no he probado… no soy tan valiente.

Para que las propiedades de nuestro efecto se guarden cuando salvamos el archivo .blend hacemos, editamos source/blender/blenloader/intern/writefile.c añadiendo la estructura de nuestro efecto, alrededor de la límea 2660:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
            SEQ_BEGIN(ed, seq)
            {
                if (seq->strip && seq->strip->done == 0) {
                    /* write strip with 'done' at 0 because readfile */

                    if (seq->effectdata) {
                        switch (seq->type) {
                            case SEQ_TYPE_COLOR:
                                writestruct(wd, DATA, SolidColorVars, 1, seq->effectdata);
                                break;
                            case SEQ_TYPE_SPEED:
                                writestruct(wd, DATA, SpeedControlVars, 1, seq->effectdata);
                                break;
                            case SEQ_TYPE_WIPE:
                                writestruct(wd, DATA, WipeVars, 1, seq->effectdata);
                                break;
                            case SEQ_TYPE_GLOW:
                                writestruct(wd, DATA, GlowVars, 1, seq->effectdata);
                                break;
                            case SEQ_TYPE_TRANSFORM:
                                writestruct(wd, DATA, TransformVars, 1, seq->effectdata);
                                break;
                            case SEQ_TYPE_GAUSSIAN_BLUR:
                                writestruct(wd, DATA, GaussianBlurVars, 1, seq->effectdata);
                                break;
                            case SEQ_TYPE_CUSTOMEFFECT:
                                writestruct(wd, DATA, CustomEffectVars, 1, seq->effectdata);
                                break;
                            case SEQ_TYPE_TEXT:
                                writestruct(wd, DATA, TextVars, 1, seq->effectdata);
                                break;
                        }
                    }

                    writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format);

Definiciones de nuestro efecto

Ya va quedando menos, tenemos esto casi configurado, sólo quedan algunos callbacks con las llamadas que hacen los propios filtros, vamos, ahora es cuando nuestro filtro hace algo, aunque es necesario definirlo para que el programa no explote:

En el archivo source/blender/blenkernel/intern/seqeffects.c encontramos el código de estos efectos. Lo primero será introducir las definiciones de nuestro efecto en la función get_sequence_effect_impl() en la línea 3315 o así, buscamos los efectos del switch y ponemos el nuestro al final:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
        case SEQ_TYPE_ADJUSTMENT:
            rval.supports_mask = true;
            rval.num_inputs = num_inputs_adjustment;
            rval.early_out = early_out_adjustment;
            rval.execute = do_adjustment;
            break;
        case SEQ_TYPE_GAUSSIAN_BLUR:
            rval.init = init_gaussian_blur_effect;
            rval.num_inputs = num_inputs_gaussian_blur;
            rval.free = free_gaussian_blur_effect;
            rval.copy = copy_gaussian_blur_effect;
            rval.early_out = early_out_gaussian_blur;
            rval.execute = do_gaussian_blur_effect;
            break;
        case SEQ_TYPE_TEXT:
            rval.num_inputs = num_inputs_text;
            rval.init = init_text_effect;
            rval.free = free_effect_default;
            rval.copy = copy_effect_default;
            rval.early_out = early_out_text;
            rval.execute = do_text_effect;
            break;
        case SEQ_TYPE_CUSTOMEFFECT:
            rval.init = init_custom_effect_effect;
            rval.num_inputs = num_inputs_custom_effect;
            rval.free = free_custom_effect_effect;
            rval.copy = copy_custom_effect_effect;
            rval.early_out = early_out_custom_effect;
            rval.execute = do_custom_effect_effect;
            break;

Aquí definiremos:

  • rval.init : función que inicializa nuestro efecto
  • rval.num_inputs : número de strips de entrada que necesita nuestro strip. Los efectos necesitan estas sobre un strip, las transiciones sobre dos, los generadores no necesitan strips.
  • rval.free : Qué hacemos cuando se quita nuestro efecto (para liberar memoria)
  • rval.copy : Qué hacer cuando copian nuestro efecto.
  • rval.early_out : A veces, podemos saber si es necesario o no aplicar el efecto antes de ponernos a procesar. Aquí veremos si procesamos, si devolvemos el valor de la entrada, o no devolvemos nada
  • rval.execute : NUESTRO EFECTO !!!
  • rval.supports_mask : ¿Soporta máscaras? (es un booleano, no un callback
  • rval.load : Qué hacer cuando se acaba de cargar el efecto?
  • rval.init_execution : Este callback se ejecutará antes de hacer el render de nuestro efecto.
  • rva.multithreaded : El efecto soporta threads. Y en lugar de llamar a rval.execute se llamará a rval.execute_slice, por lo que si hacemos nuestro efecto multihilo tendremos que hacerlo independiente de las líneas de origen y fin que nos pasen (Blender ya se encarga de crear hilos y de todo lo demás, nosotros sólo tenemos que definir lo que hace cada uno).

Encontraremos toda la información en source/blender/blenkernel/BKE_sequencer.h

Como todo lo que hemos puesto son callbacks, tendremos que definirlos, voy a poner todo el código seguido, pero si queréis tenerlo ordenado buscad funciones parecidas de otros efectos y poned el vuestro por ahí:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*********************** Custom Effect *************************/
static void init_custom_effect_effect(Sequence *seq)
{
    if (seq->effectdata)
        MEM_freeN(seq->effectdata);

    seq->effectdata = MEM_callocN(sizeof(CustomEffectVars), "customeffectvars");
}

static int num_inputs_custom_effect(void)
{
    return 1;
}

static void free_custom_effect_effect(Sequence *seq)
{
    if (seq->effectdata)
        MEM_freeN(seq->effectdata);

    seq->effectdata = NULL;
}

static void copy_custom_effect_effect(Sequence *dst, Sequence *src)
{
    dst->effectdata = MEM_dupallocN(src->effectdata);
}

static int early_out_custom_effect(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
{

    /* source/blender/blenkernel/BKE_sequencer.h */
    /* #define EARLY_NO_INPUT      -1 */
    /* #define EARLY_DO_EFFECT     0 */
    /* #define EARLY_USE_INPUT_1   1 */
    /* #define EARLY_USE_INPUT_2   2 */
   
    CustomEffectVars *UNUSED(data) = seq->effectdata;
    /* I will always do my effect */
    /* if (data->property == 0) { */
    /*  return EARLY_USE_INPUT_1; */
    /* } */
    return EARLY_DO_EFFECT;
}

// NUESTRO EFECTO !!!!!!!!!!!!!
static ImBuf *do_custom_effect_effect(const SeqRenderData *context, Sequence *seq, float UNUSED(cfra), float UNUSED(facf0), float UNUSED(facf1),
                                     ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
{
    ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);

    CustomEffectVars *cv = (CustomEffectVars *)seq->effectdata;

    unsigned char *rect, *orig;
    int x= context->rectx;
    int y= context->recty;
    float prop = cv->property;

    if (out->rect) {
        orig = (unsigned char *)ibuf1->rect;
        rect = (unsigned char *)out->rect;
        while (y--) {
            x = context->rectx;
            while (x--) {
                rect[0] = (orig[0]+ prop*orig[1])/(1+prop);
                rect[1] = (orig[1]+ prop*orig[2])/(1+prop);
                rect[2] = (orig[2]+ prop*orig[1])/(1+prop);
                rect[3] = 220;
                rect += 4;
                orig += 4;
            }
        }
    }
    else if (out->rect_float) {
        orig = (unsigned char *)ibuf1->rect_float;
        rect = (unsigned char *)out->rect_float;
        while (y--) {
            x = context->rectx;
            while (x--) {
                rect[0] = (orig[0]+ prop*orig[1])/(1+prop);
                rect[1] = (orig[1]+ prop*orig[2])/(1+prop);
                rect[2] = (orig[2]+ prop*orig[1])/(1+prop);
                rect[3] = 0.5;
                rect += 4;
                orig += 4;
               
            }
        }
    }
    return out;
}

¡Y listo! Si compilamos Blender ya tenemos nuestro efecto.

En la función do_custom_effect_effect(), tenemos los siguientes parámetros para la entrada:

  • const SeqRenderData *context : El contexto, aquí tenemos acceso a muchísimas cosas, demasiado para enumerarlo aquí, pero accedemos a la estructura Main que contiene casi todo, podemos acceder a la escena, elementos guardados y miles de cosas más.
  • Sequence *seq : Toda la información del strip actual
  • float cfra: Fotograma actual, puede tener un error de +-0.5 frames.
  • float facf0: Cuando estamos operando con contenido entrelazado y estamos animando un efecto, qué porcentaje de efecto recae sobre el campo 0?
  • float facf1: lo mismo pero para el campo 1.
  • ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3: Son las imágenes asociadas al efecto, dependiendo del efecto, habrá varias imágenes implicadas en él.

Y… como extra, si no estamos utilizando una variable, pero la queremos dejar ahí, para que el compilador no se queje podemos envolverla con la macro UNUSED()

La comunidad Blender

En https://developer.blender.org/ encontramos un sistema en el que se ponen en común bugs y pequeñas características (si quieres colaborar en algo grande, tienes que contactar con ellos). Y actualmente el secuenciador lo tienen un poco abandonado, de todas formas, hay una parte importante de la comunidad que sigue ahí, enviando parches y mejoras.

The post Experimento: Creando un nuevo efecto de imagen para el secuenciador de vídeo de Blender (VSE) con código fuente appeared first on Poesía Binaria.

Guillermo Garron

Guillermo Garron
GNU Linux

{{ post.title }}

{{ post.content | xml_escape }}
Juanje Ojeda

Juanje Ojeda
Nada de particular

Cambio de profesión

El 8 de noviembre del año pasado cumplí 38 años y me siento mejor de lo que me sentía con 20, así que estoy muy contento :-)

Además, celebré mi cumpleaños regalándome un cambio de profesión. He vuelto a una de mis 2 grandes pasiones, el cuerpo humano y la educación física.

Después de estar un tiempo reciclándome (hace 15 años que estudié Ciencias de la Actividad Física y del Deporte y han cambiado muchas cosas desde entonces...) y dedicándome a mejorar mi salud, me decidí a tirarme a la piscina y dejar los ordenadores para dedicarme a las personas.

Hacía mucho que no estaba tan motivado con algo :-)

Ya llevo casi un año metido en esa aventura y cada día más motivado. Aprendo mucho cada día e intento compartir ese conocimiento en mi nuevo blog profesional:
Juanje Ojeda

La mayoría de mis clientes son personas con mi antiguo perfil. Personas sedentarias que trabajan todo el día con ordenadores y que les cuesta encontrar tiempo y fuerza de voluntad para tomar las riendas de su salud.
Incluso he empezado a ayudar de forma remota a antiguos compañeros de trabajo y gente del gremio. Es lo bueno de Internet y las nuevas tecnologías :-P
Entrenamiento online

Espero seguir así de contento e ilusionado con esta nueva etapa durante mucho tiempo. Pero si no es así, al menos lo intenté y lo disfrutaré mientras dure :-)
Juanje Ojeda

Juanje Ojeda
Nada de particular

Nace ASOLIF. Una apuesta de futuro y colaboración

Copio el anuncio que hizo el amigo Agustín sobre el nacimiento de la asociación de empresas de software libre federadadas (ASOLIF) en la lista de socios de Hispalinux, que el lo explica mejor de lo que lo haría yo ;-)

Ayer precisamente vi a Gonzalo (Fotón), que venía de la firma de la misma y que venía muy animado y esperanzado con el proyecto. Más tarde se nos unió Victor Fernandez (gerente, socio y amigo de Emergya) y tuvimos una cena muy agradable con tapitas y cervezas en la que hablamos de ASOLIF, los diferentes modelos de negocio y enfoques de las empresas que producen y consumen software libre, y más temas relacionados y muy interesantes.
Fué un debate intenso, interesante y muy constructivo. Que es lo más importante. Exponer opiniones, argumentarlas y sacar lo mejor de cada una de ellas para mejorar y avanzar.

Bueno, no me enrollo más, les dejo el mensaje de Agustín, para que aquellos que no están en la lista, puedan enterarse de esta interesante y prometedora noticia.

-----Original Message-----
From: Agustín Benito Bethencourt

Date: Fri, 29 Feb 2008 16:25:46
To:socios EN hispalinux PUNTO es
Subject: [Socios-HispaLinux] nace asolif


Hola a todos,

me congratulo en comentar que hoy nace oficialmente ASOLIF, la asociación de
empresas de software libre federadas. Forman parte de ella inicialmente las
asociaciones regionales ESLIC (Canarias), ESLE (País Vasco) y CatPL
(Cataluña). La inauguración ha sido auspiciada por el CENATIC esta mañana.

Como miembro fundador (y de la actual Junta Directiva) de ESLIC, quiero
decirles que se trata de una iniciativa que ha costado un año llevar adelante
y que esperamos todos sea la chispa que nos permita a las empresas de
software libre disponer de un foro efectivo, donde poder conectarnos formando
una red de empresas que den soporte e impulsen el software libre a nivel
empresarial en nuestro pais. El software libre SI tiene quien lo soporte en
España.

Sé que hay muchos empresarios que pertenecen a Hispalinux y sé que la propia
asociación ha servidor muchas veces como vehículo de nuestras demandas e
inquietudes. Sólo espero que la colaboración entre Hispalinux y la nueva
Federación sea lo más fructífera posible. Nos necesitamos.

Si eres profesional o empresa, permíteme invitarte a moverte para formar una
asociación de empresas en tu Comunidad (hay algunas que lo están haciendo ya)
y pasar a formar parte de esta Federación. Debemos estar todos para que el
esfuerzo que hemos puesto en esto tenga sentido.

Saludos
--
Agustín Benito Bethencourt
Grupo CPD
abenito @ grupocpd.com
http://www.grupocpd.com
http://agustin.ejerciciosresueltos.com
http://www.toscalix.blogspot.com
_______________________________________________


IMPORTANTE: Los mensajes y opiniones que aparecen en esta lista son de la exclusiva responsabilidad de sus autores. No son atribuibles a Hispalinux ni a los gestores de la lista.
-----Original Message-----


A ver qué tal va este asunto. ¡Mucha suerte a todos! :-)



Juanje Ojeda

Juanje Ojeda
Nada de particular

Sobre la BlackBerry desde la BlackBerry (III)

Lo prometido es deuda, aquí tienen el listado de mis aplicaciones favoritas para la BlackBerry.

He buscado cosas libres, pero es complicado encontrarlas. En su defecto he encontrado aplicaciones gratuitas. No es lo mismo, pero siendo prácticos, me sirven.

Listaré las aplicaciones por funcionalidad:


Y algunas aplicaciones vía web o wap:

¿Qué es lo que más uso yo? Pues después de probar mucho y pasarseme algo de la novedad lo que realmente uso y me resulta bastante práctico es:
(ordenado por frecuencia de uso)


Por cierto, el Opera Mini está muy bien, pero tiene algunas cosas que no terminan de gustarme y no se integra bien con la Perla. El trackball no funciona como esperas y no te deja ir a un enlace directamente con él, tienes que dar dos pasos...
Menú -> Selecionar

Usabilidad: -10 :-(

Una pena porque en cuanto a rapidez de carga y formateo de páginas es genial.

Otro día una escribo una revisión a algunas de estás webs o aplicaciones que uso. Pero espero que esta pequeña relación de enlaces le resulte útil a más de uno. A mí tener algo así me hubiera ahorrado bastante tiempo...
Otra cosa de la que me gustaría hablar es sobre el PIN. Si alguien tiene información útil e interesante sobre el tema, que lo diga, así me documento mejor del tema ;-)


Sábado 11 de marzo de 2017

Pedro L. Lucas

Pedro L. Lucas
Cartas de Linux

La potencia de los recortes de código (snipples)

Un recorte de código es una pequeña plantilla que podemos reutilizar dentro de un editor de textos. Esta plantilla se pega, en el texto que se está editando, al escribir una palabra y pulsar el tabulador. En el siguiente ejemplo, al escribir html5 y pulsar tabulador, se pega la plantilla correspondiente:

Una vez pegada la plantilla se puede ver que al escribir en ciertas partes del texto, el texto se copia a otros lugares de forma automática. Pulsando tabulador, se van saltando a los diferentes campos de la plantilla.

Los recortes de código (snipples) están presentes en numerosos editores de texto como pueden ser Gedit, Vim, Sublime Text, Kate,…

Por ser Gedit un editor de textos muy extendido, en este artículo se va a mostrar cómo se activan y cómo se crean en él los recortes de código.

Activando los recortes en Gedit

Para activar los recortes de código se debe ir al menú “Editar/Preferencias” y en la pestaña “Complementos” activar “Recortes”:

También suele ser práctico activar el “Completado de palabras”.

Viendo los recortes disponibles

En el menú “Herramientas/Manage snipples” se pueden ver los recortes disponibles y la palabra que los dispara:

Como se puede ver en la imagen, para los archivos html se tienen numerosos recortes. En la parte izquierda de la ventana se pueden ver los recortes disponibles y en negrita la palabra que hay que escribir para activarlos. Por ejemplo, si se escribe html5 y se pulsa tabulador, se sustituirá por el texto, la plantilla, que aparece a la derecha. Más adelante nos meteremos en la forma de crear las plantillas.

Usando los recortes

Ya se han localizado los recortes disponibles. Sólo hay que escribir su disparador y pulsar tabulador, pero seguramente que si intentamos usarlos, no funcionen. Cada recorte sólo funciona para el tipo de archivo en el que se haya definido. Por ejemplo, los recortes de HTML sólo funcionarán si el archivo que se está editando se ha almacenado con la extensión html. Los recortes de C++ sólo funcionarán para los archivos con extensión “cpp”.

También podemos forzar el tipo de archivo seleccionándolo en la parte inferior del navegador:

Creando nuestras plantillas

Para crear una plantilla sólo hay que ir al menú “Herramientas/Manage snipples”, seleccionar en la parte izquierda el tipo de archivo para el que se desea crear el disparador y hacer clic sobre el símbolo “+” para añadirlo:

Le pondremos un nombre y en la parte inferior-derecha se escribe el disparador que deseamos que se ejecute. Ahora en la parte superior derecha escribimos el texto que se desea que se introduzca.

Por ejemplo, si se crea el disparador “hola” y en la parte superior derecha se escribe el texto “Hola mundo”, al escribir “hola” y pulsar el tabulador, se escribirá “Hola mundo”.

Pero lo interesante de las plantillas son los campos. Para definir los diferentes campos se usará $1, $2, $3,… una vez insertada la plantilla, al ir pulsando tabulador, el cursor irá saltando a las posiciones marcadas por $1, $2, $3,… Por ejemplo, se crea la plantilla:

Nombre: $1
Primer Apellido: $2
Segundo Apellido: $3
$0

Al insertarla el cursor aparecerá en la posición $1, allí escribimos el dato correspondiente. Si se vuelve a pulsar tabulador, saltará a la posición $2, rellenamos el primer apellido. Si se vuelve a pulsar tabulador, saltará a $3, rellenamos el segundo apellido. Si se pulsa tabulador una vez más, como ya no hay más posiciones a las que saltar, la plantilla se considerará finalizada y saltará a la posición indicada por $0.

Es llamativo que $0 sea la posición final.

Nos fijamos ahora en la siguiente plantilla:

Nombre: $1
Primer Apellido: $2
Segundo Apellido: $3
Nombre completo: $2 $3, $1
$0

Se puede ver que la posición $1 aparece repetida dos veces, eso significa que cuando se rellene el nombre, copiará dicho nombre en el segundo $1. De forma idéntica con $2 y $3:

A veces interesa que ciertos campos ya aparezcan rellenos con algún texto por defecto, para ello se usa la siguiente notación:

${número:Texto por defecto}

Por ejemplo:

${1:Ejemplo de texto}

En el ejemplo que se estaba desarrollando, se puede añadir un último campo, Teléfono, que por defecto muestre el texto “No disponible”:

Nombre: $1
Primer Apellido: $2
Segundo Apellido: $3
Teléfono: ${4:No disponible}
Nombre completo: $2 $3, $1
$0

Un último apunte

Los recortes de código están disponibles en numerosos editores de texto y suelen usar una sintaxis parecida para definir las plantillas, por lo que, en principio, será fácil trasladarlas de unos editores a otros.

El uso de recortes de código hace que la tarea de escribir un texto pueda ser más ágil en el caso de repetir algún cierto patrón de texto. A la hora de programar una página web, un código en C, o algo similar, los recortes de texto disminuyen los errores y ahorran tiempo.

Que los disfrutéis.


Viernes 10 de marzo de 2017

BlogDRAKE: Humor: La comunidad en estos momentos 2
José María Morales Vázquez

José María Morales Vázquez
tecnología – Un lugar en el mundo…

Chuletillas (y XXXXVII) – Instalar un programa de debian Stretch mientras que usas debian stable (Jessie)

chuletaSi quieres instalar un determinado programa (y sus dependencias obligatorias) incluido en la próxima versión de Debian (Stretch) mientras continuas usando la versión stable (Jessie) puedes hacerlo de la siguiente forma:

En primer lugar edita tu fichero sources.list (en el directorio /etc/apt) e incluye al final las direcciones de los repositorios de Stretch pero sin eliminar ni modificar los que ya usas de Jessie. Por ejemplo así:

# Repositorios de Jessie
deb http://http.debian.net/debian/ jessie main contrib non-free
deb-src http://http.debian.net/debian/ jessie main contrib non-free
deb http://security.debian.org/ jessie/updates main contrib non-free
deb-src http://security.debian.org/ jessie/updates main contrib non-free

# Updates de Jessie, antes conocidos como 'volatile'
deb http://http.debian.net/debian/ jessie-updates main contrib non-free
deb-src http://http.debian.net/debian/ jessie-updates main contrib non-free

# Backports de Jessie
deb http://http.debian.net/debian jessie-backports main contrib non-free

#Repositorios de Stretch
deb http://http.debian.net/debian/ stretch main contrib non-free
deb-src http://http.debian.net/debian/ stretch main contrib non-free
deb http://security.debian.org/ stretch/updates main contrib non-free
deb-src http://security.debian.org/ stretch/updates main contrib non-free

# Updates de Stretch
deb http://http.debian.net/debian/ stretch-updates main contrib non-free
deb-src http://http.debian.net/debian/ stretch-updates main contrib non-free

A continuación creamos un fichero llamado stretch en el directorio /etc/apt/preferences.d y escribimos en el lo siguiente:

Package: *
Pin: release n=jessie
Pin-Priority: 900

Package: *
Pin: release n=stretch
Pin-Priority: 100

Con esto estamos modificando la prioridad con la que Debian actualizará nuestros paquetes. Por defecto instala siempre la versión más moderna de todas las que tenga disponibles en sus repositorios. Con este fichero le dará preferencia a cualquier paquete de jessie frente a uno de stretch aunque tenga una versión menor. Es decir, mantendremos nuestro sistema con las versiones de jessie salvo que un paquete no exista en esta y si en stretch… O se lo indiquemos manualmente durante la instalación que es lo que vamos a ver a continuación. Si quieres maś información sobre la forma de establecer preferencia para apt puedes echarle un vistazo a esta página.

Y ya lo tenemos todo listo. Ahora, tenemos que actualizar nuestros repositorios (apt update) y cuando queramos instalar un paquete directamente de stretch lo especificamos manualmente en el comando apt. Por ejemplo, si quisiéramos instalar la versión de apache de stretch lo haríamos así:

apt-get install -t stretch apache2

Artículo Original: .

Este artículo pertenece a Un lugar en el mundo... Si quieres ver actualizaciones y comentarios interesantes visita el texto original en: Chuletillas (y XXXXVII) – Instalar un programa de debian Stretch mientras que usas debian stable (Jessie) || Hospedado en un Cloud VPS de Gigas.

Jueves 09 de marzo de 2017

Más sobre el soporte OpenType en LibO 5.3+

Como comenté hace unos meses, LibO 5.3 nos ha sorprendido con el soporte OpenType completo. Esto ciertamente significa que la próxima edición de cierto libro (cuando llegue) vendrá con el capítulo sobre tipografía completamente reescrito… Pero bueno, mientras esperamos he pensado que conviene dejar un artículo detallado sobre el tema. Pues bien, como ya comenté […]

Miércoles 08 de marzo de 2017

Aprender Linux con los cursos gratuitos de Linux Foundation

Si eres de los que todavía no ha probado Linux porque piensas que todavía no vas a ser capaz de afrontar el cambio de un sistema operativo a uno más puro o que te faltan conocimientos para ello, no pares de leer, quizá este post haga que cambies de opinión. Desde hace ya unos años la fundación Linux tiene disponibles unos cursos online tanto para profesionales que en algún ámbito de sus
Liher Sanchez

Liher Sanchez
El blog de Liher

Un año con el Xiaomi Redmi 3

Hace aproximadamente un año que compre un Xiaomi Redmi Note 3. Cuando llevaba con el un mes, mas o menos, a mi madre se le estropeó su móvil y decidí regalárselo y comprar para mi el Xiaomi Redmi 3. Ya llevamos un año con ellos y os voy a contar mis impresiones y mi opinión sobre estos terminales y sobre la marca en general.

Antes de comprar el Xiaomi Redmi Note 3 llevaba tiempo queriendo tener un móvil de dicha marca, había leído muy buenas opiniones de ellos y quería comprobarlo de primera mano. Mirando varios Xiaomi encontré muchos modelos y me costó decidirme, uno que me gustó mucho fue el Xiaomi mi5. Cuando me llegó la primera impresión que me llevé es que era muy grande para mi. El Note 3 es un móvil de 5,5 pulgadas de pantalla, ademas los botones no forman parte de la pantalla, están justo debajo, lo cual hace que sea mas grande. Si me paro a pensar la verdad es que la diferencia de tamaño con respecto al Redmi 3 no es mucha, pero ya el de 5 pulgadas se me hace un poco grande.

 

 

La verdad es que quizás sea la única pega que le encontré al Note 3, y no es que sea algo malo, pero son preferencias personales. Si te gustan los móviles grandes es una muy buena elección. Por eso, cuando recibí el Xiaomi Redmi 3 estaba mas satisfecho, ya que su tamaño me gustaba mucho mas.

En cuanto a las características de los móviles son prácticamente iguales. Ambos tienen un procesador de 8 núcleos, 2 GB de RAM, 16GB de espacio y una batería de unos 4.000 Mah. En ambos móviles he instalado juegos potentes para ver como los movían y la respuesta ha sido muy buena, quizás sea una de las mejores formas de comprobar su rendimiento y han superado la prueba con creces.

La multitarea funciona en ambos realmente bien y puedes moverte entre las diferentes aplicaciones que tengas abiertas con total soltura y sin sufrir nada de lag. La cámara tiene muy buena calidad, hace buenas fotos y graba buenos vídeos, quizás un punto flaco sea las fotos y vídeos nocturnos, pero eso pasa en prácticamente todos los móviles a no ser que sean de muy alta gama.

Una de las cosas que mas me preocupaba era la batería. Vienen con una batería de unos 4.000 Mah y, en principio debería servir para usar el móvil un día entero sin ningún problema, lo cual he podido comprobar. Ha habido varias ocasiones en las cuales la batería me ha aguantado dos días sin problemas, y dándole bastante uso. La mayoría de los días lo pongo a cargar por la noche aun quedándole un 40% de batería. Su capacidad, después de un año, no se ha visto mermada ni un ápice, sigue igual que el primer día, en ambos modelos.

En cuanto a su robustez puedo decir que son unos teléfonos muy duros. Yo soy muy torpe y el mio se me ha caído de las manos en varias ocasiones, de hecho tiene las cuatro esquinas marcadas ya que ha caído sobre ellas en mas de una ocasión y apenas tiene unas ligeras marcas y la pantalla esta intacta, por lo tanto estamos hablando de unos terminales muy resistentes.

Una cosa que me preocupaba era los posibles problemas que podrían surgir por si el terminal se estropeaba y como tramitar el tema de la garantía. Para evitar malos ratos lo mejor seria comprar un Xiaomi en una tienda en España. Mirando por Internet encontré esta tienda en la cual se pueden comprar cualquier móvil Xiaomi, ordenadores, tablets y componentes de Xiaomi y dan 2 años de garantía. Si, en el periodo de garantía, lo que hayas comprado se estropea ellos lo recogen, lo arreglan y te lo devuelven sin coste alguno y no lo mandan a China, lo arreglan aquí en España. Ademas, si no tiene arreglo te dan uno nuevo. Lo que compres en esa tienda lo tienes en casa en 24/48 horas, lo cual es algo muy bueno también y solo trabajan con Xiaomi.

Después de usar durante un año dos móviles Xiaomi tengo que decir que mi próximo móvil será de esta misma marca seguro, no me cabe ninguna duda. No creo que haya otra marca de teléfonos móviles que ofrezca una mejor relación calidad/precio que ellos, yo estoy muy satisfecho con mi compra.

Un saludo a todos.

Gaspar Fernández

Gaspar Fernández
Poesía Binaria

Edición de vídeo en GNU/Linux con software libre, ¿Qué características necesito para editar vídeo?

El momento ha llegado, tras tantos años sin pensar en ella. He vuelto a encontrármela, ahí de pie, delante de mí. Su nombre es Pandora y con una risa maliciosa viene a este humilde blog. A llenar nuestras almas de oscuridad aumentando el contraste y corrigiendo el color.

Aunque poco a poco he estado soltando pinceladas en el tiempo sobre imagen digital en GNU/Linux, vídeo digital, integración de algunas técnicas y demás. Pero creo que ha llegado el momento de hacer algo más grande y preparar una referencia mayor sobre software libre y edición de vídeo.

Mi experiencia personal y privativa

Hace muchos años que me adentré en el mundo de la edición de vídeo por ordenador. Como muchos de nosotros, empecé haciendo pequeñas animaciones en un modesto equipo del siglo pasado, sólo por hobbie y por hacer algo con mi tiempo (en aquella época en la que aún podía gozar de algo de tiempo libre). El programa que solía utilizar era Autodesk Animator. Estaba muy limitado, pero podías hacer muchas cosas. Era muy intuitivo.

Con el tiempo, fui conociendo otros programas de edición de vídeo, hasta que gracias a un amigo conocí el paquete de Ulead Videostudio. Esta persona se compró una tarjeta capturadora en aquella época en que las tarjetas de este tipo ocupaban todo el ancho de la torre y costaban un ojo de la cara y medio riñón… pero venían con mucho software para utilizar. Unos años más tarde fueron bajando de precio, aunque empezaron a ser un poco peores en la captura. Como los ordenadores de aquella época no eran tan rápidos, estas tarjetas solían llevar un chip compresor/descompresor MPEG integrado por lo que a medida que capturabas vídeo lo ibas recibiendo comprimido y todo… y como en todo, un mejor compresor generaba vídeos de menor tamaño con mayor calidad, y dado que el ancho de banda del bus es limitado llegaba un punto que una tarjeta capturadora barata no podía obtener mucha calidad. Con el tiempo terminé comprando una tarjeta de estas, de las baratas, no de las profesionales, aunque dentro de la gama de las baratas me fue muy bien.

Unos años más adelante, con capturadora nueva, no tenía cámara de vídeo y me pasé mucho tiempo pidiendo cámaras de vídeo. Si algún amigo tenía una cámara de vídeo, allá que iba yo cuando tenía algún proyecto para grabar. Me lo pasaba en grande montando historias para hacer pequeñas grabaciones en mi adolescencia. ¿Algunos ejemplos? (He perdido mucho material, tenía muchas cosas grabadas en CD y esos CDs cambiaron de plano existencial, fue una gran pérdida, no es lo mejor, pero sí lo que pude rescatar y lo que Youtube no me ha quitado por tema de licencias).

He perdido muchísimo material. Además, en 2003 hice mi paso definitivo a GNU/Linux. Aunque tenía la espinita del vídeo digital, me pudo más el hecho de dejar Windows de lado y llegó un punto en el que no arrancaba Windows para nada por lo que GNU/Linux pasó a ser el único sistema operativo de mi ordenador, y lo ha sido hasta el día de hoy.

Bueno, antes de nada decir que hasta 2003 más o menos, los programas de edición de vídeo para Windows tampoco destacaban por su estabilidad. Ya fuera por el propio sistema operativo, el uso intensivo de la memoria, los codecs y la complejidad de los sistemas, era común encontrarse con algún pantallazo azul de vez en cuando, o que el propio programa en el que estabas editando vídeo en el momento de más concentración se cierra inesperadamente dejándote todo el trabajo a medias. O, como me pasó con Huyendo del destino, el ordenador se reinició y cuando todo arrancó vi que los principales archivos del proyecto estaban corruptos (era mucho más largo y abandoné el proyecto).

Lo sé, había editores de vídeo para GNU/Linux

Soy consciente de ello, es más, de vez en cuando abría alguno e intentaba hacerme con él, aunque el problema, como en Windows era la estabilidad, aunque en este sistema era aún peor. Por un lado, los programas de edición no eran lo suficientemente maduros, casi todos acababan de nacer (incluyo como mucho hasta 2004, avisadme si falta alguno):

  • KDEnlive nació en 2002
  • Cinelerra nace en 2002
  • PiTiVi nace en 2003
  • Blender se libera en 2002, aunque no editaba vídeos
  • Shotcut nace en 2004
  • LiVES nace en 2003

Y es normal que tratándose de software libre, en este sentido estos desarrollos fueran bastante lentos. Además estábamos en una época cambiante, con respecto a codificación de vídeo (MPEG-4 estaba pisando fuerte, había nuevas formas de codificar audio y surgían formatos propios de Microsoft o Apple a los que había que dar soporte. También estaba entrando el DVD y los usuarios de GNU/Linux teníamos derecho a utilizar el DVD). Además, las cámaras empezaban a utilizar el IEEE1394 que era más rápido que USB para transmisión de datos… En definitiva, los desarrollos de codificación y soporte cambiaban muy a menudo, y quienes desarrollaban estos programas de vídeo al no estar amparados por ninguna empresa, encima recién nacidos los proyectos, era normal que no fuera la cosa tan estable como debería… y ya por no meternos en el tema de tarjetas gráficas.

El caso es que para 2006 pude volver a hacer algún montaje sencillo, con una estabilidad que más o menos me permitía no arrancarme el pelo de desesperación. En este caso con KDEnlive, un editor que he utilizado mucho y durante muchas horas, que me ha dado alegrías y penas y del que alguna vez he hecho algo en este blog.

También quiero dejar claro que, la industria del cine, según dice empieza a utilizar GNU/Linux en el año 2002 o incluso antes. Empresas como Industrial Light and Magic, Rhythm and Hues, Dreamworks, WetaDigital o Pixar dicen que utilizan GNU/Linux en algunos de sus procesos, eso sí con herramientas propias y/o privativas.

Estado del arte

Pero llega 2017. Y, sobre todo me animo a hacer esta serie de posts el hecho de que KDEnlive, después de algo más de dos años sin usarlo, en diciembre de 2016, lo he notado más estable que nunca, pude hacer un vídeo sin que me diera guerra el programa, incluso abrí un montaje hecho hace casi 5 años y no tuve ningún problema, bueno sólo un filtro que no estaba, pero era culpa mía que no lo instalé.
Por otro lado, Blender, que, aunque me gusta, tengo que decir que no siempre las versiones estables son estables, ni están libres de fallos tontos (los fallos ocurren, lo sabemos, pero hay algunos más tontos que otros, y a veces la mezcla de dos imágenes no funciona bien, o se ve claramente que se desborda un número y no se ha controlado un valor (lo siento, mi faceta de programador siempre está alerta). Pero abrí Blender 2.78 y me dio muy buena sensación, iba muy ligero y no se quejó para un pequeño montaje (cosa que antes sí que hacía).

Así que, quiero empezar este año a hacer un pequeño análisis y empezar a realizar tutoriales sobre edición de vídeo digital en GNU/Linux, efectos especiales, composición, etc. Es cierto que el software privativo en este sentido está a muchos años de distancia, pero vamos por buen camino, incluso hay cosas que podremos hacer con software libre y no con software privativo, aunque nos toque tener que programarlas.

Un pequeño vídeo

Digo edición de vídeo, pero no profundizo

Es un tema complejo y amplio que he metido en edición de vídeo, aunque sé que hay muchos subtemas que debemos tratar. Una cosa es el montaje, y otra la composición (aunque hay herramientas que las integran). Por otro lado tenemos la conversión, recorte, etalonaje (palabro de la vieja escuela, relativo a la corrección y tratamiento del color), análisis espacio-temporal, screencasting, stop-motion, edición y renderizado 3D, edición de audio y de imagen fija (sí, utilizaremos GIMP para preparar cosas), y mucho más. Tenemos para largo.
Y todo eso sin entrar en temas de producción donde encontramos software para creación de guiones, presupuestos, gestión de proyectos, storyboarding y muchísimo más.

¿Qué le pido a un editor de vídeo?

Hablo aquí de editores de vídeo no lineales, de los de toda la vida, para hacer montajes, en los que cogemos vídeos de origen, aplicamos un efecto y obtenemos un vídeo resultante.

Me quiero centrar en tres características:

Edición multicapa

Esto es, que podamos superponer varias capas de vídeo o imagen unas encima de otras para obtener una imagen resultante mezcla de todas. Podremos aplicar filtros a algunas imágenes intermedias, introducir transparencias, mover capas dentro de la imagen y mucho más.
Casi todos los editores suelen tener esta característica, mejor o peor, sólo quiero quitar del medio los programas que no valen para este tipo de edición, los que dan muchos problemas al realizarlo. No está bien que el día que necesitas 5 capas para montar un vídeo el programa empiece a ir extremadamente lento.

Proxys

Ahora editamos en resoluciones muy grandes. Es más, en el año 2000 se editaban algunas películas en 8K (y eso que ahora estamos con la novedad de las pantallas 4K). Eso sí mientras estamos editando, durante casi todo el proceso no nos importa tener las imágenes a la mayor resolución. Para conocer cambios de escena, hacer muchas tareas de corrección de color o mezclado no necesitamos las imágenes en alta resolución.
Así que un buen programa de edición de vídeo, aunque ocupe algo más de disco duro, y tarde un poco más al principio, nos permitirá generar vídeos en resoluciones más pequeñas y con algoritmos de fácil descompresión con el objetivo de facilitarnos el trabajo.
Imaginemos que mi cámara digital comprime los vídeos en MPEG-4 AVC (H.264, mal empezamos si queremos ser libres, pero bueno). El formato crea archivos de pequeño tamaño con nuestro vídeo, lo malo es que necesitamos un uso intensivo de CPU, incluso es más fácil reproducir un vídeo que extraer un fotograma suelto, y cuando estamos editando casi siempre estaremos extrayendo esos fotogramas por separado para realizar todo el trabajo de las capas. Muchas veces estos proxys suelen hacerse en MPEG-2, que a estas alturas se descomprime de forma muy sencilla, o en imágenes sueltas, JPEG, TIFF, PNG…). En definitiva, a lo mejor perdemos mucho tiempo en este trabajo. Además, si estamos trabajando en FullHD (1920×1080), seguramente la vista previa esté a un cuarto de resolución (960×540) o menos, por lo que, para crear las vistas previas, no merece la pena hacer todo el proceso en resolución completa, podemos coger la imagen a 960×540 y trabajar con ella, el resultado será el mismo y se harán un 25% de operaciones, lo que nos permitirá hacer cosas más complejas.

Eso sí, cuando vayamos a hacer el render definitivo, el programa cogerá los archivos originales. En hacer el render, no nos podemos precipitar. Es verdad que podremos optimizar y hay programas más rápidos que otros, pero lo realmente importante, creo que es el proceso de edición, el render siempre puede tirarse un ordenador varios días encendido, o podemos hacerlo en un servidor.

Máscaras

Esto es más de composición, pero me encanta que los editores tengan la posibilidad de incluir máscaras rápidas para hacer pequeños efectos rápidos. Con estas máscaras podremos dibujar zonas de la imagen que serán relevantes para nosotros descartando lo demás, que luego podremos superponer y hacer muchas tareas con ellas. Las máscaras deberían poder animarse, con lo que crearemos efectos de rotoscopía. Creo que hablaré sobre esto en un futuro post. Es un tema que me encanta.

¿Algo más?

Hay muchas más cosas que un editor debe tener, pero empecemos por estas tres. Por supuesto, deberíamos poder aplicar filtros de color, y corregirlo de forma precisa, seleccionar áreas que queremos con diferente color… aplicar efectos de barrido, ajustar velocidad de vídeos y muchas más cosas a las que me gustaría dedicarle algunos futuros posts y vídeos.

Programas para abrir boca

Sigue este enlace, donde veremos una colección de programas y recursos con los que editar vídeo y audio en GNU/Linux. El listado irá creciendo con enlaces a manuales, tutoriales y guías poco a poco.

Y tú, ¿qué software usas?

¿Qué software utilizas tú para tus montajes de vídeo? ¿Qué características son las imprescindibles para ti?

The post Edición de vídeo en GNU/Linux con software libre, ¿Qué características necesito para editar vídeo? appeared first on Poesía Binaria.

Jueves 02 de marzo de 2017

José María Morales Vázquez

José María Morales Vázquez
tecnología – Un lugar en el mundo…

Nueva página: Herramientas web de testing y monitorización

herramientas En muchos de los articulos que publico por aquí referencio herramientas web encaminadas a ayudar con la configuración, pruebas o análisis de diversos elementos de nuestra infraestructura informática. Servidores Web, certificados SSL, Disponibilidad, Correo Electrónico, Seguridad, etc. El enlace a la página está en el índice lateral y aquí:

Herramientas web de Testing y Monitorización

El propósito de esta nueva página es recogerlas en un único lugar para mantener una referencia completa, cómoda y perfectamente autorizada. Todas las herramientas relacionadas en ella son gratuitas al menos en un modo básico aunque podrían tener un modo de pago más completo. Y si conoces alguna otra que no aparece y crees que puede ser útil no dejes de enviármela a través de un comentario por favor. Gracias.

Artículo Original: .

Este artículo pertenece a Un lugar en el mundo... Si quieres ver actualizaciones y comentarios interesantes visita el texto original en: Nueva página: Herramientas web de testing y monitorización || Hospedado en un Cloud VPS de Gigas.

Lunes 27 de febrero de 2017

José María Morales Vázquez

José María Morales Vázquez
tecnología – Un lugar en el mundo…

Chuletillas (y XXXXVI) – Solventar el error de wordpress que lo deja bloqueado en modo de mantenimiento

chuleta Si trabajas habitualmente con wordpress te habrá pasado montones de veces. Tras actualizar un plugin, un tema o el propio wordpress la instancia web se queda “eternamente” mostrando un mensaje como el que sigue a pesar de que debería (y lo ha hecho) haber concluido ya la actualización en cuestión.

Briefly unavailable for scheduled maintenance. Check back in a minute.

En esos casos recurres a buscar en google un blog (como este) donde te cuentan la solución o le pides a algún amigo (que hará o habrá hecho lo mismo en alguna ocasión) que te lo solucione. En el peor de los casos le pagas a alguien para que te solucione el problema o recurres a la empresa que te lleva el mantenimiento.

La solución es muy sencilla. wordpress “detecta” que debe de mostrar el mensaje de mantenimiento porque en el directorio raiz de la instancia web existe un archivo llamado .maintenance En algunas ocasiones el borrado de ese fichero falla una vez concluida la actualización y wordpress se queda ahí encallado. Para solucionarlo basta con borrar manualmente ese fichero desde el panel web que usemos para acceder a nuestro servidor (si somos novatos) o desde la consola si nos manejamos un poco mejor. Fácil, eh?

Artículo Original: .

Este artículo pertenece a Un lugar en el mundo... Si quieres ver actualizaciones y comentarios interesantes visita el texto original en: Chuletillas (y XXXXVI) – Solventar el error de wordpress que lo deja bloqueado en modo de mantenimiento || Hospedado en un Cloud VPS de Gigas.

Domingo 19 de febrero de 2017

Marcelo Fortino

Marcelo Fortino
Fortinux

Tutorial Instalar PHP Server Monitor en Ubuntu GNU/Linux

En este tutorial vamos a instalar PHP Server Monitor en un servidor Ubuntu 14.04. PHP Server Monitor es una aplicación web open source que sirve para monitorear servidores web y/o sitios web.

Sábado 18 de febrero de 2017

Liher Sanchez

Liher Sanchez
El blog de Liher

Usar el icono del Launcher de Ubuntu para maximizar una ventana

El otro día os hable de como podemos minimizar todas las ventanas que tenemos abiertas de nuestro Ubuntu de una vez con una combinación de teclas para así poder ver nuestro escritorio. También os mostré como podéis añadir el botón de Mostrar escritorio al Launcher. Quizás esa opción debería venir por defecto, quizás no, pero la que os voy a comentar en este post me parece mas útil y si que debería venir activada, por lo menos esa es mi opinión. Se trata de que cuando tenemos una aplicación abierta, al hacer click en su icono en el Launcher, la ventana de dicha aplicación se minimice. Por defecto no viene activado, pero es muy fácil hacerlo.

Muchos dirán que las cosas que tienen que venir por defecto activadas o no en Ubuntu dependen de nuestra forma de movernos con el ordenador y que Cannonical no puede atender todas las peticiones o bien hacer un Ubuntu que sea del agrado de todos con estas pequeñas cositas, pero en fin, cada uno tiene su opinión 😀 Por suerte estas coas tienen muy fácil y rápida solución.

Personalmente, me parece que es muy útil que podamos minimizar las ventanas de los programas haciendo click en su icono, ademas de si esta minimizada poder ponerla en primer plano al hacer click también en su correspondiente icono. Digamos que es un comportamiento tipo dock que yo usaba mucho cuando tenia instalado el Cairo dock.

Si queréis que cuando una aplicación este abierta la podamos minimizar al hacer click en su icono en el Launcher de Ubuntu lo único que tenéis que hacer es abrir una Terminal y escribir el siguiente comando en ella:

gsettings set org.compiz.unityshell:/org/compiz/profiles/unity/plugins/unityshell/ launcher-minimize-window true

Solo hace falta teclear ese comando y pulsar Enter para poder disfrutar de esa posibilidad. Si, por alguna razón, queréis volver al estado inicial y no tener esa opción activada lo único que tenéis que hacer es teclear el mismo comando pero con “false” en vez de “true” al final, quedando el comando de la siguiente forma:

gsettings set org.compiz.unityshell:/org/compiz/profiles/unity/plugins/unityshell/ launcher-minimize-window false

Como podéis es bastante sencillo. Ahora solo queda que lo probéis y toméis la decisión de usarlo o no.

Un saludo a todos.

Lunes 13 de febrero de 2017

Liher Sanchez

Liher Sanchez
El blog de Liher

Los juegos que me gustan

Siempre me han gustado los videojuegos. Muchos de los que usamos ordenador hemos tenido épocas en las que los hemos usado, en mayor o menor medida. En mi caso ha habido muchos juegos que me han gustado y me gustan y quiero hablaros un poco de ellos, ademas de recordaros algunos que seguro conocéis.

Mi primer ordenador lo tuve con 14 años, era un 386 con 2 MB de RAM y 43 MB de disco duro. Por aquel entonces los juegos venían en uno o varios disketes de 3 ½. Seguramente algunos de vosotros no hayáis usado este medio, os dejo una imagen para que los podáis conocer:

 

disketes

 

Tenia una capacidad de 1,44 MB, algunos juegos ocupaban varios disketes y otros entraban de sobra en ellos. De aquella época guardo buenos recuerdos de varios juegos en especial de 3. El primero es The secret of Monkey island era un juego de tipo aventura gráfica en el cual tenias que ir saliendo airoso de varias situaciones gracias a tu ingenio, era un juego gracioso y entretenido del que seguro que muchos de mi generación guardan un buen recuerdo.

 

the secret of monkey island

 

Otro juego fue Prince of persia, era un juego de plataformas y lucha en el cual tenias que ir por diferentes niveles para rescatar a un princesa. Estaba muy entretenido y me gustó mucho.

 

prince of persia

 

El tercero es Warcraft, un juego de estrategia de guerra en el cual tenías que crear una aldea, recolectar recursos, prosperar y conquistar otras aldeas, muy parecido a Clash of clans.

 

 

Por supuesto que jugué a muchos mas juegos, pero esos tres son los que más me gustaron de aquella época.
Posteriormente, al ir cambiando de ordenador y tener una máquina más potente puede ir accediendo a juegos mas actuales como el FIFA o el Quake. Uno que me gustó mucho también fue el Age of Empires, en la linea del Warcaft, siempre me gustaron ese tipo de juegos de estrategia y guerra.

Con 22 años, mas o menos, tuve mi primera consola de videojuegos, la PS One, con ella tuve una enganchada importante al Gran Turismo 2, de hecho conseguí pasarme el juego entero. Prácticamente solo jugaba a ese juego, aunque el Driver y el FIFA me ocuparon muchas horas también.

También tuve una época en la que usaba un emulador llamado MAME con el cual se podían usar juegos de casi todas las videoconsolas y las máquinas recreativas, en un DVD podías tener el emulador en sí mismo y miles de juegos, desde los de Atari de los años 80 hasta juegos como el Tekken.

Hace tiempo que no tengo videojuegos en el ordenador, a día de hoy no tengo ninguno, ya que como se que soy de fácil enganche lo mejor es no tener ningún instalado, conócete a ti mismo ;D

También tuve una temporada en la que jugaba a algún juego online. Uno de ellos era un juego de poker. Al principio estaba bastante perdido con las reglas y el valor de las posibles combinaciones pero en Internet siempre podemos encontrar ayuda como en esta página, en la cual podemos aprender todo lo necesario gracias a un glosario del juego, y así podemos mejorar nuestra habilidad y aumentar nuestros conocimientos sobre un juego del que mucha gente piensa que es cuestión de azar y no es así, necesitamos de destreza e ingenio para jugar bien.

A día de hoy el único juego que uso es el Clash of Clans, siempre me han gustado los juegos de estrategia y con el tengo el entretenimiento que necesito. Aun a pesar de ser un juego sencillo, tiene un sinfín de posibilidades. Atacar una aldea y ganar el ataque, a la vez que tener una buena defensa en tu aldea es como una partida de ajedrez donde cada elemento tiene un propósito y hay que averiguar la mejor forma de usarlo. De echo tengo en mente crear una web sobre el juego con consejos, diseños de aldea y demás, aunque voy poco a poco.

 

clash of clans

 

Y bueno, eso es un poco todo, la verdad es que me encantaría que compartieseis los juegos que usáis, aquellos que más os gustan o los que recordáis con nostalgia. Un saludo a todos.

Martes 07 de febrero de 2017

Ramón Miranda

Ramón Miranda
Ramon Miranda

TRUN videogame cover for VGsource


Talking about TRON is talking about a classic science fiction film and one of the best tributes to creativity and imagination in the world of cinema. Somewhat misunderstood film at first, but time makes justice and put TRON in its place. And if we talk about mythical elements of the film, we have to talk about bikelight racings ...

TRUN is a videogame created in Z80 assembler based on  original TRON.
The creators of the game are Vgsource, an indie development group that codes for MSX.
A few months ago, I was contacted to design their videogame cover and thus give it a greater visual impact.
It was an interesting work because from the first moment we looked for a 80's look"  immitating the style of covers of the era of Dinamic or Topo (spanish companies), where Azpiri was king illustrating those beautiful casettes and the less important was the result on screen (at least for people like me)
The first thing I did was to take references, and as it was not going to be otherwise the TRON movie itself was the main source of inspiration. I had several keys in mind while painting this illustration:
  •     blue
  •     Light
  •     No Fx overlay.
  •     Speed
  •     80's smell
Do you want to see how development was? Then we analyze the different phases briefly.

Sketches Phase

After analyzing what I want to emphasize in the image I start working on the sketches.
These are not very detailed drawings, but you can see the main elements of the design.


I decide for the first by movement feeling.



As we know the diagonals add movement to the composition and as I want to transmit speed I choose the design with that scheme and the broad to be able to study where to place each thing. Something that in the end I will change are the bikes. Finally will be even more "homage" to the original light bikes designed by Syd Mead.

References Phase

Being the game a "clone" of the game of TRON does not seem crazy to me to take references of the film. Since we are going to make a copy of a classic we will do well. Let it be noticed! That's why I create a composition with multiple references to then paint over what I need and get the result I want, not so photo but 2d. There is still a lot of work left. This system is not the only one I use for my illustrations.
This is the result of collage done inside Krita. All images have their corresponding copyright. We only use this as an idea. At the end, 100% of the illustration is repainted.



From this point we will work the Backgrounds. For the backgrounds, brushes that are quick for "covering big areas" are usually used. I use a brush that has the characteristic that diffuses the paint when low pressure is used and is adding more paint as the pressure increases. This is what I show you in the capture.




It has a Knive effect and belongs to the set I made for the DVD of the krita foundation #muses. If you are interested you can download it here totally free.

PACK bundle muses

Note: If for some reason you see that this brush produces somekind of "Lag", a very useful thing that speed up this brush and many of Krita's brushes is to use the "precision" parameter inside the brush editor and lower it from 5 to 1 If you also use large sizes you can increase the brush spacing to 0.5 or 0.7. It can be further optimized to gain speed in very large sizes.




Beyond it you will see that it is very fluid but loses a little of quality. These brushes require important computation operations for the CPU but give very interesting results.
What I want is to blur the photo effect but respecting the colors that are underneath while still being spots and at the same time giving me more freedom to paint over. You will see that the result is very pictorial. Handcrafted within the digital.

 
Now it's time to start defining all the elements of the image.
The face in the photo does not show an emotion according to what I look for, come on man! You're playing with your life in a race! :)
I have created this Gif for those who like to follow the evolution of the steps to follow.


You can see how the lighting changes as I work the metal. The gif was done with Gimp. It explains much more than a page of text. Among other things it is seen how the light is affecting the face of the character and his helmet.

The same thing happens in the background. When I go detailing the bikes and the kind of hangar where they come from.

When completing the image we run the risk of adding too many details. So beware of the Glow and the additive or color dodge modes that hook.
Making lines or curves accurately is complicated with freehand so one way to avoid headaches is to use paint assistants.

For example a use would be in the curve that defines the motorcycle panel of the character.


LightBykes

A main element of this image are the light bikes. Let's do something simple so we do not separate too much from what will be seen on the screen.


 

The problem as I see it is that the bikes need some lines of movement. This will convey more sense of career. In the end I choose lines not on the whole bike but in part. The result is something more shocking.


Logotype design for the cover

All we have left to do is create a logo for the cover design. For that task I better use an image editor like Gimp and a vector design program like Inkscape.

In Gimp I select the text tool with the previously downloaded typography that is very similar to TRON.


To vary slightly the layout i adjust and complete the contour of the word "TRUN" That way I have a good basis for editing in Inkscape and that can be adapted to any size without loss of quality.


Now we can add the text to our image.
And the end result is what we expected. Did you like it?

** If you liked the article and learned something to help you, you can support me by sharing the news with your friends. See you in the next article.

If you want to know more about the video game these links may seem interesting.


Some photos

Asociación de amigos del MSX




https://www.msx.org/es/news/software/es/trun-nuevo-juego-de-msx
 



Ramón Miranda

Ramón Miranda
Ramon Miranda

Portada para videojuego TRUN de VGsource


Hablar de TRON es hablar de un clásico de la ciencia ficción y de uno de los mejores tributos a la creatividad e imaginación en el mundo del cine. Película un tanto incomprendida al inicio, pero el tiempo le dio la razón y la puso en su lugar. Y si hablamos de elementos míticos de la película, tenemos que hablar de las carreras de motos de luz...

TRUN es un videojuego creado en ensamblador Z80 basado en TRON.
Los creadores del Juego son Vgsource, un grupo indie de desarrollo que programa para MSX.
Hace unos meses, me contactaron para diseñar su portada y así darle un impacto visual mayor.
Fue un trabajo interesante porque desde el primer momento se buscaba un "look" ochentero imitando el estilo de portadas de la época de Dinamic o Topo, donde Azpiri era el rey ilustrando esos bellos casettes y lo de menos era el resultado en pantalla ( al menos para personas como yo)
Lo primero que hice fue coger referencias, y como no iba a ser de otra forma la propia película de TRON fue la principal fuente de inspiración. Tenía varias claves en mente mientras pintaba esta ilustración:
  • Azul
  • Luz
  • No Fx overlay.
  • Velocidad
  • Espíritu 80's
¿Os apetece ver como fue el desarrollo? Pues analizamos las diferentes fases brevemente.

    Fase de Bocetos

    Después de analizar qué quiero destacar en la imagen empiezo a trabajar en los bocetos.
    Estos son dibujos no muy detallados en los que se pueden ver los elementos principales del diseño.



    Me decido por la primera por la sensación de movimiento.



    Como ya sabemos las diagonales añaden movimiento a la composición y como quiero transmitir velocidad elijo el diseño con ese esquema y lo amplio para poder estudiar dónde colocar cada cosa. Algo que al final voy a cambiar son las motos. Finalmente serán aun más “homenaje” a las originales motos de luz diseñadas por Syd Mead.

    Fase de referencias

    Siendo el juego un calco del juego de TRON no me parece una locura coger referencias de la película. Ya que vamos a hacer una copia de un clásico vamos a hacerlo bien. ¡Que se note! Por eso creo una composición con las múltiples referencias para luego pintar por encima lo que necesite y llegar al resultado que quiero, no tan foto sino más 2d. Queda aun mucho trabajo.Este sistema no es el único que uso para mis ilustraciones.

    Este es el resultado del collage realizado dentro de Krita. Todas las imágenes tienen sus derechos de autor correspondientes. Esto solo lo usamos como idea. Al final se repinta el 100% de la ilustración.



    A partir de este punto vamos a trabajar los fondos. Para los fondos normalmente se usan pinceles que sean rápidos que "cubran" Utilizo un pincel que tiene la característica que difumina la pintura cuando se ejerce poca presión y va añadiendo más pintura según aumenta la presión. Es este que os muestro en la captura.



    Tiene un efecto como de espátula y pertenece al set que hice para el DVD de la krita foundation #muses. Si os interesa os lo podéis descargar aquí totalmente gratis.

    PACK bundle muses

    Nota: Si por alguna razón veis que este pincel produce algo de "Lag", una cosa muy útil que acelera tanto este pincel como muchos de los de Krita es utilizar el parámetro "precisión" dentro del editor de pinceles y bajarlo de 5 a 1. Si además utilizas tamaños grandes puedes aumentar el espaciado del pincel hasta 0.5 o 0.7. Se puede optimizar aun más para ganar velocidad en tamaños muy grandes.




    Más allá verás que va muy fluido pero pierde un poco de calidad. Estos pinceles exigen operaciones de cómputo importantes para la CPU pero dan resultados muyyy interesantes.  

    Lo que quiero es desdibujar el efecto foto pero respetando los colores que hay debajo aun siendo manchas  y a la vez darme más libertad para pintar por encima. Veréis que el resultado es muy pictórico. Artesanal dentro de lo digital.


     

    Ahora es tiempo de empezar a definir todos los elementos de la imagen.

    La cara en la foto no muestra una emoción acorde a lo que busco, vamos hombre! ¡Que te estás jugando la vida en una carrera! :)

    He creado este Gif para los que les gusta seguir una evolución de los pasos a seguir.

    Se puede apreciar como va cambiando la iluminación según voy trabajando el metal. El gif lo hice con Gimp. Explica mucho más que una página de texto. Entre otras cosas se ve cómo la luz va afectandola cara del personaje y su casco.
    Lo mismo sucede en el fondo. Cuando voy detallando las motos y la especie de hangar de donde salen.


    Al ir completando la imagen corremos el riesgo de añadir demasiados detalles. Así que cuidado con el Glow y los modos aditivos o color dodge que enganchan.
    Hacer lineas o curvas con precisión es complicado a mano alzada por eso una forma de evitarnos quebraderos de cabeza es utilizar los asistentes de pintura.



    Por ejemplo un uso sería en la curva que define el panel de la moto del personaje.


    Motos de Luz.

    Un elemento principal de esta imagen son las motos de Luz. Vamos a hacer algo sencillo para no separarnos demasiado de lo que se verá en pantalla.

     

    El problema según veo es que las motos necesitan unas lineas de movimiento. Esto va a transmitir más sensación de carrera. Al final opto por lineas no en toda la moto sino en parte. El resultado es algo más impactante.


    Diseño de Logo para la portada

    Ya solo nos queda realizar un logotipo para el diseño de la portada. Para esa tarea mejor utilizo un editor de imágenes como Gimp y un programa de diseño vectorial como Inkscape.

    En Gimp selecciono la herramienta texto con la tipografía previamente descargada que es muy parecida a la de TRON.



    Para variar un poco el diseño ajusto y completo el contorno de la palabra TRUN De esa forma ya tengo una buena base para editarlo en Inkscape y que se pueda adaptar a cualquier tamaño sin perdida de calidad.

    Ahora ya podemos añadir el texto a nuestra imagen.
    Y el resultado final es lo que esperábamos . ¿Os ha gustado?
    **Si te ha gustado el artículo y has aprendido algo que te ayude, puedes apoyarme compartiendo la noticia con tus amigos. Nos vemos en el próximo artículo.
    Si quieres saber más del video juego estos enlaces te pueden parecer interesantes.

    Algunas fotos

    Asociación de amigos del MSX


    https://www.msx.org/es/news/software/es/trun-nuevo-juego-de-msx
     




    Martes 31 de enero de 2017

    Tutorial de Maud, motor de plantillas HTML para Rust

    Seguimos aprendiendo en el blog sobre interesantes proyectos hechos para Rust. Ya hemos visto Iron, Piston y Neon. Hoy veremos Maud, un potente motor de plantillas que se centra en la eficiencia. Maud se compara a otras soluciones como Razor, ERB, Liquid,  Handlebars o Jade pero esta vez escribiremos nuestro HTML en Rust. ¿Locura? No, y de hecho funciona de forma bastante transparente. Vamos a verlo en acción

    Comparativa de velocidad de diferentes motores. Maud es el más rápido (menos es mejor)

    Instalando Maud

    Maud usa plugins del compilador, una característica que a día de hoy no está activado ni en el canal estable ni el canal beta, solamente en el canal nightly. Para obtener una copia de Rust nightly lo ideal es usar Rustup.

    Una vez hecho eso, creamos un nuevo proyecto y añadimos las dependencias de Maud al fichero Cargo.toml.

    maud = "*"
    maud_macros = "*"
    

    Una simple plantilla

    Ahora abrimos el archivo src/main.rs y vamos a empezar a usar Maud.

    #![feature(plugin)]
    #![plugin(maud_macros)]
    
    extern crate maud;
    
    fn main(){
            let name = "Adrián";
            let markup = html!{
                p { "Hola, soy " (name) " y estoy usando Maud"}
            };
            println!("{}", markup.into_string());
    }
    
    

    La potencia de Maud se ve en la mega-macro html!. En esta macro escribiremos la plantilla que será compilada de forma nativa a Rust, lo que nos asegura una velocidad de ejecución excepcional. En este caso la salida será una etiqueta P de párrafo con la variable interpolada.

    Simple, ¿no?

    PreEscaped y otros elementos básicos

    Por defecto en Maud todos el texto se convierte a HTML seguro. Es decir, no se pueden introducir etiquetas nuevas en el texto. Si por alguna razón necesitásemos añadir etiquetas nuevas podemos usar PreEscaped, que no realiza esta transformación de seguridad. Veamos el siguiente código:

    #![feature(plugin)]
    #![plugin(maud_macros)]
    
    extern crate maud;
    
    use maud::PreEscaped;
    
    fn main(){
            let name = "Adrián";
            let markup = html!{
                    p { "Hola, soy " (name) " y estoy usando Maud" }
                    p { "<h5>Esto no funcionará</h5>" }
                    p { (PreEscaped("<h5>Esto sí funcionará</h5>")) }
            };
            println!("{}", markup.into_string());
    }
    
    

    El primer H5 se convertirá a código HTML seguro, es decir, no añadirá la etiqueta, en cambio se verá h5 en la web. Por contra con PreEscaped se añadirá la etiqueta h5 tal cual.

    Los elementos son muy fáciles de añadir en Maud y por lo general no deberías usar PreEscaped salvo contadas ocasiones. Veamos como añadir más etiquetas.

    #![feature(plugin)]
    #![plugin(maud_macros)]
    
    extern crate maud;
    
    fn main(){
            let name = "Adrián";
            let markup = html!{
                    p { "Hola, soy " (name) " y estoy usando Maud" }
                    p {
                            "Si la montaña no viene a Mahoma"
                            br /
                            "Mahoma va la montaña"
                            small em "Atribuido a Francis Bacon"
                    }
            };
            println!("{}", markup.into_string());
    }
    
    

    En este ejemplo vemos como las etiquetas que no llevan texto como BR o INPUT debemos cerrarlas con una barra. Por otro lado es posible aglutinar varios niveles de etiquetas en una sola línea ( SMALL->EM->Texto).

    Atributos, clases e IDs

    En Maud es posible asignar atributos también, usando literales o variables. Para los atributos de texto la sintaxis es muy parecida a HTML.

    #![feature(plugin)]
    #![plugin(maud_macros)]
    
    extern crate maud;
    
    fn main(){
            let name = "Adrián";
            let amazon = "http://www.amazon.com";
            let markup = html!{
                    p { "Hola, soy " (name) " y estoy usando Maud" }
                    p {
                            "Este texto contiene enlaces a "
                            a href="http://www.google.com" "Google"
                            " y a "
                            a href=(amazon) "Amazon"
                    }
            };
            println!("{}", markup.into_string());
    }
    

    Además existen en HTML atributos vacíos. Es decir, atributos que con su sola presencia basta y normalmente no llevan valor asignado.

    #![feature(plugin)]
    #![plugin(maud_macros)]
    
    extern crate maud;
    
    fn main(){
            let name = "Adrián";
            let allow_editing = true;
            let markup = html!{
                    p { "Hola, soy " (name) " y estoy usando Maud" }
                    p contenteditable?[allow_editing] {
                    }
            };
            println!("{}", markup.into_string());
    }
    

    En este caso el atributo contenteditable se añade si la variable allow_editing es true. Si queremos añadir atributos vacíos en cualquier circunstancia podemos simplemente quitar [allow_editing] y dejar p contenteditable? {}.

    Los IDs y las clases se añaden usando la sintaxis esperable, puntos y almohadillas.

    #![feature(plugin)]
    #![plugin(maud_macros)]
    
    extern crate maud;
    
    fn main(){
            let name = "Adrián";
            let markup = html!{
                    p { "Hola, soy " (name) " y estoy usando Maud" }
                    p.red.font-big#editor contenteditable? {
                    }
            };
            println!("{}", markup.into_string());
    }
    

    Estructuras de control

    Maud soporta las estructuras de control básicas de Rust, if/else, if/let, for in y match.

    #![feature(plugin)]
    #![plugin(maud_macros)]
    
    extern crate maud;
    
    fn main(){
            let loggedIn = false;
            let email = Some("mariscal@example.com");
            let fonts = ["Arial","Times New Roman","Verdana"];
            let markup = html!{
                    @if loggedIn {
                            h1 { "Has iniciado sesión" }
                    } @else {
                            h1 { "Por favor, inicia sesión primero" }
                    }
    
                    @if let Some(mail) = email {
                            p { "Su email es " (mail) }
                    }
                    ol {
                            @for font in &fonts {
                                    li (font)
                            }
                    }
    
            };
            println!("{}", markup.into_string());
    }
    

    Como vemos, Maud posee suficientes características para ser interesante. Maud además permite extender el motor para representar cualquier tipo de dato. Por defecto Maud mirá si está implementado std::fmt::Display pero si queremos añadir etiquetas extra este método no funcionará. En cambio si se implementa la trait maud::Render tendrás control total sobre como va a mostrar Maud las variables de ese tipo. En la crate maud_extras se encuentran implementaciones por ejemplo de Markdown para Maud.

    Maud se integra además con web frameworks de Rust, en especial con Iron y con Rocket. Sin duda, una de mis crates favoritas.

    La entrada Tutorial de Maud, motor de plantillas HTML para Rust aparece primero en Blog - Adrianistan.eu.

    Domingo 29 de enero de 2017

    Gorka Urrutia

    Gorka Urrutia
    Nideaderedes

    Cómo instalar PrestaShop con Vagrant

    Para evtiar dolores de cabeza y tener que andar configurando un servidor local en Linux o algún Wamp en Windows o Mamp en Mac podemos usar Vagrant. He creado una máquina virtual que puedes usar como entorno de desarrollo para PrestaShop.

    Cómo instalar PrestaShop con Vagrant

     

    Gorka Urrutia

    Gorka Urrutia
    Nideaderedes

    La guía definitiva del código espagueti II: Que tus variables y funciones confundan al enemigo

    Porque elegir unos nombres horribles para tus variables y funciones es un arte:

    La guía definitiva del código espagueti II: Que tus variables y funciones confundan al enemigo

    Gorka Urrutia

    Gorka Urrutia
    Nideaderedes

    Programación orientada a objetos en PHP. 3: Encapsulación

    Otra entrega más (y ya van tres) del mini curso de programación orientada a objetos en PHP. Esta vez hablo de encapsulación. No te lo pierdas:

    Programación orientada a objetos en PHP capítulo 3: ¿Por qué no hacer todo public? (Encapsulación).

    Viernes 27 de enero de 2017

    Tutorial de Neon – Combina Node.js con Rust

    Hoy en día muchas webs se diseñan con Node.js. Es una solución fantástica para respuestas rápidas pero numerosos benchmarks han demostrado que su rendimiento empeora en respuestas complejas. Estos mismos benchmarks recomiendan usar Java o .NET si preveemos que nuestra aplicación web va a generar respuestas complejas. Sin embargo renunciar a las ventajas de Node.js no es del agrado de muchos. Afortunadamente hay otra solución, usar Rust. Todo ello gracias a Neon.

    Con Neon podemos generar módulos para Node.js que son escritos y compilados en Rust con las ventajas que supone desde un punto de vista de rendimiento y con la certeza de que en Rust la seguridad está garantizada.

    Usando Neon puedes desarrollar tu aplicación en Node.js y si alguna parte tiene problemas de rendimiento sustituirla por su equivalente en Rust. Para el ejemplo voy a hacer un módulo de Markdown.

    Instalando Neon

    En primer lugar instalamos la herramienta de Neon desde npm.

    npm install -g neon-cli
    

    Una vez esté instalado podemos usar la herramienta de Neon para construir un esqueleto de módulo. Este esqueleto tendrá dos partes, un punto de entrada para Node.js y otro para Rust.

    neon new PROYECTO
    

    Hacemos un npm install como nos indica. Esto no solo obtendrá dependencias de Node.js sino que también se encargará de compilar el código nativo en Rust.

    El código Node.js

    Nuestro módulo contiene un archivo de Node.js que sirve de punto de entrada. Allí lo único que se debe hacer es cargar el módulo en Rust y hacer de pegamento. Puede ser algo tan simple como esto:

    var addon = require("../native");
    
    module.exports = addon; // se exportan todos los métodos del módulo nativo
    

    Aunque si queremos añadir un tratamiento específico también es posible.

    var addon = require("../native");
    
    module.exports = {
        render: function(str){
            return addon.render(str);
        }
    }
    

    El código en Rust

    Nos dirigimos ahora al archivo native/src/lib.rs. Ahí definimos los métodos nativos que va a tener el módulo. Lo hacemos a través de la macro register_module!.

    register_module!(m,{
        m.export("render",render)
    });
    

    Ahora vamos a implementar la función render, que toma el texto en Markdown y lo devuelve en HTML.

    fn render(call: Call) -> JsResult<JsString> {
        let scope = call.scope; // obtener el contexto
        let md: Handle<JsString> = try!(try!(call.arguments.require(scope,0)).check::<JsString>()); // obtener primer argumento como JsString. aquí puede hacerse tratamiento de fallos
        let string = md.value(); // Pasar JsString a String
        let html: String = markdown::to_html(&string); // usamos la crate markdown para renderizar a html
        Ok(JsString::new(scope, &html).unwrap()) // devolvemos un JsString con el contenido del HTML
    }
    
    

    Las funciones que interactuan con Node deben devolver un JsResult de un tipo JsXXX, por ejemplo, JsString, JsUndefined o JsInteger. Siempre aceptan un argumento llamado de tipo Call que nos da toda la información necesaria y que podemos usar para sacar argumentos. El scope o contexto es muy importante y lo deberemos usar en las funciones que interactúen con Node.

    Código completo del fichero Rust

    #[macro_use]
    extern crate neon;
    extern crate markdown;
    
    use neon::vm::{Call, JsResult};
    use neon::js::JsString;
    use neon::mem::Handle;
    
    fn render(call: Call) -> JsResult<JsString> {
        let scope = call.scope;
        let md: Handle<JsString> = try!(try!(call.arguments.require(scope,0)).check::<JsString>());
        let string = md.value();
        let html: String = markdown::to_html(&string);
        Ok(JsString::new(scope, &html).unwrap())
    }
    
    register_module!(m, {
        m.export("render", render)
    });
    

    Y no te olvides de añadir la dependencia markdown al fichero Cargo.toml.

    Probándolo

    Es muy fácil probarlo. Con el REPL de Node podemos probar partes del módulo antes de publicarlo a npm.

    Para abrir el REPL ejecuta Node sin argumentos

    node
    

    E introduce línea por línea lo que quieras probar:

    var md = require("./");
    md.render("__Esto es Markdown__");
    

    Verás el resultado por la pantalla:

    Ahora que ya sabemos que funciona podemos publicarlo a npm si queremos con:

    npm publish
    

    Aunque recuerda revisar antes el fichero package.json para especificar la licencia y la descripción. Una vez esté publicado su uso en un nuevo proyecto será muy sencillo y de forma transparente se compilará el código nativo.

    var md = require("rust-markdown");
    var http = require('http');
    var fs = require("fs");
    
    var server = http.createServer((req, res) => {
      fs.readFile("index.md","utf-8",function(err,data){
         var html = md.render(data);
         res.statusCode = 200;
         res.setHeader('Content-Type', 'text/html');
         res.end(html);
      });
    });
    
    server.listen(8080, "127.0.0.1", () => {
      console.log("Server running");
    });
    
    
    
    

     

     

    La entrada Tutorial de Neon – Combina Node.js con Rust aparece primero en Blog - Adrianistan.eu.

    Sábado 21 de enero de 2017

    Ramón Miranda

    Ramón Miranda
    Ramon Miranda

    Underwater Romance


    Hola a todos mis lectores y colegas. Se fue el 2016, y el 2017 ya lo tenemos aquí.
    Este pequeño artículo es de esos momentos en los que uno hace balance de cómo le fue el año y se pone nuevas metas.Para mi ha sido espectacular. Lo más importante es que al fin di el sí quiero con la mujer que amo. Se llama Lara y es parte fundamental de que esté aquí en Málaga, en esta tierra de luz y color donde tantas veces veranee de pequeño. Nos casamos de manera discreta y sin mucho ruido como queríamos que fuera. Así que en estos momentos estoy muy feliz. Quizás algún día asome por el blog, aunque de momento os digo que no tiene nada que ver con el mundo de la imagen.

    Ya metidos en materia también es muy destacable toda la evolución que ha habido dentro del mundo Krita. Increíble trabajo el de los desarrolladores. Una de las imágenes que la fundación decidió utilizar, fue esta que publico la cual pinté exclusivamente para ellos como recompensa para los que apoyaron la campaña de Kickstarter de Krita en este año. Este es el resultado de apoyar a Krita. la recompensa de ver cómo mejora cada día y ver que más usuarios puedan aprender desentrañando la imagen en alta resolución viendo todas las capas correctamente nombradas. Si quieres apoyar para que el proyecto sea aun mas grande aquí tienes un link https://krita.org/en/support-us/donations/




    Cabe destacar que la idea de hacer la ilustración como vista en el fondo del mar, se le ocurrió a mi mujer tras ver lo que estaba haciendo y los colores que estaba usando. 

    La cara de ella quizás ha sido la parte más difícil. 3 veces la repetí hasta dar con el gesto que buscaba, una pose de inocencia y a la vez de "me dejo seducir por este guapo sireno" ;D



    Si os gusta el resultado seguro que vais a disfrutar con el próximo artículo donde explicaré cómo se hizo esta imagen desde el boceto de color a la pintura acabada.

    Nos leemos






    English Readers

    Hello to all my readers and colleagues. 2016 has gone, and 2017 is already here

    This small article is one of those moments in which you think about how the year went and set new goals. For me it has been spectacular. The most important thing is that finally! I said "yes, i do" to the woman I love. Her name is Lara and she is a fundamental part for being here in Malaga, in this land of light and color where i spent so many summers as a child. We married discreetly and without too much noise as we wanted it to be. So right now I'm very happy. Maybe someday she will write something here, for now I swear you she has nothing to do with the world of the image. :D

    Talking about the picture... is also very remarkable all the evolution that has been in the Krita world. Incredible work for the developers. One of the images that the foundation decided to use, was this one that I published exclusively for them as a reward for those who supported Krita's Kickstarter campaign this year. The bakers with 50$ baked if i remember well received the image in high res and .kra format to learn more about how to use krita. If you want to support krita more there you have a link https://krita.org/en/support-us/donations/



    It is noteworthy that the idea of ​​making the illustration as seen on the bottom of the sea, occurred to my wife after seeing what i was doing and the colors i was putting on canvas.

    Mermaid's face has been the hardest part. I repeated 3 times until I found the gesture I was looking for, a pose of innocence and at the same time "I let myself be seduced by this handsome siren";D





    If you like the result you will enjoy with the next article where I will explain how this image was made from the color sketch to the finished painting.









    Martes 17 de enero de 2017

    Tutorial de Piston, programa juegos en Rust

    Ya he hablado de Rust varias veces en este blog. La última vez fue en el tutorial de Iron, que os recomiendo ver si os interesa el tema del desarrollo web backend.

    Hoy vamos a hablar de Piston. Piston es una de las librerías más antiguas del ecosistema Rust. Surgida cuando todavía no existía Cargo, esta librería está pensada para el desarrollo de juegos. No es la única que existe en Rust pero sí la más conocida. Piston es una librería que te enseñará Rust de la mejor forma. Y ahora quiero disculparme, porque Piston no es una librería, son un montón, pero eso lo veremos enseguida. En primer lugar creamos un proyecto nuevo con Cargo.

    cargo new --bin ejemplo_piston
    cd ejemplo_piston

    Ahora abrimos el archivo Cargo.toml, vamos a añadir las dependencias necesarias. Las dependencias en Piston son un poco complicadas, veamos:

    • Existen las dependencias core, implementan la API fundamental pero no pueden usarse por separado, son window, input y event_loop. Se usan a través de piston.
    • Los backends de window, existen actualmente 3 backends: glutin, glfw, sdl2. Se importan manualmente.
    • Graphics, una API 2D, no presente en core, pero al igual que las dependencias core necesita un backend.
    • Los backends de graphics son varios: opengl, gfx y glium.
    • Existe una dependencia que nos deja todo montado, piston_window. Esta trae por defecto el core de Piston, glutin, graphics y gfx.
    • Luego existen dependencias extra, como por ejemplo para cargar texturas, estas las podremos ir añadiendo según las necesite el proyecto.

    Para simplificar añadimos piston_window únicamente:

     

    [package]
    name = "piston_example"
    version = "0.1.0"
    authors = ["Adrián Arroyo Calle"]
    
    [dependencies]
    piston_window = "0.59.0"
    

     

    Ahora abrimos el archivo main.rs. Añadimos la crate de piston_window y los módulos que vamos a usar.

    extern crate piston_window;
    
    use piston_window::*;
    use std::path::Path;
    

     

    Así mismo definimos un par de cosas para el resto del programa, la versión de OpenGL que usará Piston internamente y una estructura para guardar los movimientos de teclado.

    const OPENGL: OpenGL = OpenGL::V3_1;
    
    struct Movement{
        up: bool,
        down: bool,
        left: bool,
        right: bool
    }
    

     

    En la función main podemos crear la ventana, especificando título y tamaño. Más opciones como V-Sync, pantalla completa y demás también están disponibles.

    fn main() {
    
        let mut window: PistonWindow = WindowSettings::new("Piston - Adrianistan",[640,480])
            .exit_on_esc(true)
            .opengl(OPENGL)
            .build()
            .unwrap();
    

     

    Ahora cargamos la tipografía Sinkin Sans, que vamos a usar para dibujar texto en pantalla. Como hay dos posibles localizaciones comprobamos esos dos lugares antes de salir del programa si no se consigue cargar la fuente.

        let mut glyphs = Glyphs::new(Path::new("SinkinSans.ttf"),window.factory.clone()).unwrap_or_else(|_|{
            let glyphs = Glyphs::new(Path::new("target/debug/SinkinSans.ttf"),window.factory.clone()).unwrap_or_else(|_|{
                panic!("Failed to open the font file. Check that SinkinSans.tff is in the folder");
            });
            glyphs
        });
    

     

    Inicializamos la estructura de movimientos, generamos las dimensiones iniciales del rectángulo (que será un cuadrado en este caso), su color y la posición del ratón.

        let mut mov = Movement{
            up: false,
            down: false,
            left: false,
            right: false
        };
    
        let mut dims = rectangle::square(50.0,50.0,100.0);
        let mut rect_color = color::BLACK;
    
        let mut mc: [f64; 2] = [0.0,0.0];
    

     

    Ahora viene la parte importante, el bucle de eventos. El bucle va a funcionar infinitamente generando eventos por el camino (pueden ser eventos de inactividad también). Usamos la función draw_2d para dibujar en 2D. Hay dos maneras de dibujar un rectángulo, en primer lugar tenemos la forma abreviada y en segundo lugar una más completa que permite más opciones. Por último dibujamos el texto usando la fuente y realizando una transformación para que no quede el texto en la posición 0,0.

     while let Some(e) = window.next() {
            window.draw_2d(&e, |c, g| {
                clear([0.5, 0.5, 0.5, 1.0], g);
                rectangle([1.0, 0.0, 0.0, 1.0], // color rojo, rgba
                            [0.0, 0.0, 100.0, 100.0], // dimensiones
                            c.transform, g); // transormacion y donde se va a dibujar
    
                let rect = Rectangle::new(rect_color);
                rect.draw(dims,&c.draw_state,c.transform,g);
                text(color::BLACK,18,"¡Saludos desde Piston!",&mut glyphs,c.transform.trans(100.0,200.0),g); // aplicamos una transormacion, movemos las X 100 y las Y 200
            });
    

     

    A continuación vamos a tratar cada evento de forma independiente, como todos los métodos devuelven Option, hemos de usar esta sintaxis con Some. En primer lugar tenemos un UpdateEvent, que básicamente nos informa del tiempo delta transcurrido. Recomiendo usar este evento para realizar los cambios en las geometrías, en este caso para mover el rectángulo.

    if let Some(upd_args) = e.update_args() {
                let dt = upd_args.dt;
                
                    if mov.right {
                        dims[0] += dt*100.0;
                    }
                    if mov.left {
                        dims[0] -= dt*100.0;
                    }
                    if mov.up {
                        dims[1] -= dt*100.0;
                    }
                    if mov.down {
                        dims[1] += dt*100.0;
                    }
            }
    

    Los siguientes dos eventos son opuestos, uno se activa cuando pulsamos una tecla y el otro cuando la soltamos. Comprobamos la tecla y modificamos la estructura movement en consecuencia.

    if let Some(Button::Keyboard(key)) = e.press_args() {
                if key == Key::W {
                    mov.up = true;
                }
                if key == Key::S {
                    mov.down = true;
                }
                if key == Key::A {
                    mov.left = true;
                }
                if key == Key::D {
                    mov.right = true;
                }
            };
            if let Some(Button::Keyboard(key)) = e.release_args() {
                if key == Key::W {
                    mov.up = false;
                }
                if key == Key::S {
                    mov.down = false;
                }
                if key == Key::A {
                    mov.left = false;
                }
                if key == Key::D {
                    mov.right = false;
                }
            };
    

    Por último, si queremos comprobar clicks del ratón hacemos algo similar. He añadido código para que cambio el color del rectángulo si pulsamos sobre él.

    if let Some(Button::Mouse(mb)) = e.release_args() {
                if mb == MouseButton::Left {
                    let x = mc[0];
                    let y = mc[1];
                    if x > dims[0] && x < dims[0] + dims[2] { if y > dims[1] && y < dims[1] + dims[3] {
                            rect_color = if rect_color == [1.0,0.0,0.0,0.7]{
                                [0.0,1.0,0.0,0.7]
                            } else if rect_color == [0.0,1.0,0.0,0.7] {
                                [0.0,0.0,1.0,0.7]
                            } else{
                                [1.0,0.0,0.0,0.7]
                            }
                        }
                    }
                    
                }
            }
    

    A continuación un pequeño evento que guarda la última posición del ratón.

            if let Some(mouse_cursor) = e.mouse_cursor_args() {
                mc = mouse_cursor;
            }
        }
    }
    

     

    Y con esto ya tenemos hecho un ejemplo en Piston.

    Si quieres tener un ejecutable para Windows sin que se muestre primero la consola debes compilar la versión que vas a distribuir con unos parámetros especiales. Si usas Rust con GCC usarás:

    cargo rustc --release -- -Clink-args="-Wl,--subsystem,windows"

    Si por el contrario usas Visual C++:

    cargo rustc --release -- -Clink-args="/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"

     

    Piston todavía se encuentra en fuerte desarrollo, en la API estan documentados todos los métodos pero aun así muchas veces no se sabe como hacer ciertas cosas. Piston soporta además 3D, contando con una librería especializada en vóxels. Veremos como evoluciona esta librería.

    La entrada Tutorial de Piston, programa juegos en Rust aparece primero en Blog - Adrianistan.eu.

    Miércoles 11 de enero de 2017

    Pedro L. Lucas

    Pedro L. Lucas
    Cartas de Linux

    Creando un archivo que se puede leer desde Linux pero no desde Windows

    Hace poco, por accidente, creé una archivo que se podía manejar desde Linux, pero Windows no podía con él. La cuestión es bastante sencilla:

    Windows usá los dos puntos “:”, para identificar unidades, como por ejemplo, C:, D:, G:,… Por lo tanto el símbolo : no debería usarse en Windows para poner nombres a ficheros.

    En mi caso en el nombre del fichero había puesto una hora en el formato: “20:30:00”. Claro, el separador era “:”.

    Al llegar a Windows, me encontré que el navegador de ficheros lo listaba pero no lo podía abrir. Daba igual la aplicación que intentase usar. Para colmo el mismo error se producía si intentaba renombrar el archivo desde Windows.

    ¿La solución? En mi caso me fue más sencillo volver a Linux y cambiar el nombre del archivo.


    Domingo 08 de enero de 2017

    David Moreno

    David Moreno
    dm's blog

    Thanks Debian

    I sent this email to debian-private a few days ago, on the 10th anniversary of my Debian account creation:

    Date: Fri, 14 Aug 2015 19:37:20 +0200
    From: David Moreno 
    To: debian-private@lists.debian.org
    Subject: Retiring from Debian
    User-Agent: Mutt/1.5.23 (2014-03-12)
    
    [-- PGP output follows (current time: Sun 23 Aug 2015 06:18:36 PM CEST) --]
    gpg: Signature made Fri 14 Aug 2015 07:37:20 PM CEST using RSA key ID 4DADEC2F
    gpg: Good signature from "David Moreno "
    gpg:                 aka "David Moreno "
    gpg:                 aka "David Moreno (1984-08-08) "
    [-- End of PGP output --]
    
    [-- The following data is signed --]
    
    Hi,
    
    Ten years ago today (2005-08-14) my account was created:
    
    https://nm.debian.org/public/person/damog
    
    Today, I don't feel like Debian represents me and neither do I represent the
    project anymore.
    
    I had tried over the last couple of years to retake my involvement but lack of
    motivation and time always got on the way, so the right thing to do for me is
    to officially retire and gtfo.
    
    I certainly learned a bunch from dozens of Debian people over these many years,
    and I'm nothing but grateful with all of them; I will for sure carry the project
    close to my heart — as I carry it with the Debian swirl I still have tattooed
    on my back ;)
    
    http://damog.net/blog/2005/06/29/debian-tattoo/
    
    I have three packages left that have not been updated in forever and you can
    consider orphaned now: gcolor2, libperl6-say-perl and libxml-treepp-perl.
    
    With all best wishes,
    David Moreno.
    http://damog.net/
    
    
    [-- End of signed data --]
    

    I received a couple of questions about my decision here. I basically don’t feel like Debian represents my interests and neither do I represent the project – this doesn’t mean I don’t believe in free software, to the contrary. I think some of the best software advancements we’ve made as society are thanks to it. I don’t necessarily believe on how the project has evolved itself, whether that has been the right way, to regain relevancy and dominance, and if it’s remained primarily a way to feed dogmatism versus pragmatism. This is the perfect example of a tragic consequence. I was very happy to learn that the current Debian Conference being held in Germany got the highest attendance ever, hopefully that can be utilized in a significant and useful way.

    Regardless, my contributions to Debian were never noteworthy so it’s also not that big of a deal. I just need to close cycles myself and move forward, and the ten year anniversary looked like a significant mark for that.

    Poke me in case you wanna discuss some more. I’ll always be happy to. Specially over beer :)

    Peace.

    Miércoles 21 de diciembre de 2016

    Juanjo Amor

    Juanjo Amor
    DrAmor's Blog

    Acabemos con los intersticiales

    ¡Interstitials!

    Vaya palabro. “Interstitials”. Intersticiales en español. Anuncios intersticiales; que para la RAE serían aquellos que ocupan los intersticios, pero que, realmente, son anuncios que ocupan toda la pantalla y son especialmente molestos porque,

    • Impiden visualizar la página que queremos ver. Vamos, que molestan, y mucho más, que los pop-ups de toda la vida.
    • Incitan al click fraudulento: La mayor parte de las veces que pulsamos sobre el anuncio, no es para acceder al producto anunciado sino para cerrar el mismo. El botón para cancelarlo suele requerir de una especial destreza (o puntería) del usuario sobre su pantalla multitáctil… a menos que tengas los dedos del tamaño de la cabeza de un alfiler.

    Anuncio Intersticial, imagen de Google

    Pues bien, hace ahora más de 4 meses, Google anunció que iba a penalizar el uso de anuncios intersticiales en las búsquedas desde móvil a partir de enero de 2017, algo que ya está a la vuelta de la esquina.

    Es bueno recordarlo porque, a día de hoy, la mayor parte de las páginas de actualidad en Internet siguen incorporando este tipo de anuncios como si nada, haciendo muy incómoda la lectura, sobre todo en móviles, donde deshacerse del anuncio resulta complicado y por lo que, muchas veces, un servidor decide abandonar el medio de comunicación elegido para irme a uno alternativo que me informe más y me moleste menos.

    Aún me queda la esperanza de que esta penalización del buscador realmente consiga su efecto. Mientras tanto, seguiremos haciendo uso extensivo y abusivo de los bloqueadores de anuncios, pese a los avisos de determinados medios de que eso les hace daño.

    Lunes 05 de diciembre de 2016

    Emiliano A. González Salgado

    Emiliano A. González Salgado
    El blog de Emi

    Error al inicio de Linux debido a CUPS

    Uso Fedora 25 KDE. Desde hace tiempo y, con varias versiones anteriores. se está produciendo el mismo fallo al inicio del sistema.

    Para ver los errores que se han producido en el inicio de sesión, en los sistemas que incorporan Systemd, hay que teclear el comando:

    [root@HOST-PC ~]# journalctl -b -p err

    Uno de los que estaba arrojando últimamente era:
    cupsd[1213]: Missing value on line 11 of /var/cache/cups/job.cache.

    Los números 1213 y 11 pueden variar. El primero debe ser un índice de Journal (el registro de logs de Systemd) y el segundo hace referencia a la línea del fichero job.cache que produce el fallo.

    Es este caso era debido a que cups-pdf (la impresora virtual) al crear un fichero no le asignó un nombre en el archivo job.cache.

    Intenté borrar la caché de Cups desde el administrador de impresión (system-config-printer), pero no se encontraban trabajos pendientes ni terminados. También desde la interfaz web del servidor cups: http://localhost:631/jobs?which_jobs=all

    No era posible. No se podía borrar. Incluso eliminé el contenido de  job.cachecon un editor de texto, pero al volver a iniciarse el contenido estaba otra presente, así como el error se reproducía.

    Al final la solución llegó a través de la consola.

    Los comandos a ejecutar son:

    Parar Cups:

    [root@HOST-PC ~]# systemctl stop cups.service

    Ver la lista de trabajos completados:

    [root@HOST-PC ~]# lpstat -W completed -o

    Ver la lista de trabajos no completados:

    [root@HOST-PC ~]# lpstat -o

    Eliminar todos los trabajos:

    [root@HOST-PC ~]# cancel -a -x

    Esto cancelará todos los trabajos.

    Editar el fichero  /var/cache/cups/job.cache, borrar el contenido y guardar de nuevo.

    por ejemplo con nano como root

    [root@HOST-PC ~]# nano /var/cache/cups/job.cache

    Reiniciar el sistema y ver si se ha solucionado el fallo.

    SI las respuestas dadas aquí no funcionan:

    ps aux | grep printer kill {printer job}

    Este último comando no lo he probado. con lo anterior fue suficiente.

    Un saludo,

    Emiliano

     


    Jueves 01 de diciembre de 2016

    Luis Vilchez

    Luis Vilchez
    El blog de Jabba

    Pillars of Eternity, el heredero espiritual de Baldur's Gate para OSX y Linux

    Hablar de Baldur’s Gate es hablar del gran clásico entre los clásicos de los juegos de rol computerizado. Su legado y su influencia están muy presentes en gran cantidad de los títulos que conforman el panorama del videojuego actual. Un juego con una profundidad, libertad y capacidad de personalización nunca vistas hasta entonces. Un juego que muchos tenemos como uno de los mejores -sino el mejor- RPG de la historia.


    Quince años después Pillars of Eternity pretende devolvernos la magia, la ambientación, la jugabilidad y esa aura cautivadora y mítica propia de los grandes clásicos del género; un deleite para los sentidos de los veteranos en los juegos de rol y una experiencia inigualable para los recién llegados. Me han bastado unas semanas perdiéndome virtualmente por el mundo de Eora para confirmar que Pillars of Eternity es la oportunidad de volver a revivir un JUEGAZO infinity engine de corte clásico como los de antaño. Un juego que rezuma a Baldur's Gate del bueno por los cuatro costados. ¿Y sabéis lo mejor? Con versiones nativas para OSX y... ¡Linux!

    Es de recibo decir que gran parte de la culpa de todo esto la tienen los fans y el modelo kickstarter que sus creadores usaron para financiar el proyecto (por aquel entonces bajo el nombre de Project Eternity). El resultado ha sido un RPG de corte occidental distribuido por Paradox Interactive y desarrollado por Obsidian Entertainment, creadores de sagas como Fallout, IceWind Dale o Neverwinter Nights, además del citado Baldur’s Gate.

    Como en Baldur's Gate, la primera cosa que hay que hacer en Pillars of Eternity es crear un personaje. Aspectos como las diferentes ventajas e inconvenientes de cada raza, los atributos, las clases, las limitaciones de atributo por clase, las alineaciones morales, las habilidades complementarias, afinidad de armas, selección de conjuros, clases duales... habrá que tenerlos muy en cuenta antes incluso de comenzar la "aventura". Y seguramente no es el sistema de creación de personajes más amplio de la historia del género, pero sí es MUY completo. Incluso me atrevo a decir que podrá parecer algo complejo para los recién llegados pero hará las delicias de los veteranos del género. A fin de cuentas aprender forma parte de la esencia del rol y eso pasa por cosas como la creación de nuestro personaje. A continuación os dejo un vídeo para que lo veáis en acción.


    En otras plataformas no sé, pero en Linux sin duda estamos ante el juego del año :)

    Miércoles 30 de noviembre de 2016

    Raúl González Duque

    Raúl González Duque
    Linux – Mundo Geek

    Cómo crear un pendrive USB bootable con Ubuntu en Windows

    Tener un USB con Ubuntu siempre listo en el bolsillo puede ser muy útil para solucionar problemas con Windows, eliminar virus, realizar operaciones seguras en Internet, o simplemente para jugar un poco con Linux.

    Para crear una unidad USB arrancable con Ubuntu me gusta utilizar Rufus, que es gratuita, muy ligera, rápida y cuenta con versión portable. Además de Rufus, sólo necesitaremos una ISO de Ubuntu y un pincho USB con al menos 2GB de espacio, que debe estar vacío, o no importarte mucho su contenido, porque se formateará durante el proceso.

    Conecta el pincho USB a tu equipo y ejecuta Rufus.

    En “Dispositivo” selecciona tu pincho USB.

    Marca la opción “Crear disco de arranque con:”, selecciona “Imagen ISO”, y haz clic sobre el icono del CD Rom para abrir un diálogo en el que buscar la imagen ISO que has descargado

    USB booteable Ubuntu

    Pulsa el botón “Empezar”. Te avisará de que necesita descargar un par de archivos de Internet, pulsa en “Sí”.

    Cuando te pregunte por el modo de escritura de la imagen, selecciona “Escribir en modo Imagen ISO (Recomendado)”.

    A continuación te avisará de que va a proceder a formatear el dispositivo USB. Haz clic en “Aceptar” para empezar el proceso.

    Martes 08 de noviembre de 2016

    Raúl González Duque

    Raúl González Duque
    Linux – Mundo Geek

    ¿Cuántos usuarios de Linux se necesitan para cambiar una bombilla?

    Sea merecida o no, lo cierto es que los usuarios y desarrolladores de GNU/Linux tenemos fama de arrogantes, extremistas y de perdernos en los detalles. Desde el Proyecto GNU se toman con humor estos estereotipos calculando cuántos usuarios de Linux se necesitarían para cambiar una bombilla.

    • 1 para publicar un hilo en la lista de correo informando de que la bombilla se ha fundido
    • 1 para sugerir reiniciar la bombilla usando la línea de comandos
    • 1 para quejarse de que el usuario rompiera la bombilla
    • 1 para preguntar qué bombilla se debería instalar
    • 1 para aconsejar que no se use la palabra “fundida” para referirse a una bombilla rota, porque puede interpretarse que la bombilla se ha prendido fuego, en lugar de haberse estropeado por un exceso de corriente eléctrica
    • 25 para sugerir todos los tipos de bombilla imaginables
    • 5 para para decir que la bombilla fundida es un fallo de origen
    • 1 novato para sugerir instalar una bombilla de Microsoft
    • 250 usuarios para inundar el correo del susodicho novato
    • 300 para decir que la bombilla de Microsoft se pondría azul y tendrías que reiniciarla constantemente para que volviera a funcionar
    • 1 antiguo usuario de GNU/Linux, que todavía frecuenta el foro, para sugerir una iBombilla de Apple, que tiene un diseño fresco e innovador y sólo cuesta 250$
    • 20 para decir que las iBombillas no son libres, y que tienen muchas menos funcionalidades que una bombilla estándar 20 veces más barata
    • 15 para sugerir una bombilla nacional
    • 30 para decir que las bombillas nacionales son copias de las bombillas extranjeras y que no ofrecen nada nuevo
    • 23 para discutir si la bombilla debe ser blanca o transparente
    • 1 para recordar a todo el mundo que el nombre correcto es GNU/Bombilla
    • 1 para decir que las bombillas son sólo para usuarios de Window$ y los usuarios de GNU/Linux de verdad no tienen miedo a la oscuridad
    • 1 para anunciar finalmente el modelo de la bombilla elegida
    • 217 para descartar el modelo escogido y sugerir otro
    • 6 para quejarse de que el modelo elegido tiene elementos propietarios, y que debería usarse otro
    • 20 para decir que una bombilla 100% libre sería incompatible con el interruptor
    • Los mismos 6 anteriores para sugerir cambiar el interruptor por uno compatible
    • 1 para chillar “¡DEJAD DE DISCUTIR Y CAMBIAR LA P*#@!%¡# BOMBILLA DE UNA VEZ, POR EL AMOR DE DIOS!”
    • 350 para preguntar al usuario anterior a qué Dios se refiere, y si tiene pruebas empíricas de su existencia
    • 1 para explicar cómo funciona la electricidad y por qué una bombilla eléctrica es ineficiente
    • 1 para decir que no se puede confiar en una bombilla fabricada por una corporación y que deberíamos confiar en bombillas hechas por la comunidad
    • 1 para publicar un enlace a un archivo ODF explicando cómo construir una bombilla desde cero
    • 14 para quejarse del formato del archivo anterior, pidiendo que se envíe en txt o LaTeX
    • 5 para decir que no les gustó la decisión y van a hacer forks de la instalación eléctrica de la casa para instalar una lámpara mejor
    • 1 para publicar una serie de comandos a introducir para cambiar la bombilla
    • 1 para comentar que ejecutó los comandos y obtuvo un mensaje de error
    • 1 para aconsejar que los comandos deberían ejecutarse como root

    Y finalmente:

    • El padre del usuario original, que mientras todos estaban discutiendo, se acercó a la tienda y compró la bombilla más barata que vendían

    Lunes 07 de noviembre de 2016

    Raúl González Duque

    Raúl González Duque
    Linux – Mundo Geek

    Los 10 comandos más útiles de Linux

    CommandlineFu es una web donde los usuarios pueden enviar sus comandos Linux favoritos, añadir comentarios, y votar los comandos enviados por otros usuarios; un recurso imprescindible si queréis convertiros en verdaderos expertos en el uso de la consola. Y para muestra, un botón: estos son los 10 comandos más votados por sus usuarios.

    sudo !!

    Ejecuta el último comando introducido como root.

    python -m SimpleHTTPServer

    Inicia un servidor web que sirve los archivos del directorio actual en http://localhost:8000

    ^foo^bar

    Ejecuta el último comando, reemplazando el texto “foo” por “bar”

    Ctrl + X, Ctrl E

    Invoca un editor de textos en el que poder escribir el comando que vamos a ejecutar. El comando se ejecutará una vez se cierre el editor

    Alt + .

    Inserta el último argumento utilizado en el punto en que esté situado el cursor

    reset

    Resetea la consola

    mount | column -t

    Muestra los puntos de montaje actuales con un formato amigable para la lectura

    echo “ls -l” | at midnight

    Ejecuta un comando en el momento indicado

    curl ip.appspot.com

    Descarga el documento de http://ip.appspot.com para mostrar la IP externa del equipo

    man ascii

    Muestra la página de ayuda con la tabla de caracteres ASCII

    Domingo 30 de octubre de 2016

    Marcelo Fortino

    Marcelo Fortino
    Fortinux

    Tutorial usar git-annex para sincronizar archivos entre dispositivos GNU/Linux

    Tutorial usar git-annex como repositorio de archivos Una forma de tener nuestros archivos sincronizados entre el notebook, desktop y otros dispositivos es usar como herramienta git-annex. Git-annex gestiona archivos con Git sin verificar el contenido de los mismos. Esto permite trabajar con archivos grandes usando repositorios sincronizados.

    Martes 18 de octubre de 2016

    わき毛の抜毛には女性の大きな関心事だ。幾ら素敵な装い

    わき毛の抜毛にはマミーの大きな関心事だ。
    幾ら素敵な装いをし立としても、傍らのむだ毛が伸びていたら、ガッカリですね。
    好感触に感じていた輩も瞬く間にきらいになってしまうかも知れません。
    薄着の季節では余計に傍ら後が開いた洋服が多くなりますし、自分で処理をすると皮膚が炎症を起こしたりして余計な不便まで秘める片付けになります。
    抜毛店舗実践のお値段ですが、いつの抜毛店舗かで予算は違ってきますし、希望の抜毛要素次第で移り変わるでしょう。
    大手の抜毛店舗でよく言えるようなお得なキャンペーンの利用によって、案外低料金の抜毛が可能になる場合もあるでしょう。
    またワキや拳固など抜毛ニーズ部位ごとに通うお店を取りかえる、つまり抜毛要素それぞれでちがう抜毛店舗に通うようにするといった華奢に抜毛が進められそうです。
    また一つのお店だけを利用するのに比べてリザーブを格段に取り去り易く罹るのもうれしい部分だ。
    経済的に無理なく抜毛しようと、最初から抜毛器で自己処理やる分と抜毛店舗に任せるパイと、区別してある輩もある。
    適性もありますが、自家用の抜毛器を上手に使えば、各回、抜毛のために抜毛店舗を予約しなくてもすむでしょう。
    厳しい部分は抜毛店舗で施術してもらい、そのほかの部分は抜毛器で自己処理やる為す。
    但し抜毛器もそれなりの性能のものでないとその抜毛器による店だけムダ毛余りしてしまう結果、購入前のプレ認証は不可欠です。
    カラダ抜毛をしたら、ムダ毛のお手伝いを自分でするわずらわしさから解放され、処置がヤバイ楽になる事は確実です。
    但し、お金が幾らくらい陥るのか、ムダ毛はどのくらいきれいになるのか事前に調べておきましょう。
    カラダ脱毛するお店や店舗にて、抜毛作用やそのために加わる費用が非常に違ってきます。
    むだ毛の抜毛の手当て方法の中で、ニードル法は無限抜毛作用が最も期待できる抜毛法だと思われます。
    今は病院です抜毛病舎や一部の抜毛店舗でしか行われていない抜毛法だ。
    著しい痛みがあるので、興味はレーザー抜毛の方が高いようですが、大きい効果が期待できる結果、この方法をわざと選ぶ人も少なくないようです。
    間違って認識してる輩もいるようですが、店舗をめぐってもツルッパゲスキンになるまで、一度や二都度の手入れで抜毛が完了し立とは言えません。
    抜毛を受ける要素にても変りますが、おおまかに言って、6回から18回ほど抜毛を受ける人が多いようです。
    ですが、スキンへの恐怖によって、手入れを受けた数日後にまた抜毛が行なえる所以ではなく、頭髪回転の階級が二ヵ月なので、それくらいのスパンを空けて伺うのが最適です。
    ただただ「抜毛」と言ってもこのように長期戦になる結果、売店が多いなどで利用しやすい店舗で行ないましょう。
    できるだけ抜毛代金を安く終えるために、破格値の抜毛店舗を探している輩は少なくないです。
    ただし激安予算ばかりが売りの抜毛店舗は無事故や浄化をおろそかにしているかも知れません。
    低価格なパイ、普通の回数ではほとんど効果が出ないとか、スキンを傷める結果になっては給与も損害ですが、かけた日数ってスキンは戻って来ないでしょう。
    スキンを傷めたらムダ毛手当ては当分できません。
    予算の低廉さばかりを代物にする抜毛店舗の場合はあらかじめ評価や手答えをチェックしておいた方がいいでしょう。
    きれいに脱毛するには少々抜毛店舗に通うことになりますから、自分に当てはまるリザーブ切り口があるか確認してから契約するべきです。
    立とえばリザーブ切り口が連絡のみの抜毛店舗だと忙しさにかまけているとリザーブ電話をかけるのが後回しになりがちだ。
    リザーブがタブレットから叶う抜毛店舗だったら、単なる合間に予約できるので、心づもりをずらす必要がありません。
    綺麗に抜毛しようと思ったら、抜毛店舗に何度となく乗り物を運ばなければなりませんから、手入れのリザーブが取り易いかどうかは店舗選びの重大要素のひとつです。

    Lunes 17 de octubre de 2016

    家屋でのムダ毛加工はヘビーな操作だ。剃ろうにもビデオラ

    住宅でのムダ毛作製はヘビーな工程だ。
    剃ろうにも映像路線や背中は上手くできなかったり、毎日ムダ毛のお手入れをするのは煩わしくて疲れたり、問題に感じている方もいるのではないでしょうか。
    抜け毛店舗を利用すれば、たえず苦労しているフィールドの抜け毛も平安、自宅での作製のもめごとも気にしなくてよくなります。
    体内抜け毛店舗はたくさんありますが、抜け毛で失敗し立と感じないためには、じっさいに体内抜け毛を先輩のクチコミを聞いてみるのが一番良いでしょう。
    感想は自身によるの部分はありますが、誰もがいいという店舗は粗方決まってくる。
    重要視するのは出来ばえや早さですとか、やはり短いのが有難いとか、自分が抜け毛でやはり重視する主題を決めておくってきっと納得できるはずです。
    妊婦様であれば、多くの抜け毛店舗ではメンテナンスを行ないません。
    懐妊内輪はホルモンの不調でメンテナンスを通じても抜け毛の効力が出にくかったり、神経質になっているスキンは、少しのモチベーションも荒れてしまうからだ。
    抜け毛が完了していないうちに懐妊のリサーチが出てきたら、店舗によっては産後2ヶ月ぐらいまで休会ができる店舗もあるので申込む前にそぐういう通り道や制度を確認しましょう。
    抜け毛料金がサラリー制のところもありますから、一通りの抜け毛承認までに総額が予見できずに困ってしまっ立という自身も要るかも知れません。
    体内抜け毛総額確認の際には、抜け毛フィールドといった抜け毛承認までに陥る値段を比べて、メンテナンスのアポイントメントを入れ易い店舗を選ぶことも重要なのです。
    どんどん一度の抜け毛で全てのパートを施術して得る店舗ならひときわ容易でしょう。
    指のムダ毛は凄く自身には映るものです。
    他人のしかたを見ればわかりますが、例えネイルやかざりで盛装していても、指頭髪があるという冴えない自身認定されてしまう。
    指のお手入れの基本としてムダ毛作製を抜け毛店舗で講じる側は以前からすごく多いのです。
    しかたや指のように表皮の無い部分は考えも素晴らしいので、抜け毛手法は事前にぐっすり検討したほうがよいでしょう。
    見立て抜け毛は効力が持続するかわりに痛みを伴うので、低モチベーションの光線抜け毛様式を施術するのが一般的なようです。
    出向ける場所に一種しか仕事場がない場合はレンジがありませんが、仕事場が沢山あれば、各仕事場の詳細などを比較してから、抜け毛店舗を選択するという良いでしょう。
    では、効力、総額、アポイントメントの取り方、姿勢行為などをサイトなどの人づてなどを見て確認しなければならないことが山ほどあります。
    いくつか選択をサイトなどで通り道や人づてにおいて選んでから必ず、自分自身に合っているのか、事実通り道にあたって判断しましょう。
    ニードル抜け毛は何かと障害が多いと言います。
    最近のレギュラーな抜け毛法ではないのでほとんど知られていない手法なのかもしれませんが、ニードル抜け毛にはひどくの痛みがあるのです。
    もう一度、毛孔の全てに針をより刺していくのです極の時間がかかります。
    痛みがある上に長時間のメンテナンスが必須となるって、それなりに障害も多くなってくるのだと思います。
    華奢ゾーンの抜け毛を抜け毛店舗ですると、キレイな出来ばえだったし、肌荒れが起きにくいといわれています。
    ただし、抜け毛店舗の全てがVIO抜け毛が出来ない場合もあるのでウェブサイトなどで確認してから行きましょう。
    華奢ゾーンの抜け毛は気まずいという方も、よくいますが、同性それぞれですし、ベテランが行なうほうが自分で行うからセキュリティだ。

    Domingo 16 de octubre de 2016

    Marcelo Fortino

    Marcelo Fortino
    Fortinux

    Tutorial instalar Plone CMS en Ubuntu server

    En este tutorial veremos como podemos instalar el gestor de contenidos Plone en un servidor Ubuntu 14.04 o 16.04. Plone es un gestor de contenidos basado en el servidor de aplicaciones Zope que es bastante utilizado como Intranet en gobiernos y empresas, entre ellos, el gobierno brasileño, la universidad de Oxford (Reino Unido) o Google.

    仮に代価に余裕があるなら、その代価で抜毛ショップの加療

    もしも財貨に余裕があるなら、その財貨で抜け毛店先の施術費用を払って仕舞うのもありです。
    資金で支払うのですから、あとでカードの支払いお日様も気になりません。
    ただし、仮に資金が手もとにあって高額な先払いをしてしまうと、途中で通えない原因ができ立ときは空白分の精算が必要になります。
    それに、抜け毛店先そのものが潰れたら、先払いしてあった分だけ損をすることになります。
    少額だったり、そのつど払う場合は資金支払いも良いですが、そこそこの金額に繋がるようならカード支払いをお薦めします。
    月々定額(月収制)の抜け毛店先の場合、清算が明確なので気軽に抜け毛できるのでお薦めです。
    とはいえ体の一端しか抜け毛したくないときは、月収制を選ぶというかえってロスかも知れません。
    発毛周期を見ながら脱毛するので、もし1ポイントだけなら隔月に一度の抜け毛になるからだ。
    そのかわり、思いポイントが多いほど月収制による有難みがあるといえるだと言えます。
    ご自身の場合はどうしたいかを明確にして、ピッタリ合う抜け毛店先によるっていいだと言えます。
    「ムダ毛の憂慮」で多くの人が走り込む抜け毛スパのランキングには、大御所エステティックサロンのTBC、エルセーヌなどのエースがデイリー、上位に食い込んでいらっしゃる。
    これとは別に、抜け毛店先をこういうランキングに含めたタイミング、たとえば、ミュゼプラチナム、シースリー(C3)、抜け毛研究所、等々が上の順番に名称を連ねます。
    人気といえば、ピュウベッロやキレイモなどもあります。
    その中には、要望する抜け毛フィールドを通じてもくろみごとに分けて向かう方もいらっしゃる。
    何とか抜け毛スパに通うとすると、気にならなくなるまで脱毛するなら12回等前文向かう必要があるようです。
    気になるフィールドが上腕や脚等、他とくらべて分厚く無いポイントであるならば、5、6回の施術で感動する方もあるだと言えます。
    ただし、横やアンダーヘア等の眼たつ濃い毛が生えてしまってあるところは、ベイビー(ベイビーが生まれるまでは乳幼児好きじゃなかった方も、自分の乳幼児が産まれてみると、ベイビーがかわいくて仕方がないということがよくあるみたいです)のお肌の様なツルッとしたお肌にしようとすると、上腕や脚等の二ダブルは施術回数が必要になるケースと思います。
    皮膚がデリケートであるヤツですと剃刀負債が発生することがあるだと言えます。
    そういう人におすすめしたいのが抜け毛店先における灯抜け毛だ。
    これならば、アトピー風習の人も安全に施術をうけることが出来る為す。
    横の抜け毛に耐えるのだったら、ぜひ試してちょうだい。
    駅前駅近で目にする行いの多い抜け毛店先ですが、ムダ毛と呼ばれる体の邪魔な毛に、美専用の電気道具などを使用し、ムダ毛が出現するチェーンを遅らせたり、発毛しないように治療をするおみせのことです。
    以前は抜け毛製作というとエステでするというのが一般的なスタンスでしたが、抜け毛にもハイテクノロジーが普及した現在では短時間で効率的に抜け毛できるようになった事で抜け毛というサービスに限定して商売始めるサロンの飛躍的な繁殖につながったりゆうだ。
    ほとんどの女性がムダ毛製作を考え始めるのは温暖な春から初夏程だ。
    皮膚が周囲にふれる機会が多くなりますし、歩き、上腕のムダ毛だけでなく横などもプロフェショナルにきれいにしてもらいたいといった指し初めるのです。
    とくにいよいよ顧客はこの時期が多く、抜け毛店先が大混雑始めるぐらいですし、貸し賃は安くありません。
    貸し賃が短いのは、温度が薄くなり皮膚の登場がなくなる年代だと言えます。
    抜け毛だけでなく益々まとまりたいヤツはジェイエステティックが良いだと言えます。
    美顔、シェイプアップスパ、美貌脚も揃えたすべて美店先だ。
    一般の抜け毛店先みたい、灯方式の抜け毛を取り扱っています。
    格安で同店の美肌抜け毛を体験できるお試し教科も用意され、サロン単位の設定もスムーズなのがジェイエステティックのウリだ。
    サロンは全国に100サロン以上あり、思わぬところにおみせがあったり決める。
    もしも近くに支店があったら、キャリア教科などで様式を探るのもいいかも知れませんね。

    Lunes 29 de agosto de 2016

    David Moreno

    David Moreno
    dm's blog

    Webhook Setup with Facebook::Messenger::Bot

    The documentation for the Facebook Messenger API points out how to setup your initial bot webhook. I just committed a quick patch that would make it very easy to setup a quick script to get it done using the unreleased and still in progress Perl’s Facebook::Messenger::Bot:

    use Facebook::Messenger::Bot;
    
    use constant VERIFY_TOKEN => 'imsosecret';
    
    my $bot = Facebook::Messenger::Bot->new(); # no config specified!
    $bot->expect_verify_token( VERIFY_TOKEN );
    $bot->spin();
    

    This should get you sorted. What endpoint would that be, though? Well that depends on how you’re giving Facebook access to your Plack’s .psgi application.