Manifiesto por una Red Neutral

Los ciudadanos y las empresas usuarias de Internet adheridas a este texto manifestamos:

1.Que Internet es una Red Neutral por diseño, desde su creación hasta su actual implementación, en la que la información fluye de manera libre, sin discriminación alguna en función de origen, destino, protocolo o contenido.

2.Que las empresas, emprendedores y usuarios de Internet han podido crear servicios y productos en esa Red Neutral sin necesidad de autorizaciones ni acuerdos previos, dando lugar a una barrera de entrada prácticamente inexistente que ha permitido la explosión creativa, de innovación y de servicios que define el estado de la red actual.

3.Que todos los usuarios, emprendedores y empresas de Internet han podido definir y ofrecer sus servicios en condiciones de igualdad llevando el concepto de la libre competencia hasta extremos nunca antes conocidos.

4.Que Internet es el vehículo de libre expresión, libre información y desarrollo social más importante con el que cuentan ciudadanos y empresas. Su naturaleza no debe ser puesta en riesgo bajo ningún concepto.

5.Que para posibilitar esa Red Neutral las operadoras deben transportar paquetes de datos de manera neutral sin erigirse en “aduaneros” del tráfico y sin favorecer o perjudicar a unos contenidos por encima de otros.

6.Que la gestión del tráfico en situaciones puntuales y excepcionales de saturación de las redes debe acometerse de forma transparente, de acuerdo a criterios homogéneos de interés público y no discriminatorios ni comerciales.

7.Que dicha restricción excepcional del tráfico por parte de las operadoras no puede convertirse en una alternativa sostenida a la inversión en redes.

8.Que dicha Red Neutral se ve amenazada por operadoras interesadas en llegar a acuerdos comerciales por los que se privilegie o degrade el contenido según su relación comercial con la operadora.

9.Que algunos operadores del mercado quieren “redefinir” la Red Neutral para manejarla de acuerdo con sus intereses, y esa pretensión debe ser evitada; la definición de las reglas fundamentales del funcionamiento de Internet debe basarse en el interés de quienes la usan, no de quienes la proveen.

10.Que la respuesta ante esta amenaza para la red no puede ser la inacción: no hacer nada equivale a permitir que intereses privados puedan de facto llevar a cabo prácticas que afectan a las libertades fundamentales de los ciudadanos y la capacidad de las empresas para competir en igualdad de condiciones.

11.Que es preciso y urgente instar al Gobierno a proteger de manera clara e inequívoca la Red Neutral, con el fin de proteger el valor de Internet de cara al desarrollo de una economía más productiva, moderna, eficiente y libre de injerencias e intromisiones indebidas. Para ello es preciso que cualquier moción que se apruebe vincule de manera indisoluble la definición de Red Neutral en el contenido de la futura ley que se promueve, y no condicione su aplicación a cuestiones que poco tienen que ver con ésta.

La Red Neutral es un concepto claro y definido en el ámbito académico, donde no suscita debate: los ciudadanos y las empresas tienen derecho a que el tráfico de datos recibido o generado no sea manipulado, tergiversado, impedido, desviado, priorizado o retrasado en función del tipo de contenido, del protocolo o aplicación utilizado, del origen o destino de la comunicación ni de cualquier otra consideración ajena a la de su propia voluntad. Ese tráfico se tratará como una comunicación privada y exclusivamente bajo mandato judicial podrá ser espiado, trazado, archivado o analizado en su contenido, como correspondencia privada que es en realidad.

Europa, y España en particular, se encuentran en medio de una crisis económica tan importante que obligará al cambio radical de su modelo productivo, y a un mejor aprovechamiento de la creatividad de sus ciudadanos. La Red Neutral es crucial a la hora de preservar un ecosistema que favorezca la competencia e innovación para la creación de los innumerables productos y servicios que quedan por inventar y descubrir. La capacidad de trabajar en red, de manera colaborativa, y en mercados conectados, afectará a todos los sectores y todas las empresas de nuestro país, lo que convierte a Internet en un factor clave actual y futuro en nuestro desarrollo económico y social, determinando en gran medida el nivel de competitividad del país. De ahí nuestra profunda preocupación por la preservación de la Red Neutral. Por eso instamos con urgencia al Gobierno español a ser proactivo en el contexto europeo y a legislar de manera clara e inequívoca en ese sentido.

Si te sientes representado por este manifiesto te pedimos encarecidamente que lo copies y lo publiques en tu blog o que lo menciones en tu cuenta de Twitter o en Facebook usando el hashtag #redneutral. ¡Muchas gracias!

Las pifias de OS X (y de Office 2011)

Dado que el RFOG está últimamente bastante MACoso, y que criticar a los demás le levanta algo el ánimo, os va a contar hoy algunas aventuras con su iMAC, y como no sería justo criticar a unos y no a otros, ha decidido escribir un potpurrí de anécdotas y de paso explicaros cómo medio subsanar algunas de las carencias de OS X, que ciertamente algunas tiene, sobre todo comparándolo con Windows 7.

Para empezar os diré que, pese a gustarme mucho OS X, le veo ciertas durezas y rugosidades, y es que prefiero funcional a bonito. Será que soy diferente, pero si funciona, me da igual que sea feo, sobre todo si es bonito y no lo hace bien.

Y es el caso del Finder. Es completamente increíble que a fecha de hoy no exista ningún atajo de teclado para llamarlo desde cualquier sitio teniendo en cuenta que es el componente más usado de todo el MAC. Bueno, el más usado es el Spotlight, pero por las carencias del anterior, o al menos a veces se usa Spotlight porque no estamos al alcance del Finfer.

Eso, o a mi se me escapa algo, que todo pudiera ser.

***

Efectivamente, no existe atajo de teclado para lanzar el Finder desde cualquier sitio. O en otras palabras: no existe atajo de teclado equivalente al Win+E de Windows. Menos mal que podemos solucionarlo de aquella manera. No obstante, resulta tremendamente extraño que OS X no tenga dicho atajo… sabiendo que existe un shortcut para casi cualquier cosa (menos esa).

Veamos cómo solucionarlo. EL truco lo encontré aquí, pero no me funcionó hasta que lo arreglé. Para aquellos que no estén muy familiarizados con el uso del Automator (que digamos es un generador visual del equivalente de los ficheros .bat en MAC), sería conveniente que abrierais dicha página y la pusierais lado a lado con la mía, porque voy a traducir y expandir los puntos que allí se tratan y así aprovecháis las imágenes, que yo no tengo ganas de repetir.

1. Abrimos el Automator y elegimos un Servicio como flujo de trabajo. Digamos que un Servicio es una especie de programa disponible globalmente y que nada tiene que ver con los Servicios de Windows.

2. Después, en la ventana de la izquierda, elegimos “Utilidades” -> “Ejecutar AppleScript”. Y lo soltamos sobre la zona de la derecha, quedando algo similar a la imagen de la otra Web.

