├── 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 | --------------------------------------------------------------------------------