Используя межпрограммный интерфейс D-Bus, можно управлять поведением любого современного графического Linux-приложения извне — из своих скриптов или повесив нужное действие на сочетание клавиш. В этой статье мы рассмотрим несколько полезных трюков с D-Bus, которые пригодятся любому пользователю.

 

Вкратце о D-BUS

Чтобы ты понимал, о чем идет речь, нужно разобраться, как работает D-Bus, и что это вообще такое. Сразу предупреждаю, сейчас будет немного скучно. Но без теории никак. Иначе вместо того, чтобы практически использовать D-Bus, ты ограничишься только трюками из этой статьи.

D-Bus — это система межпроцессного взаимодействия, которая обеспечивает тесную связь десктопных приложений между собой, и связь между десктопными приложениями и системными сервисами. Например, через D-Bus программы могут узнать о наличии/ отсутствии сети у Network Manager'а; твой музыкальный плеер переключится на следующий трек и сообщит IM-клиенту название композиции, причем твои собеседники увидят ее у тебя в статусе; рабочий стол сменит фоновую картинку; все окна с рабочих столов выстроятся в режиме scale; автоматически подмонтируется вставленное USB-устройство (даже если нет прав рута, связка HAL + D-Bus + pmount) и т.д.

Что интересно, D-Bus не зависит от конкретной среды (KDE, GNOME, Xfce…), но при этом прекрасно интегрируется в каждую из них. В основе структуры D-Bus лежит понятие шины. Это специальный механизм, с помощью которого процессы обмениваются данными.

Первая и самая главная — системная шина, создается при запуске демона D-Bus, используется для «общения» различных демонов и практически недоступна для пользовательских приложений. Сессионная шина, наоборот, создается для пользователя, вошедшего в систему — по ней будут «общаться» приложения, с которыми работает пользователь. Для каждой сессионной шины запускается отдельная копия демона.

У каждого сообщения, передаваемого по шине, есть отправитель и получатель. Адреса отправителя и получателя называются путями объектов, то есть D-Bus предполагает, что каждое приложение состоит из набора объектов, а сообщения пересылаются не между приложениями, а между объектами приложений. У каждого объекта может быть один или более интерфейсов. Интерфейсы представлены в виде именованных групп методов и сигналов, как в интерфейсах Glib, Qt и Java.

D-Bus предусматривает собственную концепцию сервисов. Сервис — это уникальное местоположение приложения на шине. При запуске программа регистрирует один или несколько сервисов на шине, которыми она будет владеть, пока не освободит их. До момента освобождения ни одно другое приложение не сможет занять уже занятый сервис.

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

В D-Bus у каждого объекта свое уникальное имя. Имя объекта напоминает путь в файловой системе, например, org/kde/ kspread/sheets/1/cells/1/1. Обычно путь имеет какую-нибудь смысловую нагрузку. Например, в данном случае мы обращаемся к ячейке 1:1 на первом листе электронной книги KSpread. Но имена могут быть совершенно бессмысленными, например, /com/appl1/c5444sf956a. Тут все зависит от фантазии разработчиков.

На этом скучная часть статьи закончилась, и можно приступать к практике.

 

D-BUS и скринсейверы

Начнем с самых простых трюков, связанных с D-Bus и скринсейверами. Заблокировать экран можно следующей командой:

$ qdbus org.kde.krunner /ScreenSaver Lock

Иногда напрягает, что хранитель экрана вообще запускается. Ну не нужен он мне. Конечно, в настройках KDE его можно отключить, но раз сегодня мы говорим о D-Bus, то тебе пригодится следующая команда:

$ qdbus org.kde.krunner /ScreenSaver \
SimulateUserActivity

Кстати, в некоторых случаях X-сервер может потушить экран. Чтобы обойти эту «фичу», нужно ввести команду:

$ xset dpms 0 0 0

