Снова про звук, Linux, Qt и на этот раз — Phonon

Вообще, я ОС Линукс люблю и по возможности работаю именно в нем (но пропагандой пингвинов обычно не занимаюсь). И KDE люблю тоже. Но есть во всей этой кухне одна особенность, которая бесила меня всегда до мозга костей.

Вот, например, в ОС Windows можно было одновременно слушать музыку и, скажем, играть в игры — то есть, воспроизводить звук из разных источников параллельно — очень-очень давно. Десять лет точно. И дело не в том, что в Луниксе — нельзя. Можно, конечно. Но как-то так сложилось, что звуковая система в нем лицом повернута к самому Луниксу. А к пользователю — тем, что с оборотной стороны лица находится. Со всеми этими фронтэндами, бэкэндами, промежуточными демонами, альсами, оссами, пульсаудио, консольными плеерами и звуковыми библиотеками, разработчики пускаются во все все тяжкие, но годы проходят, а свести все это к приличному виду, чтоб хотя бы из коробки работало без конфликтов, — не получается.

Так, решил я проверить, как на новом нотбуке, куда я поставил Kubuntu 10.10 работает мой qTwister. А в твистере тоже были проблемы со звуком, так что пришлось для Луникс-версии использовать консольный play. И конечно оказалось, что в кубунте 10.10 play не только отсутствует, но и в стандартных репозиториях его нет.

Тут вспомнил, что в обсуждении предыдущих проблем со звуком неизвестный гость Виталий присоветовал мне использовать-таки Phonon. Ну и я решил воспользоваться советом, так как это, как ни крути, избавляет от необходимости где-то искать консольные проигрыватели. И даже позволяет проигрывать не только wav, но и mp3-файлы. Принялся, значит, переходить.

Вообще, написать звуковое сопровождение софта через Phonon — довольно просто. Вот инициализация:

Phonon::MediaObject * moSoundPlayer = new Phonon::MediaObject(NULL);
Phonon::AudioOutput * aOut = new Phonon::AudioOutput(Phonon::MusicCategory, NULL);
Phonon::createPath(moSoundPlayer, aOut);
Phonon::MediaSource * msButtonClick = new Phonon::MediaSource("sounds/btn.mp3");

а вот проигрыш:

moSoundPlayer->setCurrentSource(*msButtonClick);
moSoundPlayer->play();

Но, естественно, без проблем и тут никак.

Во-первых, оказывается Phonon неплохо дружит только с бэкендом gstreamer, а с бэкэндом xine дружит в меньшей степени. А разработчики разных дистрибутивов имеют весьма разное мнение на тот счет, какой бэкэнд надо использовать. В частности, xine имеет тенденцию не доигрывать звуковые файлы, прерываясь за 2 секунды до конца. Рытье по форумам навело на странное решение:

moSoundPlayer->setTransitionTime(1);

Эту строчку надо добавить к инициализации MediaObject. Почему это странное решение работает, никто не объяснил, но — с ним xine доигрывает все как надо, до конца.

Кроме того, неожиданно вскрылась проблема с Windows 7: в нем Phonon почему-то может создать только один экземпляр MediaObject, другие тоже создаются, но молчат. Пришлось, значит, отказаться от двух экземпляров. Плюс в семерке иногда наблюдается какая-то странная заторможенность при смене проигрываемых файлов, что странно само по себе.

В общем, без веселья и сношений в Луниксе звука не бывает. Но вроде все основные глюки я победил. Новую версию — скоро выложу.

Комментарии