network sacn outputting correctly on mac

This commit is contained in:
Peter Slattery 2022-04-22 11:57:52 -07:00
parent 8c904d5c1c
commit 0651c96f99
18 changed files with 602 additions and 66 deletions

Binary file not shown.

View File

@ -275,10 +275,10 @@ InitStreamHeader (u8* Buffer, s32 BufferSize,
Cursor = PackB1(Cursor, ADDRESS_AND_DATA_FORMAT); Cursor = PackB1(Cursor, ADDRESS_AND_DATA_FORMAT);
// DMP first property address // DMP first property address
Cursor = PackB2(Cursor, 0); Cursor = PackB1(Cursor, 0);
// DMP Address Increment // DMP Address Increment
Cursor = PackB2(Cursor, ADDRESS_INC); Cursor = PackB1(Cursor, ADDRESS_INC);
// Property Value Count -- Includes one byte for start code // Property Value Count -- Includes one byte for start code
Cursor = PackB2(Cursor, SlotCount + 1); Cursor = PackB2(Cursor, SlotCount + 1);

View File

@ -199,7 +199,7 @@ dw_get_u8(Data_Writer* w)
u8 result = 0; u8 result = 0;
if (w->at < w->data.size) if (w->at < w->data.size)
{ {
result = w->data.base[w->at++]; result = w->data.base[w->at];
} }
return result; return result;
} }

View File

@ -3,6 +3,91 @@
typedef struct { u64 value; } Socket_Handle; typedef struct { u64 value; } Socket_Handle;
// TODO u16 endian_swap_u16(u16 v);
u32 endian_swap_u32(u32 v);
u64 endian_swap_u64(u64 v);
#define hton_u16(v) endian_swap_u16(v)
#define hton_u32(v) endian_swap_u32(v)
#define hton_u64(v) endian_swap_u64(v)
#define ntoh_s16(v) endian_swap_u16(v)
#define ntoh_s32(v) endian_swap_u32(v)
#define ntoh_s64(v) endian_swap_u64(v)
//////////////////////////////////////////
// Implementation
u16
endian_swap_u16(u16 v)
{
u8* p = (u8*)&v;
u16 result = (u16)(
(p[0] << 8) |
(p[1] << 0)
);
return result;
}
u32
endian_swap_u32(u32 v)
{
u8* p = (u8*)&v;
u32 result = (u32)(
(p[0] << 24) |
(p[1] << 16) |
(p[2] << 8) |
(p[3] << 0)
);
return result;
}
u64
endian_swap_u64(u64 v)
{
u8* p = (u8*)&v;
u64 result = (u64)(
((u64)p[0] << 56) |
((u64)p[1] << 48) |
((u64)p[2] << 40) |
((u64)p[3] << 32) |
((u64)p[4] << 24) |
((u64)p[5] << 16) |
((u64)p[6] << 8) |
((u64)p[7] << 0)
);
return result;
}
#if defined(DEBUG)
void
core_socket_tests()
{
// u16 endian swap
u16 a_0 = 0xABCD;
u16 a_1 = endian_swap_u16(a_0);
u16 a_2 = endian_swap_u16(a_1);
assert(a_1 == 0xCDAB);
assert(a_2 == a_0);
// u32 endian swap
u32 b_0 = 0x89ABCDEF;
u32 b_1 = endian_swap_u32(b_0);
u32 b_2 = endian_swap_u32(b_1);
assert(b_1 == 0xEFCDAB89);
assert(b_2 == b_0);
// u64 endian swap
u64 c_0 = 0x7654321089ABCDEF;
u64 c_1 = endian_swap_u64(c_0);
u64 c_2 = endian_swap_u64(c_1);
assert(c_1 == 0xEFCDAB8910325476);
assert(c_2 == c_0);
}
#else
# define core_socket_tests()
#endif
#endif // LUMENARIUM_CORE_SOCKET_H #endif // LUMENARIUM_CORE_SOCKET_H

View File

@ -1,6 +1,8 @@
////////////////////////////////////////////// //////////////////////////////////////////////
// String // String
internal u64 c_str_len(char* s);
// NOTE(PS): even though this has a len and cap, it should always be // NOTE(PS): even though this has a len and cap, it should always be
// null terminated // null terminated
typedef struct String String; typedef struct String String;
@ -297,3 +299,21 @@ dw_put_str(Data_Writer* w, String str)
dw_put_u8(w, str.str[i]); dw_put_u8(w, str.str[i]);
} }
} }
internal void
dw_put_str_min_len(Data_Writer* w, String str, u64 min_len)
{
u64 start = w->at;
dw_put_str(w, str);
if (str.len < min_len)
{
w->at = start + min_len;
}
}
internal void
dw_put_str_min_len_nullterm(Data_Writer* w, String str, u64 min_len)
{
dw_put_str_min_len(w, str, min_len);
w->data.base[w->at - 1] = '\0';
}

View File

