nixpkgs/pkgs/by-name/fa/famistudio/package.nix
2024-12-04 21:14:15 +01:00

172 lines
4.8 KiB
Nix

{
stdenv,
lib,
buildDotnetModule,
dotnetCorePackages,
callPackage,
fetchFromGitHub,
ffmpeg,
glfw,
libglvnd,
libogg,
libvorbis,
openal,
portaudio,
rtmidi,
}:
let
csprojName =
if stdenv.hostPlatform.isLinux then
"FamiStudio.Linux"
else if stdenv.hostPlatform.isDarwin then
"FamiStudio.Mac"
else
throw "Don't know how to build FamiStudio for ${stdenv.hostPlatform.system}";
in
buildDotnetModule rec {
pname = "famistudio";
version = "4.2.1";
src = fetchFromGitHub {
owner = "BleuBleu";
repo = "FamiStudio";
rev = "refs/tags/${version}";
hash = "sha256-WYy/6cWQg3Ayok/eAdnvlWAvdcuhy/sdlWOVvaYcPkc=";
};
postPatch =
let
libname = library: "${library}${stdenv.hostPlatform.extensions.sharedLibrary}";
buildNativeWrapper =
args:
callPackage ./build-native-wrapper.nix (
args
// {
inherit version src;
sourceRoot = "${src.name}/ThirdParty/${args.depname}";
}
);
nativeWrapperToReplaceFormat =
args:
let
libPrefix = lib.optionalString stdenv.hostPlatform.isLinux "lib";
in
{
package = buildNativeWrapper args;
expectedName = "${libPrefix}${args.depname}";
ourName = "${libPrefix}${args.depname}";
};
librariesToReplace =
[
# Unmodified native libraries that we can fully substitute
{
package = glfw;
expectedName = "libglfw";
ourName = "libglfw";
}
{
package = rtmidi;
expectedName = "librtmidi";
ourName = "librtmidi";
}
]
++ lib.optionals stdenv.hostPlatform.isLinux [
{
package = openal;
expectedName = "libopenal32";
ourName = "libopenal";
}
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
{
package = portaudio;
expectedName = "libportaudio.2";
ourName = "libportaudio.2";
}
]
++ [
# Native libraries, with extra code for the C# wrapping
(nativeWrapperToReplaceFormat { depname = "GifDec"; })
(nativeWrapperToReplaceFormat { depname = "NesSndEmu"; })
(nativeWrapperToReplaceFormat {
depname = "NotSoFatso";
extraPostPatch = ''
# C++17 does not allow register storage class specifier
substituteInPlace build.sh \
--replace-fail "$CXX" "$CXX -std=c++14"
'';
})
(nativeWrapperToReplaceFormat { depname = "ShineMp3"; })
(nativeWrapperToReplaceFormat { depname = "Stb"; })
(nativeWrapperToReplaceFormat {
depname = "Vorbis";
buildInputs = [
libogg
libvorbis
];
})
];
libraryReplaceArgs = lib.strings.concatMapStringsSep " " (
library:
"--replace-fail '${libname library.expectedName}' '${lib.getLib library.package}/lib/${libname library.ourName}'"
) librariesToReplace;
in
''
# Don't use any prebuilt libraries
rm FamiStudio/*.{dll,dylib,so*}
# Replace copying of vendored prebuilt native libraries with copying of our native libraries
substituteInPlace ${projectFile} ${libraryReplaceArgs}
# Un-hardcode target platform if set
sed -i -e '/PlatformTarget/d' ${projectFile}
# Don't require a special name to be preserved, our OpenAL isn't 32-bit
substituteInPlace FamiStudio/Source/AudioStreams/OpenALStream.cs \
--replace-fail 'libopenal32' 'libopenal'
'';
projectFile = "FamiStudio/${csprojName}.csproj";
nugetDeps = ./deps.nix;
dotnet-sdk = dotnetCorePackages.sdk_8_0;
dotnet-runtime = dotnetCorePackages.runtime_8_0;
dotnetFlags = [ "-p:TargetFramework=net8.0" ];
runtimeDeps = lib.optionals stdenv.hostPlatform.isLinux [
libglvnd
];
executables = [ "FamiStudio" ];
postInstall = ''
mkdir -p $out/share/famistudio
for datdir in Setup/Demo\ {Instruments,Songs}; do
cp -R "$datdir" $out/share/famistudio/
done
'';
postFixup = ''
# FFMpeg looked up from PATH
wrapProgram $out/bin/FamiStudio \
--prefix PATH : ${lib.makeBinPath [ ffmpeg ]}
'';
passthru.updateScript = ./update.sh;
meta = {
homepage = "https://famistudio.org/";
description = "NES Music Editor";
longDescription = ''
FamiStudio is very simple music editor for the Nintendo Entertainment System
or Famicom. It is targeted at both chiptune artists and NES homebrewers.
'';
license = lib.licenses.mit;
maintainers = with lib.maintainers; [
OPNA2608
];
platforms = lib.platforms.unix;
mainProgram = "FamiStudio";
};
}