Capítulo 19. Agenda con mensajes sonoros

El presente caso de estudio corresponde al trabajo desarrollado por Susana Sánchez para la realización de una agenda básica, con la peculiaridad de incorporar la programación de mensajes para una hora (fecha) dada y que, en su momento, serán expuestos en forma de audio al usuario. El usuario crea estos mensajes en formato de texto (en la forma en que se muestra en la Figura 19-1) y es la aplicación la que se ha de encargar de transformalos en audio (en este caso en voz) para reproducirlos en el momento oportuno.

Figura 19-1. Formato de la tarjeta que permite la especificación de un mensaje y su programación en el tiempo.

La aplicación está diseñada en torno a una sencilla pila que dispone en cada tarjeta los controles necesarios para cada tarea y son:

La pila da incio a todo el proceso teniendo en cuenta que en posteriores ejecuciones de la misma pueden haber eventos ya planificados (programados con anterioridad) que hay que dar opción a que lo sean, por ello, el principio se dedica a confirmar que en el directorio que acoje a los ficheros de datos de la pila existan o no ficheros de audio: eventos ya preparados.

#
# Pila principal
#
global i, fichero, citas, hora_actual

On preopenstack
  if there is a directory "c:\Agenda" then
    set the directory to "c:\Agenda\"
  else
    create directory "c:\Agenda\"
    set the directory to "c:\Agenda\"
  end if
end preopenstack

on openStack
  set the directory to "c:\Agenda\"
  put the files into url "binfile:c:\Agenda\audios.txt"
  send "testfecha" to fld "comprobarFecha" of card "titulo" of stack "agenda"
  #  go to card 1
end openStack
                  

El esquema de nombres para los ficheros debe ser lo suficiente como para dar cumplimiento a la tarea. Por este motivo los ficheros se nombrarán como una expresión de fecha (que incluirá día, mes y año) y hora(en formato de hora y minutos) más la extensión del fichero.

Figura 19-2. Tarjetas que componen la aplicación, la pila principal: entrada (título), configuración del audio y controles del recordatorio.

El título de la aplicación se presenta en una tarjeta que, diligentemente, da paso a la que permite establecer un recordatorio: la tarjeta "tarjeta". De paso, se ha aprovechado para contener funciones que se utilizarán más tarde en esa propia tarjeta.

#
# Tarjeta "titulo"
#
on openCard
  send mouseUp to me in 3 seconds
end openCard

on mouseUp
  go to card "tarjeta"
end mouseUp


#
# Campo de texto "comprobarFecha" (oculto)
#
global citas, mes, dia,year, anyo, au_fecha
on testfecha 
  convert time() to dateitems
  put it into citas
  if item 3 of citas <10 then put "0"&item 3 of citas into dia
  else put item 3 of citas into dia
  if item 2 of citas <10 then put "0"&item 2 of citas into mes
  else put item 2 of citas into mes
  put item 1 of citas into year
  put char 3 of year &char 4 of year into anyo
  
  send "testhora" to fld "quien" of card "titulo" of stack "agenda"
  
end testfecha


#
#Campo de texto "voces"
#
on formatos
  global hora_actual
  if matchtext (url "c:\Agenda\audios.txt", hora_actual&".aiff") then
    play hora_actual&".aiff"
    delete file hora_actual&".aiff"
  end if
  send "testfecha" to fld "comprobarFecha" of card "titulo" of stack "agenda" in 60 seconds
end formatos


#
# Campo de texto "VS" (que contiene la versión de la aplicación)
#
on fechayhoraok
  global hora_actual
  delete file "c:\Agenda\audios.txt"
  open file "c:\Agenda\audios.txt" for read
  put the files into url "binfile:c:/Agenda/audios.txt"
  if matchtext (url "c:\Agenda\audios.txt", hora_actual&".wav") then
    play hora_actual&".wav"
    delete file hora_actual&".wav"
  end if
  if matchtext (url "c:\Agenda\audios.txt", hora_actual&".au") then
    play hora_actual&".au"
    delete file hora_actual&".au"
  end if
  send "formatos" to fld "voces" of card "titulo" of stack "agenda"
  
