Created
June 30, 2012 19:23
-
-
Save bowd/3025172 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file session_file.h | |
* @Author Bogdan Dumitru ([email protected]) | |
* @date July, 2012 | |
* @brief Functions related to the processing of Ableton Live Session files (.als) | |
* | |
* The functions regarding processing of ALS files. This is currently devided in | |
* three subsections with appropriate prefixes: | |
* | |
* (1) Regarding specifically to ALS files and entities: | |
* These are prefixed with ALS/als and refer to specific inner structures and | |
* functions of the als file and subsequent ALS reinterpretation this program stores. | |
* | |
* (2) Regarding virtual memory buffer: | |
* These are prefixed with VMEM/vmem and are used for working with a virtual memory | |
* chunk that is allocated and maintained for the storage of the session that is | |
* analysed. | |
*/ | |
#ifndef _SESSION_FILE_H_ | |
#define _SESSION_FILE_H_ | |
#include <libxml/encoding.h> | |
#include <libxml/xmlwriter.h> | |
#include <libxml/parser.h> | |
#include <libxml/tree.h> | |
#include <openssl/evp.h> | |
/* General defines */ | |
#define ALS_CONTROL_BYTES "ALSDATAFMTTREEFL" | |
#define ALS_CONTROL_BYTES_LENGTH 16 | |
#define ALS_VERSION_MAJOR 0 | |
#define ALS_VERSION_MINOR 1 | |
#define PATH_INITIAL_SIZE 256 | |
#define VMEM_INITIAL_SIZE 262144 | |
/* ALS related structures */ | |
typedef enum { | |
ALS_ELEMENT = 23, | |
ALS_DATA | |
} als_node_type; | |
typedef struct _als_attribute { | |
uint16_t name_size; | |
uint16_t value_size; | |
char data[]; | |
} als_attribute; | |
typedef struct _als_node als_node; | |
typedef struct _als_element_node { | |
uint16_t name_size; | |
uint16_t no_attrs; | |
uint16_t no_children; | |
char data[]; | |
} als_element_node; | |
typedef struct _als_data_node { | |
uint32_t size; | |
char data[]; | |
} als_data_node; | |
struct _als_node { | |
uint32_t size; | |
char id[16]; | |
als_node_type type; | |
union { | |
als_element_node element; | |
als_data_node data; | |
}; | |
}; | |
typedef struct { | |
uint16_t encoding_size; | |
uint16_t version_size; | |
char data[]; | |
} als_payload; | |
typedef struct { | |
uint32_t pula; | |
} als_index; | |
typedef struct { | |
char control_bytes[ALS_CONTROL_BYTES_LENGTH]; | |
uint16_t version_major; | |
uint16_t version_minor; | |
char index_md5[16]; | |
uint32_t index_size; | |
char payload_md5[16]; | |
uint32_t payload_size; | |
char data[]; | |
} als_file; | |
/* VMEM related structures */ | |
typedef struct { | |
uint32_t alloc_size; | |
uint32_t used; | |
char *p; | |
} vmem; | |
typedef struct { | |
vmem *mem; | |
uint32_t offset; | |
} vmem_element; | |
/* Path structures */ | |
/* VMEM macros */ | |
/** | |
* Checks if there is enough space to have an entity of the given size at the | |
* given pointer inside the memory block defined by `mem`. | |
* If it's true it returns the specific pointer. If not it first alters the | |
* memory block and then returns the pointer. | |
*/ | |
#define VMEMCHECK(ptr, size, mem) \ | |
((ptr)+(size) < (mem)->p + (mem)->alloc_size ? \ | |
(ptr) : vmem_extend((mem), (ptr))) | |
/** | |
* Tries to cast the location at `ptr` in `mem` as the given type. | |
* Uses VMEM_CHECK with sizeof(type). | |
*/ | |
#define VMEMCAST(type, ptr, mem) \ | |
((type *) (VMEM_CHECK(sizeof(type), ptr, mem))) | |
/** | |
* Performes a memcpy but with VMEM_CHECK in the middle | |
*/ | |
#define VMEMCPY(p, s, size, mem) memcpy((char *) VMEM_CHECK(size, p, mem), s, size) | |
/* vmem_element to als element macros */ | |
/** | |
* Casts a vmem_element `el` to an als of type `type` | |
*/ | |
#define ALS_EL(type, el) \ | |
((type *) (el->mem->p + el->offset)) | |
/* Shorthand functions for the given ALS types */ | |
#define ALS_FILE(el) ALS_EL(als_file, el) | |
#define ALS_PAYLOAD(el) ALS_EL(als_payload, el) | |
#define ALS_NODE(el) ALS_EL(als_node, el) | |
#define ALS_ATTR(el) ALS_EL(als_attribute, el) | |
#define VMEM_EL(ptr, mem, type) \ | |
((vmem_element *) vmem_element_at(ptr, mem, sizeof(type))) | |
#define VMEM_FILE(ptr, mem) (VMEM_EL(ptr, mem, als_file)) | |
#define VMEM_PAYLOAD(ptr, mem) (VMEM_EL(ptr, mem, als_payload)) | |
#define VMEM_NODE(ptr, mem) (VMEM_EL(ptr, mem, als_node)) | |
#define VMEM_ATTR(ptr, mem) (VMEM_EL(ptr, mem, als_attribute)) | |
/* DEPRECATED | |
#define ALS_CAST(type, el) VMEM_CAST(type, (el->mem->p + el->offset), el->mem) | |
#define ALS_UPDATE(type, el) ((type *) (el->mem->p + el->offset)) | |
*/ | |
/** | |
* Specific ALS element accessor macros based off of vmem_element in order | |
* to maintain locality when and if the data buffer is reallocated and moved | |
*/ | |
/* | |
* =================================================================== | |
* als_attribute getter/setter macros. | |
* =================================================================== | |
* Explicit getters | |
*/ | |
#define ALS_ATTR_NAME_SIZE(el) ( ALS_ATTR(el)->name_size ) | |
#define ALS_ATTR_VALUE_SIZE(el) ( ALS_ATTR(el)->value_size ) | |
#define ALS_ATTR_DATA(el) ( ALS_ATTR(el)->data ) | |
/* | |
* Implicit getters | |
*/ | |
#define ALS_ATTR_NAME(el) ((char *) ALS_ATTR(el)->data) | |
#define ALS_ATTR_VALUE(el) ((char *) (ALS_ATTR(el)->data + ALS_ATTR_NAME_SIZE(el))) | |
#define ALS_ATTR_SIZE(el) ( sizeof(uint16_t) * 2 + \ | |
sizeof(char) * ( ALS_ATTR_NAME_SIZE(el) + \ | |
ALS_ATTR_VALUE_SIZE(el) )) | |
/* | |
* Explicit setters | |
*/ | |
#define ALS_ATTR_SET_NAME_SIZE(el, sz) (ALS_ATTR(el)->name_size = sz) | |
#define ALS_ATTR_SET_VALUE_SIZE(el,sz) (ALS_ATTR(el)->value_size = sz) | |
/* | |
* Implicit setters | |
*/ | |
#define ALS_NODE_SET_NAME(el, nm, len) \ | |
do { ALS_ATTR_SET_NAME_SIZE(el, len); \ | |
VMEMCPY(ALS_ATTR_NAME(el), nm, len, el->mem); } while(false) | |
#define ALS_NODE_SET_VALUE(el, vl, len) \ | |
do { ALS_ATTR_SET_VALUE_SIZE(el, len); \ | |
VMEMCPY(ALS_ATTR_VALUE(el), vl, len, el->mmem); } while(false) | |
/* | |
* =================================================================== | |
* als_node getter/setter macros | |
* =================================================================== | |
* Explicit getters | |
*/ | |
#define ALS_NODE_SIZE(el) (ALS_NODE(el)->size) | |
#define ALS_NODE_ID(el) (ALS_NODE(el)->id ) | |
#define ALS_NODE_TYPE(el) (ALS_NODE(el)->type) | |
/* als_element_node */ | |
#define ALS_NODE_NAME_SIZE(el) (ALS_NODE(el)->element.name_size ) | |
#define ALS_NODE_NO_ATTRS(el) (ALS_NODE(el)->element.no_attrs ) | |
#define ALS_NODE_NO_CHILDREN(el) (ALS_NODE(el)->element.no_children) | |
#define ALS_NODE_EL_DATA(el) (ALS_NODE(el)->element.data ) | |
/* als_data_node */ | |
#define ALS_NODE_DATA_SIZE(el) (ALS_NODE(el)->data.size) | |
#define ALS_NODE_DATA(el) (ALS_NODE(el)->data.data) | |
/** | |
* Implicit getters | |
*/ | |
#define ALS_NODE_NAME(el) ((char *) ALS_NODE_EL_DATA(el)) | |
#define ALS_NODE_ATTR_OFFSETS_PTR(el) (ALS_NODE_EL_DATA(el) + ALS_NODE_NAME_SIZE(el)) | |
#define ALS_NODE_ATTR_OFFSETS(el) \ | |
((uint32_t *) ALS_NODE_ATTR_OFFSETS_PTR(el)) | |
#define ALS_NODE_ATTR_OFFSET(el, i) \ | |
((uint32_t) ALS_NODE_ATTR_OFFSETS(el)[i]) | |
#define ALS_NODe_ATTR_PTR(el, i) \ | |
(ALS_NODE_EL_DATA(el) + ALS_NODE_ATTR_OFFSET(el, i)) | |
#define ALS_NODE_ATTR(el, i) \ | |
(VMEM_ATTR(ALS_NODE_ATTR_PTR(el, i), el->mem)) | |
#define ALS_NODE_CHILD_OFFSETS_PTR(el) \ | |
(ALS_NODE_ATTR_OFFSETS_PTR(el) + sizeof(uint32_t) * ALS_NODE_NO_ATTRS(el)) | |
#define ALS_NODE_CHILD_OFFSETS(el) \ | |
((uint32_t *) ALS_NODE_CHILD_OFFSETS_PTR(el)) | |
#define ALS_NODE_CHILD_OFFSET(el, i) \ | |
((uint32_t) ALS_NODE_ATTR_OFFSETS(el)[i]) | |
#define ALS_NODE_CHILD_PTR(el, i) \ | |
(ALS_NODE_EL_DATA(el) + ALS_NODE_CHILD_OFFSET(el, i)) | |
#define ALS_NODE_CHILD(el, i) \ | |
(VMEM_NODE(ALS_NODE_CHILD_PTR(el, i), el->mem)) | |
/* | |
* Explicit setters | |
*/ | |
#define ALS_NODE_SET_SIZE(el, sz) (ALS_NODE(el)->size = sz) | |
#define ALS_NODE_SET_TYPE(el, tp) (ALS_NODE(el)->type = tp) | |
#define ALS_NODE_SET_NAME_SIZE(el, sz) (ALS_NODE(el)->element.name_size = sz) | |
#define ALS_NODE_SET_NO_ATTRS(el, na) (ALS_NODE(el)->element.no_attrs = na) | |
#define ALS_NODE_SET_NO_CHILDREN(el, nc) (ALS_NODE(el)->element.no_children = nc) | |
#define ALS_NODe_SET_DATA_SIZE(el, ds) (ALS_NODE(el)->data.size = ds) | |
#define ALS_NODE_SET_ID(el, id) \ | |
(memcpy(ALS_NODE_ID(el), id, 16)) | |
/** | |
* Implicit setters | |
*/ | |
#define ALS_NODE_SET_NAME(el, nm, len) \ | |
do { ALS_NODE_SET_NAME_SIZE(el, len); \ | |
VMEMCPY(ALS_NODE_NAME(el), nm, len, el->mem); } while(false) | |
#define ALS_NODE_INIT_ATTR(el, i) \ | |
do { if (i == 0) { /* FIRST ATTR */ \ | |
uint32_t *offsets = (uint32_t *) VMEMCHECK( \ | |
ALS_NODE_ATTR_OFFSETS_PTR(el), \ | |
sizeof(uint32_t) * ALS_NODE_NO_ATTRS(el), el->mem); \ | |
offsets[0] = sizeof(uint32_t) * ( ALS_NODE_NO_ATTRS(el) + \ | |
ALS_NODE_NO_CHILDREN(el) ); \ | |
} else { \ | |
uint32_t *offsets = ALS_NODE_ATTR_OFFSETS(el); \ | |
vmem_element *prev_attr = ALS_NODE_ATTR(el, (i-1)) \ | |
offsets[i] = offsets[i-1] + ALS_ATTR_SIZE(prev_attr); \ | |
free(prev_attr); \ | |
} | |
#define ALS_NODE_INIT_CHILD(el, i) \ | |
do { if (i == 0) { /* FIRST CHILD */ \ | |
uint32_t *offsets = (uint32_t *) VMEMCHECK( \ | |
ALS_NODE_CHILD_OFFSETS_PTR(el), \ | |
sizeof(uint32_t) * ALS_NODE_NO_CHILDREN(el), \ | |
el->mem); \ | |
if (ALS_NODE_NO_ATTRS(el) == 0) { /* NO_ATTRIBUTES */ \ | |
offsets[0] = sizeof(uint32_t) * ALS_NODE_NO_CHILDREN(el); \ | |
} else { \ | |
vmem_element *last_attr = \ | |
ALS_NODE_ATTR(el, ALS_NODE_NO_ATTRS(el)-1); \ | |
offsets[0] = \ | |
ALS_NODE_ATTR_OFFSET(el, ALS_NODE_NO_ATTRS(el)-1) + \ | |
ALS_ATTR_SIZE(last_attr); \ | |
free(last_attr); \ | |
} \ | |
} else { \ | |
uint32_t *offsets = ALS_NODE_CHILD_OFFSETS(el); \ | |
vmem_element *prev_child = ALS_NODE_CHILD(el, (i-1)) \ | |
offsets[i] = offsets[i-1] + ALS_NODE_SIZE(prev_child); \ | |
free(prev_child); \ | |
} | |
/** | |
* ======================================================================== | |
* als_payload setter/getter macros | |
* ======================================================================== | |
* Explicit getters | |
*/ | |
#define ALS_PAYLOAD_ENCODING_SIZE(el) (ALS_PAYLOAD(el)->encoding_size) | |
#define ALS_PAYLOAD_VERSION_SIZE(el) (ALS_PAYLOAD(el)->version_size) | |
#define ALS_PAYLOAD_DATA(el) (ALS_PAYLOAD(el)->data) | |
/** | |
* Implicit getters | |
*/ | |
#define ALS_PAYLOAD_SIZE(el) \ | |
((uint32_t) 2*sizeof(uint16_t) + \ | |
sizeof(char) * ( ALS_PAYLOAD_ENCODING_SIZE(el) + \ | |
ALS_PAYLOAD_VERSION_SIZE(el) ) + \ | |
#define ALS_PAYLOAD_ENCODING(el) ((char *) ALS_PAYLOAD_DATA(el)) | |
#define ALS_PAYLOAD_VERSION(el) ((char *) (ALS_PAYLOAD_DATA(el) + \ | |
ALS_PAYLOAD_ENCODING_SIZE(el))) | |
#define ALS_PAYLOAD_ROOT_PTR(el) \ | |
( ALS_PAYLOAD_VERSION(el) + ALS_PAYLOAD_VERSION_SIZE(el) ) | |
#define ALS_PAYLOAD_ROOT(el) \ | |
(VMEM_NODE(ALS_PAYLOAD_ROOT_PTR(el), el->mem)) | |
#define ALS_PAYLOAD_SIZE(el) \ | |
((uint32_t) 2*sizeof(uint16_t) + \ | |
sizeof(char) * ( ALS_PAYLOAD_ENCODING_SIZE(el) + \ | |
ALS_PAYLOAD_VERSION_SIZE(el) ) + \ | |
ALS_NODE(ALS_PAYLOAD_ROOT_PTR(el))->size | |
/** | |
* Explicit setters | |
*/ | |
#define ALS_PAYLOAD_SET_ENCODING_SIZE(el, sz) \ | |
(ALS_PAYLOAD(el)->encoding_size = sz) | |
#define ALS_PAYLOAD_SET_VERSION_SIZE(el, sz) \ | |
(ALS_PAYLOAD(el)->version_size = sz) | |
/** | |
* Implicit setters | |
*/ | |
#define ALS_PAYLOAD_SET_ENCODING(el, en, len) \ | |
do { ALS_PAYLOAD_SET_ENCODING_SIZE(el, len); \ | |
VMEMCPY(ALS_PAYLOAD_ENCODING(el), en, len, el->mem); } while(false) | |
#define ALS_PAYLOAD_SET_VERSION(el, vs, len) \ | |
do { ALS_PAYLOAD_SET_VERSION_SIZE(el, len); \ | |
VMEMCPY(ALS_PAYLOAD_VERSION(el), vs, len, el->mem); } while(false) | |
/** | |
* ======================================================================== | |
* als_file getter/setter macros | |
* ======================================================================== | |
* Explicit getters | |
*/ | |
#define ALS_FILE_CONTROL_BYTES(el) (ALS_FILE(el)->control_bytes) | |
#define ALS_FILE_VERSION_MAJOR(el) (ALS_FILE(el)->version_major) | |
#define ALS_FILE_VERSION_MINOR(el) (ALS_FILE(el)->version_minor) | |
#define ALS_FILE_INDEX_MD5(el) (ALS_FILE(el)->index_md5) | |
#define ALS_FILE_INDEX_SIZE(el) (ALS_FILE(el)->index_size) | |
#define ALS_FILE_PAYLOAD_MD5(el) (ALS_FILE(el)->payload_md5) | |
#define ALS_FILE_PAYLOAD_SIZE(el) (ALS_FILE(el)->payload_size) | |
#define ALS_FILE_DATA(el) (ALS_FILE(el)->data) | |
/** | |
* Implicit getters | |
*/ | |
#define ALS_FILE_PAYLOAD_PTR(el) (ALS_FILE_DATA(el)) | |
#define ALS_FILE_INDEX_PTR(el) (ALS_FILE_DATA(el) + ALS_FILE_PAYLOAD_SIZE(el)) | |
#define ALS_FILE_PAYLOAD(el) \ | |
(VMEM_PAYLOAD(ALS_FILE_PAYLOAD_PTR(el), el->mem)) | |
/** | |
* TODO: Decide how to handle the index. | |
*/ | |
#define ALS_FILE_INDEX(el) \ | |
(NULL) | |
/** | |
* Explicit setters | |
*/ | |
#define ALS_FILE_SET_CONTROL_BYTES(el) \ | |
(memcpy(ALS_FILE_CONTROL_BYTES(el), ALS_CONTROL_BYTES, ALS_CONTROL_BYTES_LENGTH)) | |
#define ALS_FILE_SET_VERSION_MAJOR(el, vm) (ALS_FILE(el)->version_major = vm) | |
#define ALS_FILE_SET_VERSION_MINOR(el, vm) (ALS_FILE(el)->version_minor = vm) | |
#define ALS_FILE_SET_INDEX_SIZE(el, sz) (ALS_FILE(el)->index_size = sz) | |
#define ALS_FILE_SET_PAYLOAD_SIZE(el, sz) (ALS_FILE(el)->payload_size = sz) | |
/* ALS functions */ | |
void als_load_xml(); | |
//void als_write_session_to_file(als_file *als, char * storage_file); | |
void als_parse_node(vmem_element *node, xmlNode *xml_node, | |
EVP_MD_CTX *path, als_node_type type); | |
void als_set_header(vmem_element *file); | |
/* Path manipulation functions */ | |
vmem *path_init(char *content, uint32_t size); | |
void path_push(vmem *path, vmem_element *node); | |
void path_pop(vmem *path); | |
void path_destroy(vmem *path); | |
char *path_element(vmem_element *node); | |
/* VMEM manipulation functions */ | |
vmem *vmem_init(uint32_t size); | |
void vmem_cpy(char *dest, char *source, uint32_t size, vmem *mem); | |
char *vmem_extend(vmem *mem, char *p); | |
void vmem_attr_init_offset(vmem_element *node, int attr_index); | |
void vmem_child_init_offset(vmem_element *node, int child_index); | |
vmem_element *vmem_element_at(char *p, vmem *mem, uint32_t size); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment