DataRefTool API

DRT has a search API for 3rd party plugins. With this, other plugins can request a list of commands or datarefs, and perform searches in the same way that a user can in a DRT window.

Example code

An example plugin is provided in src/drt_client/. This plugin queries DRT 5 seconds after the plugin has loaded; it make 5 different searches, writing results out to Log.txt and to some files on the filesystem. Most use cases will match one of the examples in example_queries.c.

Compiling the API

To use DRT's API, copy src/drt_client/drt_client.h and src/drt_client/drt_client.h into your project. They should compile with any C or C++ compiler.

Using the API

To search DRT's list of commands and datarefs, you'll need to do the following:

  1. Write a callback function for handling search results from DRT (see DRTSearchResultCallback)
  2. Put your query parameters in to the DRTSearchParameters structure
  3. Call DRTPerformSearch()
  4. Check the return value of DRTPerformSearch() to ensure that the search was successful

There are several examples of using the API in src/drt_client/example_queries.c.

// This function will be called once for every result.
// Refcon is a value that you provide- you can use this to pass information to the
// callback.
// Name is the name of a dataref or command.
void results_callback(void * refcon, const char * name) {
    ...
}

// An example of how to perform a search
void perform_search() {
    DRTSearchParameters search_params;
    search_params.struct_size = sizeof(DRTSearchParameters);
    search_params.refcon = ...; // You can use this to pass data to your
    search_params.callback = results_callback; // The callback defined above

    // Option flags (see drt_client.h). These flags correspond to the buttons in DRT.
    search_params.flags = 
        (DRT_API_SEARCH_DATAREFS | DRT_API_SEARCH_COMMANDS) |
        DRT_API_SEARCH_TERM_CASE_SENSITIVE | 
        DRT_API_DETECT_CHANGES_NONE |
        DRT_API_SEARCH_TERM_TEXT;

    search_params.search_term = ""; // no search term, so you get all results

    // Perform the search itself
    int search_success = DRTPerformSearch(&search_params);

    // Check the return value.
    switch(search_success) {
        case DRT_SEARCH_RESULT_SUCCESS:
            // yay
            break;
        case DRT_SEARCH_RESULT_PLUGIN_NOT_FOUND:
            // DRT is not installed, or an older version of DRT without the search API
            break;
        case DRT_SEARCH_RESULT_INVALID_PARAMETER:
            // One of the values provided in the DRTSearchParameters structure was invalid
            break;
        default:
            // Another return value; none are currently defined.
            break;
    }
}

Files to add to your project

To use the API, just add the following files to your project:

drt_client.h

Download drt_client.h

#ifndef _DRT_CLIENT_H_
#define _DRT_CLIENT_H_