3. Ahora borramos ese texto y pegamos el nuestro. Para facilitaros la tarea, copiad y pegad al completo esto:

on run {input, parameters}

tell application "Finder"

activate

make new Finder window to home

end tell

return input

end run

4. Dadle al icono de ejecutar. Se debe abrir una ventana del Finder. Si no lo hace revisad el texto. Si os fijáis, el script es auto descriptivo, o casi: “le decimos al Finder que se active y que cree una nueva ventana en Home. Tenéis que guardar el script y darle un nombre que recordéis. Poned, por ejemplo: “EjecutaFinder”. Ya está, ya podemos cerrar el Automator.

5. Ahora nos vamos a Sistema -> Preferencias -> Teclado -> Funciones rápidas de teclado y nos colocamos en “Aplicaciones” en el listado de la izquierda. Luego pulsamos el “+” que hay debajo y se nos abre la ventana del punto 5 de la otra Web.

6. Introducimos el nombre que le dimos al servicio (“EjecutaFinder”) en el campo de Título del Menú, asegurándonos de que en Aplicación aparece “Todas las aplicaciones”. Y finalmente, seleccionamos “Función rápida de teclado” y apretamos la combinación de teclas con la que queramos lanzar el servicio. Yo he apretado ALT+CMD+F.

7. Ya está, ya hemos terminado. Al cerrar las opciones de teclado debería activarse y cada vez que apretemos dicha combinación, debería aparecer una ventana del Finder.

Pero no lo hace porque se nos ha olvidado una cosa. Volvemos a abrir el servicio en el Automator y arriba del todo, justo encima de “Ejecutar AppleScript”, tenemos que cambiar los dos desplegables y poner “El servicio recibe sin datos de entrada en cualquier aplicación”. Grabamos y ya está, ahora sí que funciona bien.

***

Vale. ¿Cuál es el problema? Pues que tarda como diez segundos a aparecer la ventana del Finder. Al menos en mi Core2Duo con 4GB de RAM, y todavía tarda más si tengo activa la máquina virtual con Windows para poder ejecutar lo que no se puede en OS X, como el servidor NNTP para las comunidades de Microsoft.

La respuesta es que nos jodemos y punto. Es lo que hay. Carencia de MAC solucionada a trancas y barrancas.

Sí, ya sé, podemos abrir la carpeta o el fichero que queramos desde Spotlight, pero no es lo mismo y el tiempo que se tarda es más o menos el mismo si no más.

***

Otras carencias del OS X: no existe el concepto de “ir al final de la línea”. Y no veáis lo que me jode, porque en Windows es algo a lo que estoy más que acostumbrado. Tampoco existe el concepto de “saltar palabra” (Ctrl+Flecha en Windows).

Dos problemas a los que no he encontrado solución y que me traen por la calle de la amargura y hacen que mi rendimiento en OS X caiga en picado. Primero porque le doy a la tecla de fin y me salta al final del documento, y tengo que volver con el teclado, o peor todavía: armo un desbarajuste de cuidado.

Menos mal que las aplicaciones de Microsoft (léase Office) sí que aplican el concepto a sus productos. O no tan menos mal, porque entonces el lío está armado.

Me refiero a que cada vez es más automático: si estoy en el curro bajo Windows, uso los atajos de Windows. Si estoy en casa usando MAC, uso los de MAC… Pero con el Office me lío, y no poco.

En fin, a sanjoderse, de nuevo, tocan.

***

Más.

La última actualización de Office hace algo raro porque cada vez que reinicio el MAC me coloca unos ficheros recuperados en la papelera. Es algo que le ocurre a todo el mundo y está más o menos documentado, buscad “wkresources” y veréis. Esperemos que Microsoft lo solucione en breve, pero vaticino un “NOT REPRO” en los informes de Bugs… o un NEXT VERSION o un NOT TO BE SOLVED… Deseo ardientemente equivocarme.

Además, si reinicias con el Word abierto tras haber editado y cerrado ficheros, también te recupera morralla de ellos.

***

Todavía más.

No veais lo que me jode, pero en profundidad, que en MAC no exista el concepto de “ir al siguiente mensaje sin leer”. Y encima que Outlook le siga a pies juntillas.

¿A qué superlumbreras se le habrá ocurrido que a la gente no iba a interesarle, no un atajo de teclado para saltar entre mensajes sin leer, sino ni que ni siquiera exista el concepto de tal cosa? Perdonadme la expresión: es de imbéciles.

Tenemos las carpetas inteligentes, y podemos crearnos una (o varias) en las que nos aparezcan los mensajes sin leer, pero sueltos y fuera de concepto, y en Outook no nos marca que hay nuevos sin leer.

En fin, otra cagada más.

***

Y ya para finalizar, la última de la última.

¿Cómo cojones se escribe el símbolo de HOME, la tilde esa horizontal? Y ya de paso, ¿cómo puñetas se escriben los símbolos especiales que con Windows es Alt-número?

***

Pues eso, que si sabes alguna respuesta a lo que pongo, escribe un comentario. Todas son preguntas a cosas que no he podido encontrar ni en Internet ni en los libros sesudos sobre Snow Leopard que he podido consultar…

Os garantizo un profundo agradecimiento por mi parte y seguro que de muchos otros.

Addenda. Después de tener escrita la entrada e intentar publicarla, no he podido hacerlo desde MAC. Suelo escribirlas en Office para MAC, y luego las guardo en HTML. Finalmente veo el código fuente, lo copio, me voy al IE virtualizado, pego como HTML limpiando alguna morralla y entonces la entrada sale bien.

Pues en este caso ni así. Y no sé por qué. Bueno, sí que lo sé: la puta mierda de interoperabilidad entre Windows/MAC. Al final he instalado el Word en la máquina virtual, he abierto el DOCX en dicho Word, copiado/pegado sobre Live Writer… y por fin ha salido bien.

No obstante, para tener un Windows dentro de un MAC… lo tengo fuera y punto.

Timers, alarmas y el iPhone

Con esta entrada vamos a matar tres pájaros de un tiro y evitar que dios, en su infinita sabiduría, mate más gatitos. Porque sí, porque cada vez que falla la alama de un iPhone o un iPod, dios se carga uno. Pero antes de llegar al meollo de la cuestión tenemos que ver otras cosas. Aprovecharé para contaros cómo funcionan los timers en un microprocesador (el primer ave defenestrada), os explicaré el concepto para construir una aplicación que sea un reloj con alarma (el segundo pajarraco) y dejaremos una pregunta en el aire para mofa y escarnio de la gente del iOs.

Todos hemos oído hablar de la frecuencia a la que funciona un microprocesador. Los, primero megaherzios, y luego gigahercios. Y no oiremos hablar de los terahercios porque están en el rango de los efectos cuánticos y no nos valen para mover un microprocesador… (Chiste para físicos cuánticos: tengo un ordenador a 3 terahercios pero nunca estoy seguro de dónde está).

