satie
Version:
A sheet music renderer for the web
168 lines (147 loc) • 5.64 kB
text/typescript
/**
* This file is part of Satie music engraver <https://github.com/jnetterf/satie>.
* Copyright (C) Joshua Netterfield <joshua.ca> 2015 - present.
*
* Satie is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Satie is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Satie. If not, see <http://www.gnu.org/licenses/>.
*/
import {readFile} from "fs";
import * as yargs from "yargs";
import Application from "./engine_application";
import SongImpl from "./engine_songImpl";
function readStdin(onEnd: (s: string) => void) {
let content = "";
process.stdin.resume();
process.stdin.on("data", function(buf: Buffer) {
content += buf.toString();
});
process.stdin.on("end", function() {
onEnd(content);
});
}
function read(file: string, onEnd: (s: string) => void, onErr: (err: any) => void) {
if (file === "<stdin>") {
readStdin(onEnd);
} else {
readFile(file, "utf8", function (err, data) {
if (err) {
onErr(err);
}
onEnd(data);
});
}
}
function cannotRead(err: any) {
console.error("Fatal. Cannot read '%s'.", err.path);
process.exit(1);
}
(function main() {
let args = yargs
.wrap(100)
.usage("Usage: $0 <command> [options]")
.example("$0 init -x file.xml", "print initialized MusicXML")
.example("$0 init", "initialize from stdin")
.example("$0 diff -x old.xml -x new.xml", "print a patch from old to new")
.example("$0 diff -x old.xml", "print a patch from old to stdin")
.example("$0 patch -x old.xml -p p.json", "print p.json applied to old.xml")
.example("$0 patch -p p.json", "print p.json applied to stdin")
.example("$0 render -x in.xml", "prints multiple svgs concatenated")
.example("$0 render -x in.xml --as out", "writes out001.svg, out002.svg, ...")
.demand(1)
.alias("x", "xml")
.describe("x", "Specify a MusicXML input")
.default("xml", ["<stdin>"])
.alias("p", "patch")
.describe("p", "Specify a patch generated with 'satie diff'")
.help("h")
.alias("h", "help")
.check(function(argv) {
if (argv["_"].length > 1) {
throw "Unexpected string '" + argv["_"][1] + "'.";
}
switch (argv["_"][0]) {
case "init":
case "render":
if (argv["xml"].length > 1) {
throw "Too many files specified.";
}
break;
case "diff":
throw argv["_"][0] + " is not implemented, yet.";
case "patch":
throw argv["_"][0] + " is not implemented, yet.";
default:
throw new Error(`Invalid operation ${argv["_"][0]}`);
}
return true;
})
.strict();
// Some of the type definitions are lacking.
let argv = args
.command("init", "adds revision tracking and layout information to a MusicXML file")
.command("diff", "generate a patch between two initialized MusicXML files")
.command("patch", "applies patch from 'satie diff' to an initialized MusicXML file")
.command("render", "converts a MusicXML file to one or more SVGs page-by-page")
.array("xml")
.epilog("(C) Copyright Josh Netterfield 2015")
.argv;
/* tslint:disable */
new Application({
satieRoot: "https://nettek.ca/satie/vendor/",
preloadedFonts: []
});
/* tslint:enable */
let log = console.log.bind(console);
switch (argv._[0]) {
case "init":
read(argv.xml[0],
musicXML => {
let song = new SongImpl({
baseSrc: musicXML,
onError: cannotRead,
onLoaded: () => {
try {
const musicXML = song.toMusicXML();
log(musicXML);
} catch(err) {
cannotRead(err);
}
},
});
}, cannotRead);
break;
case "diff":
throw "not implemented";
case "patch":
throw "not implemented";
case "render":
read(argv.xml[0],
musicXML => {
let song = new SongImpl({
baseSrc: musicXML,
onError: cannotRead,
onLoaded: () => {
try {
const svg = song.toSVG();
log(svg);
} catch (err) {
cannotRead(err);
}
},
});
}, cannotRead);
break;
default:
throw new Error(`Invalid operation ${argv._[0]}`);
}
}());