mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 18:10:14 +01:00
remove servicepoint_binding_cs
This commit is contained in:
parent
11ec30ca74
commit
12ba47a281
|
@ -3,7 +3,6 @@ resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"crates/servicepoint",
|
"crates/servicepoint",
|
||||||
"crates/servicepoint_binding_c",
|
"crates/servicepoint_binding_c",
|
||||||
"crates/servicepoint_binding_cs",
|
|
||||||
"crates/servicepoint_binding_c/examples/lang_c"
|
"crates/servicepoint_binding_c/examples/lang_c"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "servicepoint_binding_cs"
|
|
||||||
version.workspace = true
|
|
||||||
edition = "2021"
|
|
||||||
publish = false
|
|
||||||
readme = "README.md"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type = ["cdylib"]
|
|
||||||
test = false
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
csbindgen = "1.9.3"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
servicepoint_binding_c = { version = "0.11.0", path = "../servicepoint_binding_c" }
|
|
||||||
servicepoint = { version = "0.11.0", path = "../servicepoint" }
|
|
||||||
|
|
||||||
[lints]
|
|
||||||
workspace = true
|
|
|
@ -1,65 +0,0 @@
|
||||||
# ServicePoint
|
|
||||||
|
|
||||||
In [CCCB](https://berlin.ccc.de/), there is a big pixel matrix hanging on the wall. It is called "Service Point
|
|
||||||
Display" or "Airport Display".
|
|
||||||
This crate contains C# bindings for the `servicepoint` library, enabling users to parse, encode and send packets to this display via UDP.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using ServicePoint;
|
|
||||||
|
|
||||||
// using statement calls Dispose() on scope exit, which frees unmanaged instances
|
|
||||||
using var connection = Connection.Open("127.0.0.1:2342");
|
|
||||||
using var pixels = Bitmap.New(Constants.PixelWidth, Constants.PixelHeight);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
pixels.Fill(true);
|
|
||||||
connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone()));
|
|
||||||
Thread.Sleep(5000);
|
|
||||||
|
|
||||||
pixels.Fill(false);
|
|
||||||
connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone()));
|
|
||||||
Thread.Sleep(5000);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
A full example including project files is available as part of this crate.
|
|
||||||
|
|
||||||
## Note on stability
|
|
||||||
|
|
||||||
This library is still in early development.
|
|
||||||
You can absolutely use it, and it works, but expect minor breaking changes with every version bump.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
NuGet packages are not a good way to distribute native projects ([relevant issue](https://github.com/dotnet/sdk/issues/33845)).
|
|
||||||
Because of that, there is no NuGet package you can use directly.
|
|
||||||
Including this repository as a submodule and building from source is the recommended way of using the library.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git submodule add https://github.com/cccb/servicepoint.git
|
|
||||||
git commit -m "add servicepoint submodule"
|
|
||||||
```
|
|
||||||
|
|
||||||
You can now reference `servicepoint-bindings-cs/src/ServicePoint.csproj` in your project.
|
|
||||||
The rust library will automatically be built.
|
|
||||||
|
|
||||||
Please provide more information in the form of an issue if you need the build to copy a different library file for your platform.
|
|
||||||
|
|
||||||
## Notes on differences to rust library
|
|
||||||
|
|
||||||
Uses C bindings internally to provide a similar API to rust. Things to keep in mind:
|
|
||||||
|
|
||||||
- You will get a `NullPointerException` when trying to call a method where the native instance has been consumed already (e.g. when `Send`ing a command instance twice). Send a clone instead of the original if you want to keep using it.
|
|
||||||
- Some lower-level APIs _will_ panic in native code when used improperly.
|
|
||||||
Example: manipulating the `Span<byte>` of an object after freeing the instance.
|
|
||||||
- C# specifics are documented in the library. Use the rust documentation for everything else. Naming and semantics are the same apart from CamelCase instead of kebab_case.
|
|
||||||
- You will only get rust backtraces in debug builds of the native code.
|
|
||||||
- F# is not explicitly tested. If there are usability or functionality problems, please open an issue.
|
|
||||||
- Reading and writing to instances concurrently is not safe. Only reading concurrently is safe.
|
|
||||||
|
|
||||||
## Everything else
|
|
||||||
|
|
||||||
Look at the main project [README](https://github.com/cccb/servicepoint/blob/main/README.md) for further information.
|
|
|
@ -1,28 +0,0 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicePoint", "ServicePoint/ServicePoint.csproj", "{70EFFA3F-012A-4518-9627-466BEAE4252E}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lang-cs", "examples/lang_cs/lang_cs.csproj", "{DA3B8B6E-993A-47DA-844B-F92AF520FF59}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{C2F8EC4A-2426-4DC3-990F-C43810B183F5}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
..\..\shell.nix = ..\..\shell.nix
|
|
||||||
..\..\.envrc = ..\..\.envrc
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{70EFFA3F-012A-4518-9627-466BEAE4252E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{70EFFA3F-012A-4518-9627-466BEAE4252E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{70EFFA3F-012A-4518-9627-466BEAE4252E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{70EFFA3F-012A-4518-9627-466BEAE4252E}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{DA3B8B6E-993A-47DA-844B-F92AF520FF59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{DA3B8B6E-993A-47DA-844B-F92AF520FF59}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{DA3B8B6E-993A-47DA-844B-F92AF520FF59}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{DA3B8B6E-993A-47DA-844B-F92AF520FF59}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,88 +0,0 @@
|
||||||
using ServicePoint.BindGen;
|
|
||||||
|
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public sealed class BitVec : SpNativeInstance<BindGen.BitVec>
|
|
||||||
{
|
|
||||||
public static BitVec New(int size)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new BitVec(NativeMethods.sp_bitvec_new((nuint)size));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BitVec Load(Span<byte> bytes)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
fixed (byte* bytesPtr = bytes)
|
|
||||||
{
|
|
||||||
return new BitVec(NativeMethods.sp_bitvec_load(bytesPtr, (nuint)bytes.Length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitVec Clone()
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new BitVec(NativeMethods.sp_bitvec_clone(Instance));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool this[int index]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return NativeMethods.sp_bitvec_get(Instance, (nuint)index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
NativeMethods.sp_bitvec_set(Instance, (nuint)index, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Fill(bool value)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
NativeMethods.sp_bitvec_fill(Instance, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Length
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return (int)NativeMethods.sp_bitvec_len(Instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Span<byte> Data
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
var slice = NativeMethods.sp_bitvec_unsafe_data_ref(Instance);
|
|
||||||
return new Span<byte>(slice.start, (int)slice.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe BitVec(BindGen.BitVec* instance) : base(instance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private protected override unsafe void Free() => NativeMethods.sp_bitvec_free(Instance);
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
using ServicePoint.BindGen;
|
|
||||||
|
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public sealed class Bitmap : SpNativeInstance<BindGen.Bitmap>
|
|
||||||
{
|
|
||||||
public static Bitmap New(int width, int height)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Bitmap(NativeMethods.sp_bitmap_new((nuint)width, (nuint)height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bitmap Load(int width, int height, Span<byte> bytes)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
fixed (byte* bytesPtr = bytes)
|
|
||||||
{
|
|
||||||
return new Bitmap(NativeMethods.sp_bitmap_load((nuint)width, (nuint)height, bytesPtr,
|
|
||||||
(nuint)bytes.Length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitmap Clone()
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Bitmap(NativeMethods.sp_bitmap_clone(Instance));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool this[int x, int y]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return NativeMethods.sp_bitmap_get(Instance, (nuint)x, (nuint)y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
NativeMethods.sp_bitmap_set(Instance, (nuint)x, (nuint)y, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Fill(bool value)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
NativeMethods.sp_bitmap_fill(Instance, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Width
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return (int)NativeMethods.sp_bitmap_width(Instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Height
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return (int)NativeMethods.sp_bitmap_height(Instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Span<byte> Data
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
var slice = NativeMethods.sp_bitmap_unsafe_data_ref(Instance);
|
|
||||||
return new Span<byte>(slice.start, (int)slice.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe Bitmap(BindGen.Bitmap* instance) : base(instance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private protected override unsafe void Free() => NativeMethods.sp_bitmap_free(Instance);
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
using ServicePoint.BindGen;
|
|
||||||
|
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public sealed class BrightnessGrid : SpNativeInstance<BindGen.BrightnessGrid>
|
|
||||||
{
|
|
||||||
public static BrightnessGrid New(int width, int height)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new BrightnessGrid(NativeMethods.sp_brightness_grid_new((nuint)width, (nuint)height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BrightnessGrid Load(int width, int height, Span<byte> bytes)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
fixed (byte* bytesPtr = bytes)
|
|
||||||
{
|
|
||||||
return new BrightnessGrid(NativeMethods.sp_brightness_grid_load((nuint)width, (nuint)height, bytesPtr,
|
|
||||||
(nuint)bytes.Length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BrightnessGrid Clone()
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new BrightnessGrid(NativeMethods.sp_brightness_grid_clone(Instance));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte this[int x, int y]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return NativeMethods.sp_brightness_grid_get(Instance, (nuint)x, (nuint)y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
NativeMethods.sp_brightness_grid_set(Instance, (nuint)x, (nuint)y, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Fill(byte value)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
NativeMethods.sp_brightness_grid_fill(Instance, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Width
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return (int)NativeMethods.sp_brightness_grid_width(Instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Height
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return (int)NativeMethods.sp_brightness_grid_height(Instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Span<byte> Data
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
var slice = NativeMethods.sp_brightness_grid_unsafe_data_ref(Instance);
|
|
||||||
return new Span<byte>(slice.start, (int)slice.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe BrightnessGrid(BindGen.BrightnessGrid* instance) : base(instance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private protected override unsafe void Free() => NativeMethods.sp_brightness_grid_free(Instance);
|
|
||||||
}
|
|
|
@ -1,129 +0,0 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using ServicePoint.BindGen;
|
|
||||||
|
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public sealed class Command : SpNativeInstance<BindGen.Command>
|
|
||||||
{
|
|
||||||
public static bool TryFromPacket(Packet packet, [MaybeNullWhen(false)] out Command command)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
var result = NativeMethods.sp_command_try_from_packet(packet.Into());
|
|
||||||
if (result == null)
|
|
||||||
{
|
|
||||||
command = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
command = new Command(result);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Command Clone()
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(NativeMethods.sp_command_clone(Instance));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command Clear()
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(NativeMethods.sp_command_clear());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command HardReset()
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(NativeMethods.sp_command_hard_reset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command FadeOut()
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(NativeMethods.sp_command_fade_out());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command Brightness(byte brightness)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(NativeMethods.sp_command_brightness(brightness));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command CharBrightness(int x, int y, BrightnessGrid grid)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(NativeMethods.sp_command_char_brightness((ushort)x, (ushort)y, grid.Into()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command BitmapLinear(int offset, BitVec bitVec, CompressionCode compressionCode)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(
|
|
||||||
NativeMethods.sp_command_bitmap_linear((ushort)offset, bitVec.Into(), compressionCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command BitmapLinearAnd(int offset, BitVec bitVec, CompressionCode compressionCode)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(
|
|
||||||
NativeMethods.sp_command_bitmap_linear_and((ushort)offset, bitVec.Into(), compressionCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command BitmapLinearOr(int offset, BitVec bitVec, CompressionCode compressionCode)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(
|
|
||||||
NativeMethods.sp_command_bitmap_linear_or((ushort)offset, bitVec.Into(), compressionCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command BitmapLinearXor(int offset, BitVec bitVec, CompressionCode compressionCode)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(
|
|
||||||
NativeMethods.sp_command_bitmap_linear_xor((ushort)offset, bitVec.Into(), compressionCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command BitmapLinearWin(int x, int y, Bitmap bitmap, CompressionCode compression)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(NativeMethods.sp_command_bitmap_linear_win((ushort)x, (ushort)y, bitmap.Into(), compression));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Command Cp437Data(int x, int y, Cp437Grid byteGrid)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Command(NativeMethods.sp_command_cp437_data((ushort)x, (ushort)y, byteGrid.Into()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe Command(BindGen.Command* instance) : base(instance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private protected override unsafe void Free() => NativeMethods.sp_command_free(Instance);
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
using System.Text;
|
|
||||||
using ServicePoint.BindGen;
|
|
||||||
|
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public sealed class Connection : SpNativeInstance<BindGen.Connection>
|
|
||||||
{
|
|
||||||
public static Connection Open(string host)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
fixed (byte* bytePtr = Encoding.UTF8.GetBytes(host))
|
|
||||||
{
|
|
||||||
return new Connection(NativeMethods.sp_connection_open(bytePtr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Send(Packet packet)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return NativeMethods.sp_connection_send_packet(Instance, packet.Into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Send(Command command)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return NativeMethods.sp_connection_send_command(Instance, command.Into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private protected override unsafe void Free() => NativeMethods.sp_connection_free(Instance);
|
|
||||||
|
|
||||||
private unsafe Connection(BindGen.Connection* instance) : base(instance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
using ServicePoint.BindGen;
|
|
||||||
|
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public static class Constants
|
|
||||||
{
|
|
||||||
/// size of a single tile in one dimension
|
|
||||||
public const nuint TileSize = NativeMethods.SP_TILE_SIZE;
|
|
||||||
|
|
||||||
/// tile count in the x-direction
|
|
||||||
public const nuint TileWidth = NativeMethods.SP_TILE_WIDTH;
|
|
||||||
|
|
||||||
/// tile count in the y-direction
|
|
||||||
public const nuint TileHeight = NativeMethods.SP_TILE_SIZE;
|
|
||||||
|
|
||||||
/// screen width in pixels
|
|
||||||
public const nuint PixelWidth = TileWidth * TileSize;
|
|
||||||
|
|
||||||
/// screen height in pixels
|
|
||||||
public const nuint PixelHeight = TileHeight * TileSize;
|
|
||||||
|
|
||||||
/// pixel count on whole screen
|
|
||||||
public const nuint PixelCount = PixelWidth * PixelHeight;
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
using System.Text;
|
|
||||||
using ServicePoint.BindGen;
|
|
||||||
|
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public sealed class Cp437Grid : SpNativeInstance<BindGen.Cp437Grid>
|
|
||||||
{
|
|
||||||
public static Cp437Grid New(int width, int height)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Cp437Grid(NativeMethods.sp_cp437_grid_new((nuint)width, (nuint)height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Cp437Grid Load(int width, int height, Span<byte> bytes)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
fixed (byte* bytesPtr = bytes)
|
|
||||||
{
|
|
||||||
return new Cp437Grid(NativeMethods.sp_cp437_grid_load((nuint)width, (nuint)height, bytesPtr,
|
|
||||||
(nuint)bytes.Length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cp437Grid Clone()
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Cp437Grid(NativeMethods.sp_cp437_grid_clone(Instance));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte this[int x, int y]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return NativeMethods.sp_cp437_grid_get(Instance, (nuint)x, (nuint)y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
NativeMethods.sp_cp437_grid_set(Instance, (nuint)x, (nuint)y, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string this[int y]
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
var width = Width;
|
|
||||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(value.Length, width);
|
|
||||||
|
|
||||||
var x = 0;
|
|
||||||
for (; x < value.Length; x++)
|
|
||||||
this[x, y] = (byte)value[x];
|
|
||||||
|
|
||||||
for (; x < width; x++)
|
|
||||||
this[x, y] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
for (int x = 0; x < Width; x++)
|
|
||||||
{
|
|
||||||
var val = this[x, y];
|
|
||||||
if (val == 0)
|
|
||||||
break;
|
|
||||||
sb.Append((char)val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Fill(byte value)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
NativeMethods.sp_cp437_grid_fill(Instance, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Width
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return (int)NativeMethods.sp_cp437_grid_width(Instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Height
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return (int)NativeMethods.sp_cp437_grid_height(Instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Span<byte> Data
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
var slice = NativeMethods.sp_cp437_grid_unsafe_data_ref(Instance);
|
|
||||||
return new Span<byte>(slice.start, (int)slice.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe Cp437Grid(BindGen.Cp437Grid* instance) : base(instance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private protected override unsafe void Free() => NativeMethods.sp_cp437_grid_free(Instance);
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
global using System;
|
|
|
@ -1,36 +0,0 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using ServicePoint.BindGen;
|
|
||||||
|
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public sealed class Packet : SpNativeInstance<BindGen.Packet>
|
|
||||||
{
|
|
||||||
public static Packet FromCommand(Command command)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
return new Packet(NativeMethods.sp_packet_from_command(command.Into()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryFromBytes(Span<byte> bytes, [MaybeNullWhen(false)] out Packet packet)
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
fixed (byte* bytesPtr = bytes)
|
|
||||||
{
|
|
||||||
var instance = NativeMethods.sp_packet_try_load(bytesPtr, (nuint)bytes.Length);
|
|
||||||
packet = instance == null
|
|
||||||
? null
|
|
||||||
: new Packet(instance);
|
|
||||||
return packet != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe Packet(BindGen.Packet* instance) : base(instance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private protected override unsafe void Free() => NativeMethods.sp_packet_free(Instance);
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<ImplicitUsings>disable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
|
|
||||||
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<PackageId>ServicePoint</PackageId>
|
|
||||||
<Version>0.11.0</Version>
|
|
||||||
<Authors>Repository Authors</Authors>
|
|
||||||
<Company>None</Company>
|
|
||||||
<Product>ServicePoint</Product>
|
|
||||||
<PackageTags>CCCB</PackageTags>
|
|
||||||
<Description>
|
|
||||||
C# bindings for the rust crate servicepoint. You will need a suitable native shared library to use this.
|
|
||||||
For documentation, see the rust documentation: https://docs.rs/servicepoint/latest/servicepoint/.
|
|
||||||
Note that this library is still in early development. Breaking changes are expected before 1.0 is released.
|
|
||||||
</Description>
|
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
|
||||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- generate C# bindings -->
|
|
||||||
<Target Name="BuildBindings" Condition="'$(Configuration)'=='Release'" BeforeTargets="PrepareForBuild">
|
|
||||||
<Exec Command="cargo build --release"/>
|
|
||||||
<Exec Command="cargo build --manifest-path ../../../crates/servicepoint_binding_c/Cargo.toml --release"/>
|
|
||||||
</Target>
|
|
||||||
<Target Name="BuildBindings" Condition="'$(Configuration)'=='Debug'" BeforeTargets="PrepareForBuild">
|
|
||||||
<Exec Command="cargo build"/>
|
|
||||||
<Exec Command="cargo build --manifest-path ../../../crates/servicepoint_binding_c/Cargo.toml"/>
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
<!-- include native binary in output -->
|
|
||||||
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
|
||||||
<Content Include="../../../target/debug/libservicepoint_binding_c.so" CopyToOutputDirectory="Always">
|
|
||||||
<Link>libservicepoint_binding_c.so</Link>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup Condition="'$(Configuration)'=='Release'">
|
|
||||||
<Content Include="../../../target/release/libservicepoint_binding_c.so" CopyToOutputDirectory="Always">
|
|
||||||
<Link>libservicepoint_binding_c.so</Link>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<!-- include link to source code at revision -->
|
|
||||||
<None Include="../README.md" Pack="true" PackagePath="\"/>
|
|
||||||
<!-- add README.md to package -->
|
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
|
@ -1,16 +0,0 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public static class ServicePointExtensions
|
|
||||||
{
|
|
||||||
public static Packet IntoPacket(this Command command)
|
|
||||||
{
|
|
||||||
return Packet.FromCommand(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryIntoCommand(this Packet packet, [MaybeNullWhen(false)] out Command command)
|
|
||||||
{
|
|
||||||
return Command.TryFromPacket(packet, out command);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
namespace ServicePoint;
|
|
||||||
|
|
||||||
public abstract class SpNativeInstance<T>
|
|
||||||
: IDisposable
|
|
||||||
where T : unmanaged
|
|
||||||
{
|
|
||||||
private unsafe T* _instance;
|
|
||||||
|
|
||||||
internal unsafe T* Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
throw new NullReferenceException("instance is null");
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private protected unsafe SpNativeInstance(T* instance)
|
|
||||||
{
|
|
||||||
ArgumentNullException.ThrowIfNull(instance);
|
|
||||||
_instance = instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private protected abstract void Free();
|
|
||||||
|
|
||||||
internal unsafe T* Into()
|
|
||||||
{
|
|
||||||
var instance = _instance;
|
|
||||||
_instance = null;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe void ReleaseUnmanagedResources()
|
|
||||||
{
|
|
||||||
if (_instance != null)
|
|
||||||
Free();
|
|
||||||
_instance = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
ReleaseUnmanagedResources();
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~SpNativeInstance()
|
|
||||||
{
|
|
||||||
ReleaseUnmanagedResources();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
//! Build script generating the C# code needed to call methods from the `servicepoint` C library.
|
|
||||||
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("cargo::rerun-if-changed=../servicepoint_binding_c/src");
|
|
||||||
println!("cargo::rerun-if-changed=build.rs");
|
|
||||||
|
|
||||||
let mut builder = csbindgen::Builder::default();
|
|
||||||
|
|
||||||
let mut paths = fs::read_dir("../servicepoint_binding_c/src").unwrap()
|
|
||||||
.map(|x| x.unwrap().path())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
paths.sort();
|
|
||||||
|
|
||||||
for path in paths {
|
|
||||||
println!("cargo:rerun-if-changed={}", path.display());
|
|
||||||
builder = builder.input_extern_file(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder
|
|
||||||
.csharp_dll_name("servicepoint_binding_c")
|
|
||||||
.csharp_namespace("ServicePoint.BindGen")
|
|
||||||
.csharp_use_nint_types(true)
|
|
||||||
.csharp_class_accessibility("public")
|
|
||||||
.csharp_generate_const_filter(|_| true)
|
|
||||||
.csharp_type_rename(move |name| {
|
|
||||||
if name.len() > 2
|
|
||||||
&& name.starts_with("SP")
|
|
||||||
&& name.chars().nth(2).unwrap().is_uppercase()
|
|
||||||
{
|
|
||||||
name[2..].to_string()
|
|
||||||
} else {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.generate_csharp_file("ServicePoint/BindGen/ServicePoint.g.cs")
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
using ServicePoint;
|
|
||||||
using CompressionCode = ServicePoint.BindGen.CompressionCode;
|
|
||||||
|
|
||||||
using var connection = Connection.Open("127.0.0.1:2342");
|
|
||||||
|
|
||||||
connection.Send(Command.Clear().IntoPacket());
|
|
||||||
connection.Send(Command.Brightness(128).IntoPacket());
|
|
||||||
|
|
||||||
using var pixels = Bitmap.New(Constants.PixelWidth, Constants.PixelHeight);
|
|
||||||
|
|
||||||
for (var offset = 0; offset < int.MaxValue; offset++)
|
|
||||||
{
|
|
||||||
pixels.Fill(false);
|
|
||||||
|
|
||||||
for (var y = 0; y < pixels.Height; y++)
|
|
||||||
pixels[(y + offset) % Constants.PixelWidth, y] = true;
|
|
||||||
|
|
||||||
connection.Send(Command.BitmapLinearWin(0, 0, pixels.Clone(), CompressionCode.Lzma).IntoPacket());
|
|
||||||
Thread.Sleep(14);
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<RootNamespace>lang_cs</RootNamespace>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="../../ServicePoint/ServicePoint.csproj"/>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
|
@ -1 +0,0 @@
|
||||||
//! This crate is intentionally left empty. Only the build script is relevant here.
|
|
Loading…
Reference in a new issue