Ese reloj genera una serie de pulsos (parecidos a los que aparecen en un cardiograma pero más regulares) y son para el procesador y aledaños como nuestro corazón. O como un mecanismo de cuerda, que hace girar los engranajes. Imaginaros la rueda de escape de un reloj. Pues el funcionamiento interno de un procesador es igual: ante cada punto de escape (que en informática se llama ciclo máquina) las ruedas de engranajes se van moviendo poco a poco y al final vemos cómo la aguja del segundero va trazando su arco.

Si nos da por mirar una placa base en detalle, no vamos a ver un reloj de los gigahercios que se supone tiene nuestro equipo. Con suerte veremos uno de 40 o 60 MHz. Lo demás se realiza dentro de chips especiales que dividen esa frecuencia en otras mayores mediante electrónica. Y más dentro del micro, ya que muchas partes dentro de él no necesitan tanta velocidad y a veces es contraproducente, como veremos.

Uno de los elementos que comparten absolutamente todos los microprocesadores son los timers, nombre con el que suelen conocerse en la literatura técnica. El mínimo es uno, el máximo viene determinado por el tipo y destino del microprocesador, más todavía en los microcontroladores. Existen dos modos generales de funcionamiento. A veces ambos están presentes, a veces un mismo timer se puede comportar de las dos formas, y a veces sólo hay de un tipo.

En uno de ellos tenemos acceso a un contador que se va incrementando periódicamente y que nosotros podemos leer para comparar con nuestro valor. En el otro, llegado a un punto (generalmente cero), se dispara una interrupción.

Es decir, cuando nosotros queremos activar un timer, lo que hacemos es escribir en una serie de registros del microprocesador para configurarlo. Decimos registros pero lo habitual son direcciones de memoria que están mapeadas dentro del procesador. Si os acordáis de otra entrada, nosotros escribimos en una dirección del procesador y las patillas del mismo cambian de estado. Pues ahora es lo mismo, pero en lugar de subir o bajar la tensión de una de ellas, configuramos el timer.

O en otras palabras: conectamos una serie de ruedas de engranajes que estaban detenidas, ruedas que nos permitirán tener un evento periódico, ya sea un contador que se vaya incrementando solo o una interrupicón que se lanzará con cierta frecuencia.

Pero hay un problema. En un procesador de 8 bits, los registros serán, a lo sumo, de 16 bits. En uno de 16, de 32. En uno de 64 lo habitual es que sean de 64 bits, no de 128. Para ponerlo en marcha o detenerlo sólo necesitamos un bit, pero para programar el prescaler, cuantos más bits tengamos, mejor.

Suponiendo que tenemos un registro de 16 bits, tendremos 65536 posibles valores respecto a la base de tiempos. Por decirlo de otro modo, si en ese registro ponemos el valor de 10, el procesador hará la acción (ya sea incrementar otro registro o generar una interrupción) cada vez que ese valor llegue a cero. Si tenemos una base de tiempos de 1 ns, nuestro timer será de 10 ns. Si ponemos un valor de 50000, entonces tendremos un tick cada 50 us (microsegundos).

Si os fijais, en esta situación, nuestro valor más alto será de un poco más de 65 microsegundos. Esta es la limitación de la que hablábamos antes. Algunos fabricantes lo solucionan ofreciendo DOS registros para programar el timer, o que cada salto de 1 en en ese registro sea de 10 en la base de tiempos, o ambas cosas, e incluso tendremos dentro de un mismo microprocesador varios tipos de timers.

Al final, el tema está en que lo habitual es que no podamos tener ticks mayores de unos cientos de milisegundos lo que para los programas puede ser un tiempo excesivamente largo, pero para un reloj normal son demasiado cortos.

En ambos casos la limitación es la misma: tanto la interrupción como el contador interno del microprocesador se van a disparar demasiado rápido para lo que queremos. No he dicho que en el caso del incremento de la variable, normalmente es otro registro del procesador el que se va incrementado (o decrementando), y cuando decimos registro queremos decir dirección de memoria, que podremos leer y consultar. El mayor problema de este tipo de temporizadores está en que cuando la variable llega a su mínimo o su máximo, o bien vuelve a empezar o bien el timer se detiene. Y si no lo consultamos con la frecuencia suficiente, no sabremos que se ha detenido y habremos perdido nuestra base de tiempos.

Si os acordáis, hubo en Windows 95 un fallo que hacía que el ordenador se colgara si estaba más de unos días sin reiniciar. El problema era este mismo: Windows tenía un contador interno que se iba incrementando y cuando llegaba al máximo, volvía a empezar por cero. Y entonces todo se iba al garete porque lo que quiera que lo usara para su funcionamiento esperaba un incremento, no un decremento del orden de 230 ó 231.

Incidentalmente el problema tiene solución, y encima no es compleja en exceso pero sí que necesita código y saber la frecuencia media de consulta al timer, solución que debe ser compartida entre el timer y la parte que lo consulta. De hecho existen TRES soluciones. Os lo dejo como ejercicio de clase.

Por lo tanto yo no suelo recomendar el uso de este tipo de timers, aunque a veces es inevitable, y entonces es obligatorio evaluar si se puede producir dicho desbordamiento, o al menos es lo que hacen los buenos programadores. De todos modos, al final, veremos que es muy posible que siempre nos pueda ocurrir. Y no, incidentalmente, no creo que sea este el problema con los iPhone.

***

Bueno, ahora que sabemos qué es un timer y cómo funciona, vamos a construir un ejemplo práctio… en C.

//Este es el contador global de nuestro timer.

int g_timerCntr=0;

//Esto se debe llamar una sola vez al principio de todo

//Configura y pone los registros adecuados para que nuestro

//timer sea de 1 ms.

void InstallItmer(void)

{

       //Configurar los registros

       //…

}

//Arranca el timer con un intervalo

void SetTimer(int interval)

{

       g_timerCntr=interval;

       //Arrancar el timer

}

//Devuelve "cierto" si el timer ha terminado.

int HasEnded(void)

{

       return g_timerCntr==0;

}

//La interrupción que se lanzará periódicamente.

//Aquí el linker deberá poner su dirección en el lugar adecuado.

INTERRUPT_TIMER TimerInterrupt(void)

{

       g_timerCntr–;

       if(g_timerCntr==0)

              ; //Detener el timer

       else

              ;//Recargar el timer

}

La llamada a InstallTimer() debe hacerse al arranque del procesador, o al menos antes de que vayamos a usarlo por primera vez. Lo que hace esta función es configurar los registros según lo hemos explicado, de modo que, en base a la frecuencia de trabajo del procesador, más los registros adecuados, se nos dispare una interrupción cada milisegundo (en nuestro ejemplo). Pero no lo pone en marcha, simplemente lo configura.

