1551 lines
57 KiB
HTML
1551 lines
57 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<meta name="generator" content="AsciiDoc 10.2.0">
|
|
<title>Non Session Manager protocol</title>
|
|
<style type="text/css">
|
|
/*
|
|
* AsciiDoc 'ladi' theme, based on 'volnitsky' theme for xhtml11 and html5 backends.
|
|
* Based on css from http://volnitsky.com, which was in turn based on default
|
|
* theme from AsciiDoc
|
|
*
|
|
* FIXME: The styling is still a bit rough in places.
|
|
*
|
|
*/
|
|
|
|
/* Default font. */
|
|
body {
|
|
font-family: Georgia,"Times New Roman",Times,serif;
|
|
font-size: 16pt;
|
|
}
|
|
|
|
/* Title font. */
|
|
h1, h2, h3, h4, h5, h6,
|
|
div.title, caption.title,
|
|
thead, p.table.header,
|
|
#toctitle,
|
|
#author, #revnumber, #revdate, #revremark,
|
|
#footer {
|
|
font-family: Candara,Arial,sans-serif;
|
|
}
|
|
|
|
a.image { border-bottom: 0; }
|
|
|
|
#toc a {
|
|
border-bottom: 1px dotted #999999;
|
|
color: #3A3A4D !important;
|
|
text-decoration: none !important;
|
|
}
|
|
#toc a:hover {
|
|
border-bottom: 1px solid #6D4100;
|
|
color: #6D4100 !important;
|
|
text-decoration: none !important;
|
|
}
|
|
a { color: #666688; text-decoration: none; border-bottom: 1px dotted #666688; }
|
|
a:visited { color: #615FA0; border-bottom: 1px dotted #615FA0; }
|
|
a:hover { color: #6D4100; border-bottom: 1px solid #6D4100; }
|
|
|
|
em {
|
|
font-style: italic;
|
|
color: #444466;
|
|
}
|
|
|
|
strong {
|
|
font-weight: bold;
|
|
color: #444466;
|
|
}
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
color: #666688;
|
|
margin-bottom: 0.5em;
|
|
margin-right: 1em;
|
|
line-height: 1.3;
|
|
letter-spacing:+0.15em;
|
|
}
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
margin-left: 0em;
|
|
}
|
|
|
|
/* h1 { margin-left: 2em; } */
|
|
h2 { margin-left: 2em; }
|
|
/* h3 { margin-left: 4em; } */
|
|
/* h4 { margin-left: 5em; } */
|
|
/* h5 { margin-left: 6em; } */
|
|
/* h6 { margin-left: 7em; } */
|
|
|
|
h2 { border-bottom: 4px solid #ccd; }
|
|
h3 { border-bottom: 2px dotted #ccd; }
|
|
/* h2, h3 { border-bottom: 2px solid #ccd; } */
|
|
/* h2 { padding-top: 0.5em; } */
|
|
/* h3 { float: left; } */
|
|
/* h3 + * { clear: left; } */
|
|
|
|
div.banner {
|
|
background: #004455;
|
|
text-align: center;
|
|
color: #C6E9AF;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
div.sectionbody {
|
|
margin-top: 0;
|
|
margin-left: 3em;
|
|
margin-right: 1em;
|
|
margin-bottom: 1em;
|
|
}
|
|
|
|
hr {
|
|
border: 1px solid #444466;
|
|
}
|
|
|
|
p {
|
|
margin-left: 0.5em;
|
|
margin-right: 0.5em;
|
|
margin-top: 0.5em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
|
|
ul, ol, li > p {
|
|
margin-top: 0;
|
|
}
|
|
|
|
pre {
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
#author {
|
|
color: #444466;
|
|
font-weight: bold;
|
|
font-size: 1.1em;
|
|
}
|
|
|
|
#footer {
|
|
font-size: small;
|
|
border-top: 2px solid silver;
|
|
margin: 0;
|
|
}
|
|
|
|
#footer-text {
|
|
/* float: left; */
|
|
padding: 1em;
|
|
text-align: center;
|
|
}
|
|
|
|
#footer-badges {
|
|
float: right;
|
|
padding: 0.5em;
|
|
}
|
|
|
|
#preamble {
|
|
margin-top: 1.5em;
|
|
margin-bottom: 1.5em;
|
|
}
|
|
|
|
div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
|
|
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
|
|
div.admonitionblock {
|
|
margin-top: 1.5em;
|
|
margin-bottom: 1.5em;
|
|
}
|
|
|
|
div.admonitionblock {
|
|
margin-top: 2.5em;
|
|
margin-bottom: 2.5em;
|
|
}
|
|
|
|
#content { /* Block element content. */
|
|
margin: 2em;
|
|
}
|
|
|
|
/* Block element titles. */
|
|
div.title, caption.title {
|
|
color: #444466;
|
|
font-weight: bold;
|
|
text-align: left;
|
|
margin-top: 1.0em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
div.title + * {
|
|
margin-top: 0;
|
|
}
|
|
|
|
td div.title:first-child {
|
|
margin-top: 0.0em;
|
|
}
|
|
div.content div.title:first-child {
|
|
margin-top: 0.0em;
|
|
}
|
|
div.content + div.title {
|
|
margin-top: 0.0em;
|
|
}
|
|
|
|
div.sidebarblock > div.content {
|
|
background: #ffffee;
|
|
border: 1px solid silver;
|
|
padding: 0.5em;
|
|
}
|
|
|
|
div.listingblock > div.content {
|
|
border: 1px solid silver;
|
|
background: #f4f4f4;
|
|
padding: 0.5em;
|
|
}
|
|
|
|
div.quoteblock {
|
|
padding-left: 2.0em;
|
|
margin-right: 10%;
|
|
}
|
|
div.quoteblock > div.attribution {
|
|
padding-top: 0.5em;
|
|
text-align: right;
|
|
}
|
|
|
|
div.verseblock {
|
|
padding-left: 2.0em;
|
|
margin-right: 10%;
|
|
}
|
|
div.verseblock > pre.content {
|
|
font-family: inherit;
|
|
}
|
|
div.verseblock > div.attribution {
|
|
padding-top: 0.75em;
|
|
text-align: left;
|
|
}
|
|
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
|
|
div.verseblock + div.attribution {
|
|
text-align: left;
|
|
}
|
|
|
|
div.admonitionblock .icon {
|
|
vertical-align: top;
|
|
font-size: 1.1em;
|
|
font-weight: bold;
|
|
text-decoration: underline;
|
|
color: #444466;
|
|
padding-right: 0.5em;
|
|
}
|
|
div.admonitionblock td.content {
|
|
padding-left: 0.5em;
|
|
border-left: 2px solid silver;
|
|
}
|
|
|
|
div.exampleblock > div.content {
|
|
border-left: 2px solid silver;
|
|
padding: 0.5em;
|
|
}
|
|
|
|
div.imageblock div.content { padding-left: 0; }
|
|
span.image img { border-style: none; }
|
|
a.image:visited { color: white; }
|
|
|
|
dl {
|
|
margin-top: 0.8em;
|
|
margin-bottom: 0.8em;
|
|
}
|
|
dt {
|
|
margin-top: 0.5em;
|
|
margin-bottom: 0;
|
|
font-style: normal;
|
|
color: #444466;
|
|
}
|
|
dd > *:first-child {
|
|
margin-top: 0.1em;
|
|
}
|
|
|
|
ul, ol {
|
|
list-style-position: outside;
|
|
}
|
|
ol.arabic {
|
|
list-style-type: decimal;
|
|
}
|
|
ol.loweralpha {
|
|
list-style-type: lower-alpha;
|
|
}
|
|
ol.upperalpha {
|
|
list-style-type: upper-alpha;
|
|
}
|
|
ol.lowerroman {
|
|
list-style-type: lower-roman;
|
|
}
|
|
ol.upperroman {
|
|
list-style-type: upper-roman;
|
|
}
|
|
|
|
div.compact ul, div.compact ol,
|
|
div.compact p, div.compact p,
|
|
div.compact div, div.compact div {
|
|
margin-top: 0.1em;
|
|
margin-bottom: 0.1em;
|
|
}
|
|
|
|
div.tableblock > table {
|
|
border: 3px solid #444466;
|
|
}
|
|
thead {
|
|
font-weight: bold;
|
|
color: #444466;
|
|
}
|
|
tfoot {
|
|
font-weight: bold;
|
|
}
|
|
td > div.verse {
|
|
white-space: pre;
|
|
}
|
|
p.table {
|
|
margin-top: 0;
|
|
}
|
|
/* Because the table frame attribute is overridden by CSS in most browsers. */
|
|
div.tableblock > table[frame="void"] {
|
|
border-style: none;
|
|
}
|
|
div.tableblock > table[frame="hsides"] {
|
|
border-left-style: none;
|
|
border-right-style: none;
|
|
}
|
|
div.tableblock > table[frame="vsides"] {
|
|
border-top-style: none;
|
|
border-bottom-style: none;
|
|
}
|
|
|
|
|
|
div.hdlist {
|
|
margin-top: 0.8em;
|
|
margin-bottom: 0.8em;
|
|
}
|
|
div.hdlist tr {
|
|
padding-bottom: 15px;
|
|
}
|
|
dt.hdlist1.strong, td.hdlist1.strong {
|
|
font-weight: bold;
|
|
}
|
|
td.hdlist1 {
|
|
vertical-align: top;
|
|
font-style: normal;
|
|
padding-right: 0.8em;
|
|
color: #444466;
|
|
}
|
|
td.hdlist2 {
|
|
vertical-align: top;
|
|
}
|
|
div.hdlist.compact tr {
|
|
margin: 0;
|
|
padding-bottom: 0;
|
|
}
|
|
|
|
.comment {
|
|
background: yellow;
|
|
}
|
|
|
|
@media print {
|
|
#footer-badges { display: none; }
|
|
}
|
|
|
|
#toctitle {
|
|
color: #666688;
|
|
font-size: 1.2em;
|
|
font-weight: bold;
|
|
margin-top: 1.0em;
|
|
margin-bottom: 0.1em;
|
|
}
|
|
|
|
div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { margin-top: 0; margin-bottom: 0; }
|
|
div.toclevel1 { margin-top: 0.3em; margin-left: 0; font-size: 1.0em; }
|
|
div.toclevel2 { margin-top: 0.25em; margin-left: 2em; font-size: 0.9em; }
|
|
div.toclevel3 { margin-left: 4em; font-size: 0.8em; }
|
|
div.toclevel4 { margin-left: 6em; font-size: 0.8em; }
|
|
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.monospaced, tt, div.listingblock > div.content {
|
|
font-family: Consolas, "Andale Mono", "Courier New", monospace;
|
|
color: #004400;
|
|
background: #f4f4f4;
|
|
max-width: 80em;
|
|
line-height: 1.2em;
|
|
}
|
|
|
|
#header {
|
|
text-align: center;
|
|
margin: 2em;
|
|
}
|
|
|
|
#toc {
|
|
text-align: left;
|
|
margin-left: 3em;
|
|
max-width: 80%;
|
|
}
|
|
|
|
.paragraph p {
|
|
line-height: 1.5em;
|
|
/* margin: 1em; */
|
|
}
|
|
|
|
.paragraph p, li, dd, .content { max-width: 80em; }
|
|
.admonitionblock { max-width: 35em; }
|
|
|
|
div.sectionbody div.ulist > ul > li {
|
|
list-style-type: square;
|
|
color: #aaa;
|
|
}
|
|
div.sectionbody div.ulist > ul > li > * {
|
|
color: black;
|
|
/*font-size: 50%;*/
|
|
}
|
|
|
|
|
|
div.sectionbody div.ulist > ul > li div.ulist > ul > li {
|
|
color: #ccd ;
|
|
}
|
|
div.sectionbody div.ulist > ul > li div.ulist > ul > li > * {
|
|
color: black ;
|
|
}
|
|
|
|
em {
|
|
font-style: normal ! important;
|
|
font-weight: bold ! important;
|
|
color: #662222 ! important;
|
|
letter-spacing:+0.08em ! important;
|
|
}
|
|
|
|
span.underline { text-decoration: underline; }
|
|
span.overline { text-decoration: overline; }
|
|
span.line-through { text-decoration: line-through; }
|
|
|
|
/*
|
|
* html5 specific
|
|
*
|
|
* */
|
|
|
|
table.tableblock {
|
|
margin-top: 1.0em;
|
|
margin-bottom: 1.5em;
|
|
}
|
|
thead, p.tableblock.header {
|
|
font-weight: bold;
|
|
color: #666688;
|
|
}
|
|
p.tableblock {
|
|
margin-top: 0;
|
|
}
|
|
table.tableblock {
|
|
border-width: 3px;
|
|
border-spacing: 0px;
|
|
border-style: solid;
|
|
border-color: #444466;
|
|
border-collapse: collapse;
|
|
}
|
|
th.tableblock, td.tableblock {
|
|
border-width: 1px;
|
|
padding: 4px;
|
|
border-style: solid;
|
|
border-color: #444466;
|
|
}
|
|
|
|
table.tableblock.frame-topbot {
|
|
border-left-style: hidden;
|
|
border-right-style: hidden;
|
|
}
|
|
table.tableblock.frame-sides {
|
|
border-top-style: hidden;
|
|
border-bottom-style: hidden;
|
|
}
|
|
table.tableblock.frame-none {
|
|
border-style: hidden;
|
|
}
|
|
|
|
th.tableblock.halign-left, td.tableblock.halign-left {
|
|
text-align: left;
|
|
}
|
|
th.tableblock.halign-center, td.tableblock.halign-center {
|
|
text-align: center;
|
|
}
|
|
th.tableblock.halign-right, td.tableblock.halign-right {
|
|
text-align: right;
|
|
}
|
|
|
|
th.tableblock.valign-top, td.tableblock.valign-top {
|
|
vertical-align: top;
|
|
}
|
|
th.tableblock.valign-middle, td.tableblock.valign-middle {
|
|
vertical-align: middle;
|
|
}
|
|
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
|
|
vertical-align: bottom;
|
|
}
|
|
|
|
|
|
|
|
|
|
</style>
|
|
<script type="text/javascript">
|
|
/*<![CDATA[*/
|
|
var asciidoc = { // Namespace.
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Table Of Contents generator
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/* Author: Mihai Bazon, September 2002
|
|
* http://students.infoiasi.ro/~mishoo
|
|
*
|
|
* Table Of Content generator
|
|
* Version: 0.4
|
|
*
|
|
* Feel free to use this script under the terms of the GNU General Public
|
|
* License, as long as you do not remove or alter this notice.
|
|
*/
|
|
|
|
/* modified by Troy D. Hanson, September 2006. License: GPL */
|
|
/* modified by Stuart Rackham, 2006, 2009. License: GPL */
|
|
|
|
// toclevels = 1..4.
|
|
toc: function (toclevels) {
|
|
|
|
function getText(el) {
|
|
var text = "";
|
|
for (var i = el.firstChild; i != null; i = i.nextSibling) {
|
|
if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
|
|
text += i.data;
|
|
else if (i.firstChild != null)
|
|
text += getText(i);
|
|
}
|
|
return text;
|
|
}
|
|
|
|
function TocEntry(el, text, toclevel) {
|
|
this.element = el;
|
|
this.text = text;
|
|
this.toclevel = toclevel;
|
|
}
|
|
|
|
function tocEntries(el, toclevels) {
|
|
var result = new Array;
|
|
var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
|
|
// Function that scans the DOM tree for header elements (the DOM2
|
|
// nodeIterator API would be a better technique but not supported by all
|
|
// browsers).
|
|
var iterate = function (el) {
|
|
for (var i = el.firstChild; i != null; i = i.nextSibling) {
|
|
if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
|
|
var mo = re.exec(i.tagName);
|
|
if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
|
|
result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
|
|
}
|
|
iterate(i);
|
|
}
|
|
}
|
|
}
|
|
iterate(el);
|
|
return result;
|
|
}
|
|
|
|
var toc = document.getElementById("toc");
|
|
if (!toc) {
|
|
return;
|
|
}
|
|
|
|
// Delete existing TOC entries in case we're reloading the TOC.
|
|
var tocEntriesToRemove = [];
|
|
var i;
|
|
for (i = 0; i < toc.childNodes.length; i++) {
|
|
var entry = toc.childNodes[i];
|
|
if (entry.nodeName.toLowerCase() == 'div'
|
|
&& entry.getAttribute("class")
|
|
&& entry.getAttribute("class").match(/^toclevel/))
|
|
tocEntriesToRemove.push(entry);
|
|
}
|
|
for (i = 0; i < tocEntriesToRemove.length; i++) {
|
|
toc.removeChild(tocEntriesToRemove[i]);
|
|
}
|
|
|
|
// Rebuild TOC entries.
|
|
var entries = tocEntries(document.getElementById("content"), toclevels);
|
|
for (var i = 0; i < entries.length; ++i) {
|
|
var entry = entries[i];
|
|
if (entry.element.id == "")
|
|
entry.element.id = "_toc_" + i;
|
|
var a = document.createElement("a");
|
|
a.href = "#" + entry.element.id;
|
|
a.appendChild(document.createTextNode(entry.text));
|
|
var div = document.createElement("div");
|
|
div.appendChild(a);
|
|
div.className = "toclevel" + entry.toclevel;
|
|
toc.appendChild(div);
|
|
}
|
|
if (entries.length == 0)
|
|
toc.parentNode.removeChild(toc);
|
|
},
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Footnotes generator
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/* Based on footnote generation code from:
|
|
* http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
|
|
*/
|
|
|
|
footnotes: function () {
|
|
// Delete existing footnote entries in case we're reloading the footnodes.
|
|
var i;
|
|
var noteholder = document.getElementById("footnotes");
|
|
if (!noteholder) {
|
|
return;
|
|
}
|
|
var entriesToRemove = [];
|
|
for (i = 0; i < noteholder.childNodes.length; i++) {
|
|
var entry = noteholder.childNodes[i];
|
|
if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
|
|
entriesToRemove.push(entry);
|
|
}
|
|
for (i = 0; i < entriesToRemove.length; i++) {
|
|
noteholder.removeChild(entriesToRemove[i]);
|
|
}
|
|
|
|
// Rebuild footnote entries.
|
|
var cont = document.getElementById("content");
|
|
var spans = cont.getElementsByTagName("span");
|
|
var refs = {};
|
|
var n = 0;
|
|
for (i=0; i<spans.length; i++) {
|
|
if (spans[i].className == "footnote") {
|
|
n++;
|
|
var note = spans[i].getAttribute("data-note");
|
|
if (!note) {
|
|
// Use [\s\S] in place of . so multi-line matches work.
|
|
// Because JavaScript has no s (dotall) regex flag.
|
|
note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
|
|
spans[i].innerHTML =
|
|
"[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
|
|
"' title='View footnote' class='footnote'>" + n + "</a>]";
|
|
spans[i].setAttribute("data-note", note);
|
|
}
|
|
noteholder.innerHTML +=
|
|
"<div class='footnote' id='_footnote_" + n + "'>" +
|
|
"<a href='#_footnoteref_" + n + "' title='Return to text'>" +
|
|
n + "</a>. " + note + "</div>";
|
|
var id =spans[i].getAttribute("id");
|
|
if (id != null) refs["#"+id] = n;
|
|
}
|
|
}
|
|
if (n == 0)
|
|
noteholder.parentNode.removeChild(noteholder);
|
|
else {
|
|
// Process footnoterefs.
|
|
for (i=0; i<spans.length; i++) {
|
|
if (spans[i].className == "footnoteref") {
|
|
var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
|
|
href = href.match(/#.*/)[0]; // Because IE return full URL.
|
|
n = refs[href];
|
|
spans[i].innerHTML =
|
|
"[<a href='#_footnote_" + n +
|
|
"' title='View footnote' class='footnote'>" + n + "</a>]";
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
install: function(toclevels) {
|
|
var timerId;
|
|
|
|
function reinstall() {
|
|
asciidoc.footnotes();
|
|
if (toclevels) {
|
|
asciidoc.toc(toclevels);
|
|
}
|
|
}
|
|
|
|
function reinstallAndRemoveTimer() {
|
|
clearInterval(timerId);
|
|
reinstall();
|
|
}
|
|
|
|
timerId = setInterval(reinstall, 500);
|
|
if (document.addEventListener)
|
|
document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
|
|
else
|
|
window.onload = reinstallAndRemoveTimer;
|
|
}
|
|
|
|
}
|
|
asciidoc.install(2);
|
|
/*]]>*/
|
|
</script>
|
|
</head>
|
|
<body class="article">
|
|
<div id="header">
|
|
<h1>Non Session Manager protocol</h1>
|
|
<span id="author">This is adaptation of non-session-manager documentation for needs of LADI project</span><br>
|
|
<div id="toc">
|
|
<div id="toctitle">Table of Contents</div>
|
|
<noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
|
|
</div>
|
|
</div>
|
|
<div id="content">
|
|
<div id="preamble">
|
|
<div class="sectionbody">
|
|
<div class="paragraph"><p>Document authors:</p></div>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Jonathan Moore Liles (revisions from 1 to revision 1.2 from 2013-04-06)
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Nils Hilbricht (2020-07 initial adaptation of the NON project version)
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Nedko Arnaudov (2022 onward, as part of LADI project)
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_versioning">Versioning</h2>
|
|
<div class="sectionbody">
|
|
<table class="tableblock frame-all grid-all"
|
|
style="
|
|
width:100%;
|
|
">
|
|
<col style="width:50%;">
|
|
<col style="width:50%;">
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">api_version_major</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">1</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">api_version_minor</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">0</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="paragraph"><p>This document describes the NON Session Manager OSC API as defined and
|
|
implemented by NON project. The only difference is server-control
|
|
capability which was fixed in NON project codebase before the New
|
|
Session Manager schism but as of when this document is written, is not
|
|
fixed at the NSM API URL, see <a href="http://non.tuxfamily.org/nsm/API.html">http://non.tuxfamily.org/nsm/API.html</a>
|
|
for more info.</p></div>
|
|
<div class="paragraph"><p>For definition of the new-session-manager OSC API,
|
|
see <a href="https://new-session-manager.jackaudio.org/api/index.html">https://new-session-manager.jackaudio.org/api/index.html</a></p></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_session_management_as_part_of_the_non_audio_production_suite">Session Management as part of the Non audio production suite</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph"><p>The Non Session Management API is used by the various components of the Non audio production suite
|
|
to allow any number of independent programs to be managed together as part of a logical session
|
|
(i.e. a song). Thus, operations such as loading and saving are synchronized.</p></div>
|
|
<div class="paragraph"><p>The API comprises a simple Open Sound Control (OSC) based protocol, along with some behavioral
|
|
guidelines, which can easily be implemented by various applications.</p></div>
|
|
<div class="paragraph"><p>The Non project contains an program called <span class="monospaced">nsmd</span> which is an implementation of the server side of
|
|
the NSM API. <span class="monospaced">nsmd</span> is controlled by the <span class="monospaced">non-session-manager</span> GUI. However, the same server-side
|
|
API can also be implemented by other session managers (such as LADISH), although consistency and
|
|
robustness will likely suffer if non-NSM compliant clients are allowed to participate in a session.
|
|
The only dependency for client implementations <span class="monospaced">liblo</span> (the OSC library), which several Linux audio
|
|
applications already link to or plan to link to in the future.</p></div>
|
|
<div class="paragraph"><p>The aim of this project is to thoroughly define the behavior required of clients. This is an area
|
|
where other attempts at session management (LASH and JACK-Session) have failed. Often the
|
|
difficulty with these systems has been not in implementing support for them, but in attempting to
|
|
interpret the confusing, ambiguous, or ill-conceived API documentation. For these reasons and more
|
|
all previous attempts at Linux audio session management protocols are considered harmful.</p></div>
|
|
<div class="paragraph"><p>You WILL see some unambiguous and emphatic language in this document. For the good of the user,
|
|
these rules are meant to be followed and are non-negotiable. If an application does not conform to
|
|
this specification it should be considered broken. Consistency across applications under session
|
|
management is very important for a good user experience.</p></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_client_behavior_under_session_management">Client Behavior Under Session Management</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph"><p>Most graphical applications make available to the user a common set of file operations, typically
|
|
presented under a File or Project menu.</p></div>
|
|
<div class="paragraph"><p>These are: New, Open, Save, Save As, Close and Quit or Exit.</p></div>
|
|
<div class="paragraph"><p>The following sub-sections describe how these options should behave when the application is part of
|
|
an NSM session. These rules only apply when session management is active (that is, after the
|
|
<span class="monospaced">announce</span> handshake described in the <a href="#NSM OSC Protocol">[NSM OSC Protocol]</a> section. In order to provide a
|
|
consistent and predictable user experience, it is critically important for applications to adhere
|
|
to these guidelines.</p></div>
|
|
<div class="sect2">
|
|
<h3 id="_file_menu">File Menu</h3>
|
|
<div class="sect3">
|
|
<h4 id="_new">New</h4>
|
|
<div class="paragraph"><p>This option may empty/reset the current file or project (possibly after user confirmation). UNDER
|
|
NO CIRCUMSTANCES should it allow the user to create a new project/file in another location.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_open">Open</h4>
|
|
<div class="paragraph"><p>This option MUST be disabled.</p></div>
|
|
<div class="paragraph"><p>The application may, however, elect to implement an option called <em>Import into Session</em>, creates a
|
|
copy of a file/project which is then saved at the session path provided by NSM.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_save">Save</h4>
|
|
<div class="paragraph"><p>This option should behave as normal, saving the current file/project as established by the NSM
|
|
<span class="monospaced">open</span> message.</p></div>
|
|
<div class="paragraph"><p>UNDER NO CIRCUMSTANCES should this option present the user with a choice of where to save the file.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_save_as">Save As</h4>
|
|
<div class="paragraph"><p>This option MUST be disabled.</p></div>
|
|
<div class="paragraph"><p>The application may, however, elect to implement an option called <em>Export from Session</em>, which
|
|
creates a copy of the current file/project which is then saved in a user-specified location outside
|
|
of the session path provided by NSM.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_close_as_distinguished_from_quit_or_exit">Close (as distinguished from Quit or Exit)</h4>
|
|
<div class="paragraph"><p>This option MUST be disabled unless its meaning is to disconnect the application from session
|
|
management.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_quit_or_exit">Quit or Exit</h4>
|
|
<div class="paragraph"><p>This option may behave as normal (possibly asking the user to confirm exiting).</p></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_data_storage">Data Storage</h3>
|
|
<div class="sect3">
|
|
<h4 id="_internal_files">Internal Files</h4>
|
|
<div class="paragraph"><p>All project specific data created by a client MUST be stored in the per-client storage area
|
|
provided by NSM. This includes all recorded audio and MIDI files, snapshots, etc. Only global
|
|
configuration items, exports, and renders of the project may be stored elsewhere (wherever the user
|
|
specifies).</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_external_files">External Files</h4>
|
|
<div class="paragraph"><p>Files required by the project but external to it (typically read-only data such as audio samples)
|
|
SHOULD be referenced by creating a symbolic link within the assigned session area, and then
|
|
referring to the symlink. This allows sessions to be archived and transported simply (e.g. with
|
|
"tar -h") by tools that have no knowledge of the project formats of the various clients in the
|
|
session. The symlinks thus created should, at the very least, be named after the files they refer
|
|
to (some unique component may be required to prevent collisions)</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_nsm_osc_protocol">NSM OSC Protocol</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph"><p>All message parameters are REQUIRED. All messages MUST be sent from the same socket as the <span class="monospaced">announce</span>
|
|
message, using the <span class="monospaced">lo_send_from</span> method of liblo or its equivalent, as the server uses the return
|
|
addresses to distinguish between clients.</p></div>
|
|
<div class="paragraph"><p>Clients MUST create thier OSC servers using the same protocol (UDP,TCP) as found in <span class="monospaced">NSM_URL</span>. liblo
|
|
is lacking a robust TCP implementation at the time of writing, but in the future it may be useful.</p></div>
|
|
<div class="sect2">
|
|
<h3 id="_establishing_a_connection">Establishing a Connection</h3>
|
|
<div class="sect3">
|
|
<h4 id="_announce">Announce</h4>
|
|
<div class="paragraph"><p>At launch, the client MUST check the environment for the value of <span class="monospaced">NSM_URL</span>. If present, the client
|
|
MUST send the following message to the provided address as soon as it is ready to respond to the
|
|
<span class="monospaced">/nsm/client/open</span> event:</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/server/announce s:application_name s:capabilities s:executable_name i:api_version_major i:api_version_minor i:pid</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>If <span class="monospaced">NSM_URL</span> is undefined, invalid, or unreachable, then the client should proceed assuming that
|
|
session management is unavailable.</p></div>
|
|
<div class="paragraph"><p><span class="monospaced">api_version_major</span> and <span class="monospaced">api_version_minor</span> must be the two parts of the version number of the NSM API
|
|
as defined by this document.</p></div>
|
|
<div class="paragraph"><p>Note that if the application intends to register JACK clients, <span class="monospaced">application_name</span> MUST be the same as
|
|
the name that would normally be passed to <span class="monospaced">jack_client_open</span>. For example, Non-Mixer sends
|
|
"Non-Mixer" as its <span class="monospaced">application_name</span>. Applications MUST NOT register their JACK clients until
|
|
receiving an <span class="monospaced">open</span> message; the <span class="monospaced">open</span> message will provide a unique client name prefix suitable for
|
|
passing to JACK. This is probably the most complex requirement of the NSM API, but it isn’t
|
|
difficult to implement, especially if the application simply wishes to delay its initialization
|
|
process breifly while awaiting the <span class="monospaced">announce</span> reply and subsequent <span class="monospaced">open</span> message.</p></div>
|
|
<div class="paragraph"><p><span class="monospaced">capabilities</span> MUST be a string containing a colon separated list of the special capabilities the
|
|
client possesses. e.g. <span class="monospaced">:dirty:switch:progress:</span></p></div>
|
|
<div class="paragraph"><p><span class="monospaced">executable_name</span> MUST be the executable name that the program was launched with. For C programs,
|
|
this is simply the value of <span class="monospaced">argv[0]</span>. Note that hardcoding the name of the program here is not the
|
|
same as using, as the user may have launched the program from a script with a different name using
|
|
exec, or have created a symlink to the program. Getting the correct value in scripting languages
|
|
like Python can be more challenging.</p></div>
|
|
<table class="tableblock frame-all grid-all"
|
|
style="
|
|
width:100%;
|
|
">
|
|
<caption class="title">Table 1. Available Client Capabilities</caption>
|
|
<col style="width:50%;">
|
|
<col style="width:50%;">
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Name</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Description</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">switch</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">client is capable of responding to multiple <span class="monospaced">open</span> messages without restarting</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">dirty</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">client knows when it has unsaved changes</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">progress</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">client can send progress updates during time-consuming operations</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">message</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">client can send textual status updates</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">optional-gui</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">client has an optional GUI</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="sect4">
|
|
<h5 id="_response">Response</h5>
|
|
<div class="paragraph"><p>The server will respond to the client’s announce message with the following message:</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/reply "/nsm/server/announce" s:message s:name_of_session_manager s:capabilities</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p><span class="monospaced">message</span> is a welcome message.</p></div>
|
|
<div class="paragraph"><p>The value of <span class="monospaced">name_of_session_manager</span> will depend on the implementation of the NSM server. It might
|
|
say "Non Session Manager", or it might say "LADISH". This is for display to the user.</p></div>
|
|
<div class="paragraph"><p><span class="monospaced">capabilities</span> will be a string containing a colon separated list of special server capabilities.</p></div>
|
|
<div class="paragraph"><p>Presently, the server <span class="monospaced">capabilities</span> are:</p></div>
|
|
<table class="tableblock frame-all grid-all"
|
|
style="
|
|
width:100%;
|
|
">
|
|
<caption class="title">Table 2. Available Server Capabilities</caption>
|
|
<col style="width:50%;">
|
|
<col style="width:50%;">
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Name</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Description</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">server-control</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">client-to-server control</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">broadcast</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">server responds to /nsm/server/broadcast message</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">optional-gui</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">server responds to optional-gui messages—if this capability is not present then clients with optional-guis MUST always keep them visible</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="paragraph"><p>A client should not consider itself to be under session management until it receives this response.
|
|
For example, the Non applications activate their "SM" blinkers at this time.</p></div>
|
|
<div class="paragraph"><p>If there is an error, a reply of the following form will be sent to the client:</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/error "/nsm/server/announce" i:error_code s:error_message</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>The following table defines possible values of <span class="monospaced">error_code</span>:</p></div>
|
|
<table class="tableblock frame-all grid-all"
|
|
style="
|
|
width:100%;
|
|
">
|
|
<caption class="title">Table 3. Response codes</caption>
|
|
<col style="width:50%;">
|
|
<col style="width:50%;">
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Code</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Meaning</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_GENERAL</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">General Error</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_INCOMPATIBLE_API</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Incompatible API version</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_BLACKLISTED</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Client has been blacklisted.</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_server_to_client_control_messages">Server to Client Control Messages</h3>
|
|
<div class="paragraph"><p>Compliant clients MUST accept the client control messages described in this section. All client
|
|
control messages REQUIRE a response. Responses MUST be delivered back to the sender (NSM) from the
|
|
same socket used by the client in its <span class="monospaced">announce</span> message (by using <span class="monospaced">lo_send_from</span>) AFTER the action has
|
|
been completed or if an error is encountered. The required response is described in the subsection
|
|
for each message.</p></div>
|
|
<div class="paragraph"><p>If there is an error and the action cannot be completed, then <span class="monospaced">error_code</span> MUST be set to a valid
|
|
error code (see <a href="#Error Code Definitions">[Error Code Definitions]</a>) and <span class="monospaced">message</span> to a string describing the problem
|
|
(suitable for display to the user).</p></div>
|
|
<div class="paragraph"><p>The reply can take one of the following two forms, where path MUST be the <span class="monospaced">path</span> of the message being
|
|
replied to (e.g. "nsm/client/save":</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/reply s:path s:message</pre>
|
|
</div></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/error s:path i:error_code s:message</pre>
|
|
</div></div>
|
|
<div class="sect3">
|
|
<h4 id="_quit">Quit</h4>
|
|
<div class="paragraph"><p>There is no message for this. Clients will receive the Unix SIGTERM signal and MUST close cleanly
|
|
IMMEDIATELY, without displaying any kind of dialog to the user and regardless of whether or not
|
|
unsaved changes would be lost. When a session is closed the application will receive this signal
|
|
soon after having responded to a <span class="monospaced">save</span> message.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_open_2">Open</h4>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/open s:path_to_instance_specific_project s:display_name s:client_id</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p><span class="monospaced">path_to_instance_specific_project</span> is a path name assigned to the client for storing its project
|
|
data.</p></div>
|
|
<div class="paragraph"><p>The client may append to the path, creating a sub-directory, e.g. <em>/song.foo</em> or simply append the
|
|
client’s native file extension (e.g. <em>.non</em> or <em>.XML</em>). The same transformation MUST be applied to
|
|
the name when opening an existing project, as NSM will only provide the instance specific part of
|
|
the path.</p></div>
|
|
<div class="paragraph"><p>If a project exists at the path, the client MUST immediately open it.</p></div>
|
|
<div class="paragraph"><p>If a project does not exist at the path, then the client MUST immediately create and open a new one
|
|
at the specified path or, for clients which hold all their state in memory, store the path for
|
|
later use when responding to the <span class="monospaced">save</span> message.</p></div>
|
|
<div class="paragraph"><p>No file or directory will be created at the specified path by the server. It is up to the client to
|
|
create what it needs.</p></div>
|
|
<div class="paragraph"><p>For clients which HAVE NOT specified the <span class="monospaced">:switch:</span> capability, the <span class="monospaced">open</span> message will only be
|
|
delivered once, immediately following the <span class="monospaced">announce</span> response.</p></div>
|
|
<div class="paragraph"><p>For clients which HAVE specified the <span class="monospaced">:switch:</span> capability, the client MUST immediately switch to the
|
|
specified project or create a new one if it doesn’t exist.</p></div>
|
|
<div class="paragraph"><p>Clients which are incapable of switching projects or are prone to crashing upon switching MUST NOT
|
|
include <span class="monospaced">:switch:</span> in their capability string.</p></div>
|
|
<div class="paragraph"><p>If the user the is allowed to run two or more instances of the application simultaneously (that is
|
|
to say, there is no technical limitation preventing them from doing so, even if it doesn’t make
|
|
sense to the author), then such an application MUST PRE-PEND the provided <span class="monospaced">client_id</span> string to any
|
|
names it registers with common subsystems (e.g. JACK client names). This ensures that multiple
|
|
instances of the same application can be restored in any order without scrambling the JACK
|
|
connections or causing other conflicts. The provided <span class="monospaced">client_id</span> will be a concatenation of the value
|
|
of <span class="monospaced">application_name</span> sent by the client in its <span class="monospaced">announce</span> message and a unique identifier. Therefore,
|
|
applications which create single JACK clients can use the value of <span class="monospaced">client_id</span> directly as their JACK
|
|
client name. Applications which register multiple JACK clients (e.g. Non-Mixer) MUST PRE-PEND
|
|
<span class="monospaced">client_id</span> value to the client names they register with JACK and the application determined part
|
|
MUST be unique for that (JACK) client.</p></div>
|
|
<div class="paragraph"><p>For example, a suitable JACK client name would be: <span class="monospaced">$CLIENT_ID/track-1</span></p></div>
|
|
<div class="paragraph"><p>Note that this means that the application MUST NOT register with JACK (or any
|
|
other subsystem requiring unique names) until it receives an <span class="monospaced">open</span> message from NSM. Likewise,
|
|
applications with the <span class="monospaced">:switch:</span> capability should close their JACK clients and re-create them with
|
|
using the new <span class="monospaced">client_id</span>. Re-registering is necessary because the JACK API does currently support
|
|
renaming existing clients, although this is a sorely needed addition.</p></div>
|
|
<div class="paragraph"><p>A response is REQUIRED as soon as the open operation has been completed. Ongoing progress may be
|
|
indicated by sending messages to <span class="monospaced">/nsm/client/progress</span>.</p></div>
|
|
<div class="sect4">
|
|
<h5 id="_response_2">Response</h5>
|
|
<div class="paragraph"><p>The client MUST respond to the <em>open</em> message with:</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/reply "/nsm/client/open" s:message</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>Or</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/error "/nsm/client/open" i:error_code s:message</pre>
|
|
</div></div>
|
|
<table class="tableblock frame-all grid-all"
|
|
style="
|
|
width:100%;
|
|
">
|
|
<caption class="title">Table 4. Response codes</caption>
|
|
<col style="width:50%;">
|
|
<col style="width:50%;">
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Code</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Meaning</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">General Error</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_BAD_PROJECT</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">An existing project file was found to be corrupt</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_CREATE_FAILED</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">A new project could not be created</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_UNSAVED_CHANGES</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Unsaved changes would be lost</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_NOT_NOW</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Operation cannot be completed at this time</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_save_2">Save</h4>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/save</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>This message will only be delivered after a previous <span class="monospaced">open</span> message, and may be sent any number of
|
|
times within the course of a session (including zero, if the user aborts the session).</p></div>
|
|
<div class="sect4">
|
|
<h5 id="_response_3">Response</h5>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/reply "/nsm/client/save" s:message</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>Or</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/error "/nsm/client/save" i:error_code s:message</pre>
|
|
</div></div>
|
|
<table class="tableblock frame-all grid-all"
|
|
style="
|
|
width:100%;
|
|
">
|
|
<caption class="title">Table 5. Response codes</caption>
|
|
<col style="width:50%;">
|
|
<col style="width:50%;">
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Code</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Meaning</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">General Error</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_SAVE_FAILED</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Project could not be saved</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_NOT_NOW</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Operation cannot be completed at this time</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_server_to_client_informational_messages">Server to Client Informational Messages</h3>
|
|
<div class="sect3">
|
|
<h4 id="_session_is_loaded">Session is Loaded</h4>
|
|
<div class="paragraph"><p>Accepting this message is optional. The intent is to signal to clients which may have some
|
|
interdependence (say, peer to peer OSC connections) that the session is fully loaded and all their
|
|
peers are available. Most clients will not need to act on this message. This message has no meaning
|
|
when a session is being built or run—only when it is initially loaded. Clients who intend to act
|
|
on this message MUST not do so by delaying initialization waiting for it.</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/session_is_loaded</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>This message does not require a response.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_show_optional_gui">Show Optional Gui</h4>
|
|
<div class="paragraph"><p>If the client has specified the <span class="monospaced">optional-gui</span> capability, then it may receive this message from the
|
|
server when the user wishes to change the visibility state of the GUI. It doesn’t matter if the
|
|
optional GUI is integrated with the program or if it is a separate program \(as is the case with
|
|
SooperLooper\). When the GUI is hidden, there should be no window mapped and if the GUI is a
|
|
separate program, it should be killed.</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/show_optional_gui</pre>
|
|
</div></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/hide_optional_gui</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>No response is message is required.</p></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_client_to_server_informational_messages">Client to Server Informational Messages</h3>
|
|
<div class="sect3">
|
|
<h4 id="_optional_gui">Optional GUI</h4>
|
|
<div class="paragraph"><p>If the client has specified the <span class="monospaced">optional-gui</span> capability, then it MUST send this message whenever
|
|
the state of visibility of the optional GUI has changed. It also MUST send this message after it’s
|
|
announce message to indicate the initial visibility state of the optional GUI.</p></div>
|
|
<div class="paragraph"><p>It is the responsibility of the client to remember the visibility state of its GUI across session
|
|
loads.</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/gui_is_hidden</pre>
|
|
</div></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/gui_is_shown</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>No response will be delivered.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_progress">Progress</h4>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/progress f:progress</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>For potentially time-consuming operations, such as <span class="monospaced">save</span> and <span class="monospaced">open</span>, progress updates may be
|
|
indicated throughout the duration by sending a floating point value between 0.0 and 1.0, 1.0
|
|
indicating completion, to the NSM server.</p></div>
|
|
<div class="paragraph"><p>The server will not send a response to these messages, but will relay the information to the user.</p></div>
|
|
<div class="paragraph"><p>Note that even when using the <span class="monospaced">progress</span> feature, the final response to the <span class="monospaced">save</span> or <span class="monospaced">open</span>
|
|
message is still REQUIRED.</p></div>
|
|
<div class="paragraph"><p>Clients which intend to send progress messages should include <span class="monospaced">:progress:</span> in their <span class="monospaced">announce</span>
|
|
capability string.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_dirtiness">Dirtiness</h4>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/is_dirty</pre>
|
|
</div></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/is_clean</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>Some clients may be able to inform the server when they have unsaved changes pending. Such clients
|
|
may optionally send <span class="monospaced">is_dirty</span> and <span class="monospaced">is_clean</span> messages.</p></div>
|
|
<div class="paragraph"><p>Clients which have this capability should include <span class="monospaced">:dirty:</span> in their <span class="monospaced">announce</span> capability string.</p></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_status_messsages">Status Messsages</h4>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/client/message i:priority s:message</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>Clients may send miscellaneous status updates to the server for possible display to the user. This
|
|
may simply be chatter that is normally written to the console. <span class="monospaced">priority</span> should be a number from 0
|
|
to 3, 3 being the most important.</p></div>
|
|
<div class="paragraph"><p>Clients which have this capability should include <span class="monospaced">:message:</span> in their <span class="monospaced">announce</span> capability
|
|
string.</p></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_error_code_definitions">Error Code Definitions</h3>
|
|
<table class="tableblock frame-all grid-all"
|
|
style="
|
|
width:100%;
|
|
">
|
|
<caption class="title">Table 6. Error Code Definitions</caption>
|
|
<col style="width:50%;">
|
|
<col style="width:50%;">
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Symbolic Name</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Integer Value</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_GENERAL</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-1</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_INCOMPATIBLE_API</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-2</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_BLACKLISTED</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-3</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_LAUNCH_FAILED</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-4</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_NO_SUCH_FILE</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-5</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_NO_SESSION_OPEN</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-6</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_UNSAVED_CHANGES</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-7</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_NOT_NOW</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-8</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_BAD_PROJECT</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-9</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_CREATE_FAILED</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">-10</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_client_to_server_control">Client to Server Control</h3>
|
|
<div class="paragraph"><p>If the server publishes the <span class="monospaced">:server-control:</span> capability, then clients can also initiate action by
|
|
the server. For example, a client might implement a <em>Save All</em> option which sends a
|
|
<span class="monospaced">/nsm/server/save</span> message to the server, rather than requiring the user to switch to the session
|
|
management interface to effect the save.</p></div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_server_control_api">Server Control API</h3>
|
|
<div class="paragraph"><p>The session manager not only manages clients via OSC, but it is itself controlled via OSC messages.
|
|
The server responds to the following messages.</p></div>
|
|
<div class="paragraph"><p>All of the following messages will be responded to, at the sender’s address, with one of the two
|
|
following messages:</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/reply s:path s:message</pre>
|
|
</div></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/error s:path i:error_code s:message</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>The first parameter of the reply is the path to the message being replied to. The <span class="monospaced">/error</span> reply
|
|
includes an integer error code (non-zero indicates error). <span class="monospaced">message</span> will be a description of the
|
|
error.</p></div>
|
|
<div class="paragraph"><p>The possible errors are:</p></div>
|
|
<table class="tableblock frame-all grid-all"
|
|
style="
|
|
width:100%;
|
|
">
|
|
<caption class="title">Table 7. Responses</caption>
|
|
<col style="width:50%;">
|
|
<col style="width:50%;">
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Code</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Meaning</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_GENERAL</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">General Error</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_LAUNCH_FAILED</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Launch failed</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_NO_SUCH_FILE</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">No such file</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_NO_SESSION</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">No session is open</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">ERR_UNSAVED_CHANGES</p></td>
|
|
<td class="tableblock halign-left valign-top" ><p class="tableblock">Unsaved changes would be lost</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="sect3">
|
|
<h4 id="_add">Add</h4>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
<span class="monospaced">/nsm/server/add s:executable_name</span>
|
|
</p>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Adds a client to the current session.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_save_3">Save</h4>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
<span class="monospaced">/nsm/server/save</span>
|
|
</p>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Saves the current session.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_open_3">Open</h4>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
<span class="monospaced">/nsm/server/open s:project_name</span>
|
|
</p>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Saves the current session and loads a new session.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_open_4">Open</h4>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
<span class="monospaced">/nsm/server/new s:project_name</span>
|
|
</p>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Saves the current session and creates a new session.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_duplicate">Duplicate</h4>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
<span class="monospaced">/nsm/server/duplicate s:new_project</span>
|
|
</p>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Saves and closes the current session, makes a copy, and opens it.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_close">Close</h4>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
<span class="monospaced">/nsm/server/close</span>
|
|
</p>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Saves and closes the current session.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_abort">Abort</h4>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
<span class="monospaced">/nsm/server/abort</span>
|
|
</p>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Closes the current session WITHOUT SAVING
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_quit_2">Quit</h4>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
<span class="monospaced">/nsm/server/quit</span>
|
|
</p>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Saves and closes the current session and terminates the server.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="_list_projects">List projects</h4>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
<span class="monospaced">/nsm/server/list</span>
|
|
</p>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Lists available projects. One <span class="monospaced">/reply</span> message will be sent for each existing project.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="_client_to_client_communication">Client to Client Communication</h3>
|
|
<div class="paragraph"><p>If the server includes <span class="monospaced">:broadcast:</span> in its capability string, then clients may send broadcast
|
|
messages to each other through the NSM server. Clients may send messages to the server at the path
|
|
<span class="monospaced">/nsm/server/broadcast</span>.</p></div>
|
|
<div class="paragraph"><p>The format of this message is as follows:</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/server/broadcast s:path [arguments...]</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>The message will then be relayed to all clients in the session at the path <span class="monospaced">path</span> (with the
|
|
arguments shifted by one).</p></div>
|
|
<div class="paragraph"><p>For example the message:</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/nsm/server/broadcast /tempomap/update "0,120,4/4:12351234,240,4/4"</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>Would broadcast the following message to all clients in the session (except for the sender), some
|
|
of which might respond to the message by updating their own tempo maps.</p></div>
|
|
<div class="listingblock">
|
|
<div class="content monospaced">
|
|
<pre>/tempomap/update "0,120,4/4:12351234,240,4/4"</pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>The Non programs use this feature to establish peer to peer OSC communication by symbolic names
|
|
(client IDs) without having to remember the OSC URLs of peers across sessions.</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="footnotes"><hr></div>
|
|
<div id="footer">
|
|
<div id="footer-text">
|
|
Last updated
|
|
2022-09-18 14:06:45 EEST
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|