#ifdef __cplusplus
extern "C" {
#endif

/*
 * DRT search client API
 * This API enables third party plugins to search datarefs using DRT.
 */

/*
 * Search result type
 * When perming a search, indicate whether you want just datarefs, just commands,
 * or both. You need to pass at least one of these flags if you want to get results back.
 */
#define DRT_API_SEARCH_DATAREFS 0x1
#define DRT_API_SEARCH_COMMANDS 0x2

/*
 * Case sensitivity
 * Pass one of these as a flag to indicate if the search term
 * provided is case sensitive or not.
 */
#define DRT_API_SEARCH_TERM_CASE_INSENSITIVE 0x0
#define DRT_API_SEARCH_TERM_CASE_SENSITIVE 0x100

/*
 * Detect changes
 * To see recently-changed datarefs, pass in one of these flags. The behaviour
 * of detecting big changes vs. small changes is defined in the DRT README.
 */
#define DRT_API_DETECT_CHANGES_NONE 0x0
#define DRT_API_DETECT_CHANGES_SMALL 0x200
#define DRT_API_DETECT_CHANGES_LARGE 0x400

/*
 * Regular expression search term
 * To search using a regex search term, pass the DRT_API_REGEX. If you pass this flag
 * but pass an invalid regular expression, the search term will be interpreted as
 * text instead.
 */
#define DRT_API_SEARCH_TERM_TEXT 0x0
#define DRT_API_SEARCH_TERM_REGEX 0x800

/*
 * Search result callback
 * When perfoming a search, this function is called once for each search result.
 *
 * refcon is a user-provided pointer provided in the DRTSearchParameters structure;
 * you can use this to pass your application's data to the callback function.
 * 
 * ref_name is the name of the command or dataref.
 */
typedef void (* DRTSearchResultCallback)(void * refcon, const char * ref_name);

/* Search parameters for the requested search */
typedef struct DRTSearchParameters_ {
    /* Set this equal to the struct size */
    int struct_size;

    /* Flags to set search options */
    int flags;

    /* Optional user-defined data to pass to the callback */
    void * refcon;

    /* Callback function, called for each search result. If set to
     * nullptr, only the number of results will be returned via the
     * result_count field.
     */
    DRTSearchResultCallback callback;

    /* Search term. Must be a valid null-terminated string. Multiple
     * search terms can be separated by spaces, just as in DRT.
     */
    const char * search_term;

    /* Output- this is the number of search results */
    int result_count;
} DRTSearchParameters;

/* Search return values */

/* Indicates success- a search was performed */
#define DRT_SEARCH_RESULT_SUCCESS 0

/* The DRT plugin couldn't be found, or is too old to support the search API */
#define DRT_SEARCH_RESULT_PLUGIN_NOT_FOUND -1

/* A search was no perfomed as the struct passed in was invalid */
#define DRT_SEARCH_RESULT_INVALID_PARAMETER -2

/* Perform a search. */
int DRTPerformSearch(DRTSearchParameters * search_parameters);

#ifdef __cplusplus
}
#endif

#endif /* _DRT_CLIENT_H_ */

drt_client.c

Download drt_client.c

#include "drt_client.h"

#include <XPLMPlugin.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * This message ID is sent to DRT to perform a search.
 * This value is simply "DRT SRCH" in ASCII.
 */
#define DRT_API_SEARCH_MESSAGE 0x44525453


const char * const dre_signature = "xplanesdk.examples.DataRefEditor";
const char * const drt_signature = "com.leecbaker.datareftool";

int DRTPerformSearch(DRTSearchParameters * search_parameters) {
    search_parameters->result_count = 0;

    /* Find the DRT plugin's ID */
    XPLMPluginID drt_plugin_id = XPLMFindPluginBySignature(drt_signature);

    if(XPLM_NO_PLUGIN_ID == drt_plugin_id) {
        /* DRT plugin not found- maybe it's in DRE emulation mode? */
        drt_plugin_id = XPLMFindPluginBySignature(dre_signature);
    }

    /* If no plugin was found, we're done */
    if(XPLM_NO_PLUGIN_ID == drt_plugin_id) {
        return DRT_SEARCH_RESULT_PLUGIN_NOT_FOUND;
    }

    /* 
     * Before searching, we seed the result count (which is used to return errors)
     * with DRT_SEARCH_RESULT_PLUGIN_NOT_FOUND. This way, if the message is not handled,
     * we will get a response saying that the plugin wasn't found. If the message is handled,
     * we'll get the result count back.
    */
   search_parameters->result_count = DRT_SEARCH_RESULT_PLUGIN_NOT_FOUND;

    /* Perform the search */
    XPLMSendMessageToPlugin(drt_plugin_id, DRT_API_SEARCH_MESSAGE, search_parameters);

    /*
     * DRT may send back an error code in the result count. This is a negative
     * number.
     */
    if(search_parameters->result_count < 0) {
        int error_code = search_parameters->result_count;
        search_parameters->result_count = 0;
        return error_code;
    }

    return DRT_SEARCH_RESULT_SUCCESS;
}

#ifdef __cplusplus
}
#endif