TimerInterrupt() es la interrupción que nos saltará cada vez que transcurra un milisegundo. Fijaros que decrementamos en una unidad una variable local y que si llega a cero, detenemos el timer y si no lo recargamos. Esto es un ejemplo, porque a veces no será necesario recargarlo, es decir, el procesador disparará la interrupción cada 1 ms, otras veces lo hará sólo una vez y se detendrá, todo depende del modelo y características de casa procesador y del timer que estemos usando.

Aquí, con INTERRUPT_TIMER he ejemplificado el hecho de que debemos indicarle al compilador y al enlazador que dicha función es una interrupción y que debe ser instalada en el lugar adecuado. De nuevo estamos ante las particularidades de cada compilador y enlazador, aunque cuanto más moderno sea, más fácil nos lo pondrá.

Básicamente, una interrupción está localizada en una dirección de memoria exacta, y es ahí dónde se debe poner la dirección en la que está la rutina a modo de puntero a función: cuando se dispare el timer, el hardware del micro hará un call a lo que quiera que esté apuntando esa dirección. Si hay código bueno se ejecutará. Si no, lo habitual es que se cuelgue, aunque a veces también se puede producir una excepción hardware que nos permitirá resumir, de algún modo, el funcionamiento. Además, en algunos microprocesadores la instrucción de retorno de función (ret, para entendernos) será alguna instrucción especial como iret, retorno de interrupción. De nuevo estamos ante el hecho de que hay tantas variaciones como familias y fabricantes de electrónica.

Bueno, la parte difícil ya está. La fácil son las dos funciones que nos quedan. SetTimer() asignará un valor a la variable global y HasEndend() nos devolverá cierto cuando el contador haya llegado a cero. Si, por ejemplo, pasamos 1000 a SetTimer(), habremos obtenido un metrónomo de 1 segundo. Terminar nuestro reloj es casi trivial:

int _tmain(int argc, _TCHAR* argv[])

{

       int segundo=0, minuto=0, hora=0;

       InstallTimer();

       for(;;)

       {

              //NOTA: Con esto simulamos la interrupción

              if(g_timerCntr!=0)

                      TimerInterrupt();

              //FIN DE NOTA

              if(HasEnded())

              {

                      SetTimer(1000);

                      segundo++;

                      if(segundo>=60)

                      {

                             minuto++;

                             segundo-=60;

                      }

                      if(minuto>=60)

                      {

                             hora++;

                             minuto-=60;

                      }

              }

       }

       return 0;

}

¿Lo veis, no? Lo único a destacar en el ejemplo es que hemos puesto la interrupción en nuestro bucle for (para evitar que el autor tenga que crear un thread para el timer o suscribirse a uno de windows, etc). Obviando eso, tenemos un reloj en nuestro PC que ejemplifica cómo podríamos construir uno si TimerInterrupt() realmente se disparara cada milisegundo.

Copiaros el código a un proyecto de C++ de consola de Visual C++, definid

#define INTERRUPT_TIMER void

Al principio de todo, y os debe funcionar.

Añadir alarmas es relativamente fácil. Deberíamos tener una lista de variables hora, minuto y segundo y, en el bucle, comprobar si la hora actual es igual o superior a la programada, y si lo es, lanzar el sonido.

***

Bueno, ya tenemos nuestro reloj. Bonito, ¿no? Pues NO. Ese programa es una mierda de programa, y desde luego no creo que esté hecho así en iOS, y si lo está sería para matarlos lentamente (aunque el tipo de problema que tiene me hace pensar que…). Ese programa nos sube la CPU al 100% y en un dispositivo con batería se la iba a chupar en un tris.

No, la solución es algo más compleja, y pasa por mover bastantes cosas a la interrupción. Algo así:

//Este es el contador global de nuestro timer, y los datos

//Para mantener el reloj.

int g_timerCntr=0;

int hora=0,minuto=0,segundo=0;

//La interrupción que se lanzará periódicamente.

//Aquí el linker deberá poner su dirección en el lugar adecuado.

INTERRUPT_TIMER TimerInterrupt(void)

{

       g_timerCntr–;

       if(HasEnded())

       {

              SetTimer(1000);

              segundo++;

              if(segundo>=60)

              {

                      minuto++;

                      segundo-=60;

              }

              if(minuto>=60)

              {

                      hora++;

                      minuto-=60;

              }

       }

       //Recargar el timer

}

int _tmain(int argc, _TCHAR* argv[])

{

       InstallTimer();

       Sleep(INFINITE);

       return 0;

}

Este ejemplo ya no nos va a funcionar en el PC, pero gasta un montón menos de batería y nos deja la CPU al 0% o casi.  Ahora sí que tenemos un reloj de verdad, optimizado al 100%. Y ahora es cuando entra el tío de la rebaja: tenemos que medir (con un sistema de traza, por ejemplo), cuánto tiempo tarda la ejecución del bloque que hay dentro del primer if, y si es superior al milisegundo, debemos anotarlo y corregir el contador para evitar que nuestro reloj atrase. También debemos comprobar si la interrupción es reentrante (en el caso de que no haya acabado y si llega el momento de volver a ejecutarla, el procesador lo hará o no) y actuar en consecuencia. De todos modos, por el código usado, os aseguro que se tarda menos de 1 ms a hacer todo lo que hay dentro del if.

¿De dónde viene el ahorro de energía? Es muy sencillo: si os fijás en este último caso, sólo se ejecuta código cuando es estrictamente necesario, y cuando no el programa está durmiendo sin hacer nada. En el caso anterior el programa estaba continuamente comprobando si el timer había llegado a cero o no, de continuo, usando el 100% de la CPU.

Una solución intermedia al primer programa podría haber sido poner un else y dormir el programa durante 1 ms, pero aun así sigue siendo bastante inefectivo (y en Windows esa dormida será de, al menos, 15 ms).

***

Ya, ahora sí, ahora ya está todo perfecto… ¡NO! ¡Ni mucho menos! Lo de arriba sigue siendo una enorme pérdida de tiempo, un absurdo sólo válido como explicación teórica y poco más. ¿Realmente necesitamos tres variables para el reloj? Pues no, esas tres variables sólo son necesarias para cuando tengamos que verlas los seres humanos, por lo tanto debemos plantearnos la pregunta de qué precisión necesitamos. ¿1 segundo? Pues hagamos lo siguiente:

//Este es el contador global de nuestro timer, y los datos

//Para mantener el reloj.

int g_timerCntr=0;

unsigned long g_hora=0;

//La interrupción que se lanzará periódicamente.

//Aquí el linker deberá poner su dirección en el lugar adecuado.

INTERRUPT_TIMER TimerInterrupt(void)

{

       g_timerCntr–;

       if((g_timerCntr%1000)==0)

              g_hora++;

       //Recargar el timer

}

void MuestraHoraActual(void)

