Commit 75efcc95 authored by Hanspeter Portner's avatar Hanspeter Portner

Merge commit '346f8c34'

parents 996a62ba 346f8c34
cmake_minimum_required(VERSION 2.8)
project(osc.lv2)
include_directories(${PROJECT_SOURCE_DIR})
set(CMAKE_C_FLAGS "-std=gnu11 -Wextra -Wno-unused-parameter -ffast-math -fvisibility=hidden ${CMAKE_C_FLAGS}")
set(CMAKE_C_FLAGS "-Wshadow -Wimplicit-function-declaration -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes ${CMAKE_C_FLAGS}")
include(CTest)
if(${BUILD_TESTING})
add_executable(osc_test
osc_test.c)
add_test(NAME API-Test COMMAND osc_test)
endif()
# Copyright (c) 2015 Hanspeter Portner (dev@open-music-kontrollers.ch)
# Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
#
# This is free software: you can redistribute it and/or modify
# it under the terms of the Artistic License 2.0 as published by
......
This diff is collapsed.
# Copyright (c) 2015 Hanspeter Portner (dev@open-music-kontrollers.ch)
# Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
#
# This is free software: you can redistribute it and/or modify
# it under the terms of the Artistic License 2.0 as published by
......
This diff is collapsed.
/*
* Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the Artistic License 2.0 as published by
* The Perl Foundation.
*
* This source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Artistic License 2.0 for more details.
*
* You should have received a copy of the Artistic License 2.0
* along the source as a COPYING file. If not, obtain it from
* http://www.perlfoundation.org/artistic_license_2_0.
*/
#ifndef LV2_OSC_H
#define LV2_OSC_H
#include <stdint.h>
#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
#include <lv2/lv2plug.in/ns/ext/midi/midi.h>
#define LV2_OSC_URI "http://open-music-kontrollers.ch/lv2/osc"
#define LV2_OSC_PREFIX LV2_OSC_URI "#"
#define LV2_OSC__Event LV2_OSC_PREFIX "Event" // atom message type
#define LV2_OSC__schedule LV2_OSC_PREFIX "schedule" // feature
#define LV2_OSC__Packet LV2_OSC_PREFIX "Packet" // atom object type
#define LV2_OSC__Bundle LV2_OSC_PREFIX "Bundle" // atom object type
#define LV2_OSC__bundleTimetag LV2_OSC_PREFIX "bundleTimetag" // atom object property
#define LV2_OSC__bundleItems LV2_OSC_PREFIX "bundleItems"
#define LV2_OSC__Message LV2_OSC_PREFIX "Message" // atom object type
#define LV2_OSC__messagePath LV2_OSC_PREFIX "messagePath" // atom object property
#define LV2_OSC__messageArguments LV2_OSC_PREFIX "messageArguments" // atom object property
#define LV2_OSC__Timetag LV2_OSC_PREFIX "Timetag" // atom object type
#define LV2_OSC__timetagIntegral LV2_OSC_PREFIX "timetagIntegral" // atom object property
#define LV2_OSC__timetagFraction LV2_OSC_PREFIX "timetagFraction" // atom object property
#define LV2_OSC__Impulse LV2_OSC_PREFIX "Impulse" // atom type
#define LV2_OSC__Char LV2_OSC_PREFIX "Char" // atom type
#define LV2_OSC__RGBA LV2_OSC_PREFIX "RGBA" // atom type
#define LV2_OSC_PADDED_SIZE(size) ( ( (size_t)(size) + 3 ) & ( ~3 ) )
#define LV2_OSC_IMMEDIATE 1ULL
#ifdef __cplusplus
extern "C" {
#endif
typedef void *LV2_OSC_Schedule_Handle;
typedef double (*LV2_OSC_Schedule_OSC2Frames)(
LV2_OSC_Schedule_Handle handle,
uint64_t timetag);
typedef uint64_t (*LV2_OSC_Schedule_Frames2OSC)(
LV2_OSC_Schedule_Handle handle,
double frames);
typedef struct _LV2_OSC_Schedule {
LV2_OSC_Schedule_Handle handle;
LV2_OSC_Schedule_OSC2Frames osc2frames;
LV2_OSC_Schedule_Frames2OSC frames2osc;
} LV2_OSC_Schedule;
typedef enum LV2_OSC_Type {
LV2_OSC_INT32 = 'i',
LV2_OSC_FLOAT = 'f',
LV2_OSC_STRING = 's',
LV2_OSC_BLOB = 'b',
LV2_OSC_TRUE = 'T',
LV2_OSC_FALSE = 'F',
LV2_OSC_NIL = 'N',
LV2_OSC_IMPULSE = 'I',
LV2_OSC_INT64 = 'h',
LV2_OSC_DOUBLE = 'd',
LV2_OSC_TIMETAG = 't',
LV2_OSC_SYMBOL = 'S',
LV2_OSC_CHAR = 'c',
LV2_OSC_MIDI = 'm',
LV2_OSC_RGBA = 'r'
} LV2_OSC_Type;
union swap32_t {
uint32_t u;
int32_t i;
float f;
};
union swap64_t {
uint64_t u;
int64_t h;
uint64_t t;
double d;
};
typedef struct _LV2_OSC_Timetag {
uint32_t integral;
uint32_t fraction;
} LV2_OSC_Timetag;
typedef struct _LV2_OSC_URID {
LV2_URID OSC_Packet;
LV2_URID OSC_Bundle;
LV2_URID OSC_bundleTimetag;
LV2_URID OSC_bundleItems;
LV2_URID OSC_Message;
LV2_URID OSC_messagePath;
LV2_URID OSC_messageArguments;
LV2_URID OSC_Timetag;
LV2_URID OSC_timetagIntegral;
LV2_URID OSC_timetagFraction;
LV2_URID OSC_Impulse;
LV2_URID OSC_Char;
LV2_URID OSC_RGBA;
LV2_URID MIDI_MidiEvent;
LV2_URID ATOM_Int;
LV2_URID ATOM_Long;
LV2_URID ATOM_String;
LV2_URID ATOM_Float;
LV2_URID ATOM_Double;
LV2_URID ATOM_URID;
LV2_URID ATOM_Bool;
LV2_URID ATOM_Tuple;
LV2_URID ATOM_Object;
LV2_URID ATOM_Chunk;
} LV2_OSC_URID;
static inline void
lv2_osc_urid_init(LV2_OSC_URID *osc_urid, LV2_URID_Map *map)
{
osc_urid->OSC_Packet = map->map(map->handle, LV2_OSC__Packet);
osc_urid->OSC_Bundle = map->map(map->handle, LV2_OSC__Bundle);
osc_urid->OSC_bundleTimetag = map->map(map->handle, LV2_OSC__bundleTimetag);
osc_urid->OSC_bundleItems = map->map(map->handle, LV2_OSC__bundleItems);
osc_urid->OSC_Message = map->map(map->handle, LV2_OSC__Message);
osc_urid->OSC_messagePath = map->map(map->handle, LV2_OSC__messagePath);
osc_urid->OSC_messageArguments = map->map(map->handle, LV2_OSC__messageArguments);
osc_urid->OSC_Timetag = map->map(map->handle, LV2_OSC__Timetag);
osc_urid->OSC_timetagIntegral = map->map(map->handle, LV2_OSC__timetagIntegral);
osc_urid->OSC_timetagFraction = map->map(map->handle, LV2_OSC__timetagFraction);
osc_urid->OSC_Impulse = map->map(map->handle, LV2_OSC__Impulse);
osc_urid->OSC_Char = map->map(map->handle, LV2_OSC__Char);
osc_urid->OSC_RGBA = map->map(map->handle, LV2_OSC__RGBA);
osc_urid->MIDI_MidiEvent = map->map(map->handle, LV2_MIDI__MidiEvent);
osc_urid->ATOM_Int = map->map(map->handle, LV2_ATOM__Int);
osc_urid->ATOM_Long = map->map(map->handle, LV2_ATOM__Long);
osc_urid->ATOM_String = map->map(map->handle, LV2_ATOM__String);
osc_urid->ATOM_Float = map->map(map->handle, LV2_ATOM__Float);
osc_urid->ATOM_Double = map->map(map->handle, LV2_ATOM__Double);
osc_urid->ATOM_URID = map->map(map->handle, LV2_ATOM__URID);
osc_urid->ATOM_Bool = map->map(map->handle, LV2_ATOM__Bool);
osc_urid->ATOM_Tuple = map->map(map->handle, LV2_ATOM__Tuple);
osc_urid->ATOM_Object = map->map(map->handle, LV2_ATOM__Object);
osc_urid->ATOM_Chunk = map->map(map->handle, LV2_ATOM__Chunk);
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // LV2_OSC_H
This diff is collapsed.
/*
* Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the Artistic License 2.0 as published by
* The Perl Foundation.
*
* This source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Artistic License 2.0 for more details.
*
* You should have received a copy of the Artistic License 2.0
* along the source as a COPYING file. If not, obtain it from
* http://www.perlfoundation.org/artistic_license_2_0.
*/
#ifndef LV2_OSC_UTIL_H
#define LV2_OSC_UTIL_H
#include <assert.h>
#include <ctype.h>
#include <osc.lv2/osc.h>
#include <lv2/lv2plug.in/ns/ext/atom/util.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*LV2_OSC_Method)(const char *path,
const LV2_Atom_Tuple *arguments, void *data);
// characters not allowed in OSC path string
static const char invalid_path_chars [] = {
' ', '#',
'\0'
};
// allowed characters in OSC format string
static const char valid_format_chars [] = {
LV2_OSC_INT32, LV2_OSC_FLOAT, LV2_OSC_STRING, LV2_OSC_BLOB,
LV2_OSC_TRUE, LV2_OSC_FALSE, LV2_OSC_NIL, LV2_OSC_IMPULSE,
LV2_OSC_INT64, LV2_OSC_DOUBLE, LV2_OSC_TIMETAG,
LV2_OSC_SYMBOL, LV2_OSC_MIDI,
'\0'
};
/**
TODO
*/
static inline bool
lv2_osc_check_path(const char *path)
{
assert(path);
if(path[0] != '/')
return false;
for(const char *ptr=path+1; *ptr!='\0'; ptr++)
if( (isprint(*ptr) == 0) || (strchr(invalid_path_chars, *ptr) != NULL) )
return false;
return true;
}
/**
TODO
*/
static inline bool
lv2_osc_check_fmt(const char *format, int offset)
{
assert(format);
if(offset && (format[0] != ',') )
return false;
for(const char *ptr=format+offset; *ptr!='\0'; ptr++)
if(strchr(valid_format_chars, *ptr) == NULL)
return false;
return true;
}
/**
TODO
*/
static inline uint64_t
lv2_osc_timetag_parse(const LV2_OSC_Timetag *timetag)
{
return ((uint64_t)timetag->integral << 32) | timetag->fraction;
}
/**
TODO
*/
static inline LV2_OSC_Timetag *
lv2_osc_timetag_create(LV2_OSC_Timetag *timetag, uint64_t tt)
{
timetag->integral = tt >> 32;
timetag->fraction = tt & 0xffffffff;
return timetag;
}
#define LV2_OSC_TIMETAG_CREATE(tt) \
lv2_osc_timetag_create(&(LV2_OSC_Timetag){.integral = 0, .fraction = 0}, (tt))
/**
TODO
*/
static inline bool
lv2_osc_is_packet_type(LV2_OSC_URID *osc_urid, LV2_URID type)
{
return type == osc_urid->OSC_Packet;
}
/**
TODO
*/
static inline bool
lv2_osc_is_bundle_type(LV2_OSC_URID *osc_urid, LV2_URID type)
{
return type == osc_urid->OSC_Bundle;
}
/**
TODO
*/
static inline bool
lv2_osc_is_message_type(LV2_OSC_URID *osc_urid, LV2_URID type)
{
return type == osc_urid->OSC_Message;
}
/**
TODO
*/
static inline bool
lv2_osc_is_message_or_bundle_type(LV2_OSC_URID *osc_urid, LV2_URID type)
{
return lv2_osc_is_message_type(osc_urid, type)
|| lv2_osc_is_bundle_type(osc_urid, type);
}
static inline LV2_OSC_Type
lv2_osc_argument_type(LV2_OSC_URID *osc_urid, const LV2_Atom *atom)
{
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)atom;
if(atom->type == osc_urid->ATOM_Int)
return LV2_OSC_INT32;
else if(atom->type == osc_urid->ATOM_Float)
return LV2_OSC_FLOAT;
else if(atom->type == osc_urid->ATOM_String)
return LV2_OSC_STRING;
else if(atom->type == osc_urid->ATOM_Chunk)
return LV2_OSC_BLOB;
else if(atom->type == osc_urid->ATOM_Long)
return LV2_OSC_INT64;
else if(atom->type == osc_urid->ATOM_Double)
return LV2_OSC_DOUBLE;
else if( (atom->type == osc_urid->ATOM_Object) && (obj->body.otype == osc_urid->OSC_Timetag) )
return LV2_OSC_TIMETAG;
else if(atom->type == osc_urid->ATOM_Bool)
{
if(((const LV2_Atom_Bool *)atom)->body)
return LV2_OSC_TRUE;
else
return LV2_OSC_FALSE;
}
else if( (atom->type == 0) && (atom->size == 0) )
return LV2_OSC_NIL;
else if(atom->type == osc_urid->OSC_Impulse)
return LV2_OSC_IMPULSE;
else if(atom->type == osc_urid->ATOM_URID)
return LV2_OSC_SYMBOL;
else if(atom->type == osc_urid->MIDI_MidiEvent)
return LV2_OSC_MIDI;
else if(atom->type == osc_urid->OSC_Char)
return LV2_OSC_CHAR;
else if(atom->type == osc_urid->OSC_RGBA)
return LV2_OSC_RGBA;
return '\0';
}
/**
TODO
*/
static inline void
lv2_osc_timetag_get(LV2_OSC_URID *osc_urid, const LV2_Atom_Object *obj,
LV2_OSC_Timetag *timetag)
{
assert(timetag);
const LV2_Atom_Long *integral = NULL;
const LV2_Atom_Long *fraction = NULL;
lv2_atom_object_get(obj,
osc_urid->OSC_timetagIntegral, &integral,
osc_urid->OSC_timetagFraction, &fraction,
0);
if( integral && (integral->atom.type == osc_urid->ATOM_Long)
&& fraction && (fraction->atom.type == osc_urid->ATOM_Long) )
{
timetag->integral = integral->body;
timetag->fraction = fraction->body;
}
else
{
// set to immediate
timetag->integral = 0;
timetag->fraction = 1;
}
}
/**
TODO
*/
static inline bool
lv2_osc_bundle_body_get(LV2_OSC_URID *osc_urid, uint32_t size, const LV2_Atom_Object_Body *body,
const LV2_Atom_Object **timetag, const LV2_Atom_Tuple **items)
{
assert(timetag && items);
*timetag = NULL;
*items = NULL;
lv2_atom_object_body_get(size, body,
osc_urid->OSC_bundleTimetag, timetag,
osc_urid->OSC_bundleItems, items,
0);
if(!*timetag || ((*timetag)->atom.type != osc_urid->ATOM_Object) || ((*timetag)->body.otype != osc_urid->OSC_Timetag))
return false;
if(!*items || ((*items)->atom.type != osc_urid->ATOM_Tuple))
return false;
return true;
}
/**
TODO
*/
static inline bool
lv2_osc_bundle_get(LV2_OSC_URID *osc_urid, const LV2_Atom_Object *obj,
const LV2_Atom_Object **timetag, const LV2_Atom_Tuple **items)
{
return lv2_osc_bundle_body_get(osc_urid, obj->atom.size, &obj->body,
timetag, items);
}
/**
TODO
*/
static inline bool
lv2_osc_message_body_get(LV2_OSC_URID *osc_urid, uint32_t size, const LV2_Atom_Object_Body *body,
const LV2_Atom_String **path, const LV2_Atom_Tuple **arguments)
{
assert(path && arguments);
*path = NULL;
*arguments = NULL;
lv2_atom_object_body_get(size, body,
osc_urid->OSC_messagePath, path,
osc_urid->OSC_messageArguments, arguments,
0);
if(!*path || ((*path)->atom.type != osc_urid->ATOM_String))
return false;
// message without arguments is valid
if( *arguments && ((*arguments)->atom.type != osc_urid->ATOM_Tuple))
return false;
return true;
}
/**
TODO
*/
static inline bool
lv2_osc_message_get(LV2_OSC_URID *osc_urid, const LV2_Atom_Object *obj,
const LV2_Atom_String **path, const LV2_Atom_Tuple **arguments)
{
return lv2_osc_message_body_get(osc_urid, obj->atom.size, &obj->body,
path, arguments);
}
static inline bool
lv2_osc_body_unroll(LV2_OSC_URID *osc_urid, uint32_t size, const LV2_Atom_Object_Body *body,
LV2_OSC_Method method, void *data)
{
if(body->otype == osc_urid->OSC_Bundle)
{
const LV2_Atom_Object *timetag = NULL;
const LV2_Atom_Tuple *items = NULL;
if(!lv2_osc_bundle_body_get(osc_urid, size, body, &timetag, &items))
return false;
LV2_OSC_Timetag tt;
lv2_osc_timetag_get(osc_urid, timetag, &tt);
LV2_ATOM_TUPLE_FOREACH(items, atom)
{
const LV2_Atom_Object *obj= (const LV2_Atom_Object *)atom;
if(!lv2_osc_body_unroll(osc_urid, obj->atom.size, &obj->body, method, data))
return false;
}
return true;
}
else if(body->otype == osc_urid->OSC_Message)
{
const LV2_Atom_String *path = NULL;
const LV2_Atom_Tuple *arguments = NULL;
if(!lv2_osc_message_body_get(osc_urid, size, body, &path, &arguments))
return false;
if(method)
method(LV2_ATOM_BODY_CONST(path), arguments, data);
return true;
}
return false;
}
static inline bool
lv2_osc_unroll(LV2_OSC_URID *osc_urid, const LV2_Atom_Object *obj,
LV2_OSC_Method method, void *data)
{
return lv2_osc_body_unroll(osc_urid, obj->atom.size, &obj->body, method, data);
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // LV2_OSC_UTIL_H
This diff is collapsed.
# Copyright (c) 2015 Hanspeter Portner (dev@open-music-kontrollers.ch)
# Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
#
# This is free software: you can redistribute it and/or modify
# it under the terms of the Artistic License 2.0 as published by
......@@ -13,14 +13,12 @@
# along the source as a COPYING file. If not, obtain it from
# http://www.perlfoundation.org/artistic_license_2_0.
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix midi: <http://lv2plug.in/ns/midi#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix osc: <http://open-music-kontrollers.ch/lv2/osc#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix osc: <http://open-music-kontrollers.ch/lv2/osc#> .
<http://open-music-kontrollers.ch/lv2/osc>
a owl:Ontology ;
......@@ -37,65 +35,8 @@ osc:schedule
a lv2:Feature .
osc:Event
a rdfs:Class ;
rdfs:subClassOf atom:Object ;
a rdfs:Class ,
rdfs:Datatype ;
rdfs:subClassOf atom:Atom ;
owl:onDatatype xsd:hexBinary ;
rdfs:label "OSC Event (Bundle or Message)" .
osc:Bundle
a rdfs:Class ;
rdfs:subClassOf osc:Event ;
rdfs:label "OSC Bundle" .
osc:Message
a rdfs:Class ;
rdfs:subClassOf osc:Event ;
rdfs:label "OSC Message" .
osc:bundleTimestamp
a rdf:Property ,
owl:ObjectProperty ,
owl:FunctionalProperty ;
rdfs:domain osc:Bundle ;
rdfs:range atom:Long ;
rdfs:label "OSC Bundle Timestamp" .
osc:bundleItems
a rdf:Property ,
owl:ObjectProperty ,
owl:FunctionalProperty ;
rdfs:domain osc:Bundle ;
rdfs:range atom:Tuple ;
rdfs:label "OSC Bundle Items" ;
lv2:documentation """
<p>Tuple of OSC Bundle Items (e.g. nested osc:Bundle's and/or
osc:Message's).</p>
""" .
osc:messagePath
a rdf:Property ,
owl:ObjectProperty ,
owl:FunctionalProperty ;
rdfs:domain osc:Message ;
rdfs:range atom:String ;
rdfs:label "OSC Message Path" .
osc:messageFormat
a rdf:Property ,
owl:ObjectProperty ,
owl:FunctionalProperty ;
rdfs:domain osc:Message ;
rdfs:range atom:String ;
rdfs:label "OSC Message Format" .
osc:messageArguments
a rdf:Property ,
owl:ObjectProperty ,
owl:FunctionalProperty ;
rdfs:domain osc:Message ;
rdfs:range atom:Tuple ;
rdfs:label "OSC Message Arguments" ;
lv2:documentation """
<p>Tuple of OSC Message Arguments (e.g. Atom:Int, Atom:Long, Atom:Float,
Atom:Double, Atom:String, Atom:Chunk, Atom:Bool, Atom:Blank,
MIDI:MidiEvent).</p>
""" .
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <osc.lv2/osc.h>
#include <osc.lv2/reader.h>
#include <osc.lv2/writer.h>
#include <osc.lv2/forge.h>
#define BUF_SIZE 8192
#define MAX_URIDS 512
typedef void (*test_t)(LV2_OSC_Writer *writer);
typedef struct _urid_t urid_t;
typedef struct _handle_t handle_t;
struct _urid_t {
LV2_URID urid;
char *uri;
};
struct _handle_t {
urid_t urids [MAX_URIDS];
LV2_URID urid;
};
static handle_t __handle;
static uint8_t buf0 [BUF_SIZE];
static uint8_t buf1 [BUF_SIZE];
static uint8_t buf2 [BUF_SIZE];
static const LV2_Atom_Object *obj2= (const LV2_Atom_Object *)buf2;
const uint8_t raw_0 [] = {
'/', 0x0, 0x0, 0x0,
',', 0x0, 0x0, 0x0
};
const uint8_t raw_1 [] = {
'/', 'p', 'i', 'n',
'g', 0x0, 0x0, 0x0,
',', 'i', 'f', 's',
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xc,
0x40, 0x59, 0x99, 0x9a,
'w', 'o', 'r', 'l',
'd', 0x0, 0x0, 0x0
};
const uint8_t raw_2 [] = {
'/', 'p', 'i', 'n',
'g', 0x0, 0x0, 0x0,
',', 'h', 'd', 'S',
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0xc,
0x40, 0x0b, 0x33, 0x33,
0x33, 0x33, 0x33, 0x33,
'h', 't', 't', 'p',
':', '/', '/', 'e',
'x', 'a', 'm', 'p',
'l', 'e', '.', 'c',
'o', 'm', 0x0, 0x0
};
const uint8_t raw_3 [] = {
'/', 'p', 'i', 'n',
'g', 0x0, 0x0, 0x0,
',', 'T', 'F', 'N',
'I', 0x0, 0x0, 0x0