Как стать автором
Обновить

SkypeKit и с чем его едят

Время на прочтение7 мин
Количество просмотров14K
SkypeKit — это проприетарный SDK для Skype. В принципе единственное на сегодня средство создания альтернативных Skype клиентов. Продукт интересен, но имеет достаточное количество проблем, которые могут вызвать разочарование у воодушевленного разработчика.

О том, что Skype открыл свой SDK уже писали на хабре. Поэтому топик будет непосредственно о практическом смысле применения SkypeKit и о его подводных камнях.

1. Регистрация

Я зарегистрировался еще когда SkypeKit находился в бете, а получить сие можно было только по инвайту и когда бесплатно не давали ключей для распространения в принципе.
Однако сейчас может вступить любой желающий, достаточно зайти на developer.skype.com, заполнить несложную форму и отдать кровных $10 (списывается со счета в Skype).
Большой совет: внимательно читайте лицензионные соглашения, они достаточно суровы. О лицензиях позже будет отдельный разговор. Обобщить это можно так: «Скайп попытался встать навстречу разработчикам, но так и не смог расстаться с проприетарщиной головного мозга». В относительной юридической безопасности только разработчики железяк.
Потом у вас будет возможность приглашать других пользователей в вашу организацию, но все равно с каждого попросят по 10 баксов, хотя на самом деле их можно не платить, просто давайте новым пользователям все необходимое для разработки барахло, залогиниться то они смогут (информация давно не обновлялась, могу ошибаться). Больше 100 человек в организации быть не может.

2. Получение SDK и Runtime

Интересное начинается с этого момента. Заходя на developer.skype.com/skypekit/sdks вы обнаружите предложение скачать «SkypeKit Multi-OS SDK», но поводов для радости на самом деле мало. В этом пакете кроме заголовочных файлов для C++, Java и Python и нескольких примеров на этих языках вы не найдете почти ничего. Где обещанный скайп спросите вы? А вот фиг вам просто так дадут runtime, заплатите 10 баксов и только после этого внизу страницы появится «Request a runtime». Список доступных платформ достаточно обширен: Windows, Linux, Mac с кодом в x86, ARM (v5, v6, v7) и MIPS (как little, так и big-endian). Но вы будете удивлены: видеозвонки поддерживаются только версией для Linux (причем на всех типах CPU). Ауу, Microsoft, куда ты смотришь?
ВНИМАНИЕ! Каждый рантайм собирается специально для вас и содержит вшитый идентификатор, который позволяет вас взять в анальное рабство вычислить. Полученный рантайм отождествлен с вашей зарегистрированной организацией. И во время разработки возможно залогинивание только тех аккаунтов, которые состоят в вашей организации.

3. Получение ключа

Для начала нужно зарегистрировать приложение на developer.skype.com/applications. Но тут есть забавные моменты:
  • Для одной организации можно создать до 50 приложений, удалять старые нельзя
  • Для возможности распространения большинства приложений требуется пройти сертификационный тест, который стоит $4000 и в случае неудачи, следующий тест будет стоить столько же
  • Но из предыдущего правила есть 3 исключения: обычные программы для Windows и Mac (без Linux), мобильные приложения и веб приложения. В этом случае «Distribution keypair» можно получить без прохождения тестов и траты денег, но придется принять весьма странное лицензионное соглашение
  • «Development keypair» доступен для всех приложений, но он действует только 60 дней. Причем при добавлении новых пользователей в организацию они не смогут пользоваться ранее полученным ключом
  • Чтобы можно было получить потом нормальный ключ, просто указывайте: только x86, только Windows и Standard Win/Mac application (последнее потом поменять будет нельзя)
