Опишу процесс установки старой, но всё ещё весьма доброй темы курсоров от Red Hat 9 на современный дистрибутив (в данном случае Ubuntu 7.10).

1) Создаем папку для курсоров:
$sudo mkdir /usr/share/icons/RH/

2) Из rpm-пакета redhat-artwork (в моем случае версии 0.73-1) берём каталог /usr/share/icons/Bluecurve/cursors и кидаем его в только что созданный "RH" со всем его содержимым.
Найти пакет можно на rpm.pbone.net.

3) В /usr/share/icons/RH/ создаем файл cursor.theme со следующем содержанием:
[Icon Theme]
Inherits=RH


4) В Ubuntu установить курсор по умолчанию можно с помощью системных альтернатив. Сделать это просто с помощью графической утилиты galternatives. Нужно добавить новую альтернативу "/usr/share/icons/RH/cursor.theme" для "x-cursor-theme" и выбрать её как основную.

В других системах возможно придётся сменить символическую ссылку "default" в /usr/share/icons/ на каталог с курсорами "RH", либо создать в каталоге "default" символические ссылки на "RH/cursors" и "cursor.theme".

В AltLinux например нужно в файле /etc/X11/Xresources прописать строку "Xcursor.theme: RH".

5) Убедиться в том, что теперь по умолчанию стоит наш новый курсор можно с помощью программы gcursor:

6) Всё, осталось только перегрузить X-сервер.

Под Ubuntu 7.04 наблюдались некоторые проблемы со сканированием с помощью epson 1260 photo, а именно сканер крайне долго "разогревался" перед работой, а результат сканирования был далек от совершенства (благодаря многочисленным белым полосам и засветам):


Проблема решилась заменой стандартного драйвера от независимых разработчиков "plustek" (см. xsane, меню "файл" -> "информация", "информация о драйвере") на эпсоновский, для чего нужно было:

1) Скачать нужные драйвера с сайта.
2) Сконвертить алиеном пакеты из rpm в deb (если у вас неподдерживаемый deb-дистрибутив, т.к. стандартные драйвера поставляются в rpm-пакетах) и установить обычным способом.
3) В файле /etc/sane.d/dll.conf закомментировать строку plustek и добавить строку epkowa.
4) Теперь можно сканировать, убедившись, что в xsane (см. меню "файл" -> "информация", "информация о драйвере") установлен драйвер "epkowa".

Результат на лицо, сравните до (см. предыдущий скрин) и после:

В связи со скудностью документации по библиотеке GtkExtra, мною был составлен довольно подробно комментированный простенький пример, по которому можно понять принципы построения графиков с помощью GtkExtra, его и выкладываю в блоге.
Пример во многом аналогичен примеру testiterator из стандартной поставки GtkExtra и выглядит так:

Собственно текст примера:
// Пример дынных для отрисовки -->
    // Количество точек = 12
    int nt = 12;

    // Структура для пар координат "время - значение"
    struct pair
    {
        double x;   // По X - Время
        double y;   // По Y - Значение
    };

    // Область памяти с парами координат "время - значение"
    struct pair mem[12] =
    {
        {   0,      0.2},   // 1
        {   1.5,    0},
        {   2.4,    1},
        {   3.7,    0},
        {   4.44,   0.55},  // 5
        {   6.3,    0.73},
        {   7,      0.21},
        {   8.9,    0.1},
        {   11,     0.2},
        {   14.6,   0.2},   // 10
        {   17,     0.2},
        {   20,     1}      // 12
    };
// Пример дынных для отрисовки <--


// Стандартные для GTK вещи -->
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <gtk/gtk.h>
    #include <gdk/gdk.h>

    void quit ()
    {
      gtk_main_quit();
    }
// Стандартные для GTK вещи <--


#include <gtkplotcanvas.h> 
#include <gtkplotcanvastext.h> 
#include <gtkplotcanvasplot.h> 
#include <gtkplotdata.h> 


// Массив текста для подписей к точкам
static gchar point_label[100];

// Функция, запускаемая для получения точек
// (функция запускается по разу для каждой точки)
static void graph_iter
    (
    GtkPlot *plot,
    GtkPlotData *data,
    gint iter,
    gdouble *x,
    gdouble *y,
    gdouble *z,
    gdouble *a,
    gdouble *dx,
    gdouble *dy,
    gdouble *dz,
    gdouble *da,
    gchar **label,
    gboolean *error
    )
{
    // Достаем из объекта data указатель на область памяти с координатами точек
    double *memory = (double *) g_object_get_data(G_OBJECT(data), "Dots_memory_pointer");

    // Распаковываем координаты из памяти
    *x = *(
                memory          // Начало области памяти
                + 0             // X - первый в парах, так что без смещения
                + 2 * iter);    // Смещение к нужной паре
    *y = *(
                memory          // Начало области памяти
                + 1             // Y - второй в парах, смещение к нему
                + 2 * iter);    // Смещение к нужной паре

    // Подписи к точкам
    sprintf(point_label, "Точка #%d\n", iter + 1);
    *label = point_label;

    *error = FALSE;
}


