2011-08-22 09:45:53 +02:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <FSysSettingInfo.h>
|
|
|
|
#include <FAppAppRegistry.h>
|
|
|
|
|
|
|
|
#include "backends/platform/bada/audio.h"
|
|
|
|
#include "backends/platform/bada/system.h"
|
|
|
|
|
|
|
|
#define TIMER_INCREMENT 10
|
|
|
|
#define TIMER_INTERVAL 40
|
|
|
|
#define MIN_TIMER_INTERVAL 10
|
|
|
|
#define MAX_TIMER_INTERVAL 160
|
|
|
|
#define INIT_LEVEL 3
|
|
|
|
#define CONFIG_KEY L"audiovol"
|
|
|
|
|
|
|
|
// sound level pre-sets
|
|
|
|
const int levels[] = {0, 1, 10, 45, 70, 99};
|
|
|
|
|
2011-08-22 09:46:30 +02:00
|
|
|
AudioThread::AudioThread() :
|
2011-08-22 09:45:53 +02:00
|
|
|
_mixer(0),
|
|
|
|
_timer(0),
|
|
|
|
_audioOut(0),
|
|
|
|
_head(0),
|
|
|
|
_tail(0),
|
|
|
|
_ready(0),
|
|
|
|
_interval(TIMER_INTERVAL),
|
|
|
|
_playing(-1),
|
|
|
|
_muted(true) {
|
|
|
|
}
|
|
|
|
|
|
|
|
Audio::MixerImpl *AudioThread::Construct(OSystem *system) {
|
|
|
|
logEntered();
|
|
|
|
|
|
|
|
if (IsFailed(Thread::Construct(THREAD_TYPE_EVENT_DRIVEN,
|
|
|
|
DEFAULT_STACK_SIZE,
|
|
|
|
THREAD_PRIORITY_HIGH))) {
|
|
|
|
AppLog("Failed to create AudioThread");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
_mixer = new Audio::MixerImpl(system, 44100);
|
|
|
|
return _mixer;
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioThread::~AudioThread() {
|
|
|
|
logEntered();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AudioThread::isSilentMode() {
|
|
|
|
bool silentMode;
|
|
|
|
String key(L"SilentMode");
|
|
|
|
Osp::System::SettingInfo::GetValue(key, silentMode);
|
|
|
|
return silentMode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioThread::setMute(bool on) {
|
2011-10-17 22:35:48 +10:00
|
|
|
if (_audioOut && _timer) {
|
2011-08-22 09:45:53 +02:00
|
|
|
_muted = on;
|
|
|
|
if (on) {
|
|
|
|
_timer->Cancel();
|
|
|
|
} else {
|
|
|
|
_timer->Start(_interval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int AudioThread::setVolume(bool up, bool minMax) {
|
|
|
|
int level = -1;
|
|
|
|
int numLevels = sizeof(levels) / sizeof(levels[0]);
|
|
|
|
|
2011-10-17 22:35:48 +10:00
|
|
|
if (_audioOut) {
|
2011-08-22 09:45:53 +02:00
|
|
|
int volume = _audioOut->GetVolume();
|
|
|
|
if (minMax) {
|
|
|
|
level = up ? numLevels - 1 : 0;
|
|
|
|
volume = levels[level];
|
|
|
|
} else {
|
|
|
|
// adjust volume to be one of the preset values
|
|
|
|
for (int i = 0; i < numLevels && level == -1; i++) {
|
|
|
|
if (volume == levels[i]) {
|
|
|
|
level = i;
|
|
|
|
if (up) {
|
|
|
|
if (i + 1 < numLevels) {
|
|
|
|
level = i + 1;
|
|
|
|
}
|
|
|
|
} else if (i > 0) {
|
|
|
|
level = i - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// default to INIT_LEVEL when current not preset value
|
|
|
|
if (level == -1) {
|
|
|
|
level = INIT_LEVEL;
|
|
|
|
}
|
|
|
|
volume = levels[level];
|
|
|
|
}
|
|
|
|
|
|
|
|
_audioOut->SetVolume(volume);
|
|
|
|
|
|
|
|
// remember the chosen setting
|
|
|
|
AppRegistry *registry = Application::GetInstance()->GetAppRegistry();
|
|
|
|
if (registry) {
|
|
|
|
registry->Set(CONFIG_KEY, volume);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return level;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AudioThread::OnStart(void) {
|
|
|
|
logEntered();
|
|
|
|
|
|
|
|
_audioOut = new Osp::Media::AudioOut();
|
|
|
|
if (!_audioOut ||
|
|
|
|
IsFailed(_audioOut->Construct(*this))) {
|
|
|
|
AppLog("Failed to create AudioOut");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sampleRate = _mixer->getOutputRate();
|
|
|
|
|
|
|
|
// ideally we would update _mixer with GetOptimizedSampleRate here
|
|
|
|
if (_audioOut->GetOptimizedSampleRate() != sampleRate) {
|
|
|
|
AppLog("Non optimal sample rate %d", _audioOut->GetOptimizedSampleRate());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsFailed(_audioOut->Prepare(AUDIO_TYPE_PCM_S16_LE,
|
|
|
|
AUDIO_CHANNEL_TYPE_STEREO,
|
|
|
|
sampleRate))) {
|
|
|
|
AppLog("Failed to prepare AudioOut %d", sampleRate);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bufferSize = _audioOut->GetMinBufferSize();
|
|
|
|
for (int i = 0; i < NUM_AUDIO_BUFFERS; i++) {
|
|
|
|
if (IsFailed(_audioBuffer[i].Construct(bufferSize))) {
|
|
|
|
AppLog("Failed to create audio buffer");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_timer = new Timer();
|
|
|
|
if (!_timer || IsFailed(_timer->Construct(*this))) {
|
|
|
|
AppLog("Failed to create audio timer");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsFailed(_timer->Start(_interval))) {
|
|
|
|
AppLog("failed to start audio timer");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the volume from the app-registry
|
|
|
|
int volume = levels[INIT_LEVEL];
|
|
|
|
AppRegistry *registry = Application::GetInstance()->GetAppRegistry();
|
|
|
|
if (registry) {
|
|
|
|
if (E_KEY_NOT_FOUND == registry->Get(CONFIG_KEY, volume)) {
|
|
|
|
registry->Add(CONFIG_KEY, volume);
|
|
|
|
volume = levels[INIT_LEVEL];
|
|
|
|
} else {
|
|
|
|
AppLog("Setting volume: %d", volume);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_muted = false;
|
|
|
|
_mixer->setReady(true);
|
|
|
|
_audioOut->SetVolume(isSilentMode() ? 0 : volume);
|
|
|
|
_audioOut->Start();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioThread::OnStop(void) {
|
|
|
|
logEntered();
|
|
|
|
|
|
|
|
_mixer->setReady(false);
|
|
|
|
|
|
|
|
if (_timer) {
|
|
|
|
if (!_muted) {
|
|
|
|
_timer->Cancel();
|
|
|
|
}
|
|
|
|
delete _timer;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_audioOut) {
|
|
|
|
_audioOut->Reset();
|
|
|
|
delete _audioOut;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioThread::OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r) {
|
|
|
|
logEntered();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioThread::OnAudioOutInterrupted(Osp::Media::AudioOut &src) {
|
|
|
|
logEntered();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioThread::OnAudioOutReleased(Osp::Media::AudioOut &src) {
|
|
|
|
logEntered();
|
|
|
|
_audioOut->Start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioThread::OnAudioOutBufferEndReached(Osp::Media::AudioOut &src) {
|
|
|
|
if (_ready > 0) {
|
|
|
|
_playing = _tail;
|
|
|
|
_audioOut->WriteBuffer(_audioBuffer[_tail]);
|
|
|
|
_tail = (_tail + 1) % NUM_AUDIO_BUFFERS;
|
|
|
|
_ready--;
|
|
|
|
} else {
|
|
|
|
// audio buffer empty: decrease timer inverval
|
|
|
|
_playing = -1;
|
|
|
|
_interval -= TIMER_INCREMENT;
|
|
|
|
if (_interval < MIN_TIMER_INTERVAL) {
|
|
|
|
_interval = MIN_TIMER_INTERVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioThread::OnTimerExpired(Timer &timer) {
|
|
|
|
if (_ready < NUM_AUDIO_BUFFERS) {
|
|
|
|
uint len = _audioBuffer[_head].GetCapacity();
|
2012-02-15 09:53:31 -06:00
|
|
|
int samples = _mixer->mixCallback((byte *)_audioBuffer[_head].GetPointer(), len);
|
2011-08-22 09:45:53 +02:00
|
|
|
if (samples) {
|
|
|
|
_head = (_head + 1) % NUM_AUDIO_BUFFERS;
|
|
|
|
_ready++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// audio buffer full: increase timer inverval
|
|
|
|
_interval += TIMER_INCREMENT;
|
|
|
|
if (_interval > MAX_TIMER_INTERVAL) {
|
|
|
|
_interval = MAX_TIMER_INTERVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_ready && _playing == -1) {
|
|
|
|
OnAudioOutBufferEndReached(*_audioOut);
|
|
|
|
}
|
2011-08-22 09:46:30 +02:00
|
|
|
|
2011-08-22 09:45:53 +02:00
|
|
|
_timer->Start(_interval);
|
|
|
|
}
|
|
|
|
|