Первый 0 — это время в секундах до гашения монитора без его выключения, второй 0 — это время до перехода в режим ожидания, а третий — время до выключения монитора.
Вообще, вместо команды xset можно править xorg.conf, но учитывая, что в современных дистрибутивах он отсутствует, лучше все-таки использовать команду xset.

Вернемся к методу SimulateUserActivity. Метод, как следует из его названия, имитирует активность пользователя. Его нужно вызывать периодически. Но не будешь же ты вводить приведенную выше команду, скажем, каждые 30 секунд? Тогда можно набросать небольшой сценарий:

#!/bin/bash
$* &
while jobs | grep -q Running
do
qdbus org.kde.krunner /ScreenSaver \
SimulateUserActivity
sleep 30
done

Сценарию нужно передать командную строку. Да, именно командную строку, тогда скрипт запустит приложение и будет имитировать активность пользователя. Сохрани сценарий как /usr/bin/simulate. После этого установи права доступа и запускай:

$ sudo chmod +x /usr/bin/simulate
$ simulate mplayer film.avi

Действительно, у MPlayer есть параметр '-stopxscreensaver', но у других проигрывателей подобного параметра может и не оказаться.

 

Трюки с буфером обмена

В Windows я использовал довольно неплохой менеджер закачек — FlashGet. Он активировался, как только в буфере обмена появлялась ссылка. Всплывало окно, где нужно было либо подтвердить закачку, либо отказаться от нее. Сейчас мы попробуем реализовать подобный мониторинг буфера обмена в Linux с помощью D-Bus. Следующая команда выводит содержимое клипборда:

$ qdbus org.kde.klipper /klipper \
getClipboardContents