void graph_open
    (
        GtkWidget *container,   // Контейнер, в котором рисовать график
        int dots_number,        // Количесвто точек
        void *memory            // Область памяти, содержащее координаты этих точек
    )
{
    // Создаем холст canvas 900x700 пикселей в окне -->
        GtkWidget *canvas;      // Виджет
        canvas = gtk_plot_canvas_new(   // Создаем
            900, 700,                   // Размер
            1.);                        // В натуральную величину (например для уменьшения в два раза следует поставить 0.5)
        gtk_container_add(GTK_CONTAINER(container), canvas);    // Помещаем в контейнер
    // Создаем холст canvas 900x700 пикселей в окне <--


    // Создадим подпись вверху холста -->
        GtkWidget *top_label;
        
        top_label = (GtkWidget *) gtk_plot_canvas_text_new(
                "Times-BoldItalic",             // Шрифт (можно выставить NULL для шрифта по умолчанию)
                                                    // Доступные шрифты можно посмотреть в файле gtkplotps.c
                20,                             // Высота шрифта
                0,                              // Угол наклона надписи
                NULL,                           // Цвет шрифта
                NULL,                           // Цвет фона надписи
                TRUE,                           // Прозрачность
                GTK_JUSTIFY_CENTER,             // Выравнивание
                "My first plot (первый плот).");// Собственно текст

        gtk_plot_canvas_put_child(          // Помещаем на холст
                GTK_PLOT_CANVAS(canvas),            // Холст
                (GtkPlotCanvasChild *) top_label,   // Что помещать (child)
                            // Координаты:
                .50,                                // x1 - отступ по горизонтали, в процентах от холста (зд. 50%, т.е. посередине)
                .05,                                // y1 - отступ по вертикалии, в процентах от холста (зд. 5%, т.е. почти наверху)
                0.,                                 // x2
                0.);                                // y2
    // Создадим подпись вверху холста <--


    // Устанавливаем цвет холста -->
        GdkColor color;
        gdk_color_parse("light blue", &color);
        gdk_color_alloc(gtk_widget_get_colormap(canvas), &color);
        gtk_plot_canvas_set_background(GTK_PLOT_CANVAS(canvas), &color);
    // Устанавливаем цвет холста <--


    // Создаем график plot (точнее основу графика - оси, подписи и т.п., без значений) -->
        GtkWidget *plot;    

        plot = gtk_plot_new_with_size(
            NULL,       // GdkDrawable виджет
            .65, .45);  // Высота и ширина виджета графика

        // Цвет графика -->
            gdk_color_parse("light yellow", &color);
            gdk_color_alloc(gtk_widget_get_colormap(plot), &color);
            gtk_plot_set_background(GTK_PLOT(plot), &color);
        // Цвет графика <--
        
        gtk_plot_set_range(     // По умолчанию график 1x1 деление,...
            GTK_PLOT(plot),     // ...выставим другие значения:
            0., 20.,            // По X - 20 делений
            0., 1.);            // По Y - 1 деление

        // Выставим с каким шагом проставлять метки координат на графике
        gtk_plot_set_ticks(GTK_PLOT(plot),
            GTK_PLOT_AXIS_X,    // По оси X
            2,                  // Цифры проставлять с шагом 2
            1);                 // Ставить засечки с шагом 1
        gtk_plot_set_ticks(GTK_PLOT(plot), GTK_PLOT_AXIS_Y, .1, 1);

        gtk_plot_grids_set_visible(GTK_PLOT(plot), // Координатная сетка
            TRUE,       // Вертикальная сетка сплошной линией относительно проставленных на оси цифр
            TRUE,       // Вертикальная сетка штриховой линией относительно проставленных на оси меток
            TRUE,       // Горизонтальная сетка сплошной линией относительно проставленных на оси цифр
            TRUE);      // Горизонтальная сетка штриховой линией относительно проставленных на оси меток

        gtk_widget_show(plot);  // Нужно вызвать функцию отрисовки графика заранее,
                                // иначе потом не удасться добавить к графику данные
    // Создаем график plot (точнее основу графика - оси, подписи и т.п., без значений) <--


    // Подписи к графику -->
        // Верхнюю и правую просто скроем:
        gtk_plot_axis_hide_title(gtk_plot_get_axis(GTK_PLOT(plot), GTK_PLOT_AXIS_TOP));
        gtk_plot_axis_hide_title(gtk_plot_get_axis(GTK_PLOT(plot), GTK_PLOT_AXIS_RIGHT));

        // Остальные пропишем:
        gtk_plot_axis_set_title(gtk_plot_get_axis(GTK_PLOT(plot), GTK_PLOT_AXIS_LEFT), "Значение");
        gtk_plot_axis_set_title(gtk_plot_get_axis(GTK_PLOT(plot), GTK_PLOT_AXIS_BOTTOM), "Время");
    // Подписи к графику <--


    // Создаем child с только что созданным графиком plot и рисуем его на холсте (put_child) -->
        GtkPlotCanvasChild *child;

        child = (GtkPlotCanvasChild *) gtk_plot_canvas_plot_new(GTK_PLOT(plot)); // Создание структуры child

        gtk_plot_canvas_put_child(          // Помещаем на холст
                GTK_PLOT_CANVAS(canvas),    // Холст
                child,                      // Что помещать (child)
                            // Координаты:
                .15,                            // x1 - отступ по горизонтали, в процентах от холста
                .25,                            // y1 - отступ по вертикалии, в процентах от холста
                .80,                            // x2 - ширина графика
                .85);                           // y2 - высота графика
    // Создаем child с только что созданным графиком plot и рисуем его на холсте (put_child) <--


    // Строим на графике значения (пока просто линии между точками) -->
        GtkPlotData *dataset;

        dataset = (GtkPlotData *) gtk_plot_data_new_iterator(   // Заполняем структуру данных (значения и параметры)
            (GtkPlotIterator)graph_iter,                                    // Функция, запускаемая для получения (распаковки) точек
            dots_number,                                                    // Количество точек
            GTK_PLOT_DATA_X|GTK_PLOT_DATA_Y|GTK_PLOT_DATA_LABELS);          // Маска параметров
        
        // Здесь мы сохраним указатель на адрес области памяти с данными о точках...
        // ...в объекте dataset (см. GObject Reference Manual)
        g_object_set_data(G_OBJECT(dataset), "Dots_memory_pointer", memory);

        gtk_plot_data_show_labels(dataset, TRUE);   // Отображать подписи к точкам
        gdk_color_parse("dark green", &color);
        gdk_color_alloc(gtk_widget_get_colormap(plot), &color);
        gtk_plot_data_labels_set_attributes(dataset,
                "Helvetica-Bold",                   // Шрифт (можно выставить NULL для шрифта по умолчанию)
                14,                                 // Высота шрифта
                90,                                 // Угол наклона подписи
                &color,                             // Цвет шрифта
                NULL);                              // Цвет фона подписи

        gtk_plot_add_data(GTK_PLOT(plot), dataset); // Добавляем значения на график...
        gtk_widget_show(GTK_WIDGET(dataset));       // ...и отображаем их
    // Строим на графике значения (пока просто линии между точками) <--


    // Легенда графика
    gtk_plot_data_set_legend(dataset, "Легенда");


    // Настроим вид точек <--
        gdk_color_parse("green", &color);   // Цвет - зеленый
        gdk_color_alloc(gdk_colormap_get_system(), &color);

        gtk_plot_data_set_symbol(dataset,
             GTK_PLOT_SYMBOL_DIAMOND,       // Символ - ромб
             GTK_PLOT_SYMBOL_OPAQUE,        // Стиль - непрозрачный
             20, 2,                         // Размеры
             &color, &color                 // Цвета
             );
    // Настроим вид точек -->


    // Настроим вид линий -->
        gdk_color_parse("red", &color);     // Цвет - красный
        gdk_color_alloc(gdk_colormap_get_system(), &color);
        gtk_plot_data_set_line_attributes(dataset,
            GTK_PLOT_LINE_SOLID,            // GtkPlotLineStyle
            0,                              // GdkCapStyle (как рисовать концы линий, см. GDK Reference Manual)
            0,                              // GdkJoinStyle (как объединяются сегменты линий, см. GDK Reference Manual)
            3,                              // Ширина линии
            &color);                        // Цвет
    // Настроим вид линий <--
}


