Titanium Nagoya Chatroom Vol. 2

に参加してきました。
http://atnd.org/events/25349:TitaniumNagoyaChatroomVol2
そこで紹介したアプリのコードをとりあえずここに上げときます。

Titanium.UI.setBackgroundColor('#000');

// constants

var consts = {
  IPAddress: Ti.Platform.address,
  ServerPort: 54321,
  BufferSize: 1024 * 64,
  NumberOfImages: 9
};
var funcs = {
  readCallback: null,
  sendPhoto: null,
  sendPhotoTo: null,
  connectTo: null,
  scanServers: null,
  setImageView: null
};
var vars = {
  scanIndex: 0,
  Sockets: {},
  myImageFile: null,
  ImageViews: [],
  ImageViewIndex: 0,
};

// Views

var win = Titanium.UI.createWindow({
  title : 'Photo Exchange',
  backgroundColor : '#fff'
});
var view = Ti.UI.createView({
  width : "100%",
  height : "100%",
  layout : "horizontal",
  backgroundColor : "#eee"
});
win.add(view);

var logarea1 = Ti.UI.createTextArea({
  value : '',
  editable : false,
  font : {
    fontSize : 14
  },
  left : 0,
  top : 0,
  width : 160,
  height : 150
});
var logarea2 = Ti.UI.createTextArea({
  value : '',
  editable : false,
  font : {
    fontSize : 14
  },
  left : 0,
  top : 0,
  width : 160,
  height : 150
});
view.add(logarea1);
view.add(logarea2)
var addToLog1 = function(msg) {
  var text = msg + logarea1.value;
  if(text.length > 1000)
    text = text.substring(0, 1000);
  logarea1.value = text;
};
var addToLog2 = function(msg) {
  var text = msg + logarea2.value;
  if(text.length > 1000)
    text = text.substring(0, 1000);
  logarea2.value = text;
};

var myImageView = Ti.UI.createImageView({
  width : 160,
  height : 120,
  left : 0,
  top : 0,
  backgroundColor : '#888'
});
view.add(myImageView);

var cameraButton = Ti.UI.createButton({
  title : 'camera',
  left : 0,
  top : 40,
  width : 160,
  height : 40
});
view.add(cameraButton);

for (var i = 0; i < consts.NumberOfImages; i ++) {
  var imageView = Ti.UI.createImageView({
    left: 0,
    top: 0,
    width: 154,
    height: 118,
    borderWidth: 1,
    backgroundColor: '#88c'
  });
  vars.ImageViews[i] = imageView;
  view.add(imageView);
}

win.open();

// camera

cameraButton.addEventListener('click', function() {
  Titanium.Media.showCamera({
    success : function(event) {
      var cropRect = event.cropRect;
      var image = event.media;
      myImageView.image = image;
      var myImage = myImageView.toImage();
      var file = Ti.Filesystem.createTempFile(Ti.Filesystem.tempDirectory)
      addToLog1("size:" + file.size + "\n");
      file.write(Ti.Android ? myImage.media : myImage);
      if (file.size > 400)
        vars.myImageFile = file;
      addToLog1("size:" + file.size + " path:" + file.nativePath + "\n");
      funcs.sendPhoto();
    },
    cancel : function() {
    },
    error : function(error) {
    },
    saveToPhotoGallery : false,
    allowEditing : false,
    mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO],
  });
});

// functions

funcs.setImageView = function(image) {
  vars.ImageViews[vars.ImageViewIndex].image = image;
  vars.ImageViewIndex = (vars.ImageViewIndex + 1) % consts.NumberOfImages;
};

funcs.connectTo = function(index) {
  var aa = consts.IPAddress.split(".");
  aa[3] = index;
  var socket = Ti.Network.Socket.createTCP({
    port : consts.ServerPort,
    host : aa.join("."),
    connected : function(e) {
      var cs = e.socket;
      cs.readBuffer = Ti.createBuffer({
        length : consts.BufferSize
      });
      var index = parseInt(cs.host.split(".")[3]);
      vars.Sockets[index] = cs;
      Ti.Stream.read(cs, cs.readBuffer, funcs.readCallback);
      addToLog1("connected to " + index + "\n");
      funcs.sendPhotoTo(index);
    },
    error : function(e) {
      var index = parseInt(e.socket.host.split(".")[3]);
      vars.Sockets[index] = null;
      addToLog2(" " + index);
    }
  });
  socket.connect();
};