@ -7,9 +7,9 @@ en_init(App_State* state, App_Init_Desc desc)
state->assemblies = assembly_array_create(permanent, desc.assembly_cap); state->assemblies = assembly_array_create(permanent, desc.assembly_cap);
Output* o = &state->output; Output* o = &state->output;
register_output_method(o, OutputData_Invalid, 0, 0); register_output_method(o, OutputData_Invalid, 0, 0, 0);
register_output_method(o, OutputData_NetworkSACN, output_network_sacn_build, output_network_sacn_init()); register_output_method(o, OutputData_NetworkSACN, output_network_sacn_update, output_network_sacn_build, output_network_sacn_init());
register_output_method(o, OutputData_ComUART, output_network_sacn_build, output_com_uart_init()); register_output_method(o, OutputData_ComUART, 0, output_network_sacn_build, output_com_uart_init());
lumenarium_env_validate(); lumenarium_env_validate();
} }
@ -50,28 +50,38 @@ en_frame(App_State* state)
/////////////////////////////////////// ///////////////////////////////////////
// Output Data // Output Data
Output_Methods methods = state->output.methods;
// update each method that has an update method
for (u32 i = 0; i < OutputData_Count; i++)
{
if (methods.update_procs[i] == 0) continue;
methods.update_procs[i](methods.method_data[i]);
}
Output_Data_Queue output_queue = {}; Output_Data_Queue output_queue = {};
output_queue.a = scratch.a; output_queue.a = scratch.a;
// build output data buffers // build output data buffers
Output_Methods methods = state->output.methods;
for (u32 i = 0; i < assemblies.len; i++) for (u32 i = 0; i < assemblies.len; i++)
{ {
Assembly_Strip_Array strips = assemblies.strip_arrays[i]; Assembly_Strip_Array strips = assemblies.strip_arrays[i];
Assembly_Pixel_Buffer* pixels = assemblies.pixel_buffers + i;
for (u32 j = 0; j < strips.len; j++) for (u32 j = 0; j < strips.len; j++)
{ {
Assembly_Strip* strip = strips.strips + j; Assembly_Strip* strip = strips.strips + j;
Build_Output_Data_Buffer* method_proc = methods.procs[strip->output_kind]; Build_Output_Data_Buffer* method_proc = methods.procs[strip->output_kind];
u8* method_data = methods.method_data[strip->output_kind]; u8* method_data = methods.method_data[strip->output_kind];
if (method_proc == 0) continue; if (method_proc == 0) continue;
method_proc(state, i, strip, method_data, &output_queue); method_proc(state, i, pixels, strip, method_data, &output_queue);
} }
} }
// output the buffers // output the buffers
// TODO(PS): we could sort these first if switchig between output // TODO(PS): we could sort these first if switchig between output
// types is time consuming // types is time consuming
Sacn* sacn = (Sacn*)state->output.methods.method_data[OutputData_NetworkSACN];
for (Output_Data* at = output_queue.first; at != 0; at = at->next) for (Output_Data* at = output_queue.first; at != 0; at = at->next)
{ {
// NOTE(PS): we can overload each switch case as more methods come in // NOTE(PS): we can overload each switch case as more methods come in
@ -82,7 +92,13 @@ en_frame(App_State* state)
{ {
case OutputData_NetworkSACN: case OutputData_NetworkSACN:
{ {
// TODO(PS): platform network io os_socket_send_to(
sacn->socket,
at->network.v4_addr,
at->network.port,
at->data,
0
);
} break; } break;
case OutputData_ComUART: case OutputData_ComUART:

View File

@ -1,7 +1,8 @@
internal void internal void
register_output_method(Output* output, Output_Data_Kind kind, Build_Output_Data_Buffer* proc, u8* method_data) register_output_method(Output* output, Output_Data_Kind kind, Output_Method_Update* update, Build_Output_Data_Buffer* proc, u8* method_data)
{ {
output->methods.update_procs[kind] = update;
output->methods.procs[kind] = proc; output->methods.procs[kind] = proc;
output->methods.method_data[kind] = method_data; output->methods.method_data[kind] = method_data;
} }
@ -13,6 +14,7 @@ output_data_queue_push(Output_Data_Queue* q, u32 size, Output_Data_Kind kind)
d->kind = kind; d->kind = kind;
d->data.size = size; d->data.size = size;
d->data.base = allocator_alloc(q->a, size); d->data.base = allocator_alloc(q->a, size);
sll_push(q->first, q->last, d);
return d; return d;
} }

View File

@ -49,11 +49,13 @@ struct Output_Data_Queue
Allocator* a; Allocator* a;
}; };
typedef void Build_Output_Data_Buffer(App_State* state, u32 assembly_id, Assembly_Strip* strip, u8* method_data, Output_Data_Queue* queue); typedef void Output_Method_Update(u8* method_data);
typedef void Build_Output_Data_Buffer(App_State* state, u32 assembly_id, Assembly_Pixel_Buffer* pixels, Assembly_Strip* strip, u8* method_data, Output_Data_Queue* queue);
typedef struct Output_Methods Output_Methods; typedef struct Output_Methods Output_Methods;
struct Output_Methods struct Output_Methods
{ {
Output_Method_Update* update_procs[OutputData_Count];
Build_Output_Data_Buffer* procs[OutputData_Count]; Build_Output_Data_Buffer* procs[OutputData_Count];
u8* method_data[OutputData_Count]; u8* method_data[OutputData_Count];
}; };
@ -64,7 +66,7 @@ struct Output
Output_Methods methods; Output_Methods methods;
}; };
internal void register_output_method(Output* output, Output_Data_Kind kind, Build_Output_Data_Buffer* proc, u8* method_data); internal void register_output_method(Output* output, Output_Data_Kind kind, Output_Method_Update* update, Build_Output_Data_Buffer* proc, u8* method_data);
internal Output_Data* output_data_queue_push(Output_Data_Queue* q, u32 size, Output_Data_Kind kind); internal Output_Data* output_data_queue_push(Output_Data_Queue* q, u32 size, Output_Data_Kind kind);

