├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .mailmap ├── LICENSE.AGPL.txt ├── LICENSE.txt ├── README.md ├── package-lock.json ├── package.json ├── server ├── renderer-server │ ├── Cargo.lock │ ├── Cargo.toml │ ├── rustfmt.toml │ ├── src │ │ ├── command_source │ │ │ ├── batch.rs │ │ │ ├── mod.rs │ │ │ ├── test_runner.rs │ │ │ └── ws_worker_client.rs │ │ ├── config.rs │ │ ├── container.rs │ │ ├── error.rs │ │ ├── event_loop │ │ │ ├── mod.rs │ │ │ └── state.rs │ │ ├── lib.rs │ │ ├── main.rs │ │ ├── renderer.rs │ │ ├── renderer_manager.rs │ │ └── request.rs │ └── tests │ │ ├── evil.rs │ │ ├── ly │ │ ├── danger_forever.ly │ │ ├── danger_forkbomb.ly │ │ ├── danger_kill_group.ly │ │ ├── danger_kill_lilypond.ly │ │ ├── danger_kill_ruby.ly │ │ ├── danger_rm_home.ly │ │ ├── danger_rm_slash.ly │ │ ├── danger_rm_tmp.ly │ │ ├── simple.ly │ │ ├── simple.ly.2_18_2.svg │ │ ├── simple.ly.2_18_2.txt │ │ ├── simple.ly.2_19_82.svg │ │ ├── simple.ly.2_19_82.txt │ │ ├── sleep.ly │ │ ├── sleep.ly.2_18_2.svg │ │ ├── sleep.ly.2_18_2.txt │ │ ├── sleep.ly.2_19_82.svg │ │ └── sleep.ly.2_19_82.txt │ │ ├── simple.rs │ │ ├── sleep.rs │ │ └── util.rs ├── renderer-unstable │ ├── Dockerfile │ ├── no_lyp_check_update.patch │ └── render-impl.bash ├── renderer │ ├── Dockerfile │ ├── no_lyp_check_update.patch │ └── render-impl.bash └── ws-server │ ├── hacklilyserver.cpp │ ├── hacklilyserver.h │ ├── main.cpp │ └── ws-server.pro ├── src ├── App.tsx ├── ButtonGroup.tsx ├── Editor.tsx ├── FileMenu.tsx ├── Header.tsx ├── LICENSE_HEADER.txt ├── Logs.tsx ├── Modal404.tsx ├── ModalAbout.tsx ├── ModalConflict.tsx ├── ModalLocked.tsx ├── ModalLogin.tsx ├── ModalOpen.tsx ├── ModalPublish.tsx ├── ModalSaving.tsx ├── ModalUnsavedChangesInterstitial.tsx ├── Preview.tsx ├── RPCClient.tsx ├── auth.ts ├── base64Binary.ts ├── gitfs.tsx ├── hackmidi.d.ts ├── index.css ├── index.tsx ├── logo.svg ├── logo.svg.d.ts ├── monacoConfig │ ├── CodelensProvider.tsx │ ├── Commands.tsx │ ├── LICENSE_HEADER.txt │ ├── LILYPOND_COMPLETION_ITEM_PROVIDER.tsx │ ├── LILYPOND_MONARCH_PROVIDER.tsx │ └── NOTATION_SYMBOLS.tsx ├── musicxml2ly │ ├── MusicXML2Ly.tsx │ ├── MusicXML2LyModal.tsx │ └── musicxml2ly.index.tsx ├── status │ ├── Status.tsx │ └── status.index.tsx ├── styles.tsx └── util │ └── queryString.tsx ├── static ├── 404.html ├── CenturySchL-Bold.otf ├── CenturySchL-BoldItal.otf ├── CenturySchL-Ital.otf ├── CenturySchL-Roma.otf ├── README.md ├── about-javascript.html ├── dmca.html ├── emmentaler-11.otf ├── emmentaler-13.otf ├── emmentaler-14.otf ├── emmentaler-16.otf ├── emmentaler-18.otf ├── emmentaler-20.otf ├── emmentaler-23.otf ├── emmentaler-26.otf ├── emmentaler-brace.otf ├── favicon.ico ├── github.svg ├── google4b0ced2a6eedee27.html ├── gplv3-127x51.png ├── hackmidi │ ├── Chop-28-4.mid │ ├── asset-manifest.json │ ├── favicon.ico │ ├── index.html │ ├── samples │ │ ├── Drum_000 │ │ │ ├── 025_Snare_Roll.pat │ │ │ ├── 026_Snap.pat │ │ │ ├── 027_High_Q.pat │ │ │ ├── 031_Sticks.pat │ │ │ ├── 032_Square_Click.pat │ │ │ ├── 033_Metronome_Click.pat │ │ │ ├── 034_Metronome_Bell.pat │ │ │ ├── 035_Kick_1.pat │ │ │ ├── 035_Kick_1.txt │ │ │ ├── 036_Kick_2.pat │ │ │ ├── 036_Kick_2.txt │ │ │ ├── 037_Stick_Rim.pat │ │ │ ├── 038_Snare_1.pat │ │ │ ├── 039_Clap_Hand.pat │ │ │ ├── 039_Clap_Hand.txt │ │ │ ├── 040_Snare_2.pat │ │ │ ├── 041_Tom_Low_2.pat │ │ │ ├── 041_Tom_Low_2.txt │ │ │ ├── 042_Hi-Hat_Closed.pat │ │ │ ├── 043_Tom_Low_1.pat │ │ │ ├── 043_Tom_Low_1.txt │ │ │ ├── 044_Hi-Hat_Pedal.pat │ │ │ ├── 045_Tom_Mid_2.pat │ │ │ ├── 045_Tom_Mid_2.txt │ │ │ ├── 046_Hi-Hat_Open.pat │ │ │ ├── 047_Tom_Mid_1.pat │ │ │ ├── 047_Tom_Mid_1.txt │ │ │ ├── 048_Tom_High_2.pat │ │ │ ├── 048_Tom_High_2.txt │ │ │ ├── 049_Cymbal_Crash_1.pat │ │ │ ├── 050_Tom_High_1.pat │ │ │ ├── 050_Tom_High_1.txt │ │ │ ├── 051_Cymbal_Ride_1.pat │ │ │ ├── 052_Cymbal_Chinese.pat │ │ │ ├── 053_Cymbal_Ride_Bell.pat │ │ │ ├── 053_Cymbal_Ride_Bell.txt │ │ │ ├── 054_Tombourine.pat │ │ │ ├── 055_Cymbal_Splash.pat │ │ │ ├── 056_Cow_Bell.pat │ │ │ ├── 057_Cymbal_Crash_2.pat │ │ │ ├── 058_Vibra-Slap.pat │ │ │ ├── 059_Cymbal_Ride_2.pat │ │ │ ├── 060_Bongo_High.pat │ │ │ ├── 061_Bongo_Low.pat │ │ │ ├── 062_Conga_High_1_Mute.pat │ │ │ ├── 062_Conga_High_1_mute.txt │ │ │ ├── 063_Conga_High_2_Open.pat │ │ │ ├── 064_Conga_Low.pat │ │ │ ├── 065_Timbale_High.pat │ │ │ ├── 066_Timbale_Low.pat │ │ │ ├── 067_Agogo_High.pat │ │ │ ├── 068_Agogo_Low.pat │ │ │ ├── 069_Cabasa.pat │ │ │ ├── 069_Cabasa.txt │ │ │ ├── 070_Maracas.pat │ │ │ ├── 071_Whistle_1_High_Short.pat │ │ │ ├── 072_Whistle_2_Low_Long.pat │ │ │ ├── 073_Guiro_1_Short.pat │ │ │ ├── 074_Guiro_2_Long.pat │ │ │ ├── 075_Claves.pat │ │ │ ├── 075_Claves.txt │ │ │ ├── 076_Wood_Block_1_High.pat │ │ │ ├── 077_Wood_Block_2_Low.pat │ │ │ ├── 078_Cuica_1_Mute.pat │ │ │ ├── 078_Cuica_1_Mute.txt │ │ │ ├── 079_Cuica_2_Open.pat │ │ │ ├── 079_Cuica_2_Open.txt │ │ │ ├── 080_Triangle_1_Mute.pat │ │ │ ├── 081_Triangle_2_Open.pat │ │ │ ├── 082_Shaker.pat │ │ │ └── 084_Belltree.pat │ │ ├── Tone_000 │ │ │ ├── 000_Acoustic_Grand_Piano.pat │ │ │ ├── 000_Acoustic_Grand_Piano.txt │ │ │ ├── 001_Acoustic_Brite_Piano.pat │ │ │ ├── 002_Electric_Grand_Piano.pat │ │ │ ├── 004_Electric_Piano_1_Rhodes.pat │ │ │ ├── 005_Electric_Piano_2_Chorused_Yamaha_DX.pat │ │ │ ├── 006_Harpsichord.pat │ │ │ ├── 007_Clavinet.pat │ │ │ ├── 008_Celesta.pat │ │ │ ├── 009_Glockenspiel.pat │ │ │ ├── 013_Xylophone.pat │ │ │ ├── 014_Tubular_Bells.pat │ │ │ ├── 015_Dulcimer.pat │ │ │ ├── 016_Hammond_Organ.pat │ │ │ ├── 019_Church_Organ.pat │ │ │ ├── 021_Accordion.pat │ │ │ ├── 023_Tango_Accordion.pat │ │ │ ├── 024_Nylon_Guitar.pat │ │ │ ├── 025_Steel_Guitar.pat │ │ │ ├── 026_Jazz_Guitar.pat │ │ │ ├── 027_Clean_Electric_Guitar.pat │ │ │ ├── 028_Muted_Electric_Guitar.pat │ │ │ ├── 029_Overdriven_Guitar.pat │ │ │ ├── 030_Distortion_Guitar.pat │ │ │ ├── 032_Acoustic_Bass.pat │ │ │ ├── 033_Finger_Bass.pat │ │ │ ├── 034_Pick_Bass.pat │ │ │ ├── 035_Fretless_Bass.pat │ │ │ ├── 036_Slap_Bass_1.pat │ │ │ ├── 037_Slap_Bass_2.pat │ │ │ ├── 038_Synth_Bass_1.pat │ │ │ ├── 040_Violin.pat │ │ │ ├── 042_Cello.pat │ │ │ ├── 044_Tremolo_Strings.pat │ │ │ ├── 045_Pizzicato_Strings.pat │ │ │ ├── 046_Harp.pat │ │ │ ├── 047_Timpani.pat │ │ │ ├── 048_String_Ensemble_1_Marcato.pat │ │ │ ├── 053_Voice_Oohs.pat │ │ │ ├── 056_Trumpet.pat │ │ │ ├── 057_Trombone.pat │ │ │ ├── 058_Tuba.pat │ │ │ ├── 059_Muted_Trumpet.pat │ │ │ ├── 060_French_Horn.pat │ │ │ ├── 061_Brass_Section.pat │ │ │ ├── 064_Soprano_Sax.pat │ │ │ ├── 065_Alto_Sax.pat │ │ │ ├── 066_Tenor_Sax.pat │ │ │ ├── 067_Baritone_Sax.pat │ │ │ ├── 068_Oboe.pat │ │ │ ├── 069_English_Horn.pat │ │ │ ├── 070_Bassoon.pat │ │ │ ├── 071_Clarinet.pat │ │ │ ├── 072_Piccolo.pat │ │ │ ├── 073_Flute.pat │ │ │ ├── 074_Recorder.pat │ │ │ ├── 075_Pan_Flute.pat │ │ │ ├── 076_Bottle_Blow.pat │ │ │ ├── 079_Ocarina.pat │ │ │ ├── 080_Square_Wave.pat │ │ │ ├── 084_Charang.pat │ │ │ ├── 088_New_Age.pat │ │ │ ├── 094_Halo_Pad.pat │ │ │ ├── 095_Sweep_Pad.pat │ │ │ ├── 098_Crystal.pat │ │ │ ├── 101_Goblins--Unicorn.pat │ │ │ ├── 102_Echo_Voice.pat │ │ │ ├── 104_Sitar.pat │ │ │ ├── 114_Steel_Drums.pat │ │ │ ├── 115_Wood_Block.pat │ │ │ ├── 120_Guitar_Fret_Noise.pat │ │ │ ├── 122_Seashore.pat │ │ │ └── 125_Helicopter.pat │ │ └── timidity.cfg │ └── static │ │ ├── css │ │ ├── main.7fbd665b.css │ │ └── main.7fbd665b.css.map │ │ └── js │ │ ├── main.923a807c.js │ │ ├── main.923a807c.js.LICENSE.txt │ │ └── main.923a807c.js.map ├── index.html ├── musicxml2ly.html ├── preview.css ├── privacy-statement.html ├── status.html └── vendor │ ├── bravura │ ├── FONTLOG.txt │ ├── OFL-FAQ.txt │ ├── OFL.txt │ ├── bravura-text.md │ ├── bravura_metadata.json │ ├── eot │ │ ├── Bravura.eot │ │ └── BravuraText.eot │ ├── otf │ │ ├── Bravura.otf │ │ └── BravuraText.otf │ ├── svg │ │ ├── Bravura.svg │ │ └── BravuraText.svg │ └── woff │ │ ├── Bravura.woff │ │ └── BravuraText.woff │ └── smufl │ ├── classes.json │ ├── glyphnames.json │ ├── ranges.json │ └── smufl-1.12.pdf ├── tsconfig.json └── webpack.config.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "settings": { 7 | "react": { 8 | "version": "detect", 9 | }, 10 | }, 11 | "extends": [ 12 | "eslint:recommended", 13 | "plugin:react/recommended", 14 | "plugin:@typescript-eslint/eslint-recommended", 15 | "prettier", 16 | "plugin:prettier/recommended" 17 | ], 18 | "globals": { 19 | "Atomics": "readonly", 20 | "SharedArrayBuffer": "readonly" 21 | }, 22 | "parser": "@typescript-eslint/parser", 23 | "parserOptions": { 24 | "ecmaFeatures": { 25 | "jsx": true 26 | }, 27 | "ecmaVersion": 2018, 28 | "sourceType": "module" 29 | }, 30 | "plugins": [ 31 | "react", 32 | "@typescript-eslint", 33 | "react-hooks" 34 | ], 35 | "rules": { 36 | "no-unused-vars": "off", 37 | "@typescript-eslint/no-unused-vars": ["error", {"varsIgnorePattern": "^_", "argsIgnorePattern": "^_", "caughtErrorsIgnorePattern": "^_"}], 38 | "react-hooks/rules-of-hooks": "error", 39 | "react-hooks/exhaustive-deps": "error" 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | package-lock.json binary 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | /release 12 | /server/build 13 | 14 | # misc 15 | .DS_Store 16 | .env 17 | npm-debug.log* 18 | yarn-debug.log* 19 | yarn-error.log* 20 | 21 | # C++ objects and libs 22 | 23 | *.slo 24 | *.lo 25 | *.o 26 | *.a 27 | *.la 28 | *.lai 29 | *.so 30 | *.dll 31 | *.dylib 32 | 33 | # Qt-es 34 | 35 | .qmake.cache 36 | .qmake.stash 37 | *.pro.user 38 | *.pro.user.* 39 | *.qbs.user 40 | *.qbs.user.* 41 | *.moc 42 | moc_*.cpp 43 | moc_*.h 44 | qrc_*.cpp 45 | ui_*.h 46 | 47 | # QtCreator 48 | 49 | *.autosave 50 | 51 | # QtCtreator Qml 52 | *.qmlproject.user 53 | *.qmlproject.user.* 54 | 55 | # QtCtreator CMake 56 | CMakeLists.txt.user* 57 | 58 | *~ 59 | *.autosave 60 | *.a 61 | *.core 62 | *.moc 63 | *.o 64 | *.obj 65 | *.orig 66 | *.rej 67 | *.so 68 | *.so.* 69 | *_pch.h.cpp 70 | *_resource.rc 71 | *.qm 72 | .#* 73 | *.*# 74 | core 75 | !core/ 76 | tags 77 | .DS_Store 78 | .directory 79 | *.debug 80 | *.prl 81 | *.app 82 | moc_*.cpp 83 | ui_*.h 84 | qrc_*.cpp 85 | Thumbs.db 86 | *.res 87 | *.rc 88 | /.qmake.cache 89 | /.qmake.stash 90 | 91 | # qtcreator generated files 92 | *.pro.user* 93 | 94 | # xemacs temporary files 95 | *.flc 96 | 97 | # Vim temporary files 98 | .*.swp 99 | 100 | # Visual Studio generated files 101 | *.ib_pdb_index 102 | *.idb 103 | *.ilk 104 | *.pdb 105 | *.sln 106 | *.suo 107 | *.vcproj 108 | *vcproj.*.*.user 109 | *.ncb 110 | *.sdf 111 | *.opensdf 112 | *.vcxproj 113 | *vcxproj.* 114 | 115 | # MinGW generated files 116 | *.Debug 117 | *.Release 118 | 119 | # Python byte code 120 | *.pyc 121 | 122 | # Binaries 123 | # -------- 124 | *.dll 125 | *.exe 126 | 127 | # Vim 128 | *.sw? 129 | 130 | # VSCode 131 | /.vscode/chrome 132 | 133 | # Static files not created by webpack that are created in the build process 134 | # that we want to host, but not store in this repo 135 | /public/3rdpartylicenses.txt 136 | 137 | # Rust 138 | /server/renderer-server/target/ 139 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Jocelyn Stericker 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hacklily", 3 | "version": "0.1.0", 4 | "private": true, 5 | "license": "GPLv3", 6 | "homepage": "https://www.hacklily.org", 7 | "prettier": { 8 | "trailingComma": "all" 9 | }, 10 | "dependencies": { 11 | "@blueprintjs/core": "^4.8.0", 12 | "aphrodite": "2.4.0", 13 | "dompurify": "^2.3.10", 14 | "hackmidi": "0.0.4", 15 | "lodash": "^4.17.21", 16 | "makelily": "0.1.7", 17 | "monaco-editor": "^0.33.0", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0", 20 | "react-monaco-editor": "^0.49.0", 21 | "react-router-dom": "^6.3.0" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "^7.18.10", 25 | "@babel/plugin-proposal-class-properties": "^7.18.6", 26 | "@babel/plugin-transform-runtime": "^7.18.10", 27 | "@babel/preset-env": "^7.18.10", 28 | "@babel/preset-react": "^7.18.6", 29 | "@babel/preset-typescript": "^7.18.6", 30 | "@babel/runtime": "^7.18.9", 31 | "@types/d3-dispatch": "^3.0.1", 32 | "@types/d3-drag": "^3.0.1", 33 | "@types/d3-timer": "^3.0.0", 34 | "@types/dompurify": "^2.3.3", 35 | "@types/invariant": "^2.2.35", 36 | "@types/jest": "^28.1.7", 37 | "@types/lodash": "^4.14.183", 38 | "@types/node": "^18.7.6", 39 | "@types/opentype.js": "^1.3.4", 40 | "@types/react": "^18.0.17", 41 | "@types/react-dom": "^18.0.6", 42 | "@typescript-eslint/eslint-plugin": "^5.33.1", 43 | "@typescript-eslint/parser": "^5.33.1", 44 | "babel-loader": "^8.2.5", 45 | "copy-webpack-plugin": "^11.0.0", 46 | "css-loader": "^6.7.1", 47 | "eslint": "^8.22.0", 48 | "eslint-config-prettier": "^8.5.0", 49 | "eslint-plugin-prettier": "^4.2.1", 50 | "eslint-plugin-react": "^7.30.1", 51 | "eslint-plugin-react-hooks": "^4.6.0", 52 | "file-loader": "^6.2.0", 53 | "mini-css-extract-plugin": "^2.6.1", 54 | "monaco-editor-webpack-plugin": "^7.0.1", 55 | "prettier": "^2.7.1", 56 | "rimraf": "3.0.2", 57 | "style-loader": "^3.3.1", 58 | "typescript": "^4.7.4", 59 | "webpack": "^5.74.0", 60 | "webpack-cli": "^4.10.0", 61 | "webpack-dev-server": "^4.10.0" 62 | }, 63 | "scripts": { 64 | "test": "eslint ./src --ext tsx,ts,js,jsx && tsc --noEmit", 65 | "build": "rimraf dist pkg && env REACT_APP_GITHUB_CLIENT_ID=10a6656f66c8392b4d35 REACT_APP_BACKEND_WS_URL=wss://hacklily-render.nettek.ca/rpc webpack && npm test", 66 | "start": "rimraf dist pkg && env REACT_APP_GITHUB_CLIENT_ID=5a1e4e51dea710198f18 REACT_APP_BACKEND_WS_URL=ws://localhost:2000 webpack-dev-server --open --mode development", 67 | "start:remote-backend": "rimraf dist pkg && env REACT_APP_GITHUB_CLIENT_ID=10a6656f66c8392b4d35 REACT_APP_BACKEND_WS_URL=wss://hacklily-render.nettek.ca/rpc webpack-dev-server --open --mode development" 68 | }, 69 | "overrides": { 70 | "react": "^18.2.0" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /server/renderer-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "renderer_server" 3 | version = "0.1.0" 4 | authors = ["Jocelyn Stericker "] 5 | edition = "2021" 6 | 7 | [lib] 8 | name = "renderer_lib" 9 | path = "src/lib.rs" 10 | 11 | [[bin]] 12 | name = "renderer_server" 13 | path = "src/main.rs" 14 | 15 | [dependencies] 16 | ansi_term = "0.12" 17 | clap = "3.2.17" 18 | env_logger = "0.9.0" 19 | futures = "0.3.23" 20 | libc = "0.2.132" 21 | log = "0.4.17" 22 | nix = "0.25.0" 23 | serde = { version = "1.0.143", features = ["derive"] } 24 | serde_derive = "1.0.104" 25 | serde_json = "1.0.83" 26 | rand = "0.8.5" 27 | tokio = {version = "1.20.1", features = ["time", "io-util", "process", "fs", "sync", "signal", "macros", "rt", "rt-multi-thread"]} 28 | tokio-stream = {version = "0.1.9", features = ["io-util"]} 29 | tokio-tungstenite = {version = "0.17.2", features = ["rustls-tls-native-roots"]} 30 | tokio-tls = "0.3.1" 31 | url = "2.2.2" 32 | url_serde = "0.2.0" 33 | uuid = {version = "1.1.2", features = ["serde", "v4"]} 34 | -------------------------------------------------------------------------------- /server/renderer-server/rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2018" -------------------------------------------------------------------------------- /server/renderer-server/src/command_source/mod.rs: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2018 - present Jocelyn Stericker 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | use std::future::Future; 20 | use std::pin::Pin; 21 | use tokio::sync::mpsc::Sender; 22 | use tokio_stream::Stream; 23 | 24 | use crate::config::{CommandSourceConfig, Config}; 25 | use crate::error::HacklilyError; 26 | use crate::request::{Request, Response}; 27 | 28 | mod batch; 29 | mod test_runner; 30 | mod ws_worker_client; 31 | 32 | use self::batch::batch; 33 | use self::test_runner::test_runner; 34 | use self::ws_worker_client::ws_worker_client; 35 | 36 | #[derive(Debug)] 37 | pub struct QuitSignal {} 38 | 39 | pub type ResponseCallback = Box; 40 | pub type QuitSink = Sender; 41 | 42 | pub type RequestStream = Box< 43 | dyn Stream> + Send + Unpin + 'static, 44 | >; 45 | 46 | pub type FutureCommandSource = 47 | Pin> + Send>>; 48 | 49 | pub fn new(config: &Config) -> FutureCommandSource { 50 | match &config.command_source { 51 | CommandSourceConfig::Worker { coordinator } => { 52 | let worker_count = config.stable_worker_count + config.unstable_worker_count; 53 | Box::pin(ws_worker_client(coordinator.clone(), worker_count)) 54 | } 55 | CommandSourceConfig::Batch { path } => Box::pin(batch(path.clone())), 56 | CommandSourceConfig::TestRunner { input, output } => { 57 | Box::pin(test_runner(input.clone(), output.clone())) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /server/renderer-server/src/command_source/test_runner.rs: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2018 - present Jocelyn Stericker 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | use futures::stream; 20 | use std::collections::HashMap; 21 | use std::sync::{Arc, Mutex}; 22 | use tokio::sync::mpsc; 23 | use tokio_stream::wrappers::ReceiverStream; 24 | use tokio_stream::StreamExt; 25 | 26 | use crate::command_source::{QuitSignal, QuitSink, RequestStream, ResponseCallback}; 27 | use crate::error::HacklilyError; 28 | use crate::request::{Request, Response}; 29 | 30 | enum Event { 31 | Request((Request, ResponseCallback)), 32 | QuitSignal(QuitSignal), 33 | } 34 | 35 | async fn send_quit(quit_sink: mpsc::Sender) { 36 | quit_sink 37 | .send(QuitSignal {}) 38 | .await 39 | .expect("Cannot send quit."); 40 | } 41 | 42 | pub async fn test_runner( 43 | input: Vec, 44 | output: Arc>>, 45 | ) -> Result<(RequestStream, QuitSink), HacklilyError> { 46 | let (quit_sink, quit_stream) = mpsc::channel::(50); 47 | let quit_stream = ReceiverStream::new(quit_stream).map(Event::QuitSignal); 48 | let parent_quit_sink = quit_sink.clone(); 49 | let input_len = input.len(); 50 | 51 | let request_stream = stream::iter(input.into_iter()) 52 | .filter_map(move |request| -> Option<(Request, ResponseCallback)> { 53 | let output = output.clone(); 54 | let id = request.id.clone(); 55 | let quit_sink = quit_sink.clone(); 56 | 57 | Some(( 58 | request, 59 | Box::new(move |response: Response| { 60 | let id = id.clone(); 61 | let is_done = { 62 | let mut output = output.lock().unwrap(); 63 | if output.insert(id.clone(), response).is_some() { 64 | panic!("Invariant failed: ID {} in test is not unique", id); 65 | } 66 | 67 | output.len() == input_len 68 | }; 69 | 70 | if is_done { 71 | tokio::spawn(send_quit(quit_sink.clone())); 72 | } 73 | }), 74 | )) 75 | }) 76 | .map(Event::Request); 77 | 78 | let request_stream = stream::select(request_stream, quit_stream) 79 | .take_while(|ev| !matches!(ev, Event::QuitSignal(_))) 80 | .filter_map(|req| match req { 81 | Event::Request(r) => Some(Ok(r)), 82 | Event::QuitSignal(_) => None, 83 | }); 84 | 85 | Ok((Box::new(request_stream), parent_quit_sink)) 86 | } 87 | -------------------------------------------------------------------------------- /server/renderer-server/src/config.rs: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2018 - present Jocelyn Stericker 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | use std::collections::HashMap; 20 | use std::path::PathBuf; 21 | use std::sync::{Arc, Mutex}; 22 | use url::Url; 23 | 24 | use super::request::{Request, Response}; 25 | 26 | #[derive(Clone)] 27 | pub enum CommandSourceConfig { 28 | Worker { 29 | coordinator: Url, 30 | }, 31 | 32 | Batch { 33 | path: PathBuf, 34 | }, 35 | 36 | TestRunner { 37 | input: Vec, 38 | output: Arc>>, 39 | }, 40 | } 41 | 42 | #[derive(Clone)] 43 | pub struct Config { 44 | pub stable_docker_tag: String, 45 | pub stable_worker_count: u64, 46 | 47 | pub unstable_docker_tag: String, 48 | pub unstable_worker_count: u64, 49 | 50 | pub render_timeout_msec: u64, 51 | pub command_source: CommandSourceConfig, 52 | } 53 | -------------------------------------------------------------------------------- /server/renderer-server/src/error.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::fmt; 3 | 4 | #[derive(Debug, Clone)] 5 | pub enum HacklilyError { 6 | ContainerInitError(String), 7 | RenderError(String), 8 | RenderPanic, 9 | CommandSourceError(String), 10 | } 11 | 12 | impl fmt::Display for HacklilyError { 13 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 14 | match self { 15 | HacklilyError::ContainerInitError(reason) => write!( 16 | f, 17 | "Something went wrong while creating the render container: {}", 18 | reason 19 | ), 20 | HacklilyError::RenderError(reason) => write!(f, "Crashed during render: {}", reason), 21 | HacklilyError::RenderPanic => write!(f, "Render panic"), 22 | HacklilyError::CommandSourceError(reason) => { 23 | write!(f, "Command source error: {}", reason) 24 | } 25 | } 26 | } 27 | } 28 | 29 | impl Error for HacklilyError { 30 | fn description(&self) -> &str { 31 | match self { 32 | HacklilyError::ContainerInitError(_reason) => { 33 | "Something went wrong while creating the render container." 34 | } 35 | HacklilyError::RenderError(_reason) => "Crashed during render", 36 | HacklilyError::RenderPanic => "Render panic", 37 | HacklilyError::CommandSourceError(_reason) => "Command source error", 38 | } 39 | } 40 | 41 | fn cause(&self) -> Option<&dyn Error> { 42 | // Generic error, underlying cause isn't tracked. 43 | None 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /server/renderer-server/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(clippy::all)] 2 | /** 3 | * @license 4 | * This file is part of Hacklily, a web-based LilyPond editor. 5 | * Copyright (C) 2018 - present Jocelyn Stericker 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as 9 | * published by the Free Software Foundation, either version 3 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | mod command_source; 21 | mod config; 22 | mod container; 23 | mod error; 24 | mod event_loop; 25 | mod renderer; 26 | mod renderer_manager; 27 | pub mod request; 28 | 29 | pub use crate::config::{CommandSourceConfig, Config}; 30 | pub use crate::event_loop::event_loop; 31 | -------------------------------------------------------------------------------- /server/renderer-server/src/request.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Copy, Clone)] 4 | #[serde(rename_all = "camelCase")] 5 | pub enum Backend { 6 | Svg, 7 | Pdf, 8 | #[serde(rename = "musicxml2ly")] 9 | MusicXml2Ly, 10 | } 11 | 12 | #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Copy, Clone)] 13 | #[serde(rename_all = "camelCase")] 14 | pub enum Version { 15 | Stable, 16 | Unstable, 17 | } 18 | 19 | #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)] 20 | pub struct Request { 21 | pub id: String, 22 | pub backend: Backend, 23 | pub version: Version, 24 | pub src: String, 25 | } 26 | 27 | #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)] 28 | pub struct Response { 29 | pub files: Vec, 30 | pub logs: String, 31 | // in base64 32 | pub midi: String, 33 | } 34 | -------------------------------------------------------------------------------- /server/renderer-server/tests/evil.rs: -------------------------------------------------------------------------------- 1 | #![warn(clippy::all)] 2 | 3 | extern crate renderer_lib; 4 | 5 | mod util; 6 | 7 | use self::util::run_test; 8 | use renderer_lib::request::{Backend, Request, Response, Version}; 9 | 10 | const NUM_ITERATIONS: u32 = 5; 11 | 12 | #[test] 13 | fn evil() { 14 | // Test that some obvious evil inputs do not impact good inputs. 15 | 16 | env_logger::init(); 17 | let evils = vec![ 18 | include_str!("ly/danger_forever.ly"), 19 | include_str!("ly/danger_forkbomb.ly"), 20 | include_str!("ly/danger_kill_group.ly"), 21 | include_str!("ly/danger_kill_lilypond.ly"), 22 | include_str!("ly/danger_kill_ruby.ly"), 23 | include_str!("ly/danger_rm_home.ly"), 24 | include_str!("ly/danger_rm_slash.ly"), 25 | include_str!("ly/danger_rm_tmp.ly"), 26 | ]; 27 | 28 | fn get_request(id: &str, src: &str, version: Version) -> Request { 29 | Request { 30 | id: id.to_owned(), 31 | backend: Backend::Svg, 32 | src: src.to_owned(), 33 | version, 34 | } 35 | } 36 | 37 | let mut tests = Vec::new(); 38 | for iteration in 0..NUM_ITERATIONS { 39 | for v in &[Version::Stable, Version::Unstable] { 40 | for (evil_i, evil) in evils.iter().enumerate() { 41 | let evil_id = format!("evil_{}_{:?}_{}", evil_i, v, iteration); 42 | tests.push(get_request(&evil_id, evil, *v)); 43 | 44 | let good_id = format!("good_{}_{:?}_{}", evil_i, v, iteration); 45 | tests.push(get_request(&good_id, include_str!("ly/simple.ly"), *v)) 46 | } 47 | } 48 | } 49 | 50 | let simple_stable_response = Response { 51 | files: vec![include_str!("ly/simple.ly.2_18_2.svg").to_owned()], 52 | logs: include_str!("ly/simple.ly.2_18_2.txt").to_owned(), 53 | midi: "".to_owned(), 54 | }; 55 | 56 | let simple_unstable_response = Response { 57 | files: vec![include_str!("ly/simple.ly.2_19_82.svg").to_owned()], 58 | logs: include_str!("ly/simple.ly.2_19_82.txt").to_owned(), 59 | midi: "".to_owned(), 60 | }; 61 | 62 | let res = run_test(tests); 63 | 64 | for iteration in 0..NUM_ITERATIONS { 65 | for (evil_i, _) in evils.iter().enumerate() { 66 | // Make sure the evil outputs gave something (anything!) 67 | for v in &[Version::Stable, Version::Unstable] { 68 | let evil_id = format!("evil_{}_{:?}_{}", evil_i, v, iteration); 69 | assert!(res.get(&evil_id).is_some()); 70 | } 71 | 72 | // Make sure the good output is as it is supposed to be. 73 | let good_stable_id = format!("good_{}_{:?}_{}", evil_i, Version::Stable, iteration); 74 | let good_unstable_id = format!("good_{}_{:?}_{}", evil_i, Version::Unstable, iteration); 75 | 76 | let good_stable_output = &res[&good_stable_id]; 77 | let good_unstable_output = &res[&good_unstable_id]; 78 | 79 | assert_eq!(good_stable_output, &simple_stable_response); 80 | assert_eq!(good_unstable_output, &simple_unstable_response); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/danger_forever.ly: -------------------------------------------------------------------------------- 1 | #(system "while :; do echo hi; done") -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/danger_forkbomb.ly: -------------------------------------------------------------------------------- 1 | #(system "bash -c ':(){ :|: & };:'") -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/danger_kill_group.ly: -------------------------------------------------------------------------------- 1 | #(system "kill -9 0") -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/danger_kill_lilypond.ly: -------------------------------------------------------------------------------- 1 | #(system "killall lilypond") -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/danger_kill_ruby.ly: -------------------------------------------------------------------------------- 1 | #(system "killall ruby") -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/danger_rm_home.ly: -------------------------------------------------------------------------------- 1 | #(system "rm -fr ~/*") -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/danger_rm_slash.ly: -------------------------------------------------------------------------------- 1 | #(system "rm -fr /*") -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/danger_rm_tmp.ly: -------------------------------------------------------------------------------- 1 | #(system "rm -fr /tmp/*") -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/simple.ly: -------------------------------------------------------------------------------- 1 | {d4} -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/simple.ly.2_18_2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | Music engraving by LilyPond 2.18.2—www.lilypond.org 33 | 34 | 35 | -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/simple.ly.2_18_2.txt: -------------------------------------------------------------------------------- 1 | Lyp 1.3.8 2 | GNU LilyPond Server 2.18.2 3 | Processing `/tmp/lyp/wrappers/hacklily.ly' 4 | Parsing... 5 | Interpreting music... 6 | Preprocessing graphical objects... 7 | Finding the ideal number of pages... 8 | Fitting music on 1 page... 9 | Drawing systems... 10 | Layout output to `hacklily.svg'... 11 | > 12 | -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/simple.ly.2_19_82.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Music engraving by LilyPond 2.19.82—www.lilypond.org 32 | 33 | 34 | -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/simple.ly.2_19_82.txt: -------------------------------------------------------------------------------- 1 | Lyp 1.3.8 2 | GNU LilyPond Server 2.19.82 3 | Processing `/tmp/lyp/wrappers/hacklily.ly' 4 | Parsing... 5 | Interpreting music... 6 | Preprocessing graphical objects... 7 | Finding the ideal number of pages... 8 | Fitting music on 1 page... 9 | Drawing systems... 10 | Layout output to `hacklily.svg'... 11 | > 12 | -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/sleep.ly: -------------------------------------------------------------------------------- 1 | #(system "sleep 30000") -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/sleep.ly.2_18_2.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/server/renderer-server/tests/ly/sleep.ly.2_18_2.svg -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/sleep.ly.2_18_2.txt: -------------------------------------------------------------------------------- 1 | Lyp 1.3.8 2 | GNU LilyPond Server 2.18.2 3 | Processing `/tmp/lyp/wrappers/hacklily.ly' 4 | Parsing... 5 | -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/sleep.ly.2_19_82.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/server/renderer-server/tests/ly/sleep.ly.2_19_82.svg -------------------------------------------------------------------------------- /server/renderer-server/tests/ly/sleep.ly.2_19_82.txt: -------------------------------------------------------------------------------- 1 | Lyp 1.3.8 2 | GNU LilyPond Server 2.19.82 3 | Processing `/tmp/lyp/wrappers/hacklily.ly' 4 | Parsing... 5 | -------------------------------------------------------------------------------- /server/renderer-server/tests/simple.rs: -------------------------------------------------------------------------------- 1 | #![warn(clippy::all)] 2 | 3 | extern crate renderer_lib; 4 | 5 | mod util; 6 | 7 | use self::util::run_test; 8 | use renderer_lib::request::{Backend, Request, Response, Version}; 9 | 10 | #[test] 11 | fn simple() { 12 | fn get_request(id: &str, version: Version) -> Request { 13 | Request { 14 | id: id.to_owned(), 15 | backend: Backend::Svg, 16 | src: include_str!("ly/simple.ly").to_owned(), 17 | version, 18 | } 19 | } 20 | 21 | let stable_response = Response { 22 | files: vec![include_str!("ly/simple.ly.2_18_2.svg").to_owned()], 23 | logs: include_str!("ly/simple.ly.2_18_2.txt").to_owned(), 24 | midi: "".to_owned(), 25 | }; 26 | 27 | let unstable_response = Response { 28 | files: vec![include_str!("ly/simple.ly.2_19_82.svg").to_owned()], 29 | logs: include_str!("ly/simple.ly.2_19_82.txt").to_owned(), 30 | midi: "".to_owned(), 31 | }; 32 | 33 | assert_eq!( 34 | run_test(vec![ 35 | get_request("simple1", Version::Unstable), 36 | get_request("simple2", Version::Stable), 37 | get_request("simple3", Version::Unstable), 38 | get_request("simple4", Version::Stable), 39 | get_request("simple5", Version::Unstable), 40 | get_request("simple6", Version::Stable), 41 | get_request("simple7", Version::Unstable), 42 | get_request("simple8", Version::Stable), 43 | get_request("simple9", Version::Unstable), 44 | get_request("simple10", Version::Stable), 45 | ]), 46 | cloned_hashmap! { 47 | "simple1" => unstable_response, 48 | "simple2" => stable_response, 49 | "simple3" => unstable_response, 50 | "simple4" => stable_response, 51 | "simple5" => unstable_response, 52 | "simple6" => stable_response, 53 | "simple7" => unstable_response, 54 | "simple8" => stable_response, 55 | "simple9" => unstable_response, 56 | "simple10" => stable_response 57 | } 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /server/renderer-server/tests/sleep.rs: -------------------------------------------------------------------------------- 1 | #![warn(clippy::all)] 2 | 3 | extern crate renderer_lib; 4 | 5 | mod util; 6 | 7 | use self::util::run_test; 8 | use renderer_lib::request::{Backend, Request, Response, Version}; 9 | 10 | #[test] 11 | fn sleep() { 12 | fn get_sleep_request(id: &str, version: Version) -> Request { 13 | Request { 14 | id: id.to_owned(), 15 | backend: Backend::Svg, 16 | src: include_str!("ly/sleep.ly").to_owned(), 17 | version, 18 | } 19 | } 20 | fn get_simple_request(id: &str, version: Version) -> Request { 21 | Request { 22 | id: id.to_owned(), 23 | backend: Backend::Svg, 24 | src: include_str!("ly/simple.ly").to_owned(), 25 | version, 26 | } 27 | } 28 | 29 | let simple_stable_response = Response { 30 | files: vec![include_str!("ly/simple.ly.2_18_2.svg").to_owned()], 31 | logs: include_str!("ly/simple.ly.2_18_2.txt").to_owned(), 32 | midi: "".to_owned(), 33 | }; 34 | 35 | let simple_unstable_response = Response { 36 | files: vec![include_str!("ly/simple.ly.2_19_82.svg").to_owned()], 37 | logs: include_str!("ly/simple.ly.2_19_82.txt").to_owned(), 38 | midi: "".to_owned(), 39 | }; 40 | 41 | let sleep_stable_response = Response { 42 | files: vec![include_str!("ly/sleep.ly.2_18_2.svg").to_owned()], 43 | logs: include_str!("ly/sleep.ly.2_18_2.txt").to_owned(), 44 | midi: "".to_owned(), 45 | }; 46 | 47 | let sleep_unstable_response = Response { 48 | files: vec![include_str!("ly/sleep.ly.2_19_82.svg").to_owned()], 49 | logs: include_str!("ly/sleep.ly.2_19_82.txt").to_owned(), 50 | midi: "".to_owned(), 51 | }; 52 | 53 | assert_eq!( 54 | run_test(vec![ 55 | get_sleep_request("sleep1", Version::Unstable), 56 | get_sleep_request("sleep2", Version::Unstable), 57 | get_sleep_request("sleep3", Version::Unstable), 58 | get_sleep_request("sleep4", Version::Unstable), 59 | get_sleep_request("sleep1s", Version::Stable), 60 | get_sleep_request("sleep2s", Version::Stable), 61 | get_sleep_request("sleep3s", Version::Stable), 62 | get_sleep_request("sleep4s", Version::Stable), 63 | get_simple_request("simple1", Version::Unstable), 64 | get_simple_request("simple1s", Version::Stable), 65 | ]), 66 | cloned_hashmap! { 67 | "sleep1" => sleep_unstable_response, 68 | "sleep2" => sleep_unstable_response, 69 | "sleep3" => sleep_unstable_response, 70 | "sleep4" => sleep_unstable_response, 71 | "sleep1s" => sleep_stable_response, 72 | "sleep2s" => sleep_stable_response, 73 | "sleep3s" => sleep_stable_response, 74 | "sleep4s" => sleep_stable_response, 75 | "simple1" => simple_unstable_response, 76 | "simple1s" => simple_stable_response 77 | } 78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /server/renderer-server/tests/util.rs: -------------------------------------------------------------------------------- 1 | use renderer_lib::request::{Request, Response}; 2 | use renderer_lib::{event_loop, CommandSourceConfig, Config}; 3 | use std::collections::HashMap; 4 | use std::sync::{Arc, Mutex}; 5 | 6 | #[macro_export] 7 | macro_rules! cloned_hashmap( 8 | { $($key:expr => $value:expr),+ } => { 9 | { 10 | let mut m = ::std::collections::HashMap::new(); 11 | $( 12 | m.insert($key.to_owned(), $value.clone()); 13 | )+ 14 | m 15 | } 16 | }; 17 | ); 18 | 19 | pub fn run_test(requests: Vec) -> HashMap { 20 | let output = Arc::new(Mutex::new(HashMap::new())); 21 | let config = Config { 22 | stable_docker_tag: "hacklily-renderer".to_owned(), 23 | stable_worker_count: 4, 24 | unstable_docker_tag: "hacklily-renderer-unstable".to_owned(), 25 | unstable_worker_count: 4, 26 | render_timeout_msec: 8000, 27 | command_source: CommandSourceConfig::TestRunner { 28 | input: requests, 29 | output: output.clone(), 30 | }, 31 | }; 32 | tokio::runtime::Builder::new_multi_thread() 33 | .enable_all() 34 | .build() 35 | .unwrap() 36 | .block_on(event_loop(config)); 37 | 38 | let responses = output.lock().expect("Test runner panicked."); 39 | responses.clone() 40 | } 41 | -------------------------------------------------------------------------------- /server/renderer-unstable/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:sid-slim 2 | RUN echo \ 3 | 'deb http://snapshot.debian.org/archive/debian/20230531T025815Z/ sid main' > /etc/apt/sources.list.d/snapshot.list \ 4 | && printf "Package: ghostscript\nPin: origin snapshot.debian.org\nPin-Priority: 990\n\n" > /etc/apt/preferences.d/snapshot \ 5 | && printf "Package: libgs10\nPin: origin snapshot.debian.org\nPin-Priority: 990\n\n" >> /etc/apt/preferences.d/snapshot \ 6 | && printf "Package: libgs10-common\nPin: origin snapshot.debian.org\nPin-Priority: 990\n\n" >> /etc/apt/preferences.d/snapshot \ 7 | && apt-get -o Acquire::Check-Valid-Until=false update 8 | RUN apt-get -o Acquire::Check-Valid-Until=false install --no-install-recommends -y ruby curl bzip2 git locales gsfonts ghostscript fonts-dejavu-extra psmisc emacs-intl-fonts xfonts-intl-.* fonts-ipafont-mincho xfonts-bolkhov-75dpi xfonts-cronyx-100dpi xfonts-cronyx-75dpi patch python3 adduser && \ 9 | localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 && \ 10 | curl -L https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 > /usr/local/bin/jq && \ 11 | chmod +x /usr/local/bin/jq && echo 42 | jq . 12 | ENV LANG en_US.UTF-8 13 | ENV LANGUAGE en_US:en 14 | ENV LC_ALL en_US.UTF-8 15 | COPY no_lyp_check_update.patch /tmp 16 | RUN adduser --disabled-password --gecos '' r && \ 17 | chown -R r /tmp && \ 18 | chown -R r /home/r && \ 19 | curl -OL https://github.com/noteflakes/lyp/releases/download/1.3.8/lyp-1.3.8-linux-x86_64.tar.gz && \ 20 | tar -xzf lyp-1.3.8-linux-x86_64.tar.gz && \ 21 | chown -R r ./lyp-1.3.8-linux-x86_64 && \ 22 | su r -c "./lyp-1.3.8-linux-x86_64/bin/lyp install self" && \ 23 | cd ~r/.lyp && \ 24 | patch -p0 < /tmp/no_lyp_check_update.patch && \ 25 | rm /tmp/no_lyp_check_update.patch && \ 26 | su r -c "source ~/.profile; lyp install lilypond@2.22.2 && cd; git clone https://github.com/lyp-packages/lys; lyp install lys@dev:~/lys" && \ 27 | rm /home/r/.lyp/lilyponds/*/etc/relocate/gs.reloc && \ 28 | rm /home/r/.lyp/lilyponds/*/bin/gs && \ 29 | chown r -R /tmp/* && \ 30 | chown nobody -R /home/r/.lyp/* /home/r/lys 31 | RUN apt-get remove -y curl patch && apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* 32 | RUN su r -c "source ~/.profile; cd /tmp; echo '{c4}' | lilypond --verbose -" 33 | COPY render-impl.bash /usr/local/bin 34 | USER r 35 | CMD render-impl.bash 36 | -------------------------------------------------------------------------------- /server/renderer-unstable/no_lyp_check_update.patch: -------------------------------------------------------------------------------- 1 | --- lib/app/bin/lilypond 2018-09-30 00:11:17.000000000 +0000 2 | +++ lib/app/bin/lilypond_new 2018-09-30 16:04:31.247756000 +0000 3 | @@ -50,7 +50,8 @@ 4 | puts `#{$lilypond_path} #{$argv.join(' ')}` 5 | puts LYP_LY_HELP unless $argv.first == '-dhelp' 6 | else 7 | - Lyp::Lilypond.check_update 8 | + puts "Not checking for updates" 9 | + # Lyp::Lilypond.check_update 10 | begin 11 | if $options[:resolve] && $argv.last != '-' 12 | resolver = Lyp::DependencyResolver.new($argv.last) 13 | -------------------------------------------------------------------------------- /server/renderer-unstable/render-impl.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This program is free software: you can redistribute it and/or modify 3 | # it under the terms of the GNU Affero General Public License as 4 | # published by the Free Software Foundation, either version 3 of the 5 | # License, or (at your option) any later version. 6 | # 7 | # This program is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | # GNU Affero General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU Affero General Public License 13 | # along with this program. If not, see . 14 | source ~/.profile 15 | 16 | IFS=" 17 | " 18 | export RUBYOPT="-KU -E utf-8:utf-8" 19 | cd /tmp 20 | cat << EOF > /tmp/start.ly 21 | \\require "lys" 22 | #(lys:start-server) 23 | EOF 24 | 25 | 26 | while read -r line 27 | do 28 | until printf "" 2>>/dev/null >>/dev/tcp/localhost/1225; do sleep 0.05; done 29 | backend=$( echo "$line" | jq -r .backend ) 30 | if [ "$backend" == "musicxml2ly" ]; then 31 | echo "$line" | jq -r .src | ~/.lyp/lilyponds/2.23.2/bin/musicxml2ly - -o hacklily.musicxml2ly.ly 2> hacklily.err 1>&2 32 | jq -Rs . hacklily.err > hacklily.err.json 33 | jq -Rsrc '{files: [.], logs: $errors, midi: ""}' hacklily.musicxml2ly.ly \ 34 | --argfile errors hacklily.err.json \ 35 | 2> /dev/null 36 | continue 37 | fi 38 | 39 | echo "$line" | jq -r .src > hacklily.ly 2> /dev/null 40 | 41 | timeout -s15 5 lyp compile -s /tmp/hacklily.ly 2> hacklily.err 1>&2 42 | if [ $? -eq 137 ]; then 43 | echo '{"err": "Failed to render song."}' 44 | echo 'failed to render' >&2 45 | continue 46 | fi; 47 | 48 | for f in hacklily*.$backend 49 | do 50 | if [ "hacklily*.$backend" == "$f" ]; then 51 | echo '""' > "hacklily-null.$backend.json" 52 | elif [ "$backend" == "svg" ]; then 53 | jq -Rs . $f > $f.json 2>&1 54 | else 55 | cat $f | base64 | jq -Rs . > $f.json 2>&1 56 | fi 57 | done 58 | touch hacklily.midi # Allow blank files 59 | cat hacklily.midi | base64 | jq -Rs . > hacklily.midi.json 2>&1 60 | jq -Rs . hacklily.err > hacklily.err.json 61 | jq -src '{files: ., logs: $errors, midi: $midi}' hacklily*.$backend.json \ 62 | --argfile errors hacklily.err.json \ 63 | --argfile midi hacklily.midi.json \ 64 | 2> /dev/null 65 | 66 | rm hacklily* > /dev/null 2> /dev/null 67 | done < "${1:-/dev/stdin}" & 68 | 69 | bash -c "lilypond /tmp/start.ly 1>&2" 70 | -------------------------------------------------------------------------------- /server/renderer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:sid-slim 2 | RUN echo \ 3 | 'deb http://snapshot.debian.org/archive/debian/20230531T025815Z/ sid main' > /etc/apt/sources.list.d/snapshot.list \ 4 | && printf "Package: ghostscript\nPin: origin snapshot.debian.org\nPin-Priority: 990\n\n" > /etc/apt/preferences.d/snapshot \ 5 | && printf "Package: libgs10\nPin: origin snapshot.debian.org\nPin-Priority: 990\n\n" >> /etc/apt/preferences.d/snapshot \ 6 | && printf "Package: libgs10-common\nPin: origin snapshot.debian.org\nPin-Priority: 990\n\n" >> /etc/apt/preferences.d/snapshot \ 7 | && apt-get -o Acquire::Check-Valid-Until=false update 8 | RUN apt-get -o Acquire::Check-Valid-Until=false install --no-install-recommends -y ruby curl bzip2 git locales gsfonts ghostscript fonts-dejavu-extra psmisc emacs-intl-fonts xfonts-intl-.* fonts-ipafont-mincho xfonts-bolkhov-75dpi xfonts-cronyx-100dpi xfonts-cronyx-75dpi patch python3 adduser && \ 9 | localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 && \ 10 | curl -L https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 > /usr/local/bin/jq && \ 11 | chmod +x /usr/local/bin/jq && echo 42 | jq . 12 | ENV LANG en_US.UTF-8 13 | ENV LANGUAGE en_US:en 14 | ENV LC_ALL en_US.UTF-8 15 | COPY no_lyp_check_update.patch /tmp 16 | RUN adduser --disabled-password --gecos '' r && \ 17 | chown -R r /tmp && \ 18 | chown -R r /home/r && \ 19 | curl -OL https://github.com/noteflakes/lyp/releases/download/1.3.8/lyp-1.3.8-linux-x86_64.tar.gz && \ 20 | tar -xzf lyp-1.3.8-linux-x86_64.tar.gz && \ 21 | chown -R r ./lyp-1.3.8-linux-x86_64 && \ 22 | su r -c "./lyp-1.3.8-linux-x86_64/bin/lyp install self" && \ 23 | cd ~r/.lyp && \ 24 | patch -p0 < /tmp/no_lyp_check_update.patch && \ 25 | rm /tmp/no_lyp_check_update.patch && \ 26 | su r -c "source ~/.profile; lyp install lilypond@2.22.2 && cd; git clone https://github.com/lyp-packages/lys; lyp install lys@dev:~/lys" && \ 27 | rm /home/r/.lyp/lilyponds/*/etc/relocate/gs.reloc && \ 28 | rm /home/r/.lyp/lilyponds/*/bin/gs && \ 29 | chown r -R /tmp/* && \ 30 | chown nobody -R /home/r/.lyp/* /home/r/lys 31 | RUN apt-get remove -y curl patch && apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* 32 | RUN su r -c "source ~/.profile; cd /tmp; echo '{c4}' | lilypond --verbose -" 33 | COPY render-impl.bash /usr/local/bin 34 | USER r 35 | CMD render-impl.bash 36 | -------------------------------------------------------------------------------- /server/renderer/no_lyp_check_update.patch: -------------------------------------------------------------------------------- 1 | --- lib/app/bin/lilypond 2018-09-30 00:11:17.000000000 +0000 2 | +++ lib/app/bin/lilypond_new 2018-09-30 16:04:31.247756000 +0000 3 | @@ -50,7 +50,8 @@ 4 | puts `#{$lilypond_path} #{$argv.join(' ')}` 5 | puts LYP_LY_HELP unless $argv.first == '-dhelp' 6 | else 7 | - Lyp::Lilypond.check_update 8 | + puts "Not checking for updates" 9 | + # Lyp::Lilypond.check_update 10 | begin 11 | if $options[:resolve] && $argv.last != '-' 12 | resolver = Lyp::DependencyResolver.new($argv.last) 13 | -------------------------------------------------------------------------------- /server/renderer/render-impl.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This program is free software: you can redistribute it and/or modify 3 | # it under the terms of the GNU Affero General Public License as 4 | # published by the Free Software Foundation, either version 3 of the 5 | # License, or (at your option) any later version. 6 | # 7 | # This program is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | # GNU Affero General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU Affero General Public License 13 | # along with this program. If not, see . 14 | source ~/.profile 15 | 16 | IFS=" 17 | " 18 | export RUBYOPT="-KU -E utf-8:utf-8" 19 | cd /tmp 20 | cat << EOF > /tmp/start.ly 21 | \\require "lys" 22 | #(lys:start-server) 23 | EOF 24 | 25 | 26 | while read -r line 27 | do 28 | until printf "" 2>>/dev/null >>/dev/tcp/localhost/1225; do sleep 0.05; done 29 | backend=$( echo "$line" | jq -r .backend ) 30 | if [ "$backend" == "musicxml2ly" ]; then 31 | echo "$line" | jq -r .src | ~/.lyp/lilyponds/2.22.1/bin/musicxml2ly - -o hacklily.musicxml2ly.ly 2> hacklily.err 1>&2 32 | jq -Rs . hacklily.err > hacklily.err.json 33 | jq -Rsrc '{files: [.], logs: $errors, midi: ""}' hacklily.musicxml2ly.ly \ 34 | --argfile errors hacklily.err.json \ 35 | 2> /dev/null 36 | continue 37 | fi 38 | 39 | echo "$line" | jq -r .src > hacklily.ly 2> /dev/null 40 | 41 | timeout -s15 5 lyp compile -s /tmp/hacklily.ly 2> hacklily.err 1>&2 42 | if [ $? -eq 137 ]; then 43 | echo '{"err": "Failed to render song."}' 44 | echo 'failed to render' >&2 45 | continue 46 | fi; 47 | 48 | for f in hacklily*.$backend 49 | do 50 | if [ "hacklily*.$backend" == "$f" ]; then 51 | echo '""' > "hacklily-null.$backend.json" 52 | elif [ "$backend" == "svg" ]; then 53 | jq -Rs . $f > $f.json 2>&1 54 | else 55 | cat $f | base64 | jq -Rs . > $f.json 2>&1 56 | fi 57 | done 58 | touch hacklily.midi # Allow blank files 59 | cat hacklily.midi | base64 | jq -Rs . > hacklily.midi.json 2>&1 60 | jq -Rs . hacklily.err > hacklily.err.json 61 | jq -src '{files: ., logs: $errors, midi: $midi}' hacklily*.$backend.json \ 62 | --argfile errors hacklily.err.json \ 63 | --argfile midi hacklily.midi.json \ 64 | 2> /dev/null 65 | 66 | rm hacklily* > /dev/null 2> /dev/null 67 | done < "${1:-/dev/stdin}" & 68 | 69 | bash -c "lilypond /tmp/start.ly 1>&2" 70 | -------------------------------------------------------------------------------- /server/ws-server/hacklilyserver.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as 8 | * published by the Free Software Foundation, either version 3 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef HACKLILYSERVER_H 21 | #define HACKLILYSERVER_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | struct HacklilyServerRequest 33 | { 34 | /** 35 | * @brief src Lilypond source 36 | */ 37 | QString src; 38 | /** 39 | * @brief backend svg | pdf 40 | */ 41 | QString backend; 42 | /** 43 | * @brief version stable | unstable 44 | */ 45 | QString version; 46 | QWebSocket *sender; 47 | QString requestID; 48 | 49 | QTime received; 50 | QTime renderStart; 51 | }; 52 | 53 | struct UserInfo 54 | { 55 | QByteArray accessToken; 56 | QString name; 57 | QString username; 58 | QString email; 59 | }; 60 | 61 | #define ERROR_JSON_PARSE 1 62 | #define ERROR_INTERNAL 2 63 | #define ERROR_GITHUB 3 64 | 65 | class HacklilyServer : public QObject 66 | { 67 | Q_OBJECT 68 | public: 69 | explicit HacklilyServer( 70 | QString rendererDockerTag, 71 | QString rendererUnstableDockerTag, 72 | int wsPort, 73 | QByteArray ghClientID, 74 | QByteArray ghSecret, 75 | int jobs, 76 | QObject *parent = 0); 77 | explicit HacklilyServer( 78 | QString rendererDockerTag, 79 | QString rendererUnstableDockerTag, 80 | QString coordinator, 81 | int jobs, 82 | QObject *parent = 0); 83 | virtual ~HacklilyServer(); 84 | 85 | signals: 86 | 87 | private slots: 88 | // Common 89 | void _handleNewConnection(); 90 | void _handleTextMessageReceived(QString message); 91 | void _handleBinaryMessageReceived(QByteArray ba); 92 | void _handleSocketDisconnected(); 93 | void _initRenderers(); 94 | void _processIfPossible(); 95 | void _handleRendererOutput(); 96 | void _handleRendererFinished(int exitCode, QProcess::ExitStatus); 97 | void _createRenderer(bool isUnstable, int rendererId); 98 | void _resetRenderer(int rendererId); 99 | void _doRender(HacklilyServerRequest req, int rendererId); 100 | void _checkForHangingRender(); 101 | void _sendUserInfo(QString requestID, int socketID); 102 | 103 | // Coordinator -- login flow 104 | void _handleOAuthReply(); 105 | void _handleUserReply(); 106 | 107 | // Coordinator -- logout flow 108 | void _handleOAuthDelete(); 109 | 110 | // Coordinator -- workers 111 | void _removeWorker(); 112 | 113 | // Worker 114 | void _openCoordinator(); 115 | void _handleCoordinatorConnected(); 116 | void _handleCoordinatorError(QAbstractSocket::SocketError err); 117 | void _handleCoordinatorDisconnected(); 118 | void _doCoordinatorPing(); 119 | 120 | private: 121 | // environment 122 | QString _rendererDockerTag; 123 | QString _rendererUnstableDockerTag; 124 | 125 | // environment (coordinator) 126 | int _wsPort; 127 | QByteArray _ghClientID; 128 | QByteArray _ghSecret; 129 | QList _freeWorkers; 130 | QMap _busyWorkers; 131 | 132 | // environment (worker) 133 | QString _coordinatorURL; 134 | 135 | // state (all) 136 | int _analytics_renders; 137 | int _analytics_saves; 138 | int _analytics_sign_in; 139 | QList _renderers; 140 | QList _rendererVersion; /// stable or unstable 141 | QMap _sockets; /// by socket id 142 | QMap _userInfo; /// by request id 143 | int _lastSocketID; 144 | QList _requests; 145 | QMap _localProcessingRequests; 146 | QMap _remoteProcessingRequests; 147 | QNetworkAccessManager *_nam; 148 | int _maxJobs; 149 | QDateTime _startupTime; 150 | 151 | // state (coordinator) 152 | QWebSocketServer *_server; 153 | 154 | // state (worker) 155 | QWebSocket *_coordinator; 156 | QTimer *_coordinatorPingTimer; 157 | }; 158 | 159 | #endif // HACKLILYSERVER_H 160 | -------------------------------------------------------------------------------- /server/ws-server/ws-server.pro: -------------------------------------------------------------------------------- 1 | QT += core websockets 2 | QT -= gui 3 | 4 | CONFIG += c++11 5 | 6 | TARGET = ws-server 7 | CONFIG += console 8 | CONFIG -= app_bundle 9 | 10 | TEMPLATE = app 11 | 12 | SOURCES += main.cpp \ 13 | hacklilyserver.cpp 14 | 15 | # The following define makes your compiler emit warnings if you use 16 | # any feature of Qt which as been marked deprecated (the exact warnings 17 | # depend on your compiler). Please consult the documentation of the 18 | # deprecated API in order to know how to port your code away from it. 19 | DEFINES += QT_DEPRECATED_WARNINGS 20 | 21 | # You can also make your code fail to compile if you use deprecated APIs. 22 | # In order to do so, uncomment the following line. 23 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 24 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 25 | 26 | HEADERS += \ 27 | hacklilyserver.h 28 | -------------------------------------------------------------------------------- /src/ButtonGroup.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | * 20 | * Copyright notice for the original version of this file 21 | * (https://github.com/Khan/react-components/blob/master/js/button-group.jsx): 22 | * 23 | * The MIT License (MIT) 24 | * 25 | * Copyright (c) 2014 Khan Academy 26 | * 27 | * Permission is hereby granted, free of charge, to any person obtaining a copy 28 | * of this software and associated documentation files (the "Software"), to deal 29 | * in the Software without restriction, including without limitation the rights 30 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 31 | * copies of the Software, and to permit persons to whom the Software is 32 | * furnished to do so, subject to the following conditions: 33 | * 34 | * The above copyright notice and this permission notice shall be included in all 35 | * copies or substantial portions of the Software. 36 | * 37 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 39 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 43 | * SOFTWARE. 44 | */ 45 | 46 | import { css } from "aphrodite"; 47 | import React from "react"; 48 | import { BUTTON_STYLE } from "./styles"; 49 | 50 | export interface ButtonSpec { 51 | content?: React.ReactNode; 52 | title?: string; 53 | value: string | number | null; 54 | } 55 | 56 | interface Props { 57 | allowEmpty?: boolean; 58 | buttons: ButtonSpec[]; 59 | value: string | number | null; 60 | onChange(value: string | number | null): void; 61 | } 62 | 63 | /** 64 | * ButtonGroup is an aesthetically pleasing group of buttons. 65 | * 66 | * The class requires these properties: 67 | * buttons - an array of objects with keys: 68 | * "value": this is the value returned when the button is selected 69 | * "content": this is the JSX shown within the button, typically a string 70 | * that gets rendered as the button's display text 71 | * "title": this is the title-text shown on hover 72 | * onChange - a function that is provided with the updated value 73 | * (which it then is responsible for updating) 74 | * 75 | * The class has these optional properties: 76 | * value - the initial value of the button selected, defaults to null. 77 | * allowEmpty - if false, exactly one button _must_ be selected; otherwise 78 | * it defaults to true and _at most_ one button (0 or 1) may be selected. 79 | * 80 | * Requires stylesheets/perseus-admin-package/editor.less to look nice. 81 | */ 82 | export default class ButtonGroup extends React.PureComponent { 83 | static defaultProps: Partial = { 84 | allowEmpty: true, 85 | value: null, 86 | }; 87 | 88 | render(): JSX.Element { 89 | const value: string | number | null = this.props.value; 90 | const buttons: JSX.Element[] = this.props.buttons.map( 91 | (button: ButtonSpec, i: number) => { 92 | const buttonGroupClassName: string = css( 93 | BUTTON_STYLE.buttonStyle, 94 | button.value === value && BUTTON_STYLE.selectedStyle, 95 | ); 96 | 97 | return ( 98 | 109 | ); 110 | }, 111 | ); 112 | 113 | const outerStyle: object = { 114 | display: "inline-block", 115 | }; 116 | 117 | return
{buttons}
; 118 | } 119 | 120 | private handleClick = (ev: React.MouseEvent): void => { 121 | this.toggleSelect(JSON.parse(ev.currentTarget.dataset.value || "null")); 122 | }; 123 | 124 | private toggleSelect(newValue: string | number | null): void { 125 | const value: string | number | null = this.props.value; 126 | 127 | if (this.props.allowEmpty) { 128 | // Select the new button or unselect if it's already selected 129 | this.props.onChange(value !== newValue ? newValue : null); 130 | } else { 131 | this.props.onChange(newValue); 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/FileMenu.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import { Menu, MenuDivider, MenuItem } from "@blueprintjs/core"; 22 | import React from "react"; 23 | 24 | import { Auth } from "./auth"; 25 | 26 | interface Props { 27 | auth: Auth | null; 28 | canCreateNew: boolean; 29 | canExport: boolean; 30 | canSave: boolean; 31 | canSaveAs: boolean; 32 | songURL: string | null; 33 | colourScheme: "vs-dark" | "vs"; 34 | onExportLy(): any; 35 | onExportMIDI(): any; 36 | onExportPDF(): any; 37 | onDeleteSong(song: string): void; 38 | onLoadSong(song: string): void; 39 | onShowAbout(): void; 40 | onShowClone(): void; 41 | onShowOpen(): void; 42 | onShowNew(): void; 43 | onShowPublish(): void; 44 | onSignIn(): void; 45 | onSignOut(): void; 46 | setColourScheme(colourScheme: "vs-dark" | "vs"): void; 47 | } 48 | 49 | /** 50 | * Renders the File menu. 51 | * The menu button is rendered by
52 | */ 53 | export default class FileMenu extends React.PureComponent { 54 | render(): JSX.Element { 55 | const { 56 | auth, 57 | canCreateNew, 58 | canExport, 59 | canSave, 60 | canSaveAs, 61 | onSignOut, 62 | onShowAbout, 63 | onShowClone, 64 | onShowOpen, 65 | onExportLy, 66 | onExportMIDI, 67 | onExportPDF, 68 | onShowNew, 69 | onShowPublish, 70 | songURL, 71 | } = this.props; 72 | 73 | let signOut: React.ReactNode; 74 | if (auth) { 75 | signOut = ; 76 | } 77 | 78 | const tutorial: React.ReactNode = ( 79 | 86 | ); 87 | 88 | const about: React.ReactNode = ( 89 | 90 | ); 91 | 92 | return ( 93 | 94 | 100 | 101 | 106 | 111 | 117 | 123 | 124 | 125 | 126 | 127 | {songURL && } 128 | {songURL && ( 129 | 134 | )} 135 | 136 | 137 | {this.renderSetColourScheme()} 138 | {signOut} 139 | 140 | {tutorial} 141 | {about} 142 | 143 | ); 144 | } 145 | 146 | private handleColourSchemeToggled = (): void => { 147 | const newColourScheme: "vs-dark" | "vs" = 148 | this.props.colourScheme === "vs-dark" ? "vs" : "vs-dark"; 149 | 150 | this.props.setColourScheme(newColourScheme); 151 | }; 152 | 153 | private renderSetColourScheme(): React.ReactNode { 154 | const text: string = 155 | this.props.colourScheme === "vs-dark" 156 | ? "Use light colour scheme" 157 | : "Use dark colour scheme"; 158 | 159 | return ( 160 | 165 | ); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/LICENSE_HEADER.txt: -------------------------------------------------------------------------------- 1 | @source: https://github.com/emilyskidsister/hacklily/archive/master.tar.gz 2 | 3 | @licstart The following is the entire license notice for the 4 | JavaScript code in this page. 5 | 6 | Copyright (C) 2017 - present Jocelyn Stericker 7 | 8 | The JavaScript code in this page is free software: you can 9 | redistribute it and/or modify it under the terms of the GNU 10 | General Public License (GNU GPL) as published by the Free Software 11 | Foundation, either version 3 of the License, or (at your option) 12 | any later version. The code is distributed WITHOUT ANY WARRANTY; 13 | without even the implied warranty of MERCHANTABILITY or FITNESS 14 | FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. 15 | 16 | As additional permission under GNU GPL version 3 section 7, you 17 | may distribute non-source (e.g., minimized or compacted) forms of 18 | that code without the copy of the GNU GPL normally required by 19 | section 4, provided you include this license notice and a URL 20 | through which recipients can access the Corresponding Source. 21 | 22 | As additional permission under GNU GPL version 3 section 7, 23 | the term "System Libraries" is extended to include the JavaScript 24 | libraries provided with any browser. If you modify this code, you 25 | may extend this exception to your version of the code, but you are 26 | not obligated to do so. If you do not wish to do so, delete this 27 | exception statement from your version. 28 | 29 | SEE ADDITIONAL COPYRIGHT NOTICES AT /about-javascript.html. 30 | 31 | @licend The above is the entire license notice 32 | for the JavaScript code in this file. 33 | 34 | -------------------------------------------------------------------------------- /src/Logs.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import { Button, Drawer, Position, Tooltip } from "@blueprintjs/core"; 22 | import { css, StyleSheet } from "aphrodite"; 23 | import React from "react"; 24 | 25 | interface Props { 26 | loading: boolean; 27 | logs: string | null; 28 | } 29 | 30 | interface State { 31 | showLogDrawer: boolean; 32 | } 33 | 34 | /** 35 | * Renders a logs button, that when hovered, expands to show the output from Lilypond. 36 | * 37 | * This is visible in the app whenever the preview is visible. 38 | */ 39 | export default class Logs extends React.Component { 40 | state = { 41 | showLogDrawer: false, 42 | }; 43 | 44 | render(): JSX.Element | null { 45 | const { logs, loading } = this.props; 46 | const { showLogDrawer } = this.state; 47 | 48 | const error = !logs || logs.includes("error") || logs.includes("warning"); 49 | const icon = error && !loading ? "warning-sign" : "info-sign"; 50 | 51 | const btn = ( 52 | 61 | ); 62 | 63 | return ( 64 |
65 | 72 |
{logs}
73 |
74 | {logs}} 77 | position={Position.TOP} 78 | > 79 | {btn} 80 | 81 |
82 | ); 83 | } 84 | 85 | handleClose = () => { 86 | this.setState({ showLogDrawer: false }); 87 | }; 88 | 89 | handleOpen = () => { 90 | this.setState({ showLogDrawer: true }); 91 | }; 92 | } 93 | 94 | export const styles = StyleSheet.create({ 95 | logsButtonWrapper: { 96 | position: "absolute", 97 | right: 20, 98 | bottom: 10, 99 | }, 100 | logPreview: { 101 | maxHeight: "calc(100vh - 100px)", 102 | whiteSpace: "pre-wrap", 103 | overflow: "hidden", 104 | margin: 0, 105 | position: "relative", 106 | paddingBottom: 16, 107 | ":after": { 108 | content: "''", 109 | color: "white", 110 | position: "absolute", 111 | bottom: -16, 112 | fontWeight: "bold", 113 | width: "100%", 114 | height: 40, 115 | background: 116 | "-webkit-linear-gradient( rgba(57, 75, 89, 0) 0%, rgba(57, 75, 89, 1) 100%)", 117 | backgroundImage: 118 | "-moz-linear-gradient( rgba(57, 75, 89, 0) 0%, rgba(57, 75, 89, 1) 100%), " + 119 | "-o-linear-gradient( rgba(57, 75, 89, 0) 0%, rgba(57, 75, 89, 1) 100%), " + 120 | "linear-gradient( rgba(57, 75, 89, 0) 0%, rgba(57, 75, 89, 1) 100%), " + 121 | "-ms-linear-gradient( rgba(57, 75, 89, 0) 0%, rgba(57, 75, 89, 1) 100%)", 122 | }, 123 | }, 124 | logDrawer: { 125 | paddingTop: 20, 126 | paddingBottom: 20, 127 | marginTop: 0, 128 | marginBottom: 0, 129 | marginRight: 0, 130 | marginLeft: 20, 131 | overflow: "auto", 132 | whiteSpace: "pre-wrap", 133 | }, 134 | logPreviewHint: { 135 | marginTop: 0, 136 | marginBottom: 8, 137 | }, 138 | }); 139 | -------------------------------------------------------------------------------- /src/Modal404.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import { Button, Classes, Dialog, Intent } from "@blueprintjs/core"; 22 | import React from "react"; 23 | 24 | interface Props { 25 | onHide(): void; 26 | } 27 | 28 | /** 29 | * A 404 modal that is rendered when the 404 query is set. 30 | * 31 | * 404.html (which GitHub pages will render for every unmatched URL) redirects to 32 | * '/?404=1', which renders , which results in this modal being shown. 33 | */ 34 | export default class Modal404 extends React.PureComponent { 35 | render(): JSX.Element { 36 | return ( 37 | 38 |
39 |

The requested page may have been moved or deleted.

40 |

41 | Hacklily is a free online sheet-music editor and publishing tool. 42 | While you are here, why not give it a try? 43 |

44 |
45 |
46 |
47 | 50 |
51 |
52 |
53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ModalConflict.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import { Button, Classes, Dialog, Intent } from "@blueprintjs/core"; 22 | import React from "react"; 23 | 24 | interface Props { 25 | resolveGitHub(): void; 26 | resolveLocalStorage(): void; 27 | } 28 | 29 | /** 30 | * This is shown when you load a song that was loaded dirty and has been edited elsewhere. 31 | */ 32 | export default class ModalConflict extends React.PureComponent { 33 | render(): JSX.Element { 34 | return ( 35 | 36 |
37 |

38 | This song was edited outside of this browser. You 39 | can either keep the unsaved version from this browser, or revert to 40 | the saved version. 41 |

42 |

43 | Tip: Next time, save songs before closing 44 | Hacklily. 45 |

46 |
47 |
48 |
49 | 55 | 58 |
59 |
60 |
61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/ModalLocked.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import { AnchorButton, Classes, Dialog, Intent } from "@blueprintjs/core"; 22 | import React from "react"; 23 | 24 | /** 25 | * A modal that is rendered when this song is being edited in another tab. 26 | * There's no escaping this modal. You need to reload or close the tab to continue. 27 | */ 28 | export default class ModalLocked extends React.PureComponent { 29 | render(): JSX.Element { 30 | return ( 31 | 39 |
40 | This song was opened in another tab. You can only edit in one tab at 41 | once. If you have closed the other tab, you may{" "} 42 | resume editing here. 43 |
44 |
45 |
46 | 51 | Reload 52 | 53 |
54 |
55 |
56 | ); 57 | } 58 | } 59 | 60 | export function lock(songID: string): void { 61 | // This is a trick to send a notification to other pages editing this document. 62 | // Other tabs can listen to the 'storage' event and lock when startedEditedNotification is set to 63 | // a song they are editing. 64 | localStorage.setItem("startedEditingNotification", songID); 65 | localStorage.removeItem("startedEditingNotification"); 66 | } 67 | 68 | let editingNotificationHandler: null | ((ev: StorageEvent) => void) = null; 69 | /** 70 | * Calls handler when another tab starts editing a song. 71 | */ 72 | export function setEditingNotificationHandler( 73 | handler: null | ((songID: string) => void), 74 | ): void { 75 | if (editingNotificationHandler) { 76 | window.removeEventListener("storage", editingNotificationHandler); 77 | editingNotificationHandler = null; 78 | } 79 | if (handler) { 80 | editingNotificationHandler = (ev: StorageEvent): void => { 81 | if (ev.key === "startedEditingNotification" && ev.newValue) { 82 | handler(ev.newValue); 83 | } 84 | }; 85 | window.addEventListener("storage", editingNotificationHandler); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/ModalSaving.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import { Classes, Dialog, Spinner } from "@blueprintjs/core"; 22 | import React from "react"; 23 | 24 | /** 25 | * A modal that is rendered while saving a song. 26 | * There's no escaping this modal. It's visible until saving completes. 27 | */ 28 | class ModalSaving extends React.PureComponent { 29 | render(): JSX.Element { 30 | return ( 31 | 38 |
39 | 40 |
41 |
42 | ); 43 | } 44 | } 45 | 46 | export default ModalSaving; 47 | -------------------------------------------------------------------------------- /src/ModalUnsavedChangesInterstitial.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import { Button, Classes, Dialog, Intent } from "@blueprintjs/core"; 22 | import React from "react"; 23 | 24 | interface Props { 25 | cancel(): void; 26 | discardChanges(): void; 27 | save(): void; 28 | } 29 | 30 | /** 31 | * This is the "Do you want to save your changes" modal you get when you load a song 32 | * while the current one has unsaved changes in the current song. 33 | * 34 | * Now, we could instead just redirect the user, since we do store the code for 35 | * ALL songs that are dirty in localStorage, but that may result in the user being 36 | * confused when she or he tries editing the song somewhere else and isn't sure where 37 | * the source went. Multiple sources of truth are bad in this case. So we leave this 38 | * feature only for the case when the tab is closed without saving. In no case will 39 | * the page change while leaving dirty state for the old song. 40 | * 41 | * This modal requests to be closed by calling one of the three callbacks. 42 | */ 43 | export default class ModalUnsavedChangesInterstitial extends React.PureComponent { 44 | render(): JSX.Element { 45 | return ( 46 | 47 |
48 |

49 | Your changes have not been saved. 50 |

51 |

52 | If you do not save your changes, they will be{" "} 53 | permanently lost! 54 |

55 |
56 |
57 |
58 |
59 | 60 | 67 | 74 |
75 |
76 |
77 |
78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/auth.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import RPCClient, { SignInResponse } from "./RPCClient"; 22 | 23 | export interface Repo { 24 | ["private"]: boolean; 25 | 26 | created_at: string; 27 | description: string; 28 | fork: false; 29 | forks_count: number; 30 | full_name: string; 31 | has_pages: boolean; 32 | name: string; 33 | network_count: number; 34 | project_count: number; 35 | pushed_at: string; 36 | stargazers_count: number; 37 | subscribers_count: number; 38 | updated_at: string; 39 | url: string; 40 | } 41 | 42 | export interface Auth { 43 | accessToken: string; 44 | email: string; 45 | name: string; 46 | repo: string; 47 | repoDetails?: Repo; 48 | username: string; 49 | } 50 | 51 | export const CLIENT_ID: string | undefined = 52 | process.env.REACT_APP_GITHUB_CLIENT_ID; 53 | const SCOPE: string = "public_repo"; 54 | export function getOauthRedirect(csrf: string): string { 55 | return ( 56 | "https://github.com/login/oauth/authorize" + 57 | `?client_id=${CLIENT_ID}&scope=${SCOPE}&state=${csrf}` 58 | ); 59 | } 60 | 61 | /** 62 | * It's good practice when logging out to revoke the OAuth token, I guess. 63 | */ 64 | export async function revokeGitHubAuth( 65 | rpc: RPCClient, 66 | token: string, 67 | ): Promise { 68 | try { 69 | await rpc.call("signOut", { 70 | token, 71 | }); 72 | } catch (err) { 73 | alert( 74 | "Could not revoke GitHub authorization. " + 75 | "If you would like, you can manually do this from your GitHub settings.", 76 | ); 77 | } finally { 78 | window.location.reload(); 79 | } 80 | } 81 | 82 | /** 83 | * Called by to continue the OAuth flow. 84 | */ 85 | export async function checkLogin( 86 | rpc: RPCClient, 87 | code: string, 88 | state: string, 89 | csrf: string, 90 | ): Promise { 91 | if (csrf !== state) { 92 | console.warn("Invalid csrf."); 93 | throw new Error("Something went wrong. Could not log you in."); 94 | } 95 | const response: SignInResponse = await rpc.call("signIn", { 96 | oauth: code, 97 | state, 98 | }); 99 | 100 | if ( 101 | !response.result.accessToken || 102 | !response.result.email || 103 | !response.result.name || 104 | !response.result.repo || 105 | !response.result.username 106 | ) { 107 | throw new Error("Could not log you in."); 108 | } 109 | 110 | return response.result; 111 | } 112 | 113 | /** 114 | * Deserializes Auth. Used when parsing localStorage. 115 | */ 116 | export function parseAuth(auth: string | undefined): Auth | null { 117 | if (!auth) { 118 | return null; 119 | } 120 | try { 121 | const parsedAuth: Auth = JSON.parse(auth); 122 | if ( 123 | parsedAuth && 124 | parsedAuth.accessToken && 125 | parsedAuth.email && 126 | parsedAuth.name && 127 | parsedAuth.repo && 128 | parsedAuth.username 129 | ) { 130 | return parsedAuth; 131 | } 132 | 133 | return null; 134 | } catch (err) { 135 | return null; 136 | } 137 | } 138 | 139 | export function redirectToLogin(csrf: string): void { 140 | window.location.href = getOauthRedirect(csrf); 141 | } 142 | -------------------------------------------------------------------------------- /src/base64Binary.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011, Daniel Guerrero 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL DANIEL GUERRERO BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | /** 26 | * Uses the new array typed in javascript to binary base64 encode/decode 27 | * at the moment just decodes a binary base64 encoded 28 | * into either an ArrayBuffer (decodeArrayBuffer) 29 | * or into an Uint8Array (decode) 30 | * 31 | * References: 32 | * https://developer.mozilla.org/en/JavaScript_typed_arrays/ArrayBuffer 33 | * https://developer.mozilla.org/en/JavaScript_typed_arrays/Uint8Array 34 | */ 35 | 36 | const keyStr: string = 37 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; 38 | 39 | /* will return a Uint8Array type */ 40 | export function decodeArrayBuffer(input: string): ArrayBuffer { 41 | const bytes: number = (input.length / 4) * 3; 42 | const ab: ArrayBuffer = new ArrayBuffer(bytes); 43 | decode(input, ab); 44 | 45 | return ab; 46 | } 47 | 48 | export function removePaddingChars(input: string): string { 49 | const lkey: number = keyStr.indexOf(input.charAt(input.length - 1)); 50 | if (lkey === 64) { 51 | return input.substring(0, input.length - 1); 52 | } 53 | 54 | return input; 55 | } 56 | 57 | export function decode(inputStr: string, arrayBuffer: ArrayBuffer): Uint8Array { 58 | // get last chars to see if are valid 59 | let input: string = inputStr; 60 | input = removePaddingChars(input); 61 | input = removePaddingChars(input); 62 | input = input.replace(/[^A-Za-z0-9+/=]/g, ""); 63 | 64 | const bytes: number = parseInt(String((input.length / 4) * 3), 10); 65 | 66 | const uarray: Uint8Array = arrayBuffer 67 | ? new Uint8Array(arrayBuffer) 68 | : new Uint8Array(bytes); 69 | let chr1: number; 70 | let chr2: number; 71 | let chr3: number; 72 | let enc1: number; 73 | let enc2: number; 74 | let enc3: number; 75 | let enc4: number; 76 | let j: number = 0; 77 | 78 | for (let i: number = 0; i < bytes; i += 3) { 79 | // get the 3 octects in 4 ascii chars 80 | enc1 = keyStr.indexOf(input.charAt(j)); 81 | j += 1; 82 | enc2 = keyStr.indexOf(input.charAt(j)); 83 | j += 1; 84 | enc3 = keyStr.indexOf(input.charAt(j)); 85 | j += 1; 86 | enc4 = keyStr.indexOf(input.charAt(j)); 87 | j += 1; 88 | 89 | chr1 = (enc1 << 2) | (enc2 >> 4); 90 | chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 91 | chr3 = ((enc3 & 3) << 6) | enc4; 92 | 93 | uarray[i] = chr1; 94 | if (enc3 !== 64) { 95 | uarray[i + 1] = chr2; 96 | } 97 | if (enc4 !== 64) { 98 | uarray[i + 2] = chr3; 99 | } 100 | } 101 | 102 | return uarray; 103 | } 104 | -------------------------------------------------------------------------------- /src/hackmidi.d.ts: -------------------------------------------------------------------------------- 1 | declare module "hackmidi"; 2 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import "~normalize.css"; 2 | @import "~@blueprintjs/core/lib/css/blueprint.css"; 3 | @import "~@blueprintjs/icons/lib/css/blueprint-icons.css"; 4 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/logo.svg.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | declare const text: string; 22 | export = text; 23 | -------------------------------------------------------------------------------- /src/monacoConfig/CodelensProvider.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import * as monacoEditor from "monaco-editor"; 22 | 23 | import Commands from "./Commands"; 24 | 25 | /** 26 | * Provides codelens shortcuts for lilypond. 27 | */ 28 | export default class CodelensProvider 29 | implements monacoEditor.languages.CodeLensProvider 30 | { 31 | commands: Commands; 32 | 33 | constructor(commands: Commands) { 34 | this.commands = commands; 35 | } 36 | 37 | provideCodeLenses = ( 38 | model: monacoEditor.editor.IReadOnlyModel, 39 | _token: monacoEditor.CancellationToken, 40 | ): monacoEditor.languages.CodeLensList => { 41 | const lines: string[] = model.getLinesContent(); 42 | 43 | type CodeLens = monacoEditor.languages.CodeLens; 44 | 45 | return { 46 | dispose() {}, 47 | lenses: lines.reduce( 48 | (memos: CodeLens[], line: string, i: number): CodeLens[] => { 49 | let memo: CodeLens[] = memos; 50 | 51 | if (line.indexOf("\\clef") !== -1) { 52 | memo = [ 53 | ...memo, 54 | { 55 | command: { 56 | arguments: [i], 57 | id: this.commands.setClef, 58 | title: "Tool: Change Clef", 59 | }, 60 | range: { 61 | endColumn: 1, 62 | endLineNumber: i + 2, 63 | startColumn: 1, 64 | startLineNumber: i + 1, 65 | }, 66 | }, 67 | ]; 68 | } 69 | if (line.indexOf("\\key") !== -1) { 70 | memo = [ 71 | ...memo, 72 | { 73 | command: { 74 | arguments: [i], 75 | id: this.commands.setKey, 76 | title: "Tool: Change Key Signature", 77 | }, 78 | range: { 79 | endColumn: 1, 80 | endLineNumber: i + 2, 81 | startColumn: 1, 82 | startLineNumber: i + 1, 83 | }, 84 | }, 85 | ]; 86 | } 87 | if (line.indexOf("\\time") !== -1) { 88 | memo = [ 89 | ...memo, 90 | { 91 | command: { 92 | arguments: [i], 93 | id: this.commands.setTime, 94 | title: "Tool: Change Time Signature", 95 | }, 96 | range: { 97 | endColumn: 1, 98 | endLineNumber: i + 2, 99 | startColumn: 1, 100 | startLineNumber: i + 1, 101 | }, 102 | }, 103 | ]; 104 | } 105 | if (line.indexOf("\\relative") !== -1) { 106 | memo = [ 107 | ...memo, 108 | { 109 | command: { 110 | arguments: [i], 111 | id: this.commands.insertNotes, 112 | title: "Tool: Insert Notes", 113 | }, 114 | range: { 115 | endColumn: 1, 116 | endLineNumber: i + 2, 117 | startColumn: 1, 118 | startLineNumber: i + 1, 119 | }, 120 | }, 121 | ]; 122 | } 123 | 124 | return memo; 125 | }, 126 | [], 127 | ), 128 | }; 129 | }; 130 | 131 | resolveCodeLens = ( 132 | _model: monacoEditor.editor.IReadOnlyModel, 133 | codeLens: monacoEditor.languages.CodeLens, 134 | _token: monacoEditor.CancellationToken, 135 | ): monacoEditor.languages.CodeLens => { 136 | return codeLens; 137 | }; 138 | } 139 | -------------------------------------------------------------------------------- /src/monacoConfig/Commands.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import * as monacoEditor from "monaco-editor"; 22 | 23 | /** 24 | * These are monaco commands. So far we use them in codelens actions (see codelensProvider) 25 | */ 26 | export default class Commands { 27 | insertNotes: string = ""; 28 | setClef: string = ""; 29 | setKey: string = ""; 30 | setTime: string = ""; 31 | showMakelily: (tool: string, cb?: (ly: string) => void) => void; 32 | 33 | constructor(showMakelily: (tool: string) => void) { 34 | this.showMakelily = showMakelily; 35 | } 36 | 37 | clear(): void { 38 | this.insertNotes = ""; 39 | this.setClef = ""; 40 | this.setKey = ""; 41 | this.setTime = ""; 42 | } 43 | 44 | init(editor: monacoEditor.editor.IStandaloneCodeEditor): void { 45 | function moveToStartOfNextLine(lineIdx: number): void { 46 | editor.setPosition({ 47 | column: 1, 48 | lineNumber: lineIdx + 2, 49 | }); 50 | } 51 | 52 | function replaceLine(lineIdx: number, ly: string): void { 53 | const model = editor.getModel(); 54 | if (!model) { 55 | return; 56 | } 57 | const whitespace: RegExpMatchArray | null = model 58 | .getLinesContent() 59 | [lineIdx].match(/^\s*/); 60 | const whitespacePrefix: string = whitespace ? whitespace[0] : ""; 61 | 62 | const range: monacoEditor.Range = new monacoEditor.Range( 63 | lineIdx + 1, 64 | 1, 65 | lineIdx + 2, 66 | 1, 67 | ); 68 | const op: monacoEditor.editor.IIdentifiedSingleEditOperation = { 69 | forceMoveMarkers: false, 70 | range, 71 | text: `${whitespacePrefix}${ly}`, 72 | }; 73 | editor.executeEdits("hacklily", [op]); 74 | } 75 | 76 | this.setClef = 77 | editor.addCommand( 78 | Number.MAX_VALUE, 79 | (internal: void, lineIdx: number): void => { 80 | moveToStartOfNextLine(lineIdx); 81 | this.showMakelily("clef", (ly: string) => { 82 | replaceLine(lineIdx, ly); 83 | }); 84 | }, 85 | "", 86 | ) || ""; 87 | this.setKey = 88 | editor.addCommand( 89 | Number.MAX_VALUE, 90 | (internal: void, lineIdx: number): void => { 91 | moveToStartOfNextLine(lineIdx); 92 | this.showMakelily("key", (ly: string) => { 93 | replaceLine(lineIdx, ly); 94 | }); 95 | }, 96 | "", 97 | ) || ""; 98 | this.setTime = 99 | editor.addCommand( 100 | Number.MAX_VALUE, 101 | (internal: void, lineIdx: number): void => { 102 | moveToStartOfNextLine(lineIdx); 103 | this.showMakelily("time", (ly: string) => { 104 | replaceLine(lineIdx, ly); 105 | }); 106 | }, 107 | "", 108 | ) || ""; 109 | this.insertNotes = 110 | editor.addCommand( 111 | Number.MAX_VALUE, 112 | (internal: void, lineIdx: number): void => { 113 | moveToStartOfNextLine(lineIdx); 114 | this.showMakelily("notes"); 115 | }, 116 | "", 117 | ) || ""; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/monacoConfig/LICENSE_HEADER.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @licstart The following is the entire license notice for the 3 | * JavaScript code in this file. 4 | * 5 | * Copyright (c) 2015 - present Microsoft Corporation 6 | * 7 | * All rights reserved. 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in all 17 | * copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | * SOFTWARE. 26 | * 27 | * @licend The above is the entire license notice 28 | * for the JavaScript code in this file. 29 | */ -------------------------------------------------------------------------------- /src/monacoConfig/LILYPOND_COMPLETION_ITEM_PROVIDER.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import * as monacoEditor from "monaco-editor"; 22 | 23 | import NOTATION_SYMBOLS from "./NOTATION_SYMBOLS"; 24 | 25 | const LILYPOND_COMPLETION_ITEM_PROVIDER: monacoEditor.languages.CompletionItemProvider = 26 | { 27 | provideCompletionItems( 28 | model: monacoEditor.editor.IReadOnlyModel, 29 | position: monacoEditor.Position, 30 | _context: monacoEditor.languages.CompletionContext, 31 | _token: monacoEditor.CancellationToken, 32 | ): monacoEditor.languages.CompletionList { 33 | const textUntilPosition: string = model.getValueInRange({ 34 | endColumn: position.column, 35 | endLineNumber: position.lineNumber, 36 | startColumn: 1, 37 | startLineNumber: 1, 38 | }); 39 | if (textUntilPosition[textUntilPosition.length - 2] === "\\") { 40 | return { suggestions: NOTATION_SYMBOLS }; 41 | } 42 | 43 | // Otherwise, Monaco really wants to give us word-based suggestions, 44 | // which are not helpful on note input. 45 | return { 46 | suggestions: [ 47 | { 48 | kind: 0, // text 49 | label: "", 50 | insertText: "", 51 | range: null as any, 52 | }, 53 | ], 54 | }; 55 | }, 56 | }; 57 | 58 | export default LILYPOND_COMPLETION_ITEM_PROVIDER; 59 | -------------------------------------------------------------------------------- /src/musicxml2ly/MusicXML2Ly.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import React from "react"; 22 | 23 | const INITIAL_WS_COOLOFF: number = 2; 24 | const BACKEND_WS_URL: string | undefined = process.env.REACT_APP_BACKEND_WS_URL; 25 | 26 | import "../index.css"; 27 | import RPCClient from "../RPCClient"; 28 | import MusicXML2LyModal from "./MusicXML2LyModal"; 29 | 30 | interface State { 31 | wsError: boolean; 32 | reconnectCooloff: number; 33 | reconnectTimeout: number; 34 | } 35 | 36 | export default class App extends React.PureComponent<{}, State> { 37 | state: State = { 38 | reconnectCooloff: INITIAL_WS_COOLOFF, 39 | reconnectTimeout: NaN, 40 | wsError: false, 41 | }; 42 | 43 | private rpc: RPCClient | null = null; 44 | private socket: WebSocket | null = null; 45 | 46 | componentDidMount(): void { 47 | this.connectToWS(); 48 | } 49 | 50 | componentWillUnmount(): void { 51 | this.disconnectWS(); 52 | } 53 | 54 | render(): JSX.Element { 55 | const header =
; 56 | 57 | return ( 58 |
59 | {header} 60 | {this.rpc && } 61 |
62 |
63 |
64 |
65 | ); 66 | } 67 | 68 | onLeave = (): void => { 69 | window.location.href = "/"; 70 | }; 71 | 72 | private connectToWS(): void { 73 | if (!BACKEND_WS_URL) { 74 | this.setState({ 75 | wsError: true, 76 | }); 77 | 78 | return; 79 | } 80 | this.socket = new WebSocket(BACKEND_WS_URL); 81 | 82 | this.socket.addEventListener("open", this.handleWSOpen); 83 | this.socket.addEventListener("error", this.handleWSError); 84 | this.socket.addEventListener("close", this.handleWSError); 85 | this.forceUpdate(); 86 | } 87 | 88 | private disconnectWS(): void { 89 | if (this.socket) { 90 | this.socket.removeEventListener("open", this.handleWSOpen); 91 | this.socket.removeEventListener("error", this.handleWSError); 92 | this.socket.removeEventListener("close", this.handleWSError); 93 | this.socket.close(); 94 | this.socket = null; 95 | if (this.rpc) { 96 | this.rpc.destroy(); 97 | this.rpc = null; 98 | } 99 | } 100 | } 101 | 102 | private handleWSError = (_e: Event): void => { 103 | if (!this.socket) { 104 | return; 105 | } 106 | 107 | this.disconnectWS(); 108 | this.setState({ 109 | reconnectCooloff: this.state.reconnectCooloff * 2, 110 | reconnectTimeout: this.state.reconnectCooloff, 111 | wsError: true, 112 | }); 113 | setTimeout(this.wsReconnectTick, 1000); 114 | }; 115 | 116 | private handleWSOpen = async (): Promise => { 117 | if (!this.socket) { 118 | throw new Error("Socket not opened, but handleWSOpen called."); 119 | } 120 | this.rpc = new RPCClient(this.socket); 121 | this.setState({ 122 | reconnectCooloff: INITIAL_WS_COOLOFF, 123 | }); 124 | this.forceUpdate(); 125 | }; 126 | 127 | private wsReconnectTick = (): void => { 128 | const secondsRemaining: number = this.state.reconnectTimeout - 1; 129 | if (secondsRemaining > 0) { 130 | this.setState({ 131 | reconnectTimeout: secondsRemaining, 132 | }); 133 | setTimeout(this.wsReconnectTick, 1000); 134 | } else { 135 | this.setState({ 136 | reconnectTimeout: NaN, 137 | }); 138 | this.connectToWS(); 139 | } 140 | }; 141 | } 142 | -------------------------------------------------------------------------------- /src/musicxml2ly/MusicXML2LyModal.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import { Classes, Dialog } from "@blueprintjs/core"; 22 | import React from "react"; 23 | 24 | import RPCClient from "../RPCClient"; 25 | 26 | interface Props { 27 | rpc: RPCClient; 28 | onHide(): void; 29 | } 30 | 31 | export default class MusicXML2LyModal extends React.PureComponent { 32 | render(): JSX.Element { 33 | return ( 34 | 35 |
36 |

Select a MusicXML file to import into Hacklily.

37 | 38 |
39 |
40 | ); 41 | } 42 | 43 | convert = (ev: React.ChangeEvent) => { 44 | if (!ev.target.files) { 45 | return; 46 | } 47 | const reader = new FileReader(); 48 | reader.onload = () => { 49 | this.doLoad(reader.result as any); 50 | reader.onload = null; 51 | }; 52 | reader.readAsText(ev.target.files[0]); 53 | }; 54 | 55 | doLoad = async (src: string) => { 56 | console.log(src); 57 | const rendered = await this.props.rpc.call("render", { 58 | backend: "musicxml2ly", 59 | version: "stable", 60 | src, 61 | }); 62 | const file = rendered.result.files[0]; 63 | alert(rendered.result.logs); 64 | location.href = `/#src=${encodeURIComponent(file)}`; 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /src/musicxml2ly/musicxml2ly.index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import React from "react"; 22 | import ReactDOM from "react-dom"; 23 | 24 | import MusicXML2Ly from "./MusicXML2Ly"; 25 | 26 | ReactDOM.render(, document.getElementById("root")); 27 | -------------------------------------------------------------------------------- /src/status/Status.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import React from "react"; 22 | 23 | import RPCClient, { Status as ServerStatus } from "../RPCClient"; 24 | 25 | const INITIAL_WS_COOLOFF: number = 1; 26 | const BACKEND_WS_URL: string | undefined = process.env.REACT_APP_BACKEND_WS_URL; 27 | 28 | interface State { 29 | reconnectCooloff: number; 30 | reconnectTimeout: number; 31 | status: ServerStatus | null; 32 | wsError: boolean; 33 | } 34 | 35 | /** 36 | * Renders /status.html 37 | */ 38 | export default class Status extends React.Component<{}, State> { 39 | state: State = { 40 | reconnectCooloff: INITIAL_WS_COOLOFF, 41 | reconnectTimeout: NaN, 42 | status: null, 43 | wsError: false, 44 | }; 45 | 46 | private rpc: RPCClient | null = null; 47 | private socket: WebSocket | null = null; 48 | private statusTimer: number | null = null; 49 | 50 | componentDidMount(): void { 51 | this.connectToWS(); 52 | } 53 | 54 | render(): JSX.Element { 55 | if (this.state.wsError) { 56 | return ( 57 |
58 | Could not connect to server. ({this.state.reconnectTimeout || 0}) 59 |
60 | ); 61 | } 62 | 63 | if (!this.socket || this.socket.readyState === WebSocket.CONNECTING) { 64 | return
Connecting...
; 65 | } 66 | 67 | const { status } = this.state; 68 | 69 | if (!status) { 70 | return
No status returned.
; 71 | } 72 | 73 | return ( 74 |
75 |

Status

76 |
{JSON.stringify(status, null, 2)}
77 |
78 | ); 79 | } 80 | 81 | private connectToWS(): void { 82 | if (!BACKEND_WS_URL) { 83 | this.setState({ 84 | wsError: true, 85 | }); 86 | 87 | return; 88 | } 89 | this.socket = new WebSocket(BACKEND_WS_URL); 90 | 91 | this.socket.addEventListener("open", this.handleWSOpen); 92 | this.socket.addEventListener("error", this.handleWSError); 93 | this.socket.addEventListener("close", this.handleWSError); 94 | } 95 | 96 | private disconnectWS(): void { 97 | if (this.socket) { 98 | this.socket.removeEventListener("open", this.handleWSOpen); 99 | this.socket.removeEventListener("error", this.handleWSError); 100 | this.socket.removeEventListener("close", this.handleWSError); 101 | this.socket.close(); 102 | this.socket = null; 103 | if (this.rpc) { 104 | this.rpc.destroy(); 105 | this.rpc = null; 106 | } 107 | } 108 | } 109 | 110 | private handleGetStatusTimeout = async (): Promise => { 111 | if (!this.rpc) { 112 | return; 113 | } 114 | 115 | const status: ServerStatus = (await this.rpc.call("get_status", {})).result; 116 | this.setState({ 117 | reconnectCooloff: INITIAL_WS_COOLOFF, 118 | status, 119 | wsError: false, 120 | }); 121 | }; 122 | 123 | private handleWSError = (_e: Event): void => { 124 | if (!this.socket) { 125 | return; 126 | } 127 | 128 | this.disconnectWS(); 129 | this.setState({ 130 | reconnectCooloff: this.state.reconnectCooloff * 2, 131 | reconnectTimeout: this.state.reconnectCooloff, 132 | wsError: true, 133 | }); 134 | setTimeout(this.wsReconnectTick, 1000); 135 | if (this.statusTimer) { 136 | clearInterval(this.statusTimer); 137 | } 138 | }; 139 | 140 | private handleWSOpen = async (): Promise => { 141 | if (!this.socket) { 142 | throw new Error("Socket not opened, but handleWSOpen called."); 143 | } 144 | this.rpc = new RPCClient(this.socket); 145 | 146 | this.statusTimer = window.setInterval(this.handleGetStatusTimeout, 1000); 147 | this.handleGetStatusTimeout(); 148 | }; 149 | 150 | private wsReconnectTick = (): void => { 151 | const secondsRemaining: number = this.state.reconnectTimeout - 1; 152 | if (secondsRemaining > 0) { 153 | this.setState({ 154 | reconnectTimeout: secondsRemaining, 155 | }); 156 | setTimeout(this.wsReconnectTick, 1000); 157 | } else { 158 | this.setState({ 159 | reconnectTimeout: NaN, 160 | }); 161 | this.connectToWS(); 162 | } 163 | }; 164 | } 165 | -------------------------------------------------------------------------------- /src/status/status.index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | import React from "react"; 22 | import ReactDOM from "react-dom"; 23 | 24 | import Status from "./Status"; 25 | 26 | ReactDOM.render(, document.getElementById("root")); 27 | -------------------------------------------------------------------------------- /src/util/queryString.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | // http://stackoverflow.com/a/8648962 22 | export function parseQuery(qstr: string): { [key: string]: string } { 23 | const query: { [key: string]: string } = {}; 24 | const a: string[] = (qstr[0] === "?" ? qstr.substr(1) : qstr).split("&"); 25 | for (const item of a) { 26 | if (!item) { 27 | continue; 28 | } 29 | const b: string[] = item.split("="); 30 | query[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || ""); 31 | } 32 | 33 | return query; 34 | } 35 | 36 | // http://stackoverflow.com/a/5505137 37 | export function toQueryString(obj: { [key: string]: string }): string { 38 | const parts: string[] = []; 39 | for (const i of Object.keys(obj)) { 40 | if (obj[i] !== undefined) { 41 | parts.push(`${encodeURIComponent(i)}=${encodeURIComponent(obj[i])}`); 42 | } 43 | } 44 | 45 | return parts.join("&").replace(/%2F/g, "/"); // because we can, and it's less ugly. 46 | } 47 | -------------------------------------------------------------------------------- /static/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 404 8 | 25 | 28 | 29 | 30 | 33 |

The page you were trying to reach does not exist.

34 | 35 | 36 | -------------------------------------------------------------------------------- /static/CenturySchL-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/CenturySchL-Bold.otf -------------------------------------------------------------------------------- /static/CenturySchL-BoldItal.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/CenturySchL-BoldItal.otf -------------------------------------------------------------------------------- /static/CenturySchL-Ital.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/CenturySchL-Ital.otf -------------------------------------------------------------------------------- /static/CenturySchL-Roma.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/CenturySchL-Roma.otf -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | # Hacklily 2 | 3 | If you are at https://github.com/emilyskidsister/hacklily.github.io, you are looking at the most recent 4 | Hacklily build. This is the build powering [https://www.hacklily.org](https://www.hacklily.org). 5 | 6 | For source and more information, see [the main repo](https://github.com/emilyskidsister/hacklily). 7 | -------------------------------------------------------------------------------- /static/dmca.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hacklily: DMCA 9 | 26 | 27 | 28 | 31 |

DMCA

32 |

33 | If you believe your copyright-protected work was posted on Hacklily without authorization, you may submit a 34 | copyright infringement notification. These requests should only be submitted by the copyright owner or an agent 35 | authorized to act on the owner’s behalf. 36 |

37 |

38 | Please send infringement notifications to jocelyn@nettek.ca. 39 |

40 | 41 | 42 | -------------------------------------------------------------------------------- /static/emmentaler-11.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/emmentaler-11.otf -------------------------------------------------------------------------------- /static/emmentaler-13.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/emmentaler-13.otf -------------------------------------------------------------------------------- /static/emmentaler-14.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/emmentaler-14.otf -------------------------------------------------------------------------------- /static/emmentaler-16.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/emmentaler-16.otf -------------------------------------------------------------------------------- /static/emmentaler-18.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/emmentaler-18.otf -------------------------------------------------------------------------------- /static/emmentaler-20.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/emmentaler-20.otf -------------------------------------------------------------------------------- /static/emmentaler-23.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/emmentaler-23.otf -------------------------------------------------------------------------------- /static/emmentaler-26.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/emmentaler-26.otf -------------------------------------------------------------------------------- /static/emmentaler-brace.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/emmentaler-brace.otf -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/favicon.ico -------------------------------------------------------------------------------- /static/github.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /static/google4b0ced2a6eedee27.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google4b0ced2a6eedee27.html -------------------------------------------------------------------------------- /static/gplv3-127x51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/gplv3-127x51.png -------------------------------------------------------------------------------- /static/hackmidi/Chop-28-4.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/Chop-28-4.mid -------------------------------------------------------------------------------- /static/hackmidi/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.css": "/hackmidi/static/css/main.7fbd665b.css", 4 | "main.js": "/hackmidi/static/js/main.923a807c.js", 5 | "index.html": "/hackmidi/index.html", 6 | "main.7fbd665b.css.map": "/hackmidi/static/css/main.7fbd665b.css.map", 7 | "main.923a807c.js.map": "/hackmidi/static/js/main.923a807c.js.map" 8 | }, 9 | "entrypoints": [ 10 | "static/css/main.7fbd665b.css", 11 | "static/js/main.923a807c.js" 12 | ] 13 | } -------------------------------------------------------------------------------- /static/hackmidi/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/favicon.ico -------------------------------------------------------------------------------- /static/hackmidi/index.html: -------------------------------------------------------------------------------- 1 | Hackmidi
-------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/025_Snare_Roll.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/025_Snare_Roll.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/026_Snap.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/026_Snap.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/027_High_Q.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/027_High_Q.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/031_Sticks.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/031_Sticks.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/032_Square_Click.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/032_Square_Click.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/033_Metronome_Click.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/033_Metronome_Click.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/034_Metronome_Bell.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/034_Metronome_Bell.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/035_Kick_1.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/035_Kick_1.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/035_Kick_1.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | 035_Kick_1. From sound sample by Clingre, Bass Drum, Wikimedia commons, Mar. 3 | 31, 2005, released under the following license: Permission is granted to 4 | copy, distribute and/or modify this document under the terms of the GNU Free 5 | Documentation License, Version 1.2 or any later version published by the 6 | Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, 7 | and no Back-Cover Texts. See 2006b18-Copr-Gnu-FDL.txt. Shortened and 8 | converted to patch format for Freepats by walt@w-gregg.juneau.ak.us, Feb. 9 | 2006. 10 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/036_Kick_2.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/036_Kick_2.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/036_Kick_2.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Bass drum kick 1. From sound sample BD5025.wav by Michael Fischer in Roland 3 | TR-808 Rhythm Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as 4 | tr808all.zip. These are samples of an analog synthesizer he personally 5 | recorded and released for absolutely free usage. See 6 | 2006b18-Copr-M_Fischer.txt or Michael Fischer, Very High Quality TR-808 and 7 | TR-909 samples, news:alt.music.synthpop, Sep. 5, 1994. Shortened and 8 | converted to patch format for freepats by walt@w-gregg.juneau.ak.us, Feb. 9 | 2006. 10 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/037_Stick_Rim.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/037_Stick_Rim.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/038_Snare_1.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/038_Snare_1.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/039_Clap_Hand.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/039_Clap_Hand.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/039_Clap_Hand.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Hand clap. From sound sample CP.wav by Michael Fischer in Roland TR-808 3 | Rhythm Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as tr808all.zip. These 4 | are samples of an analog synthesizer he personally recorded and released for 5 | absolutely free usage. See 2006b18-Copr-M_Fischer.txt or Michael Fischer, 6 | Very High Quality TR-808 and TR-909 samples, news:alt.music.synthpop, Sep. 7 | 5, 1994. Shortened and converted to patch format for Freepats by 8 | walt@w-gregg.juneau.ak.us, Feb. 2006. 9 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/040_Snare_2.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/040_Snare_2.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/041_Tom_Low_2.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/041_Tom_Low_2.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/041_Tom_Low_2.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Low Tom 2/Low Floor Tom. From sound sample LT00.wav by Michael Fischer in 3 | Roland TR-808 Rhythm Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as 4 | tr808all.zip. These are samples of an analog synthesizer he personally 5 | recorded and released for absolutely free usage. See 6 | 2006b18-Copr-M_Fischer.txt or Michael Fischer, Very High Quality TR-808 and 7 | TR-909 samples, news:alt.music.synthpop, Sep. 5, 1994. Shortened and 8 | converted to patch format for Freepats by walt@w-gregg.juneau.ak.us, Feb. 9 | 2006. 10 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/042_Hi-Hat_Closed.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/042_Hi-Hat_Closed.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/043_Tom_Low_1.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/043_Tom_Low_1.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/043_Tom_Low_1.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Low Tom 1/High Floor Tom. From sound sample LT10.wav by Michael Fischer in 3 | Roland TR-808 Rhythm Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as 4 | tr808all.zip. These are samples of an analog synthesizer he personally 5 | recorded and released for absolutely free usage. See 6 | 2006b18-Copr-M_Fischer.txt or Michael Fischer, Very High Quality TR-808 and 7 | TR-909 samples, news:alt.music.synthpop, Sep. 5, 1994. Shortened and 8 | converted to patch format for Freepats by walt@w-gregg.juneau.ak.us, Feb. 9 | 2006. 10 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/044_Hi-Hat_Pedal.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/044_Hi-Hat_Pedal.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/045_Tom_Mid_2.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/045_Tom_Mid_2.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/045_Tom_Mid_2.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Mid Tom 2. From sound sample MT00.wav by Michael Fischer in Roland TR-808 3 | Rhythm Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as tr808all.zip. These 4 | are samples of an analog synthesizer he personally recorded and released for 5 | absolutely free usage. See 2006b18-Copr-M_Fischer.txt or Michael Fischer, 6 | Very High Quality TR-808 and TR-909 samples, news:alt.music.synthpop, Sep. 7 | 5, 1994. Shortened and converted to patch format for Freepats by 8 | walt@w-gregg.juneau.ak.us, Feb. 2006. 9 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/046_Hi-Hat_Open.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/046_Hi-Hat_Open.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/047_Tom_Mid_1.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/047_Tom_Mid_1.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/047_Tom_Mid_1.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Mid Tom 1/Low-Mid Tom. From sound sample MT75.wav by Michael Fischer in 3 | Roland TR-808 Rhythm Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as 4 | tr808all.zip. These are samples of an analog synthesizer he personally 5 | recorded and released for absolutely free usage. See 6 | 2006b18-Copr-M_Fischer.txt or Michael Fischer, Very High Quality TR-808 and 7 | TR-909 samples, news:alt.music.synthpop, Sep. 5, 1994. Shortened and 8 | converted to patch format for Freepats by walt@w-gregg.juneau.ak.us, Feb. 9 | 2006. 10 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/048_Tom_High_2.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/048_Tom_High_2.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/048_Tom_High_2.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | High Tom 2/Hi-Mid Tom. From sound sample HT25.wav by Michael Fischer in 3 | Roland TR-808 Rhythm Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as 4 | tr808all.zip. These are samples of an analog synthesizer he personally 5 | recorded and released for absolutely free usage. See 6 | 2006b18-Copr-M_Fischer.txt or Michael Fischer, Very High Quality TR-808 and 7 | TR-909 samples, news:alt.music.synthpop, Sep. 5, 1994. Shortened and 8 | converted to patch format for Freepats by walt@w-gregg.juneau.ak.us, Feb. 9 | 2006. 10 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/049_Cymbal_Crash_1.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/049_Cymbal_Crash_1.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/050_Tom_High_1.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/050_Tom_High_1.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/050_Tom_High_1.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | High Tom 1/Hi Tom. From sound sample HT10.wav by Michael Fischer in Roland 3 | TR-808 Rhythm Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as 4 | tr808all.zip. These are samples of an analog synthesizer he personally 5 | recorded and released for absolutely free usage. See 6 | 2006b18-Copr-M_Fischer.txt or Michael Fischer, Very High Quality TR-808 and 7 | TR-909 samples, news:alt.music.synthpop, Sep. 5, 1994. Shortened and 8 | converted to patch format for Freepats by walt@w-gregg.juneau.ak.us, Feb. 9 | 2006. 10 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/051_Cymbal_Ride_1.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/051_Cymbal_Ride_1.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/052_Cymbal_Chinese.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/052_Cymbal_Chinese.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/053_Cymbal_Ride_Bell.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/053_Cymbal_Ride_Bell.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/053_Cymbal_Ride_Bell.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Ride Bell. From sound sample CY7500.wav by Michael Fischer in Roland TR-808 3 | Rhythm Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as tr808all.zip. These 4 | are samples of an analog synthesizer he personally recorded and released for 5 | absolutely free usage. See 2006b18-Copr-M_Fischer.txt or Michael Fischer, 6 | Very High Quality TR-808 and TR-909 samples, news:alt.music.synthpop, Sep. 7 | 5, 1994. Shortened and converted to patch format for Freepats by 8 | walt@w-gregg.juneau.ak.us, Feb. 2006. This isn't very close match to a Ride 9 | Bell sound. 10 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/054_Tombourine.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/054_Tombourine.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/055_Cymbal_Splash.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/055_Cymbal_Splash.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/056_Cow_Bell.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/056_Cow_Bell.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/057_Cymbal_Crash_2.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/057_Cymbal_Crash_2.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/058_Vibra-Slap.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/058_Vibra-Slap.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/059_Cymbal_Ride_2.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/059_Cymbal_Ride_2.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/060_Bongo_High.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/060_Bongo_High.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/061_Bongo_Low.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/061_Bongo_Low.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/062_Conga_High_1_Mute.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/062_Conga_High_1_Mute.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/062_Conga_High_1_mute.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Muted high conga. Freepats high conga converted to wave, modified, and 3 | converted back to patch for Freepats by walt@w-gregg.juneau.ak.us, Feb. 4 | 2006. 5 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/063_Conga_High_2_Open.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/063_Conga_High_2_Open.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/064_Conga_Low.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/064_Conga_Low.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/065_Timbale_High.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/065_Timbale_High.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/066_Timbale_Low.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/066_Timbale_Low.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/067_Agogo_High.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/067_Agogo_High.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/068_Agogo_Low.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/068_Agogo_Low.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/069_Cabasa.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/069_Cabasa.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/069_Cabasa.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Muted high conga. Freepats Maracas converted to wave, modified, and 3 | converted back to patch for Freepats by walt@w-gregg.juneau.ak.us, Feb. 4 | 2006. 5 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/070_Maracas.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/070_Maracas.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/071_Whistle_1_High_Short.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/071_Whistle_1_High_Short.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/072_Whistle_2_Low_Long.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/072_Whistle_2_Low_Long.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/073_Guiro_1_Short.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/073_Guiro_1_Short.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/074_Guiro_2_Long.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/074_Guiro_2_Long.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/075_Claves.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/075_Claves.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/075_Claves.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Claves. From sound sample CL.wav by Michael Fischer in Roland TR-808 Rhythm 3 | Composer Sound Sample Set 1.0.0, Sep. 8, 1994, as tr808all.zip. These are 4 | samples of an analog synthesizer he personally recorded and released for 5 | absolutely free usage. See 2006b18-Copr-M_Fischer.txt or Michael Fischer, 6 | Very High Quality TR-808 and TR-909 samples, news:alt.music.synthpop, Sep. 7 | 5, 1994. Shortened and converted to patch format for Freepats by 8 | walt@w-gregg.juneau.ak.us, Feb. 2006. 9 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/076_Wood_Block_1_High.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/076_Wood_Block_1_High.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/077_Wood_Block_2_Low.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/077_Wood_Block_2_Low.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/078_Cuica_1_Mute.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/078_Cuica_1_Mute.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/078_Cuica_1_Mute.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | High cuica (mute cuica). From sound sample by Anonymous, Cuica01.ogg or 3 | Cuica02ogg, Wikimedia commons, May 9, 2005, released under the following 4 | license: Permission is granted to copy, distribute and/or modify this 5 | document under the terms of the GNU Free Documentation License, Version 1.2 6 | or any later version published by the Free Software Foundation; with no 7 | Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. See 8 | 2006b18-Copr-Gnu-FDL.txt. Shortened, pitch raised, and envelope modified and 9 | converted to patch format for Freepats by walt@w-gregg.juneau.ak.us, Feb. 10 | 2006. 11 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/079_Cuica_2_Open.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/079_Cuica_2_Open.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/079_Cuica_2_Open.txt: -------------------------------------------------------------------------------- 1 | amp=100 2 | Low cuica (open cuica). From sound sample by Anonymous, Cuica01.ogg or 3 | Cuica02ogg, Wikimedia commons, May 9, 2005, released under the following 4 | license: Permission is granted to copy, distribute and/or modify this 5 | document under the terms of the GNU Free Documentation License, Version 1.2 6 | or any later version published by the Free Software Foundation; with no 7 | Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. See 8 | 2006b18-Copr-Gnu-FDL.txt. Shortened, pitch raised, and envelope modified 9 | and converted to patch format for Freepats by walt@w-gregg.juneau.ak.us, 10 | Feb. 2006. 11 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/080_Triangle_1_Mute.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/080_Triangle_1_Mute.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/081_Triangle_2_Open.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/081_Triangle_2_Open.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/082_Shaker.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/082_Shaker.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Drum_000/084_Belltree.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Drum_000/084_Belltree.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/000_Acoustic_Grand_Piano.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/000_Acoustic_Grand_Piano.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/000_Acoustic_Grand_Piano.txt: -------------------------------------------------------------------------------- 1 | amp=120 pan=center 2 | 3 | The very first line of any associated *.txt file will be appended 4 | to the auto-generated freepats.cfg file by the mkcfg.sh.txt script. 5 | 6 | The rest of the file can be used for any purpose whatsoever, like 7 | misc notes, a history of how the pat was created and/or changes to 8 | this particular pat. 9 | -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/001_Acoustic_Brite_Piano.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/001_Acoustic_Brite_Piano.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/002_Electric_Grand_Piano.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/002_Electric_Grand_Piano.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/004_Electric_Piano_1_Rhodes.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/004_Electric_Piano_1_Rhodes.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/005_Electric_Piano_2_Chorused_Yamaha_DX.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/005_Electric_Piano_2_Chorused_Yamaha_DX.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/006_Harpsichord.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/006_Harpsichord.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/007_Clavinet.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/007_Clavinet.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/008_Celesta.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/008_Celesta.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/009_Glockenspiel.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/009_Glockenspiel.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/013_Xylophone.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/013_Xylophone.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/014_Tubular_Bells.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/014_Tubular_Bells.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/015_Dulcimer.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/015_Dulcimer.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/016_Hammond_Organ.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/016_Hammond_Organ.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/019_Church_Organ.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/019_Church_Organ.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/021_Accordion.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/021_Accordion.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/023_Tango_Accordion.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/023_Tango_Accordion.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/024_Nylon_Guitar.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/024_Nylon_Guitar.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/025_Steel_Guitar.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/025_Steel_Guitar.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/026_Jazz_Guitar.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/026_Jazz_Guitar.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/027_Clean_Electric_Guitar.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/027_Clean_Electric_Guitar.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/028_Muted_Electric_Guitar.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/028_Muted_Electric_Guitar.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/029_Overdriven_Guitar.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/029_Overdriven_Guitar.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/030_Distortion_Guitar.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/030_Distortion_Guitar.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/032_Acoustic_Bass.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/032_Acoustic_Bass.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/033_Finger_Bass.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/033_Finger_Bass.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/034_Pick_Bass.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/034_Pick_Bass.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/035_Fretless_Bass.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/035_Fretless_Bass.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/036_Slap_Bass_1.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/036_Slap_Bass_1.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/037_Slap_Bass_2.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/037_Slap_Bass_2.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/038_Synth_Bass_1.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/038_Synth_Bass_1.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/040_Violin.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/040_Violin.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/042_Cello.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/042_Cello.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/044_Tremolo_Strings.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/044_Tremolo_Strings.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/045_Pizzicato_Strings.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/045_Pizzicato_Strings.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/046_Harp.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/046_Harp.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/047_Timpani.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/047_Timpani.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/048_String_Ensemble_1_Marcato.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/048_String_Ensemble_1_Marcato.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/053_Voice_Oohs.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/053_Voice_Oohs.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/056_Trumpet.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/056_Trumpet.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/057_Trombone.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/057_Trombone.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/058_Tuba.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/058_Tuba.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/059_Muted_Trumpet.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/059_Muted_Trumpet.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/060_French_Horn.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/060_French_Horn.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/061_Brass_Section.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/061_Brass_Section.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/064_Soprano_Sax.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/064_Soprano_Sax.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/065_Alto_Sax.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/065_Alto_Sax.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/066_Tenor_Sax.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/066_Tenor_Sax.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/067_Baritone_Sax.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/067_Baritone_Sax.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/068_Oboe.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/068_Oboe.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/069_English_Horn.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/069_English_Horn.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/070_Bassoon.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/070_Bassoon.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/071_Clarinet.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/071_Clarinet.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/072_Piccolo.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/072_Piccolo.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/073_Flute.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/073_Flute.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/074_Recorder.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/074_Recorder.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/075_Pan_Flute.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/075_Pan_Flute.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/076_Bottle_Blow.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/076_Bottle_Blow.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/079_Ocarina.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/079_Ocarina.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/080_Square_Wave.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/080_Square_Wave.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/084_Charang.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/084_Charang.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/088_New_Age.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/088_New_Age.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/094_Halo_Pad.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/094_Halo_Pad.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/095_Sweep_Pad.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/095_Sweep_Pad.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/098_Crystal.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/098_Crystal.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/101_Goblins--Unicorn.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/101_Goblins--Unicorn.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/102_Echo_Voice.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/102_Echo_Voice.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/104_Sitar.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/104_Sitar.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/114_Steel_Drums.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/114_Steel_Drums.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/115_Wood_Block.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/115_Wood_Block.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/120_Guitar_Fret_Noise.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/120_Guitar_Fret_Noise.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/122_Seashore.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/122_Seashore.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/Tone_000/125_Helicopter.pat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/hackmidi/samples/Tone_000/125_Helicopter.pat -------------------------------------------------------------------------------- /static/hackmidi/samples/timidity.cfg: -------------------------------------------------------------------------------- 1 | # Automatically generated on Sun Feb 19 19:22:39 EST 2006 2 | # by http://freepats.opensrc.org/mkcfg.sh.txt 3 | 4 | drumset 0 5 | 6 | 25 Drum_000/025_Snare_Roll.pat 7 | 26 Drum_000/026_Snap.pat 8 | 27 Drum_000/027_High_Q.pat 9 | 31 Drum_000/031_Sticks.pat 10 | 32 Drum_000/032_Square_Click.pat 11 | 33 Drum_000/033_Metronome_Click.pat 12 | 34 Drum_000/034_Metronome_Bell.pat 13 | 35 Drum_000/035_Kick_1.pat amp=100 14 | 36 Drum_000/036_Kick_2.pat amp=100 15 | 37 Drum_000/037_Stick_Rim.pat 16 | 38 Drum_000/038_Snare_1.pat 17 | 39 Drum_000/039_Clap_Hand.pat amp=100 18 | 40 Drum_000/040_Snare_2.pat 19 | 41 Drum_000/041_Tom_Low_2.pat amp=100 20 | 42 Drum_000/042_Hi-Hat_Closed.pat 21 | 43 Drum_000/043_Tom_Low_1.pat amp=100 22 | 44 Drum_000/044_Hi-Hat_Pedal.pat 23 | 45 Drum_000/045_Tom_Mid_2.pat amp=100 24 | 46 Drum_000/046_Hi-Hat_Open.pat 25 | 47 Drum_000/047_Tom_Mid_1.pat amp=100 26 | 48 Drum_000/048_Tom_High_2.pat amp=100 27 | 49 Drum_000/049_Cymbal_Crash_1.pat 28 | 50 Drum_000/050_Tom_High_1.pat amp=100 29 | 51 Drum_000/051_Cymbal_Ride_1.pat 30 | 52 Drum_000/052_Cymbal_Chinese.pat 31 | 53 Drum_000/053_Cymbal_Ride_Bell.pat amp=100 32 | 54 Drum_000/054_Tombourine.pat 33 | 55 Drum_000/055_Cymbal_Splash.pat 34 | 56 Drum_000/056_Cow_Bell.pat 35 | 57 Drum_000/057_Cymbal_Crash_2.pat 36 | 58 Drum_000/058_Vibra-Slap.pat 37 | 59 Drum_000/059_Cymbal_Ride_2.pat 38 | 60 Drum_000/060_Bongo_High.pat 39 | 61 Drum_000/061_Bongo_Low.pat 40 | 62 Drum_000/062_Conga_High_1_Mute.pat 41 | 63 Drum_000/063_Conga_High_2_Open.pat 42 | 64 Drum_000/064_Conga_Low.pat 43 | 65 Drum_000/065_Timbale_High.pat 44 | 66 Drum_000/066_Timbale_Low.pat 45 | 67 Drum_000/067_Agogo_High.pat 46 | 68 Drum_000/068_Agogo_Low.pat 47 | 69 Drum_000/069_Cabasa.pat amp=100 48 | 70 Drum_000/070_Maracas.pat 49 | 71 Drum_000/071_Whistle_1_High_Short.pat 50 | 72 Drum_000/072_Whistle_2_Low_Long.pat 51 | 73 Drum_000/073_Guiro_1_Short.pat 52 | 74 Drum_000/074_Guiro_2_Long.pat 53 | 75 Drum_000/075_Claves.pat amp=100 54 | 76 Drum_000/076_Wood_Block_1_High.pat 55 | 77 Drum_000/077_Wood_Block_2_Low.pat 56 | 78 Drum_000/078_Cuica_1_Mute.pat amp=100 57 | 79 Drum_000/079_Cuica_2_Open.pat amp=100 58 | 80 Drum_000/080_Triangle_1_Mute.pat 59 | 81 Drum_000/081_Triangle_2_Open.pat 60 | 82 Drum_000/082_Shaker.pat 61 | 84 Drum_000/084_Belltree.pat 62 | 63 | bank 0 64 | 65 | 0 Tone_000/000_Acoustic_Grand_Piano.pat amp=120 pan=center 66 | 1 Tone_000/001_Acoustic_Brite_Piano.pat 67 | 2 Tone_000/002_Electric_Grand_Piano.pat 68 | 4 Tone_000/004_Electric_Piano_1_Rhodes.pat 69 | 5 Tone_000/005_Electric_Piano_2_Chorused_Yamaha_DX.pat 70 | 6 Tone_000/006_Harpsichord.pat 71 | 7 Tone_000/007_Clavinet.pat 72 | 8 Tone_000/008_Celesta.pat 73 | 9 Tone_000/009_Glockenspiel.pat 74 | 13 Tone_000/013_Xylophone.pat 75 | 14 Tone_000/014_Tubular_Bells.pat 76 | 15 Tone_000/015_Dulcimer.pat 77 | 16 Tone_000/016_Hammond_Organ.pat 78 | 19 Tone_000/019_Church_Organ.pat 79 | 21 Tone_000/021_Accordion.pat 80 | 23 Tone_000/023_Tango_Accordion.pat 81 | 24 Tone_000/024_Nylon_Guitar.pat 82 | 25 Tone_000/025_Steel_Guitar.pat 83 | 26 Tone_000/026_Jazz_Guitar.pat 84 | 27 Tone_000/027_Clean_Electric_Guitar.pat 85 | 28 Tone_000/028_Muted_Electric_Guitar.pat 86 | 29 Tone_000/029_Overdriven_Guitar.pat 87 | 30 Tone_000/030_Distortion_Guitar.pat 88 | 32 Tone_000/032_Acoustic_Bass.pat 89 | 33 Tone_000/033_Finger_Bass.pat 90 | 34 Tone_000/034_Pick_Bass.pat 91 | 35 Tone_000/035_Fretless_Bass.pat 92 | 36 Tone_000/036_Slap_Bass_1.pat 93 | 37 Tone_000/037_Slap_Bass_2.pat 94 | 38 Tone_000/038_Synth_Bass_1.pat 95 | 40 Tone_000/040_Violin.pat 96 | 42 Tone_000/042_Cello.pat 97 | 44 Tone_000/044_Tremolo_Strings.pat 98 | 45 Tone_000/045_Pizzicato_Strings.pat 99 | 46 Tone_000/046_Harp.pat 100 | 47 Tone_000/047_Timpani.pat 101 | 48 Tone_000/048_String_Ensemble_1_Marcato.pat 102 | 53 Tone_000/053_Voice_Oohs.pat 103 | 56 Tone_000/056_Trumpet.pat 104 | 57 Tone_000/057_Trombone.pat 105 | 58 Tone_000/058_Tuba.pat 106 | 59 Tone_000/059_Muted_Trumpet.pat 107 | 60 Tone_000/060_French_Horn.pat 108 | 61 Tone_000/061_Brass_Section.pat 109 | 64 Tone_000/064_Soprano_Sax.pat 110 | 65 Tone_000/065_Alto_Sax.pat 111 | 66 Tone_000/066_Tenor_Sax.pat 112 | 67 Tone_000/067_Baritone_Sax.pat 113 | 68 Tone_000/068_Oboe.pat 114 | 69 Tone_000/069_English_Horn.pat 115 | 70 Tone_000/070_Bassoon.pat 116 | 71 Tone_000/071_Clarinet.pat 117 | 72 Tone_000/072_Piccolo.pat 118 | 73 Tone_000/073_Flute.pat 119 | 74 Tone_000/074_Recorder.pat 120 | 75 Tone_000/075_Pan_Flute.pat 121 | 76 Tone_000/076_Bottle_Blow.pat 122 | 79 Tone_000/079_Ocarina.pat 123 | 80 Tone_000/080_Square_Wave.pat 124 | 84 Tone_000/084_Charang.pat 125 | 88 Tone_000/088_New_Age.pat 126 | 94 Tone_000/094_Halo_Pad.pat 127 | 95 Tone_000/095_Sweep_Pad.pat 128 | 98 Tone_000/098_Crystal.pat 129 | 101 Tone_000/101_Goblins--Unicorn.pat 130 | 102 Tone_000/102_Echo_Voice.pat 131 | 104 Tone_000/104_Sitar.pat 132 | 114 Tone_000/114_Steel_Drums.pat 133 | 115 Tone_000/115_Wood_Block.pat 134 | 120 Tone_000/120_Guitar_Fret_Noise.pat 135 | 122 Tone_000/122_Seashore.pat 136 | 125 Tone_000/125_Helicopter.pat 137 | 138 | -------------------------------------------------------------------------------- /static/hackmidi/static/css/main.7fbd665b.css: -------------------------------------------------------------------------------- 1 | body{font-family:sans-serif;margin:0;padding:0}.App{text-align:left}.App-header{background-color:#222;color:#fff;padding:20px;text-align:center}.App-header a{color:#fff}.App-header a:hover{color:grey}.App-title{font-size:1.5em}.App-intro{font-size:large;margin:auto;width:600px} 2 | /*# sourceMappingURL=main.7fbd665b.css.map*/ -------------------------------------------------------------------------------- /static/hackmidi/static/css/main.7fbd665b.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"static/css/main.7fbd665b.css","mappings":"AAAA,KAGE,sBAAuB,CAFvB,QAAS,CACT,SAEF,CCJA,KACE,eACF,CAEA,YACE,qBAAsB,CAEtB,UAAY,CADZ,YAAa,CAEb,iBACF,CAEA,cACE,UACF,CAEA,oBACE,UACF,CAEA,WACE,eACF,CAEA,WACE,eAAgB,CAEhB,WAAY,CADZ,WAEF","sources":["index.css","App.css"],"sourcesContent":["body {\n margin: 0;\n padding: 0;\n font-family: sans-serif;\n}\n",".App {\n text-align: left;\n}\n\n.App-header {\n background-color: #222;\n padding: 20px;\n color: white;\n text-align: center;\n}\n\n.App-header a {\n color: white;\n}\n\n.App-header a:hover {\n color: grey;\n}\n\n.App-title {\n font-size: 1.5em;\n}\n\n.App-intro {\n font-size: large;\n width: 600px;\n margin: auto;\n}\n"],"names":[],"sourceRoot":""} -------------------------------------------------------------------------------- /static/hackmidi/static/js/main.923a807c.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @license React 3 | * react-dom.production.min.js 4 | * 5 | * Copyright (c) Facebook, Inc. and its affiliates. 6 | * 7 | * This source code is licensed under the MIT license found in the 8 | * LICENSE file in the root directory of this source tree. 9 | */ 10 | 11 | /** 12 | * @license React 13 | * react-jsx-runtime.production.min.js 14 | * 15 | * Copyright (c) Facebook, Inc. and its affiliates. 16 | * 17 | * This source code is licensed under the MIT license found in the 18 | * LICENSE file in the root directory of this source tree. 19 | */ 20 | 21 | /** 22 | * @license React 23 | * react.production.min.js 24 | * 25 | * Copyright (c) Facebook, Inc. and its affiliates. 26 | * 27 | * This source code is licensed under the MIT license found in the 28 | * LICENSE file in the root directory of this source tree. 29 | */ 30 | 31 | /** 32 | * @license React 33 | * scheduler.production.min.js 34 | * 35 | * Copyright (c) Facebook, Inc. and its affiliates. 36 | * 37 | * This source code is licensed under the MIT license found in the 38 | * LICENSE file in the root directory of this source tree. 39 | */ 40 | -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Hacklily — sheet music editor 11 | 66 | 67 | 68 | 69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /static/musicxml2ly.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hacklily — musicxml2ly 9 | 65 | 66 | 67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /static/preview.css: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * This file is part of Hacklily, a web-based LilyPond editor. 4 | * Copyright (C) 2017 - present Jocelyn Stericker 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | body { 22 | margin: 0; 23 | padding: 0; 24 | } 25 | 26 | #root { 27 | background-color: #1e1e1e; 28 | } 29 | 30 | body.modeView { 31 | overflow-x: auto; 32 | overflow-y: hidden; 33 | background-color: #1e1e1e; 34 | } 35 | 36 | body.modeView #root { 37 | height: 100%; 38 | white-space: nowrap; 39 | } 40 | 41 | svg { 42 | background-color: white; 43 | } 44 | 45 | body.modeView svg + svg { 46 | margin-left: 2px; 47 | } 48 | 49 | body.modeView svg { 50 | max-height: 100%; 51 | max-width: 100vmin; 52 | white-space: normal; 53 | } 54 | 55 | body.modeBoth svg { 56 | width: 100%; 57 | } 58 | 59 | body.modeBoth svg + svg { 60 | margin-top: 6px; 61 | } 62 | 63 | @font-face { 64 | font-family: "emmentaler-11"; 65 | src: url("/emmentaler-11.otf") format("opentype"); 66 | } 67 | 68 | @font-face { 69 | font-family: "emmentaler-13"; 70 | src: url("/emmentaler-13.otf") format("opentype"); 71 | } 72 | 73 | @font-face { 74 | font-family: "emmentaler-14"; 75 | src: url("/emmentaler-14.otf") format("opentype"); 76 | } 77 | 78 | @font-face { 79 | font-family: "emmentaler-16"; 80 | src: url("/emmentaler-16.otf") format("opentype"); 81 | } 82 | 83 | @font-face { 84 | font-family: "emmentaler-18"; 85 | src: url("/emmentaler-18.otf") format("opentype"); 86 | } 87 | 88 | @font-face { 89 | font-family: "emmentaler-20"; 90 | src: url("/emmentaler-20.otf") format("opentype"); 91 | } 92 | 93 | @font-face { 94 | font-family: "emmentaler-23"; 95 | src: url("/emmentaler-23.otf") format("opentype"); 96 | } 97 | 98 | @font-face { 99 | font-family: "emmentaler-26"; 100 | src: url("/emmentaler-26.otf") format("opentype"); 101 | } 102 | 103 | @font-face { 104 | font-family: "emmentaler-brace"; 105 | src: url("/emmentaler-brace.otf") format("opentype"); 106 | } 107 | 108 | @font-face { 109 | font-family: "Century Schoolbook L"; 110 | src: url("/CenturySchL-Roma.otf") format("opentype"); 111 | } 112 | 113 | @font-face { 114 | font-family: "Century Schoolbook L"; 115 | font-weight: bold; 116 | src: url("/CenturySchL-Bold.otf") format("opentype"); 117 | } 118 | 119 | @font-face { 120 | font-family: "Century Schoolbook L"; 121 | font-style: italic; 122 | src: url("/CenturySchL-Ital.otf") format("opentype"); 123 | } 124 | 125 | @font-face { 126 | font-family: "Century Schoolbook L"; 127 | font-weight: bold; 128 | font-style: italic; 129 | src: url("/CenturySchL-BoldItal.otf") format("opentype"); 130 | } 131 | 132 | @font-face { 133 | font-family: "LilyPond Serif"; 134 | src: url("/CenturySchL-Roma.otf") format("opentype"); 135 | } 136 | 137 | @font-face { 138 | font-family: "LilyPond Serif"; 139 | font-weight: bold; 140 | src: url("/CenturySchL-Bold.otf") format("opentype"); 141 | } 142 | 143 | @font-face { 144 | font-family: "LilyPond Serif"; 145 | font-style: italic; 146 | src: url("/CenturySchL-Ital.otf") format("opentype"); 147 | } 148 | 149 | @font-face { 150 | font-family: "LilyPond Serif"; 151 | font-weight: bold; 152 | font-style: italic; 153 | src: url("/CenturySchL-BoldItal.otf") format("opentype"); 154 | } 155 | -------------------------------------------------------------------------------- /static/status.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hacklily status 8 | 9 | 10 | 11 |
12 |
13 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /static/vendor/bravura/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright © 2015, Steinberg Media Technologies GmbH (http://www.steinberg.net/), 2 | with Reserved Font Name "Bravura". 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | -------------------------------------------------------------------------------- /static/vendor/bravura/eot/Bravura.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/vendor/bravura/eot/Bravura.eot -------------------------------------------------------------------------------- /static/vendor/bravura/eot/BravuraText.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/vendor/bravura/eot/BravuraText.eot -------------------------------------------------------------------------------- /static/vendor/bravura/otf/Bravura.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/vendor/bravura/otf/Bravura.otf -------------------------------------------------------------------------------- /static/vendor/bravura/otf/BravuraText.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/vendor/bravura/otf/BravuraText.otf -------------------------------------------------------------------------------- /static/vendor/bravura/woff/Bravura.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/vendor/bravura/woff/Bravura.woff -------------------------------------------------------------------------------- /static/vendor/bravura/woff/BravuraText.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/vendor/bravura/woff/BravuraText.woff -------------------------------------------------------------------------------- /static/vendor/smufl/smufl-1.12.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jocelyn-stericker/hacklily/f1825f5c0369fdb3acc4b61d04b6b4199332f584/static/vendor/smufl/smufl-1.12.pdf -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noEmit": true, 4 | "target": "es5", 5 | "module": "commonjs", 6 | "jsx": "preserve", 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const webpack = require("webpack"); 3 | const CopyPlugin = require("copy-webpack-plugin"); 4 | const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin"); 5 | 6 | const dist = path.resolve(__dirname, "dist"); 7 | 8 | module.exports = { 9 | mode: "production", 10 | resolve: { 11 | extensions: [".ts", ".tsx", ".js", ".jsx"], 12 | fallback: { 13 | fs: false, 14 | buffer: false, 15 | http: false, 16 | path: false, 17 | }, 18 | }, 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.(eot|ttf|woff|woff2|svg|png|gif|jpe?g)$/, 23 | use: [{ loader: "file-loader" }], 24 | }, 25 | { 26 | test: /\.css$/i, 27 | use: ["style-loader", "css-loader"], 28 | }, 29 | { 30 | test: /\.m?[jt]sx?$/, 31 | exclude: /(node_modules|bower_components)/, 32 | use: { 33 | loader: "babel-loader", 34 | options: { 35 | presets: [ 36 | "@babel/preset-env", 37 | "@babel/preset-react", 38 | "@babel/preset-typescript", 39 | ], 40 | plugins: [ 41 | "@babel/plugin-proposal-class-properties", 42 | [ 43 | "@babel/plugin-transform-runtime", 44 | { 45 | regenerator: true, 46 | }, 47 | ], 48 | ], 49 | }, 50 | }, 51 | }, 52 | ], 53 | }, 54 | entry: { 55 | index: "./src/index.tsx", 56 | status: "./src/status/status.index.tsx", 57 | musicxml2ly: "./src/musicxml2ly/musicxml2ly.index.tsx", 58 | }, 59 | output: { 60 | path: dist, 61 | filename: "[name].js", 62 | }, 63 | devServer: { 64 | static: dist, 65 | }, 66 | plugins: [ 67 | new CopyPlugin({ patterns: [path.resolve(__dirname, "static")] }), 68 | new MonacoWebpackPlugin(), 69 | new webpack.EnvironmentPlugin([ 70 | "REACT_APP_GITHUB_CLIENT_ID", 71 | "REACT_APP_BACKEND_WS_URL", 72 | ]), 73 | ].filter((a) => !!a), 74 | }; 75 | --------------------------------------------------------------------------------