sábado, 14 de junio de 2014

Cómo ver algunos partidos sin flash

Nota posteriror: Estoy funciona, salvo que por lo menos en mi caso, la conexión a el sitio web que da el streaming de video se vuelve *muy* lenta cuando hay un partido, así que no lo puedo ver. Sin embargo, queda acá por si alguien quiere mirar otros programas, o tiene una mejor conexión .

----

Hola,

    Ayer estuve viendo cómo ver los partidos del mundial por canal 7 (y mirá que no dije ATC) sin usar el navegador. En linux, el plugin de flash funciona lento, así que quería verlo con un programa específico para mirar videos, como mplayer o vlc.

    Resulta que para usan un protocolo llamado "HDS". Les contaría de qué se trata, pero no tengo ganas. En definitiva, hay que usar el script AdobeHDS.php que se puede bajar acá. El script necesita la URL del archivo "manifest", que es el que describe de dónde bajar el stream de video, y el contenido del encabezado "Referrer" del pedido HTTP.

    Para encontrar la URL y el valor del encabezado, yo usé firefox, así: 
  • Abrir el sitio web donde está la señal del canal para ver.
  • Abrir la pantalla de información sobre el tráfico de red, yendo a Tools -> Web Developer -> Network, o apretando Ctrl + Shift + Q.
  • En el navegador, poner a ejecutar el stream de video.
  • Hacer click con el botón derecho sobre la línea del archivo "manifest". Elegir "Copy URL". En la imagen, la línea correspondiente.



  • Hacer click con el mouse sobre esa misma línea. Aparecerá un panel a la derecha:



  • Buscar en ese panel, bajo el título "Request headers", la línea que dice "Referrer", y copiar la URL que le corresponde.
  • Ejecutar AdobeHDS:php con los dos parámetros tal que guarde el video en un archivo:
 php AdobeHDS.php --manifest URL_del_manifest --referrer URL_de_Referrer --outfile partido.flv 
  • En otra terminal, ejecutar mplayer o el visor de videos que uno quiera.

Eso es todo. Tiene, sin embargo, algunas contras.

Primero, hay que elegir a mano la calidad. Si se elige una más alta de la se puede, el video se va a cortar, porque mplayer va a llegar al fin del archivo. Osea, mplayer le va a "ganar" a AdobeHDS.php. Con volver a ejecutar todo es suficiente, pero bien puede pasar.

El protocolo HDS está pensado para enviar video en tiempo real, evitando el buffering. Esta solución lo usa (el cache de mplayer), así que el video tiene una demora de unos segundos. Osea, que puede pasar que el vecino grite "¡Gol!" y el video empiece a mostrar la jugada. A mi me parece muy conveniente, así puedo distraerme de partidos aburridos y alguien me avisa cuando está por pasar algo interesante. Pero seguramente sea una contra para mucha gente.

Saludos
 -- Diego.



lunes, 26 de mayo de 2014

Cómo sacar algunos sigils ($@%&), parte 3

Algunas ideas que se me ocurrieron a partir de las dos entradas anteriores:

  • Podemos hacer que al declarar las variables en BEGIN, ya que estamos, le agreguemos un default.

BEGIN {
        var "espia" => "James Bond";
        var "jefe"    => "M5";
        var "familia_que_ignora_la_verdad"  => "No tiene";
}
Solo hay que cambiar un poco el corazón de todo esto:
# Esta es la subrutina que genera las demas.
sub var ($;$) {
        say "Creando $_[0]... Hecho!" if $debug;
        my $p = "main"; # El namespace esta fijo en "main". TODO.

        # Si la sub que queremos que exista se llamara "espia" esto de abajo
        # sería: *main::espia = sub ...
        # El segundo argumento, si hay, es el default de la "variable" / sub.
        no strict 'refs';
        *{"${p}::${_[0]}"} = sub (;$) :lvalue {
                state $internal = "**internal**";
                if ( $_[0] ) { $internal = $_[0]; }
                return $internal;
        };
        &{"${p}::${_[0]}"} = "$_[1]" if $_[1];
        use strict;
}


  • También podríamos poner otras opciones en las definiciones:

BEGIN {
        var "nombre" => "NN", validate => { $_[0] !~ /admin|root/i };
        var "jefe"    => "M5",     validate => { $_[0] != nombre };
        var "edad" => 1, max => 18;
}
  • También podríamos poner otros nombres en vez de var, con otros restrains:

BEGIN {
        var "nombre" => "NN", validate => { $_[0] !~ /admin|root/i };
        bool "es_jefe"    => "true",     validate => { ... };
        int "edad" => 1, max => 18;
}
 Ya estoy delirando, porque para eso debe haber varios módulos hechos por gente que sabe más que yo :) Pero este, "casero", tiene muy pocas líneas de código.

Saludos!
 -- Diego.





domingo, 25 de mayo de 2014

Cómo sacar algunos sigils ($@%&), parte 2

Buenas! En la entrada anterior habíamos llegado a poder escribir una variable sin sigil, así:


boo = "Cuidado!!";
print boo . ", te vas  a caer de las escaleras!\n";

(estas "variables" en realidad son subrutinas, pero nadie tiene porqué saberlo :D Vamos a llamarlas variables igual, o a lo sumo "nuestras variables especiales", porque les tenemos mucho cariño).

Hay que declarar cada una de las variables como una subrutina. Un montón de copiar y pegar de código, repetido y dificil de mantener. Y ¡ay! si tenés que hacer algún cambio.

¿Se puede hacer más dinámico? No perfectamente como yo hubiera querido, pero zafa bastante bien.