4. Распаковываем полученное добро
И так мы имеем SDK, Runtime и Development keypair. Распаковываем в удобное место SDK, рантайм кладем в нужно место в %SDK%/bin, для ключа тоже придумываем место.
Наверняка вам захочется запустить примеры, но тут не так все просто. Для начала они должны знать, где лежит ключ. Для этого редактируем keypair.h, token.py и AppKeyPairMgr.java и вписываем нужный путь. Я очень не советую с душой вчитываться в какой-либо код — там страшнейший быдлокод! (позже я приведу пару примеров)
Если вы взяли рантайм с поддержкой VoicePCM/VoiceRTP или VideoRTP, тогда вам придется еще собрать заглушки для RTP/PCM (они есть в комплекте), а потом положить сборки в одну директорию с рантаймом. Для голоса в режиме SAL (Skype audio library) и без видео ничего собирать не нужно. Для запуска рантайма предназначен скрипт startskypekit.py, его можно немного подредактировать и получить удобный инструмент запуска рантайма вместе с обработчиками голоса и видео (без них рантайм тупо падает).
Теперь можно собрать примеры (в случае Python просто запустить, прежде запустив рантайм). В VisualStudio примеры собираются без каких-либо проблем. Можете поразвлекаться.

5. Особенности SDK

Есть некоторые особенности:
  • Нельзя запускать несколько рантаймов на одной машине
  • Для связи с рантаймом SDK использует сокеты
  • Можно использовать несколько аккаунтов через один рантайм
  • Код на питоне написан как-будто его писал индус, знающий только C++
  • Код SDK совместим только с рантаймами той же самой версии
Вы можете сами поизучать SDK, скачать можно и у меня: goo.gl/3egQi (благо там нет рантайма или чего-то еще персонализированного).

6. Примеры быдлокода

        if(input_started)
        {

          unsigned int samples_returned = output_buf.size() /( 2 * numOfOutputChannels );
          

          if(input_buf[(input_p % INPUT_BUF_ARRAY_SIZE)].size() != samples_returned * 2)
        input_buf[(input_p % INPUT_BUF_ARRAY_SIZE)].resize(samples_returned * 2);
    
          if(input_muted)
          {
        memset((char*)input_buf[(input_p % INPUT_BUF_ARRAY_SIZE)].data(), 0, input_buf[(input_p % INPUT_BUF_ARRAY_SIZE)].size());
          }
          else if(numOfOutputChannels > 1)
          {
        short* ob = (short*) output_buf.data();
        short* ib = (short*) input_buf[(input_p % INPUT_BUF_ARRAY_SIZE)].data();
        for(unsigned int i = 0 ; i < samples_returned; i ++)
        {
          ib[i] = ob[i * numOfOutputChannels];
        }
            
          }
          else
          {
        input_buf[(input_p % INPUT_BUF_ARRAY_SIZE)] = output_buf;
          }

          int input_samples_returned = input_buf[(input_p + 1) % INPUT_BUF_ARRAY_SIZE].size() / 2;
          m_transport->InputDeviceReady(input_samples_returned,input_sampleRate,1, input_buf[(input_p + 1) % INPUT_BUF_ARRAY_SIZE]);
        }
      }

Да, тут перенеслось несколько длинных строк, но это не сильно испортило код. Я не знаю что надо отрывать за одновременное использование табов и пробелов в отступах.
А это вообще пример «с любовью из Индии»
switch (propid) {
                case 4: return &skylibFields[689];
                case 5: return &skylibFields[690];
                case 7: return &skylibFields[691];
                case 8: return &skylibFields[692];
                case 9: return &skylibFields[693];
                case 10: return &skylibFields[694];
                case 11: return &skylibFields[695];
                case 12: return &skylibFields[696];
                case 13: return &skylibFields[697];
                case 14: return &skylibFields[698];
                case 15: return &skylibFields[699];
                case 16: return &skylibFields[700];
                case 17: return &skylibFields[701];
                case 18: return &skylibFields[702];
                case 19: return &skylibFields[703];
                case 26: return &skylibFields[704];
                case 27: return &skylibFields[705];
                case 28: return &skylibFields[706];
                case 34: return &skylibFields[707];
                case 37: return &skylibFields[708];
                case 70: return &skylibFields[709];
                case 71: return &skylibFields[710];
                case 72: return &skylibFields[711];
                case 73: return &skylibFields[712];
                case 74: return &skylibFields[713];
                case 75: return &skylibFields[714];
                case 76: return &skylibFields[715];
                case 77: return &skylibFields[716];
                case 78: return &skylibFields[717];
                case 79: return &skylibFields[718];
                case 160: return &skylibFields[719];
                case 161: return &skylibFields[720];
                case 162: return &skylibFields[721];
                case 163: return &skylibFields[722];
                case 164: return &skylibFields[723];
                case 165: return &skylibFields[724];
                case 166: return &skylibFields[725];
                case 168: return &skylibFields[726];
                case 169: return &skylibFields[727];
                case 182: return &skylibFields[728];
                case 183: return &skylibFields[729];
                case 205: return &skylibFields[730];
                case 773: return &skylibFields[731];
                case 800: return &skylibFields[732];
                case 801: return &skylibFields[733];
                case 802: return &skylibFields[734];
                case 804: return &skylibFields[735];
                default: break;
                }

