{"_id":"@benjamindehli/logic-pro-scripter-utils","name":"@benjamindehli/logic-pro-scripter-utils","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@benjamindehli/logic-pro-scripter-utils","version":"1.0.0","description":"TypeScript utilities and type definitions for Logic Pro Scripter API","type":"module","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","build:watch":"tsc --watch","clean":"rimraf dist","prebuild":"npm run clean","prepare":"npm run build","test":"jest","lint":"eslint src/**/*.ts","lint:fix":"eslint src/**/*.ts --fix","format":"prettier --write \"src/**/*.{ts,js,json}\"","format:check":"prettier --check \"src/**/*.{ts,js,json}\"","format:all":"prettier --write \"**/*.{ts,js,json,md}\" --ignore-path .gitignore"},"keywords":["logic-pro","scripter","midi","javascript","typescript","music","daw","apple"],"author":{"name":"Benjamin Dehli"},"license":"GPL-3.0","repository":{"type":"git","url":"git+https://github.com/benjamindehli/logic-pro-scripter-utils.git"},"bugs":{"url":"https://github.com/benjamindehli/logic-pro-scripter-utils/issues"},"homepage":"https://github.com/benjamindehli/logic-pro-scripter-utils#readme","devDependencies":{"@types/jest":"^29.5.0","@types/node":"^18.0.0","@typescript-eslint/eslint-plugin":"^6.0.0","@typescript-eslint/parser":"^6.0.0","eslint":"^8.0.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","jest":"^29.5.0","prettier":"^3.8.3","rimraf":"^5.0.0","ts-jest":"^29.1.0","typescript":"^5.0.0"},"engines":{"node":">=16.0.0"},"overrides":{"minimatch":">=9.0.7"},"gitHead":"97ff1da055a7b50b72495ca215afc6dfff534189","_id":"@benjamindehli/logic-pro-scripter-utils@1.0.0","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-CKSqkm73rieq7kkWKQBZ1KNWZl7e4N5/nPyeTmPbCPH4yfwHSFQZUhYO2y+Sw3eM7Cu7BkeIcoFLqkAxBhITWA==","shasum":"7234951779b6f3faeb9753a24c80a7225acbba7d","tarball":"https://registry.npmjs.org/@benjamindehli/logic-pro-scripter-utils/-/logic-pro-scripter-utils-1.0.0.tgz","fileCount":19,"unpackedSize":116538,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@benjamindehli%2flogic-pro-scripter-utils@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCID+d6UaBpGk9QcZhx50THNfg/mDvu7PcRAANR84NqepqAiEAiGs9zOa5s6Zm8XhbrMCi88b+LXkV0YHcvmxRHam4AK0="}]},"_npmUser":{"name":"benjamindehli","email":"superelg@gmail.com"},"directories":{},"maintainers":[{"name":"benjamindehli","email":"superelg@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/logic-pro-scripter-utils_1.0.0_1777134305575_0.9842061615001951"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-25T16:25:05.512Z","1.0.0":"2026-04-25T16:25:05.742Z","modified":"2026-04-25T16:25:06.066Z"},"maintainers":[{"name":"benjamindehli","email":"superelg@gmail.com"}],"description":"TypeScript utilities and type definitions for Logic Pro Scripter API","homepage":"https://github.com/benjamindehli/logic-pro-scripter-utils#readme","keywords":["logic-pro","scripter","midi","javascript","typescript","music","daw","apple"],"repository":{"type":"git","url":"git+https://github.com/benjamindehli/logic-pro-scripter-utils.git"},"author":{"name":"Benjamin Dehli"},"bugs":{"url":"https://github.com/benjamindehli/logic-pro-scripter-utils/issues"},"license":"GPL-3.0","readme":"# Logic Pro Scripter Utils\n\nA comprehensive TypeScript library providing type definitions, utilities, and helper functions for Apple Logic Pro's Scripter plugin. This package enables you to write type-safe JavaScript for MIDI processing in Logic Pro with full IntelliSense support and modern development practices.\n\n## Features\n\n- **Complete Type Definitions**: Full TypeScript interfaces for all Logic Pro Scripter APIs\n- **MIDI Event Classes**: Strongly-typed classes for all MIDI event types (NoteOn, NoteOff, ControlChange, etc.)\n- **Music Theory Utilities**: Helper functions for scales, chords, note conversion, and transposition\n- **Parameter Management**: Easy-to-use parameter definition utilities with common presets\n- **Timing Utilities**: Tools for working with Logic Pro's timing information\n- **Debug Tools**: Enhanced logging and debugging utilities for Scripter development\n- **Event Sequencing**: Tools for creating complex MIDI sequences and arpeggios\n- **Performance Monitoring**: Built-in performance measurement tools\n\n## Installation\n\n```bash\nnpm install logic-pro-scripter-utils\n```\n\n## Quick Start\n\n### Basic Usage\n\n```typescript\nimport { NoteOn, NoteOff, ControlChange, MIDIUtils, ParameterFactory, TraceLogger } from \"logic-pro-scripter-utils\";\n\n// Simple transpose example\nfunction HandleMIDI(event: Event) {\n    event.send(); // Send original\n\n    if (event instanceof NoteOn) {\n        // Transpose up an octave\n        const transposed = new NoteOn();\n        transposed.pitch = MIDIUtils.transposeNote(event.pitch, 12);\n        transposed.velocity = event.velocity;\n        transposed.channel = event.channel;\n        transposed.sendAfterMilliseconds(100);\n    }\n}\n```\n\n### Parameter Definition\n\n```typescript\nimport { ParameterFactory } from \"logic-pro-scripter-utils\";\n\nconst PluginParameters = [\n    ParameterFactory.linear(\"Transpose\", -24, 24, 0),\n    ParameterFactory.percentage(\"Mix\", 50),\n    ParameterFactory.menu(\"Scale\", [\"Major\", \"Minor\", \"Dorian\"], 0),\n    ParameterFactory.checkbox(\"Bypass\", false)\n];\n```\n\n### Music Theory Helpers\n\n```typescript\nimport { MIDIUtils, Scales, Chords } from \"logic-pro-scripter-utils\";\n\n// Convert MIDI note to frequency\nconst freq = MIDIUtils.midiNoteToFrequency(60); // 261.63 Hz (Middle C)\n\n// Get note name\nconst noteName = MIDIUtils.midiNoteToName(60); // \"C4\"\n\n// Check if note is in scale\nconst isInCMajor = MIDIUtils.isInScale(64, 60, Scales.MAJOR); // true (E in C Major)\n\n// Generate chord\nconst cMajorChord = Chords.MAJOR.map((interval) => 60 + interval); // [60, 64, 67]\n```\n\n### Enhanced Debugging\n\n```typescript\nimport { TraceLogger, MIDIEventLogger, DebugUtils } from \"logic-pro-scripter-utils\";\n\n// Set up logging\nTraceLogger.setLevel(TraceLevel.DEBUG);\nMIDIEventLogger.setLogAllEvents(true);\n\nfunction HandleMIDI(event: Event) {\n    // Log event details\n    MIDIEventLogger.logEvent(event, \"Processing\");\n\n    // Your processing logic here\n    TraceLogger.info(\"Processing note\", { pitch: event.pitch });\n\n    event.send();\n}\n```\n\n## API Reference\n\n### Event Classes\n\n#### Base Event Class\n\n```typescript\nabstract class Event {\n    channel: number; // MIDI channel (1-16)\n    articulationID: number; // Articulation ID (0-254)\n    readonly beatPos: number; // Event's beat position\n\n    send(): void;\n    sendAfterMilliseconds(ms: number): void;\n    sendAtBeat(beat: number): void;\n    sendAfterBeats(beat: number): void;\n    trace(): void;\n    toString(): string;\n}\n```\n\n#### MIDI Event Types\n\n- `NoteOn` - MIDI Note On events\n- `NoteOff` - MIDI Note Off events\n- `ControlChange` - MIDI Control Change events\n- `ProgramChange` - MIDI Program Change events\n- `PitchBend` - MIDI Pitch Bend events\n- `ChannelPressure` - MIDI Channel Pressure events\n- `PolyPressure` - MIDI Polyphonic Pressure events\n- `TargetEvent` - User-defined target events\n\n### Core Functions\n\n```typescript\n// Required for MIDI event processing\ntype HandleMIDIFunction = (event: Event) => void;\n\n// Optional timing-based processing\ntype ProcessMIDIFunction = () => void;\n\n// Plugin lifecycle\ntype ResetFunction = () => void;\ntype ParameterChangedFunction = (param: number, value: number) => void;\n\n// Global functions (available in Scripter environment)\ndeclare function GetParameter(name: string): number;\ndeclare function SetParameter(name: string, value: number): void;\ndeclare function GetTimingInfo(): TimingInfo;\ndeclare function Trace(message: any): void;\n```\n\n### Timing Information\n\n```typescript\ninterface TimingInfo {\n    readonly playing: boolean; // Transport is running\n    readonly blockStartBeat: number; // Block start beat position\n    readonly blockEndBeat: number; // Block end beat position\n    readonly blockLength: number; // Block length in beats\n    readonly tempo: number; // Current tempo\n    readonly meterNumerator: number; // Time signature numerator\n    readonly meterDenominator: number; // Time signature denominator\n    readonly cycling: boolean; // Transport is cycling\n    readonly leftCycleBeat: number; // Cycle start position\n    readonly rightCycleBeat: number; // Cycle end position\n}\n```\n\n### Parameter Types\n\n```typescript\ninterface PluginParameter {\n    name: string;\n    type: \"lin\" | \"log\" | \"indexed\" | \"checkbox\" | \"menu\";\n    minValue?: number;\n    maxValue?: number;\n    defaultValue?: number;\n    numberOfSteps?: number;\n    valueStrings?: string[];\n    unit?: string;\n}\n```\n\n### Utility Classes\n\n#### MIDIUtils\n\n- `midiNoteToFrequency(note)` - Convert MIDI note to Hz\n- `frequencyToMidiNote(freq)` - Convert Hz to MIDI note\n- `midiNoteToName(note)` - Convert MIDI note to name (e.g., \"C4\")\n- `noteNameToMidi(name)` - Convert note name to MIDI note\n- `transposeNote(note, semitones)` - Transpose a note\n- `isInScale(note, root, scale)` - Check if note is in scale\n- `normalizeVelocity(velocity)` - Convert velocity to 0-1 range\n- `applyVelocityCurve(velocity, curve)` - Apply velocity curve\n\n#### ParameterFactory\n\n- `linear(name, min, max, default)` - Linear parameter\n- `logarithmic(name, min, max, default)` - Logarithmic parameter\n- `checkbox(name, default)` - Boolean parameter\n- `menu(name, options, default)` - Menu parameter\n- `gainDB(name, min, max, default)` - Gain in dB\n- `frequency(name, min, max, default)` - Frequency in Hz\n- `percentage(name, default)` - Percentage parameter\n\n#### EventSequencer\n\n```typescript\nclass EventSequencer {\n    addEvent(event: Event, time: number): void;\n    sendSequence(startTime?: number): void;\n    clear(): void;\n    getLength(): number;\n}\n```\n\n#### Arpeggiator\n\n```typescript\nclass Arpeggiator {\n    setNotes(notes: number[]): void;\n    setPattern(pattern: number[]): void;\n    getNextNote(): number | null;\n    reset(): void;\n\n    static readonly PATTERNS = {\n        UP: [0, 1, 2, 3],\n        DOWN: [3, 2, 1, 0],\n        UP_DOWN: [0, 1, 2, 3, 2, 1]\n        // ... more patterns\n    };\n}\n```\n\n## Musical Constants\n\n### Scales\n\n```typescript\nconst Scales = {\n    MAJOR: [0, 2, 4, 5, 7, 9, 11],\n    MINOR: [0, 2, 3, 5, 7, 8, 10],\n    PENTATONIC_MAJOR: [0, 2, 4, 7, 9],\n    BLUES: [0, 3, 5, 6, 7, 10]\n    // ... more scales\n};\n```\n\n### Chords\n\n```typescript\nconst Chords = {\n    MAJOR: [0, 4, 7],\n    MINOR: [0, 3, 7],\n    MAJOR_7: [0, 4, 7, 11],\n    MINOR_7: [0, 3, 7, 10]\n    // ... more chords\n};\n```\n\n### MIDI Constants\n\n```typescript\nconst MIDIControllers = {\n    MODULATION: 1,\n    VOLUME: 7,\n    PAN: 10,\n    SUSTAIN_PEDAL: 64\n    // ... more controllers\n};\n\nconst MIDINotes = {\n    MIDDLE_C: 60,\n    A440: 69,\n    C4: 60,\n    C5: 72\n    // ... more notes\n};\n```\n\n## Examples\n\n### Chord Generator\n\n```typescript\nimport { NoteOn, Chords, MIDIUtils } from \"logic-pro-scripter-utils\";\n\nfunction HandleMIDI(event: Event) {\n    if (event instanceof NoteOn) {\n        // Send original note\n        event.send();\n\n        // Generate major chord\n        const chordType = Chords.MAJOR;\n        chordType.forEach((interval, index) => {\n            if (index === 0) return; // Skip root (already sent)\n\n            const chordNote = new NoteOn();\n            chordNote.pitch = event.pitch + interval;\n            chordNote.velocity = Math.round(event.velocity * 0.8); // Softer\n            chordNote.channel = event.channel;\n            chordNote.send();\n        });\n    } else {\n        event.send();\n    }\n}\n```\n\n### Scale Quantizer\n\n```typescript\nimport { NoteOn, MIDIUtils, Scales } from \"logic-pro-scripter-utils\";\n\nconst PluginParameters = [\n    ParameterFactory.menu(\"Root\", [\"C\", \"C#\", \"D\", \"D#\", \"E\", \"F\", \"F#\", \"G\", \"G#\", \"A\", \"A#\", \"B\"], 0),\n    ParameterFactory.menu(\"Scale\", [\"Major\", \"Minor\", \"Dorian\", \"Pentatonic\"], 0)\n];\n\nfunction HandleMIDI(event: Event) {\n    if (event instanceof NoteOn) {\n        const rootNote = GetParameter(\"Root\");\n        const scaleType = GetParameter(\"Scale\");\n        const scales = [Scales.MAJOR, Scales.MINOR, Scales.DORIAN, Scales.PENTATONIC_MAJOR];\n\n        // Quantize to scale\n        let quantizedPitch = event.pitch;\n        const scale = scales[scaleType];\n\n        if (!MIDIUtils.isInScale(event.pitch, rootNote, scale)) {\n            // Find nearest scale note\n            let minDistance = 12;\n            for (let offset = -6; offset <= 6; offset++) {\n                const testPitch = event.pitch + offset;\n                if (MIDIUtils.isInScale(testPitch, rootNote, scale)) {\n                    if (Math.abs(offset) < Math.abs(minDistance)) {\n                        minDistance = offset;\n                    }\n                }\n            }\n            quantizedPitch = event.pitch + minDistance;\n        }\n\n        event.pitch = quantizedPitch;\n    }\n\n    event.send();\n}\n```\n\n### Advanced Arpeggiator\n\n```typescript\nimport { NoteOn, NoteOff, Arpeggiator, TimingUtils, ParameterFactory } from \"logic-pro-scripter-utils\";\n\nlet arp = new Arpeggiator();\nlet heldNotes = new Set<number>();\nlet nextNoteTime = 0;\n\nconst PluginParameters = [\n    ParameterFactory.menu(\"Pattern\", [\"Up\", \"Down\", \"UpDown\"], 0),\n    ParameterFactory.linear(\"Rate\", 0.125, 2, 0.25, 16) // Note divisions\n];\n\nvar NeedsTimingInfo = true;\n\nfunction HandleMIDI(event: Event) {\n    if (event instanceof NoteOn) {\n        heldNotes.add(event.pitch);\n        updateArpeggiator();\n    } else if (event instanceof NoteOff) {\n        heldNotes.delete(event.pitch);\n        updateArpeggiator();\n    } else {\n        event.send(); // Pass through other events\n    }\n}\n\nfunction ProcessMIDI() {\n    const timing = GetTimingInfo();\n\n    if (timing.playing && heldNotes.size > 0) {\n        const rate = GetParameter(\"Rate\");\n\n        if (timing.blockStartBeat >= nextNoteTime) {\n            const nextNote = arp.getNextNote();\n            if (nextNote !== null) {\n                const noteOn = new NoteOn();\n                noteOn.pitch = nextNote;\n                noteOn.velocity = 80;\n                noteOn.sendAtBeat(nextNoteTime);\n\n                // Schedule note off\n                const noteOff = new NoteOff();\n                noteOff.pitch = nextNote;\n                noteOff.sendAtBeat(nextNoteTime + rate * 0.8);\n            }\n\n            nextNoteTime += rate;\n        }\n    }\n}\n\nfunction updateArpeggiator() {\n    const notes = Array.from(heldNotes).sort((a, b) => a - b);\n    arp.setNotes(notes);\n\n    const patternIndex = GetParameter(\"Pattern\");\n    const patterns = [Arpeggiator.PATTERNS.UP, Arpeggiator.PATTERNS.DOWN, Arpeggiator.PATTERNS.UP_DOWN];\n    arp.setPattern(patterns[patternIndex]);\n}\n```\n\n## Development\n\n### Building\n\n```bash\nnpm run build\n```\n\n### Testing\n\n```bash\nnpm test\n```\n\n### Linting\n\n```bash\nnpm run lint\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\n## License\n\nGPL-3.0 License - see the [LICENSE](LICENSE) file for details.\n\n## Related\n\n- [Logic Pro User Guide](https://support.apple.com/guide/logicpro/)\n- [Logic Pro Scripter Documentation](https://support.apple.com/en-gb/guide/logicpro/lgce3905a48c/mac)\n\n## Changelog\n\n### 1.0.0\n\n- Initial release\n- Complete TypeScript definitions for Logic Pro Scripter API\n- MIDI utilities and music theory helpers\n- Parameter management utilities\n- Debug and tracing tools\n- Event sequencing and arpeggiator classes\n- Comprehensive examples and documentation\n","readmeFilename":"README.md","_rev":"1-6e58d1712526e395831fc2ac486a6c75"}