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::AudioInfo::AudioInfo()
: filePath(nullptr)
, profileHelper(nullptr)
, volume(1.0f)
, loop(false)
, duration(TIME_UNKNOWN)
, state(AudioState::INITIALIZING)
{
}
AudioEngine::AudioInfo::~AudioInfo()
{
}
class AudioEngine::AudioEngineThreadPool
{
public:

View File

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

View File

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

View File

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

View File

@ -47,6 +47,7 @@ AudioEngineTests::AudioEngineTests()
ADD_TEST_CASE(AudioPreloadSameFileMultipleTimes);
ADD_TEST_CASE(AudioPlayFileInWritablePath);
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.
ADD_TEST_CASE(AudioSwitchStateTest);
@ -985,3 +986,58 @@ std::string AudioPlayFileInWritablePath::subtitle() const
{
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;
};
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_) */