IPlay.c revision a8179ea15c4ff78db589d742b135649f0eda7ef2
1b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat/* 2b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * Copyright (C) 2010 The Android Open Source Project 3b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * 4b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * you may not use this file except in compliance with the License. 6b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * You may obtain a copy of the License at 7b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * 8b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * 10b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * Unless required by applicable law or agreed to in writing, software 11b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * See the License for the specific language governing permissions and 14b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat * limitations under the License. 15b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat */ 16b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 17b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat/* Play implementation */ 18b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 19b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include "sles_allinclusive.h" 20b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 21b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 22b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatstatic SLresult IPlay_SetPlayState(SLPlayItf self, SLuint32 state) 23b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat{ 24b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_ENTER_INTERFACE 25b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 26b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat switch (state) { 27d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case SL_PLAYSTATE_STOPPED: 28d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case SL_PLAYSTATE_PAUSED: 29b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat case SL_PLAYSTATE_PLAYING: 30b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat { 31b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat IPlay *thiz = (IPlay *) self; 32b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat unsigned attr = ATTR_NONE; 33d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat result = SL_RESULT_SUCCESS; 34d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#ifdef USE_OUTPUTMIXEXT 35b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat CAudioPlayer *audioPlayer = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 36b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat (CAudioPlayer *) thiz->mThis : NULL; 37d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#endif 38d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat interface_lock_exclusive(thiz); 39d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#ifdef USE_OUTPUTMIXEXT 40d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat for (;; interface_cond_wait(thiz)) { 41d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 42d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // We are comparing the old state (left) vs. new state (right). 43d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // Note that the old state is 3 bits wide, but new state is only 2 bits wide. 44d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // That is why the old state is on the left and new state is on the right. 45d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat switch ((thiz->mState << 2) | state) { 46d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 47d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_STOPPED << 2) | SL_PLAYSTATE_STOPPED: 48d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_PAUSED << 2) | SL_PLAYSTATE_PAUSED: 49d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_PLAYING << 2) | SL_PLAYSTATE_PLAYING: 50d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // no-op 51d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat break; 52d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 53d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_STOPPED << 2) | SL_PLAYSTATE_PLAYING: 54d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_PAUSED << 2) | SL_PLAYSTATE_PLAYING: 55d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat attr = ATTR_TRANSPORT; 56d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // set enqueue attribute if queue is non-empty and state becomes PLAYING 57d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if ((NULL != audioPlayer) && (audioPlayer->mBufferQueue.mFront != 58d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat audioPlayer->mBufferQueue.mRear)) { 59d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat attr |= ATTR_BQ_ENQUEUE; 60d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 61d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // fall through 62d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 63d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_STOPPED << 2) | SL_PLAYSTATE_PAUSED: 64d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_PLAYING << 2) | SL_PLAYSTATE_PAUSED: 65d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // easy 66d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat thiz->mState = state; 67d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat break; 68d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 69d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_STOPPING << 2) | SL_PLAYSTATE_STOPPED: 70d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // either spurious wakeup, or someone else requested same transition 71d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat continue; 72d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 73d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_STOPPING << 2) | SL_PLAYSTATE_PAUSED: 74d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_STOPPING << 2) | SL_PLAYSTATE_PLAYING: 75d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // wait for other guy to finish his transition, then retry ours 76d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat continue; 77d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 78d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_PAUSED << 2) | SL_PLAYSTATE_STOPPED: 79d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat case (SL_PLAYSTATE_PLAYING << 2) | SL_PLAYSTATE_STOPPED: 80d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // tell mixer to stop, then wait for mixer to acknowledge the request to stop 81d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat thiz->mState = SL_PLAYSTATE_STOPPING; 82d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat continue; 83d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 84d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat default: 85d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // unexpected state 86d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat assert(SL_BOOLEAN_FALSE); 87d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat result = SL_RESULT_INTERNAL_ERROR; 88d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat break; 89d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 90d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 91d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 92d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat break; 93d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 94d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#else 95d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // Here life looks easy for an Android, but there are other troubles in play land 96d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat thiz->mState = state; 97d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat attr = ATTR_TRANSPORT; 98d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#endif 99d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat // SL_LOGD("set play state %d", state); 100d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat interface_unlock_exclusive_attributes(thiz, attr); 101d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 102d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat break; 103d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat default: 104d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat result = SL_RESULT_PARAMETER_INVALID; 105d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat break; 106d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 107d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 108d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat SL_LEAVE_INTERFACE 109d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat} 110d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 111d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 112d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatstatic SLresult IPlay_GetPlayState(SLPlayItf self, SLuint32 *pState) 113b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat{ 114b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_ENTER_INTERFACE 115b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 116b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (NULL == pState) { 117b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_PARAMETER_INVALID; 118b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } else { 119b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat IPlay *thiz = (IPlay *) self; 120b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_lock_peek(thiz); 121b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SLuint32 state = thiz->mState; 122d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat interface_unlock_peek(thiz); 123d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat result = SL_RESULT_SUCCESS; 124d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat#ifdef USE_OUTPUTMIXEXT 125b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat switch (state) { 126b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat case SL_PLAYSTATE_STOPPED: // as is 127b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat case SL_PLAYSTATE_PAUSED: 128b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat case SL_PLAYSTATE_PLAYING: 129b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat break; 130b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat case SL_PLAYSTATE_STOPPING: // these states require re-mapping 131b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat state = SL_PLAYSTATE_STOPPED; 132b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat break; 133b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat default: // impossible 134b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat assert(SL_BOOLEAN_FALSE); 135b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat state = SL_PLAYSTATE_STOPPED; 136b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_INTERNAL_ERROR; 137b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat break; 138b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 139b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#endif 140b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat *pState = state; 141b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 142b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 143b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_LEAVE_INTERFACE 144b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 1458b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat 1468b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat 147b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatstatic SLresult IPlay_GetDuration(SLPlayItf self, SLmillisecond *pMsec) 148b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat{ 149b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_ENTER_INTERFACE 150b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 151b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (NULL == pMsec) { 152b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_PARAMETER_INVALID; 153b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } else { 154b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_SUCCESS; 155b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat IPlay *thiz = (IPlay *) self; 156b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // even though this is a getter, it can modify state due to caching 157b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_lock_exclusive(thiz); 158b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SLmillisecond duration = thiz->mDuration; 159b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#ifdef ANDROID 1608b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat if ((SL_TIME_UNKNOWN == duration) && 1618b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz))) { 162b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SLmillisecond temp; 163b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = android_audioPlayer_getDuration(thiz, &temp); 164b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (SL_RESULT_SUCCESS == result) { 165b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat duration = temp; 166b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat thiz->mDuration = duration; 167b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 168b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 169b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#else 170b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // will be set by containing AudioPlayer or MidiPlayer object at Realize, if known, 171b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // otherwise the duration will be updated each time a new maximum position is detected 172b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#endif 173b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_unlock_exclusive(thiz); 174b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat *pMsec = duration; 175b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 176b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 177b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_LEAVE_INTERFACE 178b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 179b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 180b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 181b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatstatic SLresult IPlay_GetPosition(SLPlayItf self, SLmillisecond *pMsec) 182b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat{ 183b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_ENTER_INTERFACE 184b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 185b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (NULL == pMsec) { 186b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_PARAMETER_INVALID; 187b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } else { 188b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat IPlay *thiz = (IPlay *) self; 189b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SLmillisecond position; 190b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_lock_shared(thiz); 191b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#ifdef ANDROID 192b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // Android does not use the mPosition field for audio players 193b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) { 194b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat android_audioPlayer_getPosition(thiz, &position); 195b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // note that we do not cache the position 196b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } else { 197b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat position = thiz->mPosition; 198b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 199b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#else 200b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // on other platforms we depend on periodic updates to the current position 201b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat position = thiz->mPosition; 202b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // if a seek is pending, then lie about current position so the seek appears synchronous 203b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) { 204b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat CAudioPlayer *audioPlayer = (CAudioPlayer *) thiz->mThis; 2058b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat SLmillisecond pos = audioPlayer->mSeek.mPos; 206b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (SL_TIME_UNKNOWN != pos) { 207b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat position = pos; 208b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 209b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 210b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#endif 211b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_unlock_shared(thiz); 212b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat *pMsec = position; 213b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_SUCCESS; 214b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 215b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 216b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_LEAVE_INTERFACE 217b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 218b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 219b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 220b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatstatic SLresult IPlay_RegisterCallback(SLPlayItf self, slPlayCallback callback, void *pContext) 221fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat{ 222b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_ENTER_INTERFACE 2238b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat 224fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat IPlay *thiz = (IPlay *) self; 225b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_lock_exclusive(thiz); 226b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat thiz->mCallback = callback; 227b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat thiz->mContext = pContext; 228b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // omits _attributes b/c noone cares deeply enough about these fields to need quick notification 229b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_unlock_exclusive(thiz); 230b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_SUCCESS; 231b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 232b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_LEAVE_INTERFACE 233b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 234b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 235b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 236b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatstatic SLresult IPlay_SetCallbackEventsMask(SLPlayItf self, SLuint32 eventFlags) 237b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat{ 238b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_ENTER_INTERFACE 239b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 240b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (eventFlags & ~(SL_PLAYEVENT_HEADATEND | SL_PLAYEVENT_HEADATMARKER | 241b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_PLAYEVENT_HEADATNEWPOS | SL_PLAYEVENT_HEADMOVING | SL_PLAYEVENT_HEADSTALLED)) { 242b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_PARAMETER_INVALID; 243b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } else { 244b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat IPlay *thiz = (IPlay *) self; 245b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_lock_exclusive(thiz); 246b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (thiz->mEventFlags != eventFlags) { 247b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#ifdef USE_OUTPUTMIXEXT 248b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat // enabling the "head at new position" play event will postpone the next update event 249b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (!(thiz->mEventFlags & SL_PLAYEVENT_HEADATNEWPOS) && 250b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat (eventFlags & SL_PLAYEVENT_HEADATNEWPOS)) { 251b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat thiz->mFramesSincePositionUpdate = 0; 2528c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat } 253b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#endif 254b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat thiz->mEventFlags = eventFlags; 255b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); 256b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } else 257b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_unlock_exclusive(thiz); 258b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_SUCCESS; 259b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } 260b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 261b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_LEAVE_INTERFACE 262b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 263b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 264b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 265b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatstatic SLresult IPlay_GetCallbackEventsMask(SLPlayItf self, SLuint32 *pEventFlags) 266b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat{ 267b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_ENTER_INTERFACE 268b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 269b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (NULL == pEventFlags) { 270b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_PARAMETER_INVALID; 271b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } else { 272b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat IPlay *thiz = (IPlay *) self; 273b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_lock_peek(thiz); 274b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SLuint32 eventFlags = thiz->mEventFlags; 275b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_unlock_peek(thiz); 2760586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat *pEventFlags = eventFlags; 2770586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat result = SL_RESULT_SUCCESS; 2780586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat } 279b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 280b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_LEAVE_INTERFACE 281b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat} 282b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 283b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 284b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatstatic SLresult IPlay_SetMarkerPosition(SLPlayItf self, SLmillisecond mSec) 285b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat{ 286b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat SL_ENTER_INTERFACE 287b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat 288b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat IPlay *thiz = (IPlay *) self; 289b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_lock_exclusive(thiz); 290b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat if (thiz->mMarkerPosition != mSec) { 291b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat thiz->mMarkerPosition = mSec; 292b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); 293b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat } else 294b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat interface_unlock_exclusive(thiz); 295b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat result = SL_RESULT_SUCCESS; 296 297 SL_LEAVE_INTERFACE 298} 299 300 301static SLresult IPlay_ClearMarkerPosition(SLPlayItf self) 302{ 303 SL_ENTER_INTERFACE 304 305 IPlay *thiz = (IPlay *) self; 306 interface_lock_exclusive(thiz); 307#ifdef ANDROID 308 if (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) { 309 // clearing the marker position is equivalent to setting the marker at 0 310 thiz->mMarkerPosition = 0; 311 } 312#endif 313 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); 314 result = SL_RESULT_SUCCESS; 315 316 SL_LEAVE_INTERFACE 317} 318 319 320static SLresult IPlay_GetMarkerPosition(SLPlayItf self, SLmillisecond *pMsec) 321{ 322 SL_ENTER_INTERFACE 323 324 if (NULL == pMsec) { 325 result = SL_RESULT_PARAMETER_INVALID; 326 } else { 327 IPlay *thiz = (IPlay *) self; 328 interface_lock_peek(thiz); 329 SLmillisecond markerPosition = thiz->mMarkerPosition; 330 interface_unlock_peek(thiz); 331 *pMsec = markerPosition; 332 result = SL_RESULT_SUCCESS; 333 } 334 335 SL_LEAVE_INTERFACE 336} 337 338 339static SLresult IPlay_SetPositionUpdatePeriod(SLPlayItf self, SLmillisecond mSec) 340{ 341 SL_ENTER_INTERFACE 342 343 if (0 == mSec) { 344 result = SL_RESULT_PARAMETER_INVALID; 345 } else { 346 IPlay *thiz = (IPlay *) self; 347 interface_lock_exclusive(thiz); 348 if (thiz->mPositionUpdatePeriod != mSec) { 349 thiz->mPositionUpdatePeriod = mSec; 350#ifdef ANDROID 351 if (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) { 352 // result = android_audioPlayer_useEventMask(thiz, thiz->mEventFlags); 353 } 354#endif 355#ifdef USE_OUTPUTMIXEXT 356 if (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) { 357 CAudioPlayer *audioPlayer = (CAudioPlayer *) thiz->mThis; 358 SLuint32 frameUpdatePeriod = ((long long) mSec * 359 (long long) audioPlayer->mSampleRateMilliHz) / 1000000LL; 360 if (0 == frameUpdatePeriod) 361 frameUpdatePeriod = ~0; 362 thiz->mFrameUpdatePeriod = frameUpdatePeriod; 363 // setting a new update period postpones the next callback 364 thiz->mFramesSincePositionUpdate = 0; 365 } 366#endif 367 interface_unlock_exclusive_attributes(thiz, ATTR_TRANSPORT); 368 } else 369 interface_unlock_exclusive(thiz); 370 result = SL_RESULT_SUCCESS; 371 } 372 373 SL_LEAVE_INTERFACE 374} 375 376 377static SLresult IPlay_GetPositionUpdatePeriod(SLPlayItf self, SLmillisecond *pMsec) 378{ 379 SL_ENTER_INTERFACE 380 381 if (NULL == pMsec) { 382 result = SL_RESULT_PARAMETER_INVALID; 383 } else { 384 IPlay *thiz = (IPlay *) self; 385 interface_lock_peek(thiz); 386 SLmillisecond positionUpdatePeriod = thiz->mPositionUpdatePeriod; 387 interface_unlock_peek(thiz); 388 *pMsec = positionUpdatePeriod; 389 result = SL_RESULT_SUCCESS; 390 } 391 392 SL_LEAVE_INTERFACE 393} 394 395 396static const struct SLPlayItf_ IPlay_Itf = { 397 IPlay_SetPlayState, 398 IPlay_GetPlayState, 399 IPlay_GetDuration, 400 IPlay_GetPosition, 401 IPlay_RegisterCallback, 402 IPlay_SetCallbackEventsMask, 403 IPlay_GetCallbackEventsMask, 404 IPlay_SetMarkerPosition, 405 IPlay_ClearMarkerPosition, 406 IPlay_GetMarkerPosition, 407 IPlay_SetPositionUpdatePeriod, 408 IPlay_GetPositionUpdatePeriod 409}; 410 411void IPlay_init(void *self) 412{ 413 IPlay *thiz = (IPlay *) self; 414 thiz->mItf = &IPlay_Itf; 415 thiz->mState = SL_PLAYSTATE_STOPPED; 416 thiz->mDuration = SL_TIME_UNKNOWN; // will be set by containing player object 417 thiz->mPosition = (SLmillisecond) 0; 418 thiz->mCallback = NULL; 419 thiz->mContext = NULL; 420 thiz->mEventFlags = 0; 421 thiz->mMarkerPosition = 0; 422 thiz->mPositionUpdatePeriod = 1000; 423#ifdef USE_OUTPUTMIXEXT 424 thiz->mFrameUpdatePeriod = 0; // because we don't know the sample rate yet 425 thiz->mLastSeekPosition = 0; 426 thiz->mFramesSinceLastSeek = 0; 427 thiz->mFramesSincePositionUpdate = 0; 428#endif 429} 430