{

       int hora, min,seg;

       hora=g_hora/3600;

       min=g_hora/60;

       seg-=(hora*3600+min*60);

       printf("%02d:%02d:%d2d",hora,min,seg);

}

Fijaros en la interrupción, reducida a la mínima expresión a costa de crearnos una función de muestra de hora algo más compleja (que no estoy seguro si funcionará bien o no, pero sin lo hace pocas diferencias tiene que haber con la correcta). A simple vista hemos perdido, pero realmente hemos ganado, y no poco. ¿Qué relación hay entre las veces que vemos el reloj y las que se ejecuta la interrupción? Pues prácticamente infinitas.

Ahora me diréis que el iPhone muestra la hora arriba del todo. Sí, pero en minutos. Es decir, que podemos reducir incluso el contador de la interrupción a minutos en lugar de segundos. Y entonces añadimos el truco del almendruco, que es un flag para indicar a la shell que debe actualizar el reloj. Algo así:

INTERRUPT_TIMER TimerInterrupt(void)

{

       g_timerCntr–;

       if((g_timerCntr%1000)==0)

              g_hora++;

       if((g_hora)%60==0)

              g_flagCambiaMinuto=1;

       //Recargar el timer

}

Y será tarea de la interfaz del iPhone la de pintar cada vez que cambie el minuto.

Este acercamiento para el aviso de cambio de minuto es muy burdo. Lo que yo haría es tener llamar a un callback que me repinte la hora si el iPhone no está a pantalla completa y si eso no se puede hacer (que no se podrá, porque pintar en pantalla desde una interrupción como que es chapucero y a veces simplemente el hardware no lo permite), ese callback invalidaría el rectánculo de pintado y entonces el controlador de pintado, al recibir dicha invalidación, repintaría el área… con la nueva hora.

Fijaros cómo una tarea en principio simple tiene más miga de la que parece, sobre todo si quieres hacer las cosas bien. De hecho no sé cómo lo está haciendo Apple (y de paso Microsoft) con el tema de las horas, pero si yo tuviera que hacer algo así esa sería MI forma.

***

Ya está, ya terminamos. ¿Cómo podríamos añadir alarmas (y que suenen) al último ejemplo? La solución más sencilla es tener un array de variables del mismo tipo que g_hora. El tamaño podría ser dinámico con una lista enlazada, o un array estático con, pongamos, 16 variables que nos permitirian tener un máximo de 16 alarmas diferentes. Eso ya depende de la implementación. Esta sería la nueva interrupción, ya definitiva:

#define NUM_ALARMAS 16

unsigned long g_alarmas[NUM_ALARMAS];

INTERRUPT_TIMER TimerInterrupt(void)

{

       g_timerCntr–;

       if((g_timerCntr%1000)==0)

              g_hora++;

       for(int i=0;i<NUM_ALARMAS;i++)                                                    

              if(g_alarmas[i]!=0 && g_alarmas[i]<g_hora)

                      PreparaAvisoAlarma(i);      

if((g_hora)%60==0)

              g_flagCambiaMinuto=1;

       //Recargar el timer

}

Fijaros qué código más minimalista y completo: tenemos alarmas, tenemos reloj en tiempo real, actualización de la hora en el escritorio con apenas unas líneas y que apenas consumen una miseria de energía y tiempo de proceso.

Cuando g_alarmas[i] vale cero, es que esa alarma está desactivada, y si no vale cero y su valor es inferior a la hora actual, es que debe sonar. De nuevo PreparaAvisoAlarma() debe ser una función mínima que simplemente indique al sistema que la alarma debe tocar, ya sea despertando un hilo dormido o activando cualquier flag que luego alguien leerá y actuará en consecuencia.

Luego, la tarea del programa de interfaz con el usuario que le permita añadir, quitar o modificar alarmas, será la de “tocar” dichas variables a gusto del consumidor.

¿Cuál es, pues el fallo del iPhone? Pues que ante el cambio de hora, al programador de turno se le olvidó actualizar también ese array de alarmas (o su equivalente), con lo que ellas tienen el valor antiguo y sonarán cuando el valor de disparo antiguo se corresponda con el nuevo…

Peeeeeeeeeeeeeeeeeeeero, hay un gran pero, y aquí es donde vienen las risas. En mi caso, ninguna solución propuesta funciona. Ni en mi flamante iPhone 4G, ni en mi iPod Touch 2G. Ni por cierto en el de mi jefe, lo que supuso una seria discusión sobre lo inútil que era (yo) y que antes de hablar debería asegurarme de que la culpa es mía y no de los demás, como siempre hago (palabras textuales), a lo que yo le dije que probáramos el tema… Cuando vio que ni en el mío ni en el suyo funcionaban… se fue a recoger el correo (en fin, que la cosa se va acercando a su final lógico…).

La solución que me funciona es poner una alarma y activarla para TODOS LOS DÍAS de la semana, de lunes a domingo. Si no se hace así suena una hora más tarde, aunque sean alarmas antiguas o recién creadas, o apagues y reinicies el iPhone, o incluso lo restaures desde la copia de seguridad: falla.

Por lo tanto, alguna chapuza remiendosa debe de haber dentro del software del iPhone, porque, como os he demostrado, tener alarmas en un dispositivo como el que hablamos es, a nivel de desarrollo, completamente trivial, y si regenerarlas desde cero no funciona…

[NOTA: El código de ejemplo, salvo la primera parte, no está probado, así que lo mismo puede haber algún gazapo si a alguien se le ocurriera probarlo].

Un caso de fracaso… o dos

Bueno, esta es otra de esas entradas nada técnicas y personalísimas, en la que voy a contar varias cosas, respoder a las inquietudes que asertus ha comentado en la entrada anterior.

Generalmente los casos de éxito se suelen airear a lo grande, a bombo y platillo, con grandes titulares, pero los fracasos se suelen ocultar debajo de la alfombra, y cuanto menos se sepa de ellos, mejor.

Pues bien, yo voy a contar aquí un proyecto que ha fracasado, o al menos lo ha hecho según el planteamiento original, y luego comentaré algo sobre Evernote 4 y su bajada de WPF…

Aparte del firmware, y a veces junto con él, suelo entregar una aplicación para PC que se encarga de lidiar con la electrónica que vendemos, o simplemente demuestra su funcionamiento, aunque las más de las veces sirve como herramienta de configuración y verificación.

Es un proyecto bastante complejo que ha arrancado y parado varias veces, ha mutado y vuelto a mutar, pero al final estuvo claro qué se quería, y cómo. Fue tiempo de ponerse a picar código como un loco. De eso hace unos meses, y más o menos el esfuerzo duró como dos meses hasta que nuevas y más urgentes tareas volvieron a pausarlo, pero esta vez no porque se llegara a un callejón sin salida (y no me refiero a técnico, sino comercial o de concepto), sino porque se vio que había tareas de mayor prioridad.

