Skip to content

File Format Specification

Ivan Zlatev edited this page Oct 19, 2014 · 14 revisions

Version History

  • Version 1 (19 October 2014)
  • First write-up
  • File Structure complete
  • 95% of field meanings known
  • Unknown things are named explicitly named "Unknown"

Example Source Code (Reference Implementation)

There is no reference implementation, yet...

File Structure Overview

Structure definitions

Make sure to check out the Setting up guide to understand how to use those:

[View Structure Definitions File] (https://github.com/ivanz/TraktorMappingFileFormat/blob/master/Tools/TSI%20Mapping%20Template.bt)

.tsi Format

The .tsi file is an XML file. However the actual mapping data is stored as Base64 encoded binary data in one of the attributes denoted by ### HUGE STRING HERE#### in the sample here:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<NIXML>
<TraktorSettings>
	<Entry Name="DeviceIO.Config.Controller" Type="3" Value="### HUGE STRING HERE####"></Entry>
	<Entry Name="Flavour" Type="1" Value="-1"></Entry>
	<Entry Name="Version" Type="1" Value="0"></Entry>
</TraktorSettings>
</NIXML>

To work with the controller mapping data - the binary blob needs to be extracted out (refer to Setting up guide)

High Level overview

At a high level the binary part of the .tsi file is a list of ID3v2-like frames (blocks) with the following basic structure:

typedef struct Frame {
	char[4] Identifier;
    int Size;
    char[] Data;
};

All data within binary file is stored in Big Endian format.

The data contained within those frames (which can be hierarchical) in a very simplified form is:

  • The type of the device this mapping is for.
  • Basic details about the mapping: comment, version information, etc
  • Which in/out port does the mapping apply for.
  • The input and output (midi) commands/messages/notes that the device supports.
  • Bindings between those and Traktor commands together with mapping information and parameters (e.g. sensitivity, Button/Fader/Encoder, interaction types, etc)

The file format allows for it to contain more than one device mapping in it.

File Structure Details

Conventions

Endianness

The format is Big Endian.

Strings

All strings within the file are stored as 2-bytes per character non-null terminated, but instead prefixed with the length of the string. For example:

0020h: 00 00 00 0C 00 47 00 65 00 6E 00 65 00 72 00 69  .....G.e.n.e.r.i 
0030h: 00 63 00 20 00 4D 00 49 00 44 00 49              .c. .M.I.D.I

Frames

As mentioned above data is encapsulated in Frames/Blocks of data each with the following header:

typedef struct FrameHeader {
    char Id[4];
    // The size is sizeof(FrameHeader) + size of the content of the frame
    int Size;
};

Arrays, Array Frames and Naming Convention

The way elements are stored in an array is through child frames within a parent frame, where the parent frame specifies the number of children.

Example:

typedef struct DevicesList {
    FrameHeader Header;
    int NumberOfDevices;
    Device Devices[NumberOfDevices] <optimize=false>;
};

Important: As such every structure member with a plural name (Devices) will be defined by a type with a List suffix in the name (e.g. DevicesList) will be an array.

Root

At the top of the file we have a list of devices included in it

typedef struct DeviceMappingsContainer {
    FrameHeader Header;
    DIOI DIOI_Unknown;
    DevicesList Devices <optimize=false>;
};

It's unclear what data the DIOI frame contains at this point, because it always seems to just be this:

typedef struct DIOI {
    FrameHeader Header; // DIOI
    // Seems to be a constant 1
    int Unknown;
};

Device

Definition

typedef struct Device {
    DeviceType Type;
    DeviceData Data;
};

Type

Each device definition in the mapping (in practice you export only one at a time from within Traktor, so there will be only one) contains information about it's type, which is just a string.

typedef struct DeviceType {
    FrameHeader Header; // DEVI
    int NameLength;
    wchar_t Name[NameLength];
};

Example device type is "Generic MIDI" or "Kontrol S4" and this directly corresponds to the list in the Traktor preferences:

images/file-specs/device-type.png

Data

typedef struct DeviceData
{
    FrameHeader Header; // DDAT
    DeviceTragetInfo Target;
    VersionInfo Version;
    MappingFileComment Comment;
    DevicePorts Ports;
    MidiDefinitionsContainer MidiDefinitions;
    MappingsContainer Mappings;
    MidiNoteBindingList MidiBindings;
    DVST Unknown;
};

Target Deck

A new frame that contains an enum value:

typedef struct DeviceTragetInfo {
    FrameHeader Header; // DDIF
    DeviceTarget Target;
};

enum <int> DeviceTarget { 
    Focus = 0, 
    DeckA = 1, 
    DeckB = 2, 
    DeckC = 3, 
    DeckD = 4
};

Version Information

A string containing the Traktor version which was used to make this mapping and a integer with the revision of the mapping. Traktor seems to increment the revision of the mapping every now and then.

typedef struct VersionInfo {
    FrameHeader Header; // DDIV
    int VersionLength;
    wchar_t Version[VersionLength];
    int MappingFileRevision;
};

Comment

The comment is effectively when you click Edit -> Comment in the mapping screen.

If you add a comment to a mapping in Traktor it uses that as the name of the device in place of e.g. "Generic MIDI"

typedef struct MappingFileComment {
    FrameHeader Header; // DDIC
    int CommentLength;
    wchar_t Comment[CommentLength];
};

Device Port

This is simply the name of the "In-Port" and "Out-Port" in the Traktor Controller Editor screen,.

typedef struct DevicePorts {
    FrameHeader Header; // DDPT
    int InPortNameLength;
    wchar_t InPortName[InPortNameLength] <optimize=false>;
    int OutPortNameLength;
    wchar_t OutPortName[OutPortNameLength] <optimize=false>;
};

DVST - Unkown

typedef struct DVST {
    FrameHeader Header; // DVST
    byte Content[Header.Size];
};

It is unknown at this point what the meaning of this Frame is, but it seems to always contain the following static data:

6:F890h: 44 56 53 54 00 00 00 14 00 00 00 01 00 00 00 00  DVST............ 
6:F8A0h: 00 00 00 00 00 00 00 00 00 00 00 00              ............

Mapping

Overview

There are three elements involved in a mapping:

  • The device in and out capabilities midi definition
  • The mapping options such as type of control (button/encode/fader/LED), sensitivity, invert, etc - basically the things you see when you click on a mapping in the Controller Editor
  • The binding

Device Capabilities/MIDI Definitions

The MIDI Binding

Various Enums

enum <int> MidiEncoderMode {
    _3Fh_41h = 0,
    _7Fh_01h = 1,
};

enum <int> MappingTargetDeck { 
    DeviceTargetDeck = -1,
    AorFX1orRemixDeck1Slot1OrGlobal = 0,
    BorFX2orRemixDeck1Slot2 = 1,
    CorFX3orRemixDeck1Slot3 = 2,
    DorFX4orRemixDeck1Slot4 = 3,
    RemixDeck2Slot1 = 4,
    RemixDeck2Slot2 = 5,
    RemixDeck2Slot3 = 6,
    RemixDeck2Slot4 = 7,
    RemixDeck3Slot1 = 8,
    RemixDeck3Slot2 = 9,
    RemixDeck3Slot3 = 10,
    RemixDeck3Slot4 = 11,
    RemixDeck4Slot1 = 12,
    RemixDeck4Slot2 = 13,
    RemixDeck4Slot3 = 14,
    RemixDeck4Slot4 = 15,
};

enum <int> MappingInteractionMode {
    Toggle = 1,
    Hold = 2,
    Direct = 3,
    Relative = 4,
    Increment = 5,
    Decrement = 6,
    Reset = 7,
    Output = 8,
};

enum <int> MappingControllerType {
    Button = 0,
    FaderOrKnob = 1,
    Encoder = 2,
    LED = 65535,
};


// Big endian values !!
enum <DWORD> MappingResolution {
    Fine = 0x3C800000,
    Min = 0x3D800000,
    Default = 0x3D800000,
    Coarse = 0x3E000000,
    Switch = 0x3F000000,
};

Clone this wiki locally