Неясности с Phonon
Содержание:
1. Введение ;
2. Трудности с Phonon;
3. Неясности с Phonon (Вы читаете данный раздел).
От трудностей сборки перейдем к неясным местам в использовании Phonon. Phonon поддерживает те мультимедийные форматы, которые поддерживаются бэкендом. В случае с Xine или Gstreamer это зависит от установленных плагинов Xine и Gstreamer, а для Direct Show - от установленных кодеков-фильтров Direct Show. Например, для того чтобы ваша программа под Windows «понимала» Ogg Vorbis и FLAC, надо поставить в систему кодек с http://xiph.org/dshow. Как программно узнать, поддерживается ли запущенным у пользователя бэкендом некий файл? Вопрос простой, а ответ на него - не то чтобы сложный, но хлопотный.
Статичная функция Phonon::BackendCapabilities::available MimeTypes() возвращает QStringList, наполненный названиями MIME-типов, которые поддерживаются бэкендом. А уж как этим списком распорядиться - дело ваше. Опишу один из способов. Задача стоит так: узнать, какому MIME-типу соответствует файл, и посмотреть, входит ли этот MIME-тип в список поддерживаемых типов. Чтобы узнать первое, надо, во-первых, получить расширение из пути к файлу. Предлагаю для этого следующую, предусматривающую некоторые досадные неожиданности, функцию:
Если имя файла - пустое или же не содержит расширения, возвращается пустая строка, иначе - приведенное к нижнему регистру расширение, без точки.
Теперь понадобится таблица соответствий расширений файлов и MIME-типов. Есть относительно стандартная таблица от FreeDesktop - пакет с ней обычно называется shared-mime-info и находится в /usr/share/mime (смотрите файлы globs*, да и вообще полезно посмотреть содержимое этих каталогов). Эта таблица используется в GNOME и KDE. Дополнения к ней сохраняются в $HOME/.local/share/mime. Таблица большая, но отнюдь не полная. К тому же, в Windows её нет. Если вы пишете многоплатформенную программу, придется искать универсальное решение. А оно - на поверхности: надо создать собственную базу MIME-соответствий и включить её в свою программу как ресурс. Обычный ini-подобный файл, который загружаете в hash-таблицу, где ключами служат расширения файлов, а значениями - MIME-типы.
Это можно сделать с помощью следующего кода. Сначала напишем вспомогательную функцию, загружающую файл в экземпляр QString:
Теперь - саму функцию чтения в хэш-таблицу:
И наконец - пример использования. Объявим хэш-таблицу mime_types и прочитаем в нее таблицу из ресурса:

В ресурсе mime.txt у нас строки вида:
Чтобы получить «известные» в этой таблице MIME-типы, надо обратиться к функции QHash::values() без параметра. Чтобы получить MIME-типы, соответствующие некоему расширению файла, надо вызывать её же, но с параметром:
//Получаем расширение файла QString ext = file _ get _ ext (fname); if (ext.isEmpty()) return;
//Получаем список MIME-типов для расширения ext QList mts = mime _ types.values (ext); if (mime _ types.count() == 0) return;
Полученный список потребуется просмотреть в цикле и проверить, входит ли какой-либо элемент списка в список типов, поддерживаемых бэкендом. Если да, то файл поддерживается на воспроизведение.
Вот еще одна тонкость, которая плохо документирована. Речь идет о выборе выходного звукового устройства. Иногда не хочется использовать общесистемные установки (они настраиваются в центре управления KDE, в разделе настроек Phonon). Phonon умеет выдавать список доступных выходных устройств:
С ним мало что можно сделать полезного - разве что получить названия:
чтобы потом наполнить ими выпадающий список и добавить к нему выбор устройства:
Вот и сам слот:
Само же выходное устройство Phonon, с учетом возможности выбора устройства, создаем примерно так:
audioOutput = new Phonon::AudioOutput (this);
Подведу итог. От списка выходных устройств нужны две вещи: их имена и индексы. Имена отображаются пользователю, а индексы требуются, чтобы задавать нужное устройство вывода. Когда пользователь выбирает название устройства, записываем его индекс в настройки и затем задаем это устройство через функцию Phonon::AudioOutput::setOutputDevice(). То же проделывается при загрузке программы сразу после создания экземпляра класса Phonon::AudioOutput.
1. Введение ;
2. Трудности с Phonon;
3.
От трудностей сборки перейдем к неясным местам в использовании Phonon. Phonon поддерживает те мультимедийные форматы, которые поддерживаются бэкендом. В случае с Xine или Gstreamer это зависит от установленных плагинов Xine и Gstreamer, а для Direct Show - от установленных кодеков-фильтров Direct Show. Например, для того чтобы ваша программа под Windows «понимала» Ogg Vorbis и FLAC, надо поставить в систему кодек с http://xiph.org/dshow. Как программно узнать, поддерживается ли запущенным у пользователя бэкендом некий файл? Вопрос простой, а ответ на него - не то чтобы сложный, но хлопотный.
Статичная функция Phonon::BackendCapabilities::available MimeTypes() возвращает QStringList, наполненный названиями MIME-типов, которые поддерживаются бэкендом. А уж как этим списком распорядиться - дело ваше. Опишу один из способов. Задача стоит так: узнать, какому MIME-типу соответствует файл, и посмотреть, входит ли этот MIME-тип в список поддерживаемых типов. Чтобы узнать первое, надо, во-первых, получить расширение из пути к файлу. Предлагаю для этого следующую, предусматривающую некоторые досадные неожиданности, функцию:
QString file _ get _ ext (const QString Sfile _ name) {
if (file _ name.isNull() || file _ name.isEmpty())
return QString();
int i = file _ name.lastIndexOf (".");
if (i == -1)
return QString();
return file _ name.mid (i + 1).toLower();
}Если имя файла - пустое или же не содержит расширения, возвращается пустая строка, иначе - приведенное к нижнему регистру расширение, без точки.
Теперь понадобится таблица соответствий расширений файлов и MIME-типов. Есть относительно стандартная таблица от FreeDesktop - пакет с ней обычно называется shared-mime-info и находится в /usr/share/mime (смотрите файлы globs*, да и вообще полезно посмотреть содержимое этих каталогов). Эта таблица используется в GNOME и KDE. Дополнения к ней сохраняются в $HOME/.local/share/mime. Таблица большая, но отнюдь не полная. К тому же, в Windows её нет. Если вы пишете многоплатформенную программу, придется искать универсальное решение. А оно - на поверхности: надо создать собственную базу MIME-соответствий и включить её в свою программу как ресурс. Обычный ini-подобный файл, который загружаете в hash-таблицу, где ключами служат расширения файлов, а значениями - MIME-типы.
Это можно сделать с помощью следующего кода. Сначала напишем вспомогательную функцию, загружающую файл в экземпляр QString:
QString qstring_load (const QString SfileName,
const QString Scharset)
{
QFile file (fileName);
if (! file.open (QFile: :ReadOnly | QFile::Text)) return QString();
QTextStream in(Sfile); in.setCodec (charset.toAscii());
return in.readAll();
}Теперь - саму функцию чтения в хэш-таблицу:
QHash <QString, QString> hash _ load _ keyval (const QString Sfname) {
QHash<QString, QString> result;
if (! file _ exists (fname)) return result;
QStringList l = qstring_load (fname, "UTF-8").split ("n");
foreach (QString s, l) {
QStringList sl = s.split ("="); if (sl.size() > 1)
result.insertMulti (sl[0], sl[1]);
}
return result;
}И наконец - пример использования. Объявим хэш-таблицу mime_types и прочитаем в нее таблицу из ресурса:
QHash <QString, QString> mime _types = hash _load _keyval
(":/res/mime.txt");
В ресурсе mime.txt у нас строки вида:
aiff=audio/aiff
mod=audio/mod
aif=audio/x-aiff
aiff=audio/x-aiff
m4a=audio/x-m4a
wav=audio/x-basic
[и так далее]Чтобы получить «известные» в этой таблице MIME-типы, надо обратиться к функции QHash::values() без параметра. Чтобы получить MIME-типы, соответствующие некоему расширению файла, надо вызывать её же, но с параметром:
//Получаем расширение файла QString ext = file _ get _ ext (fname); if (ext.isEmpty()) return;
//Получаем список MIME-типов для расширения ext QList
Полученный список потребуется просмотреть в цикле и проверить, входит ли какой-либо элемент списка в список типов, поддерживаемых бэкендом. Если да, то файл поддерживается на воспроизведение.
Вот еще одна тонкость, которая плохо документирована. Речь идет о выборе выходного звукового устройства. Иногда не хочется использовать общесистемные установки (они настраиваются в центре управления KDE, в разделе настроек Phonon). Phonon умеет выдавать список доступных выходных устройств:
QList <Phonon::AudioOutputDevice> audioOutputDevices =
Phonon::BackendCapabilities::availableAudioOutputDevices();С ним мало что можно сделать полезного - разве что получить названия:
QStringList sl;
foreach (Phonon::AudioOutputDevice ad, audioOutputDevices) sl << ad.name();чтобы потом наполнить ими выпадающий список и добавить к нему выбор устройства:
//Создаем комбо-бокс
QComboBox *cb_ outdevs = new QComboBox (this);
//Наполняем его элементами списка cb _ outdevs->addItems (sl);
//Читаем из QSettings сохраненный в настройках индекс -//номер устройства из списка, и делаем его текущим в комбо-боксе cb _ outdevs->setCurrentIndex (settings->value
("output _dev", 0).toInt());
//Связываем комбо-бокс со слотом переключения:
connect (cb _ outdevs, SIGNAL(currentIndexChanged (int )),
this, SLOT(cb _ outdevs _ currentIndexChanged (int )));Вот и сам слот:
void MainWindow::cb _outdevs _currentIndexChanged (int index) {
//Пишем индекс устройства в настройки:
settings->setValue ("output _ dev", index); //Делаем устройство текущим, используя индекс
audioOutput->setOutputDevice (Phonon::BackendCapabilities::
availableAudioOutputDevices()[index]);
}Само же выходное устройство Phonon, с учетом возможности выбора устройства, создаем примерно так:
audioOutput = new Phonon::AudioOutput (this);
int idx = settings->value ("output _ dev", 0).toInt(); audioOutput->setOutputDevice (Phonon::BackendCapabilities::
availableAudioOutputDevices()[idx]);Подведу итог. От списка выходных устройств нужны две вещи: их имена и индексы. Имена отображаются пользователю, а индексы требуются, чтобы задавать нужное устройство вывода. Когда пользователь выбирает название устройства, записываем его индекс в настройки и затем задаем это устройство через функцию Phonon::AudioOutput::setOutputDevice(). То же проделывается при загрузке программы сразу после создания экземпляра класса Phonon::AudioOutput.