Se detuvo en un punto interesante: la parte del PC estaba casi terminada, por lo menos la primera fase, y ya iba a pasar al hardware, aunque estimé que necesitaría otra semana más para estar listo y empezar con la interoperabilidad entre el PC y la electrónica. Una siguiente iteración, cuando programa y placa se hablaran entre ellos, volvería al PC para finiquitarlo y dedicar el resto del tiempo al desarrollo embebido, cienes y cienes de variantes del firmware que el programa del PC debería ensamblar e insertar en la placa…

Esos dos meses fueron un poco como de pesadilla. Entusiasmado y emocionado, con mucha ilusión, comencé a hacerlo con el Feature Pack de Visual Studio 2008. Sí, ya sabéis, la Ribbon, las ventanas estilo Visual Studio y todo eso, la última versión de MFC. De esa pelea, porque pelea sin cuartel fue, tenéis las últimas entradas de mi sección MFC en el Guille. En concreto iba a aprovechar todo un esqueleto de Visual Studio incluyendo el control de propiedades igual que se trabaja con .NET. Es decir, el programa tendría un Editor de Propiedades y una “Paleta de Componentes” como las tiene el .NET. Pero relacionadas con mi firmware, y el usuario podría coger pedazos de firmware, echarlos sobre un contenedor y luego ir cambiando las propiedades. Finalmente, una opción enviaría dicho firmware a la placa.

Bonito, ¿no?

Bueno, pues fue un fracaso. No solo tuve que pelearme con todas y cada una de las cosas que iba añadiendo, sino que luego no funcionaban ni como estaban documentadas (en el caso de que lo estuvieran) ni como dicta la razón. Entre las cosas que me costó mucho hacer funcionar está el personalizar las barras de herramientas, hacer funcionar el editor de propiedades, y que el modelo Documento/Vista funcionara como yo quería…

No voy a contar ninguna pelea, ni voy a poner el grito en el cielo, ya no, ya me he cansado de predicar en el desierto. Básicamente me tuve que leer medio internet, y navegar hasta las profundidades del código fuente de MFC para, en primer lugar saber cómo funcionaba y por qué hacía lo que hacía, y en segundo para saber cómo heredar y cambiar el comportamiento y mirar por qué no funcionaba como se esperaba…

El summum de la desesperación vino cuando pasé el proyecto a Visual Studio 2010 y empezaron a aparecerme fugas de memoria que en la versión 2008 no había (o si las había no eran detectadas)… así que volví a la versión 2008SP1.

Pero ahí no terminan las cosas, las cosas terminan cuando, de repente, los diálogos dejaron de funcionar. Me explico. Tengo varias clases base heredadas de CDialogEx que usan una plantilla de diálogo y que implementan el contenido común. Luego heredo de ellas una jerarquía pero sin plantilla y con pocas líneas modifico el comportamiento. No son muchas, son cuatro clases base de las que heredan cuatro hijas de cada una de ellas, pero que creadas de esta forma ahorran muchos dolores de cabeza y concentran la funcionalidad siempre en un mismo sitio.

Pues bien, eso dejó de funcionar, de repente, sin tocar nada. No he investigado mucho, pero parece ser que la cadena de constructores se interrumpe cuando uno de ellos es incapaz de encontrar el recurso de diálogo en el ejecutable, diálogo que seguro existe, no tiene ningún problema y que puedo ver en el editor de Visual Studio. El constructor retorna a medio construir, y cuando se llama a ShowDialog() se dispara un ASSERT que pone un insulso mensaje en la ventana de Debug y ni se abre el diálogo, ni se genera una excepción, ni pasa nada de nada. Como el silencio administrativo pero en programa.

Ahí fue cuando decidí parar la vez anterior, o más bien llegó la fecha límite y tuve que cambiar a otra cosa. A últimos de la semana pasada retomé el proyecto, ví lo de los construtores y… lo mandé a tomar por culo.

Con esas misma palabras.

El martes empecé una versión limitada en funcionalidad, en Windows Forms y C#. Básicamente se abre un diálogo que deja elegir entre unos módulos, y luego, Form a Form, permite modificar el comportamiento. Y finalmente dándole a un botón envías el resultado. La aplicación se guarda a sí misma, la información está en ficheros INI de texto, y tiene casi toda la funcionalidad que la anterior, pero hecho de forma bastante más chapucera.

También me he encontrado con algún tropiezo, pero en su mayoría debido a mi propia torpeza. De todos modos estamos a jueves (han pasado tres días) y… ¡Ya estoy en la misma fase en la que acabé la otra vez! Es decir, he tardado 3 días a hacer en .NET lo que en MFC me llevó casi dos meses. Evidentemente no es la misma aplicación ni de lejos, ni tan bonita ni tan funcional como era la otra, y creo que no me atrevería a hacer algo de complejidad similar en C#. Ya no me fío después de cómo las he pasado con .NET…

No me malinterpretéis, con esto que os he contado no quiero decir que .NET sea la rehostia, que no lo es, de hecho ahora tengo un problema con un thread que me parece que es una limitación (que no un bug) de .NET…

Por otro lado, y es un consenso entre varios MVP de C++ y entre los programadores en general, que el Feature Pack es algo bloated, a-funcional y lleno de enormes torpezas. Complejo a conciencia, escasamente documentado, y la versión 2010 tiene fugas de memoria internas (Haced la prueba: construid una aplicación de cuadro de diálogo sin más, ejecutadla y cerradla. La ventana de depuración os dará fugas de memoria sin que el usuario haya añadido una sola línea de código).

Añadamos que nos genera ejecutables de más de 2 megas de tamaño… Ciertamente un fracaso, y no propio. Yo al menos me he sacado las castañas del fuego en tres días, a ver lo que tarda Microsoft.

***

Otra de las noticias que está corriendo como la pólvora es que Evernote 4 ha abandonado WPF en pro de C++ y del código nativo. Más o menos cuentan lo que yo ya dije hace mucho tiempo: .NET no vale para aplicaciones de sistema ni para nada medianamente complejo que no sea para lo que se ha pensado, que son aplicaciones verticales de bases de datos sin muchos Forms (ni muy complejos) y como competencia directa de Java (que todavía vale menos, IMHO).

Una prueba de ellos es que, a fecha de hoy, ninguna aplicación de Microsoft está enteramente hecha en .NET. No Office, ni partes interesantes de Windows, ni otras herramientas enterprise. Lo más cercano es el editor de Visual Studio 2010, que no está mal pero que funciona sensiblemente más lento que el del 2008, y cuando digo más lento es más lento. En mi caso, a veces ni siquiera me pilla un doble clic rápido. Además, como muestra un botón, ya que la gente que estaba haciendo el editor tuvo que ponerse seria con la que hacía WPF para que solucionaran serios problemas tanto de rendimiento como de funcionalidad, o al menos eso es lo que se deja entrever en algunas noticias y se comenta en los mentideros de la red.

