1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* Record implementation */ 18 19#include "sles_allinclusive.h" 20 21 22static SLresult IRecord_SetRecordState(SLRecordItf self, SLuint32 state) 23{ 24 SL_ENTER_INTERFACE 25 26 switch (state) { 27 case SL_RECORDSTATE_STOPPED: 28 case SL_RECORDSTATE_PAUSED: 29 case SL_RECORDSTATE_RECORDING: 30 { 31 IRecord *this = (IRecord *) self; 32 interface_lock_poke(this); 33 this->mState = state; 34#ifdef ANDROID 35 android_audioRecorder_setRecordState(InterfaceToCAudioRecorder(this), state); 36#endif 37 interface_unlock_poke(this); 38 result = SL_RESULT_SUCCESS; 39 } 40 break; 41 default: 42 result = SL_RESULT_PARAMETER_INVALID; 43 break; 44 } 45 46 SL_LEAVE_INTERFACE 47} 48 49 50static SLresult IRecord_GetRecordState(SLRecordItf self, SLuint32 *pState) 51{ 52 SL_ENTER_INTERFACE 53 54 IRecord *this = (IRecord *) self; 55 if (NULL == pState) { 56 result = SL_RESULT_PARAMETER_INVALID; 57 } else { 58 interface_lock_peek(this); 59 SLuint32 state = this->mState; 60 interface_unlock_peek(this); 61 *pState = state; 62 result = SL_RESULT_SUCCESS; 63 } 64 65 SL_LEAVE_INTERFACE 66} 67 68 69static SLresult IRecord_SetDurationLimit(SLRecordItf self, SLmillisecond msec) 70{ 71 SL_ENTER_INTERFACE 72 73 IRecord *this = (IRecord *) self; 74 interface_lock_exclusive(this); 75 if (this->mDurationLimit != msec) { 76 this->mDurationLimit = msec; 77 interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT); 78 } else { 79 interface_unlock_exclusive(this); 80 } 81 result = SL_RESULT_SUCCESS; 82 83 SL_LEAVE_INTERFACE 84} 85 86 87static SLresult IRecord_GetPosition(SLRecordItf self, SLmillisecond *pMsec) 88{ 89 SL_ENTER_INTERFACE 90 91 if (NULL == pMsec) { 92 result = SL_RESULT_PARAMETER_INVALID; 93 } else { 94 IRecord *this = (IRecord *) self; 95 SLmillisecond position; 96 interface_lock_shared(this); 97#ifdef ANDROID 98 // Android does not use the mPosition field for audio recorders 99 if (SL_OBJECTID_AUDIORECORDER == InterfaceToObjectID(this)) { 100 android_audioRecorder_getPosition(InterfaceToCAudioRecorder(this), &position); 101 } else { 102 position = this->mPosition; 103 } 104#else 105 position = this->mPosition; 106#endif 107 interface_unlock_shared(this); 108 *pMsec = position; 109 result = SL_RESULT_SUCCESS; 110 } 111 112 SL_LEAVE_INTERFACE 113} 114 115 116static SLresult IRecord_RegisterCallback(SLRecordItf self, slRecordCallback callback, 117 void *pContext) 118{ 119 SL_ENTER_INTERFACE 120 121 IRecord *this = (IRecord *) self; 122 interface_lock_exclusive(this); 123 this->mCallback = callback; 124 this->mContext = pContext; 125 interface_unlock_exclusive(this); 126 result = SL_RESULT_SUCCESS; 127 128 SL_LEAVE_INTERFACE 129} 130 131 132static SLresult IRecord_SetCallbackEventsMask(SLRecordItf self, SLuint32 eventFlags) 133{ 134 SL_ENTER_INTERFACE 135 136 if (eventFlags & ~( 137 SL_RECORDEVENT_HEADATLIMIT | 138 SL_RECORDEVENT_HEADATMARKER | 139 SL_RECORDEVENT_HEADATNEWPOS | 140 SL_RECORDEVENT_HEADMOVING | 141 SL_RECORDEVENT_HEADSTALLED | 142 SL_RECORDEVENT_BUFFER_FULL)) { 143 result = SL_RESULT_PARAMETER_INVALID; 144 } else { 145 IRecord *this = (IRecord *) self; 146 interface_lock_exclusive(this); 147 if (this->mCallbackEventsMask != eventFlags) { 148 this->mCallbackEventsMask = eventFlags; 149 interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT); 150 } else { 151 interface_unlock_exclusive(this); 152 } 153 result = SL_RESULT_SUCCESS; 154 } 155 156 SL_LEAVE_INTERFACE 157} 158 159 160static SLresult IRecord_GetCallbackEventsMask(SLRecordItf self, SLuint32 *pEventFlags) 161{ 162 SL_ENTER_INTERFACE 163 164 if (NULL == pEventFlags) { 165 result = SL_RESULT_PARAMETER_INVALID; 166 } else { 167 IRecord *this = (IRecord *) self; 168 interface_lock_peek(this); 169 SLuint32 callbackEventsMask = this->mCallbackEventsMask; 170 interface_unlock_peek(this); 171 *pEventFlags = callbackEventsMask; 172 result = SL_RESULT_SUCCESS; 173 } 174 175 SL_LEAVE_INTERFACE 176} 177 178 179static SLresult IRecord_SetMarkerPosition(SLRecordItf self, SLmillisecond mSec) 180{ 181 SL_ENTER_INTERFACE 182 183 IRecord *this = (IRecord *) self; 184 interface_lock_exclusive(this); 185 if (this->mMarkerPosition != mSec) { 186 this->mMarkerPosition = mSec; 187 interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT); 188 } else { 189 interface_unlock_exclusive(this); 190 } 191 result = SL_RESULT_SUCCESS; 192 193 SL_LEAVE_INTERFACE 194} 195 196 197static SLresult IRecord_ClearMarkerPosition(SLRecordItf self) 198{ 199 SL_ENTER_INTERFACE 200 201 IRecord *this = (IRecord *) self; 202 interface_lock_exclusive(this); 203 if (this->mMarkerPosition != 0) { 204 this->mMarkerPosition = 0; 205 interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT); 206 } else { 207 interface_unlock_exclusive(this); 208 } 209 result = SL_RESULT_SUCCESS; 210 211 SL_LEAVE_INTERFACE 212} 213 214 215static SLresult IRecord_GetMarkerPosition(SLRecordItf self, SLmillisecond *pMsec) 216{ 217 SL_ENTER_INTERFACE 218 219 if (NULL == pMsec) { 220 result = SL_RESULT_PARAMETER_INVALID; 221 } else { 222 IRecord *this = (IRecord *) self; 223 interface_lock_peek(this); 224 SLmillisecond markerPosition = this->mMarkerPosition; 225 interface_unlock_peek(this); 226 *pMsec = markerPosition; 227 result = SL_RESULT_SUCCESS; 228 } 229 230 SL_LEAVE_INTERFACE 231} 232 233 234static SLresult IRecord_SetPositionUpdatePeriod(SLRecordItf self, SLmillisecond mSec) 235{ 236 SL_ENTER_INTERFACE 237 238 if (0 == mSec) { 239 result = SL_RESULT_PARAMETER_INVALID; 240 } else { 241 IRecord *this = (IRecord *) self; 242 interface_lock_exclusive(this); 243 if (this->mPositionUpdatePeriod != mSec) { 244 this->mPositionUpdatePeriod = mSec; 245 interface_unlock_exclusive_attributes(this, ATTR_TRANSPORT); 246 } else { 247 interface_unlock_exclusive(this); 248 } 249 result = SL_RESULT_SUCCESS; 250 } 251 252 SL_LEAVE_INTERFACE 253} 254 255 256static SLresult IRecord_GetPositionUpdatePeriod(SLRecordItf self, SLmillisecond *pMsec) 257{ 258 SL_ENTER_INTERFACE 259 260 if (NULL == pMsec) { 261 result = SL_RESULT_PARAMETER_INVALID; 262 } else { 263 IRecord *this = (IRecord *) self; 264 interface_lock_peek(this); 265 SLmillisecond positionUpdatePeriod = this->mPositionUpdatePeriod; 266 interface_unlock_peek(this); 267 *pMsec = positionUpdatePeriod; 268 result = SL_RESULT_SUCCESS; 269 } 270 271 SL_LEAVE_INTERFACE 272} 273 274 275static const struct SLRecordItf_ IRecord_Itf = { 276 IRecord_SetRecordState, 277 IRecord_GetRecordState, 278 IRecord_SetDurationLimit, 279 IRecord_GetPosition, 280 IRecord_RegisterCallback, 281 IRecord_SetCallbackEventsMask, 282 IRecord_GetCallbackEventsMask, 283 IRecord_SetMarkerPosition, 284 IRecord_ClearMarkerPosition, 285 IRecord_GetMarkerPosition, 286 IRecord_SetPositionUpdatePeriod, 287 IRecord_GetPositionUpdatePeriod 288}; 289 290void IRecord_init(void *self) 291{ 292 IRecord *this = (IRecord *) self; 293 this->mItf = &IRecord_Itf; 294 this->mState = SL_RECORDSTATE_STOPPED; 295 this->mDurationLimit = 0; 296 this->mPosition = 0; 297 this->mCallback = NULL; 298 this->mContext = NULL; 299 this->mCallbackEventsMask = 0; 300 this->mMarkerPosition = 0; 301 this->mPositionUpdatePeriod = 1000; 302} 303