2/15/2009

KDE4 и Alsa

Совсем недавно вышел релиз десктоп окружения KDE за версией 4.2.

Я вот тоже решил не отставать от продвинутых линуксоидов и установил себе этот самый KDE4. Что тут можно сказать, был сделан большой прогресс в разработке и улучшения интерфейса пользователя. Я перечислять не буду, т.к. их можно посмотреть на официальном сайте. Что еще порадовало, так это то, что увеличилась производительность, по сравнению с третьей веткой. Упростился процесс конфигурации. В общем и целом впечатление весьма приятное.

Теперь вот буду использовать в качестве десктоп окружения по-умолчанию.

Однако, как оказалось чуть позже, возникли некоторые проблемы со звуком:
При запуске какого-нибудь КДЕ-шного приложения, ни одна другая программа не могла воспроизвести звук. При том что до этого все работало замечательно. KDE для вывода звука использует backend Phonon, который в свою очередь использует xine, который в свою очередь использует звуковую подсистему: alsa, oss и т.д.

Для того, чтобы настроить звук, в KDE в system_settings нужно выбрать устройство, через которое будет выводится звук. Однако там присутствовала всего одна звуковая карточка. Оказалось, что для получения списка устройств phonon использует какую-то там функцию из библиотеки alsa, и не отображает устройства без описания. Вылечивается это просто. Добавляем в соответствующую секцию файла /etc/asound.conf строк:
hint {
show on
description "Name to display for the device"
}
К примеру для микширования через dmix :

pcm.dsp0 {
type plug
slave.pcm "dmixer"
 hint {
show on
description "My dmix sound card"
}
}

Теперь в настройках KDE выбираем вместо карты по умолчанию, "My dmix sound card",
и у вас есть многопоточный звук.

2/07/2009

Настройка Microsoft-VX 3000 в Linux

Раздобыл я себе веб камеру Microsoft VX-3000. Камера сделана на чипе sonix с jpeg кодированием.
После недолгого гугления, обнаружил сайтик, где можно найти кучу драйверов для разных веб камер. Проект называется gspcav1. Моя веб камера тоже в списке поддерживаемых.
Чтобы скомпилировать проект нужно, нужно скачать архив gspca, распаковать и запустить скрипт gspca_build.
В ядре должна быть включена поддержка V4l, и естественно у вас должны быть сорцы вашего работающего ядра.
После компиляции загружаем модуль ядра, modprobe gspca, и вуаля, появляется устройство /dev/video0 - которое собственно и будет вебкамерой.
Все эти действия легко и непринужденно проделываются на ядрах, версии меньше 2.6.27.

В версиях выше 2.6.27 набор драйверов интегрировали в ядро, и перевели на интерфейс v4l2. И после этого вебкамера перестала работать.
На моей системе (Gentoo Linux 2.6.28.1 x86_64) не помогало ничего. Ни одно приложение не хотело отображать картинку с камеры. Вместо этого отображались только помехи.
Сегодня мне все это надоело, и решил я значит скомпилировать старый драйвер gspcav1, от сторонних разработчиков. И у меня это получилось, с помощью лома, и какой то матери.
И так.
В ядре отключаем встроенный драйвер gspca, включаем V4l v1 compatible layer, или как-то так. Пересобираем ядро. Дальше я наваял патчик для gspca, чтобы его можно было скомпилировать с новым ядром. Скачать его можно здесь.
Заходим в каталог gspca, делаем patch -Np0 < ../gspca.patch, затем компилируем и инсталлируем. И О чудо, моя веб камера снова работает. =)

2/02/2009

Перечислимые типы и строгая типизация.

Что такое перечислимый тип?
Перечислимый тип определяется как набор идентификаторов, с точки зрения языка играющих ту же роль, что и обычные именованные константы, но связанные с этим типом.
В языке Си, изначально перечислимый тип отсутствовал, но позднее был добавлен в стандарт ANSI.

Вот пример объявления перечислимого типа в языке Си:

typedef enum my_enum {
A, B, C
} my_enum_t;

Он состоит из трех элементов A,B,C.
Каждый элемент перечисления представляется с помощью типа int.
Фактически эта запись равносильна следующей (на большинстве платформ):

typedef int my_enum_t;
const my_enum_t A = 0;
const my_enum_t B = 1;
const my_enum_t C = 2;

Согласно стандарту ANSI C элементы перечисления по умолчанию нумеруются с 0.
Если какому-либо из элементов присвоить какое нибудь значение, то, все последующие элементы будут увеличиваться на 1, относительно этого значения.

Например:

typedef enum my_enum {
A = 500, B, C
} my_enum_t;

В таком перечислении значение A будет 500, B - 501, C - 502 и т.д.

К чему все это, спросите вы?
Пытаясь портировать одну небольшую и очень известную библиотеку,
на embeddedLinux для Архитектуры ARM9, я наткнулся на следующую проблему:
один и тот же код, скомпилированный компилятором одной и той же версии (gcc-4.1.1), с одними и теми же флагами отказывался работать.

Вот пример того кода, который не работал на ARM9:

1 #include <stdio.h>
2
3 typedef enum enum_A {
4 A1 = 0, A2, A3, A4
5 } enum_A_t;
6
7 typedef enum enum_B {
8 B1 = 1000000, B2, B3, B4, B5
9 } enum_B_t;
10
11 int main (int argc, char *argv[])
12 {
13 enum_A_t A;
14 enum_B_t B = B1;
15
16 A = B3;
17
18 printf ("A=%d, B=%d\n", sizeof (enum_A_t), sizeof (enum_B_t));
19 if (A > B)
20 printf ("Hello\n");
21 }

Ошибка состоит в том, что на x86 на консоль выводится слово HELLO, а на arm9 нет.
Как оказалось такую ситуацию можно повторить и на x86 архитектуре.

Где же ошибка:
На мой взгляд строки 16 и 20 - это просто надругательство над всем смыслом перечислимого типа. По моему мнению такое делать нельзя. Но компилятор gcc это прекрасно проглатывает, абсолютно никак не оповещя пользователя о возможных последствиях.

Ведь enum_A_t и enum_B_t это два абсолютно разных типа, с абсолютно разным диапазоном значений.
Такой код работает только потому, что элементы перечисления по сути являются элементами типа int.

Но что будет если gcc начнет оптимизировать?
Как оказалось, для экономии памяти на embedded платформе, в компиляторе была по-умолчанию включена опция -fshort-enums. При включении этой опции компилятор начинает оптимизировать перечисления, для того чтобы они занимали меньше памяти.
Как он это делает?

Просто берет и начинает использовать для хранения элементов перечисления не огромный 4-х байтовый целочисленный тип,а скажем однобайтовый char, или двухбайтовый short. Вот и в нашем случае, компилятор соптимизировал код так, что для хранения элементов типа enum_A_t использовался char, а для хранения элементов типа enum_B_t тип int.
Естественно сравнение в строке 19 всегда будет ложным.

Вывод.
Будьте внимательны при объявлении и использовании перечислений.
Такие ошибки трудноуловимы, и можно просидеть очень много времени в отладчике, пытаясь понять что же все таки не так.