int main(int argc, char *argv[])
{
    // Стандартные для GTK вещи -->
        // Здесь создаем окно и сопутствующие виджеты
        GtkWidget *window;
        gtk_init(&argc,&argv);
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_signal_connect (GTK_OBJECT (window), "destroy",
            GTK_SIGNAL_FUNC(quit), NULL);
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

        GtkWidget *main_vbox;
        main_vbox = gtk_vbox_new(FALSE, 5);
        gtk_container_add(GTK_CONTAINER(window), main_vbox);
        gtk_widget_show(main_vbox);
        
        // Frame, в который будем класть виджет с графиком
        GtkWidget *main_frame;
        main_frame = gtk_frame_new("График");
        gtk_box_pack_start(GTK_BOX(main_vbox), main_frame, TRUE, TRUE, 0);

        GtkWidget *main_hbox;
        main_hbox = gtk_hbox_new(FALSE, 0);
        gtk_box_pack_end(GTK_BOX(main_vbox), main_hbox, FALSE, FALSE, 0);

        GtkWidget *close_button;
        close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); 
        g_signal_connect(GTK_OBJECT(close_button), "clicked", G_CALLBACK(quit), NULL);
        gtk_box_pack_end(GTK_BOX(main_hbox), close_button, FALSE, FALSE, 0);
    // Стандартные для GTK вещи <--

            // Здесь предположим у нас есть область памяти со значениями координат mem
            // и количество точек nt.
            // Эти данные и передаем в нашу функцию.
            graph_open(main_frame, nt, mem);

    // Стандартные для GTK вещи -->
        gtk_widget_show_all(GTK_WIDGET(window));
        gtk_main();
        return 0;
    // Стандартные для GTK вещи <--
}


//
// Gtk Extra Example
// http://damnsmallblog.blogspot.com
//

В примере довольно универсальной функции graph_open передаются три параметра:
1) Контейнер GTK, в котором и будет отрисовн график.
2) Количество точек для отрисовки.
3) Адрес области памяти, в которой лежат значения (double) координат точек.

Вспомогательная функция graph_iter служит для распаковки точек.
main - простенькое gtk-приложение, содержащее виджет main_frame в качестве контейнера для графика.

Таблица сравнительных характеристик бесплатных (по крайне мере для некоммерческого использования) библиотек для построения графиков:











БиблиотекаЛицензияПортабильностьЗамечания


1DISLINБесплатна только для некоммерческого использования. Лицензия далеко не GPL, исходный код дают только при покупке лицензии:
DISLIN is free for non-commercial use. Licenses for commercial use, or for just supporting DISLIN, are available from the site http://www.dislin.de.
....
The source code is available on the CDROM that is distributed with a DISLIN license (since version 9.0).
Много железа, компиляторов и ОС поддерживается:
DISLIN distributions are available for the operating systems MS-DOS, Windows, Linux, FreeBSD, AIX, IRIX, Tru64 UNIX, Solaris, HP-UX and VMS. The supported Windows compilers are: Visual C++, Borland C++, GCC, LCC, G77, G95, GNU Fortran, Absoft Pro, Lahey ELF90/LF90/LF95, Intel ICC/IFC, Digital Visual Fortran, Portland Group Fortran and Salford FTN77/FTN90/FTN95. The supported compilers for Linux are: GCC, G77, G95, GNU Fortran, Absoft Pro, NAG f90/f95, Imagine F, Intel ICC/IFC, Portland Group PGF77/PGF90 and Lahey LF95.



2PGPlotБесплатна только для некоммерческого использования. И вообще далеко не GPL опять же:
PGPLOT is not public-domain software. However, it is freely available for non-commercial use. The source code and documentation are copyrighted by California Institute of Technology, and may not be redistributed or placed on public Web servers without permission. The software is provided ``as is'' with no warranty.
Платформонезависимая:
PGPLOT has been tested with UNIX (most varieties, including Linux, SunOS, Solaris, HPUX, AIX, Irix, and MacOS X/Darwin) and OpenVMS operating systems. I am unable to provide support for DOS, Microsoft Windows, but I do distribute code provided by users for use with these operating systems.
Есть возможность использовать в программах на C, но сама библиотека на Фортране.


