fixed #17591: [ios, mac, win32] Audio could not be played in the callback of AudioEngine::setFinishedCallback (#17593)

* Moves the implementation of AudioEngine::AudioInfo to cpp file.

* fixed #17591: [ios, mac, win32] Audio could not be played in the callback of AudioEngine::setFinishedCallback

* fixed #17591: Adds test case.
This commit is contained in:
James Chen 2017-03-27 17:28:39 +08:00 committed by minggo
parent c8af3fe0bd
commit 6217d8c5ca
6 changed files with 121 additions and 19 deletions

View File

@ -67,6 +67,21 @@ AudioEngineImpl* AudioEngine::_audioEngineImpl = nullptr;
AudioEngine::AudioEngineThreadPool* AudioEngine::s_threadPool = nullptr; AudioEngine::AudioEngineThreadPool* AudioEngine::s_threadPool = nullptr;
AudioEngine::AudioInfo::AudioInfo()
: filePath(nullptr)
, profileHelper(nullptr)
, volume(1.0f)
, loop(false)
, duration(TIME_UNKNOWN)
, state(AudioState::INITIALIZING)
{
}
AudioEngine::AudioInfo::~AudioInfo()
{
}
class AudioEngine::AudioEngineThreadPool class AudioEngine::AudioEngineThreadPool
{ {
public: public:

View File

@ -588,37 +588,44 @@ void AudioEngineImpl::update(float dt)
ALint sourceState; ALint sourceState;
int audioID; int audioID;
AudioPlayer* player; AudioPlayer* player;
ALuint alSource;
// ALOGV("AudioPlayer count: %d", (int)_audioPlayers.size()); // ALOGV("AudioPlayer count: %d", (int)_audioPlayers.size());
for (auto it = _audioPlayers.begin(); it != _audioPlayers.end(); ) { for (auto it = _audioPlayers.begin(); it != _audioPlayers.end(); ) {
audioID = it->first; audioID = it->first;
player = it->second; player = it->second;
alGetSourcei(player->_alSource, AL_SOURCE_STATE, &sourceState); alSource = player->_alSource;
alGetSourcei(alSource, AL_SOURCE_STATE, &sourceState);
if (player->_removeByAudioEngine) if (player->_removeByAudioEngine)
{ {
_alSourceUsed[player->_alSource] = false;
AudioEngine::remove(audioID); AudioEngine::remove(audioID);
_threadMutex.lock(); _threadMutex.lock();
it = _audioPlayers.erase(it); it = _audioPlayers.erase(it);
_threadMutex.unlock(); _threadMutex.unlock();
delete player; delete player;
_alSourceUsed[alSource] = false;
} }
else if (player->_ready && sourceState == AL_STOPPED) { else if (player->_ready && sourceState == AL_STOPPED) {
_alSourceUsed[player->_alSource] = false; std::string filePath;
if (player->_finishCallbak) { if (player->_finishCallbak) {
auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID]; auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID];
player->_finishCallbak(audioID, *audioInfo.filePath); //FIXME: callback will delay 50ms filePath = *audioInfo.filePath;
} }
AudioEngine::remove(audioID); AudioEngine::remove(audioID);
delete player;
_threadMutex.lock(); _threadMutex.lock();
it = _audioPlayers.erase(it); it = _audioPlayers.erase(it);
_threadMutex.unlock(); _threadMutex.unlock();
if (player->_finishCallbak) {
player->_finishCallbak(audioID, filePath); //FIXME: callback will delay 50ms
}
delete player;
_alSourceUsed[alSource] = false;
} }
else{ else{
++it; ++it;

View File

@ -321,13 +321,13 @@ protected:
float duration; float duration;
AudioState state; AudioState state;
AudioInfo() AudioInfo();
: profileHelper(nullptr) ~AudioInfo();
, duration(TIME_UNKNOWN) private:
, state(AudioState::INITIALIZING) AudioInfo(const AudioInfo& info);
{ AudioInfo(AudioInfo&& info);
AudioInfo& operator=(const AudioInfo& info);
} AudioInfo& operator=(AudioInfo&& info);
}; };
//audioID,audioAttribute //audioID,audioAttribute

View File

@ -444,37 +444,44 @@ void AudioEngineImpl::update(float dt)
ALint sourceState; ALint sourceState;
int audioID; int audioID;
AudioPlayer* player; AudioPlayer* player;
ALuint alSource;
// ALOGV("AudioPlayer count: %d", (int)_audioPlayers.size()); // ALOGV("AudioPlayer count: %d", (int)_audioPlayers.size());
for (auto it = _audioPlayers.begin(); it != _audioPlayers.end(); ) { for (auto it = _audioPlayers.begin(); it != _audioPlayers.end(); ) {
audioID = it->first; audioID = it->first;
player = it->second; player = it->second;
alGetSourcei(player->_alSource, AL_SOURCE_STATE, &sourceState); alSource = player->_alSource;
alGetSourcei(alSource, AL_SOURCE_STATE, &sourceState);
if (player->_removeByAudioEngine) if (player->_removeByAudioEngine)
{ {
_alSourceUsed[player->_alSource] = false;
AudioEngine::remove(audioID); AudioEngine::remove(audioID);
_threadMutex.lock(); _threadMutex.lock();
it = _audioPlayers.erase(it); it = _audioPlayers.erase(it);
_threadMutex.unlock(); _threadMutex.unlock();
delete player; delete player;
_alSourceUsed[alSource] = false;
} }
else if (player->_ready && sourceState == AL_STOPPED) { else if (player->_ready && sourceState == AL_STOPPED) {
_alSourceUsed[player->_alSource] = false; std::string filePath;
if (player->_finishCallbak) { if (player->_finishCallbak) {
auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID]; auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID];
player->_finishCallbak(audioID, *audioInfo.filePath); //FIXME: callback will delay 50ms filePath = *audioInfo.filePath;
} }
AudioEngine::remove(audioID); AudioEngine::remove(audioID);
delete player;
_threadMutex.lock(); _threadMutex.lock();
it = _audioPlayers.erase(it); it = _audioPlayers.erase(it);
_threadMutex.unlock(); _threadMutex.unlock();
if (player->_finishCallbak) {
player->_finishCallbak(audioID, filePath); //FIXME: callback will delay 50ms
}
delete player;
_alSourceUsed[alSource] = false;
} }
else{ else{
++it; ++it;

View File

@ -47,6 +47,7 @@ AudioEngineTests::AudioEngineTests()
ADD_TEST_CASE(AudioPreloadSameFileMultipleTimes); ADD_TEST_CASE(AudioPreloadSameFileMultipleTimes);
ADD_TEST_CASE(AudioPlayFileInWritablePath); ADD_TEST_CASE(AudioPlayFileInWritablePath);
ADD_TEST_CASE(AudioIssue16938Test); ADD_TEST_CASE(AudioIssue16938Test);
ADD_TEST_CASE(AudioPlayInFinishedCB);
//FIXME: Please keep AudioSwitchStateTest to the last position since this test case doesn't work well on each platforms. //FIXME: Please keep AudioSwitchStateTest to the last position since this test case doesn't work well on each platforms.
ADD_TEST_CASE(AudioSwitchStateTest); ADD_TEST_CASE(AudioSwitchStateTest);
@ -985,3 +986,58 @@ std::string AudioPlayFileInWritablePath::subtitle() const
{ {
return "Could play audio"; return "Could play audio";
} }
//
void AudioPlayInFinishedCB::onEnter()
{
AudioEngineTestDemo::onEnter();
auto item = MenuItemFont::create("Play 3 files one by one", [this](Ref* sender){
playMusic("background.mp3");
playMusic("background.mp3");
playMusic("background.mp3");
});
item->setPosition(VisibleRect::center());
auto menu = Menu::create(item, nullptr);
menu->setPosition(Vec2::ANCHOR_BOTTOM_LEFT);
addChild(menu);
}
void AudioPlayInFinishedCB::onExit()
{
AudioEngineTestDemo::onExit();
}
std::string AudioPlayInFinishedCB::title() const
{
return "Click menu item to play 3 audio files";
}
std::string AudioPlayInFinishedCB::subtitle() const
{
return "After played over, click again, should also hear 3 audios";
}
void AudioPlayInFinishedCB::doPlay(const std::string& filename)
{
int playID = AudioEngine::play2d(filename, false, 1);
AudioEngine::setFinishCallback(playID, [this](int finishID, const std::string& file){
_playList.pop_front();
log("finish music %s",file.c_str());
if (!_playList.empty()) {
const std::string& name = _playList.front();
doPlay(name);
}
});
}
void AudioPlayInFinishedCB::playMusic(const std::string& filename)
{
_playList.push_back(filename);
if (_playList.size() == 1) {
doPlay(filename);
}
}

View File

@ -271,4 +271,21 @@ private:
std::vector<std::string> _oldSearchPaths; std::vector<std::string> _oldSearchPaths;
}; };
class AudioPlayInFinishedCB : public AudioEngineTestDemo
{
public:
CREATE_FUNC(AudioPlayInFinishedCB);
virtual void onEnter() override;
virtual void onExit() override;
virtual std::string title() const override;
virtual std::string subtitle() const override;
private:
void doPlay(const std::string& filename);
void playMusic(const std::string& filename);
std::list<std::string> _playList;
};
#endif /* defined(__NEWAUDIOENGINE_TEST_H_) */ #endif /* defined(__NEWAUDIOENGINE_TEST_H_) */