diff --git a/.github/workflows/check-makeosc-build.yml b/.github/workflows/check-makeosc-build.yml new file mode 100644 index 0000000..155bc44 --- /dev/null +++ b/.github/workflows/check-makeosc-build.yml @@ -0,0 +1,25 @@ +name: Check makeosc builds +on: + pull_request: + branches: + - main + paths: + - 'apps/makeosc/**' +jobs: + build-webui: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Set up Node.js + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + with: + node-version-file: '.nvmrc' + cache: 'npm' + cache-dependency-path: 'package-lock.json' + + - name: Install Node.js dependencies + run: npm ci --workspace makeosc + + - run: npm run build --workspace makeosc diff --git a/.github/workflows/publish-makeosc.yml b/.github/workflows/publish-makeosc.yml new file mode 100644 index 0000000..eddfce4 --- /dev/null +++ b/.github/workflows/publish-makeosc.yml @@ -0,0 +1,24 @@ +name: Publish makeosc to npmjs +on: + push: + tags: + - 'makeosc/*' +jobs: + publish: + permissions: + id-token: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + with: + node-version-file: '.nvmrc' + registry-url: 'https://registry.npmjs.org' + cache: 'npm' + cache-dependency-path: './package-lock.json' + - name: Install Node.js dependencies + run: npm ci --workspace=makeosc + - name: Publish to NPM + run: npm publish --provenance --access=public --workspace=makeosc + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/apps/makeosc/.gitignore b/apps/makeosc/.gitignore new file mode 100644 index 0000000..53c37a1 --- /dev/null +++ b/apps/makeosc/.gitignore @@ -0,0 +1 @@ +dist \ No newline at end of file diff --git a/apps/makeosc/README.md b/apps/makeosc/README.md new file mode 100644 index 0000000..d29f5c6 --- /dev/null +++ b/apps/makeosc/README.md @@ -0,0 +1,41 @@ +![npm](https://img.shields.io/npm/v/makeosc) + +# makeosc + +Simple NodeJS script for generating OSC bytes output to stdout. + +## Usage + +``` +Usage: makeosc [options] + +simple util to make osc buffers + +Options: + -V, --version output the version number + --address
OSC address + --args osc args (default: []) + --slip slip encode message (default: false) + --types osc arg types (choices: "s", "i", "f", "b", default: []) + -h, --help display help for command +``` + +- using npx `npx makeosc@latest --address /hello` +- install using `npm install -g makeosc@latest` and run `makeosc --address /hello` + +## Notes + +- `--types` option is a space seperate list of type characters that will determine what the corresponding argument type will be set to + - optional + - uses type codes from the OSC spec +- `--args` option is a space-separated list of arguments. If a corresponding type is not found in the `--types` option it will default to string (`s`). + - blobs (`b`) are to be entered as hex string representing the buffer to be sent so the ASCII string `hello` would be `68656c6c6f` +- the default protocol is UDP but can be changed to TCP using the `--protocol` flag + +## Examples + +- `makeosc --address /test --args 1.0` +- `makeosc --address /this/is/sent/via/tcp` +- `makeosc --address /test/with/types --args 1 2.0 three --types i f` + - note that `types` is not the same length as `args` so the remaining argument (`three`) will default to string +- `makeosc --address /blob --args 68656c6c6f --types b` diff --git a/apps/makeosc/package.json b/apps/makeosc/package.json new file mode 100644 index 0000000..2a3e231 --- /dev/null +++ b/apps/makeosc/package.json @@ -0,0 +1,33 @@ +{ + "name": "makeosc", + "version": "0.0.1", + "description": "Simple NodeJS utility for generating osc buffers", + "main": "dist/main.js", + "bin": { + "makeosc": "dist/main.js" + }, + "scripts": { + "prebuild": "rimraf dist", + "build": "esbuild src/main.js --bundle --platform=node --outfile=dist/main.js", + "prepack": "npm run build" + }, + "author": { + "name": "Joel Wetzell", + "email": "me@jwetzell.com", + "url": "https://jwetzell.com" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/jwetzell/osc-js.git" + }, + "license": "MIT", + "dependencies": { + "@jwetzell/osc": "0.2.2", + "commander": "^11.0.0", + "slip": "^1.0.2" + }, + "devDependencies": { + "esbuild": "0.24.0", + "rimraf": "6.0.1" + } +} diff --git a/apps/makeosc/src/main.js b/apps/makeosc/src/main.js new file mode 100755 index 0000000..f14f960 --- /dev/null +++ b/apps/makeosc/src/main.js @@ -0,0 +1,45 @@ +#!/usr/bin/env node + +const { Option, program } = require('commander'); +const slip = require('slip'); +const { argToTypedArg } = require('./utils'); +const osc = require('@jwetzell/osc'); +const packageInfo = require('../package.json'); + +program.name(packageInfo.name); +program.version(packageInfo.version); +program.description('simple util to make osc buffers'); +program.addOption(new Option('--address
', 'OSC address').makeOptionMandatory()); +program.addOption(new Option('--args ', 'osc args').default([])); +program.addOption(new Option('--slip', 'slip encode message').default(false)); +program.addOption(new Option('--types ', 'osc arg types').choices(['s', 'i', 'f', 'b']).default([])); +program.action((options) => { + const { address, args, types } = options; + + const typedArgs = args?.map((rawArg, index) => { + const argType = types[index] || 's'; + + return { + type: argType, + value: argToTypedArg(rawArg, argType), + }; + }); + + let oscMsgBuffer = osc.messageToBuffer({ + address, + args: typedArgs, + }); + + if (options.slip) { + oscMsgBuffer = slip.encode(oscMsgBuffer); + } + + process.stdout.write(oscMsgBuffer); +}); +program.parse(); + +process.stdout.on('error', (err) => { + if (err.code === 'EPIPE') { + process.exit(0); + } +}); diff --git a/apps/makeosc/src/utils.js b/apps/makeosc/src/utils.js new file mode 100644 index 0000000..9242e21 --- /dev/null +++ b/apps/makeosc/src/utils.js @@ -0,0 +1,31 @@ +const oscTypeConverterMap = { + s: { + fromString: (string) => string, + }, + f: { + fromString: (string) => Number.parseFloat(string), + }, + i: { + fromString: (string) => Number.parseInt(string, 10), + }, + b: { + fromString: (string) => Buffer.from(string, 'hex'), + }, +}; + +function argToTypedArg(rawArg, type = 's') { + const typeConverter = oscTypeConverterMap[type]; + if (typeConverter === undefined) { + throw new Error('osc type error: unknown type '.concat(type)); + } + + if (typeConverter.fromString === undefined) { + throw new Error('osc type error: no string converter for type '.concat(type)); + } + + return typeConverter.fromString(rawArg); +} + +module.exports = { + argToTypedArg, +}; diff --git a/package-lock.json b/package-lock.json index d10313a..11a775d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,22 @@ "prettier": "3.3.3" } }, + "apps/makeosc": { + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "@jwetzell/osc": "0.2.2", + "commander": "^11.0.0", + "slip": "^1.0.2" + }, + "bin": { + "makeosc": "dist/main.js" + }, + "devDependencies": { + "esbuild": "0.24.0", + "rimraf": "6.0.1" + } + }, "apps/sendosc": { "version": "1.0.1", "license": "MIT", @@ -2470,6 +2486,10 @@ "node": "20 || >=22" } }, + "node_modules/makeosc": { + "resolved": "apps/makeosc", + "link": true + }, "node_modules/minimatch": { "version": "10.0.1", "dev": true,