--- linuxsampler/trunk/Documentation/lscp.xml 2005/05/09 17:40:33 534 +++ linuxsampler/trunk/Documentation/lscp.xml 2006/12/20 19:40:37 991 @@ -11,9 +11,12 @@ - - + + + + LinuxSampler Control Protocol + The frontend's LSCP minor version is less or equal than + the sampler's LSCP minor version. + + + + Compatibility can only be claimed if both rules are true. + The frontend can use the + "GET SERVER INFO" command to + get the version of the LSCP specification the sampler complies with. + + +
LinuxSampler is a so called software sampler application capable to playback audio samples from a computer's Random @@ -124,7 +164,7 @@ arbitrary MIDI input method and arbitrary MIDI channel (e.g. sampler channel 17 could be connected to an ALSA sequencer device 64:0 and listening to MIDI channel 1 there). Each sampler - engine will be assigned an own instance of one of the available + channel will be associated with an instance of one of the available sampler engines (e.g. GigEngine, DLSEngine). The audio output of each sampler channel can be routed to an arbitrary audio output method (ALSA / JACK) and an arbitrary audio output channel @@ -154,7 +194,8 @@ methods will be described next.
- This simple communication method is based on TCP. The + This simple communication method is based on + TCP. The front-end application establishes a TCP connection to the LinuxSampler instance on a certain host system. Then the front-end application will send certain ASCII based commands @@ -425,7 +466,7 @@
-
+
This chapter will describe the available control commands that can be sent on the TCP connection in detail. Some certain commands (e.g. "GET CHANNEL INFO" @@ -683,7 +724,7 @@ DEPENDS - - comma separated list of paramters this parameter depends + comma separated list of parameters this parameter depends on, means the values for fields 'DEFAULT', 'RANGE_MIN', 'RANGE_MAX' and 'POSSIBILITIES' might depend on these listed parameters, for example assuming that an audio @@ -796,7 +837,9 @@ Where <audio-output-driver> should be replaced by the desired audio - output system and <param-list> by an optional list of driver + output system as returned by the + "LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS" + command and <param-list> by an optional list of driver specific parameters in form of "key1=val1 key2=val2 ...", where character string values should be encapsulated into apostrophes ('). Note that there might be drivers which require parameter(s) to be @@ -1017,7 +1060,10 @@ Where <device-id> should be replaced by the numerical ID of the - audio output device, <key> by the name of the parameter to change + audio output device as given by the + "CREATE AUDIO_OUTPUT_DEVICE" + or "LIST AUDIO_OUTPUT_DEVICES" + command, <key> by the name of the parameter to change and <value> by the new value for this parameter. Possible Answers: @@ -1058,8 +1104,10 @@ GET AUDIO_OUTPUT_CHANNEL INFO <device-id> <audio-chan> - Where <device-id> is the numerical ID of the audio output device - and <audio-chan> the audio channel number. + Where <device-id> is the numerical ID of the audio output device as given by the + "CREATE AUDIO_OUTPUT_DEVICE" + or "LIST AUDIO_OUTPUT_DEVICES" + command and <audio-chan> the audio channel number. Possible Answers: @@ -1158,8 +1206,9 @@ - Where <dev-id> is the numerical ID of the audio output device as returned - by the "LIST AUDIO_OUTPUT_DEVICES" + Where <dev-id> is the numerical ID of the audio output device as returned by the + "CREATE AUDIO_OUTPUT_DEVICE" + or "LIST AUDIO_OUTPUT_DEVICES" command, <chan> the audio channel number and <param> a specific channel parameter name for which information should be obtained (as returned by the @@ -1261,8 +1310,10 @@ SET AUDIO_OUTPUT_CHANNEL_PARAMETER <dev-id> <chn> <key>=<value> - Where <dev-id> should be replaced by the numerical ID of the audio - device, <chn> by the audio channel number, <key> by the name of the + Where <dev-id> should be replaced by the numerical ID of the audio output device as returned by the + "CREATE AUDIO_OUTPUT_DEVICE" + or "LIST AUDIO_OUTPUT_DEVICES" + command, <chn> by the audio channel number, <key> by the name of the parameter to change and <value> by the new value for this parameter. Possible Answers: @@ -1386,7 +1437,9 @@ GET MIDI_INPUT_DRIVER INFO <midi-input-driver> - Where <midi-input-driver> is the name of the MIDI input driver. + Where <midi-input-driver> is the name of the MIDI input driver as returned + by the + "LIST AVAILABLE_MIDI_INPUT_DRIVERS" command. Possible Answers: @@ -1441,7 +1494,7 @@ - Where <midi-t> is the name of the MIDI input driver as returned + Where <midit> is the name of the MIDI input driver as returned by the "LIST AVAILABLE_MIDI_INPUT_DRIVERS" command, <param> a specific parameter name for which information should be obtained (as returned by the @@ -1514,7 +1567,7 @@ DEPENDS - - comma separated list of paramters this parameter depends + comma separated list of parameters this parameter depends on, means the values for fields 'DEFAULT', 'RANGE_MIN', 'RANGE_MAX' and 'POSSIBILITIES' might depend on these listed parameters, for example assuming that an audio @@ -1596,7 +1649,9 @@ - Where <midi-input-driver> should be replaced by the desired MIDI input system and <param-list> by an + Where <midi-input-driver> should be replaced by the desired MIDI input system as returned + by the + "LIST AVAILABLE_MIDI_INPUT_DRIVERS" command and <param-list> by an optional list of driver specific parameters in form of "key1=val1 key2=val2 ...", where character string values should be encapsulated into apostrophes ('). Note that there might be drivers which require parameter(s) to be @@ -1643,7 +1698,10 @@ DESTROY MIDI_INPUT_DEVICE <device-id> - Where <device-id> should be replaced by the device's numerical ID. + Where <device-id> should be replaced by the device's numerical ID as returned by the + "CREATE MIDI_INPUT_DEVICE" + or "LIST MIDI_INPUT_DEVICES" + command. Possible Answers: @@ -1735,7 +1793,10 @@ GET MIDI_INPUT_DEVICE INFO <device-id> - Where <device-id> is the numerical ID of the MIDI input device. + Where <device-id> is the numerical ID of the MIDI input device as returned by the + "CREATE MIDI_INPUT_DEVICE" + or "LIST MIDI_INPUT_DEVICES" + command. Possible Answers: @@ -1800,7 +1861,10 @@ Where <device-id> should be replaced by the numerical ID of the - MIDI input device, <key> by the name of the parameter to change and + MIDI input device as returned by the + "CREATE MIDI_INPUT_DEVICE" + or "LIST MIDI_INPUT_DEVICES" + command, <key> by the name of the parameter to change and <value> by the new value for this parameter. Possible Answers: @@ -1841,8 +1905,10 @@ GET MIDI_INPUT_PORT INFO <device-id> <midi-port> - Where <device-id> is the numerical ID of the MIDI input device - and <midi-port> the MIDI input port number. + Where <device-id> is the numerical ID of the MIDI input device as returned by the + "CREATE MIDI_INPUT_DEVICE" + or "LIST MIDI_INPUT_DEVICES" + command and <midi-port> the MIDI input port number. Possible Answers: @@ -1884,9 +1950,10 @@ - Where <dev-id> is the numerical ID of the MIDI input device as returned - by the - "LIST MIDI_INPUT_DEVICES" command, <port> the MIDI port number and + Where <dev-id> is the numerical ID of the MIDI input device as returned by the + "CREATE MIDI_INPUT_DEVICE" + or "LIST MIDI_INPUT_DEVICES" + command, <port> the MIDI port number and <param> a specific port parameter name for which information should be obtained (as returned by the "GET MIDI_INPUT_PORT INFO" command). @@ -1989,7 +2056,10 @@ Where <device-id> should be replaced by the numerical ID of the - MIDI device, <port> by the MIDI port number, <key> by the name of + MIDI device as returned by the + "CREATE MIDI_INPUT_DEVICE" + or "LIST MIDI_INPUT_DEVICES" + command, <port> by the MIDI port number, <key> by the name of the parameter to change and <value> by the new value for this parameter. @@ -2025,8 +2095,9 @@
- The following commands describe how to add and remove sampler channels, deploy - sampler engines, load instruments and connect sampler channels to MIDI and audio devices. + The following commands describe how to add and remove sampler channels, associate a + sampler channel with a sampler engine, load instruments and connect sampler channels to + MIDI and audio devices.
An instrument file can be loaded and assigned to a sampler channel by one of the following commands: @@ -2086,7 +2157,7 @@
- A sample engine can be deployed and assigned to a specific sampler + A sampler engine type can be associated to a specific sampler channel by the following command: @@ -2096,10 +2167,18 @@ Where <engine-name> is an engine name as obtained by the - "LIST AVAILABLE_ENGINES" command and <sampler-channel> the sampler channel the - deployed engine should be assigned to. Even if the respective - sampler channel has already a deployed engine with that engine - name, a new engine instance will be assigned to the sampler channel. + "LIST AVAILABLE_ENGINES" command and <sampler-channel> + the sampler channel as returned by the + "ADD CHANNEL" or + "LIST CHANNELS" command where + the engine type should be assigned to. This command should be issued + after adding a new sampler channel and before any other control + commands on the new sampler channel. It can also be used to change + the engine type of a sampler channel. This command has (currently) no + way to define or force if a new engine instance should be created and + assigned to the given sampler channel or if an already existing + instance of that engine type, shared with other sampler channels, + should be used. Possible Answers: @@ -2205,8 +2284,8 @@ in case a new sampler channel could be added, where <sampler-channel> reflects the channel number of the new - created sampler channel which should the be used to set up - the sampler channel by sending subsequent intialization + created sampler channel which should be used to set up + the sampler channel by sending subsequent initialization commands @@ -2241,9 +2320,12 @@ - This will decrement the sampler channel count by one and also - decrement the channel numbers of all subsequent sampler channels by - one. + Where <sampler-channel> should be replaced by the + number of the sampler channel as given by the + "ADD CHANNEL" + or "LIST CHANNELS" + command. The channel numbers of all subsequent sampler channels + remain the same. Possible Answers: @@ -2308,16 +2390,17 @@ Possible Answers: - LinuxSampler will answer by sending a comma separated character - string of the engines' names. Engine names can consist of lower and - upper cases, digits and underlines ("_" character). + LinuxSampler will answer by sending a comma separated list + of the engines' names encapsulated into apostrophes ('). + Engine names can consist of lower and upper cases, + digits and underlines ("_" character). Example: C: "LIST AVAILABLE_ENGINES" - S: "GigEngine,AkaiEngine,DLSEngine,JoesCustomEngine" + S: "'GigEngine','AkaiEngine','DLSEngine','JoesCustomEngine'"
@@ -2380,7 +2463,9 @@ GET CHANNEL INFO <sampler-channel> - Where <sampler-channel> is the sampler channel number the front-end is interested in. + Where <sampler-channel> is the sampler channel number the front-end is interested in + as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command. Possible Answers: @@ -2394,8 +2479,8 @@ ENGINE_NAME - - name of the engine that is deployed on the sampler - channel, "NONE" if there's no engine deployed yet for + name of the engine that is associated with the sampler + channel, "NONE" if there's no engine associated yet for this sampler channel @@ -2474,6 +2559,29 @@ 1.0 means amplification) + MUTE - + + Determines whether the channel is muted, "true" if the + channel is muted, "false" if the channel is not muted, and + "MUTED_BY_SOLO" if the channel is muted because of the + presence of a solo channel and will be unmuted when + there are no solo channels left + + + SOLO - + + Determines whether this is a solo channel, "true" if + the channel is a solo channel; "false" otherwise + + + MIDI_INSTRUMENT_MAP - + + Determines to which MIDI instrument map this sampler + channel is assigned to. Read chapter + "SET CHANNEL MIDI_INSTRUMENT_MAP" + for a list of possible values. + + @@ -2496,6 +2604,10 @@    "MIDI_INPUT_DEVICE: 0"    "MIDI_INPUT_PORT: 0"    "MIDI_INPUT_CHANNEL: 5" +    "VOLUME: 1.0" +    "MUTE: false" +    "SOLO: false" +    "MIDI_INSTRUMENT_MAP: NONE"    "." @@ -2509,7 +2621,9 @@ GET CHANNEL VOICE_COUNT <sampler-channel> - Where <sampler-channel> is the sampler channel number the front-end is interested in. + Where <sampler-channel> is the sampler channel number the front-end is interested in + as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command. Possible Answers: @@ -2534,7 +2648,9 @@ GET CHANNEL STREAM_COUNT <sampler-channel> - Where <sampler-channel> is the sampler channel number the front-end is interested in. + Where <sampler-channel> is the sampler channel number the front-end is interested in + as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command. Possible Answers: @@ -2568,7 +2684,9 @@ to get the fill state in percent, where <sampler-channel> is the - sampler channel number the front-end is interested in. + sampler channel number the front-end is interested in + as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command. Possible Answers: @@ -2612,9 +2730,13 @@ SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <audio-device-id> - Where <audio-device-id> is the numerical ID of the audio output - device and <sampler-channel> is the respective sampler channel - number. + Where <sampler-channel> is the respective sampler channel + number as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command and + <audio-device-id> is the numerical ID of the audio output device as given by the + "CREATE AUDIO_OUTPUT_DEVICE" + or "LIST AUDIO_OUTPUT_DEVICES" + command. Possible Answers: @@ -2646,7 +2768,7 @@
-
+
DEPRECATED: THIS COMMAND WILL DISAPPEAR SOON! The front-end can alter the audio output type on a specific sampler @@ -2697,7 +2819,9 @@ SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-chan> <audio-out> <audio-in> - Where <sampler-chan> is the sampler channel number, <audio-out> is the + Where <sampler-chan> is the sampler channel number + as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command, <audio-out> is the numerical ID of the sampler channel's audio output channel which should be rerouted and <audio-in> is the numerical ID of the audio channel of the selected audio output device where <audio-out> should be routed to. @@ -2740,8 +2864,12 @@ SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <midi-device-id> - Where <sampler-channel> is the sampler channel number and <midi-device-id> is the - the numerical ID of the MIDI input device. + Where <sampler-channel> is the sampler channel number + as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command + and <midi-device-id> is the numerical ID of the MIDI input device as returned by the + "CREATE MIDI_INPUT_DEVICE" + or "LIST MIDI_INPUT_DEVICES" command. Possible Answers: @@ -2845,7 +2973,7 @@ "ERR:<error-code>:<error-message>" - - in case it failed, providing an appropriate error code and error messag + in case it failed, providing an appropriate error code and error message @@ -2943,6 +3071,162 @@
+
+ The front-end can mute/unmute a specific sampler + channel by sending the following command: + + + SET CHANNEL MUTE <sampler-channel> <mute> + + + Where <sampler-channel> is the respective sampler channel + number as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command and + <mute> should be replaced either by "1" to mute the channel or "0" + to unmute the channel. + + Possible Answers: + + + "OK" - + + on success + + + "WRN:<warning-code>:<warning-message>" - + + if the channel was muted/unmuted, but there are noteworthy + issue(s) related, providing an appropriate warning code and + warning message + + + "ERR:<error-code>:<error-message>" - + + in case it failed, providing an appropriate error code and error message + + + + + Examples: + + + + + +
+ +
+ The front-end can solo/unsolo a specific sampler channel + by sending the following command: + + + SET CHANNEL SOLO <sampler-channel> <solo> + + + Where <sampler-channel> is the respective sampler channel + number as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command and + <solo> should be replaced either by "1" to solo the channel or "0" + to unsolo the channel. + + Possible Answers: + + + "OK" - + + on success + + + "WRN:<warning-code>:<warning-message>" - + + if the channel was soloed/unsoloed, but there are noteworthy + issue(s) related, providing an appropriate warning code and + warning message + + + "ERR:<error-code>:<error-message>" - + + in case it failed, providing an appropriate error code and error message + + + + + Examples: + + + + + +
+ +
+ The front-end can assign a MIDI instrument map to a specific sampler channel + by sending the following command: + + + SET CHANNEL MIDI_INSTRUMENT_MAP <sampler-channel> <map> + + + Where <sampler-channel> is the respective sampler channel + number as returned by the "ADD CHANNEL" + or "LIST CHANNELS" command and + <map> can have the following possibilites: + + + "NONE" - + + This is the default setting. In this case + the sampler channel is not assigned any MIDI + instrument map and thus will ignore all MIDI + program change messages. + + + "DEFAULT" - + + The sampler channel will always use the + default MIDI instrument map to handle MIDI + program change messages. + + + numeric ID - + + You can assign a specific MIDI instrument map + by replacing <map> with the respective numeric + ID of the MIDI instrument map as returned by the + "LIST MIDI_INSTRUMENT_MAPS" + command. Once that map will be deleted, the sampler + channel would fall back to "NONE". + + + + + Read chapter "MIDI Instrument Mapping" + for details regarding MIDI instrument mapping. + + Possible Answers: + + + "OK" - + + on success + + + "ERR:<error-code>:<error-message>" - + + in case it failed, providing an appropriate error code and error message + + + + + + Examples: + + + + + +
+
The front-end can reset a particular sampler channel by sending the following command: @@ -3128,6 +3412,42 @@
The following commands have global impact on the sampler. +
+ The front-end can ask for the current number of active voices on + the sampler by sending the following command: + + + GET TOTAL_VOICE_COUNT + + + + Possible Answers: + + + LinuxSampler will answer by returning the number of all active + voices on the sampler. + + +
+ +
+ The front-end can ask for the maximum number of active voices + by sending the following command: + + + GET TOTAL_VOICE_COUNT_MAX + + + + Possible Answers: + + + LinuxSampler will answer by returning the maximum number + of active voices. + + +
+
The front-end can reset the whole sampler by sending the following command: @@ -3153,30 +3473,1377 @@
+ +
+ The client can ask for general informations about the LinuxSampler + instance by sending the following command: + + + GET SERVER INFO + + + Possible Answers: + + + LinuxSampler will answer by sending a <CRLF> separated list. + Each answer line begins with the information category name + followed by a colon and then a space character <SP> and finally + the info character string to that information category. At the + moment the following categories are defined: + + + + DESCRIPTION - + + arbitrary textual description about the sampler + + + VERSION - + + version of the sampler + + + PROTOCOL_VERSION - + + version of the LSCP specification the sampler + complies with (see for details) + + + + + + + The mentioned fields above don't have to be in particular order. + Other fields might be added in future. +
+
+ + +
+ The MIDI protocol provides a way to switch between instruments + by sending so called MIDI bank select and MIDI program change + messages which are essentially just numbers. The following commands + allow to actually map arbitrary MIDI bank select / program change + numbers with real instruments. + The sampler allows to manage an arbitrary amount of MIDI + instrument maps which define which instrument to load on + which MIDI program change message. + By default, that is when the sampler is launched, there is no + map, thus the sampler will simply ignore all program change + messages. The front-end has to explicitly create at least one + map, add entries to the map and tell the respective sampler + channel(s) which MIDI instrument map to use, so the sampler + knows how to react on a given program change message on the + respective sampler channel, that is by switching to the + respectively defined engine type and loading the respective + instrument. See command + "SET CHANNEL MIDI_INSTRUMENT_MAP" + for how to assign a MIDI instrument map to a sampler channel. + Also note per MIDI specification a bank select message does not + cause to switch to another instrument. Instead when receiving a + bank select message the bank value will be stored and a subsequent + program change message (which may occur at any time) will finally + cause the sampler to switch to the respective instrument as + reflected by the current MIDI instrument map. + +
+ The front-end can add a new MIDI instrument map by sending + the following command: + + + ADD MIDI_INSTRUMENT_MAP [<name>] + + + Where <name> is an optional argument allowing to + assign a custom name to the new map. MIDI instrument Map + names do not have to be unique. + + Possible Answers: + + + "OK[<map>]" - + + in case a new MIDI instrument map could + be added, where <map> reflects the + unique ID of the newly created MIDI + instrument map + + + "ERR:<error-code>:<error-message>" - + + when a new map could not be created, which + might never occur in practice + + + + + + Examples: + + + C: "ADD MIDI_INSTRUMENT_MAP 'Standard Map'" + S: "OK[0]" + + + + + C: "ADD MIDI_INSTRUMENT_MAP 'Standard Drumkit'" + S: "OK[1]" + + + + + C: "ADD MIDI_INSTRUMENT_MAP" + S: "OK[5]" + + +
+ +
+ The front-end can delete a particular MIDI instrument map + by sending the following command: + + + REMOVE MIDI_INSTRUMENT_MAP <map> + + + Where <map> reflects the unique ID of the map to delete + as returned by the "LIST MIDI_INSTRUMENT_MAPS" + command. + The front-end can delete all MIDI instrument maps by + sending the following command: + + + REMOVE MIDI_INSTRUMENT_MAP ALL + + + + Possible Answers: + + + "OK" - + + in case the map(s) could be deleted + + + "ERR:<error-code>:<error-message>" - + + when the given map does not exist + + + + + + Examples: + + + C: "REMOVE MIDI_INSTRUMENT_MAP 0" + S: "OK" + + + + + C: "REMOVE MIDI_INSTRUMENT_MAP ALL" + S: "OK" + + +
+ +
+ The front-end can retrieve the current amount of MIDI + instrument maps by sending the following command: + + + GET MIDI_INSTRUMENT_MAPS + + + + Possible Answers: + + + The sampler will answer by returning the current + number of MIDI instrument maps. + + + + Example: + + + C: "GET MIDI_INSTRUMENT_MAPS" + S: "2" + + +
+ +
+ The number of MIDI instrument maps can change on runtime. To get the + current list of MIDI instrument maps, the front-end can send the + following command: + + + LIST MIDI_INSTRUMENT_MAPS + + + Possible Answers: + + + The sampler will answer by returning a comma separated list + with all MIDI instrument maps' numerical IDs. + + + Example: + + + C: "LIST MIDI_INSTRUMENT_MAPS" + S: "0,1,5,12" + + +
+ +
+ The front-end can ask for the current settings of a MIDI + instrument map by sending the following command: + + + GET MIDI_INSTRUMENT_MAP INFO <map> + + + Where <map> is the numerical ID of the map the + front-end is interested in as returned by the + "LIST MIDI_INSTRUMENT_MAPS" + command. + + Possible Answers: + + + LinuxSampler will answer by sending a <CRLF> separated list. + Each answer line begins with the settings category name + followed by a colon and then a space character <SP> and finally + the info character string to that setting category. At the + moment the following categories are defined: + + + + NAME - + + custom name of the given map, + which does not have to be unique + + + + + + + The mentioned fields above don't have to be in particular order. + + Example: + + + C: "GET MIDI_INSTRUMENT_MAP INFO 0" + S: "NAME: Standard Map" +    "." + + +
+ +
+ The front-end can alter the custom name of a MIDI + instrument map by sending the following command: + + + SET MIDI_INSTRUMENT_MAP NAME <map> <name> + + + Where <map> is the numerical ID of the map and + <name> the new custom name of the map, which does not + have to be unique. + + Possible Answers: + + + "OK" - + + on success + + + "ERR:<error-code>:<error-message>" - + + in case the given map does not exist + + + + + + Example: + + + C: "SET MIDI_INSTRUMENT_MAP NAME 0 'Foo instruments'" + S: "OK" + + +
+ +
+ The front-end can create a new or replace an existing entry + in a sampler's MIDI instrument map by sending the following + command: + + + MAP MIDI_INSTRUMENT <map> + <midi_bank> <midi_prog> <engine_name> + <filename> <instrument_index> <volume_value> + [<instr_load_mode>] [<name>] + + + Where <map> is the numeric ID of the map to alter, + <midi_bank> is an integer value between + 0..16383 reflecting the MIDI bank select index, + <midi_prog> an + integer value between 0..127 reflecting the MIDI program change + index, <engine_name> a sampler engine name as returned by + the "LIST AVAILABLE_ENGINES" + command (not encapsulated into apostrophes), <filename> the name + of the instrument's file to be deployed (encapsulated into apostrophes), + <instrument_index> the index (integer value) of the instrument + within the given file, <volume_value> reflects the master + volume of the instrument as optionally dotted number (where a + value < 1.0 means attenuation and a value > 1.0 means + amplification). This parameter easily allows to adjust the + volume of all intruments within a custom instrument map + without having to adjust their instrument files. The + OPTIONAL <instr_load_mode> argument defines the life + time of the instrument, that is when the instrument should + be loaded, when freed and has exactly the following + possibilities: + + + "ON_DEMAND" - + + The instrument will be loaded when needed, + that is when demanded by at least one sampler + channel. It will immediately be freed from memory + when not needed by any sampler channel anymore. + + + "ON_DEMAND_HOLD" - + + The instrument will be loaded when needed, + that is when demanded by at least one sampler + channel. It will be kept in memory even when + not needed by any sampler channel anymore. + Instruments with this mode are only freed + when the sampler is reset or all mapping + entries with this mode (and respective + instrument) are explicitly changed to + "ON_DEMAND" and no sampler channel is using + the instrument anymore. + + + "PERSISTENT" - + + The instrument will immediately be loaded + into memory in the background when this mapping + command is sent and the instrument is kept all + the time. Instruments with this mode are + only freed when the sampler is reset or all + mapping entries with this mode (and + respective instrument) are explicitly + changed to "ON_DEMAND" and no sampler + channel is using the instrument anymore. + + + not supplied - + + In case there is no <instr_load_mode> + argument given, it will be up to the + InstrumentManager to decide which mode to use. + Usually it will use "ON_DEMAND" if an entry + for the given instrument does not exist in + the InstrumentManager's list yet, otherwise + if an entry already exists, it will simply + stick with the mode currently reflected by + the already existing entry, that is it will + not change the mode. + + + + + + The <instr_load_mode> argument thus allows to define an + appropriate strategy (low memory consumption vs. fast + instrument switching) for each instrument individually. Note, the + following restrictions apply to this argument: "ON_DEMAND_HOLD" and + "PERSISTENT" have to be supported by the respective sampler engine + (which is technically the case when the engine provides an + InstrumentManager for its format). If this is not the case the + argument will automatically fall back to the default value + "ON_DEMAND". Also the load mode of one instrument may + automatically change the laod mode of other instrument(s), i.e. + because the instruments are part of the same file and the + engine does not allow a way to manage load modes for them + individually. Due to this, in case the frontend shows the + load modes of entries, the frontend should retrieve the actual + mode by i.e. sending + "GET MIDI_INSTRUMENT INFO" + command(s). Finally the OPTIONAL <name> argument allows to + set a custom name (encapsulated into apostrophes) for the mapping + entry, useful for frontends for displaying an appropriate name for + mapped instruments (using + "GET MIDI_INSTRUMENT INFO"). + + + The "MAP MIDI_INSTRUMENT" command + will immediately return, thus it will not block when an + instrument is to be loaded due to a "PERSISTENT" type + entry as instruments are loaded in the background. As a + consequence this command may not necessarily return an error + i.e. when the given instrument file does not exist or may + turn out to be corrupt. + + + Possible Answers: + + + "OK" - + + usually + + + "ERR:<error-code>:<error-message>" - + + when the given map or engine does not exist or a value + is out of range + + + + + + Examples: + + + C: "MAP MIDI_INSTRUMENT 0 3 0 gig '/usr/share/Steinway D.gig' 0 0.8 PERSISTENT" + S: "OK" + + + + + C: "MAP MIDI_INSTRUMENT 0 4 50 gig '/home/john/foostrings.gig' 7 1.0" + S: "OK" + + + + + C: "MAP MIDI_INSTRUMENT 0 0 0 gig '/usr/share/piano.gig' 0 1.0 'Normal Piano'" + S: "OK" + C: "MAP MIDI_INSTRUMENT 0 1 0 gig '/usr/share/piano.gig' 0 0.25 'Silent Piano'" + S: "OK" + + + + + C: "MAP MIDI_INSTRUMENT 1 8 120 gig '/home/joe/foodrums.gig' 0 1.0 PERSISTENT 'Foo Drumkit'" + S: "OK" + + +
+ +
+ The front-end can query the amount of currently existing + entries in a MIDI instrument map by sending the following + command: + + + GET MIDI_INSTRUMENTS <map> + + + The front-end can query the amount of currently existing + entries in all MIDI instrument maps by sending the following + command: + + + GET MIDI_INSTRUMENTS ALL + + + Possible Answers: + + + The sampler will answer by sending the current number of + entries in the MIDI instrument map(s). + + + + Example: + + + C: "GET MIDI_INSTRUMENTS 0" + S: "234" + + + + + C: "GET MIDI_INSTRUMENTS ALL" + S: "954" + + +
+ +
+ The front-end can query a list of all currently existing + entries in a certain MIDI instrument map by sending the following + command: + + + LIST MIDI_INSTRUMENTS <map> + + + Where <map> is the numeric ID of the MIDI instrument map. + The front-end can query a list of all currently existing + entries of all MIDI instrument maps by sending the following + command: + + + LIST MIDI_INSTRUMENTS ALL + + + + Possible Answers: + + + The sampler will answer by sending a comma separated + list of map ID - MIDI bank - MIDI program triples, where + each triple is encapsulated into curly braces. The + list is returned in one single line. Each triple + just reflects the key of the respective map entry, + thus subsequent + "GET MIDI_INSTRUMENT INFO" + command(s) are necessary to retrieve detailed informations + about each entry. + + + + Example: + + + C: "LIST MIDI_INSTRUMENTS 0" + S: "{0,0,0},{0,0,1},{0,0,3},{0,1,4},{1,127,127}" + + +
+ +
+ The front-end can delete an entry from a MIDI instrument + map by sending the following command: + + + UNMAP MIDI_INSTRUMENT <map> <midi_bank> <midi_prog> + + + + Where <map> is the numeric ID of the MIDI instrument map, + <midi_bank> is an integer value between 0..16383 + reflecting the MIDI bank value and + <midi_prog> an integer value between + 0..127 reflecting the MIDI program value of the map's entrie's key + index triple. + + + Possible Answers: + + + "OK" - + + usually + + + "ERR:<error-code>:<error-message>" - + + when index out of bounds + + + + + + Example: + + + C: "UNMAP MIDI_INSTRUMENT 0 2 127" + S: "OK" + + +
+ +
+ The front-end can retrieve the current settings of a certain + instrument map entry by sending the following command: + + + GET MIDI_INSTRUMENT INFO <map> <midi_bank> <midi_prog> + + + + Where <map> is the numeric ID of the MIDI instrument map, + <midi_bank> is an integer value between 0..16383 + reflecting the MIDI bank value, <midi_bank> + and <midi_prog> an integer value between + 0..127 reflecting the MIDI program value of the map's entrie's key + index triple. + + + Possible Answers: + + + LinuxSampler will answer by sending a <CRLF> + separated list. Each answer line begins with the + information category name followed by a colon and then + a space character <SP> and finally the info + character string to that info category. At the moment + the following categories are defined: + "NAME" - + + Name for this MIDI instrument map entry (if defined). + This name shall be used by frontends for displaying a + name for this mapped instrument. It can be set and + changed with the + "MAP MIDI_INSTRUMENT" + command and does not have to be unique. + + + "ENGINE_NAME" - + + Name of the engine to be deployed for this + instrument. + + + "INSTRUMENT_FILE" - + + File name of the instrument. + + + "INSTRUMENT_NR" - + + Index of the instrument within the file. + + + "INSTRUMENT_NAME" - + + Name of the loaded instrument as reflected by its file. + In contrast to the "NAME" field, the "INSTRUMENT_NAME" field + cannot be changed. + + + "LOAD_MODE" - + + Life time of instrument + (see "MAP MIDI_INSTRUMENT" for details about this setting). + + + "VOLUME" - + + master volume of the instrument as optionally + dotted number (where a value < 1.0 means attenuation + and a value > 1.0 means amplification) + + + The mentioned fields above don't have to be in particular order. + + + + Example: + + + C: "GET MIDI_INSTRUMENT INFO 1 45 120" + S: "NAME: Drums for Foo Song" +    "ENGINE_NAME: GigEngine" +    "INSTRUMENT_FILE: /usr/share/joesdrumkit.gig" +    "INSTRUMENT_NR: 0" +    "INSTRUMENT_NAME: Joe's Drumkit" +    "LOAD_MODE: PERSISTENT" +    "VOLUME: 1.0" +    "." + + +
+ +
+ The front-end can clear a whole MIDI instrument map, that + is delete all its entries by sending the following command: + + + CLEAR MIDI_INSTRUMENTS <map> + + + Where <map> is the numeric ID of the map to clear. + The front-end can clear all MIDI instrument maps, that + is delete all entries of all maps by sending the following + command: + + + CLEAR MIDI_INSTRUMENTS ALL + + + The command "CLEAR MIDI_INSTRUMENTS ALL" does not delete the + maps, only their entries, thus the map's settings like + custom name will be preservevd. + + Possible Answers: + + + "OK" - + + always + + + + + + Examples: + + + C: "CLEAR MIDI_INSTRUMENTS 0" + S: "OK" + + + + + C: "CLEAR MIDI_INSTRUMENTS ALL" + S: "OK" + + +
+
+
- TODO: will soon automatically included from src/network/lscp.y, - meanwhile have a look at that file to get the exact definition of - the command syntax. + The grammar of the control protocol as descibed in + is defined below using Backus-Naur Form (BNF as described in ) + where applicable. + + + + +input = + + line LF + + / line CR LF + + + +line = + + /* epsilon (empty line ignored) */ + + / comment + + / command + + / error + + + +comment = + + '#' + + / comment '#' + + / comment SP + + / comment number + + / comment string + + + +command = + + ADD SP add_instruction + + / MAP SP map_instruction + + / UNMAP SP unmap_instruction + + / GET SP get_instruction + + / CREATE SP create_instruction + + / DESTROY SP destroy_instruction + + / LIST SP list_instruction + + / LOAD SP load_instruction + + / REMOVE SP remove_instruction + + / SET SP set_instruction + + / SUBSCRIBE SP subscribe_event + + / UNSUBSCRIBE SP unsubscribe_event + + / SELECT SP text + + / RESET SP reset_instruction + + / CLEAR SP clear_instruction + + / RESET + + / QUIT + + + +add_instruction = + + CHANNEL + + / MIDI_INSTRUMENT_MAP + + / MIDI_INSTRUMENT_MAP SP map_name + + + +subscribe_event = + + AUDIO_OUTPUT_DEVICE_COUNT + + / AUDIO_OUTPUT_DEVICE_INFO + + / MIDI_INPUT_DEVICE_COUNT + + / MIDI_INPUT_DEVICE_INFO + + / CHANNEL_COUNT + + / VOICE_COUNT + + / STREAM_COUNT + + / BUFFER_FILL + + / CHANNEL_INFO + + / MIDI_INSTRUMENT_MAP_COUNT + + / MIDI_INSTRUMENT_MAP_INFO + + / MIDI_INSTRUMENT_COUNT + + / MIDI_INSTRUMENT_INFO + + / MISCELLANEOUS + + / TOTAL_VOICE_COUNT + + + +unsubscribe_event = + + AUDIO_OUTPUT_DEVICE_COUNT + + / AUDIO_OUTPUT_DEVICE_INFO + + / MIDI_INPUT_DEVICE_COUNT + + / MIDI_INPUT_DEVICE_INFO + + / CHANNEL_COUNT + + / VOICE_COUNT + + / STREAM_COUNT + + / BUFFER_FILL + + / CHANNEL_INFO + + / MIDI_INSTRUMENT_MAP_COUNT + + / MIDI_INSTRUMENT_MAP_INFO + + / MIDI_INSTRUMENT_COUNT + + / MIDI_INSTRUMENT_INFO + + / MISCELLANEOUS + + / TOTAL_VOICE_COUNT + + + +map_instruction = + + MIDI_INSTRUMENT SP midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value + + / MIDI_INSTRUMENT SP midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value SP instr_load_mode + + / MIDI_INSTRUMENT SP midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value SP entry_name + + / MIDI_INSTRUMENT SP midi_map SP midi_bank SP midi_prog SP engine_name SP filename SP instrument_index SP volume_value SP instr_load_mode SP entry_name + + + +unmap_instruction = + + MIDI_INSTRUMENT SP midi_map SP midi_bank SP midi_prog + + + +remove_instruction = + + CHANNEL SP sampler_channel + + / MIDI_INSTRUMENT_MAP SP midi_map + + / MIDI_INSTRUMENT_MAP SP ALL + + + +get_instruction = + + AVAILABLE_ENGINES + + / AVAILABLE_MIDI_INPUT_DRIVERS + + / MIDI_INPUT_DRIVER SP INFO SP string + + / MIDI_INPUT_DRIVER_PARAMETER SP INFO SP string SP string + + / MIDI_INPUT_DRIVER_PARAMETER SP INFO SP string SP string SP key_val_list + + / AVAILABLE_AUDIO_OUTPUT_DRIVERS + + / AUDIO_OUTPUT_DRIVER SP INFO SP string + + / AUDIO_OUTPUT_DRIVER_PARAMETER SP INFO SP string SP string + + / AUDIO_OUTPUT_DRIVER_PARAMETER SP INFO SP string SP string SP key_val_list + + / AUDIO_OUTPUT_DEVICES + + / MIDI_INPUT_DEVICES + + / AUDIO_OUTPUT_DEVICE SP INFO SP number + + / MIDI_INPUT_DEVICE SP INFO SP number + + / MIDI_INPUT_PORT SP INFO SP number SP number + + / MIDI_INPUT_PORT_PARAMETER SP INFO SP number SP number SP string + + / AUDIO_OUTPUT_CHANNEL SP INFO SP number SP number + + / AUDIO_OUTPUT_CHANNEL_PARAMETER SP INFO SP number SP number SP string + + / CHANNELS + + / CHANNEL SP INFO SP sampler_channel + + / CHANNEL SP BUFFER_FILL SP buffer_size_type SP sampler_channel + + / CHANNEL SP STREAM_COUNT SP sampler_channel + + / CHANNEL SP VOICE_COUNT SP sampler_channel + + / ENGINE SP INFO SP engine_name + + / SERVER SP INFO + + / TOTAL_VOICE_COUNT + + / TOTAL_VOICE_COUNT_MAX + + / MIDI_INSTRUMENTS SP midi_map + + / MIDI_INSTRUMENTS SP ALL + + / MIDI_INSTRUMENT SP INFO SP midi_map SP midi_bank SP midi_prog + + / MIDI_INSTRUMENT_MAPS + + / MIDI_INSTRUMENT_MAP SP INFO SP midi_map + + + +set_instruction = + + AUDIO_OUTPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list + + / AUDIO_OUTPUT_CHANNEL_PARAMETER SP number SP number SP string '=' param_val_list + + / MIDI_INPUT_DEVICE_PARAMETER SP number SP string '=' param_val_list + + / MIDI_INPUT_PORT_PARAMETER SP number SP number SP string '=' param_val_list + + / CHANNEL SP set_chan_instruction + + / MIDI_INSTRUMENT_MAP SP NAME SP midi_map SP map_name + + / ECHO SP boolean + + + +create_instruction = + + AUDIO_OUTPUT_DEVICE SP string SP key_val_list + + / AUDIO_OUTPUT_DEVICE SP string + + / MIDI_INPUT_DEVICE SP string SP key_val_list + + / MIDI_INPUT_DEVICE SP string + + + +reset_instruction = + + CHANNEL SP sampler_channel + + + +clear_instruction = + + MIDI_INSTRUMENTS SP midi_map + + / MIDI_INSTRUMENTS SP ALL + + + +destroy_instruction = + + AUDIO_OUTPUT_DEVICE SP number + + / MIDI_INPUT_DEVICE SP number + + + +load_instruction = + + INSTRUMENT SP load_instr_args + + / ENGINE SP load_engine_args + + + +set_chan_instruction = + + AUDIO_OUTPUT_DEVICE SP sampler_channel SP device_index + + / AUDIO_OUTPUT_CHANNEL SP sampler_channel SP audio_channel_index SP audio_channel_index + + / AUDIO_OUTPUT_TYPE SP sampler_channel SP audio_output_type_name + + / MIDI_INPUT SP sampler_channel SP device_index SP midi_input_port_index SP midi_input_channel_index + + / MIDI_INPUT_DEVICE SP sampler_channel SP device_index + + / MIDI_INPUT_PORT SP sampler_channel SP midi_input_port_index + + / MIDI_INPUT_CHANNEL SP sampler_channel SP midi_input_channel_index + + / MIDI_INPUT_TYPE SP sampler_channel SP midi_input_type_name + + / VOLUME SP sampler_channel SP volume_value + + / MUTE SP sampler_channel SP boolean + + / SOLO SP sampler_channel SP boolean + + / MIDI_INSTRUMENT_MAP SP sampler_channel SP midi_map + + / MIDI_INSTRUMENT_MAP SP sampler_channel SP NONE + + / MIDI_INSTRUMENT_MAP SP sampler_channel SP DEFAULT + + + +key_val_list = + + string '=' param_val_list + + / key_val_list SP string '=' param_val_list + + + +buffer_size_type = + + BYTES + + / PERCENTAGE + + + +list_instruction = + + AUDIO_OUTPUT_DEVICES + + / MIDI_INPUT_DEVICES + + / CHANNELS + + / AVAILABLE_ENGINES + + / AVAILABLE_MIDI_INPUT_DRIVERS + + / AVAILABLE_AUDIO_OUTPUT_DRIVERS + + / MIDI_INSTRUMENTS SP midi_map + + / MIDI_INSTRUMENTS SP ALL + + / MIDI_INSTRUMENT_MAPS + + + +load_instr_args = + + filename SP instrument_index SP sampler_channel + + / NON_MODAL SP filename SP instrument_index SP sampler_channel + + + +load_engine_args = + + engine_name SP sampler_channel + + + +instr_load_mode = + + ON_DEMAND + + / ON_DEMAND_HOLD + + / PERSISTENT + + + +device_index = + + number + + + +audio_channel_index = + + number + + + +audio_output_type_name = + + string + + + +midi_input_port_index = + + number + + + +midi_input_channel_index = + + number + + / ALL + + + +midi_input_type_name = + + string + + + +midi_map = + + number + + + +midi_bank = + + number + + + +midi_prog = + + number + + + +volume_value = + + dotnum + + / number + + + +sampler_channel = + + number + + + +instrument_index = + + number + + + +engine_name = + + string + + + +filename = + + stringval + + + +map_name = + + stringval + + + +entry_name = + + stringval + + + +param_val_list = + + param_val + + / param_val_list','param_val + + + +param_val = + + string + + / stringval + + / number + + / dotnum + + + + +
This chapter will describe all currently defined events supported by LinuxSampler. -
+
+ Client may want to be notified when the total number of audio output devices on the + back-end changes by issuing the following command: + + + SUBSCRIBE AUDIO_OUTPUT_DEVICE_COUNT + + + Server will start sending the following notification messages: + + + "NOTIFY:AUDIO_OUTPUT_DEVICE_COUNT:<devices>" + + + where <devices> will be replaced by the new number + of audio output devices. +
+ +
+ Client may want to be notified when changes were made to audio output devices on the + back-end by issuing the following command: + + + SUBSCRIBE AUDIO_OUTPUT_DEVICE_INFO + + + Server will start sending the following notification messages: + + + "NOTIFY:AUDIO_OUTPUT_DEVICE_INFO:<device-id>" + + + where <device-id> will be replaced by the numerical ID of the audio output device, + which settings has been changed. The front-end will have to send + the respective command to actually get the audio output device info. Because these messages + will be triggered by LSCP commands issued by other clients rather than real + time events happening on the server, it is believed that an empty notification + message is sufficient here. +
+ +
+ Client may want to be notified when the total number of MIDI input devices on the + back-end changes by issuing the following command: + + + SUBSCRIBE MIDI_INPUT_DEVICE_COUNT + + + Server will start sending the following notification messages: + + + "NOTIFY:MIDI_INPUT_DEVICE_COUNT:<devices>" + + + where <devices> will be replaced by the new number + of MIDI input devices. +
+ +
+ Client may want to be notified when changes were made to MIDI input devices on the + back-end by issuing the following command: + + + SUBSCRIBE MIDI_INPUT_DEVICE_INFO + + + Server will start sending the following notification messages: + + + "NOTIFY:MIDI_INPUT_DEVICE_INFO:<device-id>" + + + where <device-id> will be replaced by the numerical ID of the MIDI input device, + which settings has been changed. The front-end will have to send + the respective command to actually get the MIDI input device info. Because these messages + will be triggered by LSCP commands issued by other clients rather than real + time events happening on the server, it is believed that an empty notification + message is sufficient here. +
+ +
Client may want to be notified when the total number of channels on the back-end changes by issuing the following command: - SUBSCRIBE CHANNELS + SUBSCRIBE CHANNEL_COUNT Server will start sending the following notification messages: - "NOTIFY:CHANNELS:<channels>" + "NOTIFY:CHANNEL_COUNT:<channels>" where <channels> will be replaced by the new number @@ -3242,18 +4909,18 @@ "GET CHANNEL BUFFER_FILL PERCENTAGE" command was issued on this channel.
-
+
Client may want to be notified when changes were made to sampler channels on the - back-end changes by issuing the following command: + back-end by issuing the following command: - SUBSCRIBE INFO + SUBSCRIBE CHANNEL_INFO Server will start sending the following notification messages: - "NOTIFY:INFO:<sampler-channel>" + "NOTIFY:CHANNEL_INFO:<sampler-channel>" where <sampler-channel> will be replaced by the sampler channel the @@ -3264,6 +4931,106 @@ message is sufficient here.
+
+ Client may want to be notified when the total number of voices on the + back-end changes by issuing the following command: + + + SUBSCRIBE TOTAL_VOICE_COUNT + + + Server will start sending the following notification messages: + + + "NOTIFY:TOTAL_VOICE_COUNT:<voices> + + + where <voices> will be replaced by the new number of + all currently active voices. +
+ +
+ Client may want to be notified when the number of MIDI instrument maps on the + back-end changes by issuing the following command: + + + SUBSCRIBE MIDI_INSTRUMENT_MAP_COUNT + + + Server will start sending the following notification messages: + + + "NOTIFY:MIDI_INSTRUMENT_MAP_COUNT:<maps>" + + + where <maps> will be replaced by the new number + of MIDI instrument maps. +
+ +
+ Client may want to be notified when changes were made to MIDI instrument maps on the + back-end by issuing the following command: + + + SUBSCRIBE MIDI_INSTRUMENT_MAP_INFO + + + Server will start sending the following notification messages: + + + "NOTIFY:MIDI_INSTRUMENT_MAP_INFO:<map-id>" + + + where <map-id> will be replaced by the numerical ID of the MIDI instrument map, + for which information changes occurred. The front-end will have to send + the respective command to actually get the MIDI instrument map info. Because these messages + will be triggered by LSCP commands issued by other clients rather than real + time events happening on the server, it is believed that an empty notification + message is sufficient here. +
+ +
+ Client may want to be notified when the number of MIDI instrument maps on the + back-end changes by issuing the following command: + + + SUBSCRIBE MIDI_INSTRUMENT_COUNT + + + Server will start sending the following notification messages: + + + "NOTIFY:MIDI_INSTRUMENT_COUNT:<map-id> <instruments>" + + + where <map-id> is the numerical ID of the MIDI instrument map, in which + the nuber of instruments has changed and <instruments> will be replaced by + the new number of MIDI instruments in the specified map. +
+ +
+ Client may want to be notified when changes were made to MIDI instruments on the + back-end by issuing the following command: + + + SUBSCRIBE MIDI_INSTRUMENT_INFO + + + Server will start sending the following notification messages: + + + "NOTIFY:MIDI_INSTRUMENT_INFO:<map-id> <bank> <program>" + + + where <map-id> will be replaced by the numerical ID of the MIDI instrument map, + in which a MIDI instrument is changed. <bank> and <program> specifies + the location of the changed MIDI instrument in the map. The front-end will have to send + the respective command to actually get the MIDI instrument info. Because these messages + will be triggered by LSCP commands issued by other clients rather than real + time events happening on the server, it is believed that an empty notification + message is sufficient here. +
+
Client may want to be notified of miscellaneous and debugging events occurring at the server by issuing the following command: @@ -3300,6 +5067,7 @@ Rui Nuno Capela Vladimir Senkov Mark Knecht + Grigor Iliev
@@ -3307,7 +5075,41 @@ - &rfc2119; + + + + Key words for use in RFCs to Indicate Requirement Levels + + Harvard University + + + + + + + + TRANSMISSION CONTROL PROTOCOL + + Defense Advanced Research Projects Agency + + + + + + + + Augmented BNF for Syntax Specifications + + Internet Mail Consortium + + + Demon Internet Ltd + + + + + +