diff --git a/src/lib/csound/execution-context.ts b/src/lib/csound/execution-context.ts index 594b25d..d55a66f 100644 --- a/src/lib/csound/execution-context.ts +++ b/src/lib/csound/execution-context.ts @@ -4,6 +4,7 @@ export type EvalSource = 'selection' | 'block' | 'file'; export class ExecutionContext { private contentProvider: (() => string) | null = null; + private initialized = false; constructor(private csound: CsoundStore) {} @@ -12,7 +13,7 @@ export class ExecutionContext { } /** - * Execute entire file + * Execute entire file (composition mode: full restart) */ async executeFile(): Promise { const content = this.contentProvider?.() ?? ''; @@ -20,29 +21,66 @@ export class ExecutionContext { return; } + this.initialized = false; await this.csound.stop(); - await this.csound.evaluateCode(content); + await this.csound.evaluate(content); } /** - * Execute code block (instrument, opcode, or paragraph) + * Execute code block (live coding mode: incremental evaluation) */ async executeBlock(code: string): Promise { if (!code.trim()) { return; } - await this.csound.evaluateCode(code); + if (!this.initialized) { + await this.csound.restart(); + this.initialized = true; + } + + await this.evaluateCodeBlock(code); } /** - * Execute selected text + * Execute selected text (live coding mode: incremental evaluation) */ async executeSelection(code: string): Promise { if (!code.trim()) { return; } - await this.csound.evaluateCode(code); + if (!this.initialized) { + await this.csound.restart(); + this.initialized = true; + } + + await this.evaluateCodeBlock(code); + } + + /** + * Smart detection and evaluation of code blocks + */ + private async evaluateCodeBlock(code: string): Promise { + const trimmed = code.trim(); + + // Score event detection: starts with i, f, e, or a + // Examples: "i 1 0 1", "f 1 0 8192 10 1", "e", "a 0 0 1" + if (/^[ifea]\s+[\d\-]/.test(trimmed)) { + await this.csound.sendScoreEvent(trimmed); + return; + } + + // Channel assignment detection: "varname = value" + // Examples: "gkFreq = 440", "gkAmp = 0.5" + const channelMatch = trimmed.match(/^(\w+)\s*=\s*([\d\.\-]+)/); + if (channelMatch) { + const [, channelName, valueStr] = channelMatch; + await this.csound.setControlChannel(channelName, parseFloat(valueStr)); + return; + } + + // Default: orchestra code (instrument definitions, opcodes, etc.) + await this.csound.compileOrchestra(trimmed); } }