{"id":2023,"date":"2012-05-11T13:22:03","date_gmt":"2012-05-11T10:22:03","guid":{"rendered":"http:\/\/blog.railsware.com\/?p=2023"},"modified":"2021-08-16T15:36:28","modified_gmt":"2021-08-16T12:36:28","slug":"libskypekit-and-skypekit-c-and-ruby-interface-for-skype","status":"publish","type":"post","link":"https:\/\/railsware.com\/blog\/libskypekit-and-skypekit-c-and-ruby-interface-for-skype\/","title":{"rendered":"Libskypekit and Skypekit &#8211; C and Ruby interface for Skype"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Preface<\/h2>\n\n\n\n<p>There are two methods to programmatically use Skype:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Via the native desktop Skype application using <a href=\"http:\/\/developer.skype.com\/public-api-reference\" target=\"_blank\" rel=\"noreferrer noopener\">Skype Desktop API<\/a><\/li><li>Via <a href=\"http:\/\/developer.skype.com\/public\/skypekit\" target=\"_blank\" rel=\"noreferrer noopener\">SkypeKit<\/a> Runtime using SkypeKit SDK wrapper.<\/li><\/ul>\n\n\n\n<p>The first method is rather slow due to an interaction with the user interface. The second one is more interesting as there is no UI application.<\/p>\n\n\n\n<p>SkypeKit SDK includes only wrappers for:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>C++<\/li><li>Python<\/li><li>Java<\/li><\/ul>\n\n\n\n<p>Is Ruby wrapper missed? No more!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">On the way to gem<\/h2>\n\n\n\n<p>Before releasing gem, we tried several approaches. We tried to implement SkypeKit in pure Ruby as it done in SkypeKit Python Wrapper. But then, we realized that even if we make do it, its implementation will not be as fast as it should be. Then, we started to write a C extension for Ruby using the SkypeKit C++ Wrapper. But then, we admitted that this implementation will be inefficient due to asynchronous SkypeKit API and pure Ruby thread. Finally, we came to the implementation via Ruby FFI. We think that it&#8217;s the best way to do it because:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Thread stuff are completely on C side.<\/li><li>Synchronous program is easy to debug an test.<\/li><li>SkypeKit gem works in Ruby.<\/li><li>SkypeKit gem works in <strong>jRuby<\/strong>!<\/li><li>It&#8217;s possible to quickly implement SkypeKit in Perl\/Python\/lua\/etc.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">SkypeKit C library<\/h2>\n\n\n\n<p><a href=\"https:\/\/github.com\/railsware\/libskypekit\" target=\"_blank\" rel=\"noreferrer noopener\">Libskypekit<\/a> is a simple C library that brings <strong>asynchronous<\/strong> SkypeKit C++ wrapper functionality to the usual <strong>synchronous<\/strong> C applications.<\/p>\n\n\n\n<p>The goal of Libskypekit is to catch all asynchronous callbacks of SkypeKit C++ SDK and push them as events into a simple queue. Then synchronous application can pull this queue, retrieve each event and process it.<\/p>\n\n\n\n<p>Libskypekit is rather a young library, but we have already implemented the next basic events:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Account status changed<\/li><li>Chat message received<\/li><\/ul>\n\n\n\n<p>It&#8217;s enough to write simple chat applications. If your are familiar with C language look at<br><a href=\"https:\/\/github.com\/railsware\/libskypekit\/blob\/master\/examples\/ping_pong.c\" target=\"_blank\" rel=\"noreferrer noopener\">ping_pong example<\/a><\/p>\n\n\n\n<p>Is Ruby wrapper still missed? No more! :)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Skypekit Ruby gem<\/h2>\n\n\n\n<p>Thus LibskypeKit has a simple API, it&#8217;s was relatively easy to create a Ruby library using <a href=\"https:\/\/github.com\/ffi\/ffi\">Ruby FFI<\/a>.<\/p>\n\n\n\n<p>Plus the <a href=\"https:\/\/github.com\/railsware\/skypekit\">Skypekit Ruby library<\/a> provides a simple interface. For example, look at <em>ping_pong<\/em> example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">require \"skypekit\"\n\n$skype = Skypekit::Skype.new(:keyfile =&gt; 'myskypekit.pem')\n\n$skype.start\n$skype.login('myskypename', 'mypassword')\n\ndef terminate\n  puts \"Terminating\"\n  $skype.stop\n  exit\nend\n\ntrap('INT') do\n  terminate\nend\n\nloop do\n  event = $skype.get_event\n\n  unless event\n    sleep 5\n    next\n  end\n\n  case event.type\n  when :account_status\n\n    if event.data.logged_in?\n      puts \"Congrats! We are Logged in!\"\n    end\n\n    if event.data.logged_out?\n      puts \"Authentication failed: #{event.data.reason}\"\n      terminate\n    end\n\n  when :chat_message\n    message = event.data\n\n    puts \"@\" * 80\n    p message\n    puts \"@\" * 80\n\n    if message.body == \"ping\"\n      $skype.send_chat_message(message.convo_id, \"pong\")\n    end\n\n  end\nend\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">I want try it<\/h2>\n\n\n\n<p>In order to play with SkypeKit gem you need:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Register at developer.skype.com<\/li><li>Obtain SkypeKit SDK<\/li><li>Obtain SkypeKit Runtime<\/li><li>Obtain SkypeKit personal keypair<\/li><\/ul>\n\n\n\n<p>Then:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Compile SkypeKit SDK &#8211; see SDK documentation<\/li><li>Compile LibSkypeKit &#8211; see README in repository<\/li><li>Install SkypeKit gem &#8211; see README in repository<\/li><\/ul>\n\n\n\n<p>Now you can play with it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Legal part<\/h2>\n\n\n\n<p>Libskypekit and Skypekit gem are both released under the <a href=\"http:\/\/www.opensource.org\/licenses\/MIT\" target=\"_blank\" rel=\"noreferrer noopener\">MIT license<\/a>.<\/p>\n\n\n\n<p>But SkypeKit SDK is not!<\/p>\n\n\n\n<p>Please <em>carefully<\/em> read <a href=\"http:\/\/developer.skype.com\/skypekit\/legal\/license\" target=\"_blank\" rel=\"noreferrer noopener\">SkypeKit License Agreement<\/a>.<\/p>\n\n\n\n<p>There are a lot of restrictions!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"http:\/\/developer.skype.com\/public\/skypekit\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">SkypeKit SDK<\/a><\/li><li><a href=\"http:\/\/developer.skype.com\/public-api-reference\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">SkypeKit Desktop API<\/a><\/li><li><a href=\"http:\/\/developer.skype.com\/certify-market\/legal\/desktop-api\/terms-of-use\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Skype API Terms of Use<\/a><\/li><li><a href=\"http:\/\/railsware.github.com\/libskypekit\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Skypekit C library<\/a><\/li><li><a href=\"http:\/\/railsware.github.com\/skypekit\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Skypekit Ruby library<\/a><\/li><li><a href=\"https:\/\/rubygems.org\/gems\/skypekit\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Skypekit Ruby gem<\/a><\/li><li><a href=\"https:\/\/github.com\/ffi\/ffi\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Ruby FFI gem<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Preface There are two methods to programmatically use Skype: Via the native desktop Skype application using Skype Desktop APIVia SkypeKit Runtime using SkypeKit SDK wrapper. The first method is rather slow due to an interaction with the user interface. The second one is more interesting as there is no UI application. SkypeKit SDK includes only&#8230;<\/p>\n","protected":false},"author":19,"featured_media":2024,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3],"tags":[],"coauthors":["Andriy Yanko"],"class_list":["post-2023","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"aioseo_notices":[],"categories_data":[{"name":"Engineering","link":"https:\/\/railsware.com\/blog?category=development"}],"post_thumbnails":"https:\/\/railsware.com\/blog\/wp-content\/themes\/railsware\/vendors\/images\/article-thumbnail-default.jpg","amp_enabled":true,"_links":{"self":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/2023","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/comments?post=2023"}],"version-history":[{"count":22,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/2023\/revisions"}],"predecessor-version":[{"id":14142,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/2023\/revisions\/14142"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media\/2024"}],"wp:attachment":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media?parent=2023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/categories?post=2023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/tags?post=2023"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/coauthors?post=2023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}