#!/usr/bin/python # Copyright (C) 2012 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import numpy as np import scipy as sp import socket import struct sys.path.append(sys.path[0] + "/processing") from consts import * builtinFunctions = [ "echo", # send back whatever is received "intsum", # returns int64 + int64 ] CMD_HEADER = 0x0 CMD_TERMINATE = 0x1 CMD_FUNCTION = 0x2 CMD_AUDIO_MONO = 0x4 CMD_AUDIO_STEREO = 0x5 CMD_INT64 = 0x8 CMD_DOUBLE = 0x9 CMD_RESULT = 0x10 def echo(inputData, inputTypes): output = [] print "echo received ", inputData output.append(RESULT_OK) output.append(inputData) output.append(inputTypes) return output def intsum(inputData, inputTypes): output = [] output.append(RESULT_OK) sum = inputData[0] + inputData[1] print "intsum sum is ", sum outputData = [] outputData.append(sum) outputTypes = [] outputTypes.append(TYPE_I64) output.append(outputData) output.append(outputTypes) return output class CommandHandler(object): def __init__(self, conn): self.conn = conn def __del__(self): self.conn.close() def run(self): header = self.readI32() if header == CMD_TERMINATE: print "terminate cmd, will exit" sys.exit(0) nParam = 0 if header == CMD_HEADER: nParam = self.readI32() if nParam < 1: protocolError("wrong number of params") cmdFunction = self.readI32() if cmdFunction != CMD_FUNCTION: protocolError("not function") nameLen = self.readI32() self.functionName = self.readRaw(nameLen) print "Processing function:", self.functionName inputData = [] inputTypes = [] for i in range(nParam - 1): cmd = self.readI32() if (cmd == CMD_AUDIO_STEREO) or (cmd == CMD_AUDIO_MONO): dataLen = self.readI32() data = self.readI16Array(dataLen / 2) inputData.append(data) if (cmd == CMD_AUDIO_STEREO): inputTypes.append(TYPE_STEREO) else: inputTypes.append(TYPE_MONO) print i, "-th input received audio data ", dataLen, cmd elif cmd == CMD_INT64: i64 = self.readI64() inputData.append(i64) inputTypes.append(TYPE_I64) elif cmd == CMD_DOUBLE: val = self.readDouble() inputData.append(val) inputTypes.append(TYPE_DOUBLE) else: self.protocolError("unknown command " + str(cmd)) print "inputTypes ", inputTypes # length 3 list # output[0]: int, execution result, RESULT_XXX values # output[1]: output data list # output[2]: output type list output = [] if not self.functionName in builtinFunctions: mod = __import__(self.functionName) output = getattr(mod, self.functionName)(inputData, inputTypes) else: output = globals()[self.functionName](inputData, inputTypes) nOutputParams = len(output[1]) self.sendI32(CMD_HEADER) self.sendI32(nOutputParams + 1) # 1 for result self.sendI32(CMD_RESULT) self.sendI32(output[0]) outputData = output[1] outputTypes = output[2] print "outputTypes ", outputTypes for i in range(nOutputParams): if (outputTypes[i] == TYPE_I64): self.sendI32(CMD_INT64) self.sendI64(outputData[i]) elif (outputTypes[i] == TYPE_DOUBLE): self.sendI32(CMD_DOUBLE) self.sendDouble(outputData[i]) elif (outputTypes[i] == TYPE_STEREO): self.sendI32(CMD_AUDIO_STEREO) self.sendI32(len(outputData[i]) * 2) self.sendI16Array(outputData[i]) elif (outputTypes[i] == TYPE_MONO): self.sendI32(CMD_AUDIO_MONO) self.sendI32(len(outputData[i]) * 2) self.sendI16Array(outputData[i]) else: print "unknown type ", outputTypes[i], \ " returned from funcion ", self.functionName sys.exit(1) def readRaw(self, length): result = [] totalRead = 0 while totalRead < length: raw = self.conn.recv(length - totalRead) justRead = len(raw) if justRead == 0: # socket closed sys.exit(1) totalRead += justRead result.append(raw) return ''.join(result) def readI32(self): raw = self.readRaw(4) i32 = struct.unpack("<i", raw) return i32[0] def readI64(self): raw = self.readRaw(8) i64 = struct.unpack("<q", raw) return i64[0] def readDouble(self): raw = self.readRaw(8) val = struct.unpack("<d", raw) return val[0] def readI16Array(self, length): raw = self.readRaw(length * 2) data = np.fromstring(raw, dtype=np.int16) return data def sendI32(self, i32): raw = struct.pack("<i", i32) self.sendRaw(raw) def sendI64(self, i64): raw = struct.pack("<q", i64) self.sendRaw(raw) def sendDouble(self, val): raw = struct.pack("<d", val) self.sendRaw(raw) def sendI16Array(self, arry): raw = arry.tostring() self.sendRaw(raw) def sendRaw(self, rawString): totalSent = 0 stringLen = len(rawString) while totalSent < stringLen: sent = self.conn.send(rawString[totalSent:]) totalSent += sent def protocolError(self, message): print message sys.exit(1) if __name__=="__main__": HOST = "localhost" PORT = 15010 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((HOST, PORT)) s.listen(1) conn, addr = s.accept() print "client connected" # close the server socket to allow other instance to run s.close() handler = CommandHandler(conn) while 1: handler.run()