3libplot из GNU plotutilsЛицензия GPLКроссплатформенностьЧрезмерная сложность и избыточность для частных нужд (imho). Большой проект, включающий не только библиотеки, но и пользовательские программы.


4ROOT, http://root.cern.chЛицензия LGPLКроссплатформенность: Windows, Linux, Mac OS X и т.д.Та же (даже ещё большая) сложность и избыточность (вообще это система не только отображения, но и анализа данных), хотя это частично компенсируется достойной документацией.


5plplot, http://plplot.sourceforge.netЛицензия LGPLБольшое количество поддерживаемых архитектур:
It is currently known to work on the following platforms:

* Linux
* Unix
* MS-DOS (DJGPP)
* Windows (95?, 98, NT, and 2000)
* Mac OS X

We also have historically supported (but have no tests of the current PLplot) on the following platforms:

* Amiga/Exec
* MS-DOS (Various environments)
* MAC (traditional)
* OS/2
* VMS
* WIN32
Система "драйверов" вывода графиков (отдельные окана с графиками, либо вывод в различные графические форматы). Встраиваемый виджет существует только для Gnome.


6GuppiЛицензия GPLЗависимость от GNOMEБиблиотека, по заявлению авторов, на ранней стадии разработки:
Guppi is still in an early stage of development, and is still missing several important features.


7GtkExtra, http://gtkextra.sourceforge.netЛицензия LGPLПлатформонезависимость, однако есть привязка к GTKПоследний релиз датируется 2005-м годом


8http://www.eudoxos.net/gtk/gtkdatabox/Лицензия LGPLПлатформонезависимость, однако есть привязка к GTK











Доступны также версии таблицы в html и в spreadsheet на Google Docs.

Таблица сделана мной для себя, для своих нужд, выложена "as is", поэтому информация по библиотекам весьма ограниченная и в обзоре представлены лишь заинтересовавшие меня на тот момент проекты и их характеристики.

Данная заметка в большей степени "шпаргалка для себя" , за более полной информацией советую обратиться к замечательной статье неизвестного автора,
по которой я и писал эту заметку.


В первую очередь нам понадобятся два ключа - открытый, он же публичный (с помощью него можно шифровать файлы) и закрытый (с помощью которого файлы расшифровываются).

Смысл двух ключей в разделении их обязанностей. Так, вы можете выложить свой открытый ключ в общий доступ. С его помощью каждый сможет создать зашифрованный файл, который расшифровать сможете только вы с помощью закрытого ключа.

Создать пару ключей можно командой gpg --gen-key или, для ленивых, воспользоваться мастером создания ключей графической утилиты seahorse (вас попросят ввести срок годности ключа, можно поставить бесконечность, пароль и такую информацию, как имя ключа и ваш e-mail):

Для просмотра закрытых и открытых ключей служат соответственно команды
gpg --list-secret-keys и gpg --list-keys

Теперь зашифровать файл можно командой:
gpg -er [имя ключа/получатееля] ./test.file

А расшифровать командой:
gpg -d test.file.gpg > test.file

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

Делается эта нехитрая операция в три команды:

1) Создаем на локальном компьютере A пару ключей пользователя a:

a@A:~> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa):
Created directory '/home/a/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/a/.ssh/id_rsa.
Your public key has been saved in /home/a/.ssh/id_rsa.pub.
The key fingerprint is:
3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a@A

2) На удаленном сервере B создаем директорию ~/.ssh в домашнем каталоге удаленного пользователя b:
a@A:~> ssh b@B mkdir -p .ssh
b@B's password:

3) Заливаем открытый ключ на сервер B:

a@A:~> cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
b@B's password:

Всё, теперь можно логиниться без ввода пароля:

a@A:~> ssh b@B hostname
B
[по мотивам статьи на linuxproblem.org "SSH login without password"]

И настроим доступ по ssh без пароля к роутеру Linksys WRT54GL.


Активируем демон sshd через веб-интерфейс роутера (вкладка Administration -> Services, SSHD ставим "Enable") и в поле "Authorized Keys" вбиваем содержимое файла ~/.ssh/id_rsa.pub (открытый ключ нашего локального пользователя a).

Готово, можно логиниться на роутер:
ssh -l root [ip роутера]

Зайдя в очередной раз в свой веб-альбом на Picasa обнаружил необнадеживающую надпись наверху страницы:
"Вы используете браузер, который поддерживается не полностью. Некоторые функции могут работать не совсем правильно, но испытать программу все-таки можно."
Или в английском варианте:
"You are using a browser that is not fully supported. Some features may not work too well, but you are welcome to have a look around."

Скрин прилагается:
В итоге была значительна урезана функциональность picasa, совсем не работал javascript. Это по меньшей мере странно, т.к. я пользуюсь последней версией firefox.

Грешил было на noscript, однако опытным путём выяснилось, что виноват старый (но добрый) Flash Player 7. Непонятно для чего, но google видимо проверяет его версию (хотя на picasa я что-то flash не замечал).

Выход: поставить не совсем стабильный ешё Flash Player 9, либо вовсе отказаться от Flash Player (удивительно, но совсем без него picasa работает!).

В google groups обсуждают данное явление, но похоже в гугле сами ещё не до конца понимают в чём проблема.

В общем неприятный косяк от google.

iPod Shuffle Database Builder (текст касается последней на тот момент версии - rebuild_db-1.0-rc1) - отличная утилита на языке python, которая позволяет заливать музыку на ваш iPod Shuffle как на обычную флэшку, после чего все залитые аудиофайлы автоматически добавляются в плейлист запуском всего одной команды (никаких вам iTunes и прочих менеджеров плейлистов).
Расскажу как я ей пользуюсь, возможно что-то вам покажется лишним, но преимущества и суть её работы думаю будет ясна.

