| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* Record implementation */ |
| |
| #include "sles_allinclusive.h" |
| |
| |
| static SLresult IRecord_SetRecordState(SLRecordItf self, SLuint32 state) |
| { |
| SL_ENTER_INTERFACE |
| |
| switch (state) { |
| case SL_RECORDSTATE_STOPPED: |
| case SL_RECORDSTATE_PAUSED: |
| case SL_RECORDSTATE_RECORDING: |
| { |
| IRecord *thiz = (IRecord *) self; |
| interface_lock_exclusive(thiz); |
| thiz->mState = state; |
| #ifdef ANDROID |
| android_audioRecorder_setRecordState(InterfaceToCAudioRecorder(thiz), state); |
| #endif |
| interface_unlock_exclusive(thiz); |
| result = SL_RESULT_SUCCESS; |
| } |
| break; |
| default: |
| result = SL_RESULT_PARAMETER_INVALID; |
| break; |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_GetRecordState(SLRecordItf self, SLuint32 *pState) |
| { |
| SL_ENTER_INTERFACE |
| |
| IRecord *thiz = (IRecord *) self; |
| if (NULL == pState) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| interface_lock_shared(thiz); |
| SLuint32 state = thiz->mState; |
| interface_unlock_shared(thiz); |
| *pState = state; |
| result = SL_RESULT_SUCCESS; |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_SetDurationLimit(SLRecordItf self, SLmillisecond msec) |
| { |
| SL_ENTER_INTERFACE |
| |
| IRecord *thiz = (IRecord *) self; |
| interface_lock_exclusive(thiz); |
| if (thiz->mDurationLimit != msec) { |
| thiz->mDurationLimit = msec; |
| interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); |
| } else { |
| interface_unlock_exclusive(thiz); |
| } |
| result = SL_RESULT_SUCCESS; |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_GetPosition(SLRecordItf self, SLmillisecond *pMsec) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (NULL == pMsec) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IRecord *thiz = (IRecord *) self; |
| SLmillisecond position; |
| interface_lock_shared(thiz); |
| #ifdef ANDROID |
| // Android does not use the mPosition field for audio recorders |
| if (SL_OBJECTID_AUDIORECORDER == InterfaceToObjectID(thiz)) { |
| android_audioRecorder_getPosition(InterfaceToCAudioRecorder(thiz), &position); |
| } else { |
| position = thiz->mPosition; |
| } |
| #else |
| position = thiz->mPosition; |
| #endif |
| interface_unlock_shared(thiz); |
| *pMsec = position; |
| result = SL_RESULT_SUCCESS; |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_RegisterCallback(SLRecordItf self, slRecordCallback callback, |
| void *pContext) |
| { |
| SL_ENTER_INTERFACE |
| |
| IRecord *thiz = (IRecord *) self; |
| interface_lock_exclusive(thiz); |
| thiz->mCallback = callback; |
| thiz->mContext = pContext; |
| interface_unlock_exclusive(thiz); |
| result = SL_RESULT_SUCCESS; |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_SetCallbackEventsMask(SLRecordItf self, SLuint32 eventFlags) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (eventFlags & ~( |
| SL_RECORDEVENT_HEADATLIMIT | |
| SL_RECORDEVENT_HEADATMARKER | |
| SL_RECORDEVENT_HEADATNEWPOS | |
| SL_RECORDEVENT_HEADMOVING | |
| SL_RECORDEVENT_HEADSTALLED | |
| SL_RECORDEVENT_BUFFER_FULL)) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IRecord *thiz = (IRecord *) self; |
| interface_lock_exclusive(thiz); |
| if (thiz->mCallbackEventsMask != eventFlags) { |
| thiz->mCallbackEventsMask = eventFlags; |
| interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); |
| } else { |
| interface_unlock_exclusive(thiz); |
| } |
| result = SL_RESULT_SUCCESS; |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_GetCallbackEventsMask(SLRecordItf self, SLuint32 *pEventFlags) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (NULL == pEventFlags) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IRecord *thiz = (IRecord *) self; |
| interface_lock_shared(thiz); |
| SLuint32 callbackEventsMask = thiz->mCallbackEventsMask; |
| interface_unlock_shared(thiz); |
| *pEventFlags = callbackEventsMask; |
| result = SL_RESULT_SUCCESS; |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_SetMarkerPosition(SLRecordItf self, SLmillisecond mSec) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (SL_TIME_UNKNOWN == mSec) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IRecord *thiz = (IRecord *) self; |
| bool significant = false; |
| interface_lock_exclusive(thiz); |
| if (thiz->mMarkerPosition != mSec) { |
| thiz->mMarkerPosition = mSec; |
| if (thiz->mCallbackEventsMask & SL_PLAYEVENT_HEADATMARKER) { |
| significant = true; |
| } |
| } |
| if (significant) { |
| interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); |
| } else { |
| interface_unlock_exclusive(thiz); |
| } |
| result = SL_RESULT_SUCCESS; |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_ClearMarkerPosition(SLRecordItf self) |
| { |
| SL_ENTER_INTERFACE |
| |
| IRecord *thiz = (IRecord *) self; |
| bool significant = false; |
| interface_lock_exclusive(thiz); |
| // clearing the marker position is equivalent to setting the marker to SL_TIME_UNKNOWN |
| if (thiz->mMarkerPosition != SL_TIME_UNKNOWN) { |
| thiz->mMarkerPosition = SL_TIME_UNKNOWN; |
| if (thiz->mCallbackEventsMask & SL_PLAYEVENT_HEADATMARKER) { |
| significant = true; |
| } |
| } |
| if (significant) { |
| interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); |
| } else { |
| interface_unlock_exclusive(thiz); |
| } |
| result = SL_RESULT_SUCCESS; |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_GetMarkerPosition(SLRecordItf self, SLmillisecond *pMsec) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (NULL == pMsec) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IRecord *thiz = (IRecord *) self; |
| interface_lock_shared(thiz); |
| SLmillisecond markerPosition = thiz->mMarkerPosition; |
| interface_unlock_shared(thiz); |
| *pMsec = markerPosition; |
| if (SL_TIME_UNKNOWN == markerPosition) { |
| result = SL_RESULT_PRECONDITIONS_VIOLATED; |
| } else { |
| result = SL_RESULT_SUCCESS; |
| } |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_SetPositionUpdatePeriod(SLRecordItf self, SLmillisecond mSec) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (0 == mSec) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IRecord *thiz = (IRecord *) self; |
| interface_lock_exclusive(thiz); |
| if (thiz->mPositionUpdatePeriod != mSec) { |
| thiz->mPositionUpdatePeriod = mSec; |
| interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); |
| } else { |
| interface_unlock_exclusive(thiz); |
| } |
| result = SL_RESULT_SUCCESS; |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IRecord_GetPositionUpdatePeriod(SLRecordItf self, SLmillisecond *pMsec) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (NULL == pMsec) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IRecord *thiz = (IRecord *) self; |
| interface_lock_shared(thiz); |
| SLmillisecond positionUpdatePeriod = thiz->mPositionUpdatePeriod; |
| interface_unlock_shared(thiz); |
| *pMsec = positionUpdatePeriod; |
| result = SL_RESULT_SUCCESS; |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static const struct SLRecordItf_ IRecord_Itf = { |
| IRecord_SetRecordState, |
| IRecord_GetRecordState, |
| IRecord_SetDurationLimit, |
| IRecord_GetPosition, |
| IRecord_RegisterCallback, |
| IRecord_SetCallbackEventsMask, |
| IRecord_GetCallbackEventsMask, |
| IRecord_SetMarkerPosition, |
| IRecord_ClearMarkerPosition, |
| IRecord_GetMarkerPosition, |
| IRecord_SetPositionUpdatePeriod, |
| IRecord_GetPositionUpdatePeriod |
| }; |
| |
| void IRecord_init(void *self) |
| { |
| IRecord *thiz = (IRecord *) self; |
| thiz->mItf = &IRecord_Itf; |
| thiz->mState = SL_RECORDSTATE_STOPPED; |
| thiz->mDurationLimit = 0; |
| thiz->mPosition = (SLmillisecond) 0; |
| thiz->mCallback = NULL; |
| thiz->mContext = NULL; |
| thiz->mCallbackEventsMask = 0; |
| thiz->mMarkerPosition = SL_TIME_UNKNOWN; |
| thiz->mPositionUpdatePeriod = 1000; // per spec |
| } |