using System; using System.Collections.Generic; using System.Linq; using System.Text; using SafeMobileLib; using System.IO; namespace AppServer { class VoiceRecording { private string ip; private int port; private UdpMulticast udp4VoiceRecv; private bool isRecording; public bool IsRecording { get { return isRecording; } set { isRecording = value; } } private MemoryStream recStream; private string fileDir; System.Timers.Timer backUPTimer; private DBrecordingsManager DBrec; private int gwID; private int radioGWid; private int typeSD; private Int32 callType; private UdpMulticast udp_multi; private int sampleRate = 8000; private int bitdepth = 16; public int? dispatcher_id; public int? subs_imei; private int? group_cpsid; private DateTime dtStart; public VoiceRecording(string ip, int voicePort, int gwID, int radiogwID, int? dispatcherId, int? subs_imei, int? group_cpsid, int typeSD, Int32 callType, UdpMulticast udp_multi, int sampleRate, int bitdepth) { this.ip = ip; this.port = voicePort; this.gwID = gwID; this.radioGWid = radiogwID; this.dispatcher_id = dispatcherId; this.subs_imei = subs_imei; this.group_cpsid = group_cpsid; this.typeSD = typeSD; this.callType = callType; this.udp_multi = udp_multi; this.sampleRate = sampleRate; this.bitdepth = bitdepth; fileDir = @"recordings"; DirectoryInfo dir = new DirectoryInfo(fileDir); if (!Directory.Exists(fileDir)) { dir.Create(); } DBrec = new DBrecordingsManager(Program.cfg.DB_IP, Program.cfg.DB_schema, Program.cfg.DB_user, Program.cfg.DB_passwd, Program.cfg.DB_port); SM.Debug("Starting voice recording for " + ip); udp4VoiceRecv = new UdpMulticast(ip, port); udp4VoiceRecv.OnNewDataRecv += new UdpMulticast.newData4Send(udp4VoiceRecv_OnNewDataRecv); backUPTimer = new System.Timers.Timer(); backUPTimer.Interval = 60000; backUPTimer.Elapsed += new System.Timers.ElapsedEventHandler(backUPTimer_Elapsed); } void backUPTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { SM.Debug("backup timer expired(60sec) ... force stoping voice recording"); Stop(); } void udp4VoiceRecv_OnNewDataRecv(byte[] data, int dataLen) { if (isRecording) { Console.WriteLine("datalen="+dataLen); if (dataLen > 0) { recStream.Write(data, 0, dataLen); } } } public void Start() { udp4VoiceRecv.StartListen_ThreadPool(); recStream = new MemoryStream(); isRecording = true; backUPTimer.Enabled = true; dtStart = DateTime.Now; } private string test; public void Stop() { try { backUPTimer.Enabled = false; udp4VoiceRecv.StopListen(); SM.Debug("Recording stoped... dumping memory stream in to file; len=" + recStream.ToArray().Length); if (recStream.ToArray().Length == 0) { SM.Debug("Nothing to write. Returning"); return; } if (MainForm.recordings == 0) { SM.Debug("No recordings license. Returning"); return; } Int32 call_type = GetCallType(); // 0-private 1-group 2-all call 3-users voice call from dispacher // 4-private 5 -group 6 -all call string ending = ".wav"; string endRepeater = ".amb"; //format the name of the recording string filename = FormatFileName(); filename = filename.Replace(' ', '_'); //if we got some data save it 2 file if (recStream.Length > 0) { string fileName = fileDir + "/" + filename + ending; string fileNameDB = fileName; if ((MulticastListener.GatewayList[gwID] != null) && ((Boolean)MulticastListener.GatewayList[gwID])) fileName = fileDir + "/" + filename + endRepeater; using (FileStream fs1 = new FileStream(fileName, System.IO.FileMode.Create)) { if (!((MulticastListener.GatewayList[gwID] != null) && ((Boolean)MulticastListener.GatewayList[gwID]))) { WriteHeader(fs1, recStream.ToArray().Length, 1, sampleRate, bitdepth); } System.IO.BinaryWriter bw = new BinaryWriter(fs1); bw.Write(recStream.ToArray()); bw.Close(); } // trigger event when a recording was received from the repeater if ((MulticastListener.GatewayList[gwID] != null) && ((Boolean)MulticastListener.GatewayList[gwID])) OnRecordingFileWritteen(fileName); // add to db Recording rec = new Recording(dtStart.GetSecondsLocalFromDT() * 1000000 + DateTime.Now.Millisecond * 1000, dtStart.GetSecondsLocalFromDT(), DateTime.Now.GetSecondsLocalFromDT(), dtStart, DateTime.Now, fileNameDB, subs_imei, gwID, radioGWid, typeSD, call_type, group_cpsid, dispatcher_id); DBrec.addRecording(rec); test = $"#155#{rec.id}#{rec.hddLocation}#{rec.gwID}#{rec.radioGWID}#{rec.group_cpsId}#{rec.subs_imei}#{rec.startTime}#{rec.endTime}#{rec.typeSD}#{rec.calltype}#{rec.dispatcher_id}#"; MainForm.udp.Send(SafeMobileLib.Utils.Convert_text_For_multicast("#0.0" + test), SafeMobileLib.Utils.Convert_text_For_multicast("#0.0" + test).Length); } } catch (Exception ex) { SM.Debug(ex.ToString()); } finally { backUPTimer.Close(); recStream.Flush(); isRecording = false; } } private int GetCallType() { int call_type = 0; if (typeSD == 0) { if (callType == 162) call_type = 7; else { switch (callType) { case 101 /*AllCall*/: call_type = 6; break; case 102 /* Private call */: call_type = 4; break; case 103 /* Group call */: call_type = 5; break; } } } if (typeSD == 1) { switch (callType) { case 201: call_type = 3; break; case 101: call_type = 2; break; case 102: call_type = 0; break; case 103: call_type = 1; break; } } return call_type; } private string FormatDispatcherRadioFileName() { string filename = string.Empty; string tmp = ""; if (typeSD == 1) { switch (callType) { case 201: tmp = ""; if (MulticastListener.UserList[radioGWid] != null) tmp = "_" + MulticastListener.UserList[radioGWid] + "_"; else tmp = "_UserID(" + radioGWid.ToString() + ")_"; if (MulticastListener.UserList[dispatcher_id] != null) filename = MulticastListener.UserList[dispatcher_id] + "_CALL_USER_TO" + tmp + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); else filename = "UserID(" + dispatcher_id.ToString() + ")_CALL_USER_TO" + tmp + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); break; case 101: // dispatcher - radio (all call) if (MulticastListener.UserList[dispatcher_id] != null) filename = MulticastListener.UserList[dispatcher_id] + "_ALLCALL_" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); else filename = "UserID(" + dispatcher_id.ToString() + ")_ALLCALL_" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); break; case 102: // dispatcher - radio (private call) tmp = ""; if (MulticastListener.VehicleList[subs_imei.ToString()] != null) tmp = "_" + MulticastListener.VehicleList[subs_imei.ToString()] + "(" + subs_imei.ToString() + ")_"; else tmp = "_RadioID(" + subs_imei.ToString() + ")_"; if (MulticastListener.UserList[dispatcher_id] != null) filename = MulticastListener.UserList[dispatcher_id] + "_PRIVATE_CALL_TO" + tmp + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); else filename = "UserID(" + dispatcher_id.ToString() + ")_PRIVATE_CALL_TO" + tmp + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); break; case 103: // dispatcher - radio (group call) if (MulticastListener.UserList[(int)dispatcher_id] != null) filename = MulticastListener.UserList[(int)dispatcher_id] + "_GROUP_CALL_" + dispatcher_id.ToString() + "_" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); else filename = "UserID(" + dispatcher_id.ToString() + ")_GROUP_CALL_" + group_cpsid.ToString() + "_" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); break; } } return filename.Trim(); } private string FormatRadioDispatcherFileName() { string filename = string.Empty; if (typeSD == 0) { if (callType == 162) // Remote monitor { if (MulticastListener.VehicleList[subs_imei.ToString()] != null) filename = "Remote monitor " + MulticastListener.VehicleList[subs_imei.ToString()] + "(" + subs_imei.ToString() + ")" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); else filename = "Remote monitor RadioID(" + subs_imei.ToString() + ") " + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); } else { if (callType == 103) { if (MulticastListener.VehicleList[subs_imei.ToString()] != null) filename = MulticastListener.VehicleList[subs_imei.ToString()] + "(" + subs_imei.ToString() + ")" + "_DO_GROUP_CALL_ID_" + group_cpsid.ToString() + "_" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); else filename = "RadioID(" + subs_imei.ToString() + ")_DO_GROUP_CALL_ID_" + group_cpsid.ToString() + "_" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); } else if (callType == 102) // radio - dispatcher ( private call) { if (MulticastListener.VehicleList[subs_imei.ToString()] != null) filename = MulticastListener.VehicleList[subs_imei.ToString()] + "(" + subs_imei.ToString() + ")" + "_DO_A_PRIVATE_CALL_"; else filename = "RadioID(" + subs_imei.ToString() + ")_DO_A_PRIVATE_CALL_"; if (MulticastListener.VehicleList[dispatcher_id.ToString()] != null) filename += MulticastListener.VehicleList[dispatcher_id.ToString()] + "(" + dispatcher_id.ToString() + ")" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); else filename += "RadioID(" + dispatcher_id.ToString() + ")" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); } else if (callType == 101) // radio - dispatcher ( all call) { if (MulticastListener.VehicleList[subs_imei.ToString()] != null) filename = MulticastListener.VehicleList[subs_imei.ToString()] + "(" + subs_imei.ToString() + ")" + "_DO_ALL_CALL_" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); else filename = "RadioID(" + subs_imei.ToString() + ")_DO_ALL_CALL_" + DateTime.Now.ToString("dd_MMM_yy_HH_mm_ss"); } } } return filename.Trim(); } private string FormatFileName() { if (typeSD == 0) return FormatRadioDispatcherFileName(); return FormatDispatcherRadioFileName(); } public static void WriteHeader( System.IO.Stream targetStream, int byteStreamSize, int channelCount, int sampleRate, int bitdepth) { bool isFloatingPoint = false; targetStream.Position = 0; // RIFF header. // Chunk ID. targetStream.Write(Encoding.ASCII.GetBytes("RIFF"), 0, 4); // Chunk size. targetStream.Write(BitConverter.GetBytes(((bitdepth / 8) * byteStreamSize) + 36), 0, 4); // Format. targetStream.Write(Encoding.ASCII.GetBytes("WAVE"), 0, 4); // Sub-chunk 1. // Sub-chunk 1 ID. targetStream.Write(Encoding.ASCII.GetBytes("fmt "), 0, 4); // Sub-chunk 1 size. targetStream.Write(BitConverter.GetBytes(16), 0, 4); // Audio format (floating point (3) or PCM (1)). Any other format indicates compression. targetStream.Write(BitConverter.GetBytes((ushort)(isFloatingPoint ? 3 : 1)), 0, 2); // Channels. targetStream.Write(BitConverter.GetBytes(channelCount), 0, 2); // Sample rate. targetStream.Write(BitConverter.GetBytes(sampleRate), 0, 4); // Bytes rate. targetStream.Write(BitConverter.GetBytes(sampleRate * channelCount * (bitdepth / 8)), 0, 4); // Block align. targetStream.Write(BitConverter.GetBytes((ushort)channelCount * (bitdepth / 8)), 0, 2); // Bits per sample. targetStream.Write(BitConverter.GetBytes(bitdepth), 0, 2); // Sub-chunk 2. // Sub-chunk 2 ID. targetStream.Write(Encoding.ASCII.GetBytes("data"), 0, 4); // Sub-chunk 2 size. targetStream.Write(BitConverter.GetBytes((bitdepth / 8) * byteStreamSize), 0, 4); } public delegate void RecordingFileWritteenDEl(string filePath); public event RecordingFileWritteenDEl OnRecordingFileWritteen; } }