Mettre à jour la médiathèque de Kodi

Kodi est un lecteur multimédia libre. Je l’utilise à partir de LibreELEC sur un Raspberry Pi. Au moment d’écrire ces lignes, la version 9 (Leia) est la plus récente. J’ai configuré Kodi pour aller lire des fichiers vidéos sur un ordinateur sur mon réseau par SMB. Donc, il arrive que j’ajoute des fichiers sur ce disque et que je doive mettre à jour manuellement Kodi pour afficher ces nouveaux fichiers. Dans cet article nous allons voir comment provoquer la mise à jour automatiquement à partir d’une application codée avec C++Builder.

Un collègue au travail m’a parlé que Kodi possède un API qui permet d’effectuer plusieurs tâches. Il l’utilise lui-même dans un logiciel de sa conception. Il m’a dit que Kodi Leia avait brisé une des fonctionnalités qu’il utilise. L’API HTTP ne fonctionnait plus pour mettre à jour la médiathèque. Effectivement, sur le Wiki de Kodi on peux y lire le texte suivant.

HTTP (does not work in v18 Leia)

Pour remédier à cette situation il a décidé d’invoquer l’application curl. En général je n’aime pas que mes applications aient des dépendances externes. J’ai donc creusé un peu pour comprendre comment mieux faire cette action.

Tout d’abord avant de débuter il faut activer l’option Autoriser le contrôle à distance via HTTP.

Kodi: Autoriser le contrôle à distance via HTTP

Dans l’image j’ai encerclé où se trouve le port que vous allez devoir utiliser.

Avant d’utiliser mon propre code, je vais tester la fonctionnalité. Sur la page HOW-TO:Remotely update library on y trouve une commande curl que je vais utiliser dans une fenêtre de terminal.

curl --data-binary '{"jsonrpc": "2.0", "method": "VideoLibrary.Scan", "id": "mybash"}' -H 'content-type: application/json;' http://libreelec:8080/jsonrpc

Voici la réponse que j’obtiens.

{"id":"mybash","jsonrpc":"2.0","result":"OK"}

Cette commande fonctionne bien, donc on ne devrait pas avoir de problème à communiquer avec Kodi. Une chose intéressante que l’on peut voir est qu’elle utilise l’étiquette jsonrpc. En cherchant un peu on comprend que Kodi à commencer à migrer de l’API HTTP vers un API JSON-RPC. Voici ce que la documentation dit à ce sujet.

JSON-RPC is a HTTP- and/or raw TCP socket-based interface for communicating with Kodi. It replaces the deprecated HTTP API, and offers a more secure and robust mechanism in the same format.

Voilà maintenant ce qui explique que l’API HTTP ne fonctionne pas complètement sur Leia.

Maintenant que l’on sait quoi faire, débutons l’application. La première étape est de créer un nouveau projet FireMonkey. Dans la Form il faut insérer un TIdHTTP et un contrôle TButton.

Étant donnée que JSON sera utilisé, il faut ajouter cette ligne à votre fichier d’en-tête.

#include <System.JSON.hpp>

J’ai décidé de faire une petite classe minimaliste pour supporter JSON-RPC. Voici un autre bout de code à ajouter dans le fichier d’en-tête.

class TJsonRpc
{
public:
    __fastcall TJsonRpc() : Version("2.0") {}
    inline virtual __fastcall ~TJsonRpc() {}

    String Version;
    String Method;
    String Id;

    String __fastcall ToString()
    {
        TJSONObject* Obj = new TJSONObject();
        Obj->AddPair("jsonrpc", Version);
        Obj->AddPair("method", Method);
        Obj->AddPair("id", Id);
        TJSONObject* Params = new TJSONObject();
        Obj->AddPair("params", Params);
        const String Result = Obj->ToString();
        delete Obj;
        return Result;
    }
};

Finalement, il faut mettre ce code dans l’évènement OnClick du bouton.

    IdHTTP1->Request->ContentType = "application/json";

    TJsonRpc LJsonRpc;
    LJsonRpc.Method = "VideoLibrary.Scan";
    LJsonRpc.Id = "mybash";

    const String LUrl =  "http://libreelec:8080/jsonrpc";

    TStringStream* LData = NULL;
    try
    {
        LData = new TStringStream(LJsonRpc.ToString());

        const String LAnswer = IdHTTP1->Post(LUrl, LData);

        TJSONObject* Obj = static_cast<TJSONObject*>(TJSONObject::ParseJSONValue(LAnswer));
        try
        {
            TJSONPair* Pair;
            if((Pair = Obj->Get("error")) != NULL)
            {
                String LMessage;
                int LCode;
                TJSONObject* ErrorObj = static_cast<TJSONObject*>(Pair->JsonValue);
                if((Pair = ErrorObj->Get("message")) != NULL)
                {
                    TJSONString* Answer = static_cast<TJSONString*>(Pair->JsonValue);
                    LMessage = AnsiDequotedStr(Answer->ToString(), '\"');
                }
                if((Pair = ErrorObj->Get("code")) != NULL)
                {
                    TJSONNumber* Answer = static_cast<TJSONNumber*>(Pair->JsonValue);
                    LCode = Answer->AsInt;
                }
                throw Sysutils::Exception("Erreur " + String(LCode) + ": " + LMessage);
            }
        }
        __finally
        {
            delete Obj;
        }
    }
    __finally
    {
        delete LData;
    }

Même si je gère les erreurs d’API, il ne s’agit pas de code de production. Je ne vérifie pas que le ID de retour correspond à celui envoyé. Au lieu de tout mettre dans un évènement de bouton on aurait mieux fait de mettre dans une méthode séparée. On aurait pu aussi gérer la communication dans un thread séparé pour ne pas bloquer l’interface. Mais bon… l’idée c’était de montrer que la meilleure manière de communiquer avec Kodi est l’utilisation de JSON-RPC par HTTP.

J’espère que cet article vous sera utile.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*