Skype & Linux

К сожалению, разработчики Skype уделяют мало внимания Skype для Linux. На сегодняшний день, все ограничивается достаточно устаревшей версией 2, которая однако поддерживает все основные функции включая полноэкранное видео и шаринг рабочего стола.

Есть у Skype несколько замечательных багов, которые достаточно сильно мешают работе. Первый заключается в том, что если свернуть программу в область уведомлений и запустить с ярлыка еще раз, то откроется новая копия программы. Достаточно необычный сценарий использования, как считаете? Беда вся в том, что всякого рода ланчеры, панельки и докбары при потере хендла главного окна (да, при сворачивании Skype разрегистрирует окно) и запускают новый процесс.

Вторая бага начинается с того, что нужно свернуть программу в область уведомлений. Если ее не трогать некоторое время, то она может зависнуть. Я не нашел какого либо точного сценария для воспроизведения, однако Skype таки периодически виснет. Иконка останется в трее, процесс будет висеть, в сети статус offline и вытащить программу на свет никак не выйдет. Спасает killall -9 skype и перезапуск.

Эти проблемы мы сейчас и решим. Решать будем методом "в лоб", ведь у нас есть все необходимое: Skype API и DBUS.

Отредактируем skype-wrapper
sudo nano /usr/bin/skype-wrapper
Содержимое должно быть следующим:
#!/bin/sh

StartSkypeWrapper()
{
        if [ ! -e ~/.Skype/shared.xml ]; then
                mkdir -p ~/.Skype
                cp /usr/share/skype/shared.xml ~/.Skype/shared.xml
        fi


        #LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so  /usr/bin/skype "$@"
        echo skypename skypepassword | LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so skype --pipelogin &
}

# See if skype is running; if not, start it
if pidof skype > /dev/null
then
        # See if Skype is up; if so, focus it
        wmctrl -a Skype™ && exit
else
        echo 'Starting Skype . . .'
        #exec skype-wrapper "$@"
        StartSkypeWrapper && exit

fi

# Set Skype window state as active
# Thanks to aendruk at http://askubuntu.com/questions/16612/how-can-i-activate-a-panel-icon-via-a-script-or-get-its-screen-co-ordinates-to
CODE=$(/usr/bin/showskype.py)
case $CODE in
        'WINDOWSTATE NORMAL') # Skype focused normally.
                echo $CODE
                exit
                ;;
        'ERROR 68') # Skype not logged in; restart it to give focus
                echo $CODE
                killall -9 skype
                #exec skype-wrapper "$@"
                StartSkypeWrapper
                ;;
        *) # I don't know what happened
                exec zenity --error --title="$(basename "$0"): error" --text="Unknown Skype code returned: \"$CODE\"\n\nContact your system administrator for assistance."
esac

# Unreachable code block.  Bad news if we get here.
exec zenity --error --title="$(basename "$0"): error" --text="Unreachable code block reached.  Contact your system administrator if you really care."

К сожалению, dbus-send входящий в поставку Ubuntu не умеет держать сессию, а Skype принимать несколько сообщений за раз. Поэтому придется использовать кусочек на Python, который не имеет этих ограничений.
Создаем следующий файл
sudo nano /usr/bin/showskype.py
Содержимое:
#!/usr/bin/env python

import dbus

# Get a D-Bus interface to Skype
bus = dbus.SessionBus()
skype_object = bus.get_object('com.Skype.API', '/com/Skype')
skype = dbus.Interface(skype_object, dbus_interface='com.Skype.API')

# Ask for permission to control Skype
response = skype.Invoke("NAME " + __file__)
response = skype.Invoke("PROTOCOL 8")

# Issue commands
response = skype.Invoke("SET WINDOWSTATE NORMAL")
print response

Владелец и права доступа:
sudo chown root:root /usr/bin/showskype.py
sudo chmod a+x /usr/bin/showskype.py

Теперь следует заменить комманду запуска Skype в ярлычках на skype-wrapper. Первая проблема решена. Проверено на стоковой поставке ubuntu 10.10, а также в работе с Avant Window Navigator.

Для решения второй проблемы, мы будем раз в минуту дергать Skype по DBUS и если он мертв - перезагружать.

mkdir ~/bin
nano ~/bin/checkSkype.sh
Содержимое:

#!/bin/sh

StartSkypeIfCrached()
{
if pidof skype > /dev/null;
then
        LogThis "Skype is halt!!! Kill..."
        killall -9 skype
        LogThis "Start Skype."
        skype-wrapper & exit
else
        LogThis 'Skype was not started.'
fi
}

LogThis()
{
        logger -t checkSkype -s $1
}

CODE=$(dbus-send --session --type=method_call --print-reply --dest=com.Skype.API /com/Skype com.Skype.API.Invoke string:PING | grep -c PONG)
#if [$CODE="1"]
if test $CODE -ne 1;
then
        StartSkypeIfCrached
else
        LogThis "Skype OK, PID: `pidof skype`"
fi

Здесь нам не нужно несколько комманд, поэтому можно использовать dbus-send.
Не забываем права запуска:
chmod a+x ~/bin/checkSkype.sh

Добавляем в расписание:
crontab -e
Содержимое:
*/1 * * * *     DISPLAY=:0.0 sh /home/user/bin/checkSkype.sh

И вторая проблема решена. В /var/log/syslog всегда можно посмотреть на состояние Skype, скрипт логирует в syslog.

Для управления Skype были использованы его API и технология DBUS. Почитать по теме:

    Коментарі

    1. Недельное тестирование показало, что зависаючи Skype продолжает отвечать на PING по DBUS и даже разворачивает окно, но работать при этом не начинает. Т.е. метод определения некорректен.
      Правда он не меняет статус и не завершается, это нужно как то использовать для определения работоспособности. Идеи?

      ВідповістиВидалити
    2. У вас в коде пароль и логин от скайпа ваши стоят ?

      ВідповістиВидалити
    3. не подскажите, из за чего при выполнении скрипта showskype.py
      выпадает ошибка ERROR 68?
      как я понимаю это из за того что вы свои логины и пароли потерли в скрипте. Не могли бы вы подсказать куда их прописать надо.

      ВідповістиВидалити
    4. Не.
      Сейчас точно не могу сказать, но такая ошибка появляется если скрипт не может найти Скайп.
      Проверьте, скайп должен быть установлен из репозитория, и это должна быть на Static версия (в ней нет DBUS)

      ВідповістиВидалити

    Дописати коментар

    Популярні публікації