sábado, 11 de mayo de 2013

Entrada 13: Interfaz gráfica de usuario II - Abril 2013

La forma de implementar el servidor la vamos a llevar a cabo siguiendo el patrón MVC (modelo vista controlador). El controlador se encarga de realizar las acciones correspondientes según las peticiones que realice el usuario, que se reflejan en el servidor por medio de rutas. De esas acciones, las que tienen que ver con las vistas las realizar el módulo de vista y las que están relacionadas con los flujos de datos y ejecución de procesos las realiza el modelo.

De acuerdo a como definimos el comportamiento de la aplicación al final de la entrada anterior, vamos a tener tres vistas: index.html, recording.html y results.html. La primera será la que renderizará el botón "Graba", la segunda el cronómetro con el botón "Parar" y "Realizar el reconocimiento" y la tercera el resultado en una segunda variable a la que hemos llamado <%r1%> y un botón para volver al inicio de la aplicación.

Cada uno de los botones tiene una ruta asociada y, por tanto, una llamada al controlador para que decida que acciones realizar. Con todo esto, y a falta de definir las acciones, el servidor tendría la siguiente forma:
//Módulos a importar:
var http = require('http');
var URL = require('url');
var fs = require('fs');
var mime = require('mime');
var qs = require('querystring');
//Otros módulos y variables que se usan luego:
var exec = require('child_process').exec;
var child;
var tmpAudio = "";
var result = "";
//Traza para la consola:
var first=true;
if (first) {
   console.log('server inicializado');
   first=false;
}
//Servidor:
http.createServer(function(request, response){ 
   //Modelo: 
   var model = {
      //ACCIONES DEL MODELO
   } 
   //Vista:
   var view = {
      render: function (file,r1) {
  fs.readFile('app.html', 'utf-8', function(err, app) {
     if (!err) {
  fs.readFile(file, 'utf-8', function(err, view) {
        if (!err) {
        var data = app.replace(/<%view%>/, view);
        data = data.replace(/<%r1%>/, r1);
        response.writeHead(200, {
   'Content-Type': 'text/html'
        });
        response.end(data);
     } else {
        view.error(500, "Error al renderizar la vista");
     };
  });
     } else {
  view.error(500, "Error en la interfaz gráfica");
     }
  });
      },
      error: function(code, msg) {
  response.writeHead(code); 
  response.end(msg);
      },
      file: function(file) {
  fs.readFile(file, function(err, data) {
     if (!err) {
        response.writeHead(200, {
  'Content-Type': mime.lookup(file)
        });
        response.end(data);
     } else {
        view.error (500, file + " not found");
     }
  });
      }
   } 
   //Controlador:
   var controller = {
      index: function () {
 view.render('index.html',"");
      },
      recording: function () {
 //BOTÓN "GRABAR"
      },
      init: function () {
 //BOTÓN "PARAR"
      },
      results: function () {
 //BOTÓN "REALIZAR EL RECONOCIMIENTO"
      },
      file: function () { view.file(url.pathname.slice(1)); }
   }
   //Routing: 
   var url = URL.parse(request.url, true);
   var post_data = "";
   request.on('data', function(chunk){ post_data += chunk; });
   request.on('end', function() {
      post_data = qs.parse(post_data);
      var route = (post_data._method || request.method) + ' ' + url.pathname;
         switch (route) {
            case 'GET /lidonrpi/index'     : controller.index(); break;
     case 'GET /lidonrpi/recording' : controller.recording(); break;
     case 'GET /lidonrpi/results'   : controller.results(); break;
     case 'GET /init'               : controller.init(); break;
     default: {
        if (request.method == 'GET') {
           controller.file();
        } else {
    view.error(400, "Petición no contemplada");
        }
     }
         }
   });
}).listen(3000);
La vista index es un botón que lanza el proceso de grabación. Para realizar estas acciones generamos la vista (index.html) y la acción asociada al botón (controller.recording()), que es lanzar el proceso de grabación (model.record()) y renderizar la siguiente vista (view.render('recording.html',"")); de modo que los cambios a realizar son:
  • Index.html:
<form method="GET" action="/lidonrpi/recording">
   <input type="submit" value="Grabar">
</form>
  • En el controlador, en controller.recording():
model.record();
view.render('recording.html',"");
  • En el modelo, creo model.record():
record: function () {
   tmpAudio = new Date().getTime();
   console.log("grabando en " + tmpAudio + ".wav" + '\n');
   child = exec('./scripts/graba.sh '+tmpAudio,
      function (error, stdout, stderr) {
         console.log('graba.sh -> stdout: ' + stdout);       
         console.log('graba.sh -> stderr: ' + stderr);
         if (error !== null) {
            console.log('graba.sh -> exec error: ' + error);
         }
   });
},

No hay comentarios:

Publicar un comentario