Ну еще можно сказать, что не надо в питоне после окончания строки ставить точку с запятой. Причем то строчка, то строчка сяк. Я не знаю, есть-ли вообще у них какие-либо Code Style Conventions.

7. Лицензионные соглашения

Именно таким текстом вас поприветствует рантайм:
SkypeRuntime Copyright (C) 2003-2011 Skype Technologies S.A.
SkypeRuntime Version: 3.4.1/windows-x86-skypekit-novideo_3.4.1.339_%боюсь_палить%
Proprietary and confidential, do not share this application.

А по сути: соглашение раз и соглашение два
Особо порадовала цитата:
4.3. Without limiting the generality of the foregoing, you are expressly prohibited from:
4.3.1. running one or more copies of the SkypeKit Software on physical or virtual servers in order to make a SkypeKit Product available to End Users;
4.3.2. licensing, selling, marketing distributing or otherwise making available:
4.3.2.1. any Hardware Product directly (or indirectly through value added resellers or other channels) to small, medium or large businesses or enterprises;
4.3.2.2. any Prohibited Development as defined in Section 4 of the License Agreement.

То есть они говорят, что нельзя продавать железки юридическим лицам, даже если это торговые сети. Ну господа, извините, но это какое-то невыполнимое условие. Интересно, как тогда Samsung встроил скайп в свои телевизоры?

8. В итоге

Приведу маленький пример кода на питоне:
import sys, time, SkyLib

accountName = sys.argv[1]
accountPsw  = sys.argv[2]
keyFileName = sys.argv[3]

def AccountOnChange (self, property_name):
    if property_name == 'status':
        if self.status == 'LOGGED_IN':
            print 'Login complete.'
SkyLib.Account.OnPropertyChange = AccountOnChange

def OnMessage(self, message, changesInboxTimestamp, supersedesHistoryMessage, conversation):
    if message.author != accountName:
        print(message.author_displayname + ': ' + message.body_xml)
        conversation.PostText('Automated reply.', False)
SkyLib.SkyLib.OnMessage = OnMessage

skype = SkyLib.GetSkyLib(keyFileName)
account = skype.GetAccount(accountName)
print 'Logging in with ' + accountName
account.LoginWithPassword(accountPsw, False, False)

while account.status != 'LOGGED_IN':
    time.sleep(1)

print 'Now accepting incoming chat messages.'
print 'Press ENTER to quit.'
raw_input('')
skype.stop()

Несмотря на простоту эта программа принимает сообщения в скайпе и автоматически на них отвечает. Хотя метод возбуждения событий сильно попахивает C++, где для этих целей наследуется класс. Но в питоне это выглядит несколько грубо. Но можно легко написать класс — обработчик событий и писать более красиво. Но это уже на вкус программиста.
В принципе SkypeKit получился достаточно интересным продуктом, но стоило бы пересмотреть лицензионную политику и убрать быдлокод из SDK. Лично мне совершенно без разницы, какой код был при написании скайпа (он откомпилен и все), но смотреть на код в SDK мне, честное слово, противно. Ну могли бы нанять толковых программистов для написания бэкенда к рантайму, ведь не такой уж большой объем кода. В целом API нормально документирован и после некоторого ковыряния приходит понимание, как все это работает. Продукт сырой, хотя ему уже не первый год.
В мои планы входит написание транспорта Skype <-> XMPP, так что буду вкуривать в устройство libjingle. чтобы можно было и звонить. Но я не уверен, что после написания я смогу его распространять в таких лицензионных условиях.

Удачи! Делайте свои скайпы с блэкджеками и чем хотите.
Вам решать, нужно оно вам или нет. Но по моему мнению не стоит жалеть 10 долларов хотя бы ради интереса. Но и строить грандиозные планы тоже очень сложно.
Теги:
Хабы:
+52
Комментарии62

Публикации