Encapsular comandos - CGastrell/phonegap GitHub Wiki
Por que encapsular comandos?
Primero porque nos acerca al paradigma de Programacion Orientada a Objetos. Segundo porque nos permite un nivel de control extra de cosas que deben suceder cuando queremos hacer algo. En este caso, al momento de reproducir un archivo de audio, necesitamos que otras cosas sucedan al mismo tiempo.
Play, Pausa, Play, Pausa...
Como tenemos el codigo hasta ahora solo hemos dado funcionalidad de play y pausa a traves de los botones. Vamos a crear 2 metodos que nos permitan alistar otras partes de la interfaz: mediaApi.play()
y mediaApi.pausa()
.
Play
Al momento de comenzar con la reproduccion del archivo de audio vamos a establecer varios parametros:
- Una variable que nos indique que estamos reproduciendo el archivo
- Un timer que vaya controlando y preguntando en que momento estamos del archivo de audio
- Inutilizar la funcion del boton Play para no intentar ejecutar 2 veces la misma instruccion
Que timer?
Para continuamente verificar un valor usamos un interval. Un interval se instancia con el comando setInterval
:
setInterval
lleva 2 argumentos:
- Callback - {Function}: una funcion que se ejecutara cada vez que el intervalo se cumpla
- Interval - {Int}: cantidad de milisegundos entre intervalos de ejecucion de la funcion callback
Pueden probar esto en la consola de Chrome:
setInterval(function(){ console.log(new Date()); }, 2000);
Y cada 2 segundos se imprimira la fecha en consola.
Un interval corre eternamente, no tiene un limite de ejecucion. Para frenarlo/cancelarlo, guardamos una referencia al interval y luego llamamos clearInterval(ref)
donde ref es la variable donde almacenamos la referencia del intervalo.
De nuevo en la consola de Chrome:
var mi_interval = setInterval(function(){console.log(new Date())}, 2000);
Y luego podemos ejecutar clearInterval(mi_interval)
y se cancelara el intervalo.
Para nuestra utilidad, vamos a definir la variable en mediaApi.interval
, donde siempre almacenaremos una instancia de intervalo. Cuando? Cuando empecemos a reproducir el archivo.
Cambiemos la funcion del boton de play:
//inicializacion de botones
$('#play').click(function(e) {
e.preventDefault();
mediaApi.play();
});
Y en mediaApi
agregamos el metodo play()
:
play: function() {
if(mediaApi.isPlaying) {
return;
}
mediaApi.interval = setInterval(function(){
mediaApi.audio.getCurrentPosition(function(t){
mediaApi.currentTime.text( ((t * 100) << 0) / 100 );
});
},50);
mediaApi.isPlaying = true;
mediaApi.audio.play();
},
play()
verifica si estamos reproduciendo algun audio (mediaApi.isPlaying == true
), seria bueno agregar esta variable en la funcion initialize
. Si mediaApi.isPlaying
no evalua a true
la funcion se cancela (return
).
Luego define la variable mediaApi.interval
y le asigna un setInterval
. setInterval
sera un intervalo ejecutado cada 50 milisegundos y en cada ejecucion pedira al archivo de audio (mediaApi.audio
) la funcion getCurrentPosition
, la cual a su vez devolvera una funcion con un parametro que indica en que tiempo de reproduccion esta el archivo de audio.
Si el parametro es menor que 0 (cero) significa que el archivo ya no esta reproduciendose, en cuyo caso limpiaremos el intervalo y asignaremos mediaApi.isPlaying = false
. De no ser asi (el tiempo de reproduccion del archivo de audio es mayor o igual a 0), actualizaremos nuestra interfaz para que nos muestre este valor.
Una vez que configuramos todo esto, finalmente indicamos al archivo de audio que debe reproducirse: mediaApi.audio.play()
Pausa
Ahora que tenemos la funcionalidad en el metodo play()
debemos actualizar la funcion del boton de pausa
:
$('#pausa').click(function(e){
e.preventDefault();
mediaApi.pausa();
});
Y agregar el metodo mediaApi.pausa()
cancelando todo lo hecho en el metodo play()
:
pausa: function() {
if(!mediaApi.isPlaying) {
return;
}
clearInterval(mediaApi.interval);
mediaApi.isPlaying = false;
mediaApi.audio.pause();
},
En la inversa de play()
, si mediaApi.isPlaying
NO evalua a true
cancelamos la funcion con return
. Luego limpiamos el intervalo (recuerdan que lo asignamos a mediaApi.interval
?), asignammos mediaApi.isPlaying = false
y pausamos el archivo de audio.
Limpieza
Con esta funcionalidad implementada y el interval controlando la actualizacion del tiempo de reproduccion solo restaria hacer algo de limpieza.
Cuando el archivo de audio termine de reproducirse nada le dice al intervalo que debe detenerse, este seguira ejecutandose. Entonces haremos la limpieza en el onSuccess
handler:
onSuccess: function(){
if(mediaApi.interval) { // <-- check
clearInterval(mediaApi.interval); // <-- clear
mediaApi.currentTime.text(0); // <-- reset
mediaApi.interval = null; // <-- reset
mediaApi.isPlaying = false; // <-- switch
}
console.log('media stop/played/rec success');
},
A esta altura ya deberiamos tener algo presentable. Eso o no anda nada. Probemos.
A continuacion vamos a resolver algunos problemas heredados del plugin. Hack time!