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 22 static 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 *thiz = (IRecord *) self; 32 interface_lock_exclusive(thiz); 33 thiz->mState = state; 34 #ifdef ANDROID 35 android_audioRecorder_setRecordState(InterfaceToCAudioRecorder(thiz), state); 36 #endif 37 interface_unlock_exclusive(thiz); 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 50 static SLresult IRecord_GetRecordState(SLRecordItf self, SLuint32 *pState) 51 { 52 SL_ENTER_INTERFACE 53 54 IRecord *thiz = (IRecord *) self; 55 if (NULL == pState) { 56 result = SL_RESULT_PARAMETER_INVALID; 57 } else { 58 interface_lock_shared(thiz); 59 SLuint32 state = thiz->mState; 60 interface_unlock_shared(thiz); 61 *pState = state; 62 result = SL_RESULT_SUCCESS; 63 } 64 65 SL_LEAVE_INTERFACE 66 } 67 68 69 static SLresult IRecord_SetDurationLimit(SLRecordItf self, SLmillisecond msec) 70 { 71 SL_ENTER_INTERFACE 72 73 IRecord *thiz = (IRecord *) self; 74 interface_lock_exclusive(thiz); 75 if (thiz->mDurationLimit != msec) { 76 thiz->mDurationLimit = msec; 77 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); 78 } else { 79 interface_unlock_exclusive(thiz); 80 } 81 result = SL_RESULT_SUCCESS; 82 83 SL_LEAVE_INTERFACE 84 } 85 86 87 static 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 *thiz = (IRecord *) self; 95 SLmillisecond position; 96 interface_lock_shared(thiz); 97 #ifdef ANDROID 98 // Android does not use the mPosition field for audio recorders 99 if (SL_OBJECTID_AUDIORECORDER == InterfaceToObjectID(thiz)) { 100 android_audioRecorder_getPosition(InterfaceToCAudioRecorder(thiz), &position); 101 } else { 102 position = thiz->mPosition; 103 } 104 #else 105 position = thiz->mPosition; 106 #endif 107 interface_unlock_shared(thiz); 108 *pMsec = position; 109 result = SL_RESULT_SUCCESS; 110 } 111 112 SL_LEAVE_INTERFACE 113 } 114 115 116 static SLresult IRecord_RegisterCallback(SLRecordItf self, slRecordCallback callback, 117 void *pContext) 118 { 119 SL_ENTER_INTERFACE 120 121 IRecord *thiz = (IRecord *) self; 122 interface_lock_exclusive(thiz); 123 thiz->mCallback = callback; 124 thiz->mContext = pContext; 125 interface_unlock_exclusive(thiz); 126 result = SL_RESULT_SUCCESS; 127 128 SL_LEAVE_INTERFACE 129 } 130 131 132 static 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 *thiz = (IRecord *) self; 146 interface_lock_exclusive(thiz); 147 if (thiz->mCallbackEventsMask != eventFlags) { 148 thiz->mCallbackEventsMask = eventFlags; 149 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); 150 } else { 151 interface_unlock_exclusive(thiz); 152 } 153 result = SL_RESULT_SUCCESS; 154 } 155 156 SL_LEAVE_INTERFACE 157 } 158 159 160 static 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 *thiz = (IRecord *) self; 168 interface_lock_shared(thiz); 169 SLuint32 callbackEventsMask = thiz->mCallbackEventsMask; 170 interface_unlock_shared(thiz); 171 *pEventFlags = callbackEventsMask; 172 result = SL_RESULT_SUCCESS; 173 } 174 175 SL_LEAVE_INTERFACE 176 } 177 178 179 static SLresult IRecord_SetMarkerPosition(SLRecordItf self, SLmillisecond mSec) 180 { 181 SL_ENTER_INTERFACE 182 183 if (SL_TIME_UNKNOWN == mSec) { 184 result = SL_RESULT_PARAMETER_INVALID; 185 } else { 186 IRecord *thiz = (IRecord *) self; 187 bool significant = false; 188 interface_lock_exclusive(thiz); 189 if (thiz->mMarkerPosition != mSec) { 190 thiz->mMarkerPosition = mSec; 191 if (thiz->mCallbackEventsMask & SL_PLAYEVENT_HEADATMARKER) { 192 significant = true; 193 } 194 } 195 if (significant) { 196 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); 197 } else { 198 interface_unlock_exclusive(thiz); 199 } 200 result = SL_RESULT_SUCCESS; 201 } 202 203 SL_LEAVE_INTERFACE 204 } 205 206 207 static SLresult IRecord_ClearMarkerPosition(SLRecordItf self) 208 { 209 SL_ENTER_INTERFACE 210 211 IRecord *thiz = (IRecord *) self; 212 bool significant = false; 213 interface_lock_exclusive(thiz); 214 // clearing the marker position is equivalent to setting the marker to SL_TIME_UNKNOWN 215 if (thiz->mMarkerPosition != SL_TIME_UNKNOWN) { 216 thiz->mMarkerPosition = SL_TIME_UNKNOWN; 217 if (thiz->mCallbackEventsMask & SL_PLAYEVENT_HEADATMARKER) { 218 significant = true; 219 } 220 } 221 if (significant) { 222 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); 223 } else { 224 interface_unlock_exclusive(thiz); 225 } 226 result = SL_RESULT_SUCCESS; 227 228 SL_LEAVE_INTERFACE 229 } 230 231 232 static SLresult IRecord_GetMarkerPosition(SLRecordItf self, SLmillisecond *pMsec) 233 { 234 SL_ENTER_INTERFACE 235 236 if (NULL == pMsec) { 237 result = SL_RESULT_PARAMETER_INVALID; 238 } else { 239 IRecord *thiz = (IRecord *) self; 240 interface_lock_shared(thiz); 241 SLmillisecond markerPosition = thiz->mMarkerPosition; 242 interface_unlock_shared(thiz); 243 *pMsec = markerPosition; 244 if (SL_TIME_UNKNOWN == markerPosition) { 245 result = SL_RESULT_PRECONDITIONS_VIOLATED; 246 } else { 247 result = SL_RESULT_SUCCESS; 248 } 249 } 250 251 SL_LEAVE_INTERFACE 252 } 253 254 255 static SLresult IRecord_SetPositionUpdatePeriod(SLRecordItf self, SLmillisecond mSec) 256 { 257 SL_ENTER_INTERFACE 258 259 if (0 == mSec) { 260 result = SL_RESULT_PARAMETER_INVALID; 261 } else { 262 IRecord *thiz = (IRecord *) self; 263 interface_lock_exclusive(thiz); 264 if (thiz->mPositionUpdatePeriod != mSec) { 265 thiz->mPositionUpdatePeriod = mSec; 266 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); 267 } else { 268 interface_unlock_exclusive(thiz); 269 } 270 result = SL_RESULT_SUCCESS; 271 } 272 273 SL_LEAVE_INTERFACE 274 } 275 276 277 static SLresult IRecord_GetPositionUpdatePeriod(SLRecordItf self, SLmillisecond *pMsec) 278 { 279 SL_ENTER_INTERFACE 280 281 if (NULL == pMsec) { 282 result = SL_RESULT_PARAMETER_INVALID; 283 } else { 284 IRecord *thiz = (IRecord *) self; 285 interface_lock_shared(thiz); 286 SLmillisecond positionUpdatePeriod = thiz->mPositionUpdatePeriod; 287 interface_unlock_shared(thiz); 288 *pMsec = positionUpdatePeriod; 289 result = SL_RESULT_SUCCESS; 290 } 291 292 SL_LEAVE_INTERFACE 293 } 294 295 296 static const struct SLRecordItf_ IRecord_Itf = { 297 IRecord_SetRecordState, 298 IRecord_GetRecordState, 299 IRecord_SetDurationLimit, 300 IRecord_GetPosition, 301 IRecord_RegisterCallback, 302 IRecord_SetCallbackEventsMask, 303 IRecord_GetCallbackEventsMask, 304 IRecord_SetMarkerPosition, 305 IRecord_ClearMarkerPosition, 306 IRecord_GetMarkerPosition, 307 IRecord_SetPositionUpdatePeriod, 308 IRecord_GetPositionUpdatePeriod 309 }; 310 311 void IRecord_init(void *self) 312 { 313 IRecord *thiz = (IRecord *) self; 314 thiz->mItf = &IRecord_Itf; 315 thiz->mState = SL_RECORDSTATE_STOPPED; 316 thiz->mDurationLimit = 0; 317 thiz->mPosition = (SLmillisecond) 0; 318 thiz->mCallback = NULL; 319 thiz->mContext = NULL; 320 thiz->mCallbackEventsMask = 0; 321 thiz->mMarkerPosition = SL_TIME_UNKNOWN; 322 thiz->mPositionUpdatePeriod = 1000; // per spec 323 } 324