View File

@ -1,5 +1,6 @@
#define SACN_DEFAULT_PORT 5568 #define SACN_DEFAULT_PORT 5568
#define SACN_STARTCODE_DMX 0
// a description of the address space being used // a description of the address space being used
#define SACN_PREAMBLE_SIZE_ADDR 0 #define SACN_PREAMBLE_SIZE_ADDR 0
@ -59,13 +60,12 @@ internal void
sacn_vhd_pack_flags(Data_Writer* w, b8 inherit_vec, b8 inherit_head, b8 inherit_data) sacn_vhd_pack_flags(Data_Writer* w, b8 inherit_vec, b8 inherit_head, b8 inherit_data)
{ {
u8 last_byte = dw_get_u8(w) & 0x8F; u8 last_byte = dw_get_u8(w) & 0x8F;
w->at -= 1;
if (!inherit_vec) { last_byte |= SACN_VHD_V_FLAG; } if (!inherit_vec) { last_byte |= SACN_VHD_V_FLAG; }
if (!inherit_head) { last_byte |= SACN_VHD_H_FLAG; } if (!inherit_head) { last_byte |= SACN_VHD_H_FLAG; }
if (!inherit_data) { last_byte |= SACN_VHD_D_FLAG; } if (!inherit_data) { last_byte |= SACN_VHD_D_FLAG; }
dw_put_u8(w, last_byte); w->data.base[w->at] = last_byte;
} }
internal void internal void
@ -86,7 +86,6 @@ sacn_vhd_pack_len(Data_Writer* w, u32 len, b8 include_len)
// Mask out the length bits to keep flags intact // Mask out the length bits to keep flags intact
u8 last_byte = dw_get_u8(w) & 0x70; u8 last_byte = dw_get_u8(w) & 0x70;
w->at -= 1;
if (len_adjusted > SACN_VHD_MAXMINLENGTH) last_byte |= SACN_VHD_L_FLAG; if (len_adjusted > SACN_VHD_MAXMINLENGTH) last_byte |= SACN_VHD_L_FLAG;
@ -105,14 +104,230 @@ sacn_vhd_pack_len(Data_Writer* w, u32 len, b8 include_len)
} }
} }
#define CopyMemoryTo(from, to, size) CopyMemory_((u8*)(from), (u8*)(to), (size))
internal void
CopyMemory_(u8* From, u8* To, u64 Size)
{
for (u64 i = 0; i < Size; i++)
{
To[i] = From[i];
}
}
// Packs a u8 to a known big endian buffer
u8*
PackB1(u8* ptr, u8 val)
{
*ptr = val;
return ptr + sizeof(val);
}
//Unpacks a u8 from a known big endian buffer
u8
UpackB1(const u8* ptr)
{
return *ptr;
}
//Packs a u8 to a known little endian buffer
u8*
PackL1(u8* ptr, u8 val)
{
*ptr = val;
return ptr + sizeof(val);
}
//Unpacks a u8 from a known little endian buffer
u8
UpackL1(const u8* ptr)
{
return *ptr;
}
u8*
PackB2(u8* ptr, u16 val)
{
ptr[1] = (u8)(val & 0xff);
ptr[0] = (u8)((val & 0xff00) >> 8);
return ptr + sizeof(val);
}
//Unpacks a u16 from a known big endian buffer
u16
UpackB2(const u8* ptr)
{
return (u16)(ptr[1] | ptr[0] << 8);
}
//Packs a u32 to a known big endian buffer
u8*
PackB4(u8* ptr, u32 val)
{
ptr[3] = (u8) (val & 0xff);
ptr[2] = (u8)((val & 0xff00) >> 8);
ptr[1] = (u8)((val & 0xff0000) >> 16);
ptr[0] = (u8)((val & 0xff000000) >> 24);
return ptr + sizeof(val);
}
internal void
VHD_PackFlags_(u8* Buffer, b32 InheritVec, b32 InheritHead, b32 InheritData)
{
u8* Cursor = Buffer;
u8 NewByte = UpackB1(Cursor) & 0x8f;
if (!InheritVec) { NewByte |= SACN_VHD_V_FLAG; }
if (!InheritHead) { NewByte |= SACN_VHD_H_FLAG; }
if (!InheritData) { NewByte |= SACN_VHD_D_FLAG; }
PackB1(Cursor, NewByte);
}
internal u8*
VHD_PackLength_(u8* Buffer, u32 Length, b32 IncludeLength)
{
u8* Cursor = Buffer;
u32 AdjustedLength = Length;
if (IncludeLength)
{
if (Length + 1 > SACN_VHD_MAXMINLENGTH)
{
AdjustedLength += 2;
}
else
{
AdjustedLength += 1;
}
}
// Mask out the length bits to keep flags intact
u8 NewByte = UpackB1(Cursor) & 0x70;
if (AdjustedLength > SACN_VHD_MAXMINLENGTH)
{
NewByte |= SACN_VHD_L_FLAG;
}
u8 PackBuffer[4];
PackB4(PackBuffer, AdjustedLength);
if (AdjustedLength <= SACN_VHD_MAXMINLENGTH)
{
NewByte |= (PackBuffer[2] & 0x0f);
Cursor = PackB1(Cursor, NewByte);
Cursor = PackB1(Cursor, PackBuffer[3]);
}
else
{
NewByte |= (PackBuffer[1] & 0x0f);
Cursor = PackB1(Cursor, PackBuffer[2]);
Cursor = PackB1(Cursor, PackBuffer[3]);
}
return Cursor;
}
internal void
InitStreamHeader (u8* Buffer, s32 BufferSize,
u16 SlotCount,
u8 StartCode,
u16 Universe,
u8 Priority,
u16 Reserved,
u8 Options,
const char* SourceName,
Sacn_Cid CID
)
{
// TODO(pjs): Replace packing with gs_memory_cursor
u8* Cursor = Buffer;
// Preamble Size
Cursor = PackB2(Cursor, SACN_RLP_PREAMBLE_SIZE);
Cursor = PackB2(Cursor, SACN_RLP_POSTAMBLE_SIZE);
CopyMemoryTo(SACN_ACN_IDENTIFIER.str, Cursor, SACN_ACN_IDENTIFIER_SIZE);
Cursor += SACN_ACN_IDENTIFIER_SIZE;
// TODO(Peter): If you never use this anywhere else, go back and remove the parameters
VHD_PackFlags_(Cursor, false, false, false);
Cursor = VHD_PackLength_(Cursor,
SACN_BUFFER_HEADER_SIZE - SACN_RLP_PREAMBLE_SIZE + SlotCount,
false);
// root vector
Cursor = PackB4(Cursor, SACN_ROOT_VECTOR); // 22
// CID Pack
for (s32 i = 0; i < SACN_CID_BYTES; i++)
{
*Cursor++ = CID.bytes[i];
}// 38
VHD_PackFlags_(Cursor, false, false, false);
Cursor = VHD_PackLength_(Cursor,
SACN_BUFFER_HEADER_SIZE - SACN_FRAMING_FLAGS_AND_LEN_ADDR + SlotCount,
false);
// 40
// framing vector
Cursor = PackB4(Cursor, SACN_FRAMING_VECTOR);
// framing source name
// :Check
CopyMemoryTo(SourceName, (char*)Cursor, c_str_len((char*)SourceName));
Cursor[SACN_SOURCE_NAME_SIZE - 1] = '\0';
Cursor += SACN_SOURCE_NAME_SIZE; // 108
// priority
Cursor = PackB1(Cursor, Priority);
// reserved
Cursor = PackB2(Cursor, Reserved); // 111
// Sequence # is always set to 0/NONE at the beginning, but it is incremented when sending data
Cursor = PackB1(Cursor, 0);
// Options
Cursor = PackB1(Cursor, Options);
// Universe
Cursor = PackB2(Cursor, Universe); // 115
VHD_PackFlags_(Cursor, false, false, false);
Cursor = VHD_PackLength_(Cursor,
SACN_BUFFER_HEADER_SIZE - SACN_DMP_FLAGS_AND_LEN_ADDR + SlotCount,
false); // 117
// DMP Vector
Cursor = PackB1(Cursor, SACN_DMP_VECTOR);
// DMP Address and data type
Cursor = PackB1(Cursor, SACN_ADDRESS_AND_DATA_FORMAT);
// DMP first property address
Cursor = PackB1(Cursor, 0);
// DMP Address Increment
Cursor = PackB1(Cursor, SACN_ADDR_INC);
// Property Value Count -- Includes one byte for start code
Cursor = PackB2(Cursor, SlotCount + 1);
Cursor = PackB1(Cursor, StartCode);
assert(Cursor - Buffer == SACN_BUFFER_HEADER_SIZE);
}
internal void internal void
sacn_fill_buffer_header(Output_Data* d, u16 universe, Sacn* sacn) sacn_fill_buffer_header(Output_Data* d, u16 universe, Sacn* sacn)
{ {
assert(d && d->data.size > 0); assert(d && d->data.size > 0);
// TODO(PS): these should be passed in? // TODO(PS): these should be passed in?
u16 slot_count = 0; u16 slot_count = SACN_BUFFER_BODY_SIZE;
u8 start_code = 0; u8 start_code = SACN_STARTCODE_DMX;
// universe
u8 priority = 0; u8 priority = 0;
u16 reserved = 0; u16 reserved = 0;
u8 options = 0; u8 options = 0;
@ -122,7 +337,7 @@ sacn_fill_buffer_header(Output_Data* d, u16 universe, Sacn* sacn)
dw_put_u16_b(&w, SACN_RLP_PREAMBLE_SIZE); dw_put_u16_b(&w, SACN_RLP_PREAMBLE_SIZE);
dw_put_u16_b(&w, SACN_RLP_POSTAMBLE_SIZE); dw_put_u16_b(&w, SACN_RLP_POSTAMBLE_SIZE);
dw_put_str(&w, SACN_ACN_IDENTIFIER); dw_put_str_min_len(&w, SACN_ACN_IDENTIFIER, SACN_ACN_IDENTIFIER_SIZE);
sacn_vhd_pack_flags(&w, false, false, false); sacn_vhd_pack_flags(&w, false, false, false);
sacn_vhd_pack_len(&w, SACN_BUFFER_HEADER_SIZE - SACN_RLP_PREAMBLE_SIZE + slot_count, false); sacn_vhd_pack_len(&w, SACN_BUFFER_HEADER_SIZE - SACN_RLP_PREAMBLE_SIZE + slot_count, false);
@ -135,11 +350,12 @@ sacn_fill_buffer_header(Output_Data* d, u16 universe, Sacn* sacn)
sacn_vhd_pack_len(&w, SACN_BUFFER_HEADER_SIZE - SACN_FRAMING_FLAGS_AND_LEN_ADDR + slot_count, false); sacn_vhd_pack_len(&w, SACN_BUFFER_HEADER_SIZE - SACN_FRAMING_FLAGS_AND_LEN_ADDR + slot_count, false);
dw_put_u32_b(&w, SACN_FRAMING_VECTOR); dw_put_u32_b(&w, SACN_FRAMING_VECTOR);
dw_put_str(&w, sacn->source_name);
dw_put_str_min_len_nullterm(&w, sacn->source_name, SACN_SOURCE_NAME_SIZE);
dw_put_u8(&w, priority); dw_put_u8(&w, priority);
dw_put_u16_b(&w, reserved); dw_put_u16_b(&w, reserved); // synchronization
dw_put_u8(&w, 0); // Sequence Number starts at 0, gets updated dw_put_u8(&w, sacn->sequence_iter);
dw_put_u8(&w, options); dw_put_u8(&w, options);
dw_put_u16_b(&w, universe); dw_put_u16_b(&w, universe);
@ -148,8 +364,8 @@ sacn_fill_buffer_header(Output_Data* d, u16 universe, Sacn* sacn)
dw_put_u8(&w, SACN_DMP_VECTOR); dw_put_u8(&w, SACN_DMP_VECTOR);
dw_put_u8(&w, SACN_ADDRESS_AND_DATA_FORMAT); dw_put_u8(&w, SACN_ADDRESS_AND_DATA_FORMAT);
dw_put_u8(&w, 0); // dmp first priority addr dw_put_u16_b(&w, 0); // dmp first priority addr
dw_put_u8(&w, SACN_ADDR_INC); // dmp address increment dw_put_u16_b(&w, SACN_ADDR_INC); // dmp address increment
dw_put_u16_b(&w, slot_count + 1); dw_put_u16_b(&w, slot_count + 1);
dw_put_u8(&w, start_code); dw_put_u8(&w, start_code);
@ -157,9 +373,20 @@ sacn_fill_buffer_header(Output_Data* d, u16 universe, Sacn* sacn)
} }
internal void internal void
sacn_fill_buffer_body(Output_Data* d, u32* leds_placed) sacn_fill_buffer_body(Output_Data* d, Assembly_Pixel_Buffer* pixels, Assembly_Strip* strip, u32* leds_placed)
{ {
u32 first = *leds_placed;
u32 to_add = min(strip->pixels_len - first, SACN_BUFFER_BODY_SIZE / 3);
u32 one_past_last = first + to_add;
for (u32 i = *leds_placed; i < one_past_last; i++)
{
u32 led_index = strip->pixels[i];
Assembly_Pixel color = pixels->pixels[led_index];
d->data.base[SACN_BUFFER_HEADER_SIZE + (i * 3) + 0] = color.r;
d->data.base[SACN_BUFFER_HEADER_SIZE + (i * 3) + 1] = color.g;
d->data.base[SACN_BUFFER_HEADER_SIZE + (i * 3) + 2] = color.b;
}
*leds_placed += to_add;
} }
internal Sacn_Cid internal Sacn_Cid
@ -178,16 +405,34 @@ internal u8*
output_network_sacn_init() output_network_sacn_init()
{ {
Sacn* result = allocator_alloc_struct(permanent, Sacn); Sacn* result = allocator_alloc_struct(permanent, Sacn);
// TODO(PS): get platform send socket zero_struct(*result);
result->source_name = string_f(permanent, "lumenarium::incenter");
String cid_str = lit_str("{67F9D986-544E-4abb-8986-D5F79382586C}"); String cid_str = lit_str("{67F9D986-544E-4abb-8986-D5F79382586C}");
result->cid = sacn_string_to_cid(cid_str); result->cid = sacn_string_to_cid(cid_str);
s32 ttl = 20;
result->socket = os_socket_create(AF_INET, SOCK_DGRAM, 0);
os_socket_set_opt(
result->socket,
IPPROTO_IP,
IP_MULTICAST_TTL,
(u8*)&ttl, sizeof(ttl)
);
return (u8*)result; return (u8*)result;
} }
internal void internal void
output_network_sacn_build(App_State* state, u32 assembly_id, Assembly_Strip* strip, u8* method_data, Output_Data_Queue* queue) output_network_sacn_update(u8* method_data)
{
Sacn* sacn = (Sacn*)method_data;
sacn->sequence_iter += 1;
}
internal void
output_network_sacn_build(App_State* state, u32 assembly_id, Assembly_Pixel_Buffer* pixels, Assembly_Strip* strip, u8* method_data, Output_Data_Queue* queue)
{ {
Sacn* sacn = (Sacn*)method_data; Sacn* sacn = (Sacn*)method_data;
@ -200,8 +445,9 @@ output_network_sacn_build(App_State* state, u32 assembly_id, Assembly_Strip* str
Output_Data* d = output_data_queue_push(queue, SACN_BUFFER_SIZE, OutputData_NetworkSACN); Output_Data* d = output_data_queue_push(queue, SACN_BUFFER_SIZE, OutputData_NetworkSACN);
output_data_set_network_addr(d, v4_send_addr, send_port); output_data_set_network_addr(d, v4_send_addr, send_port);
//InitStreamHeader(d->data.base, d->data.size, SACN_BUFFER_BODY_SIZE, SACN_STARTCODE_DMX, universe, 0, 0, 0, "lumenarium::sacn", sacn->cid);
sacn_fill_buffer_header(d, universe, sacn); sacn_fill_buffer_header(d, universe, sacn);
sacn_fill_buffer_body(d, &leds_placed); sacn_fill_buffer_body(d, pixels, strip, &leds_placed);
universe += 1; universe += 1;
} }
} }

