Beginning of File System integration
This commit is contained in:
917
csound_browser_readme.md
Normal file
917
csound_browser_readme.md
Normal file
@ -0,0 +1,917 @@
|
||||
# @csound/browser
|
||||
[](https://www.npmjs.com/package/@csound/browser)
|
||||
[](https://github.com/csound/csound/actions?query=workflow%3Acsound_wasm)
|
||||
[](https://github.com/prettier/prettier)
|
||||
|
||||
|
||||
## Api Documentation
|
||||
|
||||
## Objects
|
||||
|
||||
<dl>
|
||||
<dt><a href="#CsoundObj">CsoundObj</a> : <code>object</code></dt>
|
||||
<dd><p>CsoundObj API.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
## Functions
|
||||
|
||||
<dl>
|
||||
<dt><a href="#Csound">Csound([params])</a> ⇒ <code>Promise.<(CsoundObj|undefined)></code></dt>
|
||||
<dd><p>The default entry for @csound/wasm/browser module.
|
||||
If loaded successfully, it returns CsoundObj,
|
||||
otherwise undefined.</p>
|
||||
</dd>
|
||||
<dt><a href="#getTable">getTable(tableNum)</a> ⇒ <code>Promise.<(Float64Array|undefined)></code></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
## Typedefs
|
||||
|
||||
<dl>
|
||||
<dt><a href="#CSOUND_PARAMS">CSOUND_PARAMS</a></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#CS_MIDIDEVICE">CS_MIDIDEVICE</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
<a name="CsoundObj"></a>
|
||||
|
||||
## CsoundObj : <code>object</code>
|
||||
CsoundObj API.
|
||||
|
||||
**Kind**: global namespace
|
||||
|
||||
* [CsoundObj](#CsoundObj) : <code>object</code>
|
||||
* _global_
|
||||
* [getTable(tableNum)](#getTable) ⇒ <code>Promise.<(Float64Array\|undefined)></code>
|
||||
* _static_
|
||||
* [.fs](#CsoundObj.fs) : <code>IFs:memfs</code>
|
||||
* [.eventNames()](#CsoundObj.eventNames) ⇒ <code>Array.<string></code>
|
||||
* [.listenerCount()](#CsoundObj.listenerCount) ⇒ <code>number</code>
|
||||
* [.listeners(eventName)](#CsoundObj.listeners) ⇒ <code>Array.<function()></code>
|
||||
* [.off(eventName, listener)](#CsoundObj.off) ⇒ <code>external:EventEmitter</code>
|
||||
* [.on(eventName, listener)](#CsoundObj.on) ⇒ <code>external:EventEmitter</code>
|
||||
* [.addListener(eventName, listener)](#CsoundObj.addListener) ⇒ <code>external:EventEmitter</code>
|
||||
* [.once(eventName, listener)](#CsoundObj.once) ⇒ <code>external:EventEmitter</code>
|
||||
* [.removeAllListeners(eventName)](#CsoundObj.removeAllListeners) ⇒ <code>external:EventEmitter</code>
|
||||
* [.removeListener(eventName, listener)](#CsoundObj.removeListener) ⇒ <code>external:EventEmitter</code>
|
||||
* [.getSr()](#CsoundObj.getSr) ⇒ <code>Promise.<number></code>
|
||||
* [.getKr()](#CsoundObj.getKr) ⇒ <code>Promise.<number></code>
|
||||
* [.getKsmps()](#CsoundObj.getKsmps) ⇒ <code>Promise.<number></code>
|
||||
* [.getNchnls()](#CsoundObj.getNchnls) ⇒ <code>Promise.<number></code>
|
||||
* [.getNchnlsInput()](#CsoundObj.getNchnlsInput) ⇒ <code>Promise.<number></code>
|
||||
* [.get0dBFS()](#CsoundObj.get0dBFS) ⇒ <code>Promise.<number></code>
|
||||
* [.getA4()](#CsoundObj.getA4) ⇒ <code>Promise.<number></code>
|
||||
* [.getCurrentTimeSamples()](#CsoundObj.getCurrentTimeSamples) ⇒ <code>Promise.<number></code>
|
||||
* [.getSizeOfMYFLT()](#CsoundObj.getSizeOfMYFLT) ⇒ <code>Promise.<number></code>
|
||||
* [.setOption(option)](#CsoundObj.setOption) ⇒ <code>Promise.<number></code>
|
||||
* [.setParams(csoundParams)](#CsoundObj.setParams) ⇒ <code>Promise.<undefined></code>
|
||||
* [.getParams()](#CsoundObj.getParams) ⇒ [<code>Promise.<CSOUND\_PARAMS></code>](#CSOUND_PARAMS)
|
||||
* [.getDebug()](#CsoundObj.getDebug) ⇒ <code>Promise.<number></code>
|
||||
* [.setDebug(debug)](#CsoundObj.setDebug) ⇒ <code>Promise.<undefined></code>
|
||||
* [.inputMessage(scoreEvent)](#CsoundObj.inputMessage) ⇒ <code>Promise.<number></code>
|
||||
* [.inputMessageAsync(scoreEvent)](#CsoundObj.inputMessageAsync) ⇒ <code>Promise.<number></code>
|
||||
* [.getControlChannel(channelName)](#CsoundObj.getControlChannel) ⇒ <code>Promise.<undefined></code>
|
||||
* [.setControlChannel(channelName, value)](#CsoundObj.setControlChannel) ⇒ <code>Promise.<undefined></code>
|
||||
* [.getStringChannel(channelName)](#CsoundObj.getStringChannel) ⇒ <code>Promise.<undefined></code>
|
||||
* [.setStringChannel(channelName, value)](#CsoundObj.setStringChannel) ⇒ <code>Promise.<undefined></code>
|
||||
* [.getOutputName()](#CsoundObj.getOutputName) ⇒ <code>Promise.<string></code>
|
||||
* [.getInputName()](#CsoundObj.getInputName) ⇒ <code>Promise.<string></code>
|
||||
* [.destroy()](#CsoundObj.destroy) ⇒ <code>Promise.<undefined></code>
|
||||
* [.getAPIVersion()](#CsoundObj.getAPIVersion) ⇒ <code>Promise.<number></code>
|
||||
* [.getVersion()](#CsoundObj.getVersion) ⇒ <code>Promise.<number></code>
|
||||
* [.initialize()](#CsoundObj.initialize) ⇒ <code>Promise.<number></code>
|
||||
* [.parseOrc(orc)](#CsoundObj.parseOrc) ⇒ <code>Promise.<object></code>
|
||||
* [.compileTree(tree)](#CsoundObj.compileTree) ⇒ <code>Promise.<number></code>
|
||||
* [.compileOrc(orc)](#CsoundObj.compileOrc) ⇒ <code>Promise.<number></code>
|
||||
* [.evalCode(orc)](#CsoundObj.evalCode) ⇒ <code>Promise.<number></code>
|
||||
* [.start()](#CsoundObj.start) ⇒ <code>Promise.<number></code>
|
||||
* [.compileCsd(path)](#CsoundObj.compileCsd) ⇒ <code>Promise.<number></code>
|
||||
* [.compileCsdText(orc)](#CsoundObj.compileCsdText) ⇒ <code>Promise.<number></code>
|
||||
* [.perform()](#CsoundObj.perform) ⇒ <code>Promise.<number></code>
|
||||
* [.performKsmps()](#CsoundObj.performKsmps) ⇒ <code>Promise.<number></code>
|
||||
* [.performBuffer()](#CsoundObj.performBuffer) ⇒ <code>Promise.<number></code>
|
||||
* [.stop()](#CsoundObj.stop) ⇒ <code>Promise.<undefined></code>
|
||||
* [.cleanup()](#CsoundObj.cleanup) ⇒ <code>Promise.<number></code>
|
||||
* [.reset()](#CsoundObj.reset) ⇒ <code>Promise.<number></code>
|
||||
* [.getInputBufferSize()](#CsoundObj.getInputBufferSize) ⇒ <code>Promise.<number></code>
|
||||
* [.getOutputBufferSize()](#CsoundObj.getOutputBufferSize) ⇒ <code>Promise.<number></code>
|
||||
* [.getInputBuffer()](#CsoundObj.getInputBuffer) ⇒ <code>Promise.<number></code>
|
||||
* [.getOutputBuffer()](#CsoundObj.getOutputBuffer) ⇒ <code>Promise.<number></code>
|
||||
* [.getSpin()](#CsoundObj.getSpin) ⇒ <code>Promise.<number></code>
|
||||
* [.getSpout()](#CsoundObj.getSpout) ⇒ <code>Promise.<number></code>
|
||||
* [.getMIDIDevList(isOutput)](#CsoundObj.getMIDIDevList) ⇒ [<code>Promise.<CS\_MIDIDEVICE></code>](#CS_MIDIDEVICE)
|
||||
* [.getRtMidiName()](#CsoundObj.getRtMidiName) ⇒ <code>Promise.<string></code>
|
||||
* [.midiMessage(midi, midi, midi)](#CsoundObj.midiMessage) ⇒ <code>Promise.<void></code>
|
||||
* [.isScorePending()](#CsoundObj.isScorePending) ⇒ <code>Promise.<number></code>
|
||||
* [.setScorePending(pending)](#CsoundObj.setScorePending) ⇒ <code>Promise.<undefined></code>
|
||||
* [.readScore(score)](#CsoundObj.readScore) ⇒ <code>Promise.<undefined></code>
|
||||
* [.getScoreTime()](#CsoundObj.getScoreTime) ⇒ <code>Promise.<number></code>
|
||||
* [.getScoreOffsetSeconds()](#CsoundObj.getScoreOffsetSeconds) ⇒ <code>Promise.<number></code>
|
||||
* [.setScoreOffsetSeconds(time)](#CsoundObj.setScoreOffsetSeconds) ⇒ <code>Promise.<number></code>
|
||||
* [.rewindScore()](#CsoundObj.rewindScore) ⇒ <code>Promise.<number></code>
|
||||
* [.tableLength(tableNum)](#CsoundObj.tableLength) ⇒ <code>Promise.<number></code>
|
||||
* [.tableGet(tableNum, tableIndex)](#CsoundObj.tableGet) ⇒ <code>Promise.<number></code>
|
||||
* [.tableSet(tableNum, tableIndex, value)](#CsoundObj.tableSet) ⇒ <code>Promise.<undefined></code>
|
||||
* [.tableCopyIn(tableNum, tableIndex, array)](#CsoundObj.tableCopyIn) ⇒ <code>Promise.<undefined></code>
|
||||
* [.tableCopyOut(tableNum)](#CsoundObj.tableCopyOut) ⇒ <code>Promise.<(Float64Array\|undefined)></code>
|
||||
* [.getTableArgs(tableNum)](#CsoundObj.getTableArgs) ⇒ <code>Promise.<(Float64Array\|undefined)></code>
|
||||
* [.isNamedGEN(tableNum)](#CsoundObj.isNamedGEN) ⇒ <code>Promise.<number></code>
|
||||
* [.getNamedGEN(tableNum)](#CsoundObj.getNamedGEN) ⇒ <code>Promise.<(string\|undefined)></code>
|
||||
|
||||
<a name="getTable"></a>
|
||||
|
||||
### CsoundObjgetTable(tableNum) ⇒ <code>Promise.<(Float64Array\|undefined)></code>
|
||||
**Kind**: global method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tableNum | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.fs"></a>
|
||||
|
||||
### CsoundObj.fs : <code>IFs:memfs</code>
|
||||
The in-browser filesystem based on nodejs's
|
||||
built-in module "fs"
|
||||
|
||||
**Kind**: static property of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.eventNames"></a>
|
||||
|
||||
### CsoundObj.eventNames() ⇒ <code>Array.<string></code>
|
||||
Returns an array listing the events for which the emitter has registered listeners.
|
||||
The values in the array are strings.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.listenerCount"></a>
|
||||
|
||||
### CsoundObj.listenerCount() ⇒ <code>number</code>
|
||||
Returns the number of listeners listening to the event named eventName.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.listeners"></a>
|
||||
|
||||
### CsoundObj.listeners(eventName) ⇒ <code>Array.<function()></code>
|
||||
Returns a copy of the array of listeners for the event named eventName.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| eventName | [<code>PublicEvents</code>](#PublicEvents) |
|
||||
|
||||
<a name="CsoundObj.off"></a>
|
||||
|
||||
### CsoundObj.off(eventName, listener) ⇒ <code>external:EventEmitter</code>
|
||||
Alias for removeListener()
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| eventName | [<code>PublicEvents</code>](#PublicEvents) |
|
||||
| listener | <code>function</code> |
|
||||
|
||||
<a name="CsoundObj.on"></a>
|
||||
|
||||
### CsoundObj.on(eventName, listener) ⇒ <code>external:EventEmitter</code>
|
||||
Adds the listener function to the end of the listeners array for the event named eventName.
|
||||
No checks are made to see if the listener has already been added.
|
||||
Multiple calls passing the same combination of eventName and listener
|
||||
will result in the listener being added, and called, multiple times.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| eventName | [<code>PublicEvents</code>](#PublicEvents) |
|
||||
| listener | <code>function</code> |
|
||||
|
||||
<a name="CsoundObj.addListener"></a>
|
||||
|
||||
### CsoundObj.addListener(eventName, listener) ⇒ <code>external:EventEmitter</code>
|
||||
Alias for "on"
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| eventName | [<code>PublicEvents</code>](#PublicEvents) |
|
||||
| listener | <code>function</code> |
|
||||
|
||||
<a name="CsoundObj.once"></a>
|
||||
|
||||
### CsoundObj.once(eventName, listener) ⇒ <code>external:EventEmitter</code>
|
||||
Adds a one-time listener function for the event named eventName.
|
||||
The next time eventName is triggered, this listener is removed and then invoked.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| eventName | [<code>PublicEvents</code>](#PublicEvents) |
|
||||
| listener | <code>function</code> |
|
||||
|
||||
<a name="CsoundObj.removeAllListeners"></a>
|
||||
|
||||
### CsoundObj.removeAllListeners(eventName) ⇒ <code>external:EventEmitter</code>
|
||||
Removes all listeners, or those of the specified eventName.
|
||||
It is bad practice to remove listeners added elsewhere in the code,
|
||||
particularly when the EventEmitter instance was created by some other
|
||||
component or module.
|
||||
Returns a reference to the EventEmitter, so that calls can be chained.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| eventName | [<code>PublicEvents</code>](#PublicEvents) |
|
||||
|
||||
<a name="CsoundObj.removeListener"></a>
|
||||
|
||||
### CsoundObj.removeListener(eventName, listener) ⇒ <code>external:EventEmitter</code>
|
||||
Removes the specified listener from the listener array for the event named eventName.
|
||||
removeListener() will remove, at most, one instance of a listener from the listener array.
|
||||
If any single listener has been added multiple times to the listener array for the specified eventName,
|
||||
then removeListener() must be called multiple times to remove each instance.
|
||||
Removes the specified listener from the listener array for the event named eventName.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| eventName | [<code>PublicEvents</code>](#PublicEvents) |
|
||||
| listener | <code>function</code> |
|
||||
|
||||
<a name="CsoundObj.getSr"></a>
|
||||
|
||||
### CsoundObj.getSr() ⇒ <code>Promise.<number></code>
|
||||
Returns the sample rate from Csound instance
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getKr"></a>
|
||||
|
||||
### CsoundObj.getKr() ⇒ <code>Promise.<number></code>
|
||||
Returns the control rate from Csound instance
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getKsmps"></a>
|
||||
|
||||
### CsoundObj.getKsmps() ⇒ <code>Promise.<number></code>
|
||||
Returns the ksmps value (kr/sr) from Csound instance
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getNchnls"></a>
|
||||
|
||||
### CsoundObj.getNchnls() ⇒ <code>Promise.<number></code>
|
||||
Returns the number of output channels from Csound instance
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getNchnlsInput"></a>
|
||||
|
||||
### CsoundObj.getNchnlsInput() ⇒ <code>Promise.<number></code>
|
||||
Returns the number of input channels from Csound instance
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.get0dBFS"></a>
|
||||
|
||||
### CsoundObj.get0dBFS() ⇒ <code>Promise.<number></code>
|
||||
Returns the value of csoundGet0dBFS
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getA4"></a>
|
||||
|
||||
### CsoundObj.getA4() ⇒ <code>Promise.<number></code>
|
||||
Returns the A4 frequency reference
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getCurrentTimeSamples"></a>
|
||||
|
||||
### CsoundObj.getCurrentTimeSamples() ⇒ <code>Promise.<number></code>
|
||||
Return the current performance time in samples
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getSizeOfMYFLT"></a>
|
||||
|
||||
### CsoundObj.getSizeOfMYFLT() ⇒ <code>Promise.<number></code>
|
||||
Return the size of MYFLT in number of bytes
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.setOption"></a>
|
||||
|
||||
### CsoundObj.setOption(option) ⇒ <code>Promise.<number></code>
|
||||
Set a single csound option (flag),
|
||||
no spaces are allowed in the string.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| option | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.setParams"></a>
|
||||
|
||||
### CsoundObj.setParams(csoundParams) ⇒ <code>Promise.<undefined></code>
|
||||
Configure Csound with a given set of
|
||||
parameters defined in the CSOUND_PARAMS structure.
|
||||
These parameters are the part of the OPARMS struct
|
||||
that are configurable through command line flags.
|
||||
The CSOUND_PARAMS structure can be obtained using
|
||||
csoundGetParams().
|
||||
These options should only be changed before
|
||||
performance has started.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| csoundParams | [<code>CSOUND\_PARAMS</code>](#CSOUND_PARAMS) | csoundParams object |
|
||||
|
||||
<a name="CsoundObj.getParams"></a>
|
||||
|
||||
### CsoundObj.getParams() ⇒ [<code>Promise.<CSOUND\_PARAMS></code>](#CSOUND_PARAMS)
|
||||
Get the current set of parameters
|
||||
from a Csound instance
|
||||
in a CSOUND_PARAMS structure.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
**Returns**: [<code>Promise.<CSOUND\_PARAMS></code>](#CSOUND_PARAMS) - - CSOUND_PARAMS object
|
||||
<a name="CsoundObj.getDebug"></a>
|
||||
|
||||
### CsoundObj.getDebug() ⇒ <code>Promise.<number></code>
|
||||
Returns whether Csound is set to print debug messages
|
||||
sent through the DebugMsg() internal API function.
|
||||
Anything different to 0 means true.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.setDebug"></a>
|
||||
|
||||
### CsoundObj.setDebug(debug) ⇒ <code>Promise.<undefined></code>
|
||||
Return the size of MYFLT in number of bytes
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| debug | <code>number</code> |
|
||||
|
||||
<a name="CsoundObj.inputMessage"></a>
|
||||
|
||||
### CsoundObj.inputMessage(scoreEvent) ⇒ <code>Promise.<number></code>
|
||||
Inputs an immediate score event
|
||||
without any pre-process parsing
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| scoreEvent | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.inputMessageAsync"></a>
|
||||
|
||||
### CsoundObj.inputMessageAsync(scoreEvent) ⇒ <code>Promise.<number></code>
|
||||
Inputs an immediate score event
|
||||
without any pre-process parsing
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| scoreEvent | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.getControlChannel"></a>
|
||||
|
||||
### CsoundObj.getControlChannel(channelName) ⇒ <code>Promise.<undefined></code>
|
||||
Retrieves the value of control channel identified by channelName.
|
||||
If the err argument is not NULL, the error (or success) code finding
|
||||
or accessing the channel is stored in it.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| channelName | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.setControlChannel"></a>
|
||||
|
||||
### CsoundObj.setControlChannel(channelName, value) ⇒ <code>Promise.<undefined></code>
|
||||
Sets the value of control channel identified by channelName
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| channelName | <code>string</code> |
|
||||
| value | <code>number</code> |
|
||||
|
||||
<a name="CsoundObj.getStringChannel"></a>
|
||||
|
||||
### CsoundObj.getStringChannel(channelName) ⇒ <code>Promise.<undefined></code>
|
||||
Retrieves the string channel identified by channelName
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| channelName | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.setStringChannel"></a>
|
||||
|
||||
### CsoundObj.setStringChannel(channelName, value) ⇒ <code>Promise.<undefined></code>
|
||||
Sets the string channel value identified by channelName
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| channelName | <code>string</code> |
|
||||
| value | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.getOutputName"></a>
|
||||
|
||||
### CsoundObj.getOutputName() ⇒ <code>Promise.<string></code>
|
||||
Returns the audio output name (-o)
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getInputName"></a>
|
||||
|
||||
### CsoundObj.getInputName() ⇒ <code>Promise.<string></code>
|
||||
Returns the audio input name (-i)
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.destroy"></a>
|
||||
|
||||
### CsoundObj.destroy() ⇒ <code>Promise.<undefined></code>
|
||||
Destroys an instance of Csound and frees memory
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getAPIVersion"></a>
|
||||
|
||||
### CsoundObj.getAPIVersion() ⇒ <code>Promise.<number></code>
|
||||
Returns the API version as int
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getVersion"></a>
|
||||
|
||||
### CsoundObj.getVersion() ⇒ <code>Promise.<number></code>
|
||||
Returns the Csound version as int
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.initialize"></a>
|
||||
|
||||
### CsoundObj.initialize() ⇒ <code>Promise.<number></code>
|
||||
Initialise Csound with specific flags.
|
||||
This function is called internally by csoundCreate(),
|
||||
so there is generally no need to use it explicitly
|
||||
unless you need to avoid default initilization that
|
||||
sets signal handlers and atexit() callbacks.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
**Returns**: <code>Promise.<number></code> - - Return value is zero on success,
|
||||
positive if initialisation was done already, and negative on error.
|
||||
<a name="CsoundObj.parseOrc"></a>
|
||||
|
||||
### CsoundObj.parseOrc(orc) ⇒ <code>Promise.<object></code>
|
||||
Parses a csound orchestra string
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| orc | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.compileTree"></a>
|
||||
|
||||
### CsoundObj.compileTree(tree) ⇒ <code>Promise.<number></code>
|
||||
Compiles AST tree
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tree | <code>object</code> |
|
||||
|
||||
<a name="CsoundObj.compileOrc"></a>
|
||||
|
||||
### CsoundObj.compileOrc(orc) ⇒ <code>Promise.<number></code>
|
||||
Compiles a csound orchestra string
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| orc | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.evalCode"></a>
|
||||
|
||||
### CsoundObj.evalCode(orc) ⇒ <code>Promise.<number></code>
|
||||
Compiles a csound orchestra string
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| orc | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.start"></a>
|
||||
|
||||
### CsoundObj.start() ⇒ <code>Promise.<number></code>
|
||||
Prepares Csound for performance
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.compileCsd"></a>
|
||||
|
||||
### CsoundObj.compileCsd(path) ⇒ <code>Promise.<number></code>
|
||||
Compiles a Csound input file but does not perform it.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| path | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.compileCsdText"></a>
|
||||
|
||||
### CsoundObj.compileCsdText(orc) ⇒ <code>Promise.<number></code>
|
||||
Compiles a CSD string but does not perform it.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| orc | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.perform"></a>
|
||||
|
||||
### CsoundObj.perform() ⇒ <code>Promise.<number></code>
|
||||
Performs(plays) audio until end is reached
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.performKsmps"></a>
|
||||
|
||||
### CsoundObj.performKsmps() ⇒ <code>Promise.<number></code>
|
||||
Performs(plays) 1 ksmps worth of sample(s)
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.performBuffer"></a>
|
||||
|
||||
### CsoundObj.performBuffer() ⇒ <code>Promise.<number></code>
|
||||
Performs(plays) 1 buffer worth of audio
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.stop"></a>
|
||||
|
||||
### CsoundObj.stop() ⇒ <code>Promise.<undefined></code>
|
||||
Stops a csoundPerform
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.cleanup"></a>
|
||||
|
||||
### CsoundObj.cleanup() ⇒ <code>Promise.<number></code>
|
||||
Prints information about the end of a performance,
|
||||
and closes audio and MIDI devices.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.reset"></a>
|
||||
|
||||
### CsoundObj.reset() ⇒ <code>Promise.<number></code>
|
||||
Prints information about the end of a performance,
|
||||
and closes audio and MIDI devices.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getInputBufferSize"></a>
|
||||
|
||||
### CsoundObj.getInputBufferSize() ⇒ <code>Promise.<number></code>
|
||||
Returns the number of samples in Csound's input buffer.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getOutputBufferSize"></a>
|
||||
|
||||
### CsoundObj.getOutputBufferSize() ⇒ <code>Promise.<number></code>
|
||||
Returns the number of samples in Csound's output buffer.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getInputBuffer"></a>
|
||||
|
||||
### CsoundObj.getInputBuffer() ⇒ <code>Promise.<number></code>
|
||||
Returns the address of the Csound audio input buffer.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getOutputBuffer"></a>
|
||||
|
||||
### CsoundObj.getOutputBuffer() ⇒ <code>Promise.<number></code>
|
||||
Returns the address of the Csound audio output buffer.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getSpin"></a>
|
||||
|
||||
### CsoundObj.getSpin() ⇒ <code>Promise.<number></code>
|
||||
Returns the address of the Csound audio input working buffer (spin).
|
||||
Enables external software to write audio into Csound before calling csoundPerformKsmps.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getSpout"></a>
|
||||
|
||||
### CsoundObj.getSpout() ⇒ <code>Promise.<number></code>
|
||||
Returns the address of the Csound audio output working buffer (spout).
|
||||
Enables external software to read audio from Csound after calling csoundPerformKsmps.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getMIDIDevList"></a>
|
||||
|
||||
### CsoundObj.getMIDIDevList(isOutput) ⇒ [<code>Promise.<CS\_MIDIDEVICE></code>](#CS_MIDIDEVICE)
|
||||
This function can be called to obtain a list of available input or output midi devices.
|
||||
If list is NULL, the function will only return the number of devices
|
||||
(isOutput=1 for out devices, 0 for in devices).
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| isOutput | <code>number</code> |
|
||||
|
||||
<a name="CsoundObj.getRtMidiName"></a>
|
||||
|
||||
### CsoundObj.getRtMidiName() ⇒ <code>Promise.<string></code>
|
||||
This function can be called to obtain a list of available input or output midi devices.
|
||||
If list is NULL, the function will only return the number of devices
|
||||
(isOutput=1 for out devices, 0 for in devices).
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.midiMessage"></a>
|
||||
|
||||
### CsoundObj.midiMessage(midi, midi, midi) ⇒ <code>Promise.<void></code>
|
||||
Emit a midi message with a given triplet of values
|
||||
in the range of 0 to 127.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| midi | <code>number</code> | status value |
|
||||
| midi | <code>number</code> | data1 |
|
||||
| midi | <code>number</code> | data2 |
|
||||
|
||||
<a name="CsoundObj.isScorePending"></a>
|
||||
|
||||
### CsoundObj.isScorePending() ⇒ <code>Promise.<number></code>
|
||||
Sees whether Csound score events are performed or not,
|
||||
independently of real-time MIDI events
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.setScorePending"></a>
|
||||
|
||||
### CsoundObj.setScorePending(pending) ⇒ <code>Promise.<undefined></code>
|
||||
Sets whether Csound score events are performed or not
|
||||
(real-time events will continue to be performed).
|
||||
Can be used by external software, such as a VST host,
|
||||
to turn off performance of score events (while continuing to perform real-time events),
|
||||
for example to mute a Csound score while working on other tracks of a piece,
|
||||
or to play the Csound instruments live.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| pending | <code>number</code> |
|
||||
|
||||
<a name="CsoundObj.readScore"></a>
|
||||
|
||||
### CsoundObj.readScore(score) ⇒ <code>Promise.<undefined></code>
|
||||
Read, preprocess, and load a score from an ASCII string It can be called repeatedly,
|
||||
with the new score events being added to the currently scheduled ones.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| score | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.getScoreTime"></a>
|
||||
|
||||
### CsoundObj.getScoreTime() ⇒ <code>Promise.<number></code>
|
||||
Returns the current score time in seconds since the beginning of performance.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.getScoreOffsetSeconds"></a>
|
||||
|
||||
### CsoundObj.getScoreOffsetSeconds() ⇒ <code>Promise.<number></code>
|
||||
Returns the score time beginning at which score events will actually immediately be performed
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.setScoreOffsetSeconds"></a>
|
||||
|
||||
### CsoundObj.setScoreOffsetSeconds(time) ⇒ <code>Promise.<number></code>
|
||||
Csound score events prior to the specified time are not performed,
|
||||
and performance begins immediately at the specified time
|
||||
(real-time events will continue to be performed as they are received).
|
||||
Can be used by external software, such as a VST host, to begin
|
||||
score performance midway through a Csound score,
|
||||
for example to repeat a loop in a sequencer,
|
||||
or to synchronize other events with the Csound score.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| time | <code>number</code> |
|
||||
|
||||
<a name="CsoundObj.rewindScore"></a>
|
||||
|
||||
### CsoundObj.rewindScore() ⇒ <code>Promise.<number></code>
|
||||
Rewinds a compiled Csound score to the time specified with csoundObj.setScoreOffsetSeconds().
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
<a name="CsoundObj.tableLength"></a>
|
||||
|
||||
### CsoundObj.tableLength(tableNum) ⇒ <code>Promise.<number></code>
|
||||
Returns the length of a function table
|
||||
(not including the guard point),
|
||||
or -1 if the table does not exist.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tableNum | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.tableGet"></a>
|
||||
|
||||
### CsoundObj.tableGet(tableNum, tableIndex) ⇒ <code>Promise.<number></code>
|
||||
Returns the value of a slot in a function table.
|
||||
The table number and index are assumed to be valid.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tableNum | <code>string</code> |
|
||||
| tableIndex | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.tableSet"></a>
|
||||
|
||||
### CsoundObj.tableSet(tableNum, tableIndex, value) ⇒ <code>Promise.<undefined></code>
|
||||
Sets the value of a slot in a function table.
|
||||
The table number and index are assumed to be valid.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tableNum | <code>string</code> |
|
||||
| tableIndex | <code>string</code> |
|
||||
| value | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.tableCopyIn"></a>
|
||||
|
||||
### CsoundObj.tableCopyIn(tableNum, tableIndex, array) ⇒ <code>Promise.<undefined></code>
|
||||
Copy the contents of an Array or TypedArray from javascript into a given csound function table.
|
||||
The table number is assumed to be valid, and the table needs to have sufficient space
|
||||
to receive all the array contents.
|
||||
The table number and index are assumed to be valid.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tableNum | <code>string</code> |
|
||||
| tableIndex | <code>string</code> |
|
||||
| array | <code>Array.<number></code> \| <code>ArrayLike.<number></code> |
|
||||
|
||||
<a name="CsoundObj.tableCopyOut"></a>
|
||||
|
||||
### CsoundObj.tableCopyOut(tableNum) ⇒ <code>Promise.<(Float64Array\|undefined)></code>
|
||||
Copies the contents of a function table from csound into Float64Array.
|
||||
The function returns a Float64Array if the table exists, otherwise
|
||||
it returns undefined.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tableNum | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.getTableArgs"></a>
|
||||
|
||||
### CsoundObj.getTableArgs(tableNum) ⇒ <code>Promise.<(Float64Array\|undefined)></code>
|
||||
Copies the contents of a function table from csound into Float64Array.
|
||||
The function returns a Float64Array if the table exists, otherwise
|
||||
it returns undefined.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tableNum | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.isNamedGEN"></a>
|
||||
|
||||
### CsoundObj.isNamedGEN(tableNum) ⇒ <code>Promise.<number></code>
|
||||
Checks if a given GEN number num is a named GEN if so,
|
||||
it returns the string length (excluding terminating NULL char).
|
||||
Otherwise it returns 0.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tableNum | <code>string</code> |
|
||||
|
||||
<a name="CsoundObj.getNamedGEN"></a>
|
||||
|
||||
### CsoundObj.getNamedGEN(tableNum) ⇒ <code>Promise.<(string\|undefined)></code>
|
||||
Gets the GEN name from a number num, if this is a named GEN.
|
||||
If the table number doesn't represent a named GEN, it will
|
||||
return undefined.
|
||||
|
||||
**Kind**: static method of [<code>CsoundObj</code>](#CsoundObj)
|
||||
|
||||
| Param | Type |
|
||||
| --- | --- |
|
||||
| tableNum | <code>string</code> |
|
||||
|
||||
<a name="PublicEvents"></a>
|
||||
|
||||
## PublicEvents : <code>enum</code>
|
||||
**Kind**: global enum
|
||||
**Read only**: true
|
||||
**Properties**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| "play" | <code>string</code> | called anytime performance goes from pause/stop to a running state. |
|
||||
| "pause" | <code>string</code> | called after any successful csound.pause() calls. |
|
||||
| "stop" | <code>string</code> | called after end of performance or after a successful csound.stop(). |
|
||||
| "realtimePerformanceStarted" | <code>string</code> | called at the start of realtime performance but not on resume or render. |
|
||||
| "realtimePerformancePaused" | <code>string</code> | only called if csound.pause() was successfully called during performance. |
|
||||
| "realtimePerformanceResumed" | <code>string</code> | only called if csound.resume() was successfully called after a pause. |
|
||||
| "realtimePerformanceEnded" | <code>string</code> | called after end of performance or after a successful csound.stop(). |
|
||||
| "renderStarted" | <code>string</code> | called at the start of offline/non-realtime render to disk. |
|
||||
| "renderEnded" | <code>string</code> | called at the end of offline/non-realtime render to disk. |
|
||||
| "onAudioNodeCreated" | <code>string</code> | called when an audioNode is created from the AudioContext before realtime performance. the event callback will include the audioNode itself, which is needed if autoConnect is set to false. |
|
||||
| "message" | <code>string</code> | the main entrypoint to csound's messaging (-m) system, a default event listener will print the message to the browser console, this default listener can be removed by the user. |
|
||||
|
||||
<a name="Csound"></a>
|
||||
|
||||
## Csound([params]) ⇒ <code>Promise.<(CsoundObj\|undefined)></code>
|
||||
The default entry for @csound/wasm/browser module.
|
||||
If loaded successfully, it returns CsoundObj,
|
||||
otherwise undefined.
|
||||
|
||||
**Kind**: global function
|
||||
|
||||
| Param | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [params] | <code>Object</code> | | Initialization parameters |
|
||||
| [params.audioContext] | <code>AudioContext</code> | | Optional AudioContext to use; if none given, an AudioContext will be created. |
|
||||
| [params.inputChannelCount] | <code>Number</code> | | Optional input channel count for AudioNode used with WebAudio graph. Defaults to the value of nchnls_i in useWorker but 2 otherwise. |
|
||||
| [params.outputChannelCount] | <code>Number</code> | | Optional output channel count AudioNode used with WebAudio graph. Defaults to the value of nchnls in useWorker but 2 otherwise. |
|
||||
| [params.autoConnect] | <code>Boolean</code> | <code>true</code> | Set to configure Csound to automatically connect to the audioContext.destination output. |
|
||||
| [params.withPlugins] | <code>Array.<Object></code> | | Array of WebAssembly Csound plugin libraries to use with Csound. |
|
||||
| [params.useWorker] | <code>Boolean</code> | <code>false</code> | Configure to use backend using Web Workers to run Csound in a thread separate from audio callback. |
|
||||
| [params.useSAB] | <code>Boolean</code> | <code>true</code> | Configure to use SharedArrayBuffers for WebWorker communications if platform supports it. |
|
||||
| [params.useSPN] | <code>Boolean</code> | <code>false</code> | Configure to use explicitly request ScriptProcessorNode rather than AudioWorklet. Recommended only for debug testing purposes. |
|
||||
|
||||
<a name="CSOUND_PARAMS"></a>
|
||||
|
||||
## CSOUND\_PARAMS
|
||||
**Kind**: global typedef
|
||||
**Properties**
|
||||
|
||||
| Name | Type |
|
||||
| --- | --- |
|
||||
| debug_mode | <code>number</code> |
|
||||
| buffer_frames | <code>number</code> |
|
||||
| hardware_buffer_frames | <code>number</code> |
|
||||
| displays | <code>number</code> |
|
||||
| ascii_graphs | <code>number</code> |
|
||||
| postscript_graphs | <code>number</code> |
|
||||
| message_level | <code>number</code> |
|
||||
| tempo | <code>number</code> |
|
||||
| ring_bell | <code>number</code> |
|
||||
| use_cscore | <code>number</code> |
|
||||
| terminate_on_midi | <code>number</code> |
|
||||
| heartbeat | <code>number</code> |
|
||||
| defer_gen01_load | <code>number</code> |
|
||||
| midi_key | <code>number</code> |
|
||||
| midi_key_cps | <code>number</code> |
|
||||
| midi_key_oct | <code>number</code> |
|
||||
| midi_key_pch | <code>number</code> |
|
||||
| midi_velocity | <code>number</code> |
|
||||
|
||||
<a name="CS_MIDIDEVICE"></a>
|
||||
|
||||
## CS\_MIDIDEVICE
|
||||
**Kind**: global typedef
|
||||
**Properties**
|
||||
|
||||
| Name | Type |
|
||||
| --- | --- |
|
||||
| device_name | <code>string</code> |
|
||||
| interface_name | <code>string</code> |
|
||||
| device_id | <code>string</code> |
|
||||
| midi_module | <code>string</code> |
|
||||
| isOutput | <code>number</code> |
|
||||
|
||||
|
||||
|
||||
217
src/App.svelte
217
src/App.svelte
@ -1,9 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import TopBar from './lib/TopBar.svelte';
|
||||
import EditorWithLogs from './lib/EditorWithLogs.svelte';
|
||||
import EditorSettings from './lib/EditorSettings.svelte';
|
||||
import FileBrowser from './lib/FileBrowser.svelte';
|
||||
import SidePanel from './lib/SidePanel.svelte';
|
||||
import Popup from './lib/Popup.svelte';
|
||||
import { csound, csoundLogs, type LogEntry } from './lib/csound';
|
||||
import { projectManager, type CsoundProject } from './lib/project-system';
|
||||
import ConfirmDialog from './lib/ConfirmDialog.svelte';
|
||||
import InputDialog from './lib/InputDialog.svelte';
|
||||
import {
|
||||
PanelLeftClose,
|
||||
PanelLeftOpen,
|
||||
@ -11,17 +17,54 @@
|
||||
PanelRightOpen,
|
||||
PanelBottomClose,
|
||||
PanelBottomOpen,
|
||||
LayoutGrid
|
||||
LayoutGrid,
|
||||
Save
|
||||
} from 'lucide-svelte';
|
||||
|
||||
let sidePanelVisible = $state(true);
|
||||
let sidePanelPosition = $state<'left' | 'right' | 'bottom'>('right');
|
||||
let popupVisible = $state(false);
|
||||
let editorValue = $state('// Start coding here...\n');
|
||||
let interpreterLogs = $state<string[]>([]);
|
||||
let editorValue = $state('<CsoundSynthesizer>\n<CsOptions>\n-odac\n</CsOptions>\n<CsInstruments>\n\nsr = 44100\nksmps = 32\nnchnls = 2\n0dbfs = 1\n\ninstr 1\n aOut oscili 0.5, 440\n outs aOut, aOut\nendin\n\n</CsInstruments>\n<CsScore>\ni 1 0 2\n</CsScore>\n</CsoundSynthesizer>\n');
|
||||
let interpreterLogs = $state<LogEntry[]>([]);
|
||||
|
||||
let sidePanelRef: SidePanel;
|
||||
let editorRef: EditorWithLogs;
|
||||
let fileBrowserRef: FileBrowser;
|
||||
let currentProjectId = $state<string | null>(null);
|
||||
let hasUnsavedChanges = $state(false);
|
||||
let isNewUnsavedBuffer = $state(false);
|
||||
let pendingProject: CsoundProject | null = null;
|
||||
let showUnsavedDialog = $state(false);
|
||||
let showSaveAsDialog = $state(false);
|
||||
|
||||
const TEMPLATE_CONTENT = '<CsoundSynthesizer>\n<CsOptions>\n-odac\n</CsOptions>\n<CsInstruments>\n\nsr = 44100\nksmps = 32\nnchnls = 2\n0dbfs = 1\n\ninstr 1\n aOut oscili 0.5, 440\n outs aOut, aOut\nendin\n\n</CsInstruments>\n<CsScore>\ni 1 0 2\n</CsScore>\n</CsoundSynthesizer>\n';
|
||||
|
||||
onMount(async () => {
|
||||
await csound.init();
|
||||
await projectManager.init();
|
||||
|
||||
const result = await projectManager.getAllProjects();
|
||||
if (result.success && result.data.length === 0) {
|
||||
await projectManager.createProject({
|
||||
title: 'Template',
|
||||
author: 'System',
|
||||
content: TEMPLATE_CONTENT,
|
||||
tags: []
|
||||
});
|
||||
}
|
||||
|
||||
const unsubscribe = csoundLogs.subscribe(logs => {
|
||||
interpreterLogs = logs;
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
});
|
||||
|
||||
onDestroy(async () => {
|
||||
await csound.destroy();
|
||||
});
|
||||
|
||||
function toggleSidePanel() {
|
||||
sidePanelVisible = !sidePanelVisible;
|
||||
@ -33,6 +76,121 @@
|
||||
|
||||
function handleEditorChange(value: string) {
|
||||
editorValue = value;
|
||||
hasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
function handleNewFile() {
|
||||
if (hasUnsavedChanges) {
|
||||
pendingProject = null;
|
||||
showUnsavedDialog = true;
|
||||
return;
|
||||
}
|
||||
|
||||
createNewBuffer();
|
||||
}
|
||||
|
||||
function createNewBuffer() {
|
||||
currentProjectId = null;
|
||||
editorValue = TEMPLATE_CONTENT;
|
||||
hasUnsavedChanges = false;
|
||||
isNewUnsavedBuffer = true;
|
||||
if (editorRef) {
|
||||
editorRef.setValue(TEMPLATE_CONTENT);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleFileSelect(project: CsoundProject | null) {
|
||||
if (hasUnsavedChanges) {
|
||||
pendingProject = project;
|
||||
showUnsavedDialog = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (project) {
|
||||
loadProject(project);
|
||||
}
|
||||
}
|
||||
|
||||
function loadProject(project: CsoundProject) {
|
||||
currentProjectId = project.id;
|
||||
editorValue = project.content;
|
||||
hasUnsavedChanges = false;
|
||||
isNewUnsavedBuffer = false;
|
||||
if (editorRef) {
|
||||
editorRef.setValue(project.content);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveCurrentProject() {
|
||||
if (isNewUnsavedBuffer) {
|
||||
showSaveAsDialog = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currentProjectId) return;
|
||||
|
||||
const result = await projectManager.updateProject({
|
||||
id: currentProjectId,
|
||||
content: editorValue
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
hasUnsavedChanges = false;
|
||||
if (fileBrowserRef) {
|
||||
fileBrowserRef.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSaveAs(title: string) {
|
||||
const finalTitle = title.trim() || 'Untitled';
|
||||
|
||||
const result = await projectManager.createProject({
|
||||
title: finalTitle,
|
||||
author: 'Anonymous',
|
||||
content: editorValue,
|
||||
tags: []
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
currentProjectId = result.data.id;
|
||||
hasUnsavedChanges = false;
|
||||
isNewUnsavedBuffer = false;
|
||||
if (fileBrowserRef) {
|
||||
fileBrowserRef.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleMetadataUpdate(projectId: string, updates: { title?: string; author?: string }) {
|
||||
const result = await projectManager.updateProject({
|
||||
id: projectId,
|
||||
...updates
|
||||
});
|
||||
|
||||
if (result.success && fileBrowserRef) {
|
||||
fileBrowserRef.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
function handleSaveAndSwitch() {
|
||||
saveCurrentProject().then(() => {
|
||||
if (pendingProject) {
|
||||
loadProject(pendingProject);
|
||||
} else {
|
||||
createNewBuffer();
|
||||
}
|
||||
pendingProject = null;
|
||||
});
|
||||
}
|
||||
|
||||
function handleDiscardAndSwitch() {
|
||||
if (pendingProject) {
|
||||
loadProject(pendingProject);
|
||||
} else {
|
||||
createNewBuffer();
|
||||
}
|
||||
pendingProject = null;
|
||||
}
|
||||
|
||||
function cyclePanelPosition() {
|
||||
@ -64,18 +222,26 @@
|
||||
{/snippet}
|
||||
|
||||
{#snippet filesTabContent()}
|
||||
<h3>File Browser</h3>
|
||||
<p>Your project files will be listed here.</p>
|
||||
<ul>
|
||||
<li>src/</li>
|
||||
<li>├── App.svelte</li>
|
||||
<li>├── main.ts</li>
|
||||
<li>└── lib/</li>
|
||||
</ul>
|
||||
<FileBrowser
|
||||
bind:this={fileBrowserRef}
|
||||
onFileSelect={handleFileSelect}
|
||||
onNewFile={handleNewFile}
|
||||
onMetadataUpdate={handleMetadataUpdate}
|
||||
selectedProjectId={currentProjectId}
|
||||
/>
|
||||
{/snippet}
|
||||
|
||||
<div class="app-container">
|
||||
<TopBar title="oldboy">
|
||||
<button
|
||||
class="icon-button"
|
||||
onclick={saveCurrentProject}
|
||||
disabled={!hasUnsavedChanges}
|
||||
title="Save {hasUnsavedChanges ? '(unsaved changes)' : ''}"
|
||||
class:has-changes={hasUnsavedChanges}
|
||||
>
|
||||
<Save size={18} />
|
||||
</button>
|
||||
<button onclick={toggleSidePanel} class="icon-button">
|
||||
{#if sidePanelVisible}
|
||||
{#if sidePanelPosition === 'left'}
|
||||
@ -154,6 +320,24 @@
|
||||
<p>You can drag it around by the header.</p>
|
||||
<p>It stays on top of everything else.</p>
|
||||
</Popup>
|
||||
|
||||
<ConfirmDialog
|
||||
bind:visible={showUnsavedDialog}
|
||||
title="Unsaved Changes"
|
||||
message="You have unsaved changes. What would you like to do?"
|
||||
confirmLabel="Save"
|
||||
cancelLabel="Discard"
|
||||
onConfirm={handleSaveAndSwitch}
|
||||
onCancel={handleDiscardAndSwitch}
|
||||
/>
|
||||
|
||||
<InputDialog
|
||||
bind:visible={showSaveAsDialog}
|
||||
title="Save As"
|
||||
label="File name"
|
||||
placeholder="Untitled"
|
||||
onConfirm={handleSaveAs}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@ -192,11 +376,20 @@
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.icon-button:hover {
|
||||
.icon-button:hover:not(:disabled) {
|
||||
background-color: #444;
|
||||
border-color: #646cff;
|
||||
}
|
||||
|
||||
.icon-button:disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.icon-button.has-changes {
|
||||
color: #646cff;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
|
||||
89
src/lib/ConfirmDialog.svelte
Normal file
89
src/lib/ConfirmDialog.svelte
Normal file
@ -0,0 +1,89 @@
|
||||
<script lang="ts">
|
||||
import Modal from './Modal.svelte';
|
||||
|
||||
interface Props {
|
||||
visible?: boolean;
|
||||
title?: string;
|
||||
message: string;
|
||||
confirmLabel?: string;
|
||||
cancelLabel?: string;
|
||||
onConfirm: () => void;
|
||||
onCancel?: () => void;
|
||||
}
|
||||
|
||||
let {
|
||||
visible = $bindable(false),
|
||||
title = 'Confirm',
|
||||
message,
|
||||
confirmLabel = 'Confirm',
|
||||
cancelLabel = 'Cancel',
|
||||
onConfirm,
|
||||
onCancel
|
||||
}: Props = $props();
|
||||
|
||||
function handleConfirm() {
|
||||
visible = false;
|
||||
onConfirm();
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
visible = false;
|
||||
onCancel?.();
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal bind:visible {title}>
|
||||
<div class="confirm-dialog">
|
||||
<p>{message}</p>
|
||||
<div class="button-group">
|
||||
<button class="button button-secondary" onclick={handleCancel}>
|
||||
{cancelLabel}
|
||||
</button>
|
||||
<button class="button button-primary" onclick={handleConfirm}>
|
||||
{confirmLabel}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.confirm-dialog p {
|
||||
margin: 0 0 1.5rem 0;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.button {
|
||||
padding: 0.5rem 1rem;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.button-primary {
|
||||
background-color: #646cff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.button-primary:hover {
|
||||
background-color: #535bf2;
|
||||
}
|
||||
|
||||
.button-secondary {
|
||||
background-color: transparent;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
border: 1px solid #3a3a3a;
|
||||
}
|
||||
|
||||
.button-secondary:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
}
|
||||
</style>
|
||||
@ -14,6 +14,7 @@
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { vim } from '@replit/codemirror-vim';
|
||||
import { editorSettings } from './stores/editorSettings';
|
||||
import { csound } from './csound';
|
||||
|
||||
interface Props {
|
||||
initialValue?: string;
|
||||
@ -40,6 +41,19 @@
|
||||
const lineWrappingCompartment = new Compartment();
|
||||
const vimCompartment = new Compartment();
|
||||
|
||||
const evaluateKeymap = keymap.of([
|
||||
{
|
||||
key: 'Mod-e',
|
||||
run: (view) => {
|
||||
const code = view.state.doc.toString();
|
||||
csound.evaluate(code).catch(err => {
|
||||
console.error('Evaluation error:', err);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
onMount(() => {
|
||||
const settings = $editorSettings;
|
||||
|
||||
@ -75,6 +89,7 @@
|
||||
...baseExtensions,
|
||||
languageExtensions[language],
|
||||
oneDark,
|
||||
evaluateKeymap,
|
||||
lineNumbersCompartment.of(settings.showLineNumbers ? lineNumbers() : []),
|
||||
lineWrappingCompartment.of(settings.enableLineWrapping ? EditorView.lineWrapping : []),
|
||||
vimCompartment.of(settings.vimMode ? vim() : []),
|
||||
|
||||
@ -67,14 +67,6 @@
|
||||
export function setValue(value: string): void {
|
||||
editorRef?.setValue(value);
|
||||
}
|
||||
|
||||
export function addLog(message: string): void {
|
||||
logPanelRef?.addLog(message);
|
||||
}
|
||||
|
||||
export function clearLogs(): void {
|
||||
logPanelRef?.clearLogs();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="editor-with-logs">
|
||||
|
||||
347
src/lib/FileBrowser.svelte
Normal file
347
src/lib/FileBrowser.svelte
Normal file
@ -0,0 +1,347 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { File, Plus, Trash2 } from 'lucide-svelte';
|
||||
import { projectManager, type CsoundProject } from './project-system';
|
||||
import ConfirmDialog from './ConfirmDialog.svelte';
|
||||
import InputDialog from './InputDialog.svelte';
|
||||
|
||||
interface Props {
|
||||
onFileSelect?: (project: CsoundProject | null) => void;
|
||||
onNewFile?: () => void;
|
||||
onMetadataUpdate?: (projectId: string, updates: { title?: string; author?: string }) => void;
|
||||
selectedProjectId?: string | null;
|
||||
}
|
||||
|
||||
let { onFileSelect, onNewFile, onMetadataUpdate, selectedProjectId = null }: Props = $props();
|
||||
|
||||
let projects = $state<CsoundProject[]>([]);
|
||||
let loading = $state(true);
|
||||
let showDeleteConfirm = $state(false);
|
||||
let projectToDelete = $state<CsoundProject | null>(null);
|
||||
|
||||
let selectedProject = $derived(
|
||||
projects.find(p => p.id === selectedProjectId) || null
|
||||
);
|
||||
|
||||
let editTitle = $state('');
|
||||
let editAuthor = $state('');
|
||||
|
||||
$effect(() => {
|
||||
if (selectedProject) {
|
||||
editTitle = selectedProject.title;
|
||||
editAuthor = selectedProject.author;
|
||||
}
|
||||
});
|
||||
|
||||
export async function refresh() {
|
||||
await loadProjects();
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
await loadProjects();
|
||||
});
|
||||
|
||||
async function loadProjects() {
|
||||
loading = true;
|
||||
try {
|
||||
await projectManager.init();
|
||||
const result = await projectManager.getAllProjects();
|
||||
if (result.success) {
|
||||
projects = result.data.sort((a, b) =>
|
||||
new Date(b.dateModified).getTime() - new Date(a.dateModified).getTime()
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load projects:', error);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleNewFile() {
|
||||
onNewFile?.();
|
||||
}
|
||||
|
||||
function selectProject(project: CsoundProject) {
|
||||
onFileSelect?.(project);
|
||||
}
|
||||
|
||||
function handleDeleteClick(project: CsoundProject, event: Event) {
|
||||
event.stopPropagation();
|
||||
projectToDelete = project;
|
||||
showDeleteConfirm = true;
|
||||
}
|
||||
|
||||
async function confirmDelete() {
|
||||
if (!projectToDelete) return;
|
||||
|
||||
const result = await projectManager.deleteProject(projectToDelete.id);
|
||||
if (result.success) {
|
||||
await loadProjects();
|
||||
}
|
||||
projectToDelete = null;
|
||||
}
|
||||
|
||||
function formatDate(dateString: string): string {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric'
|
||||
});
|
||||
}
|
||||
|
||||
function handleMetadataChange() {
|
||||
if (!selectedProject) return;
|
||||
|
||||
const hasChanges =
|
||||
editTitle !== selectedProject.title ||
|
||||
editAuthor !== selectedProject.author;
|
||||
|
||||
if (hasChanges) {
|
||||
onMetadataUpdate?.(selectedProject.id, {
|
||||
title: editTitle,
|
||||
author: editAuthor
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="file-browser">
|
||||
<div class="browser-header">
|
||||
<span class="browser-title">Files</span>
|
||||
<button class="action-button" onclick={handleNewFile} title="New file">
|
||||
<Plus size={16} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="browser-content">
|
||||
{#if loading}
|
||||
<div class="empty-state">Loading...</div>
|
||||
{:else}
|
||||
<div class="project-list">
|
||||
{#each projects as project}
|
||||
<div
|
||||
class="project-item"
|
||||
class:selected={selectedProjectId === project.id}
|
||||
onclick={() => selectProject(project)}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div class="project-icon">
|
||||
<File size={16} />
|
||||
</div>
|
||||
<div class="project-info">
|
||||
<div class="project-title">{project.title}</div>
|
||||
</div>
|
||||
<button
|
||||
class="delete-button"
|
||||
onclick={(e) => handleDeleteClick(project, e)}
|
||||
title="Delete"
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if selectedProject}
|
||||
<div class="metadata-editor">
|
||||
<div class="metadata-header">Metadata</div>
|
||||
<div class="metadata-fields">
|
||||
<div class="field">
|
||||
<label for="file-title">Name</label>
|
||||
<input
|
||||
id="file-title"
|
||||
type="text"
|
||||
bind:value={editTitle}
|
||||
onchange={handleMetadataChange}
|
||||
/>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="file-author">Author</label>
|
||||
<input
|
||||
id="file-author"
|
||||
type="text"
|
||||
bind:value={editAuthor}
|
||||
onchange={handleMetadataChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<ConfirmDialog
|
||||
bind:visible={showDeleteConfirm}
|
||||
title="Delete File"
|
||||
message="Are you sure you want to delete '{projectToDelete?.title}'?"
|
||||
confirmLabel="Delete"
|
||||
onConfirm={confirmDelete}
|
||||
/>
|
||||
|
||||
<style>
|
||||
.file-browser {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background-color: #1a1a1a;
|
||||
}
|
||||
|
||||
.browser-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.75rem;
|
||||
background-color: #2a2a2a;
|
||||
border-bottom: 1px solid #3a3a3a;
|
||||
}
|
||||
|
||||
.browser-title {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
padding: 0.25rem;
|
||||
background-color: transparent;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.action-button:hover {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.browser-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
padding: 2rem 1rem;
|
||||
text-align: center;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.project-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.project-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem;
|
||||
border-bottom: 1px solid #2a2a2a;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.project-item:hover {
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
.project-item.selected {
|
||||
background-color: rgba(100, 108, 255, 0.2);
|
||||
border-left: 3px solid #646cff;
|
||||
}
|
||||
|
||||
.project-icon {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.project-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.project-title {
|
||||
font-size: 0.875rem;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.delete-button {
|
||||
padding: 0.25rem;
|
||||
background-color: transparent;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.project-item:hover .delete-button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.delete-button:hover {
|
||||
color: rgba(255, 100, 100, 0.9);
|
||||
background-color: rgba(255, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.metadata-editor {
|
||||
border-top: 1px solid #2a2a2a;
|
||||
background-color: #1a1a1a;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.metadata-header {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.metadata-fields {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.field label {
|
||||
font-size: 0.75rem;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.field input {
|
||||
padding: 0.5rem;
|
||||
background-color: #2a2a2a;
|
||||
border: 1px solid #3a3a3a;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
font-size: 0.875rem;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.field input:focus {
|
||||
border-color: #646cff;
|
||||
}
|
||||
</style>
|
||||
121
src/lib/InputDialog.svelte
Normal file
121
src/lib/InputDialog.svelte
Normal file
@ -0,0 +1,121 @@
|
||||
<script lang="ts">
|
||||
import Modal from './Modal.svelte';
|
||||
|
||||
interface Props {
|
||||
visible?: boolean;
|
||||
title?: string;
|
||||
label: string;
|
||||
placeholder?: string;
|
||||
defaultValue?: string;
|
||||
confirmLabel?: string;
|
||||
cancelLabel?: string;
|
||||
onConfirm: (value: string) => void;
|
||||
onCancel?: () => void;
|
||||
}
|
||||
|
||||
let {
|
||||
visible = $bindable(false),
|
||||
title = 'Input',
|
||||
label,
|
||||
placeholder = '',
|
||||
defaultValue = '',
|
||||
confirmLabel = 'OK',
|
||||
cancelLabel = 'Cancel',
|
||||
onConfirm,
|
||||
onCancel
|
||||
}: Props = $props();
|
||||
|
||||
let value = $state(defaultValue);
|
||||
|
||||
function handleConfirm() {
|
||||
visible = false;
|
||||
onConfirm(value);
|
||||
value = '';
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
visible = false;
|
||||
onCancel?.();
|
||||
value = '';
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal bind:visible {title}>
|
||||
<div class="input-dialog">
|
||||
<label for="input-field">{label}</label>
|
||||
<input
|
||||
id="input-field"
|
||||
type="text"
|
||||
bind:value
|
||||
{placeholder}
|
||||
/>
|
||||
<div class="button-group">
|
||||
<button class="button button-secondary" onclick={handleCancel}>
|
||||
{cancelLabel}
|
||||
</button>
|
||||
<button class="button button-primary" onclick={handleConfirm}>
|
||||
{confirmLabel}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.input-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
label {
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 0.5rem;
|
||||
background-color: #1a1a1a;
|
||||
border: 1px solid #3a3a3a;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
font-size: 0.875rem;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
border-color: #646cff;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.button {
|
||||
padding: 0.5rem 1rem;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.button-primary {
|
||||
background-color: #646cff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.button-primary:hover {
|
||||
background-color: #535bf2;
|
||||
}
|
||||
|
||||
.button-secondary {
|
||||
background-color: transparent;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
border: 1px solid #3a3a3a;
|
||||
}
|
||||
|
||||
.button-secondary:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
}
|
||||
</style>
|
||||
@ -1,28 +1,73 @@
|
||||
<script lang="ts">
|
||||
import { Copy, Trash2 } from 'lucide-svelte';
|
||||
import { csound } from './csound';
|
||||
import type { LogEntry } from './csound';
|
||||
|
||||
interface Props {
|
||||
logs?: string[];
|
||||
logs?: LogEntry[];
|
||||
}
|
||||
|
||||
let { logs = [] }: Props = $props();
|
||||
|
||||
export function addLog(message: string) {
|
||||
logs.push(message);
|
||||
function formatTime(date: Date): string {
|
||||
return date.toLocaleTimeString('en-US', {
|
||||
hour12: false,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
fractionalSecondDigits: 3
|
||||
});
|
||||
}
|
||||
|
||||
export function clearLogs() {
|
||||
logs = [];
|
||||
async function copyLogs() {
|
||||
if (logs.length === 0) return;
|
||||
|
||||
const logText = logs
|
||||
.map(log => `[${formatTime(log.timestamp)}] ${log.type.toUpperCase()}: ${log.message}`)
|
||||
.join('\n');
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(logText);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy logs:', err);
|
||||
}
|
||||
}
|
||||
|
||||
function clearLogs() {
|
||||
csound.clearLogs();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="log-panel">
|
||||
<div class="log-header">
|
||||
<span class="log-title">Output</span>
|
||||
<div class="log-actions">
|
||||
<button
|
||||
class="action-button"
|
||||
onclick={copyLogs}
|
||||
disabled={logs.length === 0}
|
||||
title="Copy logs"
|
||||
>
|
||||
<Copy size={14} />
|
||||
</button>
|
||||
<button
|
||||
class="action-button"
|
||||
onclick={clearLogs}
|
||||
disabled={logs.length === 0}
|
||||
title="Clear logs"
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="log-content">
|
||||
{#if logs.length === 0}
|
||||
<div class="empty-state">No output yet...</div>
|
||||
{:else}
|
||||
{#each logs as log, i}
|
||||
<div class="log-entry">
|
||||
<span class="log-index">{i + 1}</span>
|
||||
<span class="log-message">{log}</span>
|
||||
<div class="log-entry" class:error={log.type === 'error'}>
|
||||
<span class="log-timestamp">{formatTime(log.timestamp)}</span>
|
||||
<span class="log-message">{log.message}</span>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
@ -37,6 +82,50 @@
|
||||
background-color: #1a1a1a;
|
||||
}
|
||||
|
||||
.log-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.5rem 0.75rem;
|
||||
background-color: #2a2a2a;
|
||||
border-bottom: 1px solid #3a3a3a;
|
||||
}
|
||||
|
||||
.log-title {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.log-actions {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
padding: 0.25rem;
|
||||
background-color: transparent;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.action-button:hover:not(:disabled) {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.action-button:disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.log-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
@ -63,10 +152,19 @@
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
.log-index {
|
||||
.log-entry.error {
|
||||
background-color: rgba(255, 0, 0, 0.1);
|
||||
border-left: 3px solid rgba(255, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.log-entry.error .log-message {
|
||||
color: rgba(255, 100, 100, 0.95);
|
||||
}
|
||||
|
||||
.log-timestamp {
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
min-width: 2rem;
|
||||
text-align: right;
|
||||
min-width: 6rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.log-message {
|
||||
|
||||
78
src/lib/Modal.svelte
Normal file
78
src/lib/Modal.svelte
Normal file
@ -0,0 +1,78 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
visible?: boolean;
|
||||
title?: string;
|
||||
onClose?: () => void;
|
||||
children: Snippet;
|
||||
}
|
||||
|
||||
let { visible = $bindable(false), title = '', onClose, children }: Props = $props();
|
||||
|
||||
function handleBackdropClick(e: MouseEvent) {
|
||||
if (e.target === e.currentTarget) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
function close() {
|
||||
visible = false;
|
||||
onClose?.();
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if visible}
|
||||
<div class="modal-backdrop" onclick={handleBackdropClick} role="dialog" tabindex="-1">
|
||||
<div class="modal-content">
|
||||
{#if title}
|
||||
<div class="modal-header">
|
||||
<h3>{title}</h3>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="modal-body">
|
||||
{@render children()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.modal-backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #2a2a2a;
|
||||
border: 1px solid #3a3a3a;
|
||||
min-width: 300px;
|
||||
max-width: 500px;
|
||||
max-height: 80vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid #3a3a3a;
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin: 0;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
125
src/lib/csound/engine.ts
Normal file
125
src/lib/csound/engine.ts
Normal file
@ -0,0 +1,125 @@
|
||||
import { Csound } from '@csound/browser';
|
||||
|
||||
export interface CsoundEngineOptions {
|
||||
onMessage?: (message: string) => void;
|
||||
onError?: (error: string) => void;
|
||||
}
|
||||
|
||||
export class CsoundEngine {
|
||||
private csound: Csound | null = null;
|
||||
private initialized = false;
|
||||
private running = false;
|
||||
private options: CsoundEngineOptions;
|
||||
|
||||
constructor(options: CsoundEngineOptions = {}) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
if (this.initialized) return;
|
||||
|
||||
try {
|
||||
this.csound = await Csound();
|
||||
|
||||
this.csound.on('message', (message: string) => {
|
||||
this.options.onMessage?.(message);
|
||||
});
|
||||
|
||||
await this.csound.setOption('-odac');
|
||||
|
||||
this.initialized = true;
|
||||
this.log('Csound initialized successfully');
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Failed to initialize Csound';
|
||||
this.error(errorMsg);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async evaluateCode(code: string): Promise<void> {
|
||||
if (!this.initialized || !this.csound) {
|
||||
throw new Error('Csound not initialized. Call init() first.');
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.running) {
|
||||
await this.stop();
|
||||
}
|
||||
|
||||
this.log('Resetting Csound...');
|
||||
await this.csound.reset();
|
||||
|
||||
this.log('Setting audio output...');
|
||||
await this.csound.setOption('-odac');
|
||||
|
||||
const orcMatch = code.match(/<CsInstruments>([\s\S]*?)<\/CsInstruments>/);
|
||||
const scoMatch = code.match(/<CsScore>([\s\S]*?)<\/CsScore>/);
|
||||
|
||||
if (!orcMatch || !scoMatch) {
|
||||
throw new Error('Invalid CSD format. Must contain <CsInstruments> and <CsScore> sections.');
|
||||
}
|
||||
|
||||
const orc = orcMatch[1].trim();
|
||||
const sco = scoMatch[1].trim();
|
||||
|
||||
this.log('Compiling orchestra...');
|
||||
await this.csound.compileOrc(orc);
|
||||
|
||||
this.log('Reading score...');
|
||||
await this.csound.readScore(sco);
|
||||
|
||||
this.log('Starting...');
|
||||
await this.csound.start();
|
||||
|
||||
this.log('Performing...');
|
||||
this.running = true;
|
||||
await this.csound.perform();
|
||||
|
||||
this.log('Performance complete');
|
||||
this.running = false;
|
||||
} catch (error) {
|
||||
this.running = false;
|
||||
const errorMsg = error instanceof Error ? error.message : 'Evaluation failed';
|
||||
this.error(errorMsg);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
if (!this.csound || !this.running) return;
|
||||
|
||||
try {
|
||||
await this.csound.stop();
|
||||
await this.csound.reset();
|
||||
this.running = false;
|
||||
this.log('Stopped');
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Failed to stop';
|
||||
this.error(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
isRunning(): boolean {
|
||||
return this.running;
|
||||
}
|
||||
|
||||
isInitialized(): boolean {
|
||||
return this.initialized;
|
||||
}
|
||||
|
||||
private log(message: string): void {
|
||||
this.options.onMessage?.(message);
|
||||
}
|
||||
|
||||
private error(message: string): void {
|
||||
this.options.onError?.(message);
|
||||
}
|
||||
|
||||
async destroy(): Promise<void> {
|
||||
if (this.running) {
|
||||
await this.stop();
|
||||
}
|
||||
this.csound = null;
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
4
src/lib/csound/index.ts
Normal file
4
src/lib/csound/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export { CsoundEngine } from './engine';
|
||||
export type { CsoundEngineOptions } from './engine';
|
||||
export { csound, csoundLogs, csoundInitialized, csoundRunning } from './store';
|
||||
export type { LogEntry } from './store';
|
||||
109
src/lib/csound/store.ts
Normal file
109
src/lib/csound/store.ts
Normal file
@ -0,0 +1,109 @@
|
||||
import { writable, derived, get } from 'svelte/store';
|
||||
import { CsoundEngine } from './engine';
|
||||
|
||||
export interface LogEntry {
|
||||
timestamp: Date;
|
||||
message: string;
|
||||
type: 'info' | 'error';
|
||||
}
|
||||
|
||||
interface CsoundState {
|
||||
initialized: boolean;
|
||||
running: boolean;
|
||||
logs: LogEntry[];
|
||||
}
|
||||
|
||||
function createCsoundStore() {
|
||||
const initialState: CsoundState = {
|
||||
initialized: false,
|
||||
running: false,
|
||||
logs: []
|
||||
};
|
||||
|
||||
const { subscribe, set, update } = writable<CsoundState>(initialState);
|
||||
|
||||
let engine: CsoundEngine | null = null;
|
||||
|
||||
function addLog(message: string, type: 'info' | 'error' = 'info') {
|
||||
update(state => ({
|
||||
...state,
|
||||
logs: [...state.logs, { timestamp: new Date(), message, type }]
|
||||
}));
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
|
||||
async init() {
|
||||
if (engine) return;
|
||||
|
||||
try {
|
||||
engine = new CsoundEngine({
|
||||
onMessage: (msg) => addLog(msg, 'info'),
|
||||
onError: (err) => addLog(err, 'error')
|
||||
});
|
||||
|
||||
await engine.init();
|
||||
|
||||
update(state => ({
|
||||
...state,
|
||||
initialized: true
|
||||
}));
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Failed to initialize';
|
||||
addLog(errorMsg, 'error');
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async evaluate(code: string) {
|
||||
if (!engine) {
|
||||
throw new Error('CSound engine not initialized');
|
||||
}
|
||||
|
||||
try {
|
||||
update(state => ({ ...state, running: true }));
|
||||
await engine.evaluateCode(code);
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Evaluation failed';
|
||||
addLog(errorMsg, 'error');
|
||||
throw error;
|
||||
} finally {
|
||||
update(state => ({ ...state, running: false }));
|
||||
}
|
||||
},
|
||||
|
||||
async stop() {
|
||||
if (!engine) return;
|
||||
|
||||
try {
|
||||
await engine.stop();
|
||||
update(state => ({ ...state, running: false }));
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Stop failed';
|
||||
addLog(errorMsg, 'error');
|
||||
}
|
||||
},
|
||||
|
||||
clearLogs() {
|
||||
update(state => ({
|
||||
...state,
|
||||
logs: []
|
||||
}));
|
||||
},
|
||||
|
||||
async destroy() {
|
||||
if (engine) {
|
||||
await engine.destroy();
|
||||
engine = null;
|
||||
}
|
||||
set(initialState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const csound = createCsoundStore();
|
||||
|
||||
export const csoundLogs = derived(csound, $csound => $csound.logs);
|
||||
export const csoundInitialized = derived(csound, $csound => $csound.initialized);
|
||||
export const csoundRunning = derived(csound, $csound => $csound.running);
|
||||
Reference in New Issue
Block a user