1) Монтируем iPod, делаем Back Up всех файлов и трём на нём всё, кроме каталога /iPod_Control/iTunes и файлов в нём (rebuild_db не умеет сам создавать базы с нуля, так что оставим старые от iTunes).
2) Кидаем файл rebuild_db.py из архива rebuild_db в корневой каталог iPod. Я так же переименовал его в update.now, т.к. в некоторых файловых менеджерах можно назначить программу, запускаемую при выборе файла какого-либо расширения (в данном случае - .now).
3) Создаем каталоги в корневой директории вашего плеера, например для музыки (Music) и для подкастов (Audiobooks), а так же для документов (Documents).
4) Создаем скрипт, которым будем запускать обновление базы, я использую такой:


#!/bin/sh
# Переходим в каталог iPod
cd /media/usbdisk
# Обновляем базу
python ./update.now -r Music Audiobooks | zenity --list --column="iPod Update DB" --height=600 --width=600
# Выходим из каталога (освобождаем девайс для размонтирования)
cd /
# TODO Здесь можно поставить umount


Этот скрипт нужно запускать после добавления/удаления музыки на iPod (и как я уже сказал в некоторых файловых менеджерах можно привязать запуск этого скрипта к двойному клику по файлу update.now).

Обращу внимание на команду обновления базы. Здесь я указываю программе индексировать только директории Music и Audiobooks (при чем именно в таком порядке, а не в алфавитном, таким образом подкасты будут всегда в конце плейлиста). При этом файлы из каталога Documents добавляться в базу не будут, таким образом в нем можно хранить и аудиофайлы, не предназначенные для проигрывания.

Отмечу, что т.к. в базу нельзя например добавлять файлы с русскими буквами в именах, rebuild_db заменит все неправильные с её точки зрения символы на символы подчеркивания.

Вывод команды rebuild_db я перенаправляю в графическое окно, созданное утилитой zenity (стандартным виджетом списка). Данный процесс можно лицезреть на скриншоте:


Можно также соорудить такой забавный хак: создать каталог Favourites и запускать команду обновления в скрипте таким образом:
python ./update.now -r Music Audiobooks Favourites Favourites Favourites.
Теперь файлы из этого каталога в режиме плеера Shuffle ("в случайном порядке") будут звучать в три раза чаще.

Для универсальности рекомендую закинуть в корень iPod и exe-файл rebuild_db.exe, чтобы была возможность на любой системе обновить базу. Если это unix-система и на ней установлен python - запускайте update.now, если оффтопик - rebuild_db.exe, однако о гибкости можно забыть, в базу будут добавлены абсолютно все аудиофайлы, содержащиеся на плеере, в алфавитном порядке.

Итак, есть желание "сграбить" AudioCD (легально купленный) под Linux для прослушивание например на флэш-плеере.
Есть множество вариантов решения данной задачи, расскажу на каком остановился я и почему.

Формат.

Для сжатия полученных треков мной был выбран аудиоформат AAC.
Связано это с тем, что во всех тестах популярнейший MP3 показывает худшие показатели из всех более-менее распространенных на сегодняшний день кодеков. Так же я вынужден был отказаться от Ogg Vorbis из-за неповсеместной поддержки его в нужных мне устройствах воспроизведения (пример - iPod или Sony PSP). С wma всё ясно думаю всем, продолжать нет смысла.

Кодек.

Здесь мой выбор пал на Nero Digital Audio. По тем же тестам он выглядит предпочтительнее open-source кодека FAAC, к тому же существуют некоторые проблемы с воспроизведением файлов, сжатым кодеком FAAC, на плеерах iPod. Архив Nero Digital Audio с бинариками под Linux и оффтопик можно бесплатно скачать с официального сайта.

Grip.



И уже для непосредственного извлечения дорожек с AudioCD я использую удобную графическую программу Grip. Вкладка с настройки для Nero Digital Audio - на скриншоте (как видно, я выставил качество выше среднего - 80% и совместимый с iPod профиль LC AAC, все равно дополнительные HE1 и HE2 профили имеет смысл использовать лишь на низких битрейтах).

Для решения задачи конвертации под Linux
видео для просмотра на Sony PSP
существует замечательная программа - PSPVC.


Процесс установки

Качаем архив (на данный момент последний релиз за номером 0.3 и все опыты проводились именно на нём) с программой с официального сайта.

Устанавливаем необходимые для сборки пакеты (и их -devel соответствия если нужно):
- nasm
- libfaac
- liba52
- libxvidcore
- gtk+2.0

Распаковываем архив и от рута даем команду установки:
./install.sh <путь для установки> (/usr/local по умолчанию)

После запуска pspvc вы увидите удобный gtk-интерфейс, где можно выставить параметры видео, запустить конвертацию и сгенерировать preview.
Описывать его подробно смысла нет.

Подводные камни

Возможно на вашем дистрибутиве программа соберётся без проблем (на Ubuntu 7.04 собирается без проблем), однако у меня (на ALTLinux) без них не обошлось.
Опишу подробней:

1) Проблема:
программа просто не собирается с ошибкой вида:
ffmpeg/libswscale/swscale_template.c
gcc is unable to create an executable file.
If gcc is a cross-compiler, use the --cross-compile option.
Only do this if you know what cross compiling means.
C compiler test failed.
If you think configure made a mistake, make sure you are using the latest
version from SVN. If the latest version fails, report the problem to the
ffmpeg-devel@mplayerhq.hu mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.err" produced by configure as this will help
solving the problem.
ERROR during configure FFMPEG

Решение:
В строке #56 файла install.sh убрать флаг "-lX11"

