1#!/usr/bin/python 2 3# Copyright (C) 2012 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import sys 18import numpy as np 19import scipy as sp 20import socket 21import struct 22sys.path.append(sys.path[0] + "/processing") 23from consts import * 24 25builtinFunctions = [ 26 "echo", # send back whatever is received 27 "intsum", # returns int64 + int64 28] 29 30CMD_HEADER = 0x0 31CMD_TERMINATE = 0x1 32CMD_FUNCTION = 0x2 33CMD_AUDIO_MONO = 0x4 34CMD_AUDIO_STEREO = 0x5 35CMD_INT64 = 0x8 36CMD_DOUBLE = 0x9 37CMD_RESULT = 0x10 38 39def echo(inputData, inputTypes): 40 output = [] 41 print "echo received ", inputData 42 output.append(RESULT_OK) 43 output.append(inputData) 44 output.append(inputTypes) 45 return output 46 47def intsum(inputData, inputTypes): 48 output = [] 49 output.append(RESULT_OK) 50 sum = inputData[0] + inputData[1] 51 print "intsum sum is ", sum 52 outputData = [] 53 outputData.append(sum) 54 outputTypes = [] 55 outputTypes.append(TYPE_I64) 56 output.append(outputData) 57 output.append(outputTypes) 58 return output 59 60 61class CommandHandler(object): 62 63 def __init__(self, conn): 64 self.conn = conn 65 def __del__(self): 66 self.conn.close() 67 def run(self): 68 header = self.readI32() 69 if header == CMD_TERMINATE: 70 print "terminate cmd, will exit" 71 sys.exit(0) 72 nParam = 0 73 if header == CMD_HEADER: 74 nParam = self.readI32() 75 if nParam < 1: 76 protocolError("wrong number of params") 77 cmdFunction = self.readI32() 78 if cmdFunction != CMD_FUNCTION: 79 protocolError("not function") 80 nameLen = self.readI32() 81 self.functionName = self.readRaw(nameLen) 82 print "Processing function:", self.functionName 83 inputData = [] 84 inputTypes = [] 85 for i in range(nParam - 1): 86 cmd = self.readI32() 87 if (cmd == CMD_AUDIO_STEREO) or (cmd == CMD_AUDIO_MONO): 88 dataLen = self.readI32() 89 data = self.readI16Array(dataLen / 2) 90 inputData.append(data) 91 if (cmd == CMD_AUDIO_STEREO): 92 inputTypes.append(TYPE_STEREO) 93 else: 94 inputTypes.append(TYPE_MONO) 95 print i, "-th input received audio data ", dataLen, cmd 96 elif cmd == CMD_INT64: 97 i64 = self.readI64() 98 inputData.append(i64) 99 inputTypes.append(TYPE_I64) 100 elif cmd == CMD_DOUBLE: 101 val = self.readDouble() 102 inputData.append(val) 103 inputTypes.append(TYPE_DOUBLE) 104 else: 105 self.protocolError("unknown command " + str(cmd)) 106 print "inputTypes ", inputTypes 107 # length 3 list 108 # output[0]: int, execution result, RESULT_XXX values 109 # output[1]: output data list 110 # output[2]: output type list 111 output = [] 112 if not self.functionName in builtinFunctions: 113 mod = __import__(self.functionName) 114 output = getattr(mod, self.functionName)(inputData, inputTypes) 115 else: 116 output = globals()[self.functionName](inputData, inputTypes) 117 nOutputParams = len(output[1]) 118 self.sendI32(CMD_HEADER) 119 self.sendI32(nOutputParams + 1) # 1 for result 120 self.sendI32(CMD_RESULT) 121 self.sendI32(output[0]) 122 outputData = output[1] 123 outputTypes = output[2] 124 print "outputTypes ", outputTypes 125 for i in range(nOutputParams): 126 if (outputTypes[i] == TYPE_I64): 127 self.sendI32(CMD_INT64) 128 self.sendI64(outputData[i]) 129 elif (outputTypes[i] == TYPE_DOUBLE): 130 self.sendI32(CMD_DOUBLE) 131 self.sendDouble(outputData[i]) 132 elif (outputTypes[i] == TYPE_STEREO): 133 self.sendI32(CMD_AUDIO_STEREO) 134 self.sendI32(len(outputData[i]) * 2) 135 self.sendI16Array(outputData[i]) 136 elif (outputTypes[i] == TYPE_MONO): 137 self.sendI32(CMD_AUDIO_MONO) 138 self.sendI32(len(outputData[i]) * 2) 139 self.sendI16Array(outputData[i]) 140 else: 141 print "unknown type ", outputTypes[i], \ 142 " returned from funcion ", self.functionName 143 sys.exit(1) 144 145 def readRaw(self, length): 146 result = [] 147 totalRead = 0 148 while totalRead < length: 149 raw = self.conn.recv(length - totalRead) 150 justRead = len(raw) 151 if justRead == 0: # socket closed 152 sys.exit(1) 153 totalRead += justRead 154 result.append(raw) 155 return ''.join(result) 156 157 def readI32(self): 158 raw = self.readRaw(4) 159 i32 = struct.unpack("<i", raw) 160 return i32[0] 161 162 def readI64(self): 163 raw = self.readRaw(8) 164 i64 = struct.unpack("<q", raw) 165 return i64[0] 166 167 def readDouble(self): 168 raw = self.readRaw(8) 169 val = struct.unpack("<d", raw) 170 return val[0] 171 172 def readI16Array(self, length): 173 raw = self.readRaw(length * 2) 174 data = np.fromstring(raw, dtype=np.int16) 175 return data 176 177 def sendI32(self, i32): 178 raw = struct.pack("<i", i32) 179 self.sendRaw(raw) 180 181 def sendI64(self, i64): 182 raw = struct.pack("<q", i64) 183 self.sendRaw(raw) 184 185 def sendDouble(self, val): 186 raw = struct.pack("<d", val) 187 self.sendRaw(raw) 188 189 def sendI16Array(self, arry): 190 raw = arry.tostring() 191 self.sendRaw(raw) 192 193 def sendRaw(self, rawString): 194 totalSent = 0 195 stringLen = len(rawString) 196 while totalSent < stringLen: 197 sent = self.conn.send(rawString[totalSent:]) 198 totalSent += sent 199 200 def protocolError(self, message): 201 print message 202 sys.exit(1) 203 204 205if __name__=="__main__": 206 HOST = "localhost" 207 PORT = 15010 208 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 209 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 210 s.bind((HOST, PORT)) 211 s.listen(1) 212 213 conn, addr = s.accept() 214 print "client connected" 215 # close the server socket to allow other instance to run 216 s.close() 217 handler = CommandHandler(conn) 218 while 1: 219 handler.run() 220