nixpkgs/pkgs/applications/audio/famistudio/default.nix
2024-07-26 11:36:49 +02:00

126 lines
4.1 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_7_0;
dotnet-runtime = dotnetCorePackages.runtime_7_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 = with lib; {
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 = licenses.mit;
maintainers = with maintainers; [ OPNA2608 ];
platforms = platforms.unix;
mainProgram = "FamiStudio";
};
}