Necesitamos primero definir cada variable con "var". Var no es más que una subrutina, que va a generar nuestra "variable especial".
var "espia";
var "amante_de_espia";
y luego podemos usarlas:
espia = "James Bond";
amante_de_espia = "Mariam D'Abo";
say "Mi nombre es " . espia ", y me acuesto con " . amante_de_espia;
Ningún sigil. ¡Genial!  ¿Cómo se hace? Es medio complicado, pero acá va:

"espia" y "amante_de_espia" son en realidad funciones (lo vimos en la primera parte), asi que "var" tiene que crearlas al vuelo. Para eso tiene que ponerlas en el mismo namespace, osea, al mismo nivel que el programa principal.
sub var ($) {
        my $p = "main";
        no strict 'refs';
        *{"${p}::${_[0]}"} = sub (;$) :lvalue {
                state $internal = "**internal**";
                if ( $_[0] ) { $internal = $_[0]; }
                return $internal;
        };
        use strict;
}
La parte horrible de esto, como se ve, es la cuarta linea.
*{"${p}::${_[0]}"}
$p es "main" (linea 2) y ${_[0]} es $_[0] escrito minuciosamente. Sí escribimos: var "espia", $_[0] es "espia". Osea, que queda:
*main::espia
Que quiere decir que vamos a manejar el nombre "espia", en el namespace "main", exactamente donde nuestro programa lo va a ir a buscar.. Vamos bien.

La línea completa es así:
*main::espia = sub (;$) :lvalue {
Que dice que nuestro nombre "espía" va a ser una función, igual que la que que vimos en la entrada anterior. Ese es todo el truco para insertarla en el espacio de nombres correcto.

Lo último que hace falta, que arruina un poco las cosas, es que el compilador, cuando revisa todo el script, encuentra que 'espia = "James Bond"' no es nada: no es una variable porque no tiene sigil, y no es una función, porque todavía no se ejecutó lo de arriba que hace que exista. Lo mejor que puede encontrar es que pongamos la definición en un bloque BEGIN:

 BEGIN { var "espia"; }
De esa manera, perl lo ejecuta primero, creando nuestras variables especiales para cuando las vaya a ejecutar. Y ¡ojo! También puede ser un buen lugar para declarar varias variables así:
BEGIN {
        var "espia";
        var "jefe";
        var "familia_que_ignora_la_verdad";
}

Creo que voy a hacer una tercera parte. Quedaron ideas :)

Saludos!
 -- Diego.





Cómo sacar algunos sigils ($@%&), parte 1

Estuve jugando a sacarle los sigils (los símbolos que indican si las variables son strings, listas o hashes (diccionarios en python))

Lo primero que podemos hacer es definir de antemano una función con un prototipo ";$", que quiere decir que la función recibe como argumento un escalar, opcionalmente. Osea, que se puede ejecutar "boo" o "boo($persona)".
#!/usr/bin/perl
use strict;
use warnings;

sub boo(;$) {
     print "Boo!";
}
Luego, para ejecutarlo, solo tenemos que llamar a la función, sin siquiera paréntesis:
#!/usr/bin/perl
use strict;
use warnings;

sub boo(;$) {
     print "Boo!";
}
boo;
Y eso nos imprime por pantalla "Boo!", como se espera.  Hagamos una mejora: si uno le da un argumento a "boo", entonces que lo guarde; si no, que lo devuelva.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

sub boo(;$) {
        state $susto = "Default Boo";
        if ( $_[0] ) { $susto = $_[0]; }
        return $susto;
}

say "En la oscuridad, llego a la esquina y... " . boo . "!";
boo "Cuidado";
say "En la oscuridad, llego a la esquina y... " . boo . "!";
Ahora tiene un poco más de pinta de variable sin sigil. Pero ¡pidamos más! ¿Podremos asignar un valor a "boo" con un igual, como en (casi) cualquier lenguaje de programación? Por supuesto! Si le ponemos el atributo "lvalue" a boo.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

sub boo(;$) :lvalue {
        state $susto = "Default Boo";
        if ( $_[0] ) { $susto = $_[0]; }
        return $susto;
}

say "En la oscuridad, llego a la esquina y... " . boo . "!";
boo "Cuidado";
say "En la oscuridad, llego a la esquina y... " . boo . "!";
boo = "AAAAAAAAAAH!";
say "En la oscuridad, llego a la esquina y... " . boo . "!";


Sigo con un intento, por ahora fallido, de hacer esto aún más general, en la segunda parte.

 -- Diego.

domingo, 17 de marzo de 2013

Text::Fuzzy

Acá hay un mini ejemplo de cómo usar Text::Fuzzy:
#!/usr/bin/env perl
use v5.16;
use warnings;
use Text::Fuzzy;

my $tf = Text::Fuzzy->new("latitude");
say "Levenshtein edit distance is ", $tf->distance("altitude");
$tf->transpositions_ok(1);
say "Damerau-Levenshtein edit distance is ", $tf->distance("altitude");

martes, 9 de octubre de 2012

Tutorial de PDL::Graphics::Gnuplot

Me encontré con un video de youtube donde explican cómo usar PDL::Graphics::Gnuplot. Interesante!! 15 minutos.

domingo, 23 de septiembre de 2012

Creciendo con Mojolicious

Una vez que nuestro proyecto con Mojolicious va creciendo, esto de tenerlo en un solo archivo se vuelve incómodo. Para separar los templates del código, ejecutamos:
./myapp inflate
Esto creará un directorio "templates" y pondrá los templates en el lugar indicado. A partir de ahí se pueden seguir agregando templates y haciéndo referencia a ellos como siempre:
$self->render('login');