Hay un tercer problema, y es que la supuesta unificación del API de .NET para deshacerse del de Win32 se está convirtiendo, con el tiempo, igual de disparejo, con las mismas inconsistencias entre diferentes partes…

Es muy posible que en fechas no muy lejanas veamos morir a más lenguajes .NET, seguro que C++/CLI entre ellos. De momento en Visual C++ 2010 no tiene IntelliSense porque al parecer no les dio tiempo a implementarlo, pero es que tampoco se ha actualizado para añadir algunas de las cosas de .NET 4.0…

Así que, una vez desaparecido éste, gente del Visual Basic, poneros a remojo. Y los Accesseros también. Son mis 2 céntimos sin usar información privilegiada de ningún tipo, pero son cosas que se ven venir. Y ya de paso metamos a Windows Phone, que tampoco creo que dure mucho y eso que acaba de nacer…

Volviendo a Evernote, y habiendo hecho un análisis somero, parece ser que han utilizado WTL, ATL y STL, con librerías de terceros, pero no MFC (No me extraña). De hecho, aplicaciones masivamente utilizadas como Chrome o Picasa no usan ni MFC ni WPF (ni .NET). Por algo será.

Tampoco han usado QT, cosa que en principio me extraña un poco porque es EL FRAMEWORK de moda y de éxito… Yo llevo bastante tiempo detrás de aprender QT, pero no me decido. Cojo un libro, leo un par de capítulos y lo dejo, para repetir al cabo de unos meses. Ahora con el iMAC en marcha veo QT de otra forma, y de hecho los dos libros de Cocoa (el de la Vespa y el Unleashed) creo que van a dormir el sueño de los justos…

Ah, por cierto, esta entrada ha sido escrita con Word 2008 para MAC, guardada como un fichero HTML, cargado en el IE 7 con una máquina virtual windows, visto su código fuente y copiado directamente como HTML en el editor WEB del blog (cosas de la interoperabilidad). Las aplicaciones Windows han estado corriendo en modo Unity y, Asertus, de momento tengo tanta faena en el curro que cuando llego a casa (antes no llegaba a casa, estaba en casa) sólo tengo tiempo y ganas de bajarme el correo personal, navegar un rato e irme a dormir. Tengo instalado QT tanto en la virtual Windows como en el iMAC, pero apenas lo he usado por encima, y eso que me está rondando una idea para un juego que…

El RFOG se ha vuelto un fanboy… o casi

Pues sí, aunque parezca mentira, al RFOG ese cada vez le gusta más el Snow Leopard y su iMAC, y de hecho está indeciso entre comprarse uno de última generación o un MAC PRO de esos con una espuerta de núcleos y memoria… El problema es el precio, que por ese dinero puedo tener un PC equivalente e irme de vacaciones al Caribe medio año…

¿Qué por qué está el RFOG usando un iMAC? Pues es una historia algo larga y que de momento tampoco me interesa mucho contar, o más bien a quien no le interesa es a mi jefe, aunque algo os diré.

El iMAC vino como una especie de capricho, como ya he contado por aquí antes. Íbamos mi hermana y yo paseando por el Mediamarkt cuando los vimos ahí, en esa mesa tan chula que es siempre la misma en todas la tiendas. Allí estaban ellos. La gente se acercaba, los toqueteaba un poco y se iba.

Pero el RFOG y su hermana se acercaron y estuvieron jugando con el más grande del momento, uno de 24 pulgadas y con 4GB de memoria… Y una cosa llevó a la otra, y al final el RFOG pasó por caja y se compró un iMAC, algo que si bien no le llamaba mucho la atención, sí que le corroía la curiosidad de ver cómo era y cómo funcionaba.

Corrián mediados del 2008, y en este blog tenéis algunos de los primeros comentarios. Luego el iMAC se quedó en el salón, y sólo se encendía para enserñarlo a las amistades y actualizar el iPod Touch 2G… Bueno, algo sí que hice con él. Tras pedir una licencia de Office para MAC como MVP (la pagué con los bucks virtuales que nos daban y ya no nos dan, cosas de la crisis), hizo con él el PowerPoint del webcast sobre Hilos en .NET.

Luego estuvo una temporada apagado, encendido sólo para actualizarlo cada vez que había alguna de ellas, ya que eso del Snow Leopard como que no lo veía muy útil.

Mientras, el RFOG continuó usando su ordenador PC compartido con la empresa como equipo principal y único. Ya os he comentado en otro momento que trabajo (digo, trabajaba) desde casa, sin tráfico, sin horarios, sin madrugones salvo contadísimas ocasiones, las más de las veces por despertarme con la idea del día.

Los motivos por los cuales no me gusta(ba) el Snow Leopard vienen porque está algo obsoleto, obsoleto comparado con Windows 7 (en aquél momento, Vista, que es casi decir lo mismo). No, no me refiero a que Windows sea mejor que MAC, me refiero a que Leopard y Snow Leopard es un grandísimo avance en cuanto ergonomía y usabilidad respecto a Windows XP, pero comparándolo con Vista/7, ganan estos últimos, aunque ajustadamente. Esperemos que el león le de un buen bocado, de nuevo, a Windows.

Pues bien, ese ordenador compartido fue originalmente mi AMD X2, que fue siendo actualizado poco a poco a cargo de la empresa, convirtiéndose en un QUAD con 8 GB de RAM, una espuerta de discos duros y dos monitores, uno de 24″ y otro de 22″. El de 24″ es mío, comprado con un dinero extra que iba a recibir por darme la gran panzada a programar durante unas navidades, fiestas incluidas… y que nunca ví. De hecho se lo precuerdo periódicamente a mi jefe. El monitor me costó más de 600 euros, junto a una tarjeta de vídeo que murió no hace mucho. Vamos, redondeando y con la subida del coste de la vida, 1000 euros que me debe cierta empresa (no en la que trabajo) y que todavía no he visto. Del ordenador hay cosas que son mías por derecho propio, otras no están tan claras. La caja. 4 de los 8 GB de memoria. El ratón/teclado (un Logitech Wave Pro), y todo el software que hay en él, o casi todo. Licencias NFR por ser MVP y otras ganadas por betatester o simplemente por tener el morro de pedirlas gratis. Todo eso me pertenece sin lugar a dudas.

Así que al final si lo juntamos todo podríamos decir que no sólo el ordenador es mío, sino que todavía, si calculamos gastos, me deben una pasta.

Bueno, pues ahora ese ordenador está en el curro y yo en mi casa estaría con una mano delante y otra detrás si no fuera por el iMAC. Todo vino con el cierre de la central en Madrid, por motivos que no vienen al caso y que no están relacionados con la crisis actual. El hecho es que en Madrid se ha dejado una pequeña oficina a cargo de una persona y todo lo demás se ha trasladado a Pinoso, a treinta minutos en coche desde donde yo vivo.

