Your tablet as a Skype Remote Control

July 20, 2016

The idea comes from a Cisco device we use every day at work :

A monitor (42" wide) and a 8" tablet used as a remote control.

The tablet is not a simple extension, it has its own IP address. So there are 2 distinct devices.

Why doing the same at home ?

I use Skype every week for work, friends and family.

For work, this is how I built my desk :

A 7" tablet (Archos 7b Xeon) with a flexible support https://www.amazon.fr/gp/product/B016B4I352

It is perfect for work, write notes (or doing other things...).

It is not easy to use from my (confortable) sofa, in front of TV.
Why not using the TV for Skype ?
Ok, just install X and Skype on my server (a desktop running 7/24).

Solved ?
Without writing any code ?
Hum, not a geek solution :)

I need at least an API to drive Skype remotly.
No VNC or pointing device, just an API to build a webapp. So, let's go !

This is how it looks like today

Skype Desktop API

Microsoft has not updated Skype for Linux for a while.
Now on Windows or MacOS Skype Desktop API is deprecated. In the future, no desktop app, just a webapp (2016 compliant ??? I think).

https://support.skype.com/en/faq/FA214/what-is-the-desktop-api

Not familiar with Dbus connection ?
Take a look at : https://github.com/taksan/skype-java-api

A Java gateway for skype ! Wow ! Only this implementation shows call, contacts and settings. Other implementations (Python, NodeJS...) has only messaging capabilities.

What is needed :

Remember : this is a Proof of Concept so using basic tools to build a simple implementation

A new Eclipse Java Web project

Code written :

package fr.mathieupassenaud.skypeweb;

import java.util.ArrayList;

import javax.ws.rs.GET;  
import javax.ws.rs.Path;  
import javax.ws.rs.Produces;  
import javax.ws.rs.core.MediaType;

import com.skype.ContactList;  
import com.skype.Friend;  
import com.skype.Skype;  
import com.skype.SkypeException;  
import com.skype.User.Status;

import fr.mathieupassenaud.skypeweb.model.FriendModel;

@Path("/contact")
public class ContactsService {

    @Path("/online")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public FriendModel[] getOnlineContacts() throws SkypeException{
        ArrayList<FriendModel> onlineFriends = new ArrayList<FriendModel>();
        ContactList list = Skype.getContactList();
        Friend[] friends = list.getAllFriends();
        for(Friend friend : friends){
            if(friend.getStatus().compareTo(Status.ONLINE) == 0){
                onlineFriends.add(new FriendModel(friend));
            }
        }
        return onlineFriends.toArray(new FriendModel[onlineFriends.size()]);
    }

    @Path("/offline")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public FriendModel[] getOfflineContacts() throws SkypeException{
        ArrayList<FriendModel> offlineFriends = new ArrayList<FriendModel>();
        ContactList list = Skype.getContactList();
        Friend[] friends = list.getAllFriends();
        for(Friend friend : friends){
            if(friend.getStatus().compareTo(Status.ONLINE) != 0){
                offlineFriends.add(new FriendModel(friend));
            }
        }
        return offlineFriends.toArray(new FriendModel[offlineFriends.size()]);
    }
}
package fr.mathieupassenaud.skypeweb;

import java.util.ArrayList;

import javax.ws.rs.DELETE;  
import javax.ws.rs.GET;  
import javax.ws.rs.POST;  
import javax.ws.rs.Path;  
import javax.ws.rs.PathParam;

import com.skype.Call;  
import com.skype.Skype;  
import com.skype.SkypeException;

import fr.mathieupassenaud.skypeweb.model.CallModel;

@Path("/call")
public class CallService {

    @Path("/start")
    @POST
    public CallModel makeCall(String contactId) throws SkypeException{
        Call call = Skype.call(contactId);
        return new CallModel(call);
    }

    @Path("/{callId}/finish")
    @DELETE
    public void hangup(@PathParam("callId") String callId) throws SkypeException{
        Skype.call(callId).finish();
    }

    @Path("/activeCalls")
    @GET
    public CallModel[] getActiveCalls() throws SkypeException{
        ArrayList<CallModel> calls = new ArrayList<CallModel>();
        Call[] c = Skype.getAllActiveCalls();
        for(Call call : c){
            calls.add(new CallModel(call));
        }
        return calls.toArray(new CallModel[calls.size()]);
    }
}

Initial implementation is not fully compliant with Jersey and webservice implementation. It uses only static methods and singletons.

5 endpoints is enought :

On skype, go into settings and "public API"

Authorize X11 and DBUS.

Build a war and run it into a Tomcat Server. Do not run Tomcat from a SSH console or share DBUS variables.

It is running !

https://github.com/mathieupassenaud/skype-remote-control