funcs.sendPhotoTo = function(index) {
  if (!vars.myImageFile)
    return;
  var socket = vars.Sockets[index];
  if (!socket)
    return;
  addToLog2(" " + socket + "index");
  if (socket.state != Ti.Network.Socket.CONNECTED) {
    vars.Sockets[index] = null;
    return;
  }

  addToLog1("send to " + socket.host + "\n");
  var img = vars.myImageFile.read();
  var stream = Ti.Stream.createStream({
    mode : Ti.Stream.MODE_READ,
    source : img
  });
  var len = img.length;
  var header = Ti.createBuffer({length: 4});
  Ti.Codec.encodeNumber({
    source: len,
    position: 0,
    dest: header,
    type: Ti.Codec.TYPE_INT,
    byteOrder: Ti.Codec.BIG_ENDIAN
  })
  var footer = Ti.createBuffer({
    length : consts.BufferSize - len - 4
  });
  addToLog1("photo sending size " + len + "\n");
  socket.write(header);
  Ti.Stream.writeStream(stream, socket, len);
  socket.write(footer);
  addToLog1("photo sent size " + len + "\n");
};

funcs.sendPhoto = function() {
  for(var i = 1; i <= 254; i++)
    funcs.sendPhotoTo(i);
};

// read from socket

funcs.readCallback = function(e) {
  addToLog1("readCallback()\n");
  var socket = e.source;
  var plen = e.bytesProcessed;
  if (plen < 0) {
    var index = parseInt(socket.host.split(".")[3]);
    vars.Sockets[index] = null;
    return;
  }
  addToLog1("read bytes " + plen + "\n");
  if (!socket.inputCache) {
    socket.inputCache = Ti.createBuffer({
      length : consts.BufferSize
    });
    socket.inputIndex = 0;
  }
  var index = 0;
  while (index < plen && socket.inputIndex < consts.BufferSize)
    socket.inputCache[socket.inputIndex++] = socket.readBuffer[index++];
  if (socket.inputIndex == consts.BufferSize) {
    var len = Ti.Codec.decodeNumber({
      source: socket.inputCache,
      position: 0,
      type: Ti.Codec.TYPE_INT,
      byteOrder: Ti.Codec.BIG_ENDIAN
    });
    var imgbuf = socket.inputCache.clone(4, len);
    var image = imgbuf.toBlob();
    funcs.setImageView(image);
    socket.inputIndex = 0;
  }
  while (index < plen)
    socket.inputCache[socket.inputIndex++] = socket.readBuffer[index++];
  addToLog1("cached bytes " + socket.inputIndex + "\n");
  Ti.Stream.read(socket, socket.readBuffer, funcs.readCallback);
};

// listen socket

var listen = Ti.Network.Socket.createTCP({
  port : consts.ServerPort,
  listenQueueSize: 20,
  accepted : function(e) {
    addToLog1("accepted " + e.socket + "\n");
    var asocket = e.inbound;
    asocket.readBuffer = Ti.createBuffer({
      length : consts.BufferSize
    });
    Ti.Stream.read(asocket, asocket.readBuffer, funcs.readCallback);
    var index = parseInt(asocket.host.split(".")[3]);
    vars.Sockets[index] = asocket;
    addToLog1("connect from " + index + "\n");
    funcs.sendPhotoTo(index);
  },
  error : function(e) {
    addToLog1(">> error " + e.error + "\n");
  }
});
listen.listen();
addToLog1(">> listening " + consts.IPAddress + "\n");
listen.accept({});

// scan server

funcs.scanServers = function() {
  vars.scanIndex += 1;
  if (vars.scanIndex >= 254)
    vars.scanIndex = 1;
  if (!vars.Sockets[vars.scanIndex] || 
    vars.Sockets[vars.scanIndex].state != Ti.Network.Socket.CONNECTED) {
    var aa = consts.IPAddress.split(".");
    if(aa[3] != vars.scanIndex)
      funcs.connectTo(vars.scanIndex);
  }
  setTimeout(funcs.scanServers, 235);
};

setTimeout(funcs.scanServers, 1000);