Если вы используете Modernizr , очень просто использовать Modernizr.touch
, как упоминалось ранее.
Однако я предпочитаю использовать комбинацию Modernizr.touch
и тестирование пользовательского агента, просто чтобы быть в безопасности.
var deviceAgent = navigator.userAgent.toLowerCase();
var isTouchDevice = Modernizr.touch ||
(deviceAgent.match(/(iphone|ipod|ipad)/) ||
deviceAgent.match(/(android)/) ||
deviceAgent.match(/(iemobile)/) ||
deviceAgent.match(/iphone/i) ||
deviceAgent.match(/ipad/i) ||
deviceAgent.match(/ipod/i) ||
deviceAgent.match(/blackberry/i) ||
deviceAgent.match(/bada/i));
if (isTouchDevice) {
//Do something touchy
} else {
//Can't touch this
}
Если вы не используете Modernizr, вы можете просто заменить приведенную выше функцию Modernizr.touch
на ('ontouchstart' in document.documentElement)
Также обратите внимание, что тестирование пользовательского агента iemobile
даст вам более широкий диапазон обнаружил мобильные устройства Microsoft, чем Windows Phone
.
Если у вас есть исходный код OpenAL, абстрагированный в класс, я думаю, вы можете просто вызвать performSelector: afterDelay:
при запуске звука:
- (void) play
{
[delegate performSelector:@selector(soundHasFinishedPlaying)
afterDelay:self.length];
…
}
(Если вы остановите тем временем звук можно отменить вручную, обратный вызов можно отменить, см. Описание класса NSObject .) Или вы можете опросить AL_SOURCE_STATE
:
- (void) checkStatus
{
ALint state;
alGetSourcei(source, AL_SOURCE_STATE, &state);
if (state == AL_PLAYING)
return;
[timer invalidate];
[delegate soundHasFinishedPlaying];
}
Я не знаю, как получить OpenAL перезвонит вам. Для чего именно вам нужен обратный звонок? Некоторые вещи можно решить лучше без обратного вызова.
Это руководство OpenAL предлагает возможные варианты решение:
Функция 'stream' также сообщает нам, закончилось ли воспроизведение потока.
... и предоставляет образец исходного кода для иллюстрации использования.
Подождите, вы говорите о завершении одного сэмпла (например, 1/44100 секунды для звука 44,1 кГц)? Или вы говорите о знании того, что источник проиграл свой буфер и у него больше нет звука для воспроизведения?
Что касается последнего, у меня были хорошие результаты опроса источника для свойства AL_BUFFERS_PROCESSED, когда я передаю буферы в источник; в случае одного буфера может работать поиск ненулевого значения этого свойства.
Мне не очень повезло с обратными вызовами в OpenAL. В своих конечных автоматах я просто опрашиваю источник и откладываю переход до его завершения.
- (BOOL)playing {
ALint sourceState;
alGetSourcei(sourceID, AL_SOURCE_STATE, &sourceState);
return sourceState == AL_PLAYING;
}
// ... //
case QSTATE_DYING:
if (![audioSource playing])
[self transitionTo:QSTATE_DEAD];
Если это не то, что вам нужно, тогда лучше всего использовать таймер. Вам не нужно жестко кодировать какие-либо значения. Вы можете определить время воспроизведения при заполнении буферов.
Небольшое понимание «почему» вопроса может предложить некоторые дополнительные варианты.