Mis condiciones iniciales contemplaban un máximo de dos días en la empresa y tres en casa, al menos eso fue lo tratado en un principio y que no está escrito en ningún lado. He pasado varios años trabajando casi exclusivamente en casa porque eso de ir de Alicante a Madrid dos días a la semana como que no tenía mucho sentido. Ahora sí, ahora sí que es posible.

El problema no es que vaya dos, sino que voy cinco. Y de chiripa que no voy más. De momento no me quejo, al menos no mucho, pero el hecho es que MI ordenador está allí y yo aquí. Y lo que iban a ser unos días para terminar un proyecto –y de paso que el jefe pudera salir dejando a alguien de [supuesta] confianza en la empresa- está por convertirse en un fijo, ni deseado ni creo que permitido por mi parte… Además, entre unas cosas y otras he pasado de currar 6/8 horas a currar unas 11 al día. Bueno, currar curro 8, pero entre idas, venidas, cosas que antes aprovechaba en los descansos por estar en casa, se han convertido en 11. Intolerable desde mi punto de vista comparado con lo anterior, y no, no quiero más pasta, quiero más tiempo libre… De momento, como consecuencia directa de eso, he dejado de actualizarme profesionalmente, al menos profesionalmente respecto a mi trabajo actual.

Y no os he contado por qué no fui al último TTT/Open Day…

Bueno, basta ya de lloros y quejas.

 

Ahora imaginaros la situación. Un pecero rabioso y empedernido de toda la vida, enfrente de un MAC, sin más cojones que tener que usar un MAC. Porque ha intentado utilizar su HP Touchsmart TM2 pero es demasiado lento, tiene la pantalla demasiado pequeña y muy poco disco duro.

Al MAC lo primero que hice fue meterle una máquina virtual con Windows 7 y operar desde ella. No es que el Fusion vaya mal, que no va, y es más rápido que la versión de Windows, pero como que no llena. Además, Visual Studio y otras herramientas como que no van todo lo sueltas que debieran.

Así que el RFOG empezó a usar la interfaz del MAC por cojones. Porque no tenía otra. Bueno, esto no es del todo cierto, porque con ir a una tienda y comprarme otro PC, listo. Pero ya de paso quería aprovechar ese iMAC…

… Y pasó lo que tenía que pasar. Al RFOG no sólo le mola mazo el iMAC, sino que está empezando a gustarle más que Windows. Además, se ha comprado un teclado Apple extendido, un Magic Mouse y tiene la tableta en la agencia de transporte.

Porque mola. El teclado extendido lo ha comprado por costumbre. Aunque su Microsoft Comfort Curve no le va mal (el Wave Pro de Logitech simplemente no funciona y hace cosas rarísimas), resulta que todos los teclados en todos los MAC son iguales, con el mismo tacto, el mismo tamaño, las teclas en el mismo sitio, etc. Así que si te acostumbras a un teclado, te has acostumbrado a todos.

El Magic Mouse es la rehostia, aunque al RFOG se le enredan los dedos. Es un ratón normal con dos botones físicos ocultos, pero la superficie es tactil y, aunque soporta hasta cuatro dedos, el driver oficial sólo funciona con dos. Existen programas de terceros que añaden hasta los cuatro dedos, pero los mouse gestures sobre una superficie tan pequeña y curva son complicados. No obstante eso de mover los dedos sobre la superficie del ratón como si fuera una tableta está genial. Para navegar, para moverse entre fotos y páginas de documentos… Ya la bolita del anterior tenía su cosa, pero en este lo han mejorado, sobre todo cuando la interfaz de los programas está preparada para ello.

En cuanto al Snow Leopard, es una gozada una vez te has aprendido cómo funciona, sobre todo la Shell, compuesta por el Finder (el navegador de archivos), el Dock (el lanzador de aplicaciones), el Exposé y Dashboard (los applets similares al sidebar de windows y el gestor de ventanas) y los Spaces (monitores virtuales). Y no veais la que se viene encima con el león… Si lo que se adivina sobre lo visto es como uno se imagina, de nuevo Windows va a quedar a la misma altura que estaba cuando salió Leopard comparado con XP.

Otra de las cosas que funcionan realmente bien es el Spotlight, equivalente al Windows Search, pero mucho más funcional y rápido. Y más integrado. En una ventanilla minúscula hay encerrado un poder que todas las variantes de búsqueda de Windows desarían tener. Bueno, realmente las tienen, pero repartidas en varias partes y no funcionan tan sueltas. En Windows, la búsqueda del menú inicio sería lo más parecido, pero no igual.

No obstante sí que hay cosas que siguen sin gustarme, pero son las menos. Por ejemplo las teclas de incio y fin, que van al inicio y al fin del documento, no de la página o de la línea activa si estás editando (y no hay equivalente a saltar entre palabras o ir al inicio/fin de la línea, o al menos yo no las he encontrado). El teclado normal no tiene la tecla de suprimir, pero el extendido sí (no obstante se llama «delete»). CMD es la tecla Windows, la de control sirve para casi lo mismo que la de Windows, pero la de «alt» tiene otra funcionalidad completamente diferente (aunque muy útil, ya que es el «comando alternativo»: si, por ejemplo, una combinación de teclas pregunta confirmación, si la pulsamos con alt no lo hará).

No existe una combinación global para llamar al finder desde cualquier sitio, ni siquiera desde Soptlight (como Win+E en Windows), aunque si estamos en él sí que ha atajos para abrir directamente las carpetas especiales.

Todo esto lo estoy aprendiendo gracias a dos libros (bueno, realmente es uno solo, con pequeñas diferencias entre las dos versiones), ambos de David Pogue. Uno de ellos se llama Switching to the MAC. Snow Leopard Edition, y el otro MAC OS X Snow Leopard. El primero enfoca el sistema operativo desde el punto de vista de un usuario de Windows que se está pasando a MAC (mi caso), y el otro es un libro que presenta las cosas desde cero. Ambos están escritos con buen humor y son, lo que llevo de ambos (los voy leyendo a la vez, como para fijar las ideas), muy completos y competentes.

Por otro lado, da gusto trabajar con el soporte de redes del MAC. Enciendes algo y segundos después ya lo tienes listado en la sección de compartido del Finder, y no se desconecta, ni se queda autista, ni hace cosas raras como algunas veces pasa en Windows. De hecho, todavía estoy esperando que me funcione el acceso al NAS por nombre netbios desde Windows… En MAC es encender el NAS y ahí lo tengo, listo para currar. Y encima mueve los ficheros más rápido.

Pues bueno, chicos, eso es todo lo que le está pasando al RFOG, y por qué tiene el blog medio abandonado, y por qué tarda tanto a responder en los foros de la MSDN… Esperemos que el tema del curro se le solucione pronto, pero me da que el gusano del MAC no se le va a ir tan pronto…