View File

@ -16,9 +16,11 @@ struct Sacn
Sacn_Cid cid; Sacn_Cid cid;
s32 sequence_iter; s32 sequence_iter;
String source_name; String source_name;
Socket_Handle socket;
}; };
internal u8* output_network_sacn_init(); internal u8* output_network_sacn_init();
internal void output_network_sacn_build(App_State* state, u32 assembly_id, Assembly_Strip* strip, u8* method_data, Output_Data_Queue* queue); internal void output_network_sacn_update(u8* method_data);
internal void output_network_sacn_build(App_State* state, u32 assembly_id, Assembly_Pixel_Buffer* pixels, Assembly_Strip* strip, u8* method_data, Output_Data_Queue* queue);
#endif //LUMENARIUM_OUTPUT_SACN_H #endif //LUMENARIUM_OUTPUT_SACN_H

View File

@ -9,7 +9,8 @@ lumenarium_init(Editor_Desc* ed_desc)
permanent = bump_allocator_create_reserve(GB(2)); permanent = bump_allocator_create_reserve(GB(2));
global_scratch_ = bump_allocator_create_reserve(GB(4)); global_scratch_ = bump_allocator_create_reserve(GB(4));
//run_tests(); run_tests();
scratch_get(scratch); scratch_get(scratch);
App_Init_Desc desc = incenter_get_init_desc(); App_Init_Desc desc = incenter_get_init_desc();
// TODO(PS): make sure the values make sense in desc // TODO(PS): make sure the values make sense in desc
@ -20,6 +21,7 @@ lumenarium_init(Editor_Desc* ed_desc)
add_flag(state->flags, AppState_RunUserSpace); add_flag(state->flags, AppState_RunUserSpace);
state->file_async_job_system = os_file_jobs_init(); state->file_async_job_system = os_file_jobs_init();
open_sockets_init();
state->input_state = input_state_create(permanent); state->input_state = input_state_create(permanent);
String exe_file_path = os_get_exe_path(scratch.a); String exe_file_path = os_get_exe_path(scratch.a);

