
Проверка наличия звукового устройства приложением
Здравствуйте, джентльмены!
Сегодня, работая над проектом не за своей обычной машиной, а за подвернувшимся под руку Windows-сервером, я случайно узнал о любопытном но, к счастью, документированном нюансе класса Sound. Если в системе отсутствует звуковая карта, то после попытки воспроизведения звука метод play() возвращает null, что может стать причиной ошибки, генерируемой отлично работавшим на других машинах кодом.
Приведу пример:
Указанный выше код отлично работает на машине со звуковой картой, но поведёт себя так, как написано в комментариях, на системе без неё.
Чтобы избежать подобной ситуации, я предлагаю добавлять при запуске приложения небольшую проверку:
Я согласен, что сейчас практически не встретишь устройство без хоть какого-нибудь звука, однако, думаю, включить этот нюанс в чек-лист не помешает.
Спасибо за внимание.
Сегодня, работая над проектом не за своей обычной машиной, а за подвернувшимся под руку Windows-сервером, я случайно узнал о любопытном но, к счастью, документированном нюансе класса Sound. Если в системе отсутствует звуковая карта, то после попытки воспроизведения звука метод play() возвращает null, что может стать причиной ошибки, генерируемой отлично работавшим на других машинах кодом.
Приведу пример:
var menuMusic: Sound = new MenuMusic; // так называется наш звук
var menuMusicSoundChannel: SoundChannel = new SoundChannel(); // здесь пока всё в порядке
menuMusicSoundChannel = menuMusic.play(); // строка выполняется, но после её выполнения menuMusicSoundChannel будет равно null
menuMusicSoundChannel.stop(); // и вот здесь флэшплеер выдаст ошибку об обращении к методу объекта, являющегося null'ом.
Указанный выше код отлично работает на машине со звуковой картой, но поведёт себя так, как написано в комментариях, на системе без неё.
Чтобы избежать подобной ситуации, я предлагаю добавлять при запуске приложения небольшую проверку:
var menuMusic: Sound = new MenuMusic; // какой-нибудь тестовый звук
var menuMusicSoundChannel: SoundChannel = new SoundChannel();
menuMusicSoundChannel = menuMusic.play(); // делаем тестовый запуск звука
if (menuMusicSoundChannel)
{
trace("Звук есть!");
menuMusicSoundChannel.stop(); // всё, проверку мы прошли, тестовый звук можно тормозить
}
else
{
trace("Грусьть и пичяль, звука нет"); // звука нет, потому больше аудио воспроизводить не пытаемся
}
Я согласен, что сейчас практически не встретишь устройство без хоть какого-нибудь звука, однако, думаю, включить этот нюанс в чек-лист не помешает.
Спасибо за внимание.
- +17
- SeeD
Комментарии (18)
На днях прочел постмортем «Мясного пацана», тоже удивил момент, когда программист каждый новый рабочий день, начинал с исправления ошибок. Даже боюсь представить, что у меня в коде творится))
Возможно таких документов с «частыми ошибками» много, было бы здорово раздобыть все
Огласите пожалуйста весь чек-лист.
2. Проверить звук
3. ????????
4. PROFIT
Как пример — здесь на блогах я давал пример моего класса SoundManager. Там все написано безопасно. Хотя я умудрился ровно в одном месте заложиться на то, что null не вернется. И получил редкую багу. Повторить я ее не мог. Багрепорты Конга малоосмысленные были. Случайно на первой неделе дистрибуции я дебажил ради других целей и словил багу. Оказалось, что я заложился на то, что если я при паузе все звуки глушу, то при unpause, восстанавливая эти звуки я никак не могу получить null, ибо если было меньше 32 канала до паузы — то при анпаузе никак не может быть больше 32-ух. Однако, по непонятно причине происходило падение.
Трайкетчи надо ставить там, где в доках прописано что эксепшн выкинут определенного типа. Например сетевые штуки обязательно. Наугад заворачивать все в трайкетчи можно только если не можешь поймать, а у тебя игра в релизе и надо срочно. Ты же не будешь всю игру заворачивать на всякий в трайкетч? Я же рассказываю что null вернуло в валидной по докам ситуации.
Логику что кончились каналы надо решать сперва самостоятельно, распределив все звуки по группам и самому держать их в пределах. На крайняк все равно проверять на null и валидно это отрабатывать. Трай кетчами это тоже можно сделать но это будет медленно (и неверно).
У меня работает как-то так.
public function play(name: String): void
{
try
{
// тут по любому где нибудь будет getDefinitionByName,
// поэтому исключения ловить нужно, а заодно ловим редкие баги с
// нулевым SoundChannel.
}
catch (e: Error)
{
}
}
И все равно выглядит криво. Ну то-есть это надо еще подумать как сделать так, чтобы после слёта через эксепш все продолжало работать нормально! Вот если оборвать саунд менеджер где-то посередине из-за того что null вывалился, то нарушатся стройность данных в структурах. Я не уверен что это выльется просто в один не прозвучавший звук. Если логика в саунд менеджере чуть более сложная чем просто «всем звучать!», то лучше продумать все и ловить самому все эти null-ы и валидно в структуре отражать. Глянь мой саунд менеджер, я здесь выкладывал. Там без логики не обойтись, иначе какофония полная будет. Звук колонн подорогам надо слеплять вместе итд. Если что-то посередине оборвать — больше шансов что начнет валиться из-за неконсистентности. Лучше валидно отлавливать все возможные null.