2) Проблема:
не компилируется ffmpeg с ошибкой (возможно из-за старой версии libxvidcore):
ERROR during configure FFMPEG

Если запустить компиляцию ffmpeg вручную видна суть ошибки:
vid_rc.o xvid_rc.c
xvid_rc.c: In function `ff_xvid_rate_control_init':
xvid_rc.c:70: error: structure has no member named `vbv_size'
xvid_rc.c:71: error: structure has no member named `vbv_maxrate'
xvid_rc.c:72: error: structure has no member named `vbv_initial'
make[1]: *** [xvid_rc.o] Ошибка 1
make[1]: Leaving directory `...'
make: *** [lib] Ошибка 2
ERROR during compilation or installation of FFMPEG

Решение:
Не самое элегантное и безопасное, но рабочее решение - закомментировать строки 70-72 в файле /pspvc-install-0.3/work/ffmpeg/libavcodec/xvid_rc (лучше перепаковать его в архив с ffmpeg, что идёт с программой, и удалить старую рабочую директорию work перед новой попыткой компиляции) :
//xvid_2pass2.vbv_size= s->avctx->rc_buffer_size;
//xvid_2pass2.vbv_maxrate= s->avctx->rc_max_rate;
//xvid_2pass2.vbv_initial= s->avctx->rc_initial_buffer_occupancy;

Расскажу как я справился с довольно типовой задачей
настройки роутера Linksys WRT54GL.

Требовался выход в интернет посредством VPN и одновременная работа локальной сети.
Если у вас есть достаточный опыт в Linux и нет страха перед командной строкой, то лучшим решением наверно будет воспользоваться прошивкой OpenWRT.
Это описание же расчитанно на неискушенного пользователя, и хоть
в своих экспериментах я активно пользовался консолью роутера (через ssh), данное описание позволяет настроить VPN используя исключительно web-интерфейс dd-wrt.


1) Ставим прошивку dd-wrt.
(Мне достался уже прошитый девайс =) , но в сети полно инфы о том, как прошить роутер, ничего сложного в этом нет. Возможно советы подойдут и для стандартной прошивки, я не проверял).
Испытания проводились на версии Firmware: DD-WRT v23.
Далее будем считать, что вы уже настроили локальную сеть,
т.е. вбили свой локальный ip/dns, либо клонировали mac-адрес и провайдер сам выдал все настройки.

2) В веб-интерфейсе открываем вкладку Administration -> Services, в разделе "pptp Client" ставим галочку "Enable". Жмём "Save settings".

3) В обновившемся поле "pptp Client" вбивает свои имя, пароль
и адрес vpn-сервера.
В полях "Remote Subnet" и "Remote Subnet Mask" оставляем нули,
если хотим через vpn лазить по всему интернету.

4) Идём в Setup -> Advanced routing
Вбиваем пути для локалки (обычно выдаются провайдером).
Главное, чтобы был путь до vpn-сервера, ну и до dns-сервера.
Базовые настройки на этом закончены.

5) Однако vpn может и не подняться из-за неподходящих для
вашего провайдера настроек, которые идут с dd-wrt по умолчанию.
Остановимся подробней на этом нетривиальном случае.
При включении роутера конфигурационный файл с опциями vpn
находится в файле /tmp/pptpd_client/options.vpn.
Соответственно этот временный файл нам и нужно поправить.
В моем случае напрмер нужно было отключить шифрование,
удалив соответствующую строку в конфиге:
"mppe required,no40,no56,stateless".
Это можно сделать редактором sed после включения роутера
с помощью команды:
cd /tmp/pptpd_client/; cp options.vpn
bak; cat bak|sed /mppe/d > options.vpn; rm bak
Этой командой мы перешли в директорию с конфигурационными файлами; скопировали файл настроек в файл bak;
отфильтровали полученный файл sed'ом >
записали результат вместо старого файла настроек;
удалили временный файл bak.

Стоит конечно прописать это в автозагрузку с небольшой поправкой:
т.к. временный файл создается не сразу, следует поставить небольшую
задержку (sleep), скажем в секунд 50.
Для этого открываем вкладку Administration -> Diagnostics,
жмём Run, вписываем в текстовом поле команду:
(sleep 50; cd /tmp/pptpd_client/; cp options.vpn bak;
cat bak|sed /mppe/d > options.vpn;rm bak
)&
(одной строкой) и жмём "Save Startup".

Данный способ изменения настроек может показаться не самым удобным, однако нельзя не отметить его гибкость.
Разобравшись как работает редактор sed можно варьировать настройки файла options.vpn как угодно.

6) Теперь можем перегрузить девайс:
на вкладке Administration жмём кнопку "Reboot Router"
После перезагрузки ждём отведённые нами 50 секунд и vpn-соединение должно работать.

UPD-2! Версия с GUI здесь.
UPD! Советы в большей степени касаются первоначальной версии framegrabber.
Обновленная версия (консольного) скрипта и описание к нему здесь!

Иногда возникает необходимость быстро создать серию скриншотов какого-либо видео, желательно аккуратно скомпонованных в одном файле (такое желание естественно например если вы релизите фильм на торрент-трекере).

Под небезызвестной ос windows есть множество утилит, которые с этим успешно справляются (см. Image Grabber 2).
Такого класса программы есть и под Linux, однако они обычно тянут за собой кучу зависимостей в виде библиотек типа xine-lib или того хуже qt4 (как тот же QFrameCatcher).

Я предлагаю вместо этого воспользоваться замечательным скриптом (к сожалению не известного мне автора):


#!/bin/bash
set +x

usage="framegrabber -h for help"
print_help()

{ cat <<'EOF'


Usage : framegrabber [-n stills] [-s size] FILE

Framegrabber is designed to extract stills from a video that is seekable and supported by
Mplayer. Framegrabber then combine them in a mosaic image allowing preview of the movie. Number of frames to extract and size of the frames can be modified via options.

Framegrabber depends on Mplayer and Imagemagick

Options :
-h : print this help message
-n : number of stills to extract
-s : size of each stills

framegrabbing -n 20 -s 100 my_video will create a mosaic of 20 stills of 100 pixels each.



EOF
}

while getopts ":n:s:h" option
do

case $option in
n ) n=$OPTARG;;
s ) s=$OPTARG;;
h ) print_help; exit 1;;
\? ) echo "Unknown option"; echo $usage; exit 1;;
* ) echo "Unknown option"; echo $usage; exit 1;;

esac
done



(( ! n )) && n=20

(( ! s )) && s=150


shift $(($OPTIND - 1))

_NFILE="$1"

_NBFRAME=$n
_SIZEFRAME=$s

_DIR=${_NFILE%/*}
_FILE=${_NFILE##*/}

(( ! $_FILE )) && print_help

cd "$_DIR"
pwd
echo "$_FILE"
mkdir sctmp
_SECONDS=`mplayer -ao null -vo null -frames 1 -identify "$_FILE" | grep ID_LENGTH= | cut -d"=" -f 2`
_FPS=`mplayer -ao null -vo null -frames 1 -identify "$_FILE" | grep ID_VIDEO_FPS= | cut -d"=" -f 2`
_INTSEC=`awk -v var="$_SECONDS" 'BEGIN { rounded = sprintf("%.0f", var); print rounded }'`
_INTFPS=`awk -v var="$_FPS" 'BEGIN { rounded = sprintf("%.0f", var); print rounded }'`
_STEP=`expr "$_INTSEC" / "$_NBFRAME"`
#_STEP=`expr $_STEP2 / $_NBFRAME`
_INTSTEP=`awk -v var="$_STEP" 'BEGIN { rounded = sprintf("%.0f", var); print rounded }'`
_SECSTEP=$_INTSTEP

_MAXFRAME=`expr 100 + $_NBFRAME + 1`

echo $_SECONDS
echo $_FPS
echo $_STEP

for i in `seq 100 $_MAXFRAME`

do
mplayer -really-quiet -ss "$_SECSTEP" -vo jpeg -frames 7 "$_FILE"
_SECSTEP=`expr $_SECSTEP + $_INTSTEP`
mv 00000007.jpg sctmp/$i.jpg
done

rm 0000000*.jpg
pwd
cd sctmp
mogrify -resize "$_SIZEFRAME"x1000 *.jpg
montage -geometry +2+2 -tile 4 *.jpg "$_FILE".png
rm *.jpg
convert "$_FILE".png "$_FILE".jpg
rm *.png
mv "$_FILE".jpg ..
cd ..
rmdir sctmp
echo "Finished"




Скрипт использует mplayer и imagemagick, которые входят в состав любого desktop-ориентированного дистрибутива. Соответственно с поддерживаемыми форматами проблем не предвидится (mplayer).

Использовать его проще простого:
$ framegrabbing -n 8 -s 320 video.avi
, где 8 - количество требуемых скриншотов, а 320 - их размер.

Результат выполнения данной команды должен выглядеть примерно так:

Важно! В скрипте автор с помощью mplayer'а создает по 7 скриншотов за раз и для конечного файла использует именно седьмой, однако mplayer (по крайне мере на некоторых файлах) не всегда выдает все 7. Поэтому имеет смысл брать именно первый скриншот, а имеено следует в строке "mv 00000007.jpg sctmp/$i.jpg" (строка 87) заменить 00000007.jpg на 00000001.jpg, т.е. всегда забирать первый файл.


Заметка про ещё один экзотический девайс и Linux.

Клавиатура от яблочников без труда определяется более-менее современным PC ещё на уровне bios, в Linux же без дополнительных телодвижений подхватывается стандартным "USB HID" драйвером. Печатать, и даже по-русски, уже можно =)

И что самое главное, подхватываются и нестандартные клавиши: xev реагирует например на нажатие клавиши повышения громкости и возвращает keycode:

KeyRelease event, serial 30, synthetic NO, window 0xe00001,
root 0x9f, subw 0x0, time 806958, (-515,533), root:(576,561),
state 0x10, keycode 176 (keysym 0x0, NoSymbol), same_screen YES,
XLookupString gives 0 bytes:

Теперь о том, что собственно подлежит настройке.

Поставим Alt на место.

Наверно самым неудобным (а скорее непривычным) кажется расположение клавиш "Alt", которые помещены непосредственно рядом с "Ctrl", так что естественным будет желание поменять их местами с "command" (кнопками с изображениями яблок).

Посмотрим модификаторы (альты, меты и проч.) по умолчанию:
bash-2.05b$ xmodmap -pm
xmodmap: up to 3 keys per modifier, (keycodes in parentheses):

shift Shift_L (0x32), Shift_R (0x3e)
lock Caps_Lock (0x42)
control Control_L (0x25), Control_R (0x6d)
mod1 Alt_L (0x40), Alt_L (0x7d), Meta_L (0x9c)
mod2 Num_Lock (0x4d)
mod3
mod4 Super_L (0x7f), Hyper_L (0x80)
mod5 Mode_switch (0x5d), ISO_Level3_Shift (0x7c)

И посмотрим маппинг нужных нам клавиш по умолчанию:
bash-2.05b$ xmodmap -pke | grep Alt ; xmodmap -pke | grep Super
keycode 64 = Alt_L Meta_L
keycode 113 = Alt_R Meta_R
keycode 125 = NoSymbol Alt_L
keycode 115 = Super_L
keycode 116 = Super_R
keycode 127 = NoSymbol Super_L

Очистим старые модификаторы:
bash-2.05b$ xmodmap -e "clear mod4"
bash-2.05b$ xmodmap -e "clear mod1"

Переназначим кнопки:
bash-2.05b$ xmodmap -e "keycode 64 = Super_L"
bash-2.05b$ xmodmap -e "keycode 115 = Alt_L Meta_L"
bash-2.05b$ xmodmap -e "keycode 113 = Super_R"
bash-2.05b$ xmodmap -e "keycode 116 = Alt_R Meta_R"
Переназначим модификаторы:

bash-2.05b$ xmodmap -e "add mod1 = Meta_L"
bash-2.05b$ xmodmap -e "add mod1 = Alt_L"
bash-2.05b$ xmodmap -e "add mod4 = Super_L"
Для автоматического применения запишем эти правила в ~/.xmodmaprc:
!Очистим старые модификаторы:
clear mod4
clear mod1
!Переназначим кнопки:
keycode 64 = Super_L
keycode 115 = Alt_L Meta_L
keycode 113 = Super_R
keycode 116 = Alt_R Meta_R
!Переназначим модификаторы:
add mod1 = Meta_L
add mod1 = Alt_L
add mod4 = Super_L
Запускать его следует так (можно прописать запуск например в ~/.xsession.d/):
bash-2.05b$ xmodmap $HOME/.xmodmaprc
И немного сcылок по теме:
Отличный how-to
Статья на Gentoo-wiki
Про ремапинг клавиш в целом

Настройка мультимедиаклавиш.
Запускаем xev и выясняем коды для мультимедиаклавиш, это 174, 176, 160 и 204 соответственно. Теперь замапим их соответствующим образом:
bash-2.05b$ xmodmap -e "keycode 174 = XF86AudioLowerVolume"
bash-2.05b$ xmodmap -e "keycode 176 = XF86AudioRaiseVolume"
bash-2.05b$ xmodmap -e "keycode 160 = XF86AudioMute"
bash-2.05b$ xmodmap -e "keycode 204 = XF86Eject"
Замечу, что это стандартные иксовые идентификаторы для такого рода кнопок, поэтому например в IceWM они будут работать уже после рестарта оконного менеджера. Привожу строки из дефолтного конфига IceWM (для привязки клавиш в других оконных средах смотрите их доки):
key "XF86AudioLowerVolume" aumix -v -5
key "XF86AudioRaiseVolume" aumix -v +5
key "XF86AudioMute" aumix -v 0
key "XF86Eject" eject

Ну и пропишем эти маппинги в
~/.xmodmaprc:
!Мультимедиа клавиши:
keycode 174 = XF86AudioLowerVolume
keycode 176 = XF86AudioRaiseVolume
keycode 160 = XF86AudioMute
keycode 204 = XF86Eject
Аналогично можно замапить и любые другие клавиши, например F13-F16.

UPD Актуальный .xmodmaprc:
!Очистим старые модификаторы:
clear mod4
clear mod1

!Переназначим кнопки:
keycode 64 = Super_L
keycode 133 = Alt_L Meta_L
!keycode 134 = Alt_R Meta_R
keycode 108 = Super_R

!Правый альт -- Compose key:
keycode 134 = Multi_key

!Переназначим модификаторы:
add mod1 = Meta_L
add mod1 = Alt_L
add mod4 = Super_L

!F13-F16
keycode 191 = F13
keycode 192 = F14
keycode 193 = F15
keycode 194 = F16

!Мультимедиа клавиши (теперь работают из коробки):
!keycode 122 = XF86AudioLowerVolume
!keycode 123 = XF86AudioRaiseVolume
!keycode 121 = XF86AudioMute
!keycode 204 = XF86Eject

Небольшая заметка о выборе и настройке usb-телефона под linux.
Выбор.
Меня интересовала не просто работа микрофона и динамика, но и как минимум клавиатуры.
Выбор пал на Skypemate p1K (в девичестве Yealink), как не на очень дорогой апппарат, при этом имеющий как полноценную клавиатуру ("как у мобильника"), так и простенький ЖК-дисплей. Ко всему прочему поддержка именно этого девайса в linux наиболее развита.
Настройка.
Поддержка собственно звука не требует практически никакой настройки. Девайс определяется как новая звуковуха:
-bash-2.05b# cat /proc/asound/cards
....
USB-Audio - VOIP USB Phone
Yealink Network Technology Ltd. VOIP USB Phone at usb-0000:00:03.0-3
В sip-клиенте достаточно выбрать например "/dev/dsp2" в качеcтве динамика/микрофона.
Что касается клавиатуры, то с этим ситуация несколько сложней.
Есть несколько проектов разной степени работоспособности:
1. SkypeMate - официальный драйвер. Бинарный, только для FedoraCore 3 (требует старый dbus-0.23). Плюс ко всему только для Skype. Отдельные джидаи запускали его на современных дистрибутивах с подменой либы dbus, с периодическими сегфолтами, я с этим заморачиваться не стал.
2. USBB2K-API - неофициальный драйвер. По отзывам пользователей - работает, однако у меня он не завелся. Девайс определялся, команды на телефон шли, однако обратной связи не наблюдалось. При этом на форумах отписывали пользователи с аналогичной проблемой, разработчики пытались им даже помочь, но дело там так и не сдвинулось с мертвой точки.
3. yealink-module - как видно из названия модуль для ядра. Последняя версия из CVS у меня собралась лишь после жесткой правки сорцов и после этого кончено нормально не работала, однако релиз за номером 0861 собрался сразу и без проблем был установлен. Замечу, что поддержка клавиатуры в нем реализована просто и универсально: клавиши телефона дублируют клавиши клавиатуры (цифровые, backspace, enter и т.д.)


 

Copyright © 2007 DamnSmallBlog. Content is licensed under Creative Commons Attribution-Noncommercial.

Design: GeckoandFly and Blogcrowds.