├── dune-project
├── esy.lock
├── opam
│ ├── seq.base
│ │ ├── files
│ │ │ ├── seq.install
│ │ │ └── META.seq
│ │ └── opam
│ ├── ocamlfind.1.8.1
│ │ ├── files
│ │ │ ├── ocaml-stub
│ │ │ └── ocamlfind.install
│ │ └── opam
│ ├── base-unix.base
│ │ └── opam
│ ├── base-bigarray.base
│ │ └── opam
│ ├── base-threads.base
│ │ └── opam
│ ├── base-bytes.base
│ │ └── opam
│ ├── dune-configurator.1.0.0
│ │ └── opam
│ ├── jbuilder.transition
│ │ └── opam
│ ├── conf-which.1
│ │ └── opam
│ ├── easy-format.1.3.1
│ │ └── opam
│ ├── lwt_react.1.1.3
│ │ └── opam
│ ├── conf-m4.1
│ │ └── opam
│ ├── lwt_log.1.1.1
│ │ └── opam
│ ├── fix.20181206
│ │ └── opam
│ ├── biniou.1.2.0
│ │ └── opam
│ ├── mmap.1.1.0
│ │ └── opam
│ ├── ppx_derivers.1.2.1
│ │ └── opam
│ ├── lwt_ppx.1.2.2
│ │ └── opam
│ ├── result.1.4
│ │ └── opam
│ ├── atdgen-runtime.2.0.0
│ │ └── opam
│ ├── js_of_ocaml-lwt.3.4.0
│ │ └── opam
│ ├── chalk.1.0
│ │ └── opam
│ ├── charInfo_width.1.1.0
│ │ └── opam
│ ├── js_of_ocaml-ppx.3.4.0
│ │ └── opam
│ ├── printbox.0.2
│ │ └── opam
│ ├── junit.2.0.1
│ │ └── opam
│ ├── ppx_tools_versioned.5.2.2
│ │ └── opam
│ ├── color.0.2.0
│ │ └── opam
│ ├── merlin-extend.0.4
│ │ └── opam
│ ├── camomile.1.0.1
│ │ └── opam
│ ├── menhir.20190924
│ │ └── opam
│ ├── atd.2.0.0
│ │ └── opam
│ ├── ocamlbuild.0.14.0
│ │ └── opam
│ ├── fpath.0.7.2
│ │ └── opam
│ ├── gg.0.9.3
│ │ └── opam
│ ├── uchar.0.0.2
│ │ └── opam
│ ├── re.1.9.0
│ │ └── opam
│ ├── react.1.2.1
│ │ └── opam
│ ├── cppo.1.6.6
│ │ └── opam
│ ├── zed.2.0.3
│ │ └── opam
│ ├── yojson.1.7.0
│ │ └── opam
│ ├── lambda-term.2.0.2
│ │ └── opam
│ ├── atdgen.2.0.0
│ │ └── opam
│ ├── ocaml-migrate-parsetree.1.3.1
│ │ └── opam
│ ├── astring.0.8.3
│ │ └── opam
│ ├── uutf.1.0.2
│ │ └── opam
│ ├── tyxml.4.3.0
│ │ └── opam
│ ├── cmdliner.1.0.2
│ │ └── opam
│ ├── ocplib-endian.1.0
│ │ └── opam
│ ├── dune.1.7.3
│ │ └── opam
│ ├── ptime.0.8.5
│ │ └── opam
│ ├── lwt.4.3.1
│ │ └── opam
│ ├── topkg.1.0.1
│ │ └── opam
│ └── merlin.3.2.2
│ │ └── opam
├── .gitignore
├── .gitattributes
└── overrides
│ ├── opam__s__dune_opam__c__1.7.3_opam_override
│ └── package.json
│ ├── opam__s__ocplib_endian_opam__c__1.0_opam_override
│ ├── files
│ │ ├── esy-fix.patch
│ │ └── ocplib-endian-0.8.patch
│ └── package.json
│ ├── opam__s__ocamlbuild_opam__c__0.14.0_opam_override
│ ├── package.json
│ └── files
│ │ └── ocamlbuild-0.14.0.patch
│ └── opam__s__ocamlfind_opam__c__1.8.1_opam_override
│ ├── package.json
│ └── files
│ └── findlib-1.8.1.patch
├── assets
├── icon.icns
├── digital-7.ttf
├── knob-inner.png
├── knob-outer.png
├── knob-outer2.png
├── Roboto-Regular.ttf
├── ASSETS.md
└── dune
├── Settings.re
├── .ci
├── use-node.yml
├── esy-build-steps.yml
├── publish-build-cache.yml
└── restore-build-cache.yml
├── App.opam
├── dune
├── App.re
├── Osc.re
├── Bitcrusher.re
├── Delay.re
├── Filter.re
├── TrackButton.re
├── .gitignore
├── PlayButton.re
├── package.json
├── Step.re
├── TempoControl.re
├── Envelope.re
├── TrackFx.re
├── SequencerPanel.re
├── MainUI.re
├── Audio.re
├── Knob.re
├── AppState.re
└── MasterFx.re
/dune-project:
--------------------------------------------------------------------------------
1 | (lang dune 1.1)
2 |
--------------------------------------------------------------------------------
/esy.lock/opam/seq.base/files/seq.install:
--------------------------------------------------------------------------------
1 | lib:[
2 | "META.seq" {"META"}
3 | ]
4 |
--------------------------------------------------------------------------------
/assets/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenwheeler/camlsynth/HEAD/assets/icon.icns
--------------------------------------------------------------------------------
/Settings.re:
--------------------------------------------------------------------------------
1 | let bufferSize = 1024;
2 | let sampleRate = 44100.;
3 | let sample = 1. /. sampleRate;
--------------------------------------------------------------------------------
/assets/digital-7.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenwheeler/camlsynth/HEAD/assets/digital-7.ttf
--------------------------------------------------------------------------------
/assets/knob-inner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenwheeler/camlsynth/HEAD/assets/knob-inner.png
--------------------------------------------------------------------------------
/assets/knob-outer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenwheeler/camlsynth/HEAD/assets/knob-outer.png
--------------------------------------------------------------------------------
/assets/knob-outer2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenwheeler/camlsynth/HEAD/assets/knob-outer2.png
--------------------------------------------------------------------------------
/assets/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kenwheeler/camlsynth/HEAD/assets/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/esy.lock/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Reset any possible .gitignore, we want all esy.lock to be un-ignored.
3 | !*
4 |
--------------------------------------------------------------------------------
/esy.lock/.gitattributes:
--------------------------------------------------------------------------------
1 |
2 | # Set eol to LF so files aren't converted to CRLF-eol on Windows.
3 | * text eol=lf
4 |
--------------------------------------------------------------------------------
/.ci/use-node.yml:
--------------------------------------------------------------------------------
1 | steps:
2 | - task: NodeTool@0
3 | displayName: 'Use Node 8.x'
4 | inputs:
5 | versionSpec: 8.x
6 |
--------------------------------------------------------------------------------
/App.opam:
--------------------------------------------------------------------------------
1 | opam-version: "1.2"
2 | version: "dev"
3 | maintainer: "bryphe@outlook.com"
4 | author: ["Bryan Phelps"]
5 | build: [
6 |
7 | ]
8 |
--------------------------------------------------------------------------------
/esy.lock/opam/ocamlfind.1.8.1/files/ocaml-stub:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | BINDIR=$(dirname "$(command -v ocamlc)")
4 | "$BINDIR/ocaml" -I "$OCAML_TOPLEVEL_PATH" "$@"
5 |
--------------------------------------------------------------------------------
/assets/ASSETS.md:
--------------------------------------------------------------------------------
1 | Knob asset is from Osmic at opengameart.org, licensed under CC-BY 3.0:
2 |
3 |
4 | https://opengameart.org/content/audio-knobs-button-sliders-etc
5 |
6 |
7 |
--------------------------------------------------------------------------------
/assets/dune:
--------------------------------------------------------------------------------
1 | (install
2 | (section bin)
3 | (package App)
4 | (files Roboto-Regular.ttf digital-7.ttf icon.icns knob-inner.png knob-outer.png knob-outer2.png))
5 |
--------------------------------------------------------------------------------
/esy.lock/opam/seq.base/files/META.seq:
--------------------------------------------------------------------------------
1 | name="seq"
2 | version="[distributed with OCaml 4.07 or above]"
3 | description="dummy backward-compatibility package for iterators"
4 | requires=""
5 |
--------------------------------------------------------------------------------
/esy.lock/opam/base-unix.base/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "https://github.com/ocaml/opam-repository/issues"
3 | description: """
4 | Unix library distributed with the OCaml compiler
5 | """
6 |
7 |
--------------------------------------------------------------------------------
/esy.lock/opam/base-bigarray.base/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "https://github.com/ocaml/opam-repository/issues"
3 | description: """
4 | Bigarray library distributed with the OCaml compiler
5 | """
6 |
7 |
--------------------------------------------------------------------------------
/esy.lock/opam/base-threads.base/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "https://github.com/ocaml/opam-repository/issues"
3 | description: """
4 | Threads library distributed with the OCaml compiler
5 | """
6 |
7 |
--------------------------------------------------------------------------------
/esy.lock/opam/ocamlfind.1.8.1/files/ocamlfind.install:
--------------------------------------------------------------------------------
1 | bin: [
2 | "src/findlib/ocamlfind" {"ocamlfind"}
3 | "?src/findlib/ocamlfind_opt" {"ocamlfind"}
4 | "?tools/safe_camlp4"
5 | ]
6 | toplevel: ["src/findlib/topfind"]
7 |
--------------------------------------------------------------------------------
/dune:
--------------------------------------------------------------------------------
1 | (executable
2 | (name App)
3 | (package App)
4 | (public_name App)
5 | (libraries
6 | bigarray
7 | reglfw
8 | Revery
9 | portaudio
10 | threads.posix
11 | ))
12 |
--------------------------------------------------------------------------------
/esy.lock/opam/base-bytes.base/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: " "
3 | authors: " "
4 | homepage: " "
5 | depends: [
6 | "ocaml" {>= "4.02.0"}
7 | "ocamlfind" {>= "1.5.3"}
8 | ]
9 | synopsis: "Bytes library distributed with the OCaml compiler"
10 |
--------------------------------------------------------------------------------
/esy.lock/overrides/opam__s__dune_opam__c__1.7.3_opam_override/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "build": [
3 | [
4 | "ocaml",
5 | "bootstrap.ml"
6 | ],
7 | [
8 | "./boot.exe",
9 | "--release",
10 | "-j",
11 | "4"
12 | ]
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/esy.lock/opam/dune-configurator.1.0.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | authors: ["Jérémie Dimino"]
3 | homepage: "https://github.com/ocaml/dune"
4 | bug-reports: "https://github.com/ocaml/dune/issues"
5 | maintainer: "Jérémie Dimino"
6 | description: """
7 | dune.configurator library distributed with Dune 1.x
8 | """
9 | depends: ["dune" {<"2.0.0"}]
10 |
--------------------------------------------------------------------------------
/.ci/esy-build-steps.yml:
--------------------------------------------------------------------------------
1 | # Cross-platform set of build steps for building esy projects
2 |
3 | steps:
4 | - script: npm install -g esy@0.5.8
5 | displayName: 'npm install -g esy@0.5.8'
6 | - script: esy install
7 | displayName: 'esy install'
8 | - script: esy build
9 | displayName: 'esy build'
10 | # Run tests or any additional steps here
11 | # - script: esy b dune runtest
12 |
--------------------------------------------------------------------------------
/esy.lock/overrides/opam__s__ocplib_endian_opam__c__1.0_opam_override/files/esy-fix.patch:
--------------------------------------------------------------------------------
1 | --- ./setup.ml
2 | +++ ./setup.ml
3 | @@ -6331,9 +6331,7 @@
4 | [
5 | "-classic-display";
6 | "-no-log";
7 | - "-no-links";
8 | - "-install-lib-dir";
9 | - (Filename.concat (standard_library ()) "ocamlbuild")
10 | + "-no-links"
11 | ]
12 | else
13 | [];
14 |
--------------------------------------------------------------------------------
/esy.lock/opam/seq.base/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: " "
3 | authors: " "
4 | homepage: " "
5 | depends: [
6 | "ocaml" {>= "4.07.0"}
7 | ]
8 | dev-repo: "git+https://github.com/ocaml/ocaml.git"
9 | bug-reports: "https://caml.inria.fr/mantis/main_page.php"
10 | synopsis:
11 | "Compatibility package for OCaml's standard iterator type starting from 4.07."
12 | extra-files: [
13 | ["seq.install" "md5=026b31e1df290373198373d5aaa26e42"]
14 | ["META.seq" "md5=b33c8a1a6c7ed797816ce27df4855107"]
15 | ]
16 |
--------------------------------------------------------------------------------
/App.re:
--------------------------------------------------------------------------------
1 | open Revery;
2 | open Revery.Math;
3 | open Revery.UI;
4 | open Revery.UI.Components;
5 | open Step;
6 | let init = app => {
7 | let win =
8 | App.createWindow(
9 | app,
10 | "Reason Composer ML-808",
11 | ~createOptions={
12 | ...WindowCreateOptions.default,
13 | resizable: false,
14 | width: 800,
15 | height: 475,
16 | backgroundColor: Color.hex("#25231E"),
17 | },
18 | );
19 |
20 | let element = ;
21 |
22 | let _ = UI.start(win, element);
23 | ();
24 | };
25 |
26 | App.start(init);
--------------------------------------------------------------------------------
/esy.lock/opam/jbuilder.transition/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "opensource@janestreet.com"
3 | authors: ["Jane Street Group, LLC "]
4 | homepage: "https://github.com/ocaml/dune"
5 | bug-reports: "https://github.com/ocaml/dune/issues"
6 | dev-repo: "git+https://github.com/ocaml/dune.git"
7 | license: "MIT"
8 | depends: ["ocaml" "dune"]
9 | post-messages: [
10 | "Jbuilder has been renamed and the jbuilder package is now a transition \
11 | package. Use the dune package instead."
12 | ]
13 | synopsis:
14 | "This is a transition package, jbuilder is now named dune. Use the dune"
15 | description: "package instead."
16 |
--------------------------------------------------------------------------------
/Osc.re:
--------------------------------------------------------------------------------
1 | open Settings;
2 |
3 | type osc = {
4 | .
5 | freq: float,
6 | gain: float,
7 | getData: float => float,
8 | };
9 |
10 | type wave =
11 | | Sine
12 | | Saw
13 | | Square
14 | | Noise;
15 |
16 | let getData = (mode: wave, freq: float, gain: float, mtime: float) => {
17 | let fpt = 1. /. freq; /* full period time */
18 | let hpt = fpt /. 2.; /* half period time */
19 | let lt = mod_float(mtime, fpt); /* local time */
20 | let doublePi = Float.pi *. 2.;
21 |
22 | switch (mode) {
23 | | Sine => sin(2. *. doublePi *. freq *. mtime) *. gain
24 | | Square => (lt < hpt ? 1.0 : (-1.0)) *. gain
25 | | Saw => (lt /. fpt *. 2. -. 1.0) *. gain
26 | | Noise => 1. -. Random.float(2.) *. gain
27 | };
28 | };
--------------------------------------------------------------------------------
/esy.lock/opam/conf-which.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "unixjunkie@sdf.org"
3 | homepage: "http://www.gnu.org/software/which/"
4 | authors: "Carlo Wood"
5 | bug-reports: "https://github.com/ocaml/opam-repository/issues"
6 | license: "GPL-2.0-or-later"
7 | build: [["which" "which"]]
8 | depexts: [
9 | ["which"] {os-distribution = "centos"}
10 | ["which"] {os-distribution = "fedora"}
11 | ["which"] {os-family = "suse"}
12 | ["debianutils"] {os-family = "debian"}
13 | ["which"] {os-distribution = "nixos"}
14 | ["which"] {os-distribution = "arch"}
15 | ]
16 | synopsis: "Virtual package relying on which"
17 | description:
18 | "This package can only install if the which program is installed on the system."
19 | flags: conf
20 |
--------------------------------------------------------------------------------
/esy.lock/overrides/opam__s__ocplib_endian_opam__c__1.0_opam_override/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "build": [
3 | [
4 | "bash",
5 | "-c",
6 | "#{os == 'windows' ? 'patch -p1 < ocplib-endian-0.8.patch' : 'true'}"
7 | ],
8 | [
9 | "bash",
10 | "-c",
11 | "#{os == 'windows' ? 'patch -p1 < esy-fix.patch' : 'true'}"
12 | ],
13 | [
14 | "ocaml",
15 | "setup.ml",
16 | "-configure",
17 | "--disable-debug",
18 | "--prefix",
19 | "#{self.install}"
20 | ],
21 | [
22 | "ocaml",
23 | "setup.ml",
24 | "-build"
25 | ]
26 | ],
27 | "install": [
28 | [
29 | "ocaml",
30 | "setup.ml",
31 | "-install"
32 | ]
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/esy.lock/opam/easy-format.1.3.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "martin@mjambon.com"
3 | authors: ["Martin Jambon"]
4 | homepage: "http://mjambon.com/easy-format.html"
5 | bug-reports: "https://github.com/mjambon/easy-format/issues"
6 | dev-repo: "git+https://github.com/mjambon/easy-format.git"
7 | build: [
8 | ["jbuilder" "build" "-p" name "-j" jobs]
9 | ["jbuilder" "runtest" "-p" name] {with-test}
10 | ]
11 | depends: [
12 | "ocaml" {>= "4.02.3"}
13 | "jbuilder" {build}
14 | ]
15 | synopsis:
16 | "High-level and functional interface to the Format module of the OCaml standard library"
17 | url {
18 | src: "https://github.com/mjambon/easy-format/archive/v1.3.1.tar.gz"
19 | checksum: "md5=4e163700fb88fdcd6b8976c3a216c8ea"
20 | }
21 |
--------------------------------------------------------------------------------
/esy.lock/overrides/opam__s__ocamlbuild_opam__c__0.14.0_opam_override/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "build": [
3 | [
4 | "bash",
5 | "-c",
6 | "#{os == 'windows' ? 'patch -p1 < ocamlbuild-0.14.0.patch' : 'true'}"
7 | ],
8 | [
9 | "make",
10 | "-f",
11 | "configure.make",
12 | "all",
13 | "OCAMLBUILD_PREFIX=#{self.install}",
14 | "OCAMLBUILD_BINDIR=#{self.bin}",
15 | "OCAMLBUILD_LIBDIR=#{self.lib}",
16 | "OCAMLBUILD_MANDIR=#{self.man}",
17 | "OCAMLBUILD_NATIVE=true",
18 | "OCAMLBUILD_NATIVE_TOOLS=true"
19 | ],
20 | [
21 | "make",
22 | "check-if-preinstalled",
23 | "all",
24 | "#{os == 'windows' ? 'install' : 'opam-install'}"
25 | ]
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/esy.lock/opam/lwt_react.1.1.3/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 |
3 | synopsis: "Helpers for using React with Lwt"
4 |
5 | version: "1.1.3"
6 | license: "MIT"
7 | homepage: "https://github.com/ocsigen/lwt"
8 | doc: "https://ocsigen.org/lwt/api/Lwt_react"
9 | bug-reports: "https://github.com/ocsigen/lwt/issues"
10 |
11 | authors: [
12 | "Jérémie Dimino"
13 | ]
14 | maintainer: [
15 | "Anton Bachin "
16 | ]
17 | dev-repo: "git+https://github.com/ocsigen/lwt.git"
18 |
19 | depends: [
20 | "dune"
21 | "lwt" {>= "3.0.0"}
22 | "ocaml"
23 | "react" {>= "1.0.0"}
24 | ]
25 |
26 | build: [
27 | ["dune" "build" "-p" name "-j" jobs]
28 | ]
29 |
30 | url {
31 | src: "https://github.com/ocsigen/lwt/archive/4.3.0.tar.gz"
32 | checksum: "md5=1a72b5ae4245707c12656632a25fc18c"
33 | }
34 |
--------------------------------------------------------------------------------
/esy.lock/opam/conf-m4.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "tim@gfxmonk.net"
3 | homepage: "http://www.gnu.org/software/m4/m4.html"
4 | bug-reports: "https://github.com/ocaml/opam-repository/issues"
5 | authors: "GNU Project"
6 | license: "GPL-3.0-only"
7 | build: [["sh" "-exc" "echo | m4"]]
8 | depexts: [
9 | ["m4"] {os-family = "debian"}
10 | ["m4"] {os-distribution = "fedora"}
11 | ["m4"] {os-distribution = "rhel"}
12 | ["m4"] {os-distribution = "centos"}
13 | ["m4"] {os-distribution = "alpine"}
14 | ["m4"] {os-distribution = "nixos"}
15 | ["m4"] {os-family = "suse"}
16 | ["m4"] {os-distribution = "ol"}
17 | ["m4"] {os-distribution = "arch"}
18 | ]
19 | synopsis: "Virtual package relying on m4"
20 | description:
21 | "This package can only install if the m4 binary is installed on the system."
22 | flags: conf
23 |
--------------------------------------------------------------------------------
/esy.lock/opam/lwt_log.1.1.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 |
3 | synopsis: "Lwt logging library (deprecated)"
4 |
5 | version: "1.1.1"
6 | license: "LGPL-2.0-or-later"
7 | homepage: "https://github.com/ocsigen/lwt_log"
8 | doc: "https://github.com/ocsigen/lwt_log/blob/master/src/core/lwt_log_core.mli"
9 | bug-reports: "https://github.com/ocsigen/lwt_log/issues"
10 |
11 | authors: [
12 | "Shawn Wagner"
13 | "Jérémie Dimino"
14 | ]
15 | maintainer: "Anton Bachin "
16 | dev-repo: "git+https://github.com/ocsigen/lwt_log.git"
17 |
18 | depends: [
19 | "dune" {>= "1.0"}
20 | "lwt" {>= "4.0.0"}
21 | ]
22 |
23 | build: [
24 | ["dune" "build" "-p" name "-j" jobs]
25 | ]
26 |
27 | url {
28 | src: "https://github.com/aantron/lwt_log/archive/1.1.1.tar.gz"
29 | checksum: "md5=02e93be62288037870ae5b1ce099fe59"
30 | }
31 |
--------------------------------------------------------------------------------
/esy.lock/opam/fix.20181206/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "francois.pottier@inria.fr"
3 | authors: [
4 | "François Pottier "
5 | ]
6 | homepage: "https://gitlab.inria.fr/fpottier/fix"
7 | dev-repo: "git+https://gitlab.inria.fr/fpottier/fix.git"
8 | bug-reports: "francois.pottier@inria.fr"
9 | build: [
10 | ["dune" "build" "-p" name "-j" jobs]
11 | ]
12 | depends: [
13 | "ocaml" { >= "4.03" }
14 | "dune"
15 | ]
16 | synopsis: "Facilities for memoization and fixed points"
17 | url {
18 | src:
19 | "https://gitlab.inria.fr/fpottier/fix/repository/20181206/archive.tar.gz"
20 | checksum: [
21 | "md5=ae129ed3822149a7f8c98f975512e534"
22 | "sha512=1db240ff0a87200979bf4308e2110a37631f280e36c5f53dde767579ca63992a760eaeb6e1fc9a41c3f3a63d3dc29a3361114ad304cb09e83945ab4213ff5f6d"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/esy.lock/opam/biniou.1.2.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "martin@mjambon.com"
3 | authors: ["Martin Jambon"]
4 |
5 | homepage: "https://github.com/mjambon/biniou"
6 | bug-reports: "https://github.com/mjambon/biniou/issues"
7 | dev-repo: "git+https://github.com/mjambon/biniou.git"
8 | license: "BSD-3-Clause"
9 |
10 | build: [
11 | ["jbuilder" "build" "-p" name "-j" jobs]
12 | ["jbuilder" "runtest" "-p" name] {with-test}
13 | ]
14 | depends: [
15 | "ocaml" {>= "4.02.3"}
16 | "conf-which" {build}
17 | "jbuilder" {build & >= "1.0+beta7"}
18 | "easy-format"
19 | ]
20 | synopsis:
21 | "Binary data format designed for speed, safety, ease of use and backward compatibility as protocols evolve"
22 | url {
23 | src: "https://github.com/mjambon/biniou/archive/v1.2.0.tar.gz"
24 | checksum: "md5=f3e92358e832ed94eaf23ce622ccc2f9"
25 | }
26 |
--------------------------------------------------------------------------------
/esy.lock/opam/mmap.1.1.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "jeremie@dimino.org"
3 | authors: ["Jérémie Dimino " "Anton Bachin" ]
4 | homepage: "https://github.com/mirage/mmap"
5 | bug-reports: "https://github.com/mirage/mmap/issues"
6 | doc: "https://mirage.github.io/mmap/"
7 | dev-repo: "git+https://github.com/mirage/mmap.git"
8 | license: "LGPL-2.1-only with OCaml-LGPL-linking-exception"
9 | build: [
10 | ["dune" "build" "-p" name "-j" jobs]
11 | ]
12 | depends: [
13 | "ocaml"
14 | "dune" {>= "1.6"}
15 | ]
16 | synopsis: "File mapping functionality"
17 | description: """
18 | This project provides a Mmap.map_file functions for mapping files in memory.
19 | """
20 | url {
21 | src:
22 | "https://github.com/mirage/mmap/releases/download/v1.1.0/mmap-v1.1.0.tbz"
23 | checksum: "md5=8c5d5fbc537296dc525867535fb878ba"
24 | }
25 |
--------------------------------------------------------------------------------
/esy.lock/opam/ppx_derivers.1.2.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "jeremie@dimino.org"
3 | authors: ["Jérémie Dimino"]
4 | license: "BSD-3-Clause"
5 | homepage: "https://github.com/ocaml-ppx/ppx_derivers"
6 | bug-reports: "https://github.com/ocaml-ppx/ppx_derivers/issues"
7 | dev-repo: "git://github.com/ocaml-ppx/ppx_derivers.git"
8 | build: [
9 | ["dune" "build" "-p" name "-j" jobs]
10 | ]
11 | depends: [
12 | "ocaml"
13 | "dune"
14 | ]
15 | synopsis: "Shared [@@deriving] plugin registry"
16 | description: """
17 | Ppx_derivers is a tiny package whose sole purpose is to allow
18 | ppx_deriving and ppx_type_conv to inter-operate gracefully when linked
19 | as part of the same ocaml-migrate-parsetree driver."""
20 | url {
21 | src: "https://github.com/ocaml-ppx/ppx_derivers/archive/1.2.1.tar.gz"
22 | checksum: "md5=5dc2bf130c1db3c731fe0fffc5648b41"
23 | }
24 |
--------------------------------------------------------------------------------
/esy.lock/opam/lwt_ppx.1.2.2/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 |
3 | synopsis: "PPX syntax for Lwt, providing something similar to async/await from JavaScript"
4 |
5 | license: "MIT"
6 | homepage: "https://github.com/ocsigen/lwt"
7 | doc: "https://ocsigen.org/lwt/api/Ppx_lwt"
8 | bug-reports: "https://github.com/ocsigen/lwt/issues"
9 |
10 | authors: [
11 | "Gabriel Radanne"
12 | ]
13 | maintainer: [
14 | "Anton Bachin "
15 | ]
16 | dev-repo: "git+https://github.com/ocsigen/lwt.git"
17 |
18 | depends: [
19 | "dune"
20 | "lwt"
21 | "ocaml" {>= "4.02.0"}
22 | "ocaml-migrate-parsetree"
23 | "ppx_tools_versioned" {>= "5.0.1"}
24 | ]
25 |
26 | build: [
27 | ["dune" "build" "-p" name "-j" jobs]
28 | ]
29 |
30 | url {
31 | src: "https://github.com/ocsigen/lwt/archive/4.2.0.tar.gz"
32 | checksum: "md5=2ce7827948adc611319f9449e4519070"
33 | }
34 |
--------------------------------------------------------------------------------
/esy.lock/opam/result.1.4/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "opensource@janestreet.com"
3 | authors: ["Jane Street Group, LLC "]
4 | homepage: "https://github.com/janestreet/result"
5 | dev-repo: "git+https://github.com/janestreet/result.git"
6 | bug-reports: "https://github.com/janestreet/result/issues"
7 | license: "BSD-3-Clause"
8 | build: [["dune" "build" "-p" name "-j" jobs]]
9 | depends: [
10 | "ocaml"
11 | "dune" {>= "1.0"}
12 | ]
13 | synopsis: "Compatibility Result module"
14 | description: """
15 | Projects that want to use the new result type defined in OCaml >= 4.03
16 | while staying compatible with older version of OCaml should use the
17 | Result module defined in this library."""
18 | url {
19 | src:
20 | "https://github.com/janestreet/result/archive/1.4.tar.gz"
21 | checksum: "md5=d3162dbc501a2af65c8c71e0866541da"
22 | }
23 |
--------------------------------------------------------------------------------
/esy.lock/opam/atdgen-runtime.2.0.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "martin@mjambon.com"
3 | authors: ["Martin Jambon"]
4 |
5 | homepage: "https://github.com/mjambon/atd"
6 | bug-reports: "https://github.com/mjambon/atd/issues"
7 | dev-repo: "git://github.com/mjambon/atd.git"
8 |
9 | build: [
10 | ["jbuilder" "subst" "-p" name] {pinned}
11 | ["jbuilder" "build" "-p" name "-j" jobs]
12 | ]
13 |
14 | # Restore when https://github.com/mjambon/atd/issues/121 is resolved.
15 | # build-test: [
16 | # ["jbuilder" "runtest" "-p" name]
17 | # ]
18 |
19 | depends: [
20 | "ocaml" {>= "4.02.3"}
21 | "jbuilder" {build}
22 | "biniou" {>= "1.0.6"}
23 | "yojson" {>= "1.2.1"}
24 | ]
25 | synopsis: "Runtime library for code generated by atdgen."
26 | url {
27 | src: "https://github.com/mjambon/atd/releases/download/2.0.0/atd-2.0.0.tbz"
28 | checksum: "md5=14e47609397c524ea0eae7c3f14f7ccf"
29 | }
30 |
--------------------------------------------------------------------------------
/esy.lock/opam/js_of_ocaml-lwt.3.4.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "dev@ocsigen.org"
3 | authors: "Ocsigen team"
4 | bug-reports: "https://github.com/ocsigen/js_of_ocaml/issues"
5 | homepage: "http://ocsigen.org/js_of_ocaml"
6 | dev-repo: "git+https://github.com/ocsigen/js_of_ocaml.git"
7 | synopsis: "Compiler from OCaml bytecode to Javascript"
8 | description: """
9 | Js_of_ocaml is a compiler from OCaml bytecode to JavaScript.
10 | It makes it possible to run pure OCaml programs in JavaScript
11 | environment like browsers and Node.js
12 | """
13 |
14 | build: [["dune" "build" "-p" name "-j" jobs]]
15 |
16 | depends: [
17 | "ocaml" {>= "4.02.0"}
18 | "dune" {>= "1.2"}
19 | "lwt" {>= "2.4.4"}
20 | "js_of_ocaml" {>= "3.2"}
21 | "js_of_ocaml-ppx"
22 | ]
23 | depopts: [ "graphics" "lwt_log" ]
24 |
25 | url {
26 | src: "https://github.com/ocsigen/js_of_ocaml/archive/3.4.0.tar.gz"
27 | checksum: "md5=42f914d0410787d65668d2822fdab1a1"
28 | }
29 |
--------------------------------------------------------------------------------
/esy.lock/opam/chalk.1.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Nick Zuber "
3 | authors: "Nick Zuber "
4 | homepage: "https://github.com/nickzuber/chalk"
5 | bug-reports: "https://github.com/nickzuber/chalk/issues"
6 | license: "MIT"
7 | dev-repo: "git+ssh://git@github.com/nickzuber/chalk.git"
8 | build: [make "build"]
9 | install: [make "build"]
10 | remove: ["ocamlfind" "remove" "chalk"]
11 | depends: ["ocaml" "ocamlfind"]
12 | synopsis: "Composable and simple terminal highlighting package"
13 | description: """
14 | Composable and simple terminal highlighting package. Very simple API;
15 | and example usage could be as follows:
16 |
17 | ```ocaml
18 | let some_string = "Hello world!"
19 | |> Chalk.red
20 | |> Chalk.bold
21 | |> Chalk.underline
22 | ```"""
23 | flags: light-uninstall
24 | url {
25 | src: "https://github.com/nickzuber/chalk/archive/v1.0.tar.gz"
26 | checksum: "md5=c685f3024e5a4e74c86b4d9ce67ae34f"
27 | }
28 |
--------------------------------------------------------------------------------
/esy.lock/opam/charInfo_width.1.1.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "zandoye@gmail.com"
3 | authors: [ "ZAN DoYe" ]
4 | homepage: "https://bitbucket.org/zandoye/charinfo_width/"
5 | bug-reports: "https://bitbucket.org/zandoye/charinfo_width/issues"
6 | license: "MIT"
7 | dev-repo: "hg+https://bitbucket.org/zandoye/charinfo_width"
8 | build: [
9 | ["dune" "build" "-p" name "-j" jobs]
10 | ["dune" "runtest" "-p" name "-j" jobs] {with-test & (ocaml:version >= "4.04.0")}
11 | ]
12 | depends: [
13 | "ocaml" {>= "4.02.3"}
14 | "result"
15 | "camomile" {>= "1.0.0" & < "2.0~"}
16 | "dune"
17 | "ppx_expect" {with-test & < "v0.13"}
18 | ]
19 |
20 | synopsis: "Determine column width for a character"
21 | description: """
22 | This module is implemented purely in OCaml and the width function follows the prototype of POSIX's wcwidth."""
23 |
24 | url {
25 | src:"https://bitbucket.org/zandoye/charinfo_width/get/1.1.0.tar.gz"
26 | checksum: "md5=c4ab038e06f06a29692c05fdd7c268c5"
27 | }
28 |
--------------------------------------------------------------------------------
/Bitcrusher.re:
--------------------------------------------------------------------------------
1 | open Settings;
2 |
3 | type bitcrusher = {
4 | mutable bitDepth: float,
5 | mutable downSampling: int,
6 | mutable lastSample: float,
7 | mutable counter: int,
8 | };
9 |
10 | let create = (bitDepth, downSampling) => {
11 | bitDepth,
12 | downSampling,
13 | lastSample: 0.,
14 | counter: 0,
15 | };
16 |
17 | let bitcrush = (v, bitDepth) => {
18 | let bd = bitDepth -. 1.;
19 | let i = ref(floor(v *. (-2.) ** bd *. (-1.)));
20 | if (v >= 1.0) {
21 | i := 2. ** bd -. 1.;
22 | } else if (v <= (-1.0)) {
23 | i := (-2.) ** bd;
24 | };
25 |
26 | let out = i^ /. (-2.) ** bd *. (-1.);
27 | out;
28 | };
29 |
30 | let process = (b: bitcrusher, input: float) => {
31 | b.counter = b.counter + 1;
32 | let out = ref(0.);
33 | if (b.counter < b.downSampling) {
34 | out := b.lastSample;
35 | } else {
36 | b.counter = 0;
37 | let sample = bitcrush(input, b.bitDepth);
38 | b.lastSample = sample;
39 | out := sample;
40 | };
41 |
42 | out^;
43 | };
--------------------------------------------------------------------------------
/esy.lock/opam/js_of_ocaml-ppx.3.4.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "dev@ocsigen.org"
3 | authors: "Ocsigen team"
4 | bug-reports: "https://github.com/ocsigen/js_of_ocaml/issues"
5 | homepage: "http://ocsigen.org/js_of_ocaml"
6 | dev-repo: "git+https://github.com/ocsigen/js_of_ocaml.git"
7 | synopsis: "Compiler from OCaml bytecode to Javascript"
8 | description: """
9 | Js_of_ocaml is a compiler from OCaml bytecode to JavaScript.
10 | It makes it possible to run pure OCaml programs in JavaScript
11 | environment like browsers and Node.js
12 | """
13 |
14 | build: [["dune" "build" "-p" name "-j" jobs]]
15 |
16 | depends: [
17 | "ocaml" {>= "4.02.0"}
18 | "dune" {>= "1.2"}
19 | "ocaml-migrate-parsetree"
20 | "ppx_tools_versioned"
21 | "js_of_ocaml" {>= "3.0"}
22 | ]
23 | conflicts: [
24 | "ppx_tools_versioned" {<="5.0beta0"}
25 | ]
26 |
27 | url {
28 | src: "https://github.com/ocsigen/js_of_ocaml/archive/3.4.0.tar.gz"
29 | checksum: "md5=42f914d0410787d65668d2822fdab1a1"
30 | }
31 |
--------------------------------------------------------------------------------
/esy.lock/opam/printbox.0.2/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | synopsis:
3 | "Allows to print nested boxes, lists, arrays, tables in several formats"
4 | maintainer: "simon.cruanes.2007@m4x.org"
5 | authors: ["Simon Cruanes" "Guillaume Bury"]
6 | tags: ["print" "box" "table" "tree"]
7 | homepage: "https://github.com/c-cube/printbox/"
8 | bug-reports: "https://github.com/c-cube/printbox/issues/"
9 | depends: [
10 | "dune"
11 | "base-bytes"
12 | "odoc" {with-doc}
13 | "ocaml" {>= "4.03"}
14 | "mdx" {with-test}
15 | ]
16 | depopts: ["tyxml"]
17 | build: [
18 | ["dune" "build" "@install" "-p" name "-j" jobs]
19 | ["dune" "runtest" "-p" name "-j" jobs] {with-test}
20 | ["dune" "build" "@doc" "-p" name "-j" jobs] {with-doc}
21 | ]
22 | dev-repo: "git+https://github.com/c-cube/printbox.git"
23 | url {
24 | src: "https://github.com/c-cube/printbox/archive/0.2.tar.gz"
25 | checksum: [
26 | "md5=d84584a8ebdf3faa7b04704f0f75813c"
27 | "sha512=fa49c037c7b1aad720a9a4e74fa40838bade84572afb7bcb6dae170c2d4cbdc9c217868ee971049da18dda0308357bbbc8a934436d32f41418eceba612d56ab3"
28 | ]
29 | }
--------------------------------------------------------------------------------
/esy.lock/opam/junit.2.0.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Louis Roché "
3 | authors: "Louis Roché "
4 | homepage: "https://github.com/Khady/ocaml-junit"
5 | bug-reports: "https://github.com/Khady/ocaml-junit/issues"
6 | license: "LGPL-3.0-or-later with OCaml-LGPL-linking-exception"
7 | dev-repo: "git+https://github.com/Khady/ocaml-junit.git"
8 | doc: "https://khady.github.io/ocaml-junit/"
9 | tags: ["junit" "jenkins"]
10 | depends: [
11 | "dune" {>= "1.0"}
12 | "ptime"
13 | "tyxml" {>= "4.0.0"}
14 | "odoc" {with-doc & >= "1.1.1"}
15 | ]
16 | build: [
17 | ["dune" "subst"] {pinned}
18 | ["dune" "build" "-p" name "-j" jobs]
19 | ["dune" "runtest" "-p" name "-j" jobs] {with-test}
20 | ["dune" "build" "-p" name "-j" jobs] {with-doc}
21 | ]
22 | name: "junit"
23 | synopsis: "JUnit XML reports generation library"
24 | description: "JUnit XML reports generation library"
25 | url {
26 | src:
27 | "https://github.com/Khady/ocaml-junit/releases/download/2.0.1/junit-2.0.1.tbz"
28 | checksum: "md5=40224fb3d4f5e47dc5ff4605587d383b"
29 | }
30 |
--------------------------------------------------------------------------------
/esy.lock/opam/ppx_tools_versioned.5.2.2/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "frederic.bour@lakaban.net"
3 | authors: [
4 | "Frédéric Bour "
5 | "Alain Frisch "
6 | ]
7 | license: "MIT"
8 | homepage: "https://github.com/ocaml-ppx/ppx_tools_versioned"
9 | bug-reports: "https://github.com/ocaml-ppx/ppx_tools_versioned/issues"
10 | dev-repo: "git://github.com/ocaml-ppx/ppx_tools_versioned.git"
11 | tags: [ "syntax" ]
12 | build: [
13 | ["dune" "subst"] {pinned}
14 | ["dune" "build" "-p" name "-j" jobs]
15 | ["dune" "runtest" "-p" name "-j" jobs] {with-test}
16 | ]
17 | depends: [
18 | "ocaml" {>= "4.02.0"}
19 | "dune" {>= "1.0"}
20 | "ocaml-migrate-parsetree" {>= "1.0.10"}
21 | ]
22 | synopsis: "A variant of ppx_tools based on ocaml-migrate-parsetree"
23 | url {
24 | src:
25 | "https://github.com/ocaml-ppx/ppx_tools_versioned/archive/5.2.2.tar.gz"
26 | checksum: [
27 | "md5=f78a3c2b4cc3b92702e1f7096a6125fa"
28 | "sha512=68c168ebc01af46fe8766ad7e36cc778caabb97d8eb303db284d106450cb79974c2a640ce459e197630b9e84b02caa24b59c97c9a8d39ddadc7efc7284e42a70"
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/esy.lock/opam/color.0.2.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | name: "color"
3 | maintainer: "anuragsoni.13@gmail.com"
4 | authors: ["Anurag Soni"]
5 | homepage: "https://github.com/anuragsoni/color"
6 | dev-repo: "git+https://github.com/anuragsoni/color.git"
7 | bug-reports: "https://github.com/anuragsoni/color/issues"
8 | doc: "https://anuragsoni.github.io/color/"
9 | license: "MIT"
10 |
11 | build: [
12 | ["dune" "subst"] {pinned}
13 | ["dune" "build" "-p" name "-j" jobs]
14 | ["dune" "runtest" "-p" name "-j" jobs] {with-test}
15 | ]
16 |
17 | depends: [
18 | "ocaml" {>= "4.05.0"}
19 | "dune"
20 | "alcotest" {with-test}
21 | "gg"
22 | ]
23 |
24 | description: """
25 | Converts between different color formats
26 |
27 | Library that converts between different color formats. Right now it deals with
28 | HSL, HSLA, RGB and RGBA formats.
29 |
30 | The goal for this library is to provide easy handling of colors on the web, when working
31 | with `js_of_ocaml`.
32 | """
33 |
34 | url {
35 | src: "https://github.com/anuragsoni/color/releases/download/0.2.0/color-0.2.0.tbz"
36 | checksum: ["md5=36a5d45385a02f96d07d40d1b0fbcf8a"]
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/esy.lock/opam/merlin-extend.0.4/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Frederic Bour "
3 | authors: "Frederic Bour "
4 | homepage: "https://github.com/let-def/merlin-extend"
5 | bug-reports: "https://github.com/let-def/merlin-extend"
6 | license: "MIT"
7 | dev-repo: "git+https://github.com/let-def/merlin-extend.git"
8 | build: [
9 | ["dune" "subst"] {pinned}
10 | ["dune" "build" "-p" name "-j" jobs]
11 | ]
12 | depends: [
13 | "dune"
14 | "cppo" {build}
15 | "ocaml" {>= "4.02.3"}
16 | ]
17 | synopsis: "A protocol to provide custom frontend to Merlin"
18 | description: """
19 | This protocol allows to replace the OCaml frontend of Merlin.
20 | It extends what used to be done with the `-pp' flag to handle a few more cases."""
21 | doc: "https://let-def.github.io/merlin-extend"
22 | url {
23 | src: "https://github.com/let-def/merlin-extend/archive/v0.4.tar.gz"
24 | checksum: [
25 | "md5=0663a58f2c45fad71615fbf0f6dd2e51"
26 | "sha512=9c0f966f57756c06622fdb8ae1e0721bc098b8a9102fb87c22ad62cb52ece77e7447da2f200993f313273ea0b7c40cd889244407813167bd0d572293f02e0968"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/esy.lock/opam/camomile.1.0.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "yoriyuki.y@gmail.com"
3 | authors: ["Yoriyuki Yamagata"]
4 | homepage: "https://github.com/yoriyuki/Camomile/wiki"
5 | bug-reports: "https://github.com/yoriyuki/Camomile/issues"
6 | license: "LGPL-2.1-or-later with OCaml-LGPL-linking-exception"
7 | dev-repo: "git+https://github.com/yoriyuki/Camomile.git"
8 | build: [
9 | ["ocaml" "configure.ml" "--share" "%{share}%/camomile"]
10 | ["jbuilder" "subst" "-p" name] {pinned}
11 | ["jbuilder" "build" "-p" name "-j" "1"]
12 | ]
13 | depends: [
14 | "ocaml" {>= "4.02.3"}
15 | "jbuilder" {build & >= "1.0+beta17"}
16 | ]
17 | synopsis: "A Unicode library"
18 | description: """
19 | Camomile is a Unicode library for OCaml. Camomile provides Unicode character
20 | type, UTF-8, UTF-16, UTF-32 strings, conversion to/from about 200 encodings,
21 | collation and locale-sensitive case mappings, and more. The library is currently
22 | designed for Unicode Standard 3.2."""
23 | url {
24 | src:
25 | "https://github.com/yoriyuki/Camomile/releases/download/1.0.1/camomile-1.0.1.tbz"
26 | checksum: "md5=82e016653431353a07f22c259adc6e05"
27 | }
28 |
--------------------------------------------------------------------------------
/esy.lock/opam/menhir.20190924/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "francois.pottier@inria.fr"
3 | authors: [
4 | "François Pottier "
5 | "Yann Régis-Gianas "
6 | ]
7 | homepage: "http://gitlab.inria.fr/fpottier/menhir"
8 | dev-repo: "git+https://gitlab.inria.fr/fpottier/menhir.git"
9 | bug-reports: "menhir@inria.fr"
10 | build: [
11 | [make "-f" "Makefile" "PREFIX=%{prefix}%" "USE_OCAMLFIND=true" "docdir=%{doc}%/menhir" "libdir=%{lib}%/menhir" "mandir=%{man}%/man1"]
12 | ]
13 | install: [
14 | [make "-f" "Makefile" "install" "PREFIX=%{prefix}%" "docdir=%{doc}%/menhir" "libdir=%{lib}%/menhir" "mandir=%{man}%/man1"]
15 | ]
16 | depends: [
17 | "ocaml" {>= "4.02"}
18 | "ocamlfind" {build}
19 | "ocamlbuild" {build}
20 | ]
21 | synopsis: "An LR(1) parser generator"
22 | url {
23 | src:
24 | "https://gitlab.inria.fr/fpottier/menhir/repository/20190924/archive.tar.gz"
25 | checksum: [
26 | "md5=677f1997fb73177d5a00fa1b8d61c3ef"
27 | "sha512=ea8a9a6d773529cf6ac05e4c6c4532770fbb8e574c9b646efcefe90d9f24544741e3e8cfd94c8afea0447e34059a8c79c2829b46764ce3a3d6dcb3e7f75980fc"
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/esy.lock/opam/atd.2.0.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "martin@mjambon.com"
3 | authors: ["Martin Jambon"]
4 |
5 | homepage: "https://github.com/mjambon/atd"
6 | bug-reports: "https://github.com/mjambon/atd/issues"
7 | dev-repo: "git://github.com/mjambon/atd.git"
8 |
9 | build: [
10 | ["jbuilder" "subst" "-p" name] {pinned}
11 | ["jbuilder" "build" "-p" name "-j" jobs]
12 | ]
13 |
14 | # Restore when https://github.com/mjambon/atd/issues/121 is resolved.
15 | # build-test: [
16 | # ["jbuilder" "runtest" "-p" name]
17 | # ]
18 |
19 | depends: [
20 | "ocaml" {>= "4.03.0"}
21 | "jbuilder" {build}
22 | "menhir" {build}
23 | "easy-format"
24 | ]
25 | synopsis: "Parser for the ATD data format description language"
26 | description: """
27 | ATD is the OCaml library providing a parser for the ATD language and
28 | various utilities. ATD stands for Adjustable Type Definitions in
29 | reference to its main property of supporting annotations that allow a
30 | good fit with a variety of data formats."""
31 | url {
32 | src: "https://github.com/mjambon/atd/releases/download/2.0.0/atd-2.0.0.tbz"
33 | checksum: "md5=14e47609397c524ea0eae7c3f14f7ccf"
34 | }
35 |
--------------------------------------------------------------------------------
/.ci/publish-build-cache.yml:
--------------------------------------------------------------------------------
1 | # Steps for publishing project cache
2 |
3 | steps:
4 | - bash: 'mkdir -p $(STAGING_DIRECTORY_UNIX)'
5 | condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
6 | displayName: '[Cache][Publish] Create cache directory'
7 |
8 | - bash: 'cd $(ESY__CACHE_INSTALL_PATH) && tar -czf $(STAGING_DIRECTORY_UNIX)/esy-cache.tar .'
9 | workingDirectory: ''
10 | condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
11 | displayName: '[Cache][Publish] Tar esy cache directory'
12 |
13 | # - bash: 'cd $(ESY__NPM_ROOT) && tar -czf $(STAGING_DIRECTORY_UNIX)/npm-cache.tar .'
14 | # condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
15 | # displayName: '[Cache][Publish] Tar npm cache directory'
16 |
17 | - task: PublishBuildArtifacts@1
18 | displayName: '[Cache][Publish] Upload tarball'
19 | condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
20 | inputs:
21 | pathToPublish: '$(STAGING_DIRECTORY)'
22 | artifactName: 'cache-$(Agent.OS)-install'
23 | parallel: true
24 | parallelCount: 8
25 |
--------------------------------------------------------------------------------
/esy.lock/overrides/opam__s__ocamlfind_opam__c__1.8.1_opam_override/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "build": [
3 | [
4 | "bash",
5 | "-c",
6 | "#{os == 'windows' ? 'patch -p1 < findlib-1.8.1.patch' : 'true'}"
7 | ],
8 | [
9 | "./configure",
10 | "-bindir",
11 | "#{self.bin}",
12 | "-sitelib",
13 | "#{self.lib}",
14 | "-mandir",
15 | "#{self.man}",
16 | "-config",
17 | "#{self.lib}/findlib.conf",
18 | "-no-custom",
19 | "-no-topfind"
20 | ],
21 | [
22 | "make",
23 | "all"
24 | ],
25 | [
26 | "make",
27 | "opt"
28 | ]
29 | ],
30 | "install": [
31 | [
32 | "make",
33 | "install"
34 | ],
35 | [
36 | "install",
37 | "-m",
38 | "0755",
39 | "ocaml-stub",
40 | "#{self.bin}/ocaml"
41 | ],
42 | [
43 | "mkdir",
44 | "-p",
45 | "#{self.toplevel}"
46 | ],
47 | [
48 | "install",
49 | "-m",
50 | "0644",
51 | "src/findlib/topfind",
52 | "#{self.toplevel}/topfind"
53 | ]
54 | ],
55 | "exportedEnv": {
56 | "OCAML_TOPLEVEL_PATH": {
57 | "val": "#{self.toplevel}",
58 | "scope": "global"
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Delay.re:
--------------------------------------------------------------------------------
1 | open Settings;
2 |
3 | type delay = {
4 | mutable duration: float,
5 | mutable gain: float,
6 | delayBuffer: array(float),
7 | mutable currentSample: int,
8 | };
9 |
10 | let create = (duration, gain) => {
11 | duration,
12 | gain,
13 | delayBuffer: Array.make(int_of_float(sampleRate *. 2.), 0.),
14 | currentSample: 0,
15 | };
16 |
17 | let process = (d: delay, input: float) => {
18 | /* Max buffer size */
19 | let max = int_of_float(sampleRate *. 2.) - 1;
20 | /* If we're at the end of the sample count, reset */
21 | if (d.currentSample > max) {
22 | d.currentSample = 0;
23 | };
24 |
25 | /* How many samples are we delaying */
26 | let delayIndex = int_of_float(sampleRate *. 2. *. d.duration);
27 | /* Get our insert index */
28 | let dt = d.currentSample + delayIndex;
29 | /* If the index exceeds the buffer length, insert at beginning with the difference */
30 | let insertIndex = dt < max + 1 ? dt : dt mod max;
31 |
32 | /* Fill our delay buffer */
33 | d.delayBuffer[insertIndex] = input;
34 |
35 | /* Mix delay buffer into input signal */
36 | let output = input +. d.delayBuffer[d.currentSample] *. d.gain;
37 |
38 | /* Increment sample counter */
39 | d.currentSample = d.currentSample + 1;
40 |
41 | output;
42 | };
--------------------------------------------------------------------------------
/esy.lock/opam/ocamlbuild.0.14.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Gabriel Scherer "
3 | authors: ["Nicolas Pouillard" "Berke Durak"]
4 | homepage: "https://github.com/ocaml/ocamlbuild/"
5 | bug-reports: "https://github.com/ocaml/ocamlbuild/issues"
6 | license: "LGPL-2.1-only with OCaml-LGPL-linking-exception"
7 | doc: "https://github.com/ocaml/ocamlbuild/blob/master/manual/manual.adoc"
8 | dev-repo: "git+https://github.com/ocaml/ocamlbuild.git"
9 | build: [
10 | [
11 | make
12 | "-f"
13 | "configure.make"
14 | "all"
15 | "OCAMLBUILD_PREFIX=%{prefix}%"
16 | "OCAMLBUILD_BINDIR=%{bin}%"
17 | "OCAMLBUILD_LIBDIR=%{lib}%"
18 | "OCAMLBUILD_MANDIR=%{man}%"
19 | "OCAML_NATIVE=%{ocaml:native}%"
20 | "OCAML_NATIVE_TOOLS=%{ocaml:native}%"
21 | ]
22 | [make "check-if-preinstalled" "all" "opam-install"]
23 | ]
24 | conflicts: [
25 | "base-ocamlbuild"
26 | "ocamlfind" {< "1.6.2"}
27 | ]
28 | synopsis:
29 | "OCamlbuild is a build system with builtin rules to easily build most OCaml projects."
30 | depends: [
31 | "ocaml" {>= "4.03"}
32 | ]
33 | url {
34 | src: "https://github.com/ocaml/ocamlbuild/archive/0.14.0.tar.gz"
35 | checksum: "sha256=87b29ce96958096c0a1a8eeafeb6268077b2d11e1bf2b3de0f5ebc9cf8d42e78"
36 | }
37 |
--------------------------------------------------------------------------------
/esy.lock/opam/fpath.0.7.2/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Daniel Bünzli "
3 | authors: ["Daniel Bünzli "]
4 | homepage: "http://erratique.ch/software/fpath"
5 | doc: "http://erratique.ch/software/fpath/doc"
6 | dev-repo: "git+http://erratique.ch/repos/fpath.git"
7 | bug-reports: "https://github.com/dbuenzli/fpath/issues"
8 | tags: [ "file" "system" "path" "org:erratique" ]
9 | license: "ISC"
10 | depends: [
11 | "ocaml" {>= "4.01.0"}
12 | "ocamlfind" {build}
13 | "ocamlbuild" {build}
14 | "topkg" {build & >= "0.9.0"}
15 | "result"
16 | "astring"
17 | ]
18 | build: [[
19 | "ocaml" "pkg/pkg.ml" "build"
20 | "--dev-pkg" "%{pinned}%" ]]
21 | synopsis: "File system paths for OCaml"
22 | description: """
23 | Fpath is an OCaml module for handling file system paths with POSIX or
24 | Windows conventions. Fpath processes paths without accessing the file
25 | system and is independent from any system library.
26 |
27 | Fpath depends on [Astring][astring] and is distributed under the ISC
28 | license.
29 |
30 | [astring]: http://erratique.ch/software/astring"""
31 | url {
32 | src: "http://erratique.ch/software/fpath/releases/fpath-0.7.2.tbz"
33 | checksum: "md5=52c7ecb0bf180088336f3c645875fa41"
34 | }
35 |
--------------------------------------------------------------------------------
/esy.lock/opam/gg.0.9.3/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Daniel Bünzli "
3 | homepage: "http://erratique.ch/software/gg"
4 | authors: [ "The gg programmers" ]
5 | doc: "http://erratique.ch/software/gg/doc/Gg"
6 | dev-repo: "git+http://erratique.ch/repos/gg.git"
7 | bug-reports: "https://github.com/dbuenzli/gg/issues"
8 | tags: [ "matrix" "vector" "color" "data-structure" "graphics" "org:erratique"]
9 | license: "ISC"
10 | depends: [
11 | "ocaml" {>= "4.02.2"}
12 | "ocamlfind" {build}
13 | "ocamlbuild" {build}
14 | "topkg" {build}
15 | "base-bigarray"
16 | # "bench" {with-test}
17 | ]
18 | build: [[
19 | "ocaml" "pkg/pkg.ml" "build" "--pinned" "%{pinned}%"
20 | ]]
21 | synopsis: """Basic types for computer graphics in OCaml"""
22 | description: """\
23 |
24 | Gg is an OCaml module providing basic types for computer graphics.
25 |
26 | It defines types and functions for floats, vectors, points, sizes,
27 | matrices, quaternions, axis-aligned boxes, colors, color spaces, and
28 | raster data.
29 |
30 | Gg is made of a single module, depends on bigarrays, and is
31 | distributed under the ISC license.
32 | """
33 | url {
34 | archive: "http://erratique.ch/software/gg/releases/gg-0.9.3.tbz"
35 | checksum: "1801fc7b6af16c597ef0bfaacc12cd5b"
36 | }
37 |
--------------------------------------------------------------------------------
/Filter.re:
--------------------------------------------------------------------------------
1 | type mode =
2 | | LowPass
3 | | HighPass;
4 |
5 | type filter = {
6 | a0: float,
7 | a1: float,
8 | a2: float,
9 | b1: float,
10 | b2: float,
11 | fc: float,
12 | q: float,
13 | peakGain: float,
14 | mutable z1: float,
15 | mutable z2: float,
16 | mode,
17 | };
18 |
19 | let process = (f: filter, input: float) => {
20 | let output = input *. f.a0 +. f.z1;
21 | f.z1 = input *. f.a1 +. f.z2 -. f.b1 *. output;
22 | f.z2 = input *. f.a2 -. f.b2 *. output;
23 | output;
24 | };
25 |
26 | let create = (mode, cutoff, q, peakGain) => {
27 | let k = tan(Float.pi *. cutoff);
28 | switch (mode) {
29 | | LowPass =>
30 | let norm = 1. /. (1. +. k /. q +. k *. k);
31 | let a0 = k *. k *. norm;
32 | let a1 = 2. *. a0;
33 | let a2 = a0;
34 | let b1 = 2. *. (k *. k -. 1.) *. norm;
35 | let b2 = (1. -. k /. q +. k *. k) *. norm;
36 | {a0, a1, a2, b1, b2, fc: cutoff, peakGain, q, z1: 0., z2: 0., mode};
37 | | HighPass =>
38 | let norm = 1. /. (1. +. k /. q +. k *. k);
39 | let a0 = 1. *. norm;
40 | let a1 = (-2.) *. a0;
41 | let a2 = a0;
42 | let b1 = 2. *. (k *. k -. 1.) *. norm;
43 | let b2 = (1. -. k /. q +. k *. k) *. norm;
44 | {a0, a1, a2, b1, b2, fc: cutoff, peakGain, q, z1: 0., z2: 0., mode};
45 | };
46 | };
--------------------------------------------------------------------------------
/esy.lock/opam/uchar.0.0.2/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Daniel Bünzli "
3 | authors: ["Daniel Bünzli "]
4 | homepage: "http://ocaml.org"
5 | doc: "https://ocaml.github.io/uchar/"
6 | dev-repo: "git+https://github.com/ocaml/uchar.git"
7 | bug-reports: "https://github.com/ocaml/uchar/issues"
8 | tags: [ "text" "character" "unicode" "compatibility" "org:ocaml.org" ]
9 | license: "typeof OCaml system"
10 | depends: [
11 | "ocaml" {>= "3.12.0"}
12 | "ocamlbuild" {build}
13 | ]
14 | build: [
15 | ["ocaml" "pkg/git.ml"]
16 | [
17 | "ocaml"
18 | "pkg/build.ml"
19 | "native=%{ocaml:native}%"
20 | "native-dynlink=%{ocaml:native-dynlink}%"
21 | ]
22 | ]
23 | synopsis: "Compatibility library for OCaml's Uchar module"
24 | description: """
25 | The `uchar` package provides a compatibility library for the
26 | [`Uchar`][1] module introduced in OCaml 4.03.
27 |
28 | The `uchar` package is distributed under the license of the OCaml
29 | compiler. See [LICENSE](LICENSE) for details.
30 |
31 | [1]: http://caml.inria.fr/pub/docs/manual-ocaml/libref/Uchar.html"""
32 | url {
33 | src:
34 | "https://github.com/ocaml/uchar/releases/download/v0.0.2/uchar-0.0.2.tbz"
35 | checksum: "md5=c9ba2c738d264c420c642f7bb1cf4a36"
36 | }
37 |
--------------------------------------------------------------------------------
/TrackButton.re:
--------------------------------------------------------------------------------
1 | open Revery;
2 | open Revery.UI;
3 | open Revery.UI.Components;
4 |
5 | let component = React.component("SimpleButton");
6 |
7 | let createElement =
8 | (
9 | ~onClick,
10 | ~active: bool=false,
11 | ~text,
12 | ~children as _: list(React.syntheticElement),
13 | (),
14 | ) =>
15 | component(hooks => {
16 | let bgColor = active ? Color.hex("#bdbaa0") : Color.hex("#EAE7C6");
17 | let wrapperStyle =
18 | Style.[
19 | backgroundColor(bgColor),
20 | width(50),
21 | flexGrow(1),
22 | marginRight(1),
23 | alignItems(`Center),
24 | justifyContent(`Center),
25 | top(-10),
26 | ];
27 |
28 | let textHeaderStyle =
29 | Style.[
30 | color(Color.hex("#25231E")),
31 | fontFamily("Roboto-Regular.ttf"),
32 | fontSize(14),
33 | marginTop(2),
34 | ];
35 |
36 | let shadow =
37 | Style.[
38 | height(active ? 0 : 5),
39 | width(50),
40 | backgroundColor(Color.hex("#9a9880")),
41 | top(-10),
42 | ];
43 |
44 | (
45 | hooks,
46 |
47 |
48 |
49 | ,
50 | );
51 | });
--------------------------------------------------------------------------------
/esy.lock/opam/re.1.9.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 |
3 | maintainer: "rudi.grinberg@gmail.com"
4 | authors: [
5 | "Jerome Vouillon"
6 | "Thomas Gazagnaire"
7 | "Anil Madhavapeddy"
8 | "Rudi Grinberg"
9 | "Gabriel Radanne"
10 | ]
11 | license: "LGPL-2.0-only with OCaml-LGPL-linking-exception"
12 | homepage: "https://github.com/ocaml/ocaml-re"
13 | bug-reports: "https://github.com/ocaml/ocaml-re/issues"
14 | dev-repo: "git+https://github.com/ocaml/ocaml-re.git"
15 |
16 | build: [
17 | ["dune" "subst"] {pinned}
18 | ["dune" "build" "-p" name "-j" jobs]
19 | ["dune" "runtest" "-p" name "-j" jobs] {with-test}
20 | ]
21 |
22 | depends: [
23 | "ocaml" {>= "4.02"}
24 | "dune"
25 | "ounit" {with-test}
26 | "seq"
27 | ]
28 |
29 | synopsis: "RE is a regular expression library for OCaml"
30 | description: """
31 | Pure OCaml regular expressions with:
32 | * Perl-style regular expressions (module Re.Perl)
33 | * Posix extended regular expressions (module Re.Posix)
34 | * Emacs-style regular expressions (module Re.Emacs)
35 | * Shell-style file globbing (module Re.Glob)
36 | * Compatibility layer for OCaml's built-in Str module (module Re.Str)
37 | """
38 | url {
39 | src:
40 | "https://github.com/ocaml/ocaml-re/releases/download/1.9.0/re-1.9.0.tbz"
41 | checksum: "md5=bddaed4f386a22cace7850c9c7dac296"
42 | }
43 |
--------------------------------------------------------------------------------
/esy.lock/opam/react.1.2.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Daniel Bünzli "
3 | homepage: "http://erratique.ch/software/react"
4 | authors: ["Daniel Bünzli "]
5 | doc: "http://erratique.ch/software/react/doc/React"
6 | dev-repo: "git+http://erratique.ch/repos/react.git"
7 | bug-reports: "https://github.com/dbuenzli/react/issues"
8 | tags: [ "reactive" "declarative" "signal" "event" "frp" "org:erratique" ]
9 | license: "ISC"
10 | depends: [
11 | "ocaml" {>= "4.01.0"}
12 | "ocamlfind" {build}
13 | "ocamlbuild" {build}
14 | "topkg" {build & >= "0.9.0"}
15 | ]
16 | build:
17 | [[ "ocaml" "pkg/pkg.ml" "build"
18 | "--dev-pkg" "%{pinned}%" ]]
19 | synopsis: "Declarative events and signals for OCaml"
20 | description: """
21 | Release %%VERSION%%
22 |
23 | React is an OCaml module for functional reactive programming (FRP). It
24 | provides support to program with time varying values : declarative
25 | events and signals. React doesn't define any primitive event or
26 | signal, it lets the client chooses the concrete timeline.
27 |
28 | React is made of a single, independent, module and distributed under
29 | the ISC license."""
30 | url {
31 | src: "http://erratique.ch/software/react/releases/react-1.2.1.tbz"
32 | checksum: "md5=ce1454438ce4e9d2931248d3abba1fcc"
33 | }
34 |
--------------------------------------------------------------------------------
/esy.lock/opam/cppo.1.6.6/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "martin@mjambon.com"
3 | authors: "Martin Jambon"
4 | license: "BSD-3-Clause"
5 | homepage: "http://mjambon.com/cppo.html"
6 | doc: "https://ocaml-community.github.io/cppo/"
7 | bug-reports: "https://github.com/ocaml-community/cppo/issues"
8 | depends: [
9 | "ocaml" {>= "4.03"}
10 | "dune" {>= "1.0"}
11 | "base-unix"
12 | ]
13 | build: [
14 | ["dune" "subst"] {pinned}
15 | ["dune" "build" "-p" name "-j" jobs]
16 | ["dune" "runtest" "-p" name "-j" jobs] {with-test}
17 | ]
18 | dev-repo: "git+https://github.com/ocaml-community/cppo.git"
19 | synopsis: "Code preprocessor like cpp for OCaml"
20 | description: """
21 | Cppo is an equivalent of the C preprocessor for OCaml programs.
22 | It allows the definition of simple macros and file inclusion.
23 |
24 | Cppo is:
25 |
26 | * more OCaml-friendly than cpp
27 | * easy to learn without consulting a manual
28 | * reasonably fast
29 | * simple to install and to maintain
30 | """
31 | url {
32 | src: "https://github.com/ocaml-community/cppo/releases/download/v1.6.6/cppo-v1.6.6.tbz"
33 | checksum: [
34 | "sha256=e7272996a7789175b87bb998efd079794a8db6625aae990d73f7b4484a07b8a0"
35 | "sha512=44ecf9d225d9e45490a2feac0bde04865ca398dba6c3579e3370fcd1ea255707b8883590852af8b2df87123801062b9f3acce2455c092deabf431f9c4fb8d8eb"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | # NOTE: this has no trailing slash since when using esy, it is a symlink
37 | node_modules
38 | jspm_packages/
39 |
40 | # TypeScript v1 declaration files
41 | typings/
42 |
43 | # Optional npm cache directory
44 | .npm
45 |
46 | # Optional eslint cache
47 | .eslintcache
48 |
49 | # Optional REPL history
50 | .node_repl_history
51 |
52 | # Output of 'npm pack'
53 | *.tgz
54 |
55 | # Yarn Integrity file
56 | .yarn-integrity
57 |
58 | # dotenv environment variables file
59 | .env
60 |
61 | # next.js build output
62 | .next
63 |
64 | # esy
65 | _build/
66 | _esy/
67 | _release/
68 |
69 | # reason
70 | *.install
71 | .merlin
72 |
73 |
--------------------------------------------------------------------------------
/esy.lock/opam/zed.2.0.3/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "opam-devel@lists.ocaml.org"
3 | authors: ["Jérémie Dimino"]
4 | homepage: "https://github.com/ocaml-community/zed"
5 | bug-reports: "https://github.com/ocaml-community/zed/issues"
6 | dev-repo: "git://github.com/ocaml-community/zed.git"
7 | license: "BSD-3-Clause"
8 | depends: [
9 | "ocaml" {>= "4.02.3"}
10 | "dune" {>= "1.1.0"}
11 | "base-bytes"
12 | "camomile" {>= "1.0.1"}
13 | "react"
14 | "charInfo_width" {>= "1.1.0" & < "2.0~"}
15 | ]
16 | build: [
17 | ["dune" "build" "-p" name "-j" jobs]
18 | ["dune" "runtest" "-p" name "-j" jobs] {with-test}
19 | ]
20 | synopsis: "Abstract engine for text edition in OCaml"
21 | description: """
22 | Zed is an abstract engine for text edition. It can be used to write text
23 | editors, edition widgets, readlines, ... Zed uses Camomile to fully support the
24 | Unicode specification, and implements an UTF-8 encoded string type with
25 | validation, and a rope datastructure to achieve efficient operations on large
26 | Unicode buffers. Zed also features a regular expression search on ropes. To
27 | support efficient text edition capabilities, Zed provides macro recording and
28 | cursor management facilities."""
29 | url {
30 | src: "https://github.com/ocaml-community/zed/releases/download/2.0.3/zed-2.0.3.tbz"
31 | checksum: "878123c9114bf3c0bd18a19fb1af73cd"
32 | }
33 |
--------------------------------------------------------------------------------
/PlayButton.re:
--------------------------------------------------------------------------------
1 | open Revery;
2 | open Revery.UI;
3 | open Revery.UI.Components;
4 |
5 | let component = React.component("SimpleButton");
6 |
7 | let createElement =
8 | (
9 | ~onClick,
10 | ~playing: bool,
11 | ~children as _: list(React.syntheticElement),
12 | (),
13 | ) =>
14 | component(hooks => {
15 | let wrapperStyle =
16 | Style.[
17 | backgroundColor(Color.hex("#EAE7C6")),
18 | width(100),
19 | flexGrow(1),
20 | alignItems(`Center),
21 | justifyContent(`Center),
22 | ];
23 |
24 | let textHeaderStyle =
25 | Style.[
26 | color(Color.hex("#25231E")),
27 | fontFamily("Roboto-Regular.ttf"),
28 | fontSize(16),
29 | marginTop(2),
30 | ];
31 |
32 | let shadow =
33 | Style.[
34 | height(playing ? 0 : 5),
35 | width(100),
36 | backgroundColor(Color.hex("#9a9880")),
37 | ];
38 |
39 | let clickableStyle =
40 | Style.[margin(16), border(~width=3, ~color=Color.hex("#bdbaa0"))];
41 |
42 | let textContent = playing ? "STOP" : "START";
43 | (
44 | hooks,
45 |
46 |
47 |
48 |
49 |
50 | ,
51 | );
52 | });
--------------------------------------------------------------------------------
/esy.lock/opam/yojson.1.7.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "martin@mjambon.com"
3 | authors: ["Martin Jambon"]
4 | homepage: "https://github.com/ocaml-community/yojson"
5 | bug-reports: "https://github.com/ocaml-community/yojson/issues"
6 | dev-repo: "git+https://github.com/ocaml-community/yojson.git"
7 | doc: "https://ocaml-community.github.io/yojson/"
8 | build: [
9 | ["dune" "subst"] {pinned}
10 | ["dune" "build" "-p" name "-j" jobs]
11 | ]
12 | run-test: [["dune" "runtest" "-p" name "-j" jobs]]
13 | depends: [
14 | "ocaml" {>= "4.02.3"}
15 | "dune"
16 | "cppo" {build}
17 | "easy-format"
18 | "biniou" {>= "1.2.0"}
19 | "alcotest" {with-test & >= "0.8.5"}
20 | ]
21 | synopsis:
22 | "Yojson is an optimized parsing and printing library for the JSON format"
23 | description: """
24 | Yojson is an optimized parsing and printing library for the JSON format.
25 |
26 | It addresses a few shortcomings of json-wheel including 2x speedup,
27 | polymorphic variants and optional syntax for tuples and variants.
28 |
29 | ydump is a pretty-printing command-line program provided with the
30 | yojson package.
31 |
32 | The program atdgen can be used to derive OCaml-JSON serializers and
33 | deserializers from type definitions."""
34 | url {
35 | src:
36 | "https://github.com/ocaml-community/yojson/releases/download/1.7.0/yojson-1.7.0.tbz"
37 | checksum: "md5=b89d39ca3f8c532abe5f547ad3b8f84d"
38 | }
39 |
--------------------------------------------------------------------------------
/esy.lock/opam/lambda-term.2.0.2/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "jeremie@dimino.org"
3 | authors: ["Jérémie Dimino"]
4 | homepage: "https://github.com/ocaml-community/lambda-term"
5 | bug-reports: "https://github.com/ocaml-community/lambda-term/issues"
6 | dev-repo: "git://github.com/ocaml-community/lambda-term.git"
7 | license: "BSD-3-Clause"
8 | build: [
9 | ["dune" "build" "-p" name "-j" jobs]
10 | ["dune" "runtest" "-p" name "-j" jobs] {with-test}
11 | ]
12 | depends: [
13 | "ocaml" {>= "4.02.3"}
14 | "lwt" {>= "4.0.0"}
15 | "lwt_log"
16 | "react"
17 | "zed" {>= "2.0.3" & < "3.0"}
18 | "camomile" {>= "1.0.1"}
19 | "lwt_react"
20 | "dune" {>= "1.0.0"}
21 | ]
22 | synopsis: "Terminal manipulation library for OCaml"
23 | description: """
24 | Lambda-term is a cross-platform library for manipulating the terminal. It
25 | provides an abstraction for keys, mouse events, colors, as well as a set of
26 | widgets to write curses-like applications. The main objective of lambda-term is
27 | to provide a higher level functional interface to terminal manipulation than,
28 | for example, ncurses, by providing a native OCaml interface instead of bindings
29 | to a C library. Lambda-term integrates with zed to provide text edition
30 | facilities in console applications."""
31 | url {
32 | src: "https://github.com/ocaml-community/lambda-term/releases/download/2.0.2/lambda-term-2.0.2.tbz"
33 | checksum: "md5=4602aa4355705909e406513322b4b27e"
34 | }
35 |
--------------------------------------------------------------------------------
/esy.lock/opam/atdgen.2.0.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "martin@mjambon.com"
3 | authors: ["Martin Jambon"]
4 |
5 | homepage: "https://github.com/mjambon/atd"
6 | bug-reports: "https://github.com/mjambon/atd/issues"
7 | dev-repo: "git://github.com/mjambon/atd.git"
8 |
9 | build: [
10 | ["jbuilder" "subst" "-p" name] {pinned}
11 | ["jbuilder" "build" "-p" name "-j" jobs]
12 | ]
13 |
14 | # Restore when https://github.com/mjambon/atd/issues/121 is resolved.
15 | # build-test: [
16 | # ["jbuilder" "runtest" "-p" name]
17 | # ]
18 |
19 | depends: [
20 | "ocaml" {>= "4.03.0"}
21 | "jbuilder" {build}
22 | "atd" {>= "2.0.0"}
23 | "atdgen-runtime" {>= "2.0.0"}
24 | "biniou" {>= "1.0.6"}
25 | "yojson" {>= "1.2.1"}
26 | ]
27 | synopsis:
28 | "Generates efficient JSON serializers, deserializers and validators"
29 | description: """
30 | Atdgen is a command-line program that takes as input type definitions in the
31 | ATD syntax and produces OCaml code suitable for data serialization and
32 | deserialization.
33 |
34 | Two data formats are currently supported, these are biniou and JSON.
35 | Atdgen-biniou and Atdgen-json will refer to Atdgen used in one context or the
36 | other.
37 |
38 | Atdgen was designed with efficiency and durability in mind. Software authors
39 | are encouraged to use Atdgen directly and to write tools that may reuse part of
40 | Atdgen’s source code."""
41 | url {
42 | src: "https://github.com/mjambon/atd/releases/download/2.0.0/atd-2.0.0.tbz"
43 | checksum: "md5=14e47609397c524ea0eae7c3f14f7ccf"
44 | }
45 |
--------------------------------------------------------------------------------
/esy.lock/opam/ocaml-migrate-parsetree.1.3.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "frederic.bour@lakaban.net"
3 | authors: [
4 | "Frédéric Bour "
5 | "Jérémie Dimino "
6 | ]
7 | license: "LGPL-2.1-only with OCaml-LGPL-linking-exception"
8 | homepage: "https://github.com/ocaml-ppx/ocaml-migrate-parsetree"
9 | bug-reports: "https://github.com/ocaml-ppx/ocaml-migrate-parsetree/issues"
10 | dev-repo: "git+https://github.com/ocaml-ppx/ocaml-migrate-parsetree.git"
11 | doc: "https://ocaml-ppx.github.io/ocaml-migrate-parsetree/"
12 | tags: [ "syntax" "org:ocamllabs" ]
13 | build: [
14 | ["dune" "build" "-p" name "-j" jobs]
15 | ]
16 | depends: [
17 | "result"
18 | "ppx_derivers"
19 | "dune" {>= "1.6.0"}
20 | "ocaml" {>= "4.02.3" & < "4.09.0"}
21 | ]
22 | synopsis: "Convert OCaml parsetrees between different versions"
23 | description: """
24 | Convert OCaml parsetrees between different versions
25 |
26 | This library converts parsetrees, outcometree and ast mappers between
27 | different OCaml versions. High-level functions help making PPX
28 | rewriters independent of a compiler version.
29 | """
30 | url {
31 | src:
32 | "https://github.com/ocaml-ppx/ocaml-migrate-parsetree/releases/download/v1.3.1/ocaml-migrate-parsetree-v1.3.1.tbz"
33 | checksum: [
34 | "sha256=83e4955a6fd6b494646ab92c476840ea96b5fb434435c287e7ad3e6efadc8338"
35 | "sha512=7da86f9596dd1439990a6f087fdeba64a0f3ce2634473be4cca92ecc02b6fcd97917956890fbe35b3cba5a126d007afec6ede1e4afd0a5218c89fd6079ad4182"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/esy.lock/opam/astring.0.8.3/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Daniel Bünzli "
3 | authors: ["Daniel Bünzli "]
4 | homepage: "http://erratique.ch/software/astring"
5 | doc: "http://erratique.ch/software/astring/doc"
6 | dev-repo: "git+http://erratique.ch/repos/astring.git"
7 | bug-reports: "https://github.com/dbuenzli/astring/issues"
8 | tags: [ "string" "org:erratique" ]
9 | license: "ISC"
10 | depends: [
11 | "ocaml" {>= "4.01.0"}
12 | "ocamlfind" {build}
13 | "ocamlbuild" {build}
14 | "topkg" {build}
15 | "base-bytes"
16 | ]
17 | build: [[
18 | "ocaml" "pkg/pkg.ml" "build"
19 | "--pinned" "%{pinned}%" ]]
20 | synopsis: "Alternative String module for OCaml"
21 | description: """
22 | Astring exposes an alternative `String` module for OCaml. This module
23 | tries to balance minimality and expressiveness for basic, index-free,
24 | string processing and provides types and functions for substrings,
25 | string sets and string maps.
26 |
27 | Remaining compatible with the OCaml `String` module is a non-goal. The
28 | `String` module exposed by Astring has exception safe functions,
29 | removes deprecated and rarely used functions, alters some signatures
30 | and names, adds a few missing functions and fully exploits OCaml's
31 | newfound string immutability.
32 |
33 | Astring depends only on the OCaml standard library. It is distributed
34 | under the ISC license."""
35 | url {
36 | src: "http://erratique.ch/software/astring/releases/astring-0.8.3.tbz"
37 | checksum: "md5=c5bf6352b9ac27fbeab342740f4fa870"
38 | }
39 |
--------------------------------------------------------------------------------
/esy.lock/opam/uutf.1.0.2/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Daniel Bünzli "
3 | authors: ["Daniel Bünzli "]
4 | homepage: "http://erratique.ch/software/uutf"
5 | doc: "http://erratique.ch/software/uutf/doc/Uutf"
6 | dev-repo: "git+http://erratique.ch/repos/uutf.git"
7 | bug-reports: "https://github.com/dbuenzli/uutf/issues"
8 | tags: [ "unicode" "text" "utf-8" "utf-16" "codec" "org:erratique" ]
9 | license: "ISC"
10 | depends: [
11 | "ocaml" {>= "4.01.0"}
12 | "ocamlfind" {build}
13 | "ocamlbuild" {build}
14 | "topkg" {build}
15 | "uchar"
16 | ]
17 | depopts: ["cmdliner"]
18 | conflicts: ["cmdliner" { < "0.9.6"} ]
19 | build: [[
20 | "ocaml" "pkg/pkg.ml" "build"
21 | "--pinned" "%{pinned}%"
22 | "--with-cmdliner" "%{cmdliner:installed}%" ]]
23 | synopsis: """Non-blocking streaming Unicode codec for OCaml"""
24 | description: """\
25 |
26 | Uutf is a non-blocking streaming codec to decode and encode the UTF-8,
27 | UTF-16, UTF-16LE and UTF-16BE encoding schemes. It can efficiently
28 | work character by character without blocking on IO. Decoders perform
29 | character position tracking and support newline normalization.
30 |
31 | Functions are also provided to fold over the characters of UTF encoded
32 | OCaml string values and to directly encode characters in OCaml
33 | Buffer.t values.
34 |
35 | Uutf has no dependency and is distributed under the ISC license.
36 | """
37 | url {
38 | archive: "http://erratique.ch/software/uutf/releases/uutf-1.0.2.tbz"
39 | checksum: "a7c542405a39630c689a82bd7ef2292c"
40 | }
41 |
--------------------------------------------------------------------------------
/esy.lock/opam/tyxml.4.3.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "dev@ocsigen.org"
3 | homepage: "https://github.com/ocsigen/tyxml/"
4 | bug-reports: "https://github.com/ocsigen/tyxml/issues"
5 | doc: "https://ocsigen.org/tyxml/manual/"
6 | dev-repo: "git+https://github.com/ocsigen/tyxml.git"
7 | license: "LGPL-2.1-only with OCaml-LGPL-linking-exception"
8 |
9 | build: [
10 | ["dune" "subst"] {pinned}
11 | ["dune" "build" "-p" name "-j" jobs]
12 | ["dune" "runtest" "-p" name "-j" jobs] {with-test}
13 | ]
14 |
15 | depends: [
16 | "ocaml" {>= "4.02"}
17 | "re" {>= "1.5.0"}
18 | ("ocaml" {>= "4.07"} | "re" {>= "1.8.0"})
19 | "dune"
20 | "alcotest" {with-test}
21 | "seq"
22 | "uutf" {>= "1.0.0"}
23 | ]
24 |
25 | synopsis:"TyXML is a library for building correct HTML and SVG documents"
26 | description:"""
27 | TyXML provides a set of convenient combinators that uses the OCaml
28 | type system to ensure the validity of the generated documents. TyXML
29 | can be used with any representation of HTML and SVG: the textual one,
30 | provided directly by this package, or DOM trees (`js_of_ocaml-tyxml`)
31 | virtual DOM (`virtual-dom`) and reactive or replicated trees
32 | (`eliom`). You can also create your own representation and use it to
33 | instantiate a new set of combinators.
34 |
35 | ```ocaml
36 | open Tyxml
37 | let to_ocaml = Html.(a ~a:[a_href "ocaml.org"] [txt "OCaml!"])
38 | ```
39 | """
40 | authors: "The ocsigen team"
41 | url {
42 | src:
43 | "https://github.com/ocsigen/tyxml/releases/download/4.3.0/tyxml-4.3.0.tbz"
44 | checksum: "md5=fd834a567f813bf447cab5f4c3a723e2"
45 | }
46 |
--------------------------------------------------------------------------------
/esy.lock/opam/cmdliner.1.0.2/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Daniel Bünzli "
3 | authors: ["Daniel Bünzli "]
4 | homepage: "http://erratique.ch/software/cmdliner"
5 | doc: "http://erratique.ch/software/cmdliner/doc/Cmdliner"
6 | dev-repo: "git+http://erratique.ch/repos/cmdliner.git"
7 | bug-reports: "https://github.com/dbuenzli/cmdliner/issues"
8 | tags: [ "cli" "system" "declarative" "org:erratique" ]
9 | license: "ISC"
10 | depends: [
11 | "ocaml" {>= "4.01.0"}
12 | "ocamlfind" {build}
13 | "ocamlbuild" {build}
14 | "topkg" {>= "0.8.1" & build}
15 | "result"
16 | ]
17 | build: [[
18 | "ocaml" "pkg/pkg.ml" "build"
19 | "--pinned" "%{pinned}%"
20 | ]]
21 | synopsis: "Declarative definition of command line interfaces for OCaml"
22 | description: """
23 | Cmdliner allows the declarative definition of command line interfaces
24 | for OCaml.
25 |
26 | It provides a simple and compositional mechanism to convert command
27 | line arguments to OCaml values and pass them to your functions. The
28 | module automatically handles syntax errors, help messages and UNIX man
29 | page generation. It supports programs with single or multiple commands
30 | and respects most of the [POSIX][1] and [GNU][2] conventions.
31 |
32 | Cmdliner has no dependencies and is distributed under the ISC license.
33 |
34 | [1]: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html
35 | [2]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html"""
36 | url {
37 | src: "http://erratique.ch/software/cmdliner/releases/cmdliner-1.0.2.tbz"
38 | checksum: "md5=ab2f0130e88e8dcd723ac6154c98a881"
39 | }
40 |
--------------------------------------------------------------------------------
/esy.lock/overrides/opam__s__ocplib_endian_opam__c__1.0_opam_override/files/ocplib-endian-0.8.patch:
--------------------------------------------------------------------------------
1 | --- ./myocamlbuild.ml
2 | +++ ./myocamlbuild.ml
3 | @@ -573,6 +573,24 @@
4 | Add a dependency after dropping support for 4.01 and earlier. *)
5 | let dispatch_cppo = function
6 | | After_rules -> begin
7 | + let is_directory s =
8 | + let slen = String.length s in
9 | + let s =
10 | + if Sys.os_type <> "Win32" || slen < 2 then
11 | + s
12 | + else
13 | + match s.[slen-1] with
14 | + | '\\' | '/' ->
15 | + if slen <> 3 || s.[1] <> ':' then
16 | + String.sub s 0 (slen -1)
17 | + else
18 | + (match s.[0] with
19 | + | 'A' .. 'Z' | 'a' .. 'z' -> s
20 | + | _ -> String.sub s 0 (slen -1))
21 | + | _ -> s
22 | + in
23 | + Pathname.is_directory s
24 | + in
25 | let cppo_rules ext =
26 | let dep = "%(name).cppo"-.-ext
27 | and prod1 = "%(name: <*> and not <*.cppo>)"-.-ext
28 | @@ -591,11 +609,11 @@
29 | pflag ["cppo"] "cppo_D" (fun s -> S [A "-D"; A s]) ;
30 | pflag ["cppo"] "cppo_U" (fun s -> S [A "-U"; A s]) ;
31 | pflag ["cppo"] "cppo_I" (fun s ->
32 | - if Pathname.is_directory s then S [A "-I"; P s]
33 | + if is_directory s then S [A "-I"; P s]
34 | else S [A "-I"; P (Pathname.dirname s)]
35 | ) ;
36 | pdep ["cppo"] "cppo_I" (fun s ->
37 | - if Pathname.is_directory s then [] else [s]) ;
38 | + if is_directory s then [] else [s]) ;
39 | flag ["cppo"; "cppo_q"] (A "-q") ;
40 | flag ["cppo"; "cppo_s"] (A "-s") ;
41 | flag ["cppo"; "cppo_n"] (A "-n") ;
42 |
--------------------------------------------------------------------------------
/esy.lock/opam/ocplib-endian.1.0/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | authors: "Pierre Chambart"
3 | maintainer: "pierre.chambart@ocamlpro.com"
4 | homepage: "https://github.com/OCamlPro/ocplib-endian"
5 | build: [
6 | ["ocaml" "setup.ml" "-configure" "--disable-debug" "--prefix" prefix]
7 | ["ocaml" "setup.ml" "-build"]
8 | ]
9 | install: [
10 | ["ocaml" "setup.ml" "-install"]
11 | ]
12 | remove: ["ocamlfind" "remove" "ocplib-endian"]
13 | depends: [
14 | "ocaml"
15 | "base-bytes"
16 | "ocamlfind"
17 | "cppo" {>= "1.1.0"}
18 | "ocamlbuild" {build}
19 | ]
20 | dev-repo: "git+https://github.com/OCamlPro/ocplib-endian.git"
21 | bug-reports: "https://github.com/OCamlPro/ocplib-endian/issues"
22 | synopsis:
23 | "Optimised functions to read and write int16/32/64 from strings and bigarrays, based on new primitives added in version 4.01."
24 | description: """
25 | The library implements three modules:
26 | * [EndianString](https://github.com/OCamlPro/ocplib-endian/blob/master/src/endianString.cppo.mli) works directly on strings, and provides submodules BigEndian and LittleEndian, with their unsafe counter-parts;
27 | * [EndianBytes](https://github.com/OCamlPro/ocplib-endian/blob/master/src/endianBytes.cppo.mli) works directly on bytes, and provides submodules BigEndian and LittleEndian, with their unsafe counter-parts;
28 | * [EndianBigstring](https://github.com/OCamlPro/ocplib-endian/blob/master/src/endianBigstring.cppo.mli) works on bigstrings (Bigarrays of chars), and provides submodules BigEndian and LittleEndian, with their unsafe counter-parts;"""
29 | flags: light-uninstall
30 | url {
31 | src: "https://github.com/OCamlPro/ocplib-endian/archive/1.0.tar.gz"
32 | checksum: "md5=74b45ba33e189283170a748c2a3ed477"
33 | }
34 |
--------------------------------------------------------------------------------
/esy.lock/opam/ocamlfind.1.8.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | synopsis: "A library manager for OCaml"
3 | maintainer: "Thomas Gazagnaire "
4 | authors: "Gerd Stolpmann "
5 | homepage: "http://projects.camlcity.org/projects/findlib.html"
6 | bug-reports: "https://gitlab.camlcity.org/gerd/lib-findlib/issues"
7 | dev-repo: "git+https://gitlab.camlcity.org/gerd/lib-findlib.git"
8 | description: """
9 | Findlib is a library manager for OCaml. It provides a convention how
10 | to store libraries, and a file format ("META") to describe the
11 | properties of libraries. There is also a tool (ocamlfind) for
12 | interpreting the META files, so that it is very easy to use libraries
13 | in programs and scripts.
14 | """
15 | build: [
16 | [
17 | "./configure"
18 | "-bindir"
19 | bin
20 | "-sitelib"
21 | lib
22 | "-mandir"
23 | man
24 | "-config"
25 | "%{lib}%/findlib.conf"
26 | "-no-custom"
27 | "-no-camlp4" {!ocaml:preinstalled & ocaml:version >= "4.02.0"}
28 | "-no-topfind" {ocaml:preinstalled}
29 | ]
30 | [make "all"]
31 | [make "opt"] {ocaml:native}
32 | ]
33 | install: [
34 | [make "install"]
35 | ["install" "-m" "0755" "ocaml-stub" "%{bin}%/ocaml"] {ocaml:preinstalled}
36 | ]
37 | depends: [
38 | "ocaml" {>= "4.00.0"}
39 | "conf-m4" {build}
40 | ]
41 | extra-files: [
42 | ["ocamlfind.install" "md5=06f2c282ab52d93aa6adeeadd82a2543"]
43 | ["ocaml-stub" "md5=181f259c9e0bad9ef523e7d4abfdf87a"]
44 | ]
45 | url {
46 | src: "http://download.camlcity.org/download/findlib-1.8.1.tar.gz"
47 | checksum: "md5=18ca650982c15536616dea0e422cbd8c"
48 | mirrors: "http://download2.camlcity.org/download/findlib-1.8.1.tar.gz"
49 | }
50 | depopts: ["graphics"]
51 |
--------------------------------------------------------------------------------
/.ci/restore-build-cache.yml:
--------------------------------------------------------------------------------
1 | # Steps for restoring project cache
2 |
3 | steps:
4 | - task: DownloadBuildArtifacts@0
5 | condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
6 | displayName: '[Cache][Restore] Restore install'
7 | inputs:
8 | buildType: 'specific'
9 | project: '$(System.TeamProject)'
10 | pipeline: '$(Build.DefinitionName)'
11 | branchName: 'refs/heads/master'
12 | buildVersionToDownload: 'latestFromBranch'
13 | downloadType: 'single'
14 | artifactName: 'cache-$(Agent.OS)-install'
15 | downloadPath: '$(STAGING_DIRECTORY)'
16 | continueOnError: true
17 |
18 | - bash: 'mkdir -p $(ESY__CACHE_INSTALL_PATH)'
19 | condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
20 | displayName: '[Cache][Restore] Create cache directory'
21 |
22 | # - bash: 'cd $(ESY__NPM_ROOT) && tar -xf $(STAGING_DIRECTORY_UNIX)/cache-$(Agent.OS)-install/npm-cache.tar -C .'
23 | # continueOnError: true
24 | # condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
25 | # displayName: '[Cache][Restore] Untar npm cache directory'
26 |
27 | - bash: 'cd $(ESY__CACHE_INSTALL_PATH) && tar -xf $(STAGING_DIRECTORY_UNIX)/cache-$(Agent.OS)-install/esy-cache.tar -C .'
28 | continueOnError: true
29 | condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
30 | displayName: '[Cache][Restore] Untar esy cache directory'
31 |
32 | - bash: 'rm -rf *'
33 | continueOnError: true
34 | workingDirectory: '$(STAGING_DIRECTORY)'
35 | condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
36 | displayName: '[Cache][Restore] Clean up'
37 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "camlsynth",
3 | "version": "0.0.1",
4 | "description": "A drum machine built in reason",
5 | "license": "MIT",
6 | "revery-packager": {
7 | "bundleName": "CamlSynthApp",
8 | "bundleId": "com.kenwheeler.camlsynth",
9 | "displayName": "ML-808 CamlSynth",
10 | "mainExecutable": "App",
11 | "iconFile": "icon.icns",
12 | "darwin": {
13 | "packages": [
14 | "tar",
15 | "dmg"
16 | ],
17 | "iconFile": "icon.icns"
18 | }
19 | },
20 | "esy": {
21 | "build": "refmterr dune build -p App",
22 | "buildsInSource": "_build",
23 | "sandboxEnv": {
24 | "PKG_CONFIG_PATH": "#${PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig"
25 | }
26 | },
27 | "dependencies": {
28 | "ocaml": "~4.7.0",
29 | "revery": "0.27.0",
30 | "@opam/dune": "1.7.3",
31 | "ocaml-portaudio": "*",
32 | "@opam/reason": "*"
33 | },
34 | "resolutions": {
35 | "ocaml-portaudio": "github:bryphe/ocaml-portaudio#c849b06",
36 | "@opam/cmdliner": "1.0.2",
37 | "@opam/js_of_ocaml": "github:ocsigen/js_of_ocaml:js_of_ocaml.opam#db257ce",
38 | "@opam/js_of_ocaml-compiler": "github:ocsigen/js_of_ocaml:js_of_ocaml-compiler.opam#db257ce",
39 | "pesy": "0.4.1",
40 | "@brisk/brisk-reconciler": "github:briskml/brisk-reconciler#daa00be",
41 | "rebez": "github:jchavarri/rebez#46cbc183",
42 | "@brisk/brisk-reconciler": "github:briskml/brisk-reconciler#dd933fc",
43 | "@opam/merlin-extend": "0.4",
44 | "@opam/reason": "let-def/reason:reason.opam#bd07255b6674c3dfae8edb037b6865f8490abaff"
45 | },
46 | "scripts": {
47 | "format": "bash -c \"refmt --in-place *.re\"",
48 | "run": "esy x App"
49 | },
50 | "devDependencies": {
51 | "ocaml": "~4.7.0",
52 | "@opam/merlin": "*",
53 | "esy-macdylibbundler": "*"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Step.re:
--------------------------------------------------------------------------------
1 | open Revery;
2 | open Revery.UI;
3 | open Revery.UI.Components;
4 |
5 | let component = React.component("Step");
6 |
7 | type buttonColor =
8 | | Red
9 | | Orange
10 | | Yellow
11 | | White;
12 |
13 | let getButtonColor = color =>
14 | switch (color) {
15 | | Red => "#D71814"
16 | | Orange => "#F16F20"
17 | | Yellow => "#DFDB34"
18 | | White => "#EAE7C6"
19 | };
20 |
21 | let createElement =
22 | (~color: buttonColor, ~active: bool, ~onClick, ~children as _, ()) =>
23 | component(hooks => {
24 | let bgColor = getButtonColor(color);
25 | let wrapperStyle =
26 | Style.[
27 | backgroundColor(Color.hex(bgColor)),
28 | alignSelf(`Stretch),
29 | alignItems(`Stretch),
30 | flexGrow(1),
31 | margin(2),
32 | ];
33 |
34 | let shadowStyle =
35 | Style.[
36 | alignSelf(`Stretch),
37 | height(5),
38 | backgroundColor(Color.rgba(0., 0., 0., 0.3)),
39 | ];
40 |
41 | let secondShadowStyle =
42 | Style.[
43 | alignSelf(`Stretch),
44 | height(20),
45 | backgroundColor(Color.rgba(0., 0., 0., 0.2)),
46 | justifyContent(`Center),
47 | ];
48 |
49 | let led =
50 | Style.[
51 | backgroundColor(
52 | active === true ? Color.hex("#ff3333") : Color.hex("#330000"),
53 | ),
54 | border(
55 | ~width=2,
56 | ~color=
57 | active === true ? Color.hex("#ff3333") : Color.hex("#330000"),
58 | ),
59 | borderRadius(5.),
60 | height(10),
61 | width(10),
62 | alignSelf(`Center),
63 | ];
64 | (
65 | hooks,
66 |
67 |
68 |
69 | ,
70 | );
71 | });
--------------------------------------------------------------------------------
/esy.lock/opam/dune.1.7.3/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "opensource@janestreet.com"
3 | authors: ["Jane Street Group, LLC "]
4 | homepage: "https://github.com/ocaml/dune"
5 | bug-reports: "https://github.com/ocaml/dune/issues"
6 | dev-repo: "git+https://github.com/ocaml/dune.git"
7 | license: "MIT"
8 | depends: [
9 | "ocaml" {>= "4.02" & < "4.09.0"}
10 | "base-unix"
11 | "base-threads"
12 | ]
13 | build: [
14 | # opam 2 sets OPAM_SWITCH_PREFIX, so we don't need a hardcoded path
15 | ["ocaml" "configure.ml" "--libdir" lib] {opam-version < "2"}
16 | ["ocaml" "bootstrap.ml"]
17 | ["./boot.exe" "--release" "--subst"] {pinned}
18 | ["./boot.exe" "--release" "-j" jobs]
19 | ]
20 | conflicts: [
21 | "jbuilder" {!= "transition"}
22 | "odoc" {< "1.3.0"}
23 | ]
24 |
25 | synopsis: "Fast, portable and opinionated build system"
26 | description: """
27 | dune is a build system that was designed to simplify the release of
28 | Jane Street packages. It reads metadata from "dune" files following a
29 | very simple s-expression syntax.
30 |
31 | dune is fast, it has very low-overhead and support parallel builds on
32 | all platforms. It has no system dependencies, all you need to build
33 | dune and packages using dune is OCaml. You don't need or make or bash
34 | as long as the packages themselves don't use bash explicitly.
35 |
36 | dune supports multi-package development by simply dropping multiple
37 | repositories into the same directory.
38 |
39 | It also supports multi-context builds, such as building against
40 | several opam roots/switches simultaneously. This helps maintaining
41 | packages across several versions of OCaml and gives cross-compilation
42 | for free.
43 | """
44 | url {
45 | src: "https://github.com/ocaml/dune/releases/download/1.7.3/dune-1.7.3.tbz"
46 | checksum: "md5=644f0c1419d70b9daccac4b4e5664523"
47 | }
48 |
--------------------------------------------------------------------------------
/esy.lock/opam/ptime.0.8.5/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Daniel Bünzli "
3 | authors: ["The ptime programmers"]
4 | homepage: "https://erratique.ch/software/ptime"
5 | doc: "https://erratique.ch/software/ptime/doc"
6 | dev-repo: "git+http://erratique.ch/repos/ptime.git"
7 | bug-reports: "https://github.com/dbuenzli/ptime/issues"
8 | tags: [ "time" "posix" "system" "org:erratique" ]
9 | license: "ISC"
10 | depends: [
11 | "ocaml" {>= "4.01.0"}
12 | "ocamlfind" {build}
13 | "ocamlbuild" {build}
14 | "topkg" {build}
15 | "result"
16 | ]
17 | depopts: [ "js_of_ocaml" ]
18 | conflicts: [ "js_of_ocaml" { < "3.3.0" } ]
19 | build:[[
20 | "ocaml" "pkg/pkg.ml" "build"
21 | "--pinned" "%{pinned}%"
22 | "--with-js_of_ocaml" "%{js_of_ocaml:installed}%" ]]
23 |
24 | synopsis: """POSIX time for OCaml"""
25 | description: """\
26 |
27 | Ptime has platform independent POSIX time support in pure OCaml. It
28 | provides a type to represent a well-defined range of POSIX timestamps
29 | with picosecond precision, conversion with date-time values,
30 | conversion with [RFC 3339 timestamps][rfc3339] and pretty printing to a
31 | human-readable, locale-independent representation.
32 |
33 | The additional Ptime_clock library provides access to a system POSIX
34 | clock and to the system's current time zone offset.
35 |
36 | Ptime is not a calendar library.
37 |
38 | Ptime depends on the `result` compatibility package. Ptime_clock
39 | depends on your system library. Ptime_clock's optional JavaScript
40 | support depends on [js_of_ocaml][jsoo]. Ptime and its libraries are
41 | distributed under the ISC license.
42 |
43 | [rfc3339]: http://tools.ietf.org/html/rfc3339
44 | [jsoo]: http://ocsigen.org/js_of_ocaml/
45 | """
46 | url {
47 | archive: "https://erratique.ch/software/ptime/releases/ptime-0.8.5.tbz"
48 | checksum: "4d48055d623ecf2db792439b3e96a520"
49 | }
50 |
--------------------------------------------------------------------------------
/esy.lock/opam/lwt.4.3.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 |
3 | synopsis: "Promises and event-driven I/O"
4 |
5 | version: "4.3.1"
6 | license: "MIT"
7 | homepage: "https://github.com/ocsigen/lwt"
8 | doc: "https://ocsigen.org/lwt/manual/"
9 | bug-reports: "https://github.com/ocsigen/lwt/issues"
10 |
11 | authors: [
12 | "Jérôme Vouillon"
13 | "Jérémie Dimino"
14 | ]
15 | maintainer: [
16 | "Anton Bachin "
17 | ]
18 | dev-repo: "git+https://github.com/ocsigen/lwt.git"
19 |
20 | depends: [
21 | "cppo" {build & >= "1.1.0"}
22 | "dune" {>= "1.7.0"}
23 | "dune-configurator"
24 | "mmap" {>= "1.1.0"} # mmap is needed as long as Lwt supports OCaml < 4.06.0.
25 | "ocaml" {>= "4.02.0"}
26 | "ocplib-endian"
27 | "result" # result is needed as long as Lwt supports OCaml 4.02.
28 | "seq" # seq is needed as long as Lwt supports OCaml < 4.07.0.
29 |
30 | "bisect_ppx" {dev & >= "1.3.0"}
31 | "ocamlfind" {dev & >= "1.7.3-1"}
32 | ]
33 |
34 | depopts: [
35 | "base-threads"
36 | "base-unix"
37 | "conf-libev"
38 | ]
39 |
40 | conflicts: [
41 | "ocaml-variants" {= "4.02.1+BER"}
42 | ]
43 |
44 | post-messages: [
45 | "Lwt 5.0.0 will make some breaking changes in November 2019. See
46 | https://github.com/ocsigen/lwt/issues/584"
47 | ]
48 |
49 | build: [
50 | ["dune" "build" "-p" name "-j" jobs]
51 | ]
52 |
53 | description: "A promise is a value that may become determined in the future.
54 |
55 | Lwt provides typed, composable promises. Promises that are resolved by I/O are
56 | resolved by Lwt in parallel.
57 |
58 | Meanwhile, OCaml code, including code creating and waiting on promises, runs in
59 | a single thread by default. This reduces the need for locks or other
60 | synchronization primitives. Code can be run in parallel on an opt-in basis."
61 |
62 | url {
63 | src: "https://github.com/ocsigen/lwt/archive/4.3.1.tar.gz"
64 | checksum: "md5=926936860087c5819d6ca04241bc894a"
65 | }
66 |
--------------------------------------------------------------------------------
/esy.lock/opam/topkg.1.0.1/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | maintainer: "Daniel Bünzli "
3 | authors: ["Daniel Bünzli "]
4 | homepage: "http://erratique.ch/software/topkg"
5 | doc: "http://erratique.ch/software/topkg/doc"
6 | license: "ISC"
7 | dev-repo: "git+http://erratique.ch/repos/topkg.git"
8 | bug-reports: "https://github.com/dbuenzli/topkg/issues"
9 | tags: ["packaging" "ocamlbuild" "org:erratique"]
10 | depends: [
11 | "ocaml" {>= "4.03.0"}
12 | "ocamlfind" {build & >= "1.6.1"}
13 | "ocamlbuild" ]
14 | build: [[
15 | "ocaml" "pkg/pkg.ml" "build"
16 | "--pkg-name" name
17 | "--dev-pkg" "%{pinned}%" ]]
18 | synopsis: """The transitory OCaml software packager"""
19 | description: """\
20 |
21 | Topkg is a packager for distributing OCaml software. It provides an
22 | API to describe the files a package installs in a given build
23 | configuration and to specify information about the package's
24 | distribution, creation and publication procedures.
25 |
26 | The optional topkg-care package provides the `topkg` command line tool
27 | which helps with various aspects of a package's life cycle: creating
28 | and linting a distribution, releasing it on the WWW, publish its
29 | documentation, add it to the OCaml opam repository, etc.
30 |
31 | Topkg is distributed under the ISC license and has **no**
32 | dependencies. This is what your packages will need as a *build*
33 | dependency.
34 |
35 | Topkg-care is distributed under the ISC license it depends on
36 | [fmt][fmt], [logs][logs], [bos][bos], [cmdliner][cmdliner],
37 | [webbrowser][webbrowser] and `opam-format`.
38 |
39 | [fmt]: http://erratique.ch/software/fmt
40 | [logs]: http://erratique.ch/software/logs
41 | [bos]: http://erratique.ch/software/bos
42 | [cmdliner]: http://erratique.ch/software/cmdliner
43 | [webbrowser]: http://erratique.ch/software/webbrowser
44 | """
45 | url {
46 | archive: "http://erratique.ch/software/topkg/releases/topkg-1.0.1.tbz"
47 | checksum: "16b90e066d8972a5ef59655e7c28b3e9"
48 | }
49 |
--------------------------------------------------------------------------------
/TempoControl.re:
--------------------------------------------------------------------------------
1 | open Revery;
2 | open Revery.UI;
3 | open Revery.UI.Components;
4 |
5 | let component = React.component("Tempo");
6 |
7 | let createElement =
8 | (
9 | ~onChange,
10 | ~tempo: float,
11 | ~children as _: list(React.syntheticElement),
12 | (),
13 | ) =>
14 | component(hooks => {
15 | let wrapperStyle =
16 | Style.[
17 | alignItems(`FlexStart),
18 | flexDirection(`Row),
19 | flexGrow(1),
20 | marginLeft(5),
21 | justifyContent(`FlexStart),
22 | marginTop(-8),
23 | ];
24 |
25 | let buttonStyle =
26 | Style.[
27 | padding(2),
28 | backgroundColor(Color.hex("#EAE7C6")),
29 | width(25),
30 | marginHorizontal(4),
31 | alignItems(`Center),
32 | ];
33 |
34 | let textButtonStyle =
35 | Style.[
36 | color(Color.hex("#25231E")),
37 | fontFamily("Roboto-Regular.ttf"),
38 | fontSize(16),
39 | ];
40 |
41 | let lcdText =
42 | Style.[
43 | color(Color.hex("#ff2222")),
44 | fontFamily("digital-7.ttf"),
45 | fontSize(28),
46 | top(15),
47 | ];
48 |
49 | let lcdWrapper =
50 | Style.[
51 | backgroundColor(Color.hex("#330000")),
52 | width(50),
53 | height(35),
54 | alignItems(`Center),
55 | border(~width=2, ~color=Color.rgba(1., 1., 1., 0.25)),
56 | ];
57 |
58 | let shadow =
59 | Style.[
60 | height(5),
61 | width(25),
62 | backgroundColor(Color.hex("#9a9880")),
63 | marginHorizontal(4),
64 | ];
65 |
66 | (
67 | hooks,
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | ,
85 | );
86 | });
--------------------------------------------------------------------------------
/esy.lock/opam/merlin.3.2.2/opam:
--------------------------------------------------------------------------------
1 | opam-version: "2.0"
2 | name: "merlin"
3 | synopsis: "Installation with Opam"
4 | description: """
5 | If you have a working [Opam](https://opam.ocaml.org/) installation, Merlin is only two commands away:
6 |
7 | ```shell
8 | opam install merlin
9 | opam user-setup install
10 | ```
11 |
12 | [opam-user-setup](https://github.com/OCamlPro/opam-user-setup) takes care of configuring Emacs and Vim to make best use of your current install.
13 |
14 | You can also [configure the editor](#editor-setup) yourself, if you prefer."""
15 | maintainer: "defree@gmail.com"
16 | authors: "The Merlin team"
17 | homepage: "https://github.com/ocaml/merlin"
18 | bug-reports: "https://github.com/ocaml/merlin/issues"
19 | depends: [
20 | "ocaml" {>= "4.02.1" & < "4.08"}
21 | "dune"
22 | "ocamlfind" {>= "1.5.2"}
23 | "yojson"
24 | "craml" {with-test}
25 | ]
26 | build: [
27 | ["dune" "subst"] {pinned}
28 | ["dune" "build" "-p" name "-j" jobs]
29 | ]
30 | post-messages:
31 | """
32 | merlin installed.
33 |
34 | Quick setup for VIM
35 | -------------------
36 | Append this to your .vimrc to add merlin to vim's runtime-path:
37 | let g:opamshare = substitute(system('opam config var share'),'\\n$','','''')
38 | execute "set rtp+=" . g:opamshare . "/merlin/vim"
39 |
40 | Also run the following line in vim to index the documentation:
41 | :execute "helptags " . g:opamshare . "/merlin/vim/doc"
42 |
43 | Quick setup for EMACS
44 | -------------------
45 | Add opam emacs directory to your load-path by appending this to your .emacs:
46 | (let ((opam-share (ignore-errors (car (process-lines "opam" "config" "var" "share")))))
47 | (when (and opam-share (file-directory-p opam-share))
48 | ;; Register Merlin
49 | (add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share))
50 | (autoload 'merlin-mode "merlin" nil t nil)
51 | ;; Automatically start it in OCaml buffers
52 | (add-hook 'tuareg-mode-hook 'merlin-mode t)
53 | (add-hook 'caml-mode-hook 'merlin-mode t)
54 | ;; Use opam switch to lookup ocamlmerlin binary
55 | (setq merlin-command 'opam)))
56 |
57 | Take a look at https://github.com/ocaml/merlin for more information
58 |
59 | Quick setup with opam-user-setup
60 | --------------------------------
61 |
62 | Opam-user-setup support Merlin.
63 |
64 | $ opam user-setup install
65 |
66 | should take care of basic setup.
67 | See https://github.com/OCamlPro/opam-user-setup"""
68 | {success & !user-setup:installed}
69 | dev-repo: "git+https://github.com/ocaml/merlin.git"
70 | url {
71 | src:
72 | "https://github.com/ocaml/merlin/releases/download/v3.2.2/merlin-v3.2.2.tbz"
73 | checksum: "md5=ede35b65f8ac9c440cfade5445662c54"
74 | }
75 |
--------------------------------------------------------------------------------
/Envelope.re:
--------------------------------------------------------------------------------
1 | open Settings;
2 |
3 | type stage =
4 | | Off
5 | | Attack
6 | | Decay
7 | | Sustain
8 | | Release;
9 |
10 | type params = array(float);
11 |
12 | let stageOrder = [|Off, Attack, Decay, Sustain, Release|];
13 |
14 | type envelope = {
15 | minimumLevel: float,
16 | mutable currentStage: stage,
17 | mutable currentLevel: float,
18 | mutable multiplier: float,
19 | mutable currentSampleIndex: int,
20 | mutable nextStageSampleIndex: int,
21 | };
22 |
23 | let create = () => {
24 | minimumLevel: 0.0001,
25 | currentStage: Off,
26 | currentLevel: 0.0001,
27 | multiplier: 0.1,
28 | currentSampleIndex: 0,
29 | nextStageSampleIndex: 0,
30 | };
31 |
32 | let rec find = (~i=0, a, x) =>
33 | if (a[i] === x) {
34 | i;
35 | } else {
36 | find(~i=i + 1, a, x);
37 | };
38 |
39 | let calculateMultiplier = (env, startLevel, endLevel, lengthInSamples) => {
40 | env.multiplier =
41 | 1.0
42 | +. (log(endLevel) -. log(startLevel))
43 | /. float_of_int(lengthInSamples);
44 | };
45 |
46 | let enterStage = (env, nextStage, params) => {
47 | env.currentStage = nextStage;
48 | env.currentSampleIndex = 0;
49 | env.nextStageSampleIndex = (
50 | switch (nextStage) {
51 | | Off => 0
52 | | Sustain => 0
53 | | _ =>
54 | let idx = find(stageOrder, nextStage, ~i=0);
55 | int_of_float(params[idx] *. sampleRate);
56 | }
57 | );
58 | switch (nextStage) {
59 | | Off =>
60 | env.currentLevel = 0.;
61 | env.multiplier = 1.0;
62 | | Attack =>
63 | env.currentLevel = env.minimumLevel;
64 | calculateMultiplier(env, env.currentLevel, 1.0, env.nextStageSampleIndex);
65 | | Decay =>
66 | env.currentLevel = 1.0;
67 | calculateMultiplier(
68 | env,
69 | env.currentLevel,
70 | max(params[3], env.minimumLevel),
71 | env.nextStageSampleIndex,
72 | );
73 | | Sustain =>
74 | env.currentLevel = params[3];
75 | env.multiplier = 1.0;
76 | | Release =>
77 | calculateMultiplier(
78 | env,
79 | env.currentLevel,
80 | env.minimumLevel,
81 | env.nextStageSampleIndex,
82 | )
83 | };
84 | ();
85 | };
86 |
87 | let nextSample = (env, params) => {
88 | switch (env.currentStage) {
89 | | Off => ()
90 | | Sustain => ()
91 | | _ =>
92 | if (env.currentSampleIndex == env.nextStageSampleIndex) {
93 | let currentStageIndex = find(stageOrder, env.currentStage, ~i=0);
94 | let newStage = (currentStageIndex + 1) mod 5;
95 | enterStage(env, stageOrder[newStage], params);
96 | };
97 | env.currentLevel = env.currentLevel *. env.multiplier;
98 | env.currentSampleIndex = env.currentSampleIndex + 1;
99 | };
100 | env.currentLevel;
101 | };
--------------------------------------------------------------------------------
/TrackFx.re:
--------------------------------------------------------------------------------
1 | open Revery;
2 | open Revery.UI;
3 | open Revery.UI.Components;
4 | open AppState;
5 |
6 | let component = React.component("TrackFx");
7 |
8 | let createElement =
9 | (
10 | ~appState,
11 | ~parentDispatch,
12 | ~children as _: list(React.syntheticElement),
13 | (),
14 | ) =>
15 | component(hooks => {
16 | let settingsContainer =
17 | Style.[
18 | flexGrow(1),
19 | alignSelf(`Stretch),
20 | flexDirection(`Row),
21 | alignItems(`Center),
22 | paddingHorizontal(10),
23 | paddingVertical(5),
24 | backgroundColor(Color.hex("#888888")),
25 | marginHorizontal(20),
26 | marginBottom(20),
27 | marginTop(-10),
28 | borderRadius(5.),
29 | height(50),
30 | justifyContent(`SpaceBetween),
31 | border(~width=1, ~color=Color.hex("#888888")),
32 | ];
33 |
34 | let sliderLabelStyle =
35 | Style.[
36 | color(Colors.black),
37 | fontFamily("Roboto-Regular.ttf"),
38 | fontSize(12),
39 | ];
40 | (
41 | hooks,
42 |
43 |
44 | parentDispatch(SetAttack(v))}
46 | value={appState.tracks[appState.activeTrack].attack}
47 | maximumValue=0.5
48 | minimumValue=0.01
49 | />
50 |
51 |
52 |
53 | parentDispatch(SetDecay(v))}
55 | value={appState.tracks[appState.activeTrack].decay}
56 | maximumValue=0.99
57 | minimumValue=0.01
58 | />
59 |
60 |
61 |
62 | parentDispatch(SetSustain(v))}
64 | value={appState.tracks[appState.activeTrack].sustain}
65 | maximumValue=0.99
66 | minimumValue=0.01
67 | />
68 |
69 |
70 |
71 | parentDispatch(SetRelease(v))}
73 | value={appState.tracks[appState.activeTrack].release}
74 | maximumValue=2.0
75 | minimumValue=0.01
76 | />
77 |
78 |
79 |
80 | parentDispatch(SetFreq(v))}
82 | value={appState.tracks[appState.activeTrack].freq}
83 | maximumValue=130.81
84 | minimumValue=16.35
85 | />
86 |
87 |
88 |
89 | parentDispatch(SetGain(v))}
91 | value={appState.tracks[appState.activeTrack].gain}
92 | maximumValue=1.5
93 | minimumValue=0.0001
94 | />
95 |
96 |
97 | ,
98 | );
99 | });
--------------------------------------------------------------------------------
/SequencerPanel.re:
--------------------------------------------------------------------------------
1 | open Revery;
2 | open Revery.UI;
3 | open Revery.UI.Components;
4 | open AppState;
5 |
6 | let component = React.component("SequencerPanel");
7 |
8 | let createElement =
9 | (
10 | ~appState,
11 | ~parentDispatch,
12 | ~children as _: list(React.syntheticElement),
13 | (),
14 | ) =>
15 | component(hooks => {
16 | let updateStep = (index, ()) => {
17 | parentDispatch(UpdateStep(index));
18 | };
19 |
20 | let stepContainer =
21 | Style.[
22 | padding(5),
23 | backgroundColor(Color.hex("#25231E")),
24 | margin(5),
25 | flexGrow(1),
26 | alignSelf(`Stretch),
27 | flexDirection(`Row),
28 | alignItems(`Center),
29 | ];
30 |
31 | let stepGroup =
32 | Style.[
33 | flexGrow(1),
34 | margin(4),
35 | alignSelf(`Stretch),
36 | flexDirection(`Row),
37 | justifyContent(`SpaceBetween),
38 | ];
39 |
40 | let currentSteps = appState.tracks[appState.activeTrack].steps;
41 |
42 | (
43 | hooks,
44 |
45 |
46 | ...{Array.to_list(
47 | Array.mapi(
48 | (i, s) => {
49 | let index = 0 + i;
50 | ;
59 | },
60 | Array.sub(currentSteps, 0, 4),
61 | ),
62 | )}
63 |
64 |
65 | ...{Array.to_list(
66 | Array.mapi(
67 | (i, s) => {
68 | let index = 4 + i;
69 | ;
78 | },
79 | Array.sub(currentSteps, 4, 4),
80 | ),
81 | )}
82 |
83 |
84 | ...{Array.to_list(
85 | Array.mapi(
86 | (i, s) => {
87 | let index = 8 + i;
88 | ;
97 | },
98 | Array.sub(currentSteps, 8, 4),
99 | ),
100 | )}
101 |
102 |
103 | ...{Array.to_list(
104 | Array.mapi(
105 | (i, s) => {
106 | let index = 12 + i;
107 | ;
116 | },
117 | Array.sub(currentSteps, 12, 4),
118 | ),
119 | )}
120 |
121 | ,
122 | );
123 | });
--------------------------------------------------------------------------------
/MainUI.re:
--------------------------------------------------------------------------------
1 | open Revery;
2 | open Revery.UI;
3 | open Revery.UI.Components;
4 | open Audio;
5 | open Thread;
6 | open Portaudio;
7 | open AppState;
8 |
9 | type threadArgs = {
10 | dispatch: action => unit,
11 | appStateRef: ref(appState),
12 | };
13 |
14 | let component = React.component("DrumMachine");
15 |
16 | type streamParams =
17 | option(Portaudio.stream_parameters(float, Bigarray.float32_elt));
18 |
19 | let stream:
20 | Portaudio.stream(streamParams, streamParams, float, Bigarray.float32_elt) =
21 | getStream();
22 |
23 | let appStateRef = ref(initialAppState);
24 |
25 | let createElement = (~children as _, ()) =>
26 | component(hooks => {
27 | let (appState, dispatch, hooks) =
28 | Hooks.reducer(~initialState=initialAppState, reducer, hooks);
29 |
30 | let hooks =
31 | Hooks.effect(
32 | Always,
33 | () => {
34 | appStateRef := appState;
35 | None;
36 | },
37 | hooks,
38 | );
39 |
40 | let setActiveStep = step => {
41 | dispatch(SetActiveStep(step - 1));
42 | };
43 |
44 | let updateTrack = (track, ()) => {
45 | dispatch(SetActiveTrack(track));
46 | };
47 |
48 | let updateTempo = (tempo, ()) => {
49 | dispatch(UpdateTempo(tempo));
50 | };
51 |
52 | let playToggle = () => {
53 | if (appState.playing) {
54 | setActiveStep(0);
55 | Audio.stop(stream);
56 | dispatch(SetPlaying(false));
57 | } else {
58 | start_stream(stream);
59 | let _handle =
60 | Thread.create(
61 | ({dispatch, appStateRef}) =>
62 | Audio.play(stream, dispatch, appStateRef),
63 | {dispatch, appStateRef},
64 | );
65 | dispatch(SetPlaying(true));
66 | };
67 |
68 | ();
69 | };
70 |
71 | let containerStyle =
72 | Style.[
73 | position(`Absolute),
74 | justifyContent(`Center),
75 | alignItems(`Center),
76 | bottom(0),
77 | top(0),
78 | left(0),
79 | right(0),
80 | ];
81 |
82 | let innerStyle =
83 | Style.[
84 | flexGrow(0),
85 | alignSelf(`Stretch),
86 | flexDirection(`Row),
87 | alignItems(`FlexEnd),
88 | backgroundColor(Color.hex("#888888")),
89 | margin(20),
90 | height(100),
91 | borderRadius(5.),
92 | border(~width=1, ~color=Color.hex("#888888")),
93 | ];
94 |
95 | let headerStyle =
96 | Style.[
97 | flexDirection(`Row),
98 | justifyContent(`FlexEnd),
99 | alignSelf(`Stretch),
100 | paddingTop(20),
101 | paddingRight(20),
102 | borderBottom(~width=1, ~color=Color.hex("#F16F20")),
103 | ];
104 | let textHeaderStyle =
105 | Style.[
106 | color(Color.hex("#F16F20")),
107 | fontFamily("Roboto-Regular.ttf"),
108 | fontSize(24),
109 | ];
110 |
111 | let subTextStyle =
112 | Style.[
113 | color(Color.hex("#F16F20")),
114 | fontFamily("Roboto-Regular.ttf"),
115 | fontSize(18),
116 | marginLeft(20),
117 | marginTop(6),
118 | ];
119 |
120 | let trackStyle =
121 | Style.[
122 | alignItems(`FlexStart),
123 | flexDirection(`Row),
124 | flexGrow(1),
125 | marginLeft(20),
126 | justifyContent(`FlexStart),
127 | ];
128 |
129 | (
130 | hooks,
131 |
132 |
133 |
134 |
139 |
144 |
149 |
154 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | ,
171 | );
172 | });
--------------------------------------------------------------------------------
/Audio.re:
--------------------------------------------------------------------------------
1 | open Portaudio;
2 | open Bigarray;
3 | open Settings;
4 | open AppState;
5 |
6 | /* Time reference */
7 | let mtime = ref(0.0);
8 | /* Time increment by sample rate */
9 | let mdelta = 1. /. sampleRate;
10 | let currentSample = ref(0.0);
11 |
12 | let playing = ref(false);
13 |
14 | let passthrough = d => d;
15 |
16 | Random.self_init();
17 | Portaudio.init();
18 |
19 | let deviceId = Portaudio.get_default_output_device();
20 | let device = Portaudio.get_device_info(deviceId);
21 |
22 | /* Open and return portaudio stream */
23 | let getStream = () => {
24 | let outparam =
25 | Some({
26 | channels: 2,
27 | device: deviceId,
28 | sample_format: format_float32,
29 | latency: device.d_default_low_output_latency,
30 | });
31 |
32 | let stream = open_stream(None, outparam, sampleRate, bufferSize, []);
33 |
34 | stream;
35 | };
36 |
37 | /* Iterates through tracks and combines track/oscs with effects */
38 | let getData = (appState, mtime) =>
39 | Array.fold_left(
40 | /* Combine tracks */
41 | (acc, t) => {
42 | let d =
43 | Array.fold_left(
44 | /* Combine oscillators */
45 | (ac2, o) => {
46 | let params = [|0., t.attack, t.decay, t.sustain, t.release|];
47 | /* Add osc data */
48 | ac2
49 | +. Osc.getData(
50 | o.wave,
51 | t.freq *. o.offset,
52 | t.gain *. o.gain,
53 | mtime^,
54 | )
55 | /* Apply envelope */
56 | *. Envelope.nextSample(t.env, params);
57 | },
58 | 0.,
59 | t.osc,
60 | );
61 | /* return mixed track with filter applied */
62 | acc
63 | +. (
64 | switch (t.filter) {
65 | | None => d
66 | | Some(f) => Filter.process(f, d)
67 | }
68 | );
69 | },
70 | 0.,
71 | appState.tracks,
72 | )
73 | /* Apply master effects if enabled */
74 | |> (
75 | appState.bitcrusherEnabled
76 | ? Bitcrusher.process(appState.bitcrusher) : passthrough
77 | )
78 | |> (appState.delayEnabled ? Delay.process(appState.delay) : passthrough)
79 | |> (appState.filterEnabled ? Filter.process(appState.filter) : passthrough);
80 |
81 | /* Method that fills Bigarray with audio data */
82 | let fill_ba = (ba, dispatch, appState) => {
83 | /* time */
84 | let beatMs = 60000. /. appState.tempo;
85 | let beatS = beatMs /. 1000.;
86 | let stepSec = beatS /. 4.;
87 | let step = floor(stepSec *. sampleRate);
88 |
89 | /* Fill the buffer */
90 | for (i in 0 to bufferSize - 1) {
91 | /* if the step matches */
92 | if (mod_float(currentSample^, step) == 0.0) {
93 | /* get current sequencer step for time */
94 | let stepIndex = int_of_float(currentSample^ /. step);
95 |
96 | /* if the matched step is active, start envelope */
97 | Array.iter(
98 | t => {
99 | let params = [|0., t.attack, t.decay, t.sustain, t.release|];
100 | if (stepIndex !== 0 && t.steps[stepIndex - 1] === 1) {
101 | Envelope.enterStage(t.env, Attack, params);
102 | };
103 | },
104 | appState.tracks,
105 | );
106 | dispatch(SetActiveStep(stepIndex));
107 | };
108 |
109 | /* Reset the sequencer step to 0 */
110 | if (currentSample^ > step *. 16.) {
111 | currentSample := 0.0;
112 | };
113 |
114 | /* Reset mtime if it gets too big */
115 | if (mtime^ > Float.max_float) {
116 | mtime := 0.;
117 | };
118 |
119 | /* Reset envelope */
120 | Array.iter(
121 | t => {
122 | let params = [|0., t.attack, t.decay, t.sustain, t.release|];
123 | if (t.env.currentStage === Sustain) {
124 | Envelope.enterStage(t.env, Release, params);
125 | };
126 | },
127 | appState.tracks,
128 | );
129 |
130 | /* Get Audio Data */
131 | let data = getData(appState, mtime);
132 |
133 | /* Increment time by sample */
134 | mtime := mtime^ +. mdelta;
135 |
136 | /* Increment sample counter */
137 | currentSample := currentSample^ +. 1.0;
138 |
139 | /* Get stereo channel array indexes */
140 | let left = [|2 * i|];
141 | let right = [|2 * i + 1|];
142 |
143 | /* Set the data at the index */
144 | Genarray.set(ba, left, data);
145 | Genarray.set(ba, right, data);
146 | };
147 | };
148 |
149 | /*Stop portaudio stream */
150 | let stop = stream => {
151 | playing := false;
152 | stop_stream(stream);
153 | };
154 | /* Create data array and begin loop to fill stream */
155 | let play = (stream, dispatch, appStateRef) => {
156 | mtime := 0.;
157 | playing := true;
158 | currentSample := 0.;
159 | /* Create array relative to buffer size */
160 | let dims = [|2 * bufferSize|];
161 | let ba = Genarray.create(float32, c_layout, dims);
162 | /* Fill the array on loop and write */
163 | while (playing^ === true) {
164 | fill_ba(ba, dispatch, appStateRef^);
165 | Portaudio.write_stream_ba(stream, ba, 0, bufferSize);
166 | };
167 | ();
168 | };
--------------------------------------------------------------------------------
/Knob.re:
--------------------------------------------------------------------------------
1 | /*
2 | * Knob.re
3 | *
4 | * Simple component, based on the component from Revery / react-native
5 | * Based on: https://github.com/revery-ui/revery/blob/master/src/UI_Components/Slider.re
6 | */
7 |
8 | open Revery;
9 | open Revery.Math;
10 | open Revery.UI;
11 | open Revery.UI.Components;
12 |
13 | type clickFunction = unit => unit;
14 | let noop = () => ();
15 |
16 | type valueChangedFunction = float => unit;
17 | let noopValueChanged = _f => ();
18 |
19 | let component = React.component("Knob");
20 |
21 | let createElement =
22 | (
23 | ~children as _,
24 | ~onValueChanged=noopValueChanged,
25 | ~minimumValue=0.,
26 | ~maximumValue=1.,
27 | ~value=0.,
28 | ~size=64,
29 | (),
30 | ) =>
31 | component(hooks => {
32 | // We keep a reference to the 'slider' bounding box for calculations with the mouse position
33 | // This is kind of a carry-over from Revery's slider that I ported over - it's important
34 | // to have the bounds for a slider, because you want to match up the mouse position with
35 | // the boundaries. We could get away with less here - just knowing the start position
36 | // where the 'mousedown' happened, and calculated based on the latest mouse position would
37 | // be sufficient.
38 | let (slideRef, setSlideRefOption, hooks) = Hooks.state(None, hooks);
39 |
40 | // Active is used so we can show some custom UI while the
41 | let (isActive, setActive, hooks) = Hooks.state(false, hooks);
42 |
43 | // Initial value is used to detect if the 'value' parameter ever changes
44 | let (initialValue, setInitialValue, hooks) = Hooks.state(value, hooks);
45 |
46 | // [v] is the actual value of the slider
47 | let (v, setV, hooks) = Hooks.state(value, hooks);
48 |
49 | /*
50 | * If the slider value is updated (controlled),
51 | * it should override whatever previous value was set
52 | */
53 | let v =
54 | if (value != initialValue) {
55 | setInitialValue(value);
56 | setV(value);
57 | value;
58 | } else {
59 | v;
60 | };
61 |
62 | let setSlideRef = r => setSlideRefOption(Some(r));
63 |
64 | // When the mouse moves, let's figure out the new slider value
65 | let sliderUpdate = (w, startPosition, endPosition, mouseX, mouseY) => {
66 | let mousePosition = mouseY;
67 | let thumbPosition =
68 | clamp(mousePosition, startPosition, endPosition) -. startPosition;
69 |
70 | let normalizedValue =
71 | thumbPosition /. w *. (maximumValue -. minimumValue) +. minimumValue;
72 | setV(normalizedValue);
73 | onValueChanged(normalizedValue);
74 | };
75 |
76 | let sliderComplete = () => {
77 | setActive(false);
78 | };
79 |
80 | // We had an 'Always' hook that sets mouse capture - meaning we takeover
81 | // handling the mouse movement / mouseup events while the gesture is in progress
82 | // (until 'sliderComplete' is called, or the component unmounts).
83 | let hooks =
84 | Hooks.effect(
85 | Always,
86 | () => {
87 | let isCaptured = isActive;
88 |
89 | if (isCaptured) {
90 | switch (slideRef) {
91 | | Some(slider) =>
92 | let w = float_of_int(size);
93 | let sliderDimensions: BoundingBox2d.t = slider#getBoundingBox();
94 |
95 | let startPosition = Vec2.get_y(sliderDimensions.min);
96 | let endPosition = startPosition +. w;
97 |
98 | Mouse.setCapture(
99 | ~onMouseMove=
100 | evt =>
101 | sliderUpdate(
102 | w,
103 | startPosition,
104 | endPosition,
105 | evt.mouseX,
106 | evt.mouseY,
107 | ),
108 | ~onMouseUp=_evt => sliderComplete(),
109 | (),
110 | );
111 | | _ => ()
112 | };
113 | };
114 |
115 | Some(
116 | () =>
117 | if (isCaptured) {
118 | Mouse.releaseCapture();
119 | },
120 | );
121 | },
122 | hooks,
123 | );
124 |
125 | let onMouseDown = (evt: NodeEvents.mouseButtonEventParams) =>
126 | switch (slideRef) {
127 | | Some(slider) =>
128 | let w = float_of_int(size);
129 | let sliderDimensions: BoundingBox2d.t = slider#getBoundingBox();
130 |
131 | let startPosition = Vec2.get_y(sliderDimensions.min);
132 | let endPosition = startPosition +. w;
133 |
134 | sliderUpdate(w, startPosition, endPosition, evt.mouseX, evt.mouseY);
135 | setActive(true);
136 | | _ => ()
137 | };
138 |
139 | let sliderOpacity = isActive ? 1.0 : 0.8;
140 |
141 | let normalizedValue =
142 | (v -. minimumValue) /. (maximumValue -. minimumValue);
143 |
144 | let style =
145 | Style.[width(size), height(size), cursor(MouseCursors.pointer)];
146 |
147 | let width = size;
148 | let height = size;
149 |
150 | let sideThumbSize = 2;
151 | let sideThumbPosition =
152 | int_of_float(float_of_int(size - sideThumbSize) *. normalizedValue);
153 |
154 | // We'll show a helper slider while the slide-gesture is active
155 | let sideSlider =
156 |
157 |
158 |
159 |
160 |
161 | ;
162 |
163 | let sliderVisualization = isActive ? sideSlider : React.empty;
164 |
165 | (
166 | hooks,
167 |
168 | setSlideRef(r)}>
169 |
170 |
171 |
172 |
173 |
174 |
186 |
187 | sliderVisualization
188 |
189 |
190 | ,
191 | );
192 | });
--------------------------------------------------------------------------------
/AppState.re:
--------------------------------------------------------------------------------
1 | open Settings;
2 |
3 | type tone = {
4 | wave: Osc.wave,
5 | offset: float,
6 | gain: float,
7 | };
8 |
9 | type track = {
10 | steps: array(int),
11 | osc: array(tone),
12 | env: Envelope.envelope,
13 | mutable freq: float,
14 | mutable gain: float,
15 | mutable attack: float,
16 | mutable decay: float,
17 | mutable sustain: float,
18 | mutable release: float,
19 | filter: option(Filter.filter),
20 | };
21 |
22 | type appState = {
23 | playing: bool,
24 | tempo: float,
25 | activeStep: int,
26 | tracks: array(track),
27 | activeTrack: int,
28 | bitcrusherEnabled: bool,
29 | delayEnabled: bool,
30 | filterEnabled: bool,
31 | bitcrusher: Bitcrusher.bitcrusher,
32 | mutable filter: Filter.filter,
33 | delay: Delay.delay,
34 | };
35 |
36 | type action =
37 | | SetPlaying(bool)
38 | | SetActiveStep(int)
39 | | UpdateStep(int)
40 | | UpdateTempo(float)
41 | | SetActiveTrack(int)
42 | | SetGain(float)
43 | | SetFreq(float)
44 | | SetAttack(float)
45 | | SetDecay(float)
46 | | SetSustain(float)
47 | | SetRelease(float)
48 | | ToggleBitcrusherEnabled(bool)
49 | | ToggleDelayEnabled(bool)
50 | | ToggleFilterEnabled(bool)
51 | | SetBitcrusherBitrate(float)
52 | | SetBitcrusherSampling(int)
53 | | SetFilter(Filter.filter)
54 | | SetDelayDuration(float)
55 | | SetDelayGain(float);
56 |
57 | let reducer = (action, state) =>
58 | switch (action) {
59 | | SetPlaying(p) => {...state, playing: p}
60 | | SetActiveStep(n) => {...state, activeStep: n}
61 | | SetActiveTrack(n) => {...state, activeTrack: n}
62 | | UpdateTempo(n) => {...state, tempo: n}
63 | | ToggleBitcrusherEnabled(e) => {...state, bitcrusherEnabled: e}
64 | | ToggleDelayEnabled(e) => {...state, delayEnabled: e}
65 | | ToggleFilterEnabled(e) => {...state, filterEnabled: e}
66 | | SetBitcrusherBitrate(b) => {
67 | ...state,
68 | bitcrusher: {
69 | ...state.bitcrusher,
70 | bitDepth: floor(b),
71 | },
72 | }
73 | | SetBitcrusherSampling(b) => {
74 | ...state,
75 | bitcrusher: {
76 | ...state.bitcrusher,
77 | downSampling: b,
78 | },
79 | }
80 | | SetDelayDuration(d) => {
81 | ...state,
82 | delay: {
83 | ...state.delay,
84 | duration: d,
85 | },
86 | }
87 | | SetDelayGain(d) => {
88 | ...state,
89 | delay: {
90 | ...state.delay,
91 | gain: d,
92 | },
93 | }
94 | | SetFilter(c) => {...state, filter: c}
95 | | SetGain(n) =>
96 | let t = Array.copy(state.tracks);
97 | let s = t[state.activeTrack];
98 | s.gain = n;
99 | {...state, tracks: t};
100 | | SetFreq(n) =>
101 | let t = Array.copy(state.tracks);
102 | let s = t[state.activeTrack];
103 | s.freq = n;
104 | {...state, tracks: t};
105 | | SetSustain(n) =>
106 | let t = Array.copy(state.tracks);
107 | let s = t[state.activeTrack];
108 | s.sustain = n;
109 | {...state, tracks: t};
110 | | SetAttack(n) =>
111 | let t = Array.copy(state.tracks);
112 | let s = t[state.activeTrack];
113 | s.attack = n;
114 | {...state, tracks: t};
115 | | SetDecay(n) =>
116 | let t = Array.copy(state.tracks);
117 | let s = t[state.activeTrack];
118 | s.decay = n;
119 | {...state, tracks: t};
120 | | SetRelease(n) =>
121 | let t = Array.copy(state.tracks);
122 | let s = t[state.activeTrack];
123 | s.release = n;
124 | {...state, tracks: t};
125 | | UpdateStep(u) =>
126 | let t = Array.copy(state.tracks);
127 | let s = t[state.activeTrack].steps;
128 | s[u] = s[u] === 1 ? 0 : 1;
129 | {...state, tracks: t};
130 | };
131 |
132 | let initialAppState = {
133 | playing: false,
134 | tempo: 90.,
135 | activeStep: (-1),
136 | activeTrack: 0,
137 | bitcrusherEnabled: false,
138 | delayEnabled: false,
139 | filterEnabled: false,
140 | bitcrusher: Bitcrusher.create(16., 12),
141 | delay: Delay.create(0.25, 0.25),
142 | filter: Filter.create(Filter.LowPass, 4000. /. sampleRate, 1.0, 0.0),
143 | tracks: [|
144 | {
145 | osc: [|{wave: Osc.Sine, offset: 1.0, gain: 1.0}|],
146 | freq: 21.83,
147 | gain: 1.0,
148 | attack: 0.01,
149 | decay: 0.2,
150 | sustain: 0.1,
151 | release: 0.25,
152 | env: Envelope.create(),
153 | steps: [|1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0|],
154 | filter:
155 | Some(Filter.create(Filter.LowPass, 3000. /. sampleRate, 1.0, 0.0)),
156 | },
157 | {
158 | osc: [|
159 | {wave: Osc.Sine, offset: (-1.0), gain: 1.0},
160 | {wave: Osc.Noise, offset: 1.0, gain: 0.75},
161 | |],
162 | freq: 65.,
163 | gain: 0.75,
164 | attack: 0.01,
165 | decay: 0.1,
166 | sustain: 0.1,
167 | release: 0.5,
168 | env: Envelope.create(),
169 | steps: [|0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0|],
170 | filter:
171 | Some(Filter.create(Filter.LowPass, 9000. /. sampleRate, 1.0, 0.0)),
172 | },
173 | {
174 | osc: [|
175 | {wave: Osc.Square, offset: 2., gain: 0.5},
176 | {wave: Osc.Square, offset: 3., gain: 0.5},
177 | {wave: Osc.Square, offset: 4.16, gain: 0.5},
178 | {wave: Osc.Square, offset: 5.43, gain: 0.5},
179 | {wave: Osc.Square, offset: 6.79, gain: 0.5},
180 | {wave: Osc.Square, offset: 8.21, gain: 0.5},
181 | |],
182 | freq: 55.,
183 | gain: 0.25,
184 | attack: 0.01,
185 | decay: 0.2,
186 | sustain: 0.1,
187 | release: 0.9,
188 | env: Envelope.create(),
189 | steps: [|0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0|],
190 | filter:
191 | Some(Filter.create(Filter.HighPass, 8000. /. sampleRate, 1.0, 0.0)),
192 | },
193 | {
194 | osc: [|
195 | {wave: Osc.Square, offset: 6.0, gain: 0.25},
196 | {wave: Osc.Saw, offset: 4.0, gain: 0.25},
197 | |],
198 | freq: 130.81,
199 | gain: 0.25,
200 | attack: 0.01,
201 | decay: 0.05,
202 | sustain: 0.1,
203 | release: 1.0,
204 | env: Envelope.create(),
205 | steps: [|0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0|],
206 | filter:
207 | Some(Filter.create(Filter.LowPass, 5000. /. sampleRate, 1.0, 0.0)),
208 | },
209 | {
210 | osc: [|
211 | {wave: Osc.Noise, offset: 1.0, gain: 0.05},
212 | {wave: Osc.Sine, offset: 3.0, gain: 0.75},
213 | |],
214 | freq: 130.81,
215 | gain: 0.5,
216 | attack: 0.01,
217 | decay: 0.05,
218 | sustain: 0.1,
219 | release: 0.5,
220 | env: Envelope.create(),
221 | steps: [|0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0|],
222 | filter:
223 | Some(Filter.create(Filter.HighPass, 1200. /. sampleRate, 1.0, 0.0)),
224 | },
225 | |],
226 | };
--------------------------------------------------------------------------------
/MasterFx.re:
--------------------------------------------------------------------------------
1 | open Revery;
2 | open Revery.UI;
3 | open Revery.UI.Components;
4 | open AppState;
5 | open Settings;
6 | let component = React.component("MasterFx");
7 |
8 | let createElement =
9 | (
10 | ~appState,
11 | ~parentDispatch,
12 | ~children as _: list(React.syntheticElement),
13 | (),
14 | ) =>
15 | component(hooks => {
16 | let fxContainer =
17 | Style.[
18 | flexGrow(1),
19 | alignSelf(`Stretch),
20 | flexDirection(`Column),
21 | alignItems(`Center),
22 | paddingHorizontal(10),
23 | paddingVertical(5),
24 | backgroundColor(Color.hex("#888888")),
25 | marginHorizontal(20),
26 | marginBottom(20),
27 | marginTop(-10),
28 | borderRadius(5.),
29 | height(120),
30 | justifyContent(`FlexStart),
31 | border(~width=1, ~color=Color.hex("#888888")),
32 | ];
33 | let checkboxStyle =
34 | Style.[
35 | border(~width=2, ~color=Color.hex("#EAE7C6")),
36 | height(15),
37 | width(15),
38 | marginRight(4),
39 | ];
40 |
41 | let fxHeaderStyle =
42 | Style.[
43 | color(Colors.black),
44 | fontFamily("Roboto-Regular.ttf"),
45 | fontSize(12),
46 | ];
47 |
48 | let fxLabelStyle =
49 | Style.[
50 | color(Colors.black),
51 | fontFamily("Roboto-Regular.ttf"),
52 | fontSize(12),
53 | ];
54 |
55 | let panelsStyle =
56 | Style.[
57 | flexGrow(1),
58 | marginHorizontal(4),
59 | alignSelf(`Stretch),
60 | flexDirection(`Row),
61 | justifyContent(`SpaceBetween),
62 | ];
63 |
64 | let panelStyle =
65 | Style.[
66 | flexGrow(1),
67 | alignSelf(`Stretch),
68 | flexDirection(`Column),
69 | justifyContent(`SpaceBetween),
70 | marginHorizontal(4),
71 | ];
72 |
73 | let inputWrapper =
74 | Style.[
75 | flexDirection(`Row),
76 | flexGrow(1),
77 | justifyContent(`FlexStart),
78 | alignItems(`Center),
79 | marginBottom(4),
80 | ];
81 |
82 | let paramWrapper =
83 | Style.[
84 | flexDirection(`Row),
85 | flexGrow(1),
86 | alignItems(`Center),
87 | justifyContent(`SpaceAround),
88 | backgroundColor(Color.rgba(0., 0., 0., 0.25)),
89 | border(~width=2, ~color=Color.rgba(0., 0., 0., 0.25)),
90 | borderRadius(4.),
91 | padding(4),
92 | ];
93 |
94 | let sliderLabelStyle =
95 | Style.[
96 | color(Colors.black),
97 | fontFamily("Roboto-Regular.ttf"),
98 | fontSize(12),
99 | ];
100 | (
101 | hooks,
102 |
103 |
104 |
105 |
106 |
107 |
110 | parentDispatch(
111 | ToggleBitcrusherEnabled(!appState.bitcrusherEnabled),
112 | )
113 | }
114 | checkedColor={Color.hex("#F16F20")}
115 | style=checkboxStyle
116 | />
117 |
118 |
119 |
120 |
121 |
123 | parentDispatch(SetBitcrusherBitrate(v))
124 | }
125 | value={appState.bitcrusher.bitDepth}
126 | maximumValue=32.
127 | minimumValue=2.
128 | />
129 |
130 |
131 |
132 |
133 |
134 |
136 | parentDispatch(SetBitcrusherSampling(int_of_float(v)))
137 | }
138 | value={float_of_int(appState.bitcrusher.downSampling)}
139 | maximumValue=64.
140 | minimumValue=1.
141 | />
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
153 | parentDispatch(ToggleDelayEnabled(!appState.delayEnabled))
154 | }
155 | checkedColor={Color.hex("#F16F20")}
156 | style=checkboxStyle
157 | />
158 |
159 |
160 |
161 |
162 | parentDispatch(SetDelayDuration(v))}
164 | value={appState.delay.duration}
165 | maximumValue=0.5
166 | minimumValue=0.01
167 | />
168 |
169 |
170 |
171 | parentDispatch(SetDelayGain(v))}
173 | value={appState.delay.gain}
174 | maximumValue=0.9
175 | minimumValue=0.01
176 | />
177 |
178 |
179 |
180 |
181 |
182 |
183 |
186 | parentDispatch(
187 | ToggleFilterEnabled(!appState.filterEnabled),
188 | )
189 | }
190 | checkedColor={Color.hex("#F16F20")}
191 | style=checkboxStyle
192 | />
193 |
194 |
195 |
196 |
197 |
199 | parentDispatch(
200 | SetFilter(
201 | Filter.create(
202 | appState.filter.mode,
203 | v /. sampleRate,
204 | 1.0,
205 | 0.0,
206 | ),
207 | ),
208 | )
209 | }
210 | maximumValue=20000.
211 | minimumValue=20.
212 | />
213 |
214 |
215 |
216 |
217 |
218 |
219 |
222 | parentDispatch(
223 | SetFilter(
224 | Filter.create(
225 | Filter.LowPass,
226 | appState.filter.fc,
227 | 1.0,
228 | 0.0,
229 | ),
230 | ),
231 | )
232 | }
233 | checkedColor={Color.hex("#F16F20")}
234 | style=checkboxStyle
235 | />
236 |
237 |
238 |
239 |
242 | parentDispatch(
243 | SetFilter(
244 | Filter.create(
245 | Filter.HighPass,
246 | appState.filter.fc,
247 | 0.707,
248 | 0.0,
249 | ),
250 | ),
251 | )
252 | }
253 | checkedColor={Color.hex("#F16F20")}
254 | style=checkboxStyle
255 | />
256 |
257 |
258 |
259 |
260 |
261 |
262 | ,
263 | );
264 | });
--------------------------------------------------------------------------------
/esy.lock/overrides/opam__s__ocamlfind_opam__c__1.8.1_opam_override/files/findlib-1.8.1.patch:
--------------------------------------------------------------------------------
1 | --- ./Makefile
2 | +++ ./Makefile
3 | @@ -57,16 +57,16 @@
4 | cat findlib.conf.in | \
5 | $(SH) tools/patch '@SITELIB@' '$(OCAML_SITELIB)' >findlib.conf
6 | if ./tools/cmd_from_same_dir ocamlc; then \
7 | - echo 'ocamlc="ocamlc.opt"' >>findlib.conf; \
8 | + echo 'ocamlc="ocamlc.opt$(EXEC_SUFFIX)"' >>findlib.conf; \
9 | fi
10 | if ./tools/cmd_from_same_dir ocamlopt; then \
11 | - echo 'ocamlopt="ocamlopt.opt"' >>findlib.conf; \
12 | + echo 'ocamlopt="ocamlopt.opt$(EXEC_SUFFIX)"' >>findlib.conf; \
13 | fi
14 | if ./tools/cmd_from_same_dir ocamldep; then \
15 | - echo 'ocamldep="ocamldep.opt"' >>findlib.conf; \
16 | + echo 'ocamldep="ocamldep.opt$(EXEC_SUFFIX)"' >>findlib.conf; \
17 | fi
18 | if ./tools/cmd_from_same_dir ocamldoc; then \
19 | - echo 'ocamldoc="ocamldoc.opt"' >>findlib.conf; \
20 | + echo 'ocamldoc="ocamldoc.opt$(EXEC_SUFFIX)"' >>findlib.conf; \
21 | fi
22 |
23 | .PHONY: install-doc
24 | --- ./src/findlib/findlib_config.mlp
25 | +++ ./src/findlib/findlib_config.mlp
26 | @@ -24,3 +24,5 @@
27 | | "MacOS" -> "" (* don't know *)
28 | | _ -> failwith "Unknown Sys.os_type"
29 | ;;
30 | +
31 | +let exec_suffix = "@EXEC_SUFFIX@";;
32 | --- ./src/findlib/findlib.ml
33 | +++ ./src/findlib/findlib.ml
34 | @@ -28,15 +28,20 @@
35 | let conf_ldconf = ref "";;
36 | let conf_ignore_dups_in = ref ([] : string list);;
37 |
38 | -let ocamlc_default = "ocamlc";;
39 | -let ocamlopt_default = "ocamlopt";;
40 | -let ocamlcp_default = "ocamlcp";;
41 | -let ocamloptp_default = "ocamloptp";;
42 | -let ocamlmklib_default = "ocamlmklib";;
43 | -let ocamlmktop_default = "ocamlmktop";;
44 | -let ocamldep_default = "ocamldep";;
45 | -let ocamlbrowser_default = "ocamlbrowser";;
46 | -let ocamldoc_default = "ocamldoc";;
47 | +let add_exec str =
48 | + match Findlib_config.exec_suffix with
49 | + | "" -> str
50 | + | a -> str ^ a ;;
51 | +let ocamlc_default = add_exec "ocamlc";;
52 | +let ocamlopt_default = add_exec "ocamlopt";;
53 | +let ocamlcp_default = add_exec "ocamlcp";;
54 | +let ocamloptp_default = add_exec "ocamloptp";;
55 | +let ocamlmklib_default = add_exec "ocamlmklib";;
56 | +let ocamlmktop_default = add_exec "ocamlmktop";;
57 | +let ocamldep_default = add_exec "ocamldep";;
58 | +let ocamlbrowser_default = add_exec "ocamlbrowser";;
59 | +let ocamldoc_default = add_exec "ocamldoc";;
60 | +
61 |
62 |
63 | let init_manually
64 | --- ./src/findlib/fl_package_base.ml
65 | +++ ./src/findlib/fl_package_base.ml
66 | @@ -133,7 +133,15 @@
67 | List.find (fun def -> def.def_var = "exists_if") p.package_defs in
68 | let files = Fl_split.in_words def.def_value in
69 | List.exists
70 | - (fun file -> Sys.file_exists (Filename.concat d' file))
71 | + (fun file ->
72 | + let fln = Filename.concat d' file in
73 | + let e = Sys.file_exists fln in
74 | + (* necessary for ppx executables *)
75 | + if e || Sys.os_type <> "Win32" || Filename.check_suffix fln ".exe" then
76 | + e
77 | + else
78 | + Sys.file_exists (fln ^ ".exe")
79 | + )
80 | files
81 | with Not_found -> true in
82 |
83 | --- ./src/findlib/fl_split.ml
84 | +++ ./src/findlib/fl_split.ml
85 | @@ -126,10 +126,17 @@
86 | | '/' | '\\' -> true
87 | | _ -> false in
88 | let norm_dir_win() =
89 | - if l >= 1 && s.[0] = '/' then
90 | - Buffer.add_char b '\\' else Buffer.add_char b s.[0];
91 | - if l >= 2 && s.[1] = '/' then
92 | - Buffer.add_char b '\\' else Buffer.add_char b s.[1];
93 | + if l >= 1 then (
94 | + if s.[0] = '/' then
95 | + Buffer.add_char b '\\'
96 | + else
97 | + Buffer.add_char b s.[0] ;
98 | + if l >= 2 then
99 | + if s.[1] = '/' then
100 | + Buffer.add_char b '\\'
101 | + else
102 | + Buffer.add_char b s.[1];
103 | + );
104 | for k = 2 to l - 1 do
105 | let c = s.[k] in
106 | if is_slash c then (
107 | --- ./src/findlib/frontend.ml
108 | +++ ./src/findlib/frontend.ml
109 | @@ -31,10 +31,18 @@
110 | else
111 | Sys_error (arg ^ ": " ^ Unix.error_message code)
112 |
113 | +let is_win = Sys.os_type = "Win32"
114 | +
115 | +let () =
116 | + match Findlib_config.system with
117 | + | "win32" | "win64" | "mingw" | "cygwin" | "mingw64" | "cygwin64" ->
118 | + (try set_binary_mode_out stdout true with _ -> ());
119 | + (try set_binary_mode_out stderr true with _ -> ());
120 | + | _ -> ()
121 |
122 | let slashify s =
123 | match Findlib_config.system with
124 | - | "mingw" | "mingw64" | "cygwin" ->
125 | + | "win32" | "win64" | "mingw" | "cygwin" | "mingw64" | "cygwin64" ->
126 | let b = Buffer.create 80 in
127 | String.iter
128 | (function
129 | @@ -49,7 +57,7 @@
130 |
131 | let out_path ?(prefix="") s =
132 | match Findlib_config.system with
133 | - | "mingw" | "mingw64" | "cygwin" ->
134 | + | "win32" | "win64" | "mingw" | "mingw64" | "cygwin" ->
135 | let u = slashify s in
136 | prefix ^
137 | (if String.contains u ' ' then
138 | @@ -273,11 +281,9 @@
139 |
140 |
141 | let identify_dir d =
142 | - match Sys.os_type with
143 | - | "Win32" ->
144 | - failwith "identify_dir" (* not available *)
145 | - | _ ->
146 | - let s = Unix.stat d in
147 | + if is_win then
148 | + failwith "identify_dir"; (* not available *)
149 | + let s = Unix.stat d in
150 | (s.Unix.st_dev, s.Unix.st_ino)
151 | ;;
152 |
153 | @@ -459,6 +465,96 @@
154 | )
155 | packages
156 |
157 | +let rewrite_cmd s =
158 | + if s = "" || not is_win then
159 | + s
160 | + else
161 | + let s =
162 | + let l = String.length s in
163 | + let b = Buffer.create l in
164 | + for i = 0 to pred l do
165 | + match s.[i] with
166 | + | '/' -> Buffer.add_char b '\\'
167 | + | x -> Buffer.add_char b x
168 | + done;
169 | + Buffer.contents b
170 | + in
171 | + if (Filename.is_implicit s && String.contains s '\\' = false) ||
172 | + Filename.check_suffix (String.lowercase s) ".exe" then
173 | + s
174 | + else
175 | + let s' = s ^ ".exe" in
176 | + if Sys.file_exists s' then
177 | + s'
178 | + else
179 | + s
180 | +
181 | +let rewrite_cmd s =
182 | + if s = "" || not is_win then s else
183 | + let s =
184 | + let l = String.length s in
185 | + let b = Buffer.create l in
186 | + for i = 0 to pred l do
187 | + match s.[i] with
188 | + | '/' -> Buffer.add_char b '\\'
189 | + | x -> Buffer.add_char b x
190 | + done;
191 | + Buffer.contents b
192 | + in
193 | + if (Filename.is_implicit s && String.contains s '\\' = false) ||
194 | + Filename.check_suffix (String.lowercase s) ".exe" then
195 | + s
196 | + else
197 | + let s' = s ^ ".exe" in
198 | + if Sys.file_exists s' then
199 | + s'
200 | + else
201 | + s
202 | +
203 | +let rewrite_pp cmd =
204 | + if not is_win then cmd else
205 | + let module T = struct exception Keep end in
206 | + let is_whitespace = function
207 | + | ' ' | '\011' | '\012' | '\n' | '\r' | '\t' -> true
208 | + | _ -> false in
209 | + (* characters that triggers special behaviour (cmd.exe, not unix shell) *)
210 | + let is_unsafe_char = function
211 | + | '(' | ')' | '%' | '!' | '^' | '<' | '>' | '&' -> true
212 | + | _ -> false in
213 | + let len = String.length cmd in
214 | + let buf = Buffer.create (len + 4) in
215 | + let buf_cmd = Buffer.create len in
216 | + let rec iter_ws i =
217 | + if i >= len then () else
218 | + let cur = cmd.[i] in
219 | + if is_whitespace cur then (
220 | + Buffer.add_char buf cur;
221 | + iter_ws (succ i)
222 | + )
223 | + else
224 | + iter_cmd i
225 | + and iter_cmd i =
226 | + if i >= len then add_buf_cmd () else
227 | + let cur = cmd.[i] in
228 | + if is_unsafe_char cur || cur = '"' || cur = '\'' then
229 | + raise T.Keep;
230 | + if is_whitespace cur then (
231 | + add_buf_cmd ();
232 | + Buffer.add_substring buf cmd i (len - i)
233 | + )
234 | + else (
235 | + Buffer.add_char buf_cmd cur;
236 | + iter_cmd (succ i)
237 | + )
238 | + and add_buf_cmd () =
239 | + if Buffer.length buf_cmd > 0 then
240 | + Buffer.add_string buf (rewrite_cmd (Buffer.contents buf_cmd))
241 | + in
242 | + try
243 | + iter_ws 0;
244 | + Buffer.contents buf
245 | + with
246 | + | T.Keep -> cmd
247 |
248 | let process_pp_spec syntax_preds packages pp_opts =
249 | (* Returns: pp_command *)
250 | @@ -549,7 +645,7 @@
251 | None -> []
252 | | Some cmd ->
253 | ["-pp";
254 | - cmd ^ " " ^
255 | + (rewrite_cmd cmd) ^ " " ^
256 | String.concat " " (List.map Filename.quote pp_i_options) ^ " " ^
257 | String.concat " " (List.map Filename.quote pp_archives) ^ " " ^
258 | String.concat " " (List.map Filename.quote pp_opts)]
259 | @@ -625,9 +721,11 @@
260 | in
261 | try
262 | let preprocessor =
263 | + rewrite_cmd (
264 | resolve_path
265 | ~base ~explicit:true
266 | - (package_property predicates pname "ppx") in
267 | + (package_property predicates pname "ppx") )
268 | + in
269 | ["-ppx"; String.concat " " (preprocessor :: options)]
270 | with Not_found -> []
271 | )
272 | @@ -895,6 +993,14 @@
273 | switch (e.g. -L instead of -L )
274 | *)
275 |
276 | +(* We may need to remove files on which we do not have complete control.
277 | + On Windows, removing a read-only file fails so try to change the
278 | + mode of the file first. *)
279 | +let remove_file fname =
280 | + try Sys.remove fname
281 | + with Sys_error _ when is_win ->
282 | + (try Unix.chmod fname 0o666 with Unix.Unix_error _ -> ());
283 | + Sys.remove fname
284 |
285 | let ocamlc which () =
286 |
287 | @@ -1022,9 +1128,12 @@
288 |
289 | "-intf",
290 | Arg.String (fun s -> pass_files := !pass_files @ [ Intf(slashify s) ]);
291 | -
292 | +
293 | "-pp",
294 | - Arg.String (fun s -> pp_specified := true; add_spec_fn "-pp" s);
295 | + Arg.String (fun s -> pp_specified := true; add_spec_fn "-pp" (rewrite_pp s));
296 | +
297 | + "-ppx",
298 | + Arg.String (fun s -> add_spec_fn "-ppx" (rewrite_pp s));
299 |
300 | "-thread",
301 | Arg.Unit (fun _ -> threads := threads_default);
302 | @@ -1237,7 +1346,7 @@
303 | with
304 | any ->
305 | close_out initl;
306 | - Sys.remove initl_file_name;
307 | + remove_file initl_file_name;
308 | raise any
309 | end;
310 |
311 | @@ -1245,9 +1354,9 @@
312 | at_exit
313 | (fun () ->
314 | let tr f x = try f x with _ -> () in
315 | - tr Sys.remove initl_file_name;
316 | - tr Sys.remove (Filename.chop_extension initl_file_name ^ ".cmi");
317 | - tr Sys.remove (Filename.chop_extension initl_file_name ^ ".cmo");
318 | + tr remove_file initl_file_name;
319 | + tr remove_file (Filename.chop_extension initl_file_name ^ ".cmi");
320 | + tr remove_file (Filename.chop_extension initl_file_name ^ ".cmo");
321 | );
322 |
323 | let exclude_list = [ stdlibdir; threads_dir; vmthreads_dir ] in
324 | @@ -1493,7 +1602,9 @@
325 | [ "-v", Arg.Unit (fun () -> verbose := Verbose);
326 | "-pp", Arg.String (fun s ->
327 | pp_specified := true;
328 | - options := !options @ ["-pp"; s]);
329 | + options := !options @ ["-pp"; rewrite_pp s]);
330 | + "-ppx", Arg.String (fun s ->
331 | + options := !options @ ["-ppx"; rewrite_pp s]);
332 | ]
333 | )
334 | )
335 | @@ -1672,7 +1783,9 @@
336 | Arg.String (fun s -> add_spec_fn "-I" (slashify (resolve_path s)));
337 |
338 | "-pp", Arg.String (fun s -> pp_specified := true;
339 | - add_spec_fn "-pp" s);
340 | + add_spec_fn "-pp" (rewrite_pp s));
341 | + "-ppx", Arg.String (fun s -> add_spec_fn "-ppx" (rewrite_pp s));
342 | +
343 | ]
344 | )
345 | )
346 | @@ -1830,7 +1943,10 @@
347 | output_string ch_out append;
348 | close_out ch_out;
349 | close_in ch_in;
350 | - Unix.utimes outpath s.Unix.st_mtime s.Unix.st_mtime;
351 | + (try Unix.utimes outpath s.Unix.st_mtime s.Unix.st_mtime
352 | + with Unix.Unix_error(e,_,_) ->
353 | + prerr_endline("Warning: setting utimes for " ^ outpath
354 | + ^ ": " ^ Unix.error_message e));
355 |
356 | prerr_endline("Installed " ^ outpath);
357 | with
358 | @@ -1882,6 +1998,8 @@
359 | Unix.openfile (Filename.concat dir owner_file) [Unix.O_RDONLY] 0 in
360 | let f =
361 | Unix.in_channel_of_descr fd in
362 | + if is_win then
363 | + set_binary_mode_in f false;
364 | try
365 | let line = input_line f in
366 | let is_my_file = (line = pkg) in
367 | @@ -2208,7 +2326,7 @@
368 | let lines = read_ldconf !ldconf in
369 | let dlldir_norm = Fl_split.norm_dir dlldir in
370 | let dlldir_norm_lc = string_lowercase_ascii dlldir_norm in
371 | - let ci_filesys = (Sys.os_type = "Win32") in
372 | + let ci_filesys = is_win in
373 | let check_dir d =
374 | let d' = Fl_split.norm_dir d in
375 | (d' = dlldir_norm) ||
376 | @@ -2356,7 +2474,7 @@
377 | List.iter
378 | (fun file ->
379 | let absfile = Filename.concat dlldir file in
380 | - Sys.remove absfile;
381 | + remove_file absfile;
382 | prerr_endline ("Removed " ^ absfile)
383 | )
384 | dll_files
385 | @@ -2365,7 +2483,7 @@
386 | (* Remove the files from the package directory: *)
387 | if Sys.file_exists pkgdir then begin
388 | let files = Sys.readdir pkgdir in
389 | - Array.iter (fun f -> Sys.remove (Filename.concat pkgdir f)) files;
390 | + Array.iter (fun f -> remove_file (Filename.concat pkgdir f)) files;
391 | Unix.rmdir pkgdir;
392 | prerr_endline ("Removed " ^ pkgdir)
393 | end
394 | @@ -2415,7 +2533,9 @@
395 |
396 |
397 | let print_configuration() =
398 | + let sl = slashify in
399 | let dir s =
400 | + let s = sl s in
401 | if Sys.file_exists s then
402 | s
403 | else
404 | @@ -2453,27 +2573,27 @@
405 | if md = "" then "the corresponding package directories" else dir md
406 | );
407 | Printf.printf "The standard library is assumed to reside in:\n %s\n"
408 | - (Findlib.ocaml_stdlib());
409 | + (sl (Findlib.ocaml_stdlib()));
410 | Printf.printf "The ld.conf file can be found here:\n %s\n"
411 | - (Findlib.ocaml_ldconf());
412 | + (sl (Findlib.ocaml_ldconf()));
413 | flush stdout
414 | | Some "conf" ->
415 | - print_endline (Findlib.config_file())
416 | + print_endline (sl (Findlib.config_file()))
417 | | Some "path" ->
418 | - List.iter print_endline (Findlib.search_path())
419 | + List.iter ( fun x -> print_endline (sl x)) (Findlib.search_path())
420 | | Some "destdir" ->
421 | - print_endline (Findlib.default_location())
422 | + print_endline ( sl (Findlib.default_location()))
423 | | Some "metadir" ->
424 | - print_endline (Findlib.meta_directory())
425 | + print_endline ( sl (Findlib.meta_directory()))
426 | | Some "metapath" ->
427 | let mdir = Findlib.meta_directory() in
428 | let ddir = Findlib.default_location() in
429 | - print_endline
430 | - (if mdir <> "" then mdir ^ "/META.%s" else ddir ^ "/%s/META")
431 | + print_endline ( sl
432 | + (if mdir <> "" then mdir ^ "/META.%s" else ddir ^ "/%s/META"))
433 | | Some "stdlib" ->
434 | - print_endline (Findlib.ocaml_stdlib())
435 | + print_endline ( sl (Findlib.ocaml_stdlib()))
436 | | Some "ldconf" ->
437 | - print_endline (Findlib.ocaml_ldconf())
438 | + print_endline ( sl (Findlib.ocaml_ldconf()))
439 | | _ ->
440 | assert false
441 | ;;
442 | @@ -2481,7 +2601,7 @@
443 |
444 | let ocamlcall pkg cmd =
445 | let dir = package_directory pkg in
446 | - let path = Filename.concat dir cmd in
447 | + let path = rewrite_cmd (Filename.concat dir cmd) in
448 | begin
449 | try Unix.access path [ Unix.X_OK ]
450 | with
451 | @@ -2647,6 +2767,10 @@
452 | | Sys_error f ->
453 | prerr_endline ("ocamlfind: " ^ f);
454 | exit 2
455 | + | Unix.Unix_error (e, fn, f) ->
456 | + prerr_endline ("ocamlfind: " ^ fn ^ " " ^ f
457 | + ^ ": " ^ Unix.error_message e);
458 | + exit 2
459 | | Findlib.No_such_package(pkg,info) ->
460 | prerr_endline ("ocamlfind: Package `" ^ pkg ^ "' not found" ^
461 | (if info <> "" then " - " ^ info else ""));
462 | --- ./src/findlib/Makefile
463 | +++ ./src/findlib/Makefile
464 | @@ -90,6 +90,7 @@
465 | cat findlib_config.mlp | \
466 | $(SH) $(TOP)/tools/patch '@CONFIGFILE@' '$(OCAMLFIND_CONF)' | \
467 | $(SH) $(TOP)/tools/patch '@STDLIB@' '$(OCAML_CORE_STDLIB)' | \
468 | + $(SH) $(TOP)/tools/patch '@EXEC_SUFFIX@' '$(EXEC_SUFFIX)' | \
469 | sed -e 's;@AUTOLINK@;$(OCAML_AUTOLINK);g' \
470 | -e 's;@SYSTEM@;$(SYSTEM);g' \
471 | >findlib_config.ml
472 |
--------------------------------------------------------------------------------
/esy.lock/overrides/opam__s__ocamlbuild_opam__c__0.14.0_opam_override/files/ocamlbuild-0.14.0.patch:
--------------------------------------------------------------------------------
1 | --- ./Makefile
2 | +++ ./Makefile
3 | @@ -213,7 +213,7 @@
4 | rm -f man/ocamlbuild.1
5 |
6 | man/options_man.byte: src/ocamlbuild_pack.cmo
7 | - $(OCAMLC) $^ -I src man/options_man.ml -o man/options_man.byte
8 | + $(OCAMLC) -I +unix unix.cma $^ -I src man/options_man.ml -o man/options_man.byte
9 |
10 | clean::
11 | rm -f man/options_man.cm*
12 | --- ./src/command.ml
13 | +++ ./src/command.ml
14 | @@ -148,9 +148,10 @@
15 | let self = string_of_command_spec_with_calls call_with_tags call_with_target resolve_virtuals in
16 | let b = Buffer.create 256 in
17 | (* The best way to prevent bash from switching to its windows-style
18 | - * quote-handling is to prepend an empty string before the command name. *)
19 | + * quote-handling is to prepend an empty string before the command name.
20 | + * space seems to work, too - and the ouput is nicer *)
21 | if Sys.os_type = "Win32" then
22 | - Buffer.add_string b "''";
23 | + Buffer.add_char b ' ';
24 | let first = ref true in
25 | let put_space () =
26 | if !first then
27 | @@ -260,7 +261,7 @@
28 |
29 | let execute_many ?(quiet=false) ?(pretend=false) cmds =
30 | add_parallel_stat (List.length cmds);
31 | - let degraded = !*My_unix.is_degraded || Sys.os_type = "Win32" in
32 | + let degraded = !*My_unix.is_degraded in
33 | let jobs = !jobs in
34 | if jobs < 0 then invalid_arg "jobs < 0";
35 | let max_jobs = if jobs = 0 then None else Some jobs in
36 | --- ./src/findlib.ml
37 | +++ ./src/findlib.ml
38 | @@ -66,9 +66,6 @@
39 | (fun command -> lexer & Lexing.from_string & run_and_read command)
40 | command
41 |
42 | -let run_and_read command =
43 | - Printf.ksprintf run_and_read command
44 | -
45 | let rec query name =
46 | try
47 | Hashtbl.find packages name
48 | @@ -135,7 +132,8 @@
49 | with Not_found -> s
50 |
51 | let list () =
52 | - List.map before_space (split_nl & run_and_read "%s list" ocamlfind)
53 | + let cmd = Shell.quote_filename_if_needed ocamlfind ^ " list" in
54 | + List.map before_space (split_nl & run_and_read cmd)
55 |
56 | (* The closure algorithm is easy because the dependencies are already closed
57 | and sorted for each package. We only have to make the union. We could also
58 | --- ./src/main.ml
59 | +++ ./src/main.ml
60 | @@ -162,6 +162,9 @@
61 | Tags.mem "traverse" tags
62 | || List.exists (Pathname.is_prefix path_name) !Options.include_dirs
63 | || List.exists (Pathname.is_prefix path_name) target_dirs)
64 | + && ((* beware: !Options.build_dir is an absolute directory *)
65 | + Pathname.normalize !Options.build_dir
66 | + <> Pathname.normalize (Pathname.pwd/path_name))
67 | end
68 | end
69 | end
70 | --- ./src/my_std.ml
71 | +++ ./src/my_std.ml
72 | @@ -271,13 +271,107 @@
73 | try Array.iter (fun x -> if x = basename then raise Exit) a; false
74 | with Exit -> true
75 |
76 | +let command_plain = function
77 | +| [| |] -> 0
78 | +| margv ->
79 | + let rec waitpid a b =
80 | + match Unix.waitpid a b with
81 | + | exception (Unix.Unix_error(Unix.EINTR,_,_)) -> waitpid a b
82 | + | x -> x
83 | + in
84 | + let pid = Unix.(create_process margv.(0) margv stdin stdout stderr) in
85 | + let pid', process_status = waitpid [] pid in
86 | + assert (pid = pid');
87 | + match process_status with
88 | + | Unix.WEXITED n -> n
89 | + | Unix.WSIGNALED _ -> 2 (* like OCaml's uncaught exceptions *)
90 | + | Unix.WSTOPPED _ -> 127
91 | +
92 | +(* can't use Lexers because of circular dependency *)
93 | +let split_path_win str =
94 | + let rec aux pos =
95 | + try
96 | + let i = String.index_from str pos ';' in
97 | + let len = i - pos in
98 | + if len = 0 then
99 | + aux (succ i)
100 | + else
101 | + String.sub str pos (i - pos) :: aux (succ i)
102 | + with Not_found | Invalid_argument _ ->
103 | + let len = String.length str - pos in
104 | + if len = 0 then [] else [String.sub str pos len]
105 | + in
106 | + aux 0
107 | +
108 | +let windows_shell = lazy begin
109 | + let rec iter = function
110 | + | [] -> [| "bash.exe" ; "--norc" ; "--noprofile" |]
111 | + | hd::tl ->
112 | + let dash = Filename.concat hd "dash.exe" in
113 | + if Sys.file_exists dash then [|dash|] else
114 | + let bash = Filename.concat hd "bash.exe" in
115 | + if Sys.file_exists bash = false then iter tl else
116 | + (* if sh.exe and bash.exe exist in the same dir, choose sh.exe *)
117 | + let sh = Filename.concat hd "sh.exe" in
118 | + if Sys.file_exists sh then [|sh|] else [|bash ; "--norc" ; "--noprofile"|]
119 | + in
120 | + split_path_win (try Sys.getenv "PATH" with Not_found -> "") |> iter
121 | +end
122 | +
123 | +let prep_windows_cmd cmd =
124 | + (* workaround known ocaml bug, remove later *)
125 | + if String.contains cmd '\t' && String.contains cmd ' ' = false then
126 | + " " ^ cmd
127 | + else
128 | + cmd
129 | +
130 | +let run_with_shell = function
131 | +| "" -> 0
132 | +| cmd ->
133 | + let cmd = prep_windows_cmd cmd in
134 | + let shell = Lazy.force windows_shell in
135 | + let qlen = Filename.quote cmd |> String.length in
136 | + (* old versions of dash had problems with bs *)
137 | + try
138 | + if qlen < 7_900 then
139 | + command_plain (Array.append shell [| "-ec" ; cmd |])
140 | + else begin
141 | + (* it can still work, if the called command is a cygwin tool *)
142 | + let ch_closed = ref false in
143 | + let file_deleted = ref false in
144 | + let fln,ch =
145 | + Filename.open_temp_file
146 | + ~mode:[Open_binary]
147 | + "ocamlbuildtmp"
148 | + ".sh"
149 | + in
150 | + try
151 | + let f_slash = String.map ( fun x -> if x = '\\' then '/' else x ) fln in
152 | + output_string ch cmd;
153 | + ch_closed:= true;
154 | + close_out ch;
155 | + let ret = command_plain (Array.append shell [| "-e" ; f_slash |]) in
156 | + file_deleted:= true;
157 | + Sys.remove fln;
158 | + ret
159 | + with
160 | + | x ->
161 | + if !ch_closed = false then
162 | + close_out_noerr ch;
163 | + if !file_deleted = false then
164 | + (try Sys.remove fln with _ -> ());
165 | + raise x
166 | + end
167 | + with
168 | + | (Unix.Unix_error _) as x ->
169 | + (* Sys.command doesn't raise an exception, so run_with_shell also won't
170 | + raise *)
171 | + Printexc.to_string x ^ ":" ^ cmd |> prerr_endline;
172 | + 1
173 | +
174 | let sys_command =
175 | - match Sys.os_type with
176 | - | "Win32" -> fun cmd ->
177 | - if cmd = "" then 0 else
178 | - let cmd = "bash --norc -c " ^ Filename.quote cmd in
179 | - Sys.command cmd
180 | - | _ -> fun cmd -> if cmd = "" then 0 else Sys.command cmd
181 | + if Sys.win32 then run_with_shell
182 | + else fun cmd -> if cmd = "" then 0 else Sys.command cmd
183 |
184 | (* FIXME warning fix and use Filename.concat *)
185 | let filename_concat x y =
186 | --- ./src/my_std.mli
187 | +++ ./src/my_std.mli
188 | @@ -69,3 +69,6 @@
189 |
190 | val split_ocaml_version : (int * int * int * string) option
191 | (** (major, minor, patchlevel, rest) *)
192 | +
193 | +val windows_shell : string array Lazy.t
194 | +val prep_windows_cmd : string -> string
195 | --- ./src/ocamlbuild_executor.ml
196 | +++ ./src/ocamlbuild_executor.ml
197 | @@ -34,6 +34,8 @@
198 | job_stdin : out_channel;
199 | job_stderr : in_channel;
200 | job_buffer : Buffer.t;
201 | + job_pid : int;
202 | + job_tmp_file: string option;
203 | mutable job_dying : bool;
204 | };;
205 |
206 | @@ -76,6 +78,61 @@
207 | in
208 | loop 0
209 | ;;
210 | +
211 | +let open_process_full_win cmd env =
212 | + let (in_read, in_write) = Unix.pipe () in
213 | + let (out_read, out_write) = Unix.pipe () in
214 | + let (err_read, err_write) = Unix.pipe () in
215 | + Unix.set_close_on_exec in_read;
216 | + Unix.set_close_on_exec out_write;
217 | + Unix.set_close_on_exec err_read;
218 | + let inchan = Unix.in_channel_of_descr in_read in
219 | + let outchan = Unix.out_channel_of_descr out_write in
220 | + let errchan = Unix.in_channel_of_descr err_read in
221 | + let shell = Lazy.force Ocamlbuild_pack.My_std.windows_shell in
222 | + let test_cmd =
223 | + String.concat " " (List.map Filename.quote (Array.to_list shell)) ^
224 | + "-ec " ^
225 | + Filename.quote (Ocamlbuild_pack.My_std.prep_windows_cmd cmd) in
226 | + let argv,tmp_file =
227 | + if String.length test_cmd < 7_900 then
228 | + Array.append
229 | + shell
230 | + [| "-ec" ; Ocamlbuild_pack.My_std.prep_windows_cmd cmd |],None
231 | + else
232 | + let fln,ch = Filename.open_temp_file ~mode:[Open_binary] "ocamlbuild" ".sh" in
233 | + output_string ch (Ocamlbuild_pack.My_std.prep_windows_cmd cmd);
234 | + close_out ch;
235 | + let fln' = String.map (function '\\' -> '/' | c -> c) fln in
236 | + Array.append
237 | + shell
238 | + [| "-c" ; fln' |], Some fln in
239 | + let pid =
240 | + Unix.create_process_env argv.(0) argv env out_read in_write err_write in
241 | + Unix.close out_read;
242 | + Unix.close in_write;
243 | + Unix.close err_write;
244 | + (pid, inchan, outchan, errchan,tmp_file)
245 | +
246 | +let close_process_full_win (pid,inchan, outchan, errchan, tmp_file) =
247 | + let delete tmp_file =
248 | + match tmp_file with
249 | + | None -> ()
250 | + | Some x -> try Sys.remove x with Sys_error _ -> () in
251 | + let tmp_file_deleted = ref false in
252 | + try
253 | + close_in inchan;
254 | + close_out outchan;
255 | + close_in errchan;
256 | + let res = snd(Unix.waitpid [] pid) in
257 | + tmp_file_deleted := true;
258 | + delete tmp_file;
259 | + res
260 | + with
261 | + | x when tmp_file <> None && !tmp_file_deleted = false ->
262 | + delete tmp_file;
263 | + raise x
264 | +
265 | (* ***)
266 | (*** execute *)
267 | (* XXX: Add test for non reentrancy *)
268 | @@ -130,10 +187,16 @@
269 | (*** add_job *)
270 | let add_job cmd rest result id =
271 | (*display begin fun oc -> fp oc "Job %a is %s\n%!" print_job_id id cmd; end;*)
272 | - let (stdout', stdin', stderr') = open_process_full cmd env in
273 | + let (pid,stdout', stdin', stderr', tmp_file) =
274 | + if Sys.win32 then open_process_full_win cmd env else
275 | + let a,b,c = open_process_full cmd env in
276 | + -1,a,b,c,None
277 | + in
278 | incr jobs_active;
279 | - set_nonblock (doi stdout');
280 | - set_nonblock (doi stderr');
281 | + if not Sys.win32 then (
282 | + set_nonblock (doi stdout');
283 | + set_nonblock (doi stderr');
284 | + );
285 | let job =
286 | { job_id = id;
287 | job_command = cmd;
288 | @@ -143,7 +206,9 @@
289 | job_stdin = stdin';
290 | job_stderr = stderr';
291 | job_buffer = Buffer.create 1024;
292 | - job_dying = false }
293 | + job_dying = false;
294 | + job_tmp_file = tmp_file;
295 | + job_pid = pid }
296 | in
297 | outputs := FDM.add (doi stdout') job (FDM.add (doi stderr') job !outputs);
298 | jobs := JS.add job !jobs;
299 | @@ -199,6 +264,7 @@
300 | try
301 | read fd u 0 (Bytes.length u)
302 | with
303 | + | Unix.Unix_error(Unix.EPIPE,_,_) when Sys.win32 -> 0
304 | | Unix.Unix_error(e,_,_) ->
305 | let msg = error_message e in
306 | display (fun oc -> fp oc
307 | @@ -241,14 +307,19 @@
308 | decr jobs_active;
309 |
310 | (* PR#5371: we would get EAGAIN below otherwise *)
311 | - clear_nonblock (doi job.job_stdout);
312 | - clear_nonblock (doi job.job_stderr);
313 | -
314 | + if not Sys.win32 then (
315 | + clear_nonblock (doi job.job_stdout);
316 | + clear_nonblock (doi job.job_stderr);
317 | + );
318 | do_read ~loop:true (doi job.job_stdout) job;
319 | do_read ~loop:true (doi job.job_stderr) job;
320 | outputs := FDM.remove (doi job.job_stdout) (FDM.remove (doi job.job_stderr) !outputs);
321 | jobs := JS.remove job !jobs;
322 | - let status = close_process_full (job.job_stdout, job.job_stdin, job.job_stderr) in
323 | + let status =
324 | + if Sys.win32 then
325 | + close_process_full_win (job.job_pid, job.job_stdout, job.job_stdin, job.job_stderr, job.job_tmp_file)
326 | + else
327 | + close_process_full (job.job_stdout, job.job_stdin, job.job_stderr) in
328 |
329 | let shown = ref false in
330 |
331 | --- ./src/ocamlbuild_unix_plugin.ml
332 | +++ ./src/ocamlbuild_unix_plugin.ml
333 | @@ -48,12 +48,22 @@
334 | end
335 |
336 | let run_and_open s kont =
337 | + let s_orig = s in
338 | + let s =
339 | + (* Be consistent! My_unix.run_and_open uses My_std.sys_command and
340 | + sys_command uses bash. *)
341 | + if Sys.win32 = false then s else
342 | + let l = match Lazy.force My_std.windows_shell |> Array.to_list with
343 | + | hd::tl -> (Filename.quote hd)::tl
344 | + | _ -> assert false in
345 | + "\"" ^ (String.concat " " l) ^ " -ec " ^ Filename.quote (" " ^ s) ^ "\""
346 | + in
347 | let ic = Unix.open_process_in s in
348 | let close () =
349 | match Unix.close_process_in ic with
350 | | Unix.WEXITED 0 -> ()
351 | | Unix.WEXITED _ | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
352 | - failwith (Printf.sprintf "Error while running: %s" s) in
353 | + failwith (Printf.sprintf "Error while running: %s" s_orig) in
354 | let res = try
355 | kont ic
356 | with e -> (close (); raise e)
357 | --- ./src/options.ml
358 | +++ ./src/options.ml
359 | @@ -174,11 +174,24 @@
360 | build_dir := Filename.concat (Sys.getcwd ()) s
361 | else
362 | build_dir := s
363 | +
364 | +let slashify =
365 | + if Sys.win32 then fun p -> String.map (function '\\' -> '/' | x -> x) p
366 | + else fun p ->p
367 | +
368 | +let sb () =
369 | + match Sys.os_type with
370 | + | "Win32" ->
371 | + (try set_binary_mode_out stdout true with _ -> ());
372 | + | _ -> ()
373 | +
374 | +
375 | let spec = ref (
376 | let print_version () =
377 | + sb ();
378 | Printf.printf "ocamlbuild %s\n%!" Ocamlbuild_config.version; raise Exit_OK
379 | in
380 | - let print_vnum () = print_endline Ocamlbuild_config.version; raise Exit_OK in
381 | + let print_vnum () = sb (); print_endline Ocamlbuild_config.version; raise Exit_OK in
382 | Arg.align
383 | [
384 | "-version", Unit print_version , " Display the version";
385 | @@ -257,8 +270,8 @@
386 | "-build-dir", String set_build_dir, " Set build directory (implies no-links)";
387 | "-install-lib-dir", Set_string Ocamlbuild_where.libdir, " Set the install library directory";
388 | "-install-bin-dir", Set_string Ocamlbuild_where.bindir, " Set the install binary directory";
389 | - "-where", Unit (fun () -> print_endline !Ocamlbuild_where.libdir; raise Exit_OK), " Display the install library directory";
390 | - "-which", String (fun cmd -> print_endline (find_tool cmd); raise Exit_OK), " Display path to the tool command";
391 | + "-where", Unit (fun () -> sb (); print_endline (slashify !Ocamlbuild_where.libdir); raise Exit_OK), " Display the install library directory";
392 | + "-which", String (fun cmd -> sb (); print_endline (slashify (find_tool cmd)); raise Exit_OK), " Display path to the tool command";
393 | "-ocamlc", set_cmd ocamlc, " Set the OCaml bytecode compiler";
394 | "-plugin-ocamlc", set_cmd plugin_ocamlc, " Set the OCaml bytecode compiler \
395 | used when building myocamlbuild.ml (only)";
396 | --- ./src/pathname.ml
397 | +++ ./src/pathname.ml
398 | @@ -84,6 +84,26 @@
399 | | x :: xs -> x :: normalize_list xs
400 |
401 | let normalize x =
402 | + let x =
403 | + if Sys.win32 = false then
404 | + x
405 | + else
406 | + let len = String.length x in
407 | + let b = Bytes.create len in
408 | + for i = 0 to pred len do
409 | + match x.[i] with
410 | + | '\\' -> Bytes.set b i '/'
411 | + | c -> Bytes.set b i c
412 | + done;
413 | + if len > 1 then (
414 | + let c1 = Bytes.get b 0 in
415 | + let c2 = Bytes.get b 1 in
416 | + if c2 = ':' && c1 >= 'a' && c1 <= 'z' &&
417 | + ( len = 2 || Bytes.get b 2 = '/') then
418 | + Bytes.set b 0 (Char.uppercase_ascii c1)
419 | + );
420 | + Bytes.unsafe_to_string b
421 | + in
422 | if Glob.eval not_normal_form_re x then
423 | let root, paths = split x in
424 | join root (normalize_list paths)
425 | --- ./src/shell.ml
426 | +++ ./src/shell.ml
427 | @@ -24,12 +24,26 @@
428 | | 'a'..'z' | 'A'..'Z' | '0'..'9' | '.' | '-' | '/' | '_' | ':' | '@' | '+' | ',' -> loop (pos + 1)
429 | | _ -> false in
430 | loop 0
431 | +
432 | +let generic_quote quotequote s =
433 | + let l = String.length s in
434 | + let b = Buffer.create (l + 20) in
435 | + Buffer.add_char b '\'';
436 | + for i = 0 to l - 1 do
437 | + if s.[i] = '\''
438 | + then Buffer.add_string b quotequote
439 | + else Buffer.add_char b s.[i]
440 | + done;
441 | + Buffer.add_char b '\'';
442 | + Buffer.contents b
443 | +let unix_quote = generic_quote "'\\''"
444 | +
445 | let quote_filename_if_needed s =
446 | if is_simple_filename s then s
447 | (* We should probably be using [Filename.unix_quote] except that function
448 | * isn't exported. Users on Windows will have to live with not being able to
449 | * install OCaml into c:\o'caml. Too bad. *)
450 | - else if Sys.os_type = "Win32" then Printf.sprintf "'%s'" s
451 | + else if Sys.os_type = "Win32" then unix_quote s
452 | else Filename.quote s
453 | let chdir dir =
454 | reset_filesys_cache ();
455 | @@ -37,7 +51,7 @@
456 | let run args target =
457 | reset_readdir_cache ();
458 | let cmd = String.concat " " (List.map quote_filename_if_needed args) in
459 | - if !*My_unix.is_degraded || Sys.os_type = "Win32" then
460 | + if !*My_unix.is_degraded then
461 | begin
462 | Log.event cmd target Tags.empty;
463 | let st = sys_command cmd in
464 |
--------------------------------------------------------------------------------