View File

@ -17,6 +17,7 @@ global Allocator* global_scratch_; // gets reset at frame boundaries
// Engine // Engine
typedef struct Assembly_Strip Assembly_Strip; typedef struct Assembly_Strip Assembly_Strip;
typedef struct Assembly_Pixel_Buffer Assembly_Pixel_Buffer;
#include "engine/lumenarium_engine_output.h" #include "engine/lumenarium_engine_output.h"
#include "engine/lumenarium_engine_assembly.h" #include "engine/lumenarium_engine_assembly.h"
#include "engine/output/lumenarium_output_uart.h" #include "engine/output/lumenarium_output_uart.h"
@ -48,6 +49,8 @@ lumenarium_env_validate_()
bump_allocator_validate(permanent); bump_allocator_validate(permanent);
bump_allocator_validate(global_scratch_); bump_allocator_validate(global_scratch_);
bump_allocator_validate(file_jobs_arena); bump_allocator_validate(file_jobs_arena);
core_socket_tests();
} }

View File

@ -155,7 +155,7 @@ dw_get_u8(Data_Writer* w)
u8 result = 0; u8 result = 0;
if (w->at < w->data.size) if (w->at < w->data.size)
{ {
result = w->data.base[w->at++]; result = w->data.base[w->at];
} }
return result; return result;
} }
@ -227,6 +227,24 @@ dw_put_str(Data_Writer* w, String str)
} }
} }
internal void
dw_put_str_min_len(Data_Writer* w, String str, u64 min_len)
{
u64 start = w->at;
dw_put_str(w, str);
if (str->len < min_len)
{
w->at = start + min_len;
}
}
internal void
dw_put_str_min_len_nullterm(Data_Writer* w, String str, u64 min_len)
{
dw_put_str_min_len(w, str, min_len);
w->data.base[w->at - 1] = '\0';
}
// TODO(PS): get functions // TODO(PS): get functions
#define Bytes(x) (x) #define Bytes(x) (x)

View File

@ -45,14 +45,17 @@ u32 os_interlocked_cmp_exchg(volatile u32* dest, u32 new_value, u32 old_value);
/////////////////////////////////////// ///////////////////////////////////////
// Network Access // Network Access
Socket_Handle os_socket_create(); Socket_Handle os_socket_create(s32 domain, s32 type, s32 protocol);
bool os_socket_bind(); bool os_socket_bind();
bool os_socket_connect(); bool os_socket_connect();
bool os_socket_close(); bool os_socket_close();
Data os_socket_recv(); Data os_socket_recv();
s32 os_Socket_set_listening(); s32 os_socket_set_listening();
s32 os_Socket_send(); s32 os_socket_send();
s32 os_Socket_send_to(); s32 os_socket_send_to(Socket_Handle handle, u32 addr, u32 port, Data data, s32 flags);
s32 os_Socket_set_opt(); s32 os_socket_set_opt(Socket_Handle handle, int level, int option_name,
u8* option_value, s32 option_len);
void open_sockets_init();
#endif // LUMENARIUM_OS #endif // LUMENARIUM_OS

View File

@ -8,6 +8,9 @@
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#include <OpenGL/gl.h> #include <OpenGL/gl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "lumenarium_osx_memory.h" #include "lumenarium_osx_memory.h"
#include "../../core/lumenarium_core.h" #include "../../core/lumenarium_core.h"
#include "../lumenarium_os.h" #include "../lumenarium_os.h"
@ -37,34 +40,15 @@ osx_err_print_(char* proc, char* sub_proc, s32 errsv)
#define OS_FILE_HANDLE_TYPE s32 #define OS_FILE_HANDLE_TYPE s32
#define OS_FILE_MAX_PATH PATH_MAX #define OS_FILE_MAX_PATH PATH_MAX
#define OS_FILE_INVALID_HANDLE -1 #define OS_FILE_INVALID_HANDLE -1
#define OS_SOCKET_TYPE s32
#define OS_SOCKET_INVALID_HANDLE -1
#include "../shared/lumenarium_shared_file_tracker.h" #include "../shared/lumenarium_shared_file_tracker.h"
#include "../shared/lumenarium_shared_file_async_work_on_job.h" #include "../shared/lumenarium_shared_file_async_work_on_job.h"
#include "../shared/lumenarium_shared_network.h"
#include "lumenarium_osx_file.h" #include "lumenarium_osx_file.h"
#include "lumenarium_osx_time.h" #include "lumenarium_osx_time.h"
#include "lumenarium_osx_graphics.h" #include "lumenarium_osx_graphics.h"
#include "lumenarium_osx_network.h"
void osx_tests()
{
Ticks t0 = os_get_ticks();
// File Tests
File_Handle file = os_file_open(lit_str("text.txt"), FileAccess_Read | FileAccess_Write, FileCreate_OpenAlways);
File_Info info = os_file_get_info(file, global_scratch_);
Data d = os_file_read_all(file, global_scratch_);
os_file_write_all(file, d);
os_file_close(file);
// Path tests
String path_exe = os_get_exe_path(global_scratch_);
printf("%.*s\n", str_varg(path_exe));
String path = string_chop_last_slash(path_exe);
String path0 = string_copy(path, global_scratch_);
os_pwd_set(path0);
Ticks t1 = os_get_ticks();
Ticks td = get_ticks_elapsed(t0, t1);
r64 sd = ticks_to_seconds(td, os_get_ticks_per_second());
}
void void
glfw_error_callback(int error, const char* description) glfw_error_callback(int error, const char* description)
@ -280,8 +264,6 @@ scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
int main (int arg_count, char** args) int main (int arg_count, char** args)
{ {
// osx_tests();
if (!glfwInit()) if (!glfwInit())
{ {
printf("Error: Could not initialize glfw.\n"); printf("Error: Could not initialize glfw.\n");

View File

@ -0,0 +1,86 @@
Socket_Handle
os_socket_create(s32 domain, s32 type, s32 protocol)
{
Socket_Handle result = {};
OS_SOCKET_TYPE sock = socket(domain, type, protocol);
if (sock == -1) {
perror("Error: os_socket_create\n");
return result;
}
result = open_sockets_put(sock);
if (result.value == 0)
{
fprintf(stderr, "Error: os_socket_create - not enough room in open_sockets\n");
}
return result;
}
bool
os_socket_bind()
{
return false;
}
bool
os_socket_connect()
{
return false;
}
bool
os_socket_close()
{
return false;
}
Data
os_socket_recv()
{
return (Data){};
}
s32
os_socket_set_listening()
{
return 0;
}
s32
os_socket_send()
{
return 0;
}
s32
os_socket_send_to(Socket_Handle handle, u32 addr, u32 port, Data data, s32 flags)
{
OS_SOCKET_TYPE sock = open_sockets_get(handle);
struct sockaddr_in dst = {
.sin_family = AF_INET,
.sin_port = hton_u16(port),
.sin_addr.s_addr = hton_u32(addr),
};
struct sockaddr* dst_ptr = (struct sockaddr*)&dst;
s32 len_sent = sendto(sock, data.base, data.size, flags, dst_ptr, sizeof(struct sockaddr_in));
if (len_sent == -1)
{
perror("Error: os_socket_send_to\n");
return 0;
}
return len_sent;
}
s32
os_socket_set_opt(Socket_Handle handle, int level, int option_name,
u8* option_value, s32 option_len)
{
OS_SOCKET_TYPE sock = open_sockets_get(handle);
s32 err = setsockopt(sock, level, option_name, (void*)option_value, (socklen_t)option_len);
if (err) {
fprintf(stderr, "Error: setsockopt - %d\n\targs: %d %d %.*s\n", err, level, option_name, option_len, (char*)option_value);
}
return 0;
}

View File

@ -0,0 +1,67 @@
#if !defined(OS_SOCKET_TYPE)
# error "You must define an OS_SOCKET_TYPE"
#endif
#if !defined(OS_SOCKET_INVALID_HANDLE)
# error "You must define an OS_SOCKET_INVALID_HANDLE"
#endif
#define open_sockets_cap 2
global u32 open_sockets_len = 1;
global OS_SOCKET_TYPE open_sockets[open_sockets_cap];
void open_sockets_init();
s32 open_sockets_next_free();
bool open_sockets_has_room();
OS_SOCKET_TYPE open_sockets_get(Socket_Handle handle);
Socket_Handle open_sockets_put(OS_SOCKET_TYPE socket);
void open_sockets_rem(Socket_Handle handle);
////////////////////////////////////////////////
// IMPLEMENTATION
void
open_sockets_init()
{
for (u32 i = 0; i < open_sockets_cap; i++)
{
open_sockets[i] = OS_SOCKET_INVALID_HANDLE;
}
}
s32
open_sockets_next_free()
{
if (open_sockets_len < open_sockets_cap) return open_sockets_len++;
for (u32 i = 1; i < open_sockets_len; i++)
{
if (open_sockets[i] == OS_SOCKET_INVALID_HANDLE) return i;
}
return 0;
}
OS_SOCKET_TYPE
open_sockets_get(Socket_Handle handle)
{
assert(handle.value < open_sockets_len);
return open_sockets[handle.value];
}
Socket_Handle
open_sockets_put(OS_SOCKET_TYPE socket)
{
Socket_Handle result = { .value = open_sockets_next_free() };
assert(result.value != 0);
open_sockets[result.value] = socket;
return result;
}
void
open_sockets_rem(Socket_Handle handle)
{
assert(handle.value < open_sockets_len);
open_sockets[handle.value] = OS_SOCKET_INVALID_HANDLE;
if (handle.value + 1 == open_sockets_len) {
open_sockets_len -= 1;
}
}

View File

@ -40,6 +40,8 @@ incenter_init(App_State* state)
for (u32 i = 0; i < 40; i++) for (u32 i = 0; i < 40; i++)
{ {
Assembly_Strip* strip = assembly_add_strip(&state->assemblies, ah, 123); Assembly_Strip* strip = assembly_add_strip(&state->assemblies, ah, 123);
strip->output_kind = OutputData_NetworkSACN;
strip->sacn_universe = i;
r32 theta = random_series_next_unilateral(&rand) * r32_tau; r32 theta = random_series_next_unilateral(&rand) * r32_tau;
r32 phi = random_series_next_unilateral(&rand) * r32_tau; r32 phi = random_series_next_unilateral(&rand) * r32_tau;