jami-docs

Forked version of Jami documentation, see wrycode.com/jami-docs-demo
git clone git://git.wrycode.com/wrycode/jami-docs.git
Log | Files | Refs

create-a-plugin.rst (26309B)


      1 Creating Plugins
      2 ================
      3 
      4 **NOTE: this page introduces the Jami Plugins SDK.**
      5 
      6 As from September of 2020, Jami team has added plugins as a call feature
      7 for GNU/Linux, Windows, and Android users. This meaning that now you can
      8 personalize your call and chat experience by using one of our available
      9 plugins. But that is not all, you can also transform your awesome ideas
     10 into a brand new plugin!
     11 
     12 Here you will be guided throught the SDK that will help you start your
     13 plugin developpment. The text is organized as: \* A description of our
     14 `#SDK <#sdk>`__; \* An example of how to create your own base plugin
     15 with our SDK - `#Create my first plugin <#create-my-first-plugin>`__.
     16 
     17 SDK
     18 ---
     19 
     20 We developped a Plugin System for Jami and we have a few plugins
     21 available to be used. However as an open source project, we now desire
     22 users to be able to create, use, and distribute their own plugins. To
     23 achieve that goal, we also developped a Jami Plugins SDK. This kit is
     24 fully writen in python, and can be invoked running pluginMainSDK.py from
     25 ``<plugins>`` folder. To get started you must:
     26 
     27 .. code:: bash
     28 
     29    mkdir jami-plugins && cd jami-plugins
     30    git clone https://review.jami.net/ring-daemon daemon
     31    git clone https://review.jami.net/jami-plugins plugins
     32    cd plugins
     33    pip3 install -r SDK/requirements.txt
     34    python3 SDK/pluginMainSDK.py
     35 
     36 You will notice that this script will generate a Jami Plugins SDK shell
     37 that allows users to:
     38 
     39 -  `Create full plugin skeleton <#create-full-plugin-skeleton>`__;
     40 -  `Create, modify or delete a
     41    manifest.json <#create-modify-or-delete-manifest-json>`__;
     42 -  `Create a package.json <#create-a-package-json>`__;
     43 -  `Create or delete a preference <#create-or-delete-a-preference>`__;
     44 -  `Create functionality <#create-functionality>`__;
     45 -  `Create main <#create-main>`__;
     46 -  `Assemble files <#assemble-files>`__;
     47 -  `Build <#build>`__;
     48 -  `Merge jpls <#merge-jpls>`__.
     49 
     50 Each one of these functionalities will be detailled next. We also will
     51 explain the importance of the files it generates and any related SDK
     52 limitations.
     53 
     54 Create full plugin skeleton
     55 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
     56 
     57 This option performs a sequence of actions to properly create all base
     58 files needed to start a plugin development. The steps are:
     59 
     60 1. gather authorship information;
     61 2. define a plugin name;
     62 3. create manifest;
     63 4. create functionalities and preferences;
     64 5. create main file;
     65 6. define basic package.json;
     66 7. define basic build files (build.sh and CMakeLists.txt).
     67 
     68 If all is completed successfully, the plugin may be build, installed,
     69 and loaded. Also the functionallities may be toggled, however, since
     70 their data processes are not implemented, they will perform no action.
     71 In our ``HelloWorld`` plugin, we implement a simple process using
     72 **OpenCV**. For more complex options, you can refer to our available
     73 plugins at
     74 `jami-plugins <https://git.jami.net/savoirfairelinux/jami-plugins>`__.
     75 Feel free to implement any ideas you may have, but you should respect
     76 those constrains: \* use ffmpeg, opencv, and onnx from ring-daemon
     77 project; \* if using tensorflow, choose version 2.1.0. Why? \* We have
     78 all needed header files of tensorflow 2.1.0 in /contrib/libs.tar.gz; \*
     79 We provide docker images with libraries for Tensorflow C++ API and
     80 Tensorflow Lite, for both Android and Linux development. \* if you need
     81 other libraries, check if we support it’s build with ring-daemon
     82 project, otherwise, you will have to build it and ensure correct link to
     83 the plugin libraries.
     84 
     85 To fully create a basic plugin with pre-implementation of desired
     86 functionalities APIs, preferences, package, manifest, main file, and
     87 basic build related files, from inside Jami Plugins SDK shell, the user
     88 must call:
     89 
     90 ::
     91 
     92    (Jami Plugins SDK) plugin
     93 
     94 The SDK will ask other informations needed to correctly accomplish the
     95 task.
     96 
     97 Create, modify or delete manifest.json
     98 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     99 
    100 Every plugin must have a manifest. This file contains the official name,
    101 a description, and carries the plugin build version as in the example
    102 bellow. Without it, the plugin system will not be able to find the
    103 plugin library it should load. Due to it’s importance, every time Jami
    104 Plugin SDK is told to create files to a non existing plugin or to a
    105 plugin with no manifest, it will first create a new manifest.
    106 
    107 .. code:: bash
    108 
    109    {
    110        "name": "HelloWorld",
    111        "description" : "HelloWorld plugin will guide you throught Jami Plugins SDK use!",
    112        "version" : "1.0.0"
    113    }
    114 
    115 To create/modify (or to delete) a manifest.json, from inside Jami
    116 Plugins SDK shell, the user must call:
    117 
    118 ::
    119 
    120    (Jami Plugins SDK) manifest (-del)
    121 
    122 The SDK will ask other informations needed to correctly accomplish the
    123 task.
    124 
    125 Create a package.json
    126 ~~~~~~~~~~~~~~~~~~~~~
    127 
    128 Jami currently supports plugins for GNU/Linux, Android and Windows. For
    129 the latter, the build system used is the same as for Jami, it is, we
    130 call the plugin build using a python script. This script will look for a
    131 ``package.json`` file to aquire build informations and commands. Without
    132 this file our build pipeline for Windows will not work.
    133 
    134 An example package.json file is shown bellow. \* ``name`` and
    135 ``version`` in the package.json and manifest.json files should match. \*
    136 ``extractLibs`` indicates to the build system if the files under
    137 ``<jami-plugins>/contrib/libs.tar.gz`` will be used. This archive
    138 contains header files for **Tensorflow**. Thus, you only need to set
    139 ``extractLibs`` to true if you plan to use this library. \* To play with
    140 audio or video, the plugin is dependent of **ffmpeg**. By adding it to
    141 ``deps``, the build system will automatically compile this library from
    142 ``<ring-daemon>/contrib`` if needed. We also provide **OpenCV** build
    143 from inside ``<ring-daemon>/contrib`` ! If you want to use Tensorflow,
    144 we provide built libraries for GNU/Linux and Android with our docker
    145 images
    146 `here <https://hub.docker.com/repository/docker/sflagsantos/tensorflow-cuda>`__
    147 and
    148 `here <https://hub.docker.com/repository/docker/sflagsantos/tensorflowlite>`__.
    149 For more information about OpenCV and Tensorflow build, please refer to
    150 `jami-plugins <plugins>`__ technical documentation. There we have a
    151 step-by-step! \* If you’re using cmake, your can set configuration
    152 definition in ``defines`` property. Exemple: if your configuration line
    153 is of the form ``cmake -DCPU=TRUE ..`` you may set
    154 ``"defines": ["CPU=TRUE"]``. \* Any command directly related to the
    155 plugin build can be defined inside ``custom_scripts``. Bellow we create
    156 the build folder to with the plugins project will be configured with
    157 ``mkdir msvc`` and we also set the build command as
    158 ``cmake --build ./msvc --config Release``. Our example CMakeLists.txt
    159 may have pre and post build instruction that are not listed here.
    160 
    161 .. code:: bash
    162 
    163    {
    164        "name": "Hello World",
    165        "version": "1.0.0",
    166        "extractLibs": false,
    167        "deps": [
    168            "ffmpeg"
    169        ],
    170        "defines": [],
    171        "custom_scripts": {
    172            "pre_build": [
    173                "mkdir msvc"
    174            ],
    175            "build": [
    176                "cmake --build ./msvc --config Release"
    177                ],
    178            "post_build": []
    179        }
    180    }
    181 
    182 To create a package.json, from inside Jami Plugins SDK shell, the user
    183 must call:
    184 
    185 ::
    186 
    187    (Jami Plugins SDK) package
    188 
    189 The SDK will ask other informations needed to correctly accomplish the
    190 task. After the base package.json creation, the user must add or modify
    191 any information not previewed by the SDK process.
    192 
    193 Create or delete a preference
    194 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    195 
    196 A preference is a internal variable that will be used upon loading or
    197 while running the plugin. There is limited types of preferences
    198 supported by the plugin system and each of them must contain generic and
    199 specific informations. Those informations must be placed under a certain
    200 structure that will form one preference and each preference must be
    201 listed inside a ``preference.json`` file.
    202 
    203 The generic properties of a preference are those that must be set by any
    204 type of preference: ``category``, ``type``, ``key``, ``title``,
    205 ``summary``, ``defaultValue``, and ``scope``. The specific ones are
    206 linked to the type of the preference constructed. For ``EDITTEXT``
    207 preferences there is no other property to be set. For ``PATH``
    208 preferences we have: ``mimeType``. For ``LIST`` preferences we have:
    209 ``entries`` and ``entryValues``. A ``LIST`` preference must have a list
    210 of possible values to be used and a list of ‘names’ for these values.
    211 For example: If you have two ``entriesValues``: ‘0’ and ‘1’, these
    212 values may not be understandable by the user. Jami’s UI will take the
    213 values from ``entries`` to be shown as ‘names’ for each one of these
    214 ``entryValues``. Then you can call ‘0’ and ‘1’ as ‘sent’ and ‘received’.
    215 The UI will show these names that are more user friendly! It is
    216 important to note that ``entries`` and ``entryValues`` must have the
    217 same number of items.
    218 
    219 Another important point to be noted for the preferences is that their
    220 values could be modified during runtime if, and only if, two conditions
    221 are satisfied:
    222 
    223 1. the code that applies the new value is within your functionality
    224    implementation and;
    225 2. this functionality is listed in the preference’s ``scope`` property.
    226 
    227 To better explain, we have to detail what is a scope and how a
    228 preference changement is implemented inside the plugin.
    229 
    230 -  **Scope**: A scope is a list of functionalities that can modify a
    231    preference value even if the functionality is under use. It is,
    232    imagine you have a functionality called “Circle” that prints a
    233    colored circle to your video. Consider also that the color of that
    234    circle is set by a preference and that this preference lists “Circle”
    235    as one of it’s scopes. In that scenario “Circle” will be able to
    236    modify the default circle color to another one.
    237 -  **Code implementation**: Continuing our example above, “Circle” also
    238    is the implementation of an abstract API class from Daemon (for more
    239    details check `#Create functionality <#create-functionality>`__. When
    240    a user changes a preference value, the plugin system will call the
    241    ``setPreferenceAttribute`` implementation for each of the
    242    functionalities listed by the preference’s scope. By it’s turn, this
    243    function will match the preference unique ``key`` and call an
    244    internal function to apply the new value.
    245 
    246 For a pratical example, you can check the ‘Foreground Segmentation’
    247 functionality of the GreenScreen plugin -
    248 `pluginMediaHandler.cpp <https://git.jami.net/savoirfairelinux/jami-plugins/blob/master/GreenScreen/pluginMediaHandler.cpp>`__
    249 and
    250 `preferences-onnx.json <https://git.jami.net/savoirfairelinux/jami-plugins/blob/master/GreenScreen/preferences-onnx.json>`__.
    251 This plugin has both ``LIST`` and ``PATH`` preferences and also has one
    252 preference that can be modified during runtime. Can you tell wich one?
    253 
    254 To create (or delete) a preference, from inside Jami Plugins SDK shell,
    255 the user must call:
    256 
    257 ::
    258 
    259    (Jami Plugins SDK) preference (-del)
    260 
    261 The SDK will ask other informations needed to correctly accomplish the
    262 task. If a preference is created from outside a functionality creation
    263 pipeline, any API implementation will not be changed in order to avoid
    264 overwrittings. Thus, if you want to allow values changement during
    265 runtime, you may need to manually modify your functionality
    266 implementation to fit running time changements conditions.
    267 
    268 Create functionality
    269 ~~~~~~~~~~~~~~~~~~~~
    270 
    271 A Jami plugin may wrap one or multiple functionalities. It is, the same
    272 plugins may have a functionality to change background and to draw a
    273 circle to a video for example. Each functionality must implement an
    274 abstract API class defined by Jami plugins System. That way, we can say
    275 that one functionality is one implementation of an API. Currently we
    276 have the ``MediaHandler`` which allows access to audio or video frames
    277 and we have ``ChatHandler`` which allows acces to messages exchanged in
    278 a conversation.
    279 
    280 When defining a new a functionality, the SDK will create basic header
    281 and cpp files for you work on. However, your new functionality can not
    282 be added to the scopes of a previously existing preference. For more
    283 information, please refer to `Create or delete a
    284 preference <#create-or-delete-a-preference>`__.
    285 
    286 To create a functionality, from inside Jami Plugins SDK shell, the user
    287 must call:
    288 
    289 ::
    290 
    291    (Jami Plugins SDK) functionality
    292 
    293 The SDK will ask other informations needed to correctly accomplish the
    294 task.
    295 
    296 Create main
    297 ~~~~~~~~~~~
    298 
    299 This option create plugin’s ``main.cpp``. A file that implements the
    300 plugin external loading function that Jami Plugin System will call to
    301 initialize and register all functionalities for latter use.
    302 
    303 The SDK is set to rewrite the main file every time you create a new
    304 functionality. Thus, if you want to manually create or delete a
    305 functionality, we recomend calling this option instead.
    306 
    307 To create a ``main.cpp``, from inside Jami Plugins SDK shell, the user
    308 must call:
    309 
    310 ::
    311 
    312    (Jami Plugins SDK) main
    313 
    314 The SDK will ask other informations needed to correctly accomplish the
    315 task.
    316 
    317 Assemble files
    318 ~~~~~~~~~~~~~~
    319 
    320 The final plugin file is an archive compressed to a ``JPL`` format. This
    321 archive contains libraries, manifest.json, preferences.json, icons and
    322 other custom important files for your plugin. OBS.: files added by the
    323 developper must be organized under the ``data/`` folder.
    324 
    325 The SDK assemble option has two different behaviours:
    326 
    327 -  it creates a build folder and copies there all files that will be
    328    compressed to the final plugin archive. For linux host:
    329    ``<plugins>/<HelloWorld>/build-local/jpl/`` and for a windows host:
    330    ``<plugins>/<HelloWorld>/msvc/jpl/``;
    331 -  it compresses all files inside the build folder to the jpl archive
    332    wich is output under ``<plugins>/build``.
    333 
    334 Both process should be called from inside the CMakeLists.txt as
    335 POST_BUILD and PRE_BUILD commands, respectively. Also, the build.sh
    336 script should call them. For more information about CMakeLists.txt and
    337 build.sh files, please refere to `build <#build>`__ and to our available
    338 plugins at
    339 `jami-plugins <https://git.jami.net/savoirfairelinux/jami-plugins>`__.
    340 
    341 To create a build folder and copy all important files there, from inside
    342 Jami Plugins SDK shell, the user must call:
    343 
    344 ::
    345 
    346    (Jami Plugins SDK) assemble -pre
    347 
    348 To compress all assembled to a jpl archive, from inside Jami Plugins SDK
    349 shell, the user must call:
    350 
    351 ::
    352 
    353    (Jami Plugins SDK) assemble
    354 
    355 The SDK will ask other informations needed to correctly accomplish the
    356 task.
    357 
    358 Build
    359 ~~~~~
    360 
    361 The SDK build option has two different behaviours:
    362 
    363 -  it creates basic CMakeLists.txt and buils.sh files;
    364 -  it build the plugin library with default options defined at the files
    365    mentioned above.
    366 
    367 A description of thes CMakeLists.txt and buils.sh files are found
    368 further in this section.
    369 
    370 To create basic CMakeLists.txt and buils.sh files, from inside Jami
    371 Plugins SDK shell, the user must call:
    372 
    373 ::
    374 
    375    (Jami Plugins SDK) build -def
    376 
    377 To build plugin library with default configuration, from inside Jami
    378 Plugins SDK shell, the user must call:
    379 
    380 ::
    381 
    382    (Jami Plugins SDK) build
    383 
    384 The SDK will ask other informations needed to correctly accomplish the
    385 task. For the moment, the build option does not support
    386 cross-compilation neither non default builds. If you have build
    387 variables to be set differently than the default option, please directly
    388 use the ``<plugins>/build-plugin.py`` script.
    389 
    390 CMakeLists.txt
    391 ^^^^^^^^^^^^^^
    392 
    393 This file is used only by Jami’s Windows build pipeline.
    394 
    395 If you need to pass any defines to cmake generation, your definitions
    396 can be in ``package.json`` as explained in the package section. The
    397 package.json created specifies the default configuration that calling
    398 the build from Jami Plugins SDK will consider. If you want to build with
    399 no default configuration, you can: directly use the script mentioned
    400 above and pass non-default definitions as an argument or; you also can
    401 manually change your package.json file. For examples, you can refer to
    402 our available plugins at
    403 `jami-plugins <https://git.jami.net/savoirfairelinux/jami-plugins>`__.
    404 
    405 Another important information about CMakeLists.txt is that it has to add
    406 custom commands. For PRE_BUILD, it must call the pre-assemble
    407 functionality process. For POST_BUILD, it must copy the built library to
    408 the build folder and call the assemble functionality process. In the
    409 end, your jpl archive may be found under ``<plugins>/build``. The
    410 CMakeLists.txt file automatically created by our SDK, already respects
    411 these constraints.
    412 
    413 build.sh
    414 ^^^^^^^^
    415 
    416 This file is used by Jami to build plugins for GNU/Linux and Android
    417 platforms.
    418 
    419 The basic script consider the environment variable ``DAEMON`` that must
    420 point to the ring-daemon folder. Besides, you can pass an argument for
    421 the platform used like ``-t android`` if you want to cross-compile for
    422 Android. Further custom definitions and environment variables should be
    423 handled by the plugin developper. If you want to build with no default
    424 configuration, you can modify the environment variables values and then
    425 call the build. Ie: for android, you can set which ABI you want to build
    426 with ``export ANDROID_ABI="arm64-v8a armeabi-v7a``. For other examples,
    427 you can refer to our `technical
    428 documentation <https://git.jami.net/savoirfairelinux/ring-project/wikis/technical/7.-Jami-plugins>`__
    429 and to our `available
    430 plugins <https://git.jami.net/savoirfairelinux/jami-plugins>`__.
    431 
    432 Another important information about build.sh is that it has to call pre
    433 and post assemble. Before the build, it must call the pre-assemble
    434 functionality process. After it, it must copy the built library to the
    435 build folder and call the assemble functionality process. In the end,
    436 your jpl archive may be found under ``<plugins>/build``. The build.sh
    437 file automatically created by our SDK, already respects these
    438 constraints.
    439 
    440 Merge jpls
    441 ~~~~~~~~~~
    442 
    443 If you have more than one jpl archives, like one build for Android and
    444 anothe for GNU/Linux platforms, you can merge them into one to easy it’s
    445 distribution. However, you should know that merging two or more jpls may
    446 inccur orverwritting some of the files inside them if they are not equal
    447 for all archives. The only files that may not present conflicting
    448 contents are the ones that do not repeate themselves. If conflicts
    449 occur, files from the first jpl in the arguments will prevail over the
    450 others.
    451 
    452 To merge two or more jpls, from inside Jami Plugins SDK shell, the user
    453 must simple call:
    454 
    455 ::
    456 
    457    (Jami Plugins SDK) merge
    458 
    459 The SDK will ask other informations needed to correctly accomplish the
    460 task.
    461 
    462 Create my first plugin
    463 ----------------------
    464 
    465 Through this section we will present a step-by-step construction of a
    466 ``HelloWorld`` plugin using our SDK. Our goal is to print a coloured
    467 circle in the midle of the video frames using **OpenCV**. The color of
    468 that circle will be defined by a preference which will be changeable
    469 during runtime. Also we can set a stream preferece to define if the
    470 plugin will modify the video sent or the one received, this time we
    471 don’t want to allow a changement during runtime. We can define a second
    472 functionality that will aways draw a circle in the right top corner,
    473 with the color defined by the same preference as the previous
    474 functionality but that cannot be changed during runtime. At the end we
    475 will exemplify how to build your plugin with and without the SDK.
    476 
    477 Step 1 - prepare developpment environment
    478 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    479 
    480 The first step towards plugin development is to properly prepare the
    481 environment.
    482 
    483 .. code:: bash
    484 
    485    mkdir jami-plugins && cd jami-plugins
    486    git clone https://review.jami.net/ring-daemon daemon
    487    git clone https://review.jami.net/jami-plugins plugins
    488    cd plugins
    489    pip3 install -r SDK/requirements.txt
    490 
    491 Step 2 - create HelloWorld with one functionality
    492 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    493 
    494 -  Use Jami Plugins SDK to create the plugin skeleton
    495 
    496 .. code:: python
    497 
    498    python3 SDK/pluginMainSDK.py
    499 
    500 ..
    501 
    502    (Jami Plugins SDK) plugin
    503 
    504    Tell us who you are?
    505 
    506 ..
    507 
    508    What’s your name? Aline Gondim Santos
    509 
    510    What’s your e-mail? aline.gondimsantos@savoirfairelinux.com
    511 
    512 ..
    513 
    514    Leave Empty or Press ‘q’ to quit this option.
    515 
    516    Now, you need to tell how you want yout plugin to be called.
    517 
    518 ..
    519 
    520    Choose a cool name for your plugin: Hello World
    521 
    522    Nice! Your HelloWorld will be awesome!
    523 
    524 ..
    525 
    526    Defining a manifest for “HelloWorld” plugin, we gonna need more
    527    information..
    528 
    529    Press ‘q’ to quit this option.
    530 
    531 ..
    532 
    533    Tell us a description: HelloWorld draws a circle in the center of a
    534    call’s video
    535 
    536    Version must be of the form X.Y.Z Set plugin version (default 0.0.0):
    537    1.0.0
    538 
    539 ..
    540 
    541    Chose a functionality name: CenterCircle
    542 
    543    Choose a API for functionality “CenterCircle”.
    544 
    545 ..
    546 
    547    Available APIs: (1) video during a call (Media Handler API) (2) audio
    548    during a call (Media Handler API) (3) chat messages (Chat Handler
    549    API) For more information about the API, call help preferences.
    550 
    551    Enter a data type number: 1
    552 
    553 ..
    554 
    555    Add another functionaliy? [y/N]
    556 
    557    Would you like to add a preference? [y/n] y
    558 
    559 ..
    560 
    561    Your preferences options available are: (0) List; (1) Path; (2)
    562    EditText;
    563 
    564    Which preference type do you choose: 0 Type a value for category:
    565    stream Type a value for key: videostream Type a value for title:
    566    Video stream Type a value for summary: select a video direction Type
    567    a value for defaultValue: 0
    568 
    569 ..
    570 
    571    Would you like to add a scope? [y/n] n
    572 
    573    Do you want to add a new entry Value? [y/n] y Type one new entry: 0
    574 
    575 ..
    576 
    577    Do you want to add a new entry Value? [y/n] y Type one new entry: 1
    578 
    579    Do you want to add a new entry Value? [y/n] n Type an entry name for
    580    ‘0’: sent Type an entry name for ‘1’: received
    581 
    582 ..
    583 
    584    Would you like to add a preference? [y/n] y
    585 
    586    Your preferences options available are: (0) List; (1) Path; (3)
    587    EditText;
    588 
    589 ..
    590 
    591    Which preference type do you choose: 0 Type a value for category:
    592    color Type a value for key: color Type a value for title: Circle
    593    color Type a value for summary: select a color Type a value for
    594    defaultValue: ##00FF00
    595 
    596    Would you like to add a scope? [y/n] y
    597 
    598 ..
    599 
    600    Possible values for scope: (0) centerCircle;
    601 
    602    Which scope do you choose: 0
    603 
    604 ..
    605 
    606    Do you want to add a new entry Value? [y/n] y Type one new entry:
    607    #0000FF
    608 
    609    Do you want to add a new entry Value? [y/n] y Type one new entry:
    610    #00FF00
    611 
    612 ..
    613 
    614    Do you want to add a new entry Value? [y/n] y Type one new entry:
    615    #FF0000
    616 
    617    Do you want to add a new entry Value? [y/n] n Type an entry name for
    618    ‘#0000FF’: blue Type an entry name for ‘#00FF00’: green Type an entry
    619    name for ‘#FF0000’: red
    620 
    621 ..
    622 
    623    Would you like to add a preference? [y/n] n
    624 
    625    The preference Circle color will be changeable during running time
    626    for centerCircle functionality? [y/n] y
    627 
    628 ..
    629 
    630    Package ok.
    631 
    632    CMakeLists.txt and build.sh ok.
    633 
    634 -  modify CenterCircleMediaHandler.cpp, CenterCircleVideoSubscriver.h,
    635    CenterCircleVideoSubscriber.cpp;
    636 -  You will need to modify package.json, CMakeLists.txt and build.sh to
    637    add OpenCV dependencies.
    638 
    639 All final files can be found
    640 `here <https://git.jami.net/savoirfairelinux/jami-plugins>`__
    641 
    642 Step 3 - build
    643 ~~~~~~~~~~~~~~
    644 
    645 Before building the HelloWorld, you should compile ffmpeg and OpenCV
    646 dependencies. This can be achieved by following the build instructions
    647 for OpenCV `here <plugins>`__. Ffmpeg will be automatically build if you
    648 follow those instructions. To build you plugin, you can either: \* Call
    649 the build from Jami Plugins SDK (works for GNU/Linux and Windows):
    650 
    651 .. code:: python
    652 
    653    python3 SDK/pluginMainSDK.py
    654 
    655 ..
    656 
    657    (Jami Plugins SDK) build
    658 
    659    Leave Empty or Press ‘q’ to quit this option.
    660 
    661 ..
    662 
    663    Plugin to pass build related step: HelloWorld
    664 
    665    DAEMON not provided, building with ./../../daemon
    666 
    667 -  Call plugin-build.py script (works for GNU/Linux, Windows and
    668    Android):
    669 
    670 -  GNU/Linux or Windows: > python3 build-plugin.py –projects=HelloWorld
    671 
    672 -  Android: > python3 build-plugin.py –projects=HelloWorld
    673    –distribution=android
    674 
    675 OBS: For Android, you can set ``ANDROID_ABI`` environment variable to
    676 the ABI you want to build. Currently Jami supports ``x86_64``,
    677 ``armeabi-v7a``, and ``arm64-v8a``. Plugins will be build for the three
    678 options by default.
    679 
    680 Step 4 - create another functionality for HelloWorld and rebuild
    681 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    682 
    683 Now that you tested and your HelloWorld is working, you can try to do
    684 add another functionality to it.
    685 
    686 .. code:: python
    687 
    688    python3 SDK/pluginMainSDK.py
    689 
    690 ..
    691 
    692    (Jami Plugins SDK) functionality
    693 
    694    Tell us who you are?
    695 
    696 ..
    697 
    698    What’s your name? Aline Gondim Santos
    699 
    700    What’s your e-mail? aline.gondimsantos@savoirfairelinux.com
    701 
    702 ..
    703 
    704    Leave Empty or Press ‘q’ to quit this option.
    705 
    706    Plugin to be modified or created: HelloWorld
    707 
    708 ..
    709 
    710    Chose a functionality name: CoinCircle
    711 
    712    Choose a API for functionality “CoinCircle”.
    713 
    714 ..
    715 
    716    Available APIs: (1) video during a call (Media Handler API) (2) audio
    717    during a call (Media Handler API) (3) chat messages (Chat Handler
    718    API) For more information about the API, call help preferences.
    719 
    720    Enter a data type number: 1
    721 
    722 ..
    723 
    724    Add another functionaliy? [y/N] n
    725 
    726    Would you like to add a preference? [y/n] n
    727 
    728 ..
    729 
    730    CMakeLists.txt and build.sh ok.
    731 
    732 Again, all code modifications are available
    733 `here <https://git.jami.net/savoirfairelinux/jami-plugins>`__
    734 
    735 Optionally, you can change your plugin version and description:
    736 
    737 .. code:: python
    738 
    739    python3 SDK/pluginMainSDK.py
    740 
    741 ..
    742 
    743    (Jami Plugins SDK) manifest Leave Empty or Press ‘q’ to quit this
    744    option.
    745 
    746    Plugin to be modified or created: HelloWorld New description for your
    747    plugin (ignore to keep previous description): HelloWorld can draw a
    748    circle at the center or at the top-left of a call’s video New plugin
    749    version (ignore to keep previous version): 2.0
    750 
    751 Finally, you can rebuild the plugin using the same steps as before!
    752 
    753 Now you can start your own creations! Do not forget to tag Jami or
    754 Savoir-Faire Linux in your repository, this way we can get to know how
    755 the community is developping their own plugins!