diff options
author | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2021-07-08 19:20:28 +0200 |
---|---|---|
committer | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2021-07-08 19:20:28 +0200 |
commit | 39bad8ff88a4c3980e00e9758e5d06775843d375 (patch) | |
tree | ea4725dc57180ba749749602ed12935d09b9a4e8 | |
parent | 2968222c96e97036c5ab8209fbc8aee3ee9f2e01 (diff) | |
download | patchmatrix-39bad8ff88a4c3980e00e9758e5d06775843d375.tar.xz |
Deprecate JACK session management.
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | cJSON/LICENSE | 20 | ||||
-rw-r--r-- | cJSON/cJSON.c | 2350 | ||||
-rw-r--r-- | cJSON/cJSON.h | 244 | ||||
-rw-r--r-- | meson.build | 5 | ||||
-rw-r--r-- | patchmatrix.1 | 12 | ||||
-rw-r--r-- | patchmatrix.c | 16 | ||||
-rw-r--r-- | patchmatrix.h | 71 | ||||
-rw-r--r-- | patchmatrix_db.c | 77 | ||||
-rw-r--r-- | patchmatrix_jack.c | 120 | ||||
-rw-r--r-- | patchmatrix_mixer.1 | 12 | ||||
-rw-r--r-- | patchmatrix_mixer.c | 130 | ||||
-rw-r--r-- | patchmatrix_monitor.1 | 12 | ||||
-rw-r--r-- | patchmatrix_monitor.c | 90 |
14 files changed, 13 insertions, 3148 deletions
@@ -1 +1 @@ -0.25.11 +0.25.13 diff --git a/cJSON/LICENSE b/cJSON/LICENSE deleted file mode 100644 index fa0a438..0000000 --- a/cJSON/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - diff --git a/cJSON/cJSON.c b/cJSON/cJSON.c deleted file mode 100644 index fb0c216..0000000 --- a/cJSON/cJSON.c +++ /dev/null @@ -1,2350 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -#pragma GCC visibility push(default) -#include <string.h> -#include <stdio.h> -#include <math.h> -#include <stdlib.h> -#include <float.h> -#include <limits.h> -#include <ctype.h> -#include <locale.h> -#pragma GCC visibility pop - -#include "cJSON.h" - -/* define our own boolean type */ -#define true ((cJSON_bool)1) -#define false ((cJSON_bool)0) - -static const unsigned char *global_ep = NULL; - -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) -{ - return (const char*) global_ep; -} - -/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 4) || (CJSON_VERSION_PATCH != 7) - #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. -#endif - -CJSON_PUBLIC(const char*) cJSON_Version(void) -{ - static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); - - return version; -} - -/* case insensitive strcmp */ -static int cJSON_strcasecmp(const unsigned char *s1, const unsigned char *s2) -{ - if (!s1) - { - return (s1 == s2) ? 0 : 1; /* both NULL? */ - } - if (!s2) - { - return 1; - } - for(; tolower(*s1) == tolower(*s2); (void)++s1, ++s2) - { - if (*s1 == '\0') - { - return 0; - } - } - - return tolower(*s1) - tolower(*s2); -} - -typedef struct internal_hooks -{ - void *(*allocate)(size_t size); - void (*deallocate)(void *pointer); - void *(*reallocate)(void *pointer, size_t size); -} internal_hooks; - -static internal_hooks global_hooks = { malloc, free, realloc }; - -static unsigned char* cJSON_strdup(const unsigned char* str, const internal_hooks * const hooks) -{ - size_t len = 0; - unsigned char *copy = NULL; - - if (str == NULL) - { - return NULL; - } - - len = strlen((const char*)str) + sizeof(""); - if (!(copy = (unsigned char*)hooks->allocate(len))) - { - return NULL; - } - memcpy(copy, str, len); - - return copy; -} - -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (hooks == NULL) - { - /* Reset hooks */ - global_hooks.allocate = malloc; - global_hooks.deallocate = free; - global_hooks.reallocate = realloc; - return; - } - - global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) - { - global_hooks.allocate = hooks->malloc_fn; - } - - global_hooks.deallocate = free; - if (hooks->free_fn != NULL) - { - global_hooks.deallocate = hooks->free_fn; - } - - /* use realloc only if both free and malloc are used */ - global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) - { - global_hooks.reallocate = realloc; - } -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(const internal_hooks * const hooks) -{ - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if (node) - { - memset(node, '\0', sizeof(cJSON)); - } - - return node; -} - -/* Delete a cJSON structure. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *c) -{ - cJSON *next = NULL; - while (c) - { - next = c->next; - if (!(c->type & cJSON_IsReference) && c->child) - { - cJSON_Delete(c->child); - } - if (!(c->type & cJSON_IsReference) && c->valuestring) - { - global_hooks.deallocate(c->valuestring); - } - if (!(c->type & cJSON_StringIsConst) && c->string) - { - global_hooks.deallocate(c->string); - } - global_hooks.deallocate(c); - c = next; - } -} - -/* get the decimal point character of the current locale */ -static unsigned char get_decimal_point(void) -{ - struct lconv *lconv = localeconv(); - return (unsigned char) lconv->decimal_point[0]; -} - -/* Parse the input text to generate a number, and populate the result into item. */ -static const unsigned char *parse_number(cJSON * const item, const unsigned char * const input) -{ - double number = 0; - unsigned char *after_end = NULL; - unsigned char number_c_string[64]; - unsigned char decimal_point = get_decimal_point(); - size_t i = 0; - - if (input == NULL) - { - return NULL; - } - - /* copy the number into a temporary buffer and replace '.' with the decimal point - * of the current locale (for strtod) */ - for (i = 0; (i < (sizeof(number_c_string) - 1)) && (input[i] != '\0'); i++) - { - switch (input[i]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - case 'e': - case 'E': - number_c_string[i] = input[i]; - break; - - case '.': - number_c_string[i] = decimal_point; - break; - - default: - goto loop_end; - } - } -loop_end: - number_c_string[i] = '\0'; - - number = strtod((const char*)number_c_string, (char**)&after_end); - if (number_c_string == after_end) - { - return NULL; /* parse_error */ - } - - item->valuedouble = number; - - /* use saturation in case of overflow */ - if (number >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (number <= INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)number; - } - - item->type = cJSON_Number; - - return input + (after_end - number_c_string); -} - -/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) -{ - if (number >= INT_MAX) - { - object->valueint = INT_MAX; - } - else if (number <= INT_MIN) - { - object->valueint = INT_MIN; - } - else - { - object->valueint = (int)number; - } - - return object->valuedouble = number; -} - -typedef struct -{ - unsigned char *buffer; - size_t length; - size_t offset; - cJSON_bool noalloc; -} printbuffer; - -/* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer * const p, size_t needed, const internal_hooks * const hooks) -{ - unsigned char *newbuffer = NULL; - size_t newsize = 0; - - if ((p == NULL) || (p->buffer == NULL)) - { - return NULL; - } - - if ((p->length > 0) && (p->offset >= p->length)) - { - /* make sure that offset is valid */ - return NULL; - } - - if (needed > INT_MAX) - { - /* sizes bigger than INT_MAX are currently not supported */ - return NULL; - } - - needed += p->offset + 1; - if (needed <= p->length) - { - return p->buffer + p->offset; - } - - if (p->noalloc) { - return NULL; - } - - /* calculate new buffer size */ - if (needed > (INT_MAX / 2)) - { - /* overflow of int, use INT_MAX if possible */ - if (needed <= INT_MAX) - { - newsize = INT_MAX; - } - else - { - return NULL; - } - } - else - { - newsize = needed * 2; - } - - if (hooks->reallocate != NULL) - { - /* reallocate with realloc if available */ - newbuffer = (unsigned char*)hooks->reallocate(p->buffer, newsize); - } - else - { - /* otherwise reallocate manually */ - newbuffer = (unsigned char*)hooks->allocate(newsize); - if (!newbuffer) - { - hooks->deallocate(p->buffer); - p->length = 0; - p->buffer = NULL; - - return NULL; - } - if (newbuffer) - { - memcpy(newbuffer, p->buffer, p->offset + 1); - } - hooks->deallocate(p->buffer); - } - p->length = newsize; - p->buffer = newbuffer; - - return newbuffer + p->offset; -} - -/* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer * const buffer) -{ - const unsigned char *buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) - { - return; - } - buffer_pointer = buffer->buffer + buffer->offset; - - buffer->offset += strlen((const char*)buffer_pointer); -} - -/* Removes trailing zeroes from the end of a printed number */ -static int trim_trailing_zeroes(const unsigned char * const number, int length, const unsigned char decimal_point) -{ - if ((number == NULL) || (length <= 0)) - { - return -1; - } - - while ((length > 0) && (number[length - 1] == '0')) - { - length--; - } - if ((length > 0) && (number[length - 1] == decimal_point)) - { - /* remove trailing decimal_point */ - length--; - } - - return length; -} - -/* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer, const internal_hooks * const hooks) -{ - unsigned char *output_pointer = NULL; - double d = item->valuedouble; - int length = 0; - size_t i = 0; - cJSON_bool trim_zeroes = true; /* should zeroes at the end be removed? */ - unsigned char number_buffer[64]; /* temporary buffer to print the number into */ - unsigned char decimal_point = get_decimal_point(); - - if (output_buffer == NULL) - { - return false; - } - - /* This checks for NaN and Infinity */ - if ((d * 0) != 0) - { - length = sprintf((char*)number_buffer, "null"); - } - else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60)) - { - /* integer */ - length = sprintf((char*)number_buffer, "%.0f", d); - trim_zeroes = false; /* don't remove zeroes for "big integers" */ - } - else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9)) - { - length = sprintf((char*)number_buffer, "%e", d); - trim_zeroes = false; /* don't remove zeroes in engineering notation */ - } - else - { - length = sprintf((char*)number_buffer, "%f", d); - } - - /* sprintf failed or buffer overrun occured */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) - { - return false; - } - - if (trim_zeroes) - { - length = trim_trailing_zeroes(number_buffer, length, decimal_point); - if (length <= 0) - { - return false; - } - } - - /* reserve appropriate space in the output */ - output_pointer = ensure(output_buffer, (size_t)length, hooks); - if (output_pointer == NULL) - { - return false; - } - - /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for (i = 0; i < ((size_t)length); i++) - { - if (number_buffer[i] == decimal_point) - { - output_pointer[i] = '.'; - continue; - } - - output_pointer[i] = number_buffer[i]; - } - output_pointer[i] = '\0'; - - output_buffer->offset += (size_t)length; - - return true; -} - -/* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char * const input) -{ - unsigned int h = 0; - size_t i = 0; - - for (i = 0; i < 4; i++) - { - /* parse digit */ - if ((input[i] >= '0') && (input[i] <= '9')) - { - h += (unsigned int) input[i] - '0'; - } - else if ((input[i] >= 'A') && (input[i] <= 'F')) - { - h += (unsigned int) 10 + input[i] - 'A'; - } - else if ((input[i] >= 'a') && (input[i] <= 'f')) - { - h += (unsigned int) 10 + input[i] - 'a'; - } - else /* invalid */ - { - return 0; - } - - if (i < 3) - { - /* shift left to make place for the next nibble */ - h = h << 4; - } - } - - return h; -} - -/* converts a UTF-16 literal to UTF-8 - * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer, const unsigned char **error_pointer) -{ - long unsigned int codepoint = 0; - unsigned int first_code = 0; - const unsigned char *first_sequence = input_pointer; - unsigned char utf8_length = 0; - unsigned char utf8_position = 0; - unsigned char sequence_length = 0; - unsigned char first_byte_mark = 0; - - if ((input_end - first_sequence) < 6) - { - /* input ends unexpectedly */ - *error_pointer = first_sequence; - goto fail; - } - - /* get the first utf16 sequence */ - first_code = parse_hex4(first_sequence + 2); - - /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)) || (first_code == 0)) - { - *error_pointer = first_sequence; - goto fail; - } - - /* UTF16 surrogate pair */ - if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) - { - const unsigned char *second_sequence = first_sequence + 6; - unsigned int second_code = 0; - sequence_length = 12; /* \uXXXX\uXXXX */ - - if ((input_end - second_sequence) < 6) - { - /* input ends unexpectedly */ - *error_pointer = first_sequence; - goto fail; - } - - if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) - { - /* missing second half of the surrogate pair */ - *error_pointer = first_sequence; - goto fail; - } - - /* get the second utf16 sequence */ - second_code = parse_hex4(second_sequence + 2); - /* check that the code is valid */ - if ((second_code < 0xDC00) || (second_code > 0xDFFF)) - { - /* invalid second half of the surrogate pair */ - *error_pointer = first_sequence; - goto fail; - } - - - /* calculate the unicode codepoint from the surrogate pair */ - codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); - } - else - { - sequence_length = 6; /* \uXXXX */ - codepoint = first_code; - } - - /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if (codepoint < 0x80) - { - /* normal ascii, encoding 0xxxxxxx */ - utf8_length = 1; - } - else if (codepoint < 0x800) - { - /* two bytes, encoding 110xxxxx 10xxxxxx */ - utf8_length = 2; - first_byte_mark = 0xC0; /* 11000000 */ - } - else if (codepoint < 0x10000) - { - /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ - utf8_length = 3; - first_byte_mark = 0xE0; /* 11100000 */ - } - else if (codepoint <= 0x10FFFF) - { - /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ - utf8_length = 4; - first_byte_mark = 0xF0; /* 11110000 */ - } - else - { - /* invalid unicode codepoint */ - *error_pointer = first_sequence; - goto fail; - } - - /* encode as utf8 */ - for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) - { - /* 10xxxxxx */ - (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); - codepoint >>= 6; - } - /* encode first byte */ - if (utf8_length > 1) - { - (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); - } - else - { - (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); - } - - *output_pointer += utf8_length; - - return sequence_length; - -fail: - return 0; -} - -/* Parse the input text into an unescaped cinput, and populate item. */ -static const unsigned char *parse_string(cJSON * const item, const unsigned char * const input, const unsigned char ** const error_pointer, const internal_hooks * const hooks) -{ - const unsigned char *input_pointer = input + 1; - const unsigned char *input_end = input + 1; - unsigned char *output_pointer = NULL; - unsigned char *output = NULL; - - /* not a string */ - if (*input != '\"') - { - *error_pointer = input; - goto fail; - } - - { - /* calculate approximate size of the output (overestimate) */ - size_t allocation_length = 0; - size_t skipped_bytes = 0; - while ((*input_end != '\"') && (*input_end != '\0')) - { - /* is escape sequence */ - if (input_end[0] == '\\') - { - if (input_end[1] == '\0') - { - /* prevent buffer overflow when last input character is a backslash */ - goto fail; - } - skipped_bytes++; - input_end++; - } - input_end++; - } - if (*input_end == '\0') - { - goto fail; /* string ended unexpectedly */ - } - - /* This is at most how much we need for the output */ - allocation_length = (size_t) (input_end - input) - skipped_bytes; - output = (unsigned char*)hooks->allocate(allocation_length + sizeof("")); - if (output == NULL) - { - goto fail; /* allocation failure */ - } - } - - output_pointer = output; - /* loop through the string literal */ - while (input_pointer < input_end) - { - if (*input_pointer != '\\') - { - *output_pointer++ = *input_pointer++; - } - /* escape sequence */ - else - { - unsigned char sequence_length = 2; - switch (input_pointer[1]) - { - case 'b': - *output_pointer++ = '\b'; - break; - case 'f': - *output_pointer++ = '\f'; - break; - case 'n': - *output_pointer++ = '\n'; - break; - case 'r': - *output_pointer++ = '\r'; - break; - case 't': - *output_pointer++ = '\t'; - break; - case '\"': - case '\\': - case '/': - *output_pointer++ = input_pointer[1]; - break; - - /* UTF-16 literal */ - case 'u': - sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer, error_pointer); - if (sequence_length == 0) - { - /* failed to convert UTF16-literal to UTF-8 */ - goto fail; - } - break; - - default: - *error_pointer = input_pointer; - goto fail; - } - input_pointer += sequence_length; - } - } - - /* zero terminate the output */ - *output_pointer = '\0'; - - item->type = cJSON_String; - item->valuestring = (char*)output; - - return input_end + 1; - -fail: - if (output != NULL) - { - hooks->deallocate(output); - } - - return NULL; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer, const internal_hooks * const hooks) -{ - const unsigned char *input_pointer = NULL; - unsigned char *output = NULL; - unsigned char *output_pointer = NULL; - size_t output_length = 0; - /* numbers of additional characters needed for escaping */ - size_t escape_characters = 0; - - if (output_buffer == NULL) - { - return false; - } - - /* empty string */ - if (input == NULL) - { - output = ensure(output_buffer, sizeof("\"\""), hooks); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "\"\""); - - return true; - } - - /* set "flag" to 1 if something needs to be escaped */ - for (input_pointer = input; *input_pointer; input_pointer++) - { - if (strchr("\"\\\b\f\n\r\t", *input_pointer)) - { - /* one character escape sequence */ - escape_characters++; - } - else if (*input_pointer < 32) - { - /* UTF-16 escape sequence uXXXX */ - escape_characters += 5; - } - } - output_length = (size_t)(input_pointer - input) + escape_characters; - - output = ensure(output_buffer, output_length + sizeof("\"\""), hooks); - if (output == NULL) - { - return false; - } - - /* no characters have to be escaped */ - if (escape_characters == 0) - { - output[0] = '\"'; - memcpy(output + 1, input, output_length); - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; - } - - output[0] = '\"'; - output_pointer = output + 1; - /* copy the string */ - for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) - { - if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) - { - /* normal character, copy */ - *output_pointer = *input_pointer; - } - else - { - /* character needs to be escaped */ - *output_pointer++ = '\\'; - switch (*input_pointer) - { - case '\\': - *output_pointer = '\\'; - break; - case '\"': - *output_pointer = '\"'; - break; - case '\b': - *output_pointer = 'b'; - break; - case '\f': - *output_pointer = 'f'; - break; - case '\n': - *output_pointer = 'n'; - break; - case '\r': - *output_pointer = 'r'; - break; - case '\t': - *output_pointer = 't'; - break; - default: - /* escape and print as unicode codepoint */ - sprintf((char*)output_pointer, "u%04x", *input_pointer); - output_pointer += 4; - break; - } - } - } - output[output_length + 1] = '\"'; - output[output_length + 2] = '\0'; - - return true; -} - -/* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON * const item, printbuffer * const p, const internal_hooks * const hooks) -{ - return print_string_ptr((unsigned char*)item->valuestring, p, hooks); -} - -/* Predeclare these prototypes. */ -static const unsigned char *parse_value(cJSON * const item, const unsigned char * const input, const unsigned char ** const ep, const internal_hooks * const hooks); -static cJSON_bool print_value(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks); -static const unsigned char *parse_array(cJSON * const item, const unsigned char *input, const unsigned char ** const ep, const internal_hooks * const hooks); -static cJSON_bool print_array(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks); -static const unsigned char *parse_object(cJSON * const item, const unsigned char *input, const unsigned char ** const ep, const internal_hooks * const hooks); -static cJSON_bool print_object(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks); - -/* Utility to jump whitespace and cr/lf */ -static const unsigned char *skip_whitespace(const unsigned char *in) -{ - while (in && *in && (*in <= 32)) - { - in++; - } - - return in; -} - -/* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) -{ - const unsigned char *end = NULL; - /* use global error pointer if no specific one was given */ - const unsigned char **ep = return_parse_end ? (const unsigned char**)return_parse_end : &global_ep; - cJSON *c = cJSON_New_Item(&global_hooks); - *ep = NULL; - if (!c) /* memory fail */ - { - return NULL; - } - - end = parse_value(c, skip_whitespace((const unsigned char*)value), ep, &global_hooks); - if (!end) - { - /* parse failure. ep is set. */ - cJSON_Delete(c); - return NULL; - } - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) - { - end = skip_whitespace(end); - if (*end) - { - cJSON_Delete(c); - *ep = end; - return NULL; - } - } - if (return_parse_end) - { - *return_parse_end = (const char*)end; - } - - return c; -} - -/* Default options for cJSON_Parse */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) -{ - return cJSON_ParseWithOpts(value, 0, 0); -} - -#define min(a, b) ((a < b) ? a : b) - -static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) -{ - printbuffer buffer[1]; - unsigned char *printed = NULL; - - memset(buffer, 0, sizeof(buffer)); - - /* create buffer */ - buffer->buffer = (unsigned char*) hooks->allocate(256); - if (buffer->buffer == NULL) - { - goto fail; - } - - /* print the value */ - if (!print_value(item, 0, format, buffer, hooks)) - { - goto fail; - } - update_offset(buffer); - - /* copy the buffer over to a new one */ - printed = (unsigned char*) hooks->allocate(buffer->offset + 1); - if (printed == NULL) - { - goto fail; - } - strncpy((char*)printed, (char*)buffer->buffer, min(buffer->length, buffer->offset + 1)); - printed[buffer->offset] = '\0'; /* just to be sure */ - - /* free the buffer */ - hooks->deallocate(buffer->buffer); - - return printed; - -fail: - if (buffer->buffer != NULL) - { - hooks->deallocate(buffer->buffer); - } - - if (printed != NULL) - { - hooks->deallocate(printed); - } - - return NULL; -} - -/* Render a cJSON item/entity/structure to text. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) -{ - return (char*)print(item, true, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) -{ - return (char*)print(item, false, &global_hooks); -} - -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) -{ - printbuffer p; - - if (prebuffer < 0) - { - return NULL; - } - - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) - { - return NULL; - } - - p.length = (size_t)prebuffer; - p.offset = 0; - p.noalloc = false; - - if (!print_value(item, 0, fmt, &p, &global_hooks)) - { - return NULL; - } - - return (char*)p.buffer; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt) -{ - printbuffer p; - - if (len < 0) - { - return false; - } - - p.buffer = (unsigned char*)buf; - p.length = (size_t)len; - p.offset = 0; - p.noalloc = true; - return print_value(item, 0, fmt, &p, &global_hooks); -} - -/* Parser core - when encountering text, process appropriately. */ -static const unsigned char *parse_value(cJSON * const item, const unsigned char * const input, const unsigned char ** const error_pointer, const internal_hooks * const hooks) -{ - if (input == NULL) - { - return NULL; /* no input */ - } - - /* parse the different types of values */ - /* null */ - if (!strncmp((const char*)input, "null", 4)) - { - item->type = cJSON_NULL; - return input + 4; - } - /* false */ - if (!strncmp((const char*)input, "false", 5)) - { - item->type = cJSON_False; - return input + 5; - } - /* true */ - if (!strncmp((const char*)input, "true", 4)) - { - item->type = cJSON_True; - item->valueint = 1; - return input + 4; - } - /* string */ - if (*input == '\"') - { - return parse_string(item, input, error_pointer, hooks); - } - /* number */ - if ((*input == '-') || ((*input >= '0') && (*input <= '9'))) - { - return parse_number(item, input); - } - /* array */ - if (*input == '[') - { - return parse_array(item, input, error_pointer, hooks); - } - /* object */ - if (*input == '{') - { - return parse_object(item, input, error_pointer, hooks); - } - - /* failure. */ - *error_pointer = input; - return NULL; -} - -/* Render a value to text. */ -static cJSON_bool print_value(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks) -{ - unsigned char *output = NULL; - - if ((item == NULL) || (output_buffer == NULL)) - { - return false; - } - - switch ((item->type) & 0xFF) - { - case cJSON_NULL: - output = ensure(output_buffer, 5, hooks); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "null"); - return true; - - case cJSON_False: - output = ensure(output_buffer, 6, hooks); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "false"); - return true; - - case cJSON_True: - output = ensure(output_buffer, 5, hooks); - if (output == NULL) - { - return false; - } - strcpy((char*)output, "true"); - return true; - - case cJSON_Number: - return print_number(item, output_buffer, hooks); - - case cJSON_Raw: - { - size_t raw_length = 0; - if (item->valuestring == NULL) - { - if (!output_buffer->noalloc) - { - hooks->deallocate(output_buffer->buffer); - } - return false; - } - - raw_length = strlen(item->valuestring) + sizeof(""); - output = ensure(output_buffer, raw_length, hooks); - if (output == NULL) - { - return false; - } - memcpy(output, item->valuestring, raw_length); - return true; - } - - case cJSON_String: - return print_string(item, output_buffer, hooks); - - case cJSON_Array: - return print_array(item, depth, format, output_buffer, hooks); - - case cJSON_Object: - return print_object(item, depth, format, output_buffer, hooks); - - default: - return false; - } -} - -/* Build an array from input text. */ -static const unsigned char *parse_array(cJSON * const item, const unsigned char *input, const unsigned char ** const error_pointer, const internal_hooks * const hooks) -{ - cJSON *head = NULL; /* head of the linked list */ - cJSON *current_item = NULL; - - if (*input != '[') - { - /* not an array */ - *error_pointer = input; - goto fail; - } - - input = skip_whitespace(input + 1); - if (*input == ']') - { - /* empty array */ - goto success; - } - - /* step back to character in front of the first element */ - input--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(hooks); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse next value */ - input = skip_whitespace(input + 1); - input = parse_value(current_item, input, error_pointer, hooks); - input = skip_whitespace(input); - if (input == NULL) - { - goto fail; /* failed to parse value */ - } - } - while (*input == ','); - - if (*input != ']') - { - *error_pointer = input; - goto fail; /* expected end of array */ - } - -success: - item->type = cJSON_Array; - item->child = head; - - return input + 1; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return NULL; -} - -/* Render an array to text */ -static cJSON_bool print_array(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_element = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output array. */ - /* opening square bracket */ - output_pointer = ensure(output_buffer, 1, hooks); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer = '['; - output_buffer->offset++; - - while (current_element != NULL) - { - if (!print_value(current_element, depth + 1, format, output_buffer, hooks)) - { - return false; - } - update_offset(output_buffer); - if (current_element->next) - { - length = (size_t) (format ? 2 : 1); - output_pointer = ensure(output_buffer, length + 1, hooks); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ','; - if(format) - { - *output_pointer++ = ' '; - } - *output_pointer = '\0'; - output_buffer->offset += length; - } - current_element = current_element->next; - } - - output_pointer = ensure(output_buffer, 2, hooks); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ']'; - *output_pointer = '\0'; - - return true; -} - -/* Build an object from the text. */ -static const unsigned char *parse_object(cJSON * const item, const unsigned char *input, const unsigned char ** const error_pointer, const internal_hooks * const hooks) -{ - cJSON *head = NULL; /* linked list head */ - cJSON *current_item = NULL; - - if (*input != '{') - { - *error_pointer = input; - goto fail; /* not an object */ - } - - input = skip_whitespace(input + 1); - if (*input == '}') - { - goto success; /* empty object */ - } - - /* step back to character in front of the first element */ - input--; - /* loop through the comma separated array elements */ - do - { - /* allocate next item */ - cJSON *new_item = cJSON_New_Item(hooks); - if (new_item == NULL) - { - goto fail; /* allocation failure */ - } - - /* attach next item to list */ - if (head == NULL) - { - /* start the linked list */ - current_item = head = new_item; - } - else - { - /* add to the end and advance */ - current_item->next = new_item; - new_item->prev = current_item; - current_item = new_item; - } - - /* parse the name of the child */ - input = skip_whitespace(input + 1); - input = parse_string(current_item, input, error_pointer, hooks); - input = skip_whitespace(input); - if (input == NULL) - { - goto fail; /* faile to parse name */ - } - - /* swap valuestring and string, because we parsed the name */ - current_item->string = current_item->valuestring; - current_item->valuestring = NULL; - - if (*input != ':') - { - *error_pointer = input; - goto fail; /* invalid object */ - } - - /* parse the value */ - input = skip_whitespace(input + 1); - input = parse_value(current_item, input, error_pointer, hooks); - input = skip_whitespace(input); - if (input == NULL) - { - goto fail; /* failed to parse value */ - } - } - while (*input == ','); - - if (*input != '}') - { - *error_pointer = input; - goto fail; /* expected end of object */ - } - -success: - item->type = cJSON_Object; - item->child = head; - - return input + 1; - -fail: - if (head != NULL) - { - cJSON_Delete(head); - } - - return NULL; -} - -/* Render an object to text. */ -static cJSON_bool print_object(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks) -{ - unsigned char *output_pointer = NULL; - size_t length = 0; - cJSON *current_item = item->child; - - if (output_buffer == NULL) - { - return false; - } - - /* Compose the output: */ - length = (size_t) (format ? 2 : 1); /* fmt: {\n */ - output_pointer = ensure(output_buffer, length + 1, hooks); - if (output_pointer == NULL) - { - return false; - } - - *output_pointer++ = '{'; - if (format) - { - *output_pointer++ = '\n'; - } - output_buffer->offset += length; - - while (current_item) - { - if (format) - { - size_t i; - output_pointer = ensure(output_buffer, depth + 1, hooks); - if (output_pointer == NULL) - { - return false; - } - for (i = 0; i < depth + 1; i++) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += depth + 1; - } - - /* print key */ - if (!print_string_ptr((unsigned char*)current_item->string, output_buffer, hooks)) - { - return false; - } - update_offset(output_buffer); - - length = (size_t) (format ? 2 : 1); - output_pointer = ensure(output_buffer, length, hooks); - if (output_pointer == NULL) - { - return false; - } - *output_pointer++ = ':'; - if (format) - { - *output_pointer++ = '\t'; - } - output_buffer->offset += length; - - /* print value */ - if (!print_value(current_item, depth + 1, format, output_buffer, hooks)) - { - return false; - } - update_offset(output_buffer); - - /* print comma if not last */ - length = (size_t) ((format ? 1 : 0) + (current_item->next ? 1 : 0)); - output_pointer = ensure(output_buffer, length + 1, hooks); - if (output_pointer == NULL) - { - return false; - } - if (current_item->next) - { - *output_pointer++ = ','; - } - - if (format) - { - *output_pointer++ = '\n'; - } - *output_pointer = '\0'; - output_buffer->offset += length; - - current_item = current_item->next; - } - - output_pointer = ensure(output_buffer, format ? (depth + 2) : 2, hooks); - if (output_pointer == NULL) - { - return false; - } - if (format) - { - size_t i; - for (i = 0; i < (depth); i++) - { - *output_pointer++ = '\t'; - } - } - *output_pointer++ = '}'; - *output_pointer = '\0'; - - return true; -} - -/* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) -{ - cJSON *c = array->child; - size_t i = 0; - while(c) - { - i++; - c = c->next; - } - - /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ - - return (int)i; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item) -{ - cJSON *c = array ? array->child : NULL; - while (c && item > 0) - { - item--; - c = c->next; - } - - return c; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string) -{ - cJSON *c = object ? object->child : NULL; - while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string)) - { - c = c->next; - } - return c; -} - -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) -{ - cJSON *current_element = NULL; - - if ((object == NULL) || (string == NULL)) - { - return NULL; - } - - current_element = object->child; - while ((current_element != NULL) && (strcmp(string, current_element->string) != 0)) - { - current_element = current_element->next; - } - - return current_element; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) -{ - return cJSON_GetObjectItem(object, string) ? 1 : 0; -} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev, cJSON *item) -{ - prev->next = item; - item->prev = prev; -} - -/* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) -{ - cJSON *ref = cJSON_New_Item(hooks); - if (!ref) - { - return NULL; - } - memcpy(ref, item, sizeof(cJSON)); - ref->string = NULL; - ref->type |= cJSON_IsReference; - ref->next = ref->prev = NULL; - return ref; -} - -/* Add item to array/object. */ -CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) -{ - cJSON *child = NULL; - - if ((item == NULL) || (array == NULL)) - { - return; - } - - child = array->child; - - if (child == NULL) - { - /* list is empty, start new one */ - array->child = item; - } - else - { - /* append to the end */ - while (child->next) - { - child = child->next; - } - suffix_object(child, item); - } -} - -CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) -{ - /* call cJSON_AddItemToObjectCS for code reuse */ - cJSON_AddItemToObjectCS(object, (char*)cJSON_strdup((const unsigned char*)string, &global_hooks), item); - /* remove cJSON_StringIsConst flag */ - item->type &= ~cJSON_StringIsConst; -} - -#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic push -#endif -#pragma GCC diagnostic ignored "-Wcast-qual" -/* Add an item to an object with constant string as key */ -CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) -{ - if (!item) - { - return; - } - if (!(item->type & cJSON_StringIsConst) && item->string) - { - global_hooks.deallocate(item->string); - } - item->string = (char*)string; - item->type |= cJSON_StringIsConst; - cJSON_AddItemToArray(object, item); -} -#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic pop -#endif - -CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) -{ - cJSON_AddItemToArray(array, create_reference(item, &global_hooks)); -} - -CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) -{ - cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks)); -} - -static cJSON *DetachItemFromArray(cJSON *array, size_t which) -{ - cJSON *c = array->child; - while (c && (which > 0)) - { - c = c->next; - which--; - } - if (!c) - { - /* item doesn't exist */ - return NULL; - } - if (c->prev) - { - /* not the first element */ - c->prev->next = c->next; - } - if (c->next) - { - c->next->prev = c->prev; - } - if (c==array->child) - { - array->child = c->next; - } - /* make sure the detached item doesn't point anywhere anymore */ - c->prev = c->next = NULL; - - return c; -} -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) -{ - if (which < 0) - { - return NULL; - } - - return DetachItemFromArray(array, (size_t)which); -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) -{ - cJSON_Delete(cJSON_DetachItemFromArray(array, which)); -} - -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) -{ - size_t i = 0; - cJSON *c = object->child; - while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string)) - { - i++; - c = c->next; - } - if (c) - { - return DetachItemFromArray(object, i); - } - - return NULL; -} - -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) -{ - cJSON_Delete(cJSON_DetachItemFromObject(object, string)); -} - -/* Replace array/object items with new ones. */ -CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) -{ - cJSON *c = array->child; - while (c && (which > 0)) - { - c = c->next; - which--; - } - if (!c) - { - cJSON_AddItemToArray(array, newitem); - return; - } - newitem->next = c; - newitem->prev = c->prev; - c->prev = newitem; - if (c == array->child) - { - array->child = newitem; - } - else - { - newitem->prev->next = newitem; - } -} - -static void ReplaceItemInArray(cJSON *array, size_t which, cJSON *newitem) -{ - cJSON *c = array->child; - while (c && (which > 0)) - { - c = c->next; - which--; - } - if (!c) - { - return; - } - newitem->next = c->next; - newitem->prev = c->prev; - if (newitem->next) - { - newitem->next->prev = newitem; - } - if (c == array->child) - { - array->child = newitem; - } - else - { - newitem->prev->next = newitem; - } - c->next = c->prev = NULL; - cJSON_Delete(c); -} -CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) -{ - if (which < 0) - { - return; - } - - ReplaceItemInArray(array, (size_t)which, newitem); -} - -CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) -{ - size_t i = 0; - cJSON *c = object->child; - while(c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string)) - { - i++; - c = c->next; - } - if(c) - { - /* free the old string if not const */ - if (!(newitem->type & cJSON_StringIsConst) && newitem->string) - { - global_hooks.deallocate(newitem->string); - } - - newitem->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - ReplaceItemInArray(object, i, newitem); - } -} - -/* Create basic types: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_NULL; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_True; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = b ? cJSON_True : cJSON_False; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Number; - item->valuedouble = num; - - /* use saturation in case of overflow */ - if (num >= INT_MAX) - { - item->valueint = INT_MAX; - } - else if (num <= INT_MIN) - { - item->valueint = INT_MIN; - } - else - { - item->valueint = (int)num; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); - if(!item->valuestring) - { - cJSON_Delete(item); - return NULL; - } - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type=cJSON_Array; - } - - return item; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) -{ - cJSON *item = cJSON_New_Item(&global_hooks); - if (item) - { - item->type = cJSON_Object; - } - - return item; -} - -/* Create Arrays: */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if (count < 0) - { - return NULL; - } - - a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if (!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if (count < 0) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber((double)numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if (count < 0) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for(i = 0;a && (i < (size_t)count); i++) - { - n = cJSON_CreateNumber(numbers[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p, n); - } - p = n; - } - - return a; -} - -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) -{ - size_t i = 0; - cJSON *n = NULL; - cJSON *p = NULL; - cJSON *a = NULL; - - if (count < 0) - { - return NULL; - } - - a = cJSON_CreateArray(); - - for (i = 0; a && (i < (size_t)count); i++) - { - n = cJSON_CreateString(strings[i]); - if(!n) - { - cJSON_Delete(a); - return NULL; - } - if(!i) - { - a->child = n; - } - else - { - suffix_object(p,n); - } - p = n; - } - - return a; -} - -/* Duplication */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) -{ - cJSON *newitem = NULL; - cJSON *child = NULL; - cJSON *next = NULL; - cJSON *newchild = NULL; - - /* Bail on bad ptr */ - if (!item) - { - goto fail; - } - /* Create new item */ - newitem = cJSON_New_Item(&global_hooks); - if (!newitem) - { - goto fail; - } - /* Copy over all vars */ - newitem->type = item->type & (~cJSON_IsReference); - newitem->valueint = item->valueint; - newitem->valuedouble = item->valuedouble; - if (item->valuestring) - { - newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); - if (!newitem->valuestring) - { - goto fail; - } - } - if (item->string) - { - newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); - if (!newitem->string) - { - goto fail; - } - } - /* If non-recursive, then we're done! */ - if (!recurse) - { - return newitem; - } - /* Walk the ->next chain for the child. */ - child = item->child; - while (child != NULL) - { - newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) - { - goto fail; - } - if (next != NULL) - { - /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - next->next = newchild; - newchild->prev = next; - next = newchild; - } - else - { - /* Set newitem->child and move to it */ - newitem->child = newchild; - next = newchild; - } - child = child->next; - } - - return newitem; - -fail: - if (newitem != NULL) - { - cJSON_Delete(newitem); - } - - return NULL; -} - -CJSON_PUBLIC(void) cJSON_Minify(char *json) -{ - unsigned char *into = (unsigned char*)json; - while (*json) - { - if (*json == ' ') - { - json++; - } - else if (*json == '\t') - { - /* Whitespace characters. */ - json++; - } - else if (*json == '\r') - { - json++; - } - else if (*json=='\n') - { - json++; - } - else if ((*json == '/') && (json[1] == '/')) - { - /* double-slash comments, to end of line. */ - while (*json && (*json != '\n')) - { - json++; - } - } - else if ((*json == '/') && (json[1] == '*')) - { - /* multiline comments. */ - while (*json && !((*json == '*') && (json[1] == '/'))) - { - json++; - } - json += 2; - } - else if (*json == '\"') - { - /* string literals, which are \" sensitive. */ - *into++ = (unsigned char)*json++; - while (*json && (*json != '\"')) - { - if (*json == '\\') - { - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - *into++ = (unsigned char)*json++; - } - else - { - /* All other characters. */ - *into++ = (unsigned char)*json++; - } - } - - /* and null-terminate. */ - *into = '\0'; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Invalid; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_False; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xff) == cJSON_True; -} - - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & (cJSON_True | cJSON_False)) != 0; -} -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_NULL; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Number; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_String; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Array; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Object; -} - -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) -{ - if (item == NULL) - { - return false; - } - - return (item->type & 0xFF) == cJSON_Raw; -} diff --git a/cJSON/cJSON.h b/cJSON/cJSON.h deleted file mode 100644 index 6d99951..0000000 --- a/cJSON/cJSON.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* project version */ -#define CJSON_VERSION_MAJOR 1 -#define CJSON_VERSION_MINOR 4 -#define CJSON_VERSION_PATCH 7 - -#include <stddef.h> - -/* cJSON Types: */ -#define cJSON_Invalid (0) -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) -#define cJSON_Number (1 << 3) -#define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) -#define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ - -#define cJSON_IsReference 256 -#define cJSON_StringIsConst 512 - -/* The cJSON structure: */ -typedef struct cJSON -{ - /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *next; - struct cJSON *prev; - /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - struct cJSON *child; - - /* The type of the item, as above. */ - int type; - - /* The item's string, if type==cJSON_String and type == cJSON_Raw */ - char *valuestring; - /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ - int valueint; - /* The item's number, if type==cJSON_Number */ - double valuedouble; - - /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ - char *string; -} cJSON; - -typedef struct cJSON_Hooks -{ - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); -} cJSON_Hooks; - -typedef int cJSON_bool; - -#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) -#define __WINDOWS__ -#endif -#ifdef __WINDOWS__ - -/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options: - -CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols -CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) -CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol - -For *nix builds that support visibility attribute, you can define similar behavior by - -setting default visibility to hidden by adding --fvisibility=hidden (for gcc) -or --xldscope=hidden (for sun cc) -to CFLAGS - -then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does - -*/ - -/* export symbols by default, this is necessary for copy pasting the C and header file */ -#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_EXPORT_SYMBOLS -#endif - -#if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type __stdcall -#elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall -#elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall -#endif -#else /* !WIN32 */ -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type -#else -#define CJSON_PUBLIC(type) type -#endif -#endif - -/* returns the version of cJSON as a string */ -CJSON_PUBLIC(const char*) cJSON_Version(void); - -/* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); - - -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ -CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); -/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ -CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ -CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); -/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ -CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); -/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ -/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ -CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); -/* Delete a cJSON entity and all subentities. */ -CJSON_PUBLIC(void) cJSON_Delete(cJSON *c); - -/* Returns the number of items in an array (or object). */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); -/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ -CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item); -/* Get item "string" from object. Case insensitive. */ -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *object, const char *string); -CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); - -/* These functions check the type of an item */ -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); - -/* These calls create a cJSON item of the appropriate type. */ -CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); -CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); -CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); -/* raw json */ -CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); -CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); -CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); - -/* These utilities create an Array of count items. */ -CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); -CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count); - -/* Append item to the specified array/object. */ -CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); -/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. - * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before - * writing to `item->string` */ -CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); - -/* Remove/Detatch items from Arrays/Objects. */ -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); -CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); -CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); - -/* Update array items. */ -CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ -CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); - -/* Duplicate a cJSON item */ -CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will -need to be released. With recurse!=0, it will duplicate any children connected to the item. -The item->next and ->prev pointers are always zero on return from Duplicate. */ - -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); - -CJSON_PUBLIC(void) cJSON_Minify(char *json); - -/* Macros for creating things quickly. */ -#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) -#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) -#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) -#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) -#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) -#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) -#define cJSON_AddRawToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateRaw(s)) - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) -/* helper for the cJSON_SetNumberValue macro */ -CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); -#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) - -/* Macro for iterating over an array */ -#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/meson.build b/meson.build index bab92df..9d8f9f7 100644 --- a/meson.build +++ b/meson.build @@ -65,27 +65,22 @@ dsp_srcs = [ 'patchmatrix_nk.c' ] -cjson_lib = static_library('cJSON', join_paths('cJSON', 'cJSON.c')) - executable('patchmatrix', [dsp_srcs], c_args : c_args, dependencies : [dsp_deps, ui_deps], include_directories : incs, - link_with : cjson_lib, install : true) executable('patchmatrix_mixer', 'patchmatrix_mixer.c', c_args : c_args, dependencies : [dsp_deps, ui_deps], include_directories : incs, - link_with : cjson_lib, install : true) executable('patchmatrix_monitor', 'patchmatrix_monitor.c', c_args : c_args, dependencies : [dsp_deps, ui_deps], include_directories : incs, - link_with : cjson_lib, install : true) configure_file( diff --git a/patchmatrix.1 b/patchmatrix.1 index 08c7c6d..d4dc455 100644 --- a/patchmatrix.1 +++ b/patchmatrix.1 @@ -1,4 +1,4 @@ -.TH PATCHMATRIX "1" "Apr 13, 2020" +.TH PATCHMATRIX "1" "Jul 08, 2021" .SH NAME patchmatrix \- a JACK patchbay @@ -35,16 +35,6 @@ Print usage information .IP Connect to named JACK daemon -.HP -\fB\-u\fR client-uuid -.IP -Client UUID for JACK session management - -.HP -\fB\-d\fR session-dir -.IP -Directory for JACK session management - .SH LICENSE Artistic License 2.0. diff --git a/patchmatrix.c b/patchmatrix.c index a20eb09..884165a 100644 --- a/patchmatrix.c +++ b/patchmatrix.c @@ -56,7 +56,6 @@ main(int argc, char **argv) app.nxt_default = 30; app.server_name = NULL; - app.session_id = NULL; fprintf(stderr, "%s "PATCHMATRIX_VERSION"\n" @@ -64,7 +63,7 @@ main(int argc, char **argv) "Released under Artistic License 2.0 by Open Music Kontrollers\n", argv[0]); int c; - while((c = getopt(argc, argv, "vhn:u:d:")) != -1) + while((c = getopt(argc, argv, "vhn:")) != -1) { switch(c) { @@ -93,20 +92,12 @@ main(int argc, char **argv) "OPTIONS\n" " [-v] print version and full license information\n" " [-h] print usage information\n" - " [-n] server-name connect to named JACK daemon\n" - " [-u] client-uuid client UUID for JACK session management\n" - " [-d] session-dir directory for JACK session management\n\n" + " [-n] server-name connect to named JACK daemon\n\n" , argv[0]); return 0; case 'n': app.server_name = optarg; break; - case 'u': - app.session_id = optarg; - break; - case 'd': - app.root = _load_session(optarg); - break; case '?': if( (optopt == 'n') || (optopt == 'u') || (optopt == 'd') ) fprintf(stderr, "Option `-%c' requires an argument.\n", optopt); @@ -162,8 +153,5 @@ cleanup: _ui_deinit(&app); - if(app.root) - cJSON_Delete(app.root); - return 0; } diff --git a/patchmatrix.h b/patchmatrix.h index e647f95..0bce641 100644 --- a/patchmatrix.h +++ b/patchmatrix.h @@ -29,7 +29,6 @@ #include <semaphore.h> #include <jack/jack.h> -#include <jack/session.h> #include <jack/midiport.h> #ifdef JACK_HAS_METADATA_API # include <jack/uuid.h> @@ -37,8 +36,6 @@ # include <jackey.h> #endif -#include <cJSON/cJSON.h> - #include <lv2/lv2plug.in/ns/ext/port-groups/port-groups.h> #include <lv2/lv2plug.in/ns/extensions/ui/ui.h> @@ -89,7 +86,6 @@ enum _event_type_t { EVENT_PORT_CONNECT, EVENT_ON_INFO_SHUTDOWN, EVENT_GRAPH_ORDER, - EVENT_SESSION, EVENT_FREEWHEEL, EVENT_BUFFER_SIZE, EVENT_SAMPLE_RATE, @@ -244,10 +240,6 @@ struct _event_t { } on_info_shutdown; struct { - jack_session_event_t *event; - } session; - - struct { int starting; } freewheel; @@ -286,7 +278,6 @@ struct _app_t { varchunk_t *from_jack; const char *server_name; - const char *session_id; nk_pugl_window_t win; @@ -313,8 +304,6 @@ struct _app_t { atomic_bool done; bool animating; struct nk_rect contextbounds; - - cJSON *root; }; #define HASH_FOREACH(hash, itr) \ @@ -484,66 +473,6 @@ _mkdirp(const char* path, mode_t mode) return ret; } -static cJSON * -_load_session(const char *session_dir) -{ - cJSON *root = NULL; - - // path may not exist yet - _mkdirp(session_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - - char *session_file; - if(asprintf(&session_file, "%s%s", session_dir, "state.json") != -1) - { - FILE *file = fopen(session_file, "r"); - if(file) - { - fseek(file, 0, SEEK_END); - const size_t sz = ftell(file); - fseek(file, 0, SEEK_SET); - - char *buf = malloc(sz + 1); - if(buf) - { - if(fread(buf, sz, 1, file) == 1) - { - buf[sz] = '\0'; - root = cJSON_Parse(buf); - } - free(buf); - } - fclose(file); - } - free(session_file); - } - - return root; -} - -static void -_save_session(cJSON *root, const char *session_dir) -{ - // path may not exist yet - _mkdirp(session_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - - char *buf = cJSON_Print(root); - if(buf) - { - char *session_file; - if(asprintf(&session_file, "%s%s", session_dir, "state.json") != -1) - { - FILE *file = fopen(session_file, "w"); - if(file) - { - fwrite(buf, strlen(buf), 1, file); - fclose(file); - } - free(session_file); - } - free(buf); - } -} - static const char *port_labels [] = { [TYPE_NONE] = NULL, [TYPE_AUDIO] = "AUDIO", diff --git a/patchmatrix_db.c b/patchmatrix_db.c index 54285e8..f20005a 100644 --- a/patchmatrix_db.c +++ b/patchmatrix_db.c @@ -110,47 +110,6 @@ _client_add(app_t *app, const char *client_name, int client_flags) jack_free(client_uuid_str); } - if(app->root) - { - cJSON *clients_node = cJSON_GetObjectItem(app->root, "clients"); - if(clients_node && cJSON_IsArray(clients_node)) - { - cJSON *client_node; - cJSON_ArrayForEach(client_node, clients_node) - { - cJSON *uuid_node = cJSON_GetObjectItem(client_node, "client_uuid"); - if(uuid_node && cJSON_IsString(uuid_node)) - { - jack_uuid_t client_uuid; - jack_uuid_parse(uuid_node->valuestring, &client_uuid); - - int flags = 0; - - cJSON *sinks_node = cJSON_GetObjectItem(client_node, "sinks"); - if(sinks_node && (sinks_node->type == cJSON_True) ) - flags |= JackPortIsInput; - - cJSON *sources_node = cJSON_GetObjectItem(client_node, "sources"); - if(sources_node && (sources_node->type == cJSON_True) ) - flags |= JackPortIsOutput; - - if(!jack_uuid_compare(client_uuid, client->uuid) && (client->flags == flags) ) - { - cJSON *xpos_node = cJSON_GetObjectItem(client_node, "xpos"); - if(xpos_node && cJSON_IsNumber(xpos_node)) - client->pos.x = xpos_node->valuedouble; - - cJSON *ypos_node = cJSON_GetObjectItem(client_node, "ypos"); - if(ypos_node && cJSON_IsNumber(ypos_node)) - client->pos.y = ypos_node->valuedouble; - - break; // exit loop - } - } - } - } - } - #ifdef JACK_HAS_METADATA_API { char *value = NULL; @@ -385,42 +344,6 @@ _client_conn_add(app_t *app, client_t *source_client, client_t *sink_client) (source_client->pos.y + sink_client->pos.y)/2); client_conn->type = TYPE_NONE; - if(app->root) - { - cJSON *conns_node = cJSON_GetObjectItem(app->root, "conns"); - if(conns_node && cJSON_IsArray(conns_node)) - { - cJSON *conn_node; - cJSON_ArrayForEach(conn_node, conns_node) - { - cJSON *source_uuid_node = cJSON_GetObjectItem(conn_node, "source_uuid"); - cJSON *sink_uuid_node = cJSON_GetObjectItem(conn_node, "sink_uuid"); - if( source_uuid_node && cJSON_IsString(source_uuid_node) - && sink_uuid_node && cJSON_IsString(sink_uuid_node) ) - { - jack_uuid_t source_uuid; - jack_uuid_t sink_uuid; - jack_uuid_parse(source_uuid_node->valuestring, &source_uuid); - jack_uuid_parse(sink_uuid_node->valuestring, &sink_uuid); - - if( !jack_uuid_compare(source_uuid, client_conn->source_client->uuid) - && !jack_uuid_compare(sink_uuid, client_conn->sink_client->uuid) ) - { - cJSON *xpos_node = cJSON_GetObjectItem(conn_node, "xpos"); - if(xpos_node && cJSON_IsNumber(xpos_node)) - client_conn->pos.x = xpos_node->valuedouble; - - cJSON *ypos_node = cJSON_GetObjectItem(conn_node, "ypos"); - if(ypos_node && cJSON_IsNumber(ypos_node)) - client_conn->pos.y = ypos_node->valuedouble; - - break; // exit loop - } - } - } - } - } - _hash_add(&app->conns, client_conn); } diff --git a/patchmatrix_jack.c b/patchmatrix_jack.c index b845ac1..fd3dfa7 100644 --- a/patchmatrix_jack.c +++ b/patchmatrix_jack.c @@ -19,72 +19,6 @@ #include <patchmatrix_db.h> #include <patchmatrix_nk.h> -static cJSON * -_create_session(app_t *app) -{ - cJSON *root = cJSON_CreateObject(); - if(root) - { - cJSON *clients_node = cJSON_CreateArray(); - if(clients_node) - { - HASH_FOREACH(&app->clients, client_itr) - { - client_t *client = *client_itr; - - cJSON *client_node = cJSON_CreateObject(); - if(client_node) - { - char uuid_str [JACK_UUID_STRING_SIZE]; - jack_uuid_unparse(client->uuid, uuid_str); - - cJSON_AddStringToObject(client_node, "client_name", client->name); - cJSON_AddStringToObject(client_node, "client_uuid", uuid_str); - cJSON_AddNumberToObject(client_node, "xpos", client->pos.x); - cJSON_AddNumberToObject(client_node, "ypos", client->pos.y); - cJSON_AddBoolToObject(client_node, "sinks", client->flags & JackPortIsInput); - cJSON_AddBoolToObject(client_node, "sources", client->flags & JackPortIsOutput); - - cJSON_AddItemToArray(clients_node, client_node); - } - } - - cJSON_AddItemToObject(root, "clients", clients_node); - } - - cJSON *conns_node = cJSON_CreateArray(); - if(conns_node) - { - HASH_FOREACH(&app->conns, client_conn_itr) - { - client_conn_t *client_conn = *client_conn_itr; - - cJSON *conn_node = cJSON_CreateObject(); - if(conn_node) - { - char source_uuid_str [JACK_UUID_STRING_SIZE]; - char sink_uuid_str [JACK_UUID_STRING_SIZE]; - jack_uuid_unparse(client_conn->source_client->uuid, source_uuid_str); - jack_uuid_unparse(client_conn->sink_client->uuid, sink_uuid_str); - - cJSON_AddStringToObject(conn_node, "source_name", client_conn->source_client->name); - cJSON_AddStringToObject(conn_node, "sink_name", client_conn->sink_client->name); - cJSON_AddStringToObject(conn_node, "source_uuid", source_uuid_str); - cJSON_AddStringToObject(conn_node, "sink_uuid", sink_uuid_str); - cJSON_AddNumberToObject(conn_node, "xpos", client_conn->pos.x); - cJSON_AddNumberToObject(conn_node, "ypos", client_conn->pos.y); - - cJSON_AddItemToArray(conns_node, conn_node); - } - } - - cJSON_AddItemToObject(root, "conns", conns_node); - } - } - - return root; -} - bool _jack_anim(app_t *app) { @@ -446,38 +380,6 @@ _jack_anim(app_t *app) //FIXME } break; - case EVENT_SESSION: - { - jack_session_event_t *jev = ev->session.event; - - asprintf(&jev->command_line, "patchmatrix -u %s -d ${SESSION_DIR}", - jev->client_uuid); - - switch(jev->type) - { - case JackSessionSave: - case JackSessionSaveAndQuit: - { - cJSON *root = _create_session(app); - if(root) - { - _save_session(root, jev->session_dir); - cJSON_Delete(root); - } - - if(jev->type == JackSessionSaveAndQuit) - quit = true; - } break; - case JackSessionSaveTemplate: - { - // nothing - } break; - } - - jack_session_reply(app->client, jev); - jack_session_event_free(jev); - } break; - case EVENT_FREEWHEEL: { app->freewheel = ev->freewheel.starting; @@ -738,22 +640,6 @@ _jack_property_change_cb(jack_uuid_t uuid, const char *key, jack_property_change #endif static void -_jack_session_cb(jack_session_event_t *jev, void *arg) -{ - app_t *app = arg; - - event_t *ev; - if((ev = varchunk_write_request(app->from_jack, sizeof(event_t)))) - { - ev->type = EVENT_SESSION; - ev->session.event = jev; - - varchunk_write_advance(app->from_jack, sizeof(event_t)); - _ui_signal(app); - } -} - -static void _jack_populate(app_t *app) { const char **port_names = jack_get_ports(app->client, NULL, NULL, 0); @@ -823,13 +709,10 @@ _jack_init(app_t *app) jack_options_t opts = JackNullOption | JackNoStartServer; if(app->server_name) opts |= JackServerName; - if(app->session_id) - opts |= JackSessionID; jack_status_t status; app->client = jack_client_open("patchmatrix", opts, &status, - app->server_name ? app->server_name : app->session_id, - app->server_name ? app->session_id : NULL); + app->server_name ? app->server_name : NULL); if(!app->client) return -1; @@ -870,7 +753,6 @@ _jack_init(app_t *app) jack_set_port_connect_callback(app->client, _jack_port_connect_cb, app); jack_set_xrun_callback(app->client, _jack_xrun_cb, app); jack_set_graph_order_callback(app->client, _jack_graph_order_cb, app); - jack_set_session_callback(app->client, _jack_session_cb, app); #ifdef JACK_HAS_PORT_RENAME_CALLBACK jack_set_port_rename_callback(app->client, _jack_port_rename_cb, app); #endif diff --git a/patchmatrix_mixer.1 b/patchmatrix_mixer.1 index 388ccbe..afa588e 100644 --- a/patchmatrix_mixer.1 +++ b/patchmatrix_mixer.1 @@ -1,4 +1,4 @@ -.TH PATCHMATRIX_MIXER "1" "Apr 13, 2020" +.TH PATCHMATRIX_MIXER "1" "Jul 18, 2021" .SH NAME patchmatrix_mixer \- a JACK port mixer @@ -45,16 +45,6 @@ Number of output ports (1-128) .IP Connect to named JACK daemon -.HP -\fB\-u\fR client-uuid -.IP -Client UUID for JACK session management - -.HP -\fB\-d\fR session-dir -.IP -Directory for JACK session management - .SH LICENSE Artistic License 2.0. diff --git a/patchmatrix_mixer.c b/patchmatrix_mixer.c index bf13c39..243062a 100644 --- a/patchmatrix_mixer.c +++ b/patchmatrix_mixer.c @@ -369,86 +369,13 @@ _midi_mixer_process(jack_nframes_t nframes, void *arg) return 0; } -static cJSON * -_create_session(mixer_app_t *mixer) -{ - mixer_shm_t *shm = mixer->shm; - - cJSON *root = cJSON_CreateObject(); - if(root) - { - cJSON_AddStringToObject(root, "type", _port_type_to_string(mixer->type)); - cJSON_AddNumberToObject(root, "nsinks", shm->nsinks); - cJSON_AddNumberToObject(root, "nsources", shm->nsources); - cJSON *arr1 = cJSON_CreateArray(); - if(arr1) - { - for(unsigned j = 0; j < shm->nsources; j++) - { - cJSON *arr2 = cJSON_CreateArray(); - if(arr2) - { - for(unsigned i = 0; i < shm->nsinks; i++) - { - const int32_t gain = atomic_load_explicit(&shm->jgains[j][i], memory_order_relaxed); - cJSON_AddItemToArray(arr2, cJSON_CreateNumber(gain)); - } - cJSON_AddItemToArray(arr1, arr2); - } - } - cJSON_AddItemToObject(root, "gains", arr1); - } - - return root; - } - - return NULL; -} - -static void -_jack_session_cb(jack_session_event_t *jev, void *arg) -{ - mixer_app_t *mixer= arg; - mixer_shm_t *shm = mixer->shm; - - asprintf(&jev->command_line, "patchmatrix_mixer -u %s -d ${SESSION_DIR}", - jev->client_uuid); - - switch(jev->type) - { - case JackSessionSave: - case JackSessionSaveAndQuit: - { - cJSON *root = _create_session(mixer); - if(root) - { - _save_session(root, jev->session_dir); - cJSON_Delete(root); - } - - if(jev->type == JackSessionSaveAndQuit) - _close(shm); - } break; - case JackSessionSaveTemplate: - { - // nothing - } break; - } - - jack_session_reply(mixer->client, jev); - jack_session_event_free(jev); -} - int main(int argc, char **argv) { static mixer_app_t mixer; const size_t total_size = sizeof(mixer_shm_t); - cJSON *root = NULL; - cJSON *gains_node = NULL; const char *server_name = NULL; - const char *session_id = NULL; unsigned nsinks = 1; unsigned nsources = 1; mixer.type = TYPE_AUDIO; @@ -459,7 +386,7 @@ main(int argc, char **argv) "Released under Artistic License 2.0 by Open Music Kontrollers\n", argv[0]); int c; - while((c = getopt(argc, argv, "vhn:u:t:i:o:d:")) != -1) + while((c = getopt(argc, argv, "vht:i:o:n:")) != -1) { switch(c) { @@ -491,20 +418,12 @@ main(int argc, char **argv) " [-t] port-type port type (audio, midi)\n" " [-i] input-num port input number (1-%i)\n" " [-o] output-num port output number (1-%i)\n" - " [-n] server-name connect to named JACK daemon\n" - " [-u] client-uuid client UUID for JACK session management\n" - " [-d] session-dir directory for JACK session management\n\n" + " [-n] server-name connect to named JACK daemon\n\n" , argv[0], PORT_MAX, PORT_MAX); return 0; case 'n': server_name = optarg; break; - case 'u': - session_id = optarg; - break; - case 'd': - root = _load_session(optarg); - break; case 't': mixer.type = _port_type_from_string(optarg); break; @@ -532,41 +451,13 @@ main(int argc, char **argv) } } - if(root) - { - cJSON *type_node = cJSON_GetObjectItem(root, "type"); - if(type_node && cJSON_IsString(type_node)) - { - const char *port_type = type_node->valuestring; - - mixer.type = _port_type_from_string(port_type); - } - - cJSON *nsinks_node = cJSON_GetObjectItem(root, "nsinks"); - if(nsinks_node && cJSON_IsNumber(nsinks_node)) - { - nsinks = nsinks_node->valueint; - } - - cJSON *nsources_node = cJSON_GetObjectItem(root, "nsources"); - if(nsources_node && cJSON_IsNumber(nsources_node)) - { - nsources = nsources_node->valueint; - } - - gains_node = cJSON_GetObjectItem(root, "gains"); - } - jack_options_t opts = JackNullOption | JackNoStartServer; if(server_name) opts |= JackServerName; - if(session_id) - opts |= JackSessionID; jack_status_t status; mixer.client = jack_client_open(PATCHMATRIX_MIXER_ID, opts, &status, - server_name ? server_name : session_id, - server_name ? session_id : NULL); + server_name ? server_name : NULL); if(!mixer.client) return -1; @@ -665,17 +556,6 @@ main(int argc, char **argv) atomic_init(&mixer.shm->jgains[j][i], 0); else atomic_init(&mixer.shm->jgains[j][i], -3600); - - if(gains_node) - { - cJSON *row = cJSON_GetArrayItem(gains_node, j); - if(row) - { - cJSON *col = cJSON_GetArrayItem(row, i); - if(col && cJSON_IsNumber(col)) - atomic_init(&mixer.shm->jgains[j][i], col->valueint); - } - } } } @@ -686,7 +566,6 @@ main(int argc, char **argv) mixer.type == TYPE_AUDIO ? _audio_mixer_process : _midi_mixer_process, &mixer); //TODO CV - jack_set_session_callback(mixer.client, _jack_session_cb, &mixer); jack_activate(mixer.client); @@ -735,8 +614,5 @@ main(int argc, char **argv) jack_client_close(mixer.client); - if(root) - cJSON_Delete(root); - return 0; } diff --git a/patchmatrix_monitor.1 b/patchmatrix_monitor.1 index 1c40091..2567039 100644 --- a/patchmatrix_monitor.1 +++ b/patchmatrix_monitor.1 @@ -1,4 +1,4 @@ -.TH PATCHMATRIX_MONITOR "1" "Apr 13, 2020" +.TH PATCHMATRIX_MONITOR "1" "Jul 08, 2021" .SH NAME patchmatrix_monitor \- a JACK port monitor @@ -40,16 +40,6 @@ Number of input ports (1-128) .IP Connect to named JACK daemon -.HP -\fB\-u\fR client-uuid -.IP -Client UUID for JACK session management - -.HP -\fB\-d\fR session-dir -.IP -Directory for JACK session management - .SH LICENSE Artistic License 2.0. diff --git a/patchmatrix_monitor.c b/patchmatrix_monitor.c index bc5aceb..b102c14 100644 --- a/patchmatrix_monitor.c +++ b/patchmatrix_monitor.c @@ -157,66 +157,13 @@ _midi_monitor_process(jack_nframes_t nframes, void *arg) return 0; } -static cJSON * -_create_session(monitor_app_t *monitor) -{ - monitor_shm_t *shm = monitor->shm; - - cJSON *root = cJSON_CreateObject(); - if(root) - { - cJSON_AddStringToObject(root, "type", _port_type_to_string(monitor->type)); - cJSON_AddNumberToObject(root, "nsinks", shm->nsinks); - - return root; - } - - return NULL; -} - -static void -_jack_session_cb(jack_session_event_t *jev, void *arg) -{ - monitor_app_t *monitor= arg; - monitor_shm_t *shm = monitor->shm; - - asprintf(&jev->command_line, "patchmatrix_monitor -u %s -d ${SESSION_DIR}", - jev->client_uuid); - - switch(jev->type) - { - case JackSessionSave: - case JackSessionSaveAndQuit: - { - cJSON *root = _create_session(monitor); - if(root) - { - _save_session(root, jev->session_dir); - cJSON_Delete(root); - } - - if(jev->type == JackSessionSaveAndQuit) - _close(shm); - } break; - case JackSessionSaveTemplate: - { - // nothing - } break; - } - - jack_session_reply(monitor->client, jev); - jack_session_event_free(jev); -} - int main(int argc, char **argv) { static monitor_app_t monitor; const size_t total_size = sizeof(monitor_shm_t); - cJSON *root = NULL; const char *server_name = NULL; - const char *session_id = NULL; unsigned nsinks = 1; monitor.type = TYPE_AUDIO; @@ -226,7 +173,7 @@ main(int argc, char **argv) "Released under Artistic License 2.0 by Open Music Kontrollers\n", argv[0]); int c; - while((c = getopt(argc, argv, "vhn:u:t:i:d:")) != -1) + while((c = getopt(argc, argv, "vht:i:n:")) != -1) { switch(c) { @@ -257,20 +204,12 @@ main(int argc, char **argv) " [-h] print usage information\n" " [-t] port-type port type (audio, midi)\n" " [-i] input-num port input number (1-%i)\n" - " [-n] server-name connect to named JACK daemon\n" - " [-u] client-uuid client UUID for JACK session management\n" - " [-d] session-dir directory for JACK session management\n\n" + " [-n] server-name connect to named JACK daemon\n\n" , argv[0], PORT_MAX); return 0; case 'n': server_name = optarg; break; - case 'u': - session_id = optarg; - break; - case 'd': - root = _load_session(optarg); - break; case 't': monitor.type = _port_type_from_string(optarg); break; @@ -293,35 +232,13 @@ main(int argc, char **argv) } } - if(root) - { - cJSON *type_node = cJSON_GetObjectItem(root, "type"); - if(type_node && cJSON_IsString(type_node)) - { - const char *port_type = type_node->valuestring; - - monitor.type = _port_type_from_string(port_type); - } - - cJSON *nsinks_node = cJSON_GetObjectItem(root, "nsinks"); - if(nsinks_node && cJSON_IsNumber(nsinks_node)) - { - nsinks = nsinks_node->valueint; - } - - cJSON_Delete(root); - } - jack_options_t opts = JackNullOption | JackNoStartServer; if(server_name) opts |= JackServerName; - if(session_id) - opts |= JackSessionID; jack_status_t status; monitor.client = jack_client_open(PATCHMATRIX_MONITOR_ID, opts, &status, - server_name ? server_name : session_id, - server_name ? session_id : NULL); + server_name ? server_name : NULL); if(!monitor.client) return -1; @@ -377,7 +294,6 @@ main(int argc, char **argv) monitor.type == TYPE_AUDIO ? _audio_monitor_process : _midi_monitor_process, &monitor); //TODO CV - jack_set_session_callback(monitor.client, _jack_session_cb, &monitor); jack_activate(monitor.client); |