end fechayhoraok


#
#Campo de texto "quien" (que guarda la autoría de la obra)
#
global dia, citas, mes,year, anyo, au_fecha, hora, minu, au_hora, hora_actual
on testhora
  put  dia&mes&anyo into au_fecha
  if item 4 of citas <10 then put "0"&item 4 of citas into hora
  else put item 4 of citas into hora
  if item 5 of citas <10 then put "0"&item 5 of citas into minu
  else put item 5 of citas into minu
  --put hora&minu into au_hora
  
  put au_fecha&","&hora&minu into hora_actual
  send "fechayhoraok" to fld "vs" of card "titulo" of stack "agenda"
  
end testhora


                  

En la tarjeta que es protagonista de todo este caso, se puede encontrar la serie de controles que permiten la edición de un mensaje, su programación en el tiempo (incluyendo la conversión a audio), la configuración del audio a generar, la ayuda y una opción para terminar la aplicación.

Nada más entrar en la tarjeta se limpian los campos editables para que el usuario pueda empezar desde esa situación. La cual puede recuperar en cualquier momento utilizando el botón cuya leyenda reza Nueva. Ambos códigos son idénticos.

#
# Tarjeta "tarjeta"
#
#global i, fichero, citas, hora_actual, cinco, au_hora,au_fecha
on openCard
 put empty into fld "cita"
  put empty into fld "hora"
  put empty into fld "fecha"
end openCard

#
# Botón "nuevo" (que muestra "Nueva")
#
on mouseUp
  put empty into fld "cita"
  put empty into fld "hora"
  put empty into fld "fecha"
end mouseUp

#
# Botón "recordar" (que muestra un texto de "Grabar")
#
on mouseUp
  global fichero, texto1, audio, velocidad
  if the length of fld "fecha" <> 8 then \
      answer warning "El formato de la fecha debe ser dd/mm/aa" \
                     with "OK" titled "Fecha errónea"
  if the length of fld "hora" <> 5 then \
     answer warning "El formato de la hora debe ser hh:mm" \
                    with "OK" titled "Hora errónea"
  
  palette stack "descargando"
  
  if audio is empty then put ".wav" into audio
  if velocidad is empty then put "normal" into velocidad

  put urlEncode(text of fld "cita" of this card) into texto1
  put (char 1 of fld "fecha"&  char 2 of fld "fecha"&\
           char 4 of fld "fecha"&  char 5 of fld "fecha"&\
           char 7 of fld "fecha"&  char 8 of fld "fecha"&\
           ","&char 1 of fld "hora"& char 2 of fld "hora"&\
           char 4 of fld "hora"& char 5 of fld "hora") into fichero
  put url ("http://wwwtts.research.bell-labs.com/cgi-user/tts/spanishtts?text=" &\
                 texto1 &\
                 "&rate=normal&dialect=Castilian&audio="&\
                 audio) into url ("binfile:"&fichero&audio)
  close stack "descargando"
end mouseUp


#
#Botón "config" ("Configuración del texto")
#
global cinco

on mouseUp
  visual effect scroll left
  go to card "Configura"
end mouseUp

on cinco
  convert time() to dateitems
  put it into minuto
  if (minuto mod 5) =0 then put si into cinco
  else put (minuto mod 5) into x
  send cinco to me in 1 minute
end cinco
                  

En la parte baja de la tarjeta hay están los otros dos controles que hemos enunciado:

#
# Botón "ayuda"
#
on mouseUp
  palette stack "ayuda"
end mouseUp

#
#Botón "salir"
#
on mouseUp
  quit
end mouseUp
                  

Si se ha utilizado el botón Configuración del audio, se accede a la sencilla tarjeta que pemite establecer la velocidad y el tipo de fichero:

#
# Tarjeta "Configura"
#

# Botón "au"
global audio
on mouseUp
  put ".au" into audio
end mouseUp

# Botón "wav"
global audio
on mouseUp
  put ".wav" into audio
end mouseUp

# Botón "aiff"
global audio
on mouseUp
  put ".aiff" into audio
end mouseUp

# Botón "f" (con el texto "Rápido")
global velocidad
on mouseUp
  put "fast" into velocidad
end mouseUp

# Botón "s" (con el texto "Lento")
global velocidad
on mouseUp
  put "slow" into velocidad
end mouseUp

# Botón "n" (con el texto "Normal")
global velocidad
on mouseUp
  put "normal" into velocidad
end mouseUp

                  

La aplicación se apoya en otras pilas del sistema para realizar su tarea y se ha creado una a propósito de la obtención de los ficheros desde la web, que es de particular interés en este caso (Figura 19-3).

La pila de "descargando" se utiliza para mostrar los mensajes al usuario que a este respecto se den. Sólo se emplea código para estas tareas que se concreta en la presentación del primer mensaje, que realiza el:

on openCard
  hide fld texto
  show fld texto with visual effect scroll left very slow
end openCard
                  

y en los botones de Aceptar que cerrarán esta propia pila con

on mouseUp
  quit
end mouseUp
                  

Figura 19-3. Otras pilas forman parte del proyecto, aparte de las habituales del sistema, para informar del estado de la descarga de ficheros desde la web.

Como en toda aplicación se agradece que exista un apartado de ayuda, en este caso relativa a la secuencia de acciones a desarrollar para emplear la misma. La pila destinada a contener la ayuda es las más sencilla: tiene botones que perimten una navegación muy básica y se puede ver en la Figura 19-4. El código que esta contiene es tan sencillo como:

#
# Pila "Ayuda"
#

# Botón "Aceptar" (de la primera tarjeta) y "Salir" (de la segunda)
on mouseUp
  close this stack
end mouseUp

# Botón "Continuar"
on mouseUp
  go to next card
end mouseUp
	

Figura 19-4. Tarjetas de la pila "Ayuda".

Conclusiones

En esta sección se ha presentado la primera parte y se propone una "Agenda 2ª parte". Esta es una continuación de la agenda de Susana planteada como grabadora de mensajes con un par de variantes:

Al respecto del código original, a mi parecer, no es buena idea utilizar objetos que tienen dos misiones diferentes por la complicación que supone asociar dichas tareas a un objeto: me refiero a los controles que, ocultos o no, en la primera tarjeta guardan código para comprobar la fecha al tiempo que muestran un texto estático en la aplicación.

Por otra parte, el lector que ha seguido la obra habrá podido apreciar que esta aplicación, tal como está, sólo puede utilizarse en un sistema operativo que tenga por costrumbre poner nombre (con un criterio variable en función de su punto de montaje) a sus unidades de disco y en un directorio que no están bajo el control del usuario. Sería muy interesante deshacerse de esta lacra en las futuras versiones.

Aunque la aplicación fue desarrollada a finales del año 2000, el formato en que se exprea el año no sobreviviría al "efecto 2000" o similar. Debido a la aplicación en cuestión, tampoco parece necesario insistir más sobre que el comentarlo.

Lo que si es posible es mejorar cuestiones en las que se utiliza código de forma muy recurrente, como en la asignación de valores a variables globales de la configuración del audio. Para poder ampliar esta sección sería necesario crear nuevos controles y darles código. En cambio, si este fuese en función de su nombre hubiese facilitado la creación de los existentes y la posible ampliación, si fuera el caso. Por ejemplo, agrupando los controles que dan la extensión al archivo y nombrándolos como tales extensiones se podría haber hecho:

#
# En el grupo correspondiente ...
#
global audio

on mouseUp
  put the short name of target into audio
end mouseUp