/** * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr) * This file is part of CSipSimple. * * CSipSimple is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * If you own a pjsip commercial license you can also redistribute it * and/or modify it under the terms of the GNU Lesser General Public License * as an android library. * * CSipSimple is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CSipSimple. If not, see <http://www.gnu.org/licenses/>. */ package com.csipsimple.pjsip.recorder.impl; import android.content.Intent; import android.text.format.DateFormat; import com.csipsimple.api.SipCallSession; import com.csipsimple.api.SipManager; import com.csipsimple.pjsip.recorder.IRecorderHandler; import com.csipsimple.service.SipService.SameThreadException; import org.pjsip.pjsua.pj_str_t; import org.pjsip.pjsua.pjsua; import java.io.File; import java.io.IOException; import java.util.Date; public class SimpleWavRecorderHandler implements IRecorderHandler { final int way; final SipCallSession callInfo; private final int recorderId; private final String recordingPath; public SimpleWavRecorderHandler(SipCallSession callInfo, File recordFolder, int way) throws SameThreadException, IOException { this.way = way; this.callInfo = callInfo; File targetFile = getRecordFile(recordFolder, callInfo.getRemoteContact(), way); if (targetFile == null) { throw new IOException("No target file possible"); } recordingPath = targetFile.getAbsolutePath(); pj_str_t file = pjsua.pj_str_copy(recordingPath); int[] rcId = new int[1]; int status = pjsua.recorder_create(file, 0, (byte[]) null, 0, 0, rcId); if (status == pjsua.PJ_SUCCESS) { recorderId = rcId[0]; } else { throw new IOException("Pjsip not able to write the file"); } } /** * Get the file to record to for a given remote contact. This will * implicitly get the current date in file name. * * @param remoteContact The remote contact name * @return The file to store conversation */ private File getRecordFile(File dir, String remoteContact, int way) { if (dir != null) { // The file name is only to have an unique identifier. // It should never be used to store datas as may change. // The app using the recording files should rely on the broadcast // and on callInfo instead that is reliable. String datePart = (String) DateFormat.format("yy-MM-dd_kkmmss", new Date()); String remotePart = sanitizeForFile(remoteContact); String fileName = datePart + "_" + remotePart; if (way != (SipManager.BITMASK_ALL)) { fileName += ((way & SipManager.BITMASK_IN) == 0) ? "_out" : "_in"; } File file = new File(dir.getAbsoluteFile() + File.separator + fileName + ".wav"); return file; } return null; } private String sanitizeForFile(String remoteContact) { String fileName = remoteContact; fileName = fileName.replaceAll("[\\.\\\\<>:; \"\'\\*]", "_"); return fileName; } @Override public void startRecording() { // TODO : treat connect errors ? is it useful? Should we fail gracefully int wavPort = pjsua.recorder_get_conf_port(recorderId); if ((way & SipManager.BITMASK_IN) == SipManager.BITMASK_IN) { int wavConfPort = callInfo.getConfPort(); pjsua.conf_connect(wavConfPort, wavPort); } if ((way & SipManager.BITMASK_OUT) == SipManager.BITMASK_OUT) { pjsua.conf_connect(0, wavPort); } } @Override public void stopRecording() { pjsua.recorder_destroy(recorderId); } @Override public void fillBroadcastWithInfo(Intent it) { it.putExtra(SipManager.EXTRA_FILE_PATH, recordingPath); it.putExtra(SipManager.EXTRA_SIP_CALL_CALL_WAY, way); } }