blob: 6a04b83edb73c78db04d33151dbb24f73f33d4ba [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/* AudioStreamInALSA.cpp
2 **
3 ** Copyright 2008-2009 Wind River Systems
4 ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
5 **
6 ** Licensed under the Apache License, Version 2.0 (the "License");
7 ** you may not use this file except in compliance with the License.
8 ** You may obtain a copy of the License at
9 **
10 ** http://www.apache.org/licenses/LICENSE-2.0
11 **
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 */
18
19#include <errno.h>
20#include <stdarg.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <dlfcn.h>
26
Ajay Dudani9746c472012-06-18 16:01:16 -070027#define LOG_TAG "AudioStreamInALSA"
Iliyan Malchev4765c432012-06-11 14:36:16 -070028//#define LOG_NDEBUG 0
Ajay Dudani9746c472012-06-18 16:01:16 -070029#define LOG_NDDEBUG 0
Iliyan Malchev4765c432012-06-11 14:36:16 -070030#include <utils/Log.h>
31#include <utils/String8.h>
32
33#include <cutils/properties.h>
34#include <media/AudioRecord.h>
35#include <hardware_legacy/power.h>
36
37#include "AudioHardwareALSA.h"
38
39extern "C" {
Ajay Dudani9746c472012-06-18 16:01:16 -070040#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070041#include "csd_client.h"
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070042static int (*csd_start_record)(int);
43static int (*csd_stop_record)(void);
Iliyan Malchev4765c432012-06-11 14:36:16 -070044#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070045
Ajay Dudani9746c472012-06-18 16:01:16 -070046#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070047#include "surround_filters_interface.h"
48#endif
49}
50
51namespace android_audio_legacy
52{
Ajay Dudani9746c472012-06-18 16:01:16 -070053#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070054#define SURROUND_FILE_1R "/system/etc/surround_sound/filter1r.pcm"
55#define SURROUND_FILE_2R "/system/etc/surround_sound/filter2r.pcm"
56#define SURROUND_FILE_3R "/system/etc/surround_sound/filter3r.pcm"
57#define SURROUND_FILE_4R "/system/etc/surround_sound/filter4r.pcm"
58
59#define SURROUND_FILE_1I "/system/etc/surround_sound/filter1i.pcm"
60#define SURROUND_FILE_2I "/system/etc/surround_sound/filter2i.pcm"
61#define SURROUND_FILE_3I "/system/etc/surround_sound/filter3i.pcm"
62#define SURROUND_FILE_4I "/system/etc/surround_sound/filter4i.pcm"
63
64// Use AAC/DTS channel mapping as default channel mapping: C,FL,FR,Ls,Rs,LFE
65const int chanMap[] = { 1, 2, 4, 3, 0, 5 };
66#endif
67
68AudioStreamInALSA::AudioStreamInALSA(AudioHardwareALSA *parent,
69 alsa_handle_t *handle,
70 AudioSystem::audio_in_acoustics audio_acoustics) :
71 ALSAStreamOps(parent, handle),
72 mFramesLost(0),
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070073 mAcoustics(audio_acoustics),
74 mParent(parent)
Ajay Dudani9746c472012-06-18 16:01:16 -070075#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070076 , mFp_4ch(NULL),
77 mFp_6ch(NULL),
78 mRealCoeffs(NULL),
79 mImagCoeffs(NULL),
80 mSurroundObj(NULL),
81 mSurroundOutputBuffer(NULL),
82 mSurroundInputBuffer(NULL),
83 mSurroundOutputBufferIdx(0),
84 mSurroundInputBufferIdx(0)
85#endif
86{
Ajay Dudani9746c472012-06-18 16:01:16 -070087#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070088 char c_multi_ch_dump[128] = {0};
89 status_t err = NO_ERROR;
90
91 // Call surround sound library init if device is Surround Sound
92 if ( handle->channels == 6) {
93 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
94 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
95
96 err = initSurroundSoundLibrary(handle->bufferSize);
97 if ( NO_ERROR != err) {
Iliyan Malchev4113f342012-06-11 14:39:47 -070098 ALOGE("initSurroundSoundLibrary failed: %d handle->bufferSize:%d", err,handle->bufferSize);
Iliyan Malchev4765c432012-06-11 14:36:16 -070099 }
100
101 property_get("ssr.pcmdump",c_multi_ch_dump,"0");
102 if (0 == strncmp("true",c_multi_ch_dump, sizeof("ssr.dump-pcm"))) {
103 //Remember to change file system permission of data(e.g. chmod 777 data/),
104 //otherwise, fopen may fail.
105 if ( !mFp_4ch)
106 mFp_4ch = fopen("/data/4ch_ssr.pcm", "wb");
107 if ( !mFp_6ch)
108 mFp_6ch = fopen("/data/6ch_ssr.pcm", "wb");
109 if ((!mFp_4ch) || (!mFp_6ch))
Iliyan Malchev4113f342012-06-11 14:39:47 -0700110 ALOGE("mfp_4ch or mfp_6ch open failed: mfp_4ch:%p mfp_6ch:%p",mFp_4ch,mFp_6ch);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700111 }
112 }
113 }
114#endif
115}
116
117AudioStreamInALSA::~AudioStreamInALSA()
118{
119 close();
120}
121
122status_t AudioStreamInALSA::setGain(float gain)
123{
124 return 0; //mixer() ? mixer()->setMasterGain(gain) : (status_t)NO_INIT;
125}
126
127ssize_t AudioStreamInALSA::read(void *buffer, ssize_t bytes)
128{
129 int period_size;
130
Iliyan Malchev4113f342012-06-11 14:39:47 -0700131 ALOGV("read:: buffer %p, bytes %d", buffer, bytes);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700132
133 int n;
134 status_t err;
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700135 ssize_t read = 0;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700136 char *use_case;
137 int newMode = mParent->mode();
138
139 if((mHandle->handle == NULL) && (mHandle->rxHandle == NULL) &&
140 (strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) &&
141 (strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
142 mParent->mLock.lock();
143 snd_use_case_get(mHandle->ucMgr, "_verb", (const char **)&use_case);
144 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
145 if ((mHandle->devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
146 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700147 ALOGD("read:: mParent->mIncallMode=%d", mParent->mIncallMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700148 if ((mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
149 (mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700150#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700151 if (mParent->mFusion3Platform) {
152 mParent->mALSADevice->setVocRecMode(INCALL_REC_STEREO);
153 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
154 sizeof(mHandle->useCase));
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700155 start_csd_record(INCALL_REC_STEREO);
156 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700157#endif
158 {
159 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
160 sizeof(mHandle->useCase));
161 }
162 } else if (mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700163#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700164 if (mParent->mFusion3Platform) {
165 mParent->mALSADevice->setVocRecMode(INCALL_REC_MONO);
166 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
167 sizeof(mHandle->useCase));
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700168 start_csd_record(INCALL_REC_MONO);
169 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700170#endif
171 {
172 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
173 sizeof(mHandle->useCase));
174 }
175 }
Ajay Dudani92919432012-06-28 14:23:11 -0700176#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700177 } else if(mHandle->devices == AudioSystem::DEVICE_IN_FM_RX) {
178 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(mHandle->useCase));
179 } else if (mHandle->devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
180 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(mHandle->useCase));
181#endif
182 } else if(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)) {
183 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(mHandle->useCase));
SathishKumar Mani88613382012-08-13 18:40:18 -0700184 } else {
185 char value[128];
186 property_get("persist.audio.lowlatency.rec",value,"0");
187 if (!strcmp("true", value)) {
188 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(mHandle->useCase));
189 } else {
190 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(mHandle->useCase));
191 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700192 }
193 } else {
194 if ((mHandle->devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
195 (newMode == AudioSystem::MODE_IN_CALL)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700196 ALOGD("read:: ---- mParent->mIncallMode=%d", mParent->mIncallMode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700197 if ((mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
198 (mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700199#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700200 if (mParent->mFusion3Platform) {
201 mParent->mALSADevice->setVocRecMode(INCALL_REC_STEREO);
202 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC,
203 sizeof(mHandle->useCase));
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700204 start_csd_record(INCALL_REC_STEREO);
205 } else
Iliyan Malchev4765c432012-06-11 14:36:16 -0700206#endif
207 {
208 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_UL_DL_REC,
209 sizeof(mHandle->useCase));
210 }
211 } else if (mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700212#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700213 if (mParent->mFusion3Platform) {
214 mParent->mALSADevice->setVocRecMode(INCALL_REC_MONO);
215 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC,
216 sizeof(mHandle->useCase));
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700217 start_csd_record(INCALL_REC_MONO);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700218 } else
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700219#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700220 {
221 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_DL_REC,
222 sizeof(mHandle->useCase));
223 }
224 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700225#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700226 } else if(mHandle->devices == AudioSystem::DEVICE_IN_FM_RX) {
227 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_FM_REC, sizeof(mHandle->useCase));
228 } else if (mHandle->devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
229 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(mHandle->useCase));
230#endif
231 } else if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)){
232 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(mHandle->useCase));
233 } else {
SathishKumar Mani88613382012-08-13 18:40:18 -0700234 char value[128];
235 property_get("persist.audio.lowlatency.rec",value,"0");
236 if (!strcmp("true", value)) {
237 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(mHandle->useCase));
238 } else {
239 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(mHandle->useCase));
240 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700241 }
242 }
243 free(use_case);
244 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
245 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700246#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700247 if((mDevices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
248 (mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)) {
249 mHandle->module->route(mHandle, (mDevices | AudioSystem::DEVICE_IN_PROXY) , AudioSystem::MODE_IN_COMMUNICATION);
250 }else
251#endif
252 {
253 mHandle->module->route(mHandle, mDevices , AudioSystem::MODE_IN_COMMUNICATION);
254 }
255 } else {
Ajay Dudani9746c472012-06-18 16:01:16 -0700256#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700257 if((mHandle->devices == AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET)||
258 (mHandle->devices == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)){
259 mHandle->module->route(mHandle, AudioSystem::DEVICE_IN_PROXY , mParent->mode());
260 } else
261#endif
262 {
263
264 mHandle->module->route(mHandle, mDevices , mParent->mode());
265 }
266 }
267 if (!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
SathishKumar Mani88613382012-08-13 18:40:18 -0700268 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -0700269 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_FM_REC) ||
270 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL) ||
271 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
272 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
273 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_DL_REC) ||
274 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
275 snd_use_case_set(mHandle->ucMgr, "_verb", mHandle->useCase);
276 } else {
277 snd_use_case_set(mHandle->ucMgr, "_enamod", mHandle->useCase);
278 }
279 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
280 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
281 err = mHandle->module->startVoipCall(mHandle);
282 }
283 else
284 mHandle->module->open(mHandle);
285 if(mHandle->handle == NULL) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700286 ALOGE("read:: PCM device open failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700287 mParent->mLock.unlock();
288
289 return 0;
290 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700291#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700292 if((mHandle->devices == AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET)||
293 (mHandle->devices == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)){
294 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
295 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
296 mParent->musbRecordingState |= USBRECBIT_VOIPCALL;
297 } else {
298 mParent->startUsbRecordingIfNotStarted();
299 mParent->musbRecordingState |= USBRECBIT_REC;
300 }
301 }
302#endif
303 mParent->mLock.unlock();
304 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700305#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700306 if(((mDevices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
307 (mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)) &&
308 (!mParent->musbRecordingState)) {
309 mParent->mLock.lock();
Iliyan Malchev4113f342012-06-11 14:39:47 -0700310 ALOGD("Starting UsbRecording thread");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700311 mParent->startUsbRecordingIfNotStarted();
312 if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL) ||
313 !strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700314 ALOGD("Enabling voip recording bit");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700315 mParent->musbRecordingState |= USBRECBIT_VOIPCALL;
316 }else{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700317 ALOGD("Enabling HiFi Recording bit");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700318 mParent->musbRecordingState |= USBRECBIT_REC;
319 }
320 mParent->mLock.unlock();
321 }
322#endif
323 period_size = mHandle->periodSize;
324 int read_pending = bytes;
325
Ajay Dudani9746c472012-06-18 16:01:16 -0700326#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700327 if (mSurroundObj) {
328 int processed = 0;
329 int processed_pending;
330 int samples = bytes >> 1;
331 void *buffer_start = buffer;
332 int period_bytes = mHandle->handle->period_size;
333 int period_samples = period_bytes >> 1;
334
335 do {
336 if (mSurroundOutputBufferIdx > 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700337 ALOGV("AudioStreamInALSA::read() - copy processed output "
Iliyan Malchev4765c432012-06-11 14:36:16 -0700338 "to buffer, mSurroundOutputBufferIdx = %d",
339 mSurroundOutputBufferIdx);
340 // Copy processed output to buffer
341 processed_pending = mSurroundOutputBufferIdx;
342 if (processed_pending > (samples - processed)) {
343 processed_pending = (samples - processed);
344 }
345 memcpy(buffer, mSurroundOutputBuffer, processed_pending * sizeof(Word16));
346 buffer += processed_pending * sizeof(Word16);
347 processed += processed_pending;
348 if (mSurroundOutputBufferIdx > processed_pending) {
349 // Shift leftover samples to beginning of the buffer
350 memcpy(&mSurroundOutputBuffer[0],
351 &mSurroundOutputBuffer[processed_pending],
352 (mSurroundOutputBufferIdx - processed_pending) * sizeof(Word16));
353 }
354 mSurroundOutputBufferIdx -= processed_pending;
355 }
356
357 if (processed >= samples) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700358 ALOGV("AudioStreamInALSA::read() - done processing buffer, "
Iliyan Malchev4765c432012-06-11 14:36:16 -0700359 "processed = %d", processed);
360 // Done processing this buffer
361 break;
362 }
363
364 // Fill input buffer until there is enough to process
365 read_pending = SSR_INPUT_FRAME_SIZE - mSurroundInputBufferIdx;
366 read = mSurroundInputBufferIdx;
367 while (mHandle->handle && read_pending > 0) {
368 n = pcm_read(mHandle->handle, &mSurroundInputBuffer[read],
369 period_bytes);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700370 ALOGV("pcm_read() returned n = %d buffer:%p size:%d", n, &mSurroundInputBuffer[read], period_bytes);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700371 if (n && n != -EAGAIN) {
372 //Recovery part of pcm_read. TODO:split recovery.
373 return static_cast<ssize_t>(n);
374 }
375 else if (n < 0) {
376 // Recovery is part of pcm_write. TODO split is later.
377 return static_cast<ssize_t>(n);
378 }
379 else {
380 read_pending -= period_samples;
381 read += period_samples;
382 }
383 }
384
385
386 if (mFp_4ch) {
387 fwrite( mSurroundInputBuffer, 1,
388 SSR_INPUT_FRAME_SIZE * sizeof(Word16), mFp_4ch);
389 }
390
391 //apply ssr libs to conver 4ch to 6ch
392 surround_filters_intl_process(mSurroundObj,
393 &mSurroundOutputBuffer[mSurroundOutputBufferIdx],
394 (Word16 *)mSurroundInputBuffer);
395
396 // Shift leftover samples to beginning of input buffer
397 if (read_pending < 0) {
398 memcpy(&mSurroundInputBuffer[0],
399 &mSurroundInputBuffer[SSR_INPUT_FRAME_SIZE],
400 (-read_pending) * sizeof(Word16));
401 }
402 mSurroundInputBufferIdx = -read_pending;
403
404 if (mFp_6ch) {
405 fwrite( &mSurroundOutputBuffer[mSurroundOutputBufferIdx],
406 1, SSR_OUTPUT_FRAME_SIZE * sizeof(Word16), mFp_6ch);
407 }
408
409 mSurroundOutputBufferIdx += SSR_OUTPUT_FRAME_SIZE;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700410 ALOGV("do_while loop: processed=%d, samples=%d\n", processed, samples);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700411 } while (mHandle->handle && processed < samples);
412 read = processed * sizeof(Word16);
413 buffer = buffer_start;
414 } else
Ajay Dudani9746c472012-06-18 16:01:16 -0700415#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700416 {
417
418 do {
419 if (read_pending < period_size) {
420 read_pending = period_size;
421 }
422
423 n = pcm_read(mHandle->handle, buffer,
424 period_size);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700425 ALOGV("pcm_read() returned n = %d", n);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700426 if (n && (n == -EIO || n == -EAGAIN || n == -EPIPE || n == -EBADFD)) {
427 mParent->mLock.lock();
Iliyan Malchev4113f342012-06-11 14:39:47 -0700428 ALOGW("pcm_read() returned error n %d, Recovering from error\n", n);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700429 pcm_close(mHandle->handle);
430 mHandle->handle = NULL;
431 if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) ||
432 (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) {
433 pcm_close(mHandle->rxHandle);
434 mHandle->rxHandle = NULL;
435 mHandle->module->startVoipCall(mHandle);
436 }
437 else
438 mHandle->module->open(mHandle);
439 mParent->mLock.unlock();
440 continue;
441 }
442 else if (n < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700443 ALOGD("pcm_read() returned n < 0");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700444 return static_cast<ssize_t>(n);
445 }
446 else {
447 read += static_cast<ssize_t>((period_size));
448 read_pending -= period_size;
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700449 buffer = ((uint8_t *)buffer) + period_size;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700450 }
451
452 } while (mHandle->handle && read < bytes);
453 }
454
455 return read;
456}
457
458status_t AudioStreamInALSA::dump(int fd, const Vector<String16>& args)
459{
460 return NO_ERROR;
461}
462
463status_t AudioStreamInALSA::open(int mode)
464{
465 Mutex::Autolock autoLock(mParent->mLock);
466
467 status_t status = ALSAStreamOps::open(mode);
468
469 return status;
470}
471
472status_t AudioStreamInALSA::close()
473{
474 Mutex::Autolock autoLock(mParent->mLock);
475
Iliyan Malchev4113f342012-06-11 14:39:47 -0700476 ALOGD("close");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700477 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
478 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
479 if((mParent->mVoipStreamCount)) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700480#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4113f342012-06-11 14:39:47 -0700481 ALOGD("musbRecordingState: %d, mVoipStreamCount:%d",mParent->musbRecordingState,
Iliyan Malchev4765c432012-06-11 14:36:16 -0700482 mParent->mVoipStreamCount );
483 if(mParent->mVoipStreamCount == 1) {
SathishKumar Mani0a019912012-09-11 12:33:11 -0700484 ALOGD("Deregistering VOIP Call bit, musbPlaybackState:%d,"
Iliyan Malchev4765c432012-06-11 14:36:16 -0700485 "musbRecordingState:%d", mParent->musbPlaybackState, mParent->musbRecordingState);
486 mParent->musbPlaybackState &= ~USBPLAYBACKBIT_VOIPCALL;
487 mParent->musbRecordingState &= ~USBRECBIT_VOIPCALL;
488 mParent->closeUsbRecordingIfNothingActive();
489 mParent->closeUsbPlaybackIfNothingActive();
490 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700491#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700492 return NO_ERROR;
493 }
494 mParent->mVoipStreamCount = 0;
495 mParent->mVoipMicMute = 0;
Ajay Dudani9746c472012-06-18 16:01:16 -0700496#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700497 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700498 ALOGD("Deregistering REC bit, musbRecordingState:%d", mParent->musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700499 mParent->musbRecordingState &= ~USBRECBIT_REC;
Ajay Dudani9746c472012-06-18 16:01:16 -0700500#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700501 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700502#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700503 if (mParent->mFusion3Platform) {
504 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC)) ||
505 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE))) {
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700506 stop_csd_record();
Iliyan Malchev4765c432012-06-11 14:36:16 -0700507 }
508 }
509#endif
Iliyan Malchev4113f342012-06-11 14:39:47 -0700510 ALOGD("close");
Ajay Dudani9746c472012-06-18 16:01:16 -0700511#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700512 mParent->closeUsbRecordingIfNothingActive();
Ajay Dudani9746c472012-06-18 16:01:16 -0700513#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700514
515 ALSAStreamOps::close();
516
Ajay Dudani9746c472012-06-18 16:01:16 -0700517#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700518 if (mSurroundObj) {
519 surround_filters_release(mSurroundObj);
520 if (mSurroundObj)
521 free(mSurroundObj);
522 mSurroundObj = NULL;
523 if (mRealCoeffs){
524 for (int i =0; i<COEFF_ARRAY_SIZE; i++ ) {
525 if (mRealCoeffs[i]) {
526 free(mRealCoeffs[i]);
527 mRealCoeffs[i] = NULL;
528 }
529 }
530 free(mRealCoeffs);
531 mRealCoeffs = NULL;
532 }
533 if (mImagCoeffs){
534 for (int i =0; i<COEFF_ARRAY_SIZE; i++ ) {
535 if (mImagCoeffs[i]) {
536 free(mImagCoeffs[i]);
537 mImagCoeffs[i] = NULL;
538 }
539 }
540 free(mImagCoeffs);
541 mImagCoeffs = NULL;
542 }
543 if (mSurroundOutputBuffer){
544 free(mSurroundOutputBuffer);
545 mSurroundOutputBuffer = NULL;
546 }
547 if (mSurroundInputBuffer) {
548 free(mSurroundInputBuffer);
549 mSurroundInputBuffer = NULL;
550 }
551
552 if ( mFp_4ch ) fclose(mFp_4ch);
553 if ( mFp_6ch ) fclose(mFp_6ch);
554
555 }
556#endif
557
558 return NO_ERROR;
559}
560
561status_t AudioStreamInALSA::standby()
562{
563 Mutex::Autolock autoLock(mParent->mLock);
564
Iliyan Malchev4113f342012-06-11 14:39:47 -0700565 ALOGD("standby");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700566
567 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
568 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
569 return NO_ERROR;
570 }
571
Ajay Dudani9746c472012-06-18 16:01:16 -0700572#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4113f342012-06-11 14:39:47 -0700573 ALOGD("standby");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700574 if (mParent->mFusion3Platform) {
575 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC)) ||
576 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700577 ALOGD(" into standby, stop record");
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700578 stop_csd_record();
Iliyan Malchev4765c432012-06-11 14:36:16 -0700579 }
580 }
581#endif
582 mHandle->module->standby(mHandle);
583
Ajay Dudani9746c472012-06-18 16:01:16 -0700584#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4113f342012-06-11 14:39:47 -0700585 ALOGD("Checking for musbRecordingState %d", mParent->musbRecordingState);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700586 mParent->musbRecordingState &= ~USBRECBIT_REC;
587 mParent->closeUsbRecordingIfNothingActive();
Ajay Dudani9746c472012-06-18 16:01:16 -0700588#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700589
590 return NO_ERROR;
591}
592
593void AudioStreamInALSA::resetFramesLost()
594{
595 mFramesLost = 0;
596}
597
598unsigned int AudioStreamInALSA::getInputFramesLost() const
599{
600 unsigned int count = mFramesLost;
601 // Stupid interface wants us to have a side effect of clearing the count
602 // but is defined as a const to prevent such a thing.
603 ((AudioStreamInALSA *)this)->resetFramesLost();
604 return count;
605}
606
607status_t AudioStreamInALSA::setAcousticParams(void *params)
608{
609 Mutex::Autolock autoLock(mParent->mLock);
610
611 return (status_t)NO_ERROR;
612}
613
Ajay Dudani9746c472012-06-18 16:01:16 -0700614#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700615status_t AudioStreamInALSA::initSurroundSoundLibrary(unsigned long buffersize)
616{
617 int subwoofer = 0; // subwoofer channel assignment: default as first microphone input channel
618 int low_freq = 4; // frequency upper bound for subwoofer: frequency=(low_freq-1)/FFT_SIZE*samplingRate, default as 4
619 int high_freq = 100; // frequency upper bound for spatial processing: frequency=(high_freq-1)/FFT_SIZE*samplingRate, default as 100
620 int ret = 0;
621
622 mSurroundInputBufferIdx = 0;
623 mSurroundOutputBufferIdx = 0;
624
625 if ( mSurroundObj ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700626 ALOGE("ola filter library is already initialized");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700627 return ALREADY_EXISTS;
628 }
629
630 // Allocate memory for input buffer
631 mSurroundInputBuffer = (Word16 *) calloc(2 * SSR_INPUT_FRAME_SIZE,
632 sizeof(Word16));
633 if ( !mSurroundInputBuffer ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700634 ALOGE("Memory allocation failure. Not able to allocate memory for surroundInputBuffer");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700635 goto init_fail;
636 }
637
638 // Allocate memory for output buffer
639 mSurroundOutputBuffer = (Word16 *) calloc(2 * SSR_OUTPUT_FRAME_SIZE,
640 sizeof(Word16));
641 if ( !mSurroundOutputBuffer ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700642 ALOGE("Memory allocation failure. Not able to allocate memory for surroundOutputBuffer");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700643 goto init_fail;
644 }
645
646 // Allocate memory for real and imag coeffs array
647 mRealCoeffs = (Word16 **) calloc(COEFF_ARRAY_SIZE, sizeof(Word16 *));
648 if ( !mRealCoeffs ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700649 ALOGE("Memory allocation failure during real Coefficient array");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700650 goto init_fail;
651 }
652
653 mImagCoeffs = (Word16 **) calloc(COEFF_ARRAY_SIZE, sizeof(Word16 *));
654 if ( !mImagCoeffs ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700655 ALOGE("Memory allocation failure during imaginary Coefficient array");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700656 goto init_fail;
657 }
658
659 if( readCoeffsFromFile() != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700660 ALOGE("Error while loading coeffs from file");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700661 goto init_fail;
662 }
663
664 //calculate the size of data to allocate for mSurroundObj
665 ret = surround_filters_init(NULL,
666 6, // Num output channel
667 4, // Num input channel
668 mRealCoeffs, // Coeffs hardcoded in header
669 mImagCoeffs, // Coeffs hardcoded in header
670 subwoofer,
671 low_freq,
672 high_freq,
673 NULL);
674
675 if ( ret > 0 ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700676 ALOGV("Allocating surroundObj size is %d", ret);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700677 mSurroundObj = (void *)malloc(ret);
678 memset(mSurroundObj,0,ret);
679 if (NULL != mSurroundObj) {
680 //initialize after allocating the memory for mSurroundObj
681 ret = surround_filters_init(mSurroundObj,
682 6,
683 4,
684 mRealCoeffs,
685 mImagCoeffs,
686 subwoofer,
687 low_freq,
688 high_freq,
689 NULL);
690 if (0 != ret) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700691 ALOGE("surround_filters_init failed with ret:%d",ret);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700692 surround_filters_release(mSurroundObj);
693 goto init_fail;
694 }
695 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700696 ALOGE("Allocationg mSurroundObj failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700697 goto init_fail;
698 }
699 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700700 ALOGE("surround_filters_init(mSurroundObj=Null) failed with ret: %d",ret);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700701 goto init_fail;
702 }
703
704 (void) surround_filters_set_channel_map(mSurroundObj, chanMap);
705
706 return NO_ERROR;
707
708init_fail:
709 if (mSurroundObj) {
710 free(mSurroundObj);
711 mSurroundObj = NULL;
712 }
713 if (mSurroundOutputBuffer) {
714 free(mSurroundOutputBuffer);
715 mSurroundOutputBuffer = NULL;
716 }
717 if (mSurroundInputBuffer) {
718 free(mSurroundInputBuffer);
719 mSurroundInputBuffer = NULL;
720 }
721 if (mRealCoeffs){
722 for (int i =0; i<COEFF_ARRAY_SIZE; i++ ) {
723 if (mRealCoeffs[i]) {
724 free(mRealCoeffs[i]);
725 mRealCoeffs[i] = NULL;
726 }
727 }
728 free(mRealCoeffs);
729 mRealCoeffs = NULL;
730 }
731 if (mImagCoeffs){
732 for (int i =0; i<COEFF_ARRAY_SIZE; i++ ) {
733 if (mImagCoeffs[i]) {
734 free(mImagCoeffs[i]);
735 mImagCoeffs[i] = NULL;
736 }
737 }
738 free(mImagCoeffs);
739 mImagCoeffs = NULL;
740 }
741
742 return NO_MEMORY;
743
744}
745
746
747// Helper function to read coeffs from File and updates real and imaginary
748// coeff array member variable
749status_t AudioStreamInALSA::readCoeffsFromFile()
750{
751 FILE *flt1r;
752 FILE *flt2r;
753 FILE *flt3r;
754 FILE *flt4r;
755 FILE *flt1i;
756 FILE *flt2i;
757 FILE *flt3i;
758 FILE *flt4i;
759
760 if ( (flt1r = fopen(SURROUND_FILE_1R, "rb")) == NULL ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700761 ALOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_1R);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700762 return NAME_NOT_FOUND;
763 }
764
765 if ( (flt2r = fopen(SURROUND_FILE_2R, "rb")) == NULL ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700766 ALOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_2R);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700767 return NAME_NOT_FOUND;
768 }
769
770 if ( (flt3r = fopen(SURROUND_FILE_3R, "rb")) == NULL ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700771 ALOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_3R);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700772 return NAME_NOT_FOUND;
773 }
774
775 if ( (flt4r = fopen(SURROUND_FILE_4R, "rb")) == NULL ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700776 ALOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_4R);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700777 return NAME_NOT_FOUND;
778 }
779
780 if ( (flt1i = fopen(SURROUND_FILE_1I, "rb")) == NULL ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700781 ALOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_1I);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700782 return NAME_NOT_FOUND;
783 }
784
785 if ( (flt2i = fopen(SURROUND_FILE_2I, "rb")) == NULL ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700786 ALOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_2I);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700787 return NAME_NOT_FOUND;
788 }
789
790 if ( (flt3i = fopen(SURROUND_FILE_3I, "rb")) == NULL ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700791 ALOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_3I);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700792 return NAME_NOT_FOUND;
793 }
794
795 if ( (flt4i = fopen(SURROUND_FILE_4I, "rb")) == NULL ) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700796 ALOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_4I);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700797 return NAME_NOT_FOUND;
798 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700799 ALOGV("readCoeffsFromFile all filter files opened");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700800
801 for (int i=0; i<COEFF_ARRAY_SIZE; i++) {
802 mRealCoeffs[i] = (Word16 *)calloc(FILT_SIZE, sizeof(Word16));
803 }
804 for (int i=0; i<COEFF_ARRAY_SIZE; i++) {
805 mImagCoeffs[i] = (Word16 *)calloc(FILT_SIZE, sizeof(Word16));
806 }
807
808 // Read real co-efficients
809 if (NULL != mRealCoeffs[0]) {
810 fread(mRealCoeffs[0], sizeof(int16), FILT_SIZE, flt1r);
811 }
812 if (NULL != mRealCoeffs[0]) {
813 fread(mRealCoeffs[1], sizeof(int16), FILT_SIZE, flt2r);
814 }
815 if (NULL != mRealCoeffs[0]) {
816 fread(mRealCoeffs[2], sizeof(int16), FILT_SIZE, flt3r);
817 }
818 if (NULL != mRealCoeffs[0]) {
819 fread(mRealCoeffs[3], sizeof(int16), FILT_SIZE, flt4r);
820 }
821
822 // read imaginary co-efficients
823 if (NULL != mImagCoeffs[0]) {
824 fread(mImagCoeffs[0], sizeof(int16), FILT_SIZE, flt1i);
825 }
826 if (NULL != mImagCoeffs[0]) {
827 fread(mImagCoeffs[1], sizeof(int16), FILT_SIZE, flt2i);
828 }
829 if (NULL != mImagCoeffs[0]) {
830 fread(mImagCoeffs[2], sizeof(int16), FILT_SIZE, flt3i);
831 }
832 if (NULL != mImagCoeffs[0]) {
833 fread(mImagCoeffs[3], sizeof(int16), FILT_SIZE, flt4i);
834 }
835
836 fclose(flt1r);
837 fclose(flt2r);
838 fclose(flt3r);
839 fclose(flt4r);
840 fclose(flt1i);
841 fclose(flt2i);
842 fclose(flt3i);
843 fclose(flt4i);
844
845 return NO_ERROR;
846}
847#endif
848
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700849#ifdef QCOM_CSDCLIENT_ENABLED
850int AudioStreamInALSA::start_csd_record(int param)
851{
852 int err = NO_ERROR;
853
854 if (mParent->mCsdHandle != NULL) {
855 csd_start_record = (int (*)(int))::dlsym(mParent->mCsdHandle,"csd_client_start_record");
856 if (csd_start_record == NULL) {
857 ALOGE("dlsym:Error:%s Loading csd_client_start_record", dlerror());
858 } else {
859 err = csd_start_record(param);
860 }
861 }
862 return err;
863}
864
865int AudioStreamInALSA::stop_csd_record()
866{
867 int err = NO_ERROR;
868 if (mParent->mCsdHandle != NULL) {
869 csd_stop_record = (int (*)())::dlsym(mParent->mCsdHandle,"csd_client_stop_record");
870 if (csd_start_record == NULL) {
871 ALOGE("dlsym:Error:%s Loading csd_client_start_record", dlerror());
872 } else {
873 csd_stop_record();
874 }
875 }
876 return err;
877}
878#endif
879
Iliyan Malchev4765c432012-06-11 14:36:16 -0700880} // namespace android_audio_legacy