ladi-website/nsm-proto.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&#8217;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&#8217;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&#8212;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&#8217;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&#8217;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&#8217;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&#8212;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&#8217;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&#8217;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&#8217;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>