Теперь напишем простенький сценарий, выводящий содержимое буфера обмена, если в нем есть URL (для простоты мы будем учитывать только http://):

#!/bin/bash
while true
do
if qdbus org.kde.klipper /klipper
getClipboardContents | egrep -q '^(http://)'
then
qdbus org.kde.klipper /klipper
getClipboardContents
fi
sleep 1
done

Скрипт не делает ничего сверхъестественного. Сначала запускается бесконечный цикл (прервать выполнение можно либо нажатием <Ctrl+C>, либо закрытием окна терминала), затем анализируется содержимое буфера обмена. Если оно содержит URL (строку, начинающуюся с http://), то сценарий просто выводит содержимое клипборда, а затем засыпает на секунду. Чтобы сценарий закачивал файл, нужно модифицировать его так:


then
in='qdbus org.kde.klipper /klipper \
getClipboardContents'
wget $in
fi

Мы сохраняем содержимое буфера обмена в переменной in, а затем передаем ее программе wget, которая и загружает файл. Конечно, наш «менеджер загрузок» далек от совершенства. Вопервых, нужно научить его реагировать и на FTP-адреса. Во-вторых, если в буфере обмена кроме URL будет еще и произвольный текст, например, «Ссылка http://server/file», то сценарий завершится с ошибкой. Тут можно так и оставить (FlashGet тоже не активируется, если в буфере обмена есть еще что-то, кроме URL), а можно посредством регулярных выражений выделить URL, и получить его с помощью wget. В любом случае, все это уже не относится к D-Bus и буферу обмена, поэтому пусть это будет твоим домашним заданием. Кроме метода getClipboardContents есть метод setClipboardContents, устанавливающий содержимое буфера обмена. Использовать его можно так:


if qdbus org.kde.klipper /klipper getClipboardContents |
egrep -q '^(http://)'
then
qdbus org.kde.klipper /klipper setClipboardContents
"Копировать URL запрещено"

 

Управляем проигрывателем AMAROK 2 с помощью D-BUS

Следующие команды аналогичны нажатию кнопок Play, Pause, Next, Prev, Stop, Quit:

$ dbus-send --type=method_call --dest=org.kde.amarok \
/Player org.freedesktop.MediaPlayer.Play
$ dbus-send --type=method_call --dest=org.kde.amarok \
/Player org.freedesktop.MediaPlayer.Pause
...
$ dbus-send --type=method_call --dest=org.kde.amarok \
/ org.freedesktop.MediaPlayer.Quit

Кстати, у Amarok2 есть поддержка Last.FM, но для этого сервиса поддерж иваются только методы Stop и Play. Приведу воркэраунд для пропуска текущей песни:

#!/bin/bash
dbus-send --type=method_call --dest=org.kde.amarok \
/Player org.freedesktop.MediaPlayer.Stop
sleep 5
dbus-send --type=method_call --dest=org.kde.amarok \
/Player org.freedesktop.MediaPlayer.Play

Вывести всю информацию о текущем треке можно следующим образом:

$ qdbus org.kde.amarok /Player GetMetadata

Еще очень полезный метод GetStatus, возвращающий 4 целых числа:

  • Первое число: 0 — трек воспроизводится, 1 — пауза, 2 — остановлен;
  • Второе число: 0 — последовательное воспроизведение, 1 — случайное воспроизведение;
  • Третье число: 0 — перейти к следующему элементу после воспроизведения текущего, 1 — повторить текущий элемент;
  • Четвертое число: 0 — остановить воспроизведение, как только будет достигнут последний элемент, 1 — продолжить воспроизведение с начала.
 

Управление проигрывателями VLC и XMMS

Аналогично можно управлять и другим проигрывателем — VLC. Вот действие, аналогичное нажатию на кнопку воспроизведения:

$ dbus-send --print-reply --session --dest=org.mpris.
vlc /Player org.freedesktop.MediaPlayer.Play

Как только я начал свое знакомство с Linux, лучшим медиа-проигрывателем для него был XMMS. Отчасти его популярность заключалась во внешней схожести с популярным в то время Winamp. Недавно наткнулся на полное описание D-Bus интерфейса современной версии XMMS (XMMS 2): http://xmms2.org/wiki/MPRIS#D-Bus. Если тебе нравится XMMS 2, то эта ссылка будет весьма полезной для тебя.

 

Интерфейс org.freedesktop.mediaplayer (MPRIS 1.0 DBUS API)

Все популярные проигрыватели, такие как Amarok, VLC, XMMS, Audacious, BMPx, используют интерфейс MPRIS. Следовательно, можно написать универсальный сценарий управления проигрывателями, в качестве параметра которому передавать название плеера. Берем команду dbus-send и вместо значения параметра '--dest' указываем своего фаворита:

$ dbus-send --type=method_call --dest=проигрыватель \
/Player org.freedesktop.MediaPlayer.Play

Далее все стандартно. Управление проигрывателем осуществляется через интерфейс org.freedesktop.MediaPlayer объекта /Player. А управление списком композиций — через объект /TrackList.

 

Регулировка громкости

Установить уровень громкости можно с помощью метода VolumeSet:

$ dbus-send --type=method_call --dest=проигрыватель \
/Player org.freedesktop.MediaPlayer.VolumeSet значение

Значение может быть в диапазоне 0…100. 0 — звук выключен, 100 — максимальная громкость. Например:

$ qdbus org.kde.amarok /Player VolumeSet 90

Узнать текущее значение громкости можно методом VolumeGet.

 

А что дальше? Или метод научного тыка

С помощью D-Bus можно управлять практически любым современным графическим Linux-приложением. Поскольку я не могу читать твои мысли, то не могу предусмотреть все трюки, которые ты хотел бы видеть в этой статье. Поэтому я только расскажу, что нужно для самостоятельного исследования объектов и методов D-Bus. Запусти yakuake (это мой любимый терминал в KDE, запускается при нажатии <F12>) и введи команду:

$ qdbus org.kde.yakuake
/KDebug
/Konsole
/MainApplication
/Sessions
/Sessions/1
/yakuake
/yakuake/MainWindow_1
/yakuake/sessions
/yakuake/tabs
/yakuake/window

В результате ты получишь список объектов сервиса org.kde.yakuake. Если ты знаешь, что такое ООП, то уже догадался, что у каждого объекта есть методы. Просмотреть список методов можно так:

qdbus сервис объект

Например:

$ qdbus org.kde.yakuake /yakuake/tabs

Приведенная выше команда выводит методы объекта /yakuake/tabs. Например, метод setTabTitle() позволяет установить заголовок вкладки. Для этого методу нужно передать номер сессии и строку — будущий заголовок. Чтобы узнать номер сессии, посмотрим на список методов объекта /yakuake/sessions:

$ qdbus org.kde.yakuake /yakuake/sessions

Номер (идентификатор) активной сессии возвращается методом activeSessionId(). Чтобы получить номер текущей сессии (под сессией в yakuake подразумевается вкладка), нужно ввести команду:

$ qdbus org.kde.yakuake /yakuake/sessions \
activeSessionId

Синтаксис следующий:

qdbus сервис объект метод

Напишем сценарий, изменяющий заголовок текущей вкладки:

#!/bin/bash
id=`qdbus org.kde.yakuake /yakuake/sessions
activeSessionId`
echo $id
qdbus org.kde.yakuake /yakuake/sessions setTabTitle \
$id "произвольный текст"

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

#!/bin/bash
id=`qdbus org.kde.yakuake /yakuake/sessions
activeSessionId`
qdbus org.kde.yakuake /yakuake/sessions setTabTitle \
$id $1

 

Заключение

Кому не нравится изучать объекты и методы D-Bus в терминале, могут использовать утилиту qdbusviewer из пакета qt4-dev-tools, которая предоставляет более удобный интерфейс для просмотра списков объектов и методов D-Bus. Точное описание объектов и методов ты найдешь на страничке разработчиков той или иной программы. А вот что касается самой D-Bus, то настоятельно рекомендую ознакомиться вот с этим руководством — http://dbus.freedesktop.org/doc/dbus-tutorial.html. Удачи!

 

Кобра, мыло и все остальные

Приложения в рамках одной среды рабочего стола должны тесно взаимодействовать между собой. В KDE не так давно для этого использовалась система DCOP (Desktop COmmunication Protocol), которая в настоящее время заменена на D-Bus. Кроме DCOP существовала возможность коммуникации с помощью CORBA, SOAP или XML-RPC. Но CORBA требует много системных ресурсов, а SOAP и XML-RPC предназначены больше для веб-сервисов.

Работа с программой мгновенного обмена сообщениями Kopete

 

Получить массив, содержащий список контактов запущенного Kopete:

$ dbus-send --type=method_call --dest=org.kde.kopete \
--print-reply /Kopete org.kde.Kopete.contacts

 

Завершение сеанса

$ dbus-send --session --type=method_call \
--dest=org.kde.kopete \
/Kopete org.kde.Kopete.disconnectAll

 

Пользовательские сессии и D-Bus

Сохранить текущую сессию можно вот такой командой:

$ dbus-send --dest=org.kde.ksmserver /KSMServer \
org.kde.KSMServerInterface.saveCurrentSession

Если ты хочешь сохранить сессию и выйти, набирай:

$ qdbus org.kde.ksmserver /KSMServer logout 0 2 0

• Выключить компьютер (без прав root'а):

$ dbus-send --system --dest=org.freedesktop.Hal \
--type=method_call --print-reply \
/org/freedesktop/Hal/devices/computer \
org.freedesktop.Hal.Device.SystemPowerManagement.Shutdown

 

Links

Check Also

Дьявольски-красный пентест. Строим цепочки туннелей через докер-контейнеры на виртуалке с Hack The Box

Что делать, когда тебе нужно захватить контроль над хостом, который находится в другой под…

Оставить мнение