Add managed UIKit iOS client
.NET port / test (macos-latest) (push) Canceled after 0s
.NET port / test (ubuntu-24.04) (push) Canceled after 0s
.NET port / test (windows-latest) (push) Canceled after 0s
.NET port / apple-client (push) Canceled after 0s
.NET port / cpp-conformance (push) Canceled after 0s
.NET port / test (macos-latest) (push) Canceled after 0s
.NET port / test (ubuntu-24.04) (push) Canceled after 0s
.NET port / test (windows-latest) (push) Canceled after 0s
.NET port / apple-client (push) Canceled after 0s
.NET port / cpp-conformance (push) Canceled after 0s
This commit is contained in:
@@ -7,4 +7,7 @@
|
||||
<AnalysisLevel>latest</AnalysisLevel>
|
||||
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(VoiceCatIosStatic)' == 'true'">
|
||||
<DefineConstants>$(DefineConstants);VOICECAT_IOS_STATIC</DefineConstants>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/bin/zsh
|
||||
set -euo pipefail
|
||||
|
||||
script_dir=${0:A:h}
|
||||
build_one() {
|
||||
local sdk=$1
|
||||
local rid=$2
|
||||
local sdk_path
|
||||
sdk_path=$(xcrun --sdk "$sdk" --show-sdk-path)
|
||||
local compiler
|
||||
compiler=$(xcrun --sdk "$sdk" --find clang)
|
||||
local build_dir="$script_dir/artifacts/native-build-$rid-cmake"
|
||||
cmake -S "$script_dir/native" -B "$build_dir" \
|
||||
-DCMAKE_SYSTEM_NAME=iOS \
|
||||
-DCMAKE_C_COMPILER="$compiler" \
|
||||
-DCMAKE_OSX_SYSROOT="$sdk_path" \
|
||||
-DCMAKE_OSX_ARCHITECTURES=arm64 \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=18.0 \
|
||||
-DVOICECAT_DOTNET_RID="$rid" \
|
||||
-DVOICECAT_BUNDLED_OPUS=ON
|
||||
cmake --build "$build_dir" --config Release --target voicecat_media --parallel 2
|
||||
cmake --install "$build_dir" --config Release \
|
||||
--component DotnetMedia --prefix "$script_dir/artifacts/native"
|
||||
local staged="$script_dir/artifacts/native/runtimes/$rid/native/libvoicecat_media.a"
|
||||
local opus="$build_dir/_deps/opus-build/libopus.a"
|
||||
local rnnoise="$build_dir/librnnoise.a"
|
||||
local combined="$staged.combined"
|
||||
xcrun --sdk "$sdk" libtool -static -o "$combined" "$build_dir/libvoicecat_media.a" "$opus" "$rnnoise"
|
||||
mv "$combined" "$staged"
|
||||
}
|
||||
|
||||
build_one iphoneos ios-arm64
|
||||
build_one iphonesimulator iossimulator-arm64
|
||||
@@ -6,8 +6,9 @@ if(MSVC)
|
||||
set(OPUS_STATIC_RUNTIME ON CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
||||
set(VOICECAT_MEDIA_LIBRARY_TYPE SHARED)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
message(FATAL_ERROR "iOS static NativeReference packaging belongs to the later client phase.")
|
||||
set(VOICECAT_MEDIA_LIBRARY_TYPE STATIC)
|
||||
endif()
|
||||
|
||||
if(NOT TARGET Opus::opus)
|
||||
@@ -59,7 +60,7 @@ if(NOT TARGET rnnoise)
|
||||
set_target_properties(rnnoise PROPERTIES POSITION_INDEPENDENT_CODE ON C_VISIBILITY_PRESET hidden)
|
||||
endif()
|
||||
|
||||
add_library(voicecat_media SHARED media.c)
|
||||
add_library(voicecat_media ${VOICECAT_MEDIA_LIBRARY_TYPE} media.c)
|
||||
target_compile_features(voicecat_media PRIVATE c_std_99)
|
||||
target_link_libraries(voicecat_media PRIVATE Opus::opus rnnoise)
|
||||
set_target_properties(voicecat_media PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
@@ -93,7 +94,8 @@ endif()
|
||||
|
||||
install(TARGETS voicecat_media
|
||||
RUNTIME DESTINATION runtimes/${VOICECAT_DOTNET_RID}/native COMPONENT DotnetMedia
|
||||
LIBRARY DESTINATION runtimes/${VOICECAT_DOTNET_RID}/native COMPONENT DotnetMedia)
|
||||
LIBRARY DESTINATION runtimes/${VOICECAT_DOTNET_RID}/native COMPONENT DotnetMedia
|
||||
ARCHIVE DESTINATION runtimes/${VOICECAT_DOTNET_RID}/native COMPONENT DotnetMedia)
|
||||
install(FILES ${RNNOISE_DIR}/COPYING DESTINATION licenses RENAME RNNoise.txt COMPONENT DotnetMedia)
|
||||
install(FILES ${CMAKE_CURRENT_LIST_DIR}/NOTICE.txt DESTINATION licenses COMPONENT DotnetMedia)
|
||||
if(VOICECAT_OPUS_LICENSE)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"Google.Protobuf": "[3.36.1, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"net10.0/iossimulator-arm64": {}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,11 @@ namespace VoiceCat.Codec;
|
||||
|
||||
internal static unsafe partial class NativeMethods
|
||||
{
|
||||
#if VOICECAT_IOS_STATIC
|
||||
private const string Library = "__Internal";
|
||||
#else
|
||||
private const string Library = "voicecat_media";
|
||||
#endif
|
||||
[LibraryImport(Library, EntryPoint = "vcm_opus_version")]
|
||||
internal static partial nint Version();
|
||||
[LibraryImport(Library, EntryPoint = "vcm_opus_error")]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net10.0": {}
|
||||
"net10.0": {},
|
||||
"net10.0/iossimulator-arm64": {}
|
||||
}
|
||||
}
|
||||
@@ -32,13 +32,6 @@ public sealed record ServerProfile(Guid Id, string Host, ushort Port, ServerAuth
|
||||
|
||||
public sealed class ServerProfileStore(string path)
|
||||
{
|
||||
private static readonly JsonSerializerOptions Json = new()
|
||||
{
|
||||
Converters = { new JsonStringEnumConverter() },
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
public IReadOnlyList<ServerProfile> Load()
|
||||
{
|
||||
try
|
||||
@@ -48,7 +41,7 @@ public sealed class ServerProfileStore(string path)
|
||||
using JsonDocument document = JsonDocument.Parse(contents);
|
||||
if (document.RootElement.ValueKind == JsonValueKind.Array && document.RootElement.EnumerateArray().Any(LooksLegacy))
|
||||
return LoadLegacy(document.RootElement);
|
||||
return (JsonSerializer.Deserialize<ServerProfile[]>(contents, Json) ?? [])
|
||||
return (JsonSerializer.Deserialize(contents, ServerProfileJsonContext.Default.ServerProfileArray) ?? [])
|
||||
.Where(profile => profile.IsValid).ToArray();
|
||||
}
|
||||
catch (Exception exception) when (exception is IOException or UnauthorizedAccessException or JsonException) { return []; }
|
||||
@@ -64,7 +57,7 @@ public sealed class ServerProfileStore(string path)
|
||||
string temporary = fullPath + "." + Guid.NewGuid().ToString("N") + ".tmp";
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(temporary, JsonSerializer.SerializeToUtf8Bytes(valid, Json));
|
||||
File.WriteAllBytes(temporary, JsonSerializer.SerializeToUtf8Bytes(valid, ServerProfileJsonContext.Default.ServerProfileArray));
|
||||
File.Move(temporary, fullPath, true);
|
||||
}
|
||||
finally { if (File.Exists(temporary)) File.Delete(temporary); }
|
||||
@@ -104,3 +97,7 @@ public sealed class ServerProfileStore(string path)
|
||||
catch (JsonException) { }
|
||||
}
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, WriteIndented = true, UseStringEnumConverter = true)]
|
||||
[JsonSerializable(typeof(ServerProfile[]))]
|
||||
internal sealed partial class ServerProfileJsonContext : JsonSerializerContext;
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"Google.Protobuf": "[3.36.1, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"net10.0/iossimulator-arm64": {}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
"Google.Protobuf": "[3.36.1, )"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"net10.0/iossimulator-arm64": {}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,11 @@ namespace VoiceCat.Dsp;
|
||||
|
||||
public sealed unsafe partial class RnnoiseProcessor : IDisposable
|
||||
{
|
||||
#if VOICECAT_IOS_STATIC
|
||||
private const string NativeLibrary = "__Internal";
|
||||
#else
|
||||
private const string NativeLibrary = "voicecat_media";
|
||||
#endif
|
||||
public const int SampleRate = 48000;
|
||||
public const int FrameSamples = 480;
|
||||
private readonly RnnoiseHandle handle;
|
||||
@@ -37,11 +42,11 @@ public sealed unsafe partial class RnnoiseProcessor : IDisposable
|
||||
|
||||
public void Dispose() => handle.Dispose();
|
||||
|
||||
[LibraryImport("voicecat_media", EntryPoint = "vcm_rnnoise_create")]
|
||||
[LibraryImport(NativeLibrary, EntryPoint = "vcm_rnnoise_create")]
|
||||
private static partial nint Create();
|
||||
[LibraryImport("voicecat_media", EntryPoint = "vcm_rnnoise_destroy")]
|
||||
[LibraryImport(NativeLibrary, EntryPoint = "vcm_rnnoise_destroy")]
|
||||
private static partial void Destroy(nint state);
|
||||
[LibraryImport("voicecat_media", EntryPoint = "vcm_rnnoise_process")]
|
||||
[LibraryImport(NativeLibrary, EntryPoint = "vcm_rnnoise_process")]
|
||||
private static partial float ProcessFrame(RnnoiseHandle state, float* output, float* input);
|
||||
|
||||
private sealed class RnnoiseHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net10.0": {}
|
||||
"net10.0": {},
|
||||
"net10.0/iossimulator-arm64": {}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
"resolved": "2.83.0",
|
||||
"contentHash": "vK2Go/83W0v2Nn7tTP9fGrX4IjmOa93s3M0SZeFimU1vIIr2wL9yNJlIyK21y85SGm3++JncB8IF751cjoLHuQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"net10.0/iossimulator-arm64": {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user