|
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="generator" content="Asciidoctor 2.0.17">
- <meta name="author" content="Jonathan Moore Liles, Nils Hilbricht">
- <title>New Session Manager - API</title>
- <style>
- /*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
- /* Uncomment the following line when using as a custom stylesheet */
- /* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
- html{font-family:sans-serif;-webkit-text-size-adjust:100%}
- a{background:none}
- a:focus{outline:thin dotted}
- a:active,a:hover{outline:0}
- h1{font-size:2em;margin:.67em 0}
- b,strong{font-weight:bold}
- abbr{font-size:.9em}
- abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
- dfn{font-style:italic}
- hr{height:0}
- mark{background:#ff0;color:#000}
- code,kbd,pre,samp{font-family:monospace;font-size:1em}
- pre{white-space:pre-wrap}
- q{quotes:"\201C" "\201D" "\2018" "\2019"}
- small{font-size:80%}
- sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
- sup{top:-.5em}
- sub{bottom:-.25em}
- img{border:0}
- svg:not(:root){overflow:hidden}
- figure{margin:0}
- audio,video{display:inline-block}
- audio:not([controls]){display:none;height:0}
- fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
- legend{border:0;padding:0}
- button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
- button,input{line-height:normal}
- button,select{text-transform:none}
- button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
- button[disabled],html input[disabled]{cursor:default}
- input[type=checkbox],input[type=radio]{padding:0}
- button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
- textarea{overflow:auto;vertical-align:top}
- table{border-collapse:collapse;border-spacing:0}
- *,::before,::after{box-sizing:border-box}
- html,body{font-size:100%}
- body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
- a:hover{cursor:pointer}
- img,object,embed{max-width:100%;height:auto}
- object,embed{height:100%}
- img{-ms-interpolation-mode:bicubic}
- .left{float:left!important}
- .right{float:right!important}
- .text-left{text-align:left!important}
- .text-right{text-align:right!important}
- .text-center{text-align:center!important}
- .text-justify{text-align:justify!important}
- .hide{display:none}
- img,object,svg{display:inline-block;vertical-align:middle}
- textarea{height:auto;min-height:50px}
- select{width:100%}
- .subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
- div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
- a{color:#2156a5;text-decoration:underline;line-height:inherit}
- a:hover,a:focus{color:#1d4b8f}
- a img{border:0}
- p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
- p aside{font-size:.875em;line-height:1.35;font-style:italic}
- h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
- h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
- h1{font-size:2.125em}
- h2{font-size:1.6875em}
- h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
- h4,h5{font-size:1.125em}
- h6{font-size:1em}
- hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
- em,i{font-style:italic;line-height:inherit}
- strong,b{font-weight:bold;line-height:inherit}
- small{font-size:60%;line-height:inherit}
- code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
- ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
- ul,ol{margin-left:1.5em}
- ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
- ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
- ul.square{list-style-type:square}
- ul.circle{list-style-type:circle}
- ul.disc{list-style-type:disc}
- ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
- dl dt{margin-bottom:.3125em;font-weight:bold}
- dl dd{margin-bottom:1.25em}
- blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
- blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
- @media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
- h1{font-size:2.75em}
- h2{font-size:2.3125em}
- h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
- h4{font-size:1.4375em}}
- table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
- table thead,table tfoot{background:#f7f8f7}
- table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
- table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
- table tr.even,table tr.alt{background:#f8f8f7}
- table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
- h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
- h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
- .center{margin-left:auto;margin-right:auto}
- .stretch{width:100%}
- .clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
- .clearfix::after,.float-group::after{clear:both}
- :not(pre).nobreak{word-wrap:normal}
- :not(pre).nowrap{white-space:nowrap}
- :not(pre).pre-wrap{white-space:pre-wrap}
- :not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
- pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
- pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
- pre>code{display:block}
- pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
- em em{font-style:normal}
- strong strong{font-weight:400}
- .keyseq{color:rgba(51,51,51,.8)}
- kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
- .keyseq kbd:first-child{margin-left:0}
- .keyseq kbd:last-child{margin-right:0}
- .menuseq,.menuref{color:#000}
- .menuseq b:not(.caret),.menuref{font-weight:inherit}
- .menuseq{word-spacing:-.02em}
- .menuseq b.caret{font-size:1.25em;line-height:.8}
- .menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
- b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
- b.button::before{content:"[";padding:0 3px 0 2px}
- b.button::after{content:"]";padding:0 2px 0 3px}
- p a>code:hover{color:rgba(0,0,0,.9)}
- #header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
- #header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
- #header::after,#content::after,#footnotes::after,#footer::after{clear:both}
- #content{margin-top:1.25em}
- #content::before{content:none}
- #header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
- #header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
- #header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
- #header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
- #header .details span:first-child{margin-left:-.125em}
- #header .details span.email a{color:rgba(0,0,0,.85)}
- #header .details br{display:none}
- #header .details br+span::before{content:"\00a0\2013\00a0"}
- #header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
- #header .details br+span#revremark::before{content:"\00a0|\00a0"}
- #header #revnumber{text-transform:capitalize}
- #header #revnumber::after{content:"\00a0"}
- #content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
- #toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
- #toc>ul{margin-left:.125em}
- #toc ul.sectlevel0>li>a{font-style:italic}
- #toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
- #toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
- #toc li{line-height:1.3334;margin-top:.3334em}
- #toc a{text-decoration:none}
- #toc a:active{text-decoration:underline}
- #toctitle{color:#7a2518;font-size:1.2em}
- @media screen and (min-width:768px){#toctitle{font-size:1.375em}
- body.toc2{padding-left:15em;padding-right:0}
- #toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
- #toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
- #toc.toc2>ul{font-size:.9em;margin-bottom:0}
- #toc.toc2 ul ul{margin-left:0;padding-left:1em}
- #toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
- body.toc2.toc-right{padding-left:0;padding-right:15em}
- body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
- @media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
- #toc.toc2{width:20em}
- #toc.toc2 #toctitle{font-size:1.375em}
- #toc.toc2>ul{font-size:.95em}
- #toc.toc2 ul ul{padding-left:1.25em}
- body.toc2.toc-right{padding-left:0;padding-right:20em}}
- #content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
- #content #toc>:first-child{margin-top:0}
- #content #toc>:last-child{margin-bottom:0}
- #footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
- #footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
- #content{margin-bottom:.625em}
- .sect1{padding-bottom:.625em}
- @media screen and (min-width:768px){#content{margin-bottom:1.25em}
- .sect1{padding-bottom:1.25em}}
- .sect1:last-child{padding-bottom:0}
- .sect1+.sect1{border-top:1px solid #e7e7e9}
- #content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
- #content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
- #content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
- #content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
- #content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
- details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
- details{margin-left:1.25rem}
- details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
- details>summary::-webkit-details-marker{display:none}
- details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
- details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
- details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
- .admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
- table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
- .paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
- .admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
- .admonitionblock>table td.icon{text-align:center;width:80px}
- .admonitionblock>table td.icon img{max-width:none}
- .admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
- .admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
- .admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
- .exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
- .exampleblock>.content>:first-child{margin-top:0}
- .exampleblock>.content>:last-child{margin-bottom:0}
- .sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
- .sidebarblock>:first-child{margin-top:0}
- .sidebarblock>:last-child{margin-bottom:0}
- .sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
- .exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
- .literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
- @media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
- @media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
- .literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
- .literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
- .listingblock>.content{position:relative}
- .listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
- .listingblock:hover code[data-lang]::before{display:block}
- .listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
- .listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
- .listingblock pre.highlightjs{padding:0}
- .listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
- .listingblock pre.prettyprint{border-width:0}
- .prettyprint{background:#f7f7f8}
- pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
- pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
- pre.prettyprint li code[data-lang]::before{opacity:1}
- pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
- table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
- table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
- table.linenotable td.code{padding-left:.75em}
- table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
- pre.pygments span.linenos{display:inline-block;margin-right:.75em}
- .quoteblock{margin:0 1em 1.25em 1.5em;display:table}
- .quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
- .quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
- .quoteblock blockquote{margin:0;padding:0;border:0}
- .quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
- .quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
- .quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
- .verseblock{margin:0 1em 1.25em}
- .verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
- .verseblock pre strong{font-weight:400}
- .verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
- .quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
- .quoteblock .attribution br,.verseblock .attribution br{display:none}
- .quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
- .quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
- .quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
- .quoteblock.abstract{margin:0 1em 1.25em;display:block}
- .quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
- .quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
- .quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
- .quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
- .quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
- p.tableblock:last-child{margin-bottom:0}
- td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
- td.tableblock>.content>:last-child{margin-bottom:-1.25em}
- table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
- table.grid-all>*>tr>*{border-width:1px}
- table.grid-cols>*>tr>*{border-width:0 1px}
- table.grid-rows>*>tr>*{border-width:1px 0}
- table.frame-all{border-width:1px}
- table.frame-ends{border-width:1px 0}
- table.frame-sides{border-width:0 1px}
- table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
- table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
- table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
- table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
- table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
- th.halign-left,td.halign-left{text-align:left}
- th.halign-right,td.halign-right{text-align:right}
- th.halign-center,td.halign-center{text-align:center}
- th.valign-top,td.valign-top{vertical-align:top}
- th.valign-bottom,td.valign-bottom{vertical-align:bottom}
- th.valign-middle,td.valign-middle{vertical-align:middle}
- table thead th,table tfoot th{font-weight:bold}
- tbody tr th{background:#f7f8f7}
- tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
- p.tableblock>code:only-child{background:none;padding:0}
- p.tableblock{font-size:1em}
- ol{margin-left:1.75em}
- ul li ol{margin-left:1.5em}
- dl dd{margin-left:1.125em}
- dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
- li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
- ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
- ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
- ul.unstyled,ol.unstyled{margin-left:0}
- li>p:empty:only-child::before{content:"";display:inline-block}
- ul.checklist>li>p:first-child{margin-left:-1em}
- ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
- ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
- ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
- ul.inline>li{margin-left:1.25em}
- .unstyled dl dt{font-weight:400;font-style:normal}
- ol.arabic{list-style-type:decimal}
- ol.decimal{list-style-type:decimal-leading-zero}
- 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}
- ol.lowergreek{list-style-type:lower-greek}
- .hdlist>table,.colist>table{border:0;background:none}
- .hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
- td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
- td.hdlist1{font-weight:bold;padding-bottom:1.25em}
- td.hdlist2{word-wrap:anywhere}
- .literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
- .colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
- .colist td:not([class]):first-child img{max-width:none}
- .colist td:not([class]):last-child{padding:.25em 0}
- .thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
- .imageblock.left{margin:.25em .625em 1.25em 0}
- .imageblock.right{margin:.25em 0 1.25em .625em}
- .imageblock>.title{margin-bottom:0}
- .imageblock.thumb,.imageblock.th{border-width:6px}
- .imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
- .image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
- .image.left{margin-right:.625em}
- .image.right{margin-left:.625em}
- a.image{text-decoration:none;display:inline-block}
- a.image object{pointer-events:none}
- sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
- sup.footnote a,sup.footnoteref a{text-decoration:none}
- sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
- #footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
- #footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
- #footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
- #footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
- #footnotes .footnote:last-of-type{margin-bottom:0}
- #content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
- div.unbreakable{page-break-inside:avoid}
- .big{font-size:larger}
- .small{font-size:smaller}
- .underline{text-decoration:underline}
- .overline{text-decoration:overline}
- .line-through{text-decoration:line-through}
- .aqua{color:#00bfbf}
- .aqua-background{background:#00fafa}
- .black{color:#000}
- .black-background{background:#000}
- .blue{color:#0000bf}
- .blue-background{background:#0000fa}
- .fuchsia{color:#bf00bf}
- .fuchsia-background{background:#fa00fa}
- .gray{color:#606060}
- .gray-background{background:#7d7d7d}
- .green{color:#006000}
- .green-background{background:#007d00}
- .lime{color:#00bf00}
- .lime-background{background:#00fa00}
- .maroon{color:#600000}
- .maroon-background{background:#7d0000}
- .navy{color:#000060}
- .navy-background{background:#00007d}
- .olive{color:#606000}
- .olive-background{background:#7d7d00}
- .purple{color:#600060}
- .purple-background{background:#7d007d}
- .red{color:#bf0000}
- .red-background{background:#fa0000}
- .silver{color:#909090}
- .silver-background{background:#bcbcbc}
- .teal{color:#006060}
- .teal-background{background:#007d7d}
- .white{color:#bfbfbf}
- .white-background{background:#fafafa}
- .yellow{color:#bfbf00}
- .yellow-background{background:#fafa00}
- span.icon>.fa{cursor:default}
- a span.icon>.fa{cursor:inherit}
- .admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
- .admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
- .admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
- .admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
- .admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
- .admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
- .conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
- .conum[data-value] *{color:#fff!important}
- .conum[data-value]+b{display:none}
- .conum[data-value]::after{content:attr(data-value)}
- pre .conum[data-value]{position:relative;top:-.125em}
- b.conum *{color:inherit!important}
- .conum:not([data-value]):empty{display:none}
- dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
- h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
- p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
- p,blockquote,dt,td.content,span.alt,summary{font-size:1.0625rem}
- p{margin-bottom:1.25rem}
- .sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
- .exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
- .print-only{display:none!important}
- @page{margin:1.25cm .75cm}
- @media print{*{box-shadow:none!important;text-shadow:none!important}
- html{font-size:80%}
- a{color:inherit!important;text-decoration:underline!important}
- a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
- a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
- abbr[title]{border-bottom:1px dotted}
- abbr[title]::after{content:" (" attr(title) ")"}
- pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
- thead{display:table-header-group}
- svg{max-width:100%}
- p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
- h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
- #header,#content,#footnotes,#footer{max-width:none}
- #toc,.sidebarblock,.exampleblock>.content{background:none!important}
- #toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
- body.book #header{text-align:center}
- body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
- body.book #header .details{border:0!important;display:block;padding:0!important}
- body.book #header .details span:first-child{margin-left:0!important}
- body.book #header .details br{display:block}
- body.book #header .details br+span::before{content:none!important}
- body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
- body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
- .listingblock code[data-lang]::before{display:block}
- #footer{padding:0 .9375em}
- .hide-on-print{display:none!important}
- .print-only{display:block!important}
- .hide-for-print{display:none!important}
- .show-for-print{display:inherit!important}}
- @media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
- .sect1{padding:0!important}
- .sect1+.sect1{border:0}
- #footer{background:none}
- #footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
- @media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
- </style>
- </head>
- <body class="article">
- <div id="header">
- <h1>New Session Manager - API</h1>
- <div class="details">
- <span id="author" class="author">Jonathan Moore Liles, Nils Hilbricht</span><br>
- <span id="revnumber">version API 1.1.2</span>
- <br><span id="revremark">License CC-By-SA v2.5</span>
- </div>
- <div id="toc" class="toc">
- <div id="toctitle">Table of Contents</div>
- <ul class="sectlevel1">
- <li><a href="#_client_behavior_under_session_management">1. Client Behavior Under Session Management</a>
- <ul class="sectlevel2">
- <li><a href="#_file_menu">1.1. File Menu</a>
- <ul class="sectlevel3">
- <li><a href="#_new">1.1.1. New</a></li>
- <li><a href="#_open">1.1.2. Open</a></li>
- <li><a href="#_save">1.1.3. Save</a></li>
- <li><a href="#_save_as">1.1.4. Save As</a></li>
- <li><a href="#_close_as_distinguished_from_quit_or_exit">1.1.5. Close (as distinguished from Quit or Exit)</a></li>
- <li><a href="#_quit_or_exit">1.1.6. Quit or Exit</a></li>
- </ul>
- </li>
- <li><a href="#_data_storage">1.2. Data Storage</a>
- <ul class="sectlevel3">
- <li><a href="#_internal_files">1.2.1. Internal Files</a></li>
- <li><a href="#_external_files">1.2.2. External Files</a></li>
- <li><a href="#_session_root_and_session_directories">1.2.3. Session Root and Session Directories</a>
- <ul class="sectlevel4">
- <li><a href="#_subdirectories_hierarchical_structure">1.2.3.1. Subdirectories / Hierarchical Structure</a></li>
- <li><a href="#_write_protection_for_session_templates">1.2.3.2. Write-Protection for Session Templates</a></li>
- <li><a href="#_lockfiles">1.2.3.3. Lockfiles</a></li>
- <li><a href="#_daemon_discovery">1.2.3.4. Daemon Discovery</a></li>
- </ul>
- </li>
- </ul>
- </li>
- </ul>
- </li>
- <li><a href="#_nsm_osc_protocol">2. NSM OSC Protocol</a>
- <ul class="sectlevel2">
- <li><a href="#_establishing_a_connection">2.1. Establishing a Connection</a>
- <ul class="sectlevel3">
- <li><a href="#_announce">2.1.1. Announce</a></li>
- <li><a href="#_response">2.1.2. Response</a></li>
- </ul>
- </li>
- <li><a href="#_server_to_client_control_messages">2.2. Server to Client Control Messages</a>
- <ul class="sectlevel3">
- <li><a href="#_quit">2.2.1. Quit</a></li>
- <li><a href="#server-to-client-control-messages-open">2.2.2. Open</a>
- <ul class="sectlevel4">
- <li><a href="#_response_2">2.2.2.1. Response</a></li>
- </ul>
- </li>
- <li><a href="#_save_2">2.2.3. Save</a>
- <ul class="sectlevel4">
- <li><a href="#_response_3">2.2.3.1. Response</a></li>
- </ul>
- </li>
- </ul>
- </li>
- <li><a href="#_server_to_client_informational_messages">2.3. Server to Client Informational Messages</a>
- <ul class="sectlevel3">
- <li><a href="#_session_is_loaded">2.3.1. Session is Loaded</a></li>
- <li><a href="#_show_optional_gui">2.3.2. Show Optional Gui</a></li>
- </ul>
- </li>
- <li><a href="#_client_to_server_informational_messages">2.4. Client to Server Informational Messages</a>
- <ul class="sectlevel3">
- <li><a href="#_optional_gui">2.4.1. Optional GUI</a></li>
- <li><a href="#_progress">2.4.2. Progress</a></li>
- <li><a href="#_dirtiness">2.4.3. Dirtiness</a></li>
- <li><a href="#_status_messsages">2.4.4. Status Messsages</a></li>
- </ul>
- </li>
- <li><a href="#_error_code_definitions">2.5. Error Code Definitions</a></li>
- <li><a href="#_client_to_server_control">2.6. Client to Server Control</a></li>
- <li><a href="#_server_control_api">2.7. Server Control API</a>
- <ul class="sectlevel3">
- <li><a href="#_client_to_client_communication">2.7.1. Client to Client Communication</a></li>
- </ul>
- </li>
- </ul>
- </li>
- <li><a href="#_api_versions_and_behaviour_changes">3. API Versions and Behaviour Changes</a>
- <ul class="sectlevel2">
- <li><a href="#_guidelines">3.1. Guidelines</a></li>
- <li><a href="#_changes_in_api_version_1_1_0">3.2. Changes in API Version 1.1.0</a></li>
- <li><a href="#_changes_in_api_version_1_1_1">3.3. Changes in API Version 1.1.1</a></li>
- <li><a href="#_changes_in_api_version_1_1_2">3.4. Changes in API Version 1.1.2</a></li>
- </ul>
- </li>
- </ul>
- </div>
- </div>
- <div id="content">
- <div id="preamble">
- <div class="sectionbody">
- <div class="admonitionblock important">
- <table>
- <tr>
- <td class="icon">
- <div class="title">Important</div>
- </td>
- <td class="content">
- "New Session Manager" is a community version of the
- <a href="http://non.tuxfamily.org/nsm/API.html">"Non Session Manager" by Jonathan Moore Liles</a>, who also
- wrote the majority of this API document, especially the API itself. <strong>The API is the same</strong>. Any
- technical changes or differences in behaviour are described in <a href="#_api_versions_and_behaviour_changes">API Versions and Behaviour Changes</a>.
- All other changes to this document can be reviewed by accessing the git log. This document is
- licensed under CC-By-Sa v2.5. See <a href="https://github.com/jackaudio/new-session-manager/tree/master/docs/src/api">LICENSE</a>
- </td>
- </tr>
- </table>
- </div>
- <div class="admonitionblock important">
- <table>
- <tr>
- <td class="icon">
- <div class="title">Important</div>
- </td>
- <td class="content">
- The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD
- NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as
- described in <a href="https://tools.ietf.org/html/rfc2119">RFC 2119</a>.
- </td>
- </tr>
- </table>
- </div>
- <div class="paragraph">
- <p>The "New Session Manager"-API is used by many music and audio programs in Linux distributions
- 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>This project contains a program called <code>nsmd</code> which is an implementation of the server side of
- the NSM API. <code>nsmd</code> can be controlled by direct OSC messages, or (more commonly) a GUI:
- Included in this package is the <code>nsm-legacy-gui</code>, which gets symlinked to "non-session-manager`.
- Another GUI is "Agordejo". Other applications exist that (partially) support the NSM API and are able
- to load clients, but they do not use the New-Session-Manager (or Non-Session-Manager) implementation
- and are therefore out of scope for this document.</p>
- </div>
- <div class="paragraph">
- <p>However, the same server-side API can also be implemented by other programs (such as Carla),
- although consistency and robustness will likely suffer if non-NSM compliant clients are allowed to
- participate in a session.</p>
- </div>
- <div class="paragraph">
- <p>There is no direct dependency for client implementations, as long as they
- can send and receive OSC.
- Some clients use <code>liblo</code> (the OSC library), which becomes a dependency if you choose to implement
- NSM-support with the provided header file <code>nsm.h</code> (<code>extras/nsm.h/nsm.h</code> in the git repository).
- Some clients use the provided single-file python library <code>pynsm</code> (<code>extras/pynsm/nsmclient.py</code> in the git repository)
- which has no dependencies outside the Python3 standard library.</p>
- </div>
- <div class="paragraph">
- <p>The aim of this project is to thoroughly define the behavior required of clients. Often the
- difficulty with other session-management approaches has been not in implementing code-support for
- them, but in not defining rules and behaviour clearly enough.</p>
- </div>
- <div class="paragraph">
- <p>As written above unambiguous rules are created by using RFC 2119 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">1. 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
- <code>announce</code> 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">1.1. File Menu</h3>
- <div class="sect3">
- <h4 id="_new">1.1.1. New</h4>
- <div class="paragraph">
- <p>This option MAY empty/reset the current file or project (possibly after user confirmation).
- It MUST NOT allow the user to create a new project/file in another location.</p>
- </div>
- </div>
- <div class="sect3">
- <h4 id="_open">1.1.2. Open</h4>
- <div class="paragraph">
- <p>This option MUST be disabled.</p>
- </div>
- <div class="paragraph">
- <p>The application MAY elect to implement an option called "Import into Session", which 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">1.1.3. Save</h4>
- <div class="paragraph">
- <p>This option should behave as normal, saving the current file/project as established by the NSM
- <code>open</code> message.</p>
- </div>
- <div class="paragraph">
- <p>This option MUST NOT present the user with a choice of where to save the file.</p>
- </div>
- </div>
- <div class="sect3">
- <h4 id="_save_as">1.1.4. Save As</h4>
- <div class="paragraph">
- <p>This option MUST be disabled.</p>
- </div>
- <div class="paragraph">
- <p>The application MAY elect to implement an option called 'Export from Session', 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">1.1.5. 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">1.1.6. Quit or Exit</h4>
- <div class="paragraph">
- <p>This option MAY behave as normal (possibly asking the user to confirm exiting), or MAY do nothing
- to only allow quit from the session-manager control.
- When the client supports :optional-gui: this option SHOULD be replaced with hiding the client’s GUI
- so a quit by window manager hides.</p>
- </div>
- </div>
- </div>
- <div class="sect2">
- <h3 id="_data_storage">1.2. Data Storage</h3>
- <div class="sect3">
- <h4 id="_internal_files">1.2.1. 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">1.2.2. 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 class="sect3">
- <h4 id="_session_root_and_session_directories">1.2.3. Session Root and Session Directories</h4>
- <div class="paragraph">
- <p>Client programs MUST NOT handle the following themselves. This section is background-information.</p>
- </div>
- <div class="paragraph">
- <p>NSM follows the <a href="https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG Base Directory Specifications</a></p>
- </div>
- <div class="paragraph">
- <p>All existing and new sessions are directories below the session-root, which defaults to
- <code>$XDG_DATA_HOME/nsm/</code>, which usually results in <code>$HOME/.local/share/nsm/</code>.</p>
- </div>
- <div class="paragraph">
- <p>Each session directory contains a file <code>session.nsm</code> with one client per line <code>name:executable:UID\n</code>
- For example:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight"><code>JACKPatch:jackpatch:nBEIQ
- jack_mixer:jack_mixer:nTXHV
- Carla-Rack:carla-rack:nFAOD</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p><code>nsmd</code> loads and saves this file, client names are their self-reported names.
- The file format is final and frozen. Additions or changes SHALL NOT be made.</p>
- </div>
- <div class="sect4">
- <h5 id="_subdirectories_hierarchical_structure">1.2.3.1. Subdirectories / Hierarchical Structure</h5>
- <div class="paragraph">
- <p>Subdirectories MAY be made to organize sessions into meaningful structures, such as album/track or
- composer/genre/piece. For example: <code>Johann Sebastian Bach/Kantaten/Wie schön leuchtet der Morgenstern</code>.
- Which results in the same directory structure on disk. Session names can contain any characters that
- are supported by the underlying file system, usually UTF-8.</p>
- </div>
- <div class="paragraph">
- <p>Subdirectories are created by either <code>nsmd</code> itself or by the users themselves, through their file
- manager or a GUI (while the session is not open).</p>
- </div>
- <div class="paragraph">
- <p>The project_name from <code>/nsm/server/new s:project_name</code> accepts the format <code>a/b/c/d</code>.</p>
- </div>
- <div class="paragraph">
- <p>Any session itself MUST be a "leaf" in this directory tree. A session MUST NOT contain further
- session subdirectories: any directory that contains a file <code>session.nsm</code> is the final
- element in the hierarchy.</p>
- </div>
- </div>
- <div class="sect4">
- <h5 id="_write_protection_for_session_templates">1.2.3.2. Write-Protection for Session Templates</h5>
- <div class="paragraph">
- <p>Write protection for a whole session directory can either happen by "accident" (files from
- another user, a network mount etc.) or on purpose, to protect a session template against accidental
- changes. The latter is possible with a recursive <code>chown</code>, <code>chmod</code> or <code>chattr -R +i session-dir</code>.</p>
- </div>
- <div class="paragraph">
- <p>nsmd itself just checks if <code>session.nsm</code> is read-only. In this case it will not send the save
- command to it’s session clients. This does not prevent hypothetical problems when the user
- triggers a clients internal save command in a write protected directory. Clients SHOULD handle
- their write protected save files themselves.</p>
- </div>
- <div class="paragraph">
- <p>Advanced contraptions, like overlay filesystems or copy-on-write hardlinks to create read-only
- sessions without the clients noticing, are out of scope for nsm.</p>
- </div>
- </div>
- <div class="sect4">
- <h5 id="_lockfiles">1.2.3.3. Lockfiles</h5>
- <div class="paragraph">
- <p>Because multiple <code>nsmd</code> can run at the same time we need to prevent accidental write-access to the
- same session by different nsm-daemons, and subsequently GUIs.</p>
- </div>
- <div class="paragraph">
- <p>Therefore each currently open session creates a lockfile under <code>$XDG_RUNTIME_DIR/nsm/</code> (usually
- <code>/run/user/XXXX/nsm/</code>) that tells <code>nsmd</code> to not open such a locked session. This directory gets
- cleaned by the operating system, preventing sessions to stay locked after e.g. a power failure.</p>
- </div>
- <div class="paragraph">
- <p>The lockfile is named after the simple session name combined with a numeric ID for the session
- root. It is possible that two <code>nsmd</code> opened two different session roots, both with the same simple
- session name, e.g. "my song". Lockfiles are able to distinguish between those and will not prevent
- access in this scenario. The numeric ID is a djb2 hash modulo (%) 65521 of the session root directory
- (see <code>src/file.cpp</code> function <code>simple_hash()</code>).</p>
- </div>
- <div class="paragraph">
- <p>The lockfile contains, on separate lines:</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>The absolute path to the session, including the root-dir, which could be overriden by <code>nsmd --session-root</code>, allowing two sessions of the same basic name in different roots.</p>
- </li>
- <li>
- <p>the OSC URL of the server that runs this session, the same as <code>$NSM_URL</code>.</p>
- </li>
- <li>
- <p>the PID of <code>nsmd</code></p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>Example:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight"><code>/home/johann/.local/share/nsm/cantatas/easter1751
- osc.udp://myuser.localdomain:11287/
- 3022</code></pre>
- </div>
- </div>
- </div>
- <div class="sect4">
- <h5 id="_daemon_discovery">1.2.3.4. Daemon Discovery</h5>
- <div class="paragraph">
- <p>Each running <code>nsmd</code>, per user, creates a state file under <code>$XDG_RUNTIME_DIR/nsm/d/</code> (usually
- <code>/run/user/XXXX/nsm/d/</code>) that can be used to look up running daemons, even if no session is loaded.
- The name of the file is <code>nsmd</code> PID and the files contain their daemons osc.udp URL that is
- compatible with the --nsm-url parameter of the GUI.</p>
- </div>
- <div class="paragraph">
- <p>This enables you to e.g. start nsmd at boot with a random free port. Server-control programs such
- as GUIs can then use this to look for running servers without requiring the user to look up and
- input an osc URL manually as command line parameter.</p>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="sect1">
- <h2 id="_nsm_osc_protocol">2. 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 <code>announce</code>
- message, using the <code>lo_send_from</code> 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 <code>NSM_URL</code>.
- <code>nsmd</code> itself is using UDP only.</p>
- </div>
- <div class="sect2">
- <h3 id="_establishing_a_connection">2.1. Establishing a Connection</h3>
- <div class="sect3">
- <h4 id="_announce">2.1.1. Announce</h4>
- <div class="paragraph">
- <p>At launch, the client MUST check the environment for the value of <code>NSM_URL</code>. If present, the client
- MUST send the following message to the provided address as soon as it is ready to respond to the
- <code>/nsm/client/open</code> event:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/server/announce s:application_name s:capabilities s:executable_name i:api_version_major i:api_version_minor i:pid</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>If <code>NSM_URL</code> is undefined, invalid, or unreachable, then the client should proceed assuming that
- session management is unavailable.</p>
- </div>
- <div class="paragraph">
- <p><code>api_version_major</code> and <code>api_version_minor</code> 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, <code>application_name</code> MUST be the same as
- the name that would normally be passed to <code>jack_client_open</code>. For example, Non-Mixer sends
- "Non-Mixer" as its <code>application_name</code>. Applications MUST NOT register their JACK clients until
- receiving an <code>open</code> message; the <code>open</code> 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 briefly while awaiting the <code>announce</code> reply and subsequent <code>open</code> message.</p>
- </div>
- <div class="paragraph">
- <p><code>capabilities</code> MUST be a string containing a colon separated list of the special capabilities the
- client possesses. e.g. <code>:dirty:switch:progress:</code></p>
- </div>
- <div class="paragraph">
- <p><code>executable_name</code> MUST be the executable name that the program was launched with. For C programs,
- this is simply the value of <code>argv[0]</code>. 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 stripes-even stretch">
- <caption class="title">Table 1. Available Client Capabilities</caption>
- <colgroup>
- <col style="width: 50%;">
- <col style="width: 50%;">
- </colgroup>
- <thead>
- <tr>
- <th class="tableblock halign-left valign-top">Name</th>
- <th class="tableblock halign-left valign-top">Description</th>
- </tr>
- </thead>
- <tbody>
- <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 <code>open</code> 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>
- <div class="sect3">
- <h4 id="_response">2.1.2. Response</h4>
- <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">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/reply "/nsm/server/announce" s:message s:name_of_session_manager s:capabilities</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p><code>message</code> is a welcome message.</p>
- </div>
- <div class="paragraph">
- <p>The value of <code>name_of_session_manager</code> will depend on the implementation of the NSM server. It
- might say "New Session Manager", or it might say "Non Session Manager" etc. This is for display to
- the user.</p>
- </div>
- <div class="paragraph">
- <p><code>capabilities</code> will be a string containing a colon separated list of special server capabilities.</p>
- </div>
- <div class="paragraph">
- <p>Presently, the server <code>capabilities</code> are:</p>
- </div>
- <table class="tableblock frame-all grid-all stripes-even stretch">
- <caption class="title">Table 2. Available Server Capabilities</caption>
- <colgroup>
- <col style="width: 50%;">
- <col style="width: 50%;">
- </colgroup>
- <thead>
- <tr>
- <th class="tableblock halign-left valign-top">Name</th>
- <th class="tableblock halign-left valign-top">Description</th>
- </tr>
- </thead>
- <tbody>
- <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. This capability is always present and MUST be supported by any server implementation.</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">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/error "/nsm/server/announce" i:error_code s:error_message</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The following table defines possible values of <code>error_code</code>:</p>
- </div>
- <table class="tableblock frame-all grid-all stripes-even stretch">
- <caption class="title">Table 3. Response codes</caption>
- <colgroup>
- <col style="width: 50%;">
- <col style="width: 50%;">
- </colgroup>
- <thead>
- <tr>
- <th class="tableblock halign-left valign-top">Code</th>
- <th class="tableblock halign-left valign-top">Meaning</th>
- </tr>
- </thead>
- <tbody>
- <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 class="sect2">
- <h3 id="_server_to_client_control_messages">2.2. 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 (<code>nsmd</code>) from the
- same socket used by the client in its <code>announce</code> message (by using <code>lo_send_from</code>) 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 <code>error_code</code> MUST be set to a valid
- error code (see <a href="#_error_code_definitions">Error Code Definitions</a>) and <code>message</code> 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 <code>path</code> of the message being
- replied to (e.g. "nsm/client/save":</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/reply s:path s:message</code></pre>
- </div>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/error s:path i:error_code s:message</code></pre>
- </div>
- </div>
- <div class="sect3">
- <h4 id="_quit">2.2.1. 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 <code>save</code> message.</p>
- </div>
- </div>
- <div class="sect3">
- <h4 id="server-to-client-control-messages-open">2.2.2. Open</h4>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/open s:path_to_instance_specific_project s:display_name s:client_id</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p><code>path_to_instance_specific_project</code> is a path name in the form client_name.ID, assigned to the
- client for storing its project data. The client MUST choose one of the four strategies below to
- save, so that every file in the session can be traced back to a client and, vice versa, a client
- name.ID can be used to look up all its files. (For example to clean up the session dir)</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>The client has no state and does not save at all</p>
- <div class="ulist">
- <ul>
- <li>
- <p>and it MUST NOT misuse e.g. ~/.config to save session specific information e.g. synth-instrument settings</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p>The client may use the path client_name.ID directly, resulting in a file client_name.ID in the session directory</p>
- </li>
- <li>
- <p>The client may append its native file extension (e.g. <code>.json</code>) to the path client_name.ID</p>
- </li>
- <li>
- <p>The client may use the path as directory, creating arbitrary files below, for example recorded .wav.</p>
- <div class="ulist">
- <ul>
- <li>
- <p>and it MUST NOT use the client ID below this point. This way the data stays transferable by hand to another client instance (in another session).</p>
- </li>
- <li>
- <p>best case practice is to always use the same file names, for example <code>client_name.ID/savefile.json</code></p>
- </li>
- </ul>
- </div>
- </li>
- </ul>
- </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 <code>save</code> 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 <code>:switch:</code> capability, the <code>open</code> message will only be
- delivered once, immediately following the <code>announce</code> response.</p>
- </div>
- <div class="paragraph">
- <p>For clients which HAVE specified the <code>:switch:</code> 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 <code>:switch:</code> 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
- then such an application MUST PRE-PEND the provided <code>client_id</code> string, followed by "/", 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.</p>
- </div>
- <div class="paragraph">
- <p>The provided <code>client_id</code> will be a concatenation of the value of <code>application_name</code> sent by the
- client in its <code>announce</code> message and a unique identifier.</p>
- </div>
- <div class="paragraph">
- <p>Therefore, applications which create single JACK clients can use the value of <code>client_id</code> directly
- as their JACK client name.</p>
- </div>
- <div class="paragraph">
- <p>Applications which register multiple JACK clients (e.g. Carla or Non-Mixer) MUST PRE-PEND
- <code>client_id</code> value, followed by "/", 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, Carla is a plugin-host that loads each plugin as JACK client.
- Suitable JACK client names are: <code>carla-jack-multi.nBAF/ZynAddSubFx</code> or <code>carla-jack-multi.nBAF/Helm</code>
- Please note that ZynAddSubFx and Helm are <strong>not ports</strong> but clients. Each of them can have any number
- of audio and midi ports below them.</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 <code>open</code> message from NSM. Likewise,
- applications with the <code>:switch:</code> capability should close their JACK clients and re-create them with
- using the new <code>client_id</code> (renaming JACK-clients is not possible, only ports).</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 <code>/nsm/client/progress</code>.</p>
- </div>
- <div class="sect4">
- <h5 id="_response_2">2.2.2.1. Response</h5>
- <div class="paragraph">
- <p>The client MUST respond to the 'open' message with:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/reply "/nsm/client/open" s:message</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>Or</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/error "/nsm/client/open" i:error_code s:message</code></pre>
- </div>
- </div>
- <table class="tableblock frame-all grid-all stripes-even stretch">
- <caption class="title">Table 4. Response codes</caption>
- <colgroup>
- <col style="width: 50%;">
- <col style="width: 50%;">
- </colgroup>
- <thead>
- <tr>
- <th class="tableblock halign-left valign-top">Code</th>
- <th class="tableblock halign-left valign-top">Meaning</th>
- </tr>
- </thead>
- <tbody>
- <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">2.2.3. Save</h4>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/save</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>This message will only be delivered after a previous <code>open</code> 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">2.2.3.1. Response</h5>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/reply "/nsm/client/save" s:message</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>Or</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/error "/nsm/client/save" i:error_code s:message</code></pre>
- </div>
- </div>
- <table class="tableblock frame-all grid-all stripes-even stretch">
- <caption class="title">Table 5. Response codes</caption>
- <colgroup>
- <col style="width: 50%;">
- <col style="width: 50%;">
- </colgroup>
- <thead>
- <tr>
- <th class="tableblock halign-left valign-top">Code</th>
- <th class="tableblock halign-left valign-top">Meaning</th>
- </tr>
- </thead>
- <tbody>
- <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">2.3. Server to Client Informational Messages</h3>
- <div class="sect3">
- <h4 id="_session_is_loaded">2.3.1. 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">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/session_is_loaded</code></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">2.3.2. Show Optional Gui</h4>
- <div class="paragraph">
- <p>If the client has specified the <code>optional-gui</code> 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">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/show_optional_gui</code></pre>
- </div>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/hide_optional_gui</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>This message does not require a response.</p>
- </div>
- </div>
- </div>
- <div class="sect2">
- <h3 id="_client_to_server_informational_messages">2.4. Client to Server Informational Messages</h3>
- <div class="sect3">
- <h4 id="_optional_gui">2.4.1. Optional GUI</h4>
- <div class="paragraph">
- <p>If the client has specified the <code>optional-gui</code> 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 its
- announce message to indicate the initial visibility state of the optional GUI.</p>
- </div>
- <div class="paragraph">
- <p>The client SHOULD always start hidden, if not saved as visible. That implies the first load, after
- adding to the session, SHOULD always be hidden.</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">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/gui_is_hidden</code></pre>
- </div>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/gui_is_shown</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>No response will be delivered.</p>
- </div>
- </div>
- <div class="sect3">
- <h4 id="_progress">2.4.2. Progress</h4>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/progress f:progress</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>For potentially time-consuming operations, such as <code>save</code> and <code>open</code>, 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 <code>progress</code> feature, the final response to the <code>save</code> or <code>open</code>
- message is still REQUIRED.</p>
- </div>
- <div class="paragraph">
- <p>Clients which intend to send progress messages MUST include <code>:progress:</code> in their <code>announce</code>
- capability string.</p>
- </div>
- </div>
- <div class="sect3">
- <h4 id="_dirtiness">2.4.3. Dirtiness</h4>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/is_dirty</code></pre>
- </div>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/is_clean</code></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 <code>is_dirty</code> and <code>is_clean</code> messages.</p>
- </div>
- <div class="paragraph">
- <p>Clients which have and use this capability MUST include <code>:dirty:</code> in their <code>announce</code> capability string.</p>
- </div>
- </div>
- <div class="sect3">
- <h4 id="_status_messsages">2.4.4. Status Messsages</h4>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/client/message i:priority s:message</code></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. <code>priority</code> MUST be a number from 0
- to 3, 3 being the most important.</p>
- </div>
- <div class="paragraph">
- <p>Clients which have and use this capability MUST include <code>:message:</code> in their <code>announce</code> capability
- string.</p>
- </div>
- </div>
- </div>
- <div class="sect2">
- <h3 id="_error_code_definitions">2.5. Error Code Definitions</h3>
- <table class="tableblock frame-all grid-all stripes-even stretch">
- <caption class="title">Table 6. Error Code Definitions</caption>
- <colgroup>
- <col style="width: 50%;">
- <col style="width: 50%;">
- </colgroup>
- <thead>
- <tr>
- <th class="tableblock halign-left valign-top">Symbolic Name</th>
- <th class="tableblock halign-left valign-top">Integer Value</th>
- </tr>
- </thead>
- <tbody>
- <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">2.6. Client to Server Control</h3>
- <div class="paragraph">
- <p>If the server publishes the <code>:server-control:</code> capability, then clients can also initiate action by
- the server. For example, a client might implement a 'Save All' option which sends a
- <code>/nsm/server/save</code> 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">2.7. 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">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/reply s:path s:message</code></pre>
- </div>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/error s:path i:error_code s:message</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The first parameter of the reply is the path to the message being replied to. The <code>/error</code> reply
- includes an integer error code (non-zero indicates error). <code>message</code> 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 stripes-even stretch">
- <caption class="title">Table 7. Responses</caption>
- <colgroup>
- <col style="width: 50%;">
- <col style="width: 50%;">
- </colgroup>
- <thead>
- <tr>
- <th class="tableblock halign-left valign-top">Code</th>
- <th class="tableblock halign-left valign-top">Meaning</th>
- </tr>
- </thead>
- <tbody>
- <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="ulist">
- <ul>
- <li>
- <p><code>/nsm/server/add s:executable_name</code></p>
- <div class="ulist">
- <ul>
- <li>
- <p>Adds a client to the current session.</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p><code>/nsm/server/save</code></p>
- <div class="ulist">
- <ul>
- <li>
- <p>Saves the current session.</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p><code>/nsm/server/open s:project_name</code></p>
- <div class="ulist">
- <ul>
- <li>
- <p>Saves the current session and loads a new session.</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p><code>/nsm/server/new s:project_name</code></p>
- <div class="ulist">
- <ul>
- <li>
- <p>Saves the current session and creates a new session.</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p><code>/nsm/server/duplicate s:new_project</code></p>
- <div class="ulist">
- <ul>
- <li>
- <p>Saves and closes the current session, makes a copy, and opens it.</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p><code>/nsm/server/close</code></p>
- <div class="ulist">
- <ul>
- <li>
- <p>Saves and closes the current session.</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p><code>/nsm/server/abort</code></p>
- <div class="ulist">
- <ul>
- <li>
- <p>Closes the current session WITHOUT SAVING</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p><code>/nsm/server/quit</code></p>
- <div class="ulist">
- <ul>
- <li>
- <p>Saves and closes the current session and terminates the server.</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p><code>/nsm/server/list</code></p>
- <div class="ulist">
- <ul>
- <li>
- <p>Lists available projects. One <code>/reply</code> message will be sent for each existing project.</p>
- </li>
- <li>
- <p>Afer listing the last session one final <code>/reply</code> with <code>/nsm/server/list, ""</code> will be send. That is an empty string.</p>
- </li>
- </ul>
- </div>
- </li>
- </ul>
- </div>
- <div class="sect3">
- <h4 id="_client_to_client_communication">2.7.1. Client to Client Communication</h4>
- <div class="paragraph">
- <p>If the server includes <code>:broadcast:</code> 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
- <code>/nsm/server/broadcast</code>.</p>
- </div>
- <div class="paragraph">
- <p>The format of this message is as follows:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/server/broadcast s:path [arguments...]</code></pre>
- </div>
- </div>
- <div class="paragraph">
- <p>The message will then be relayed to all clients in the session at the path <code>path</code> (with the
- arguments shifted by one).</p>
- </div>
- <div class="paragraph">
- <p>For example the message:</p>
- </div>
- <div class="listingblock">
- <div class="content">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/nsm/server/broadcast /tempomap/update "0,120,4/4:12351234,240,4/4"</code></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">
- <pre class="highlight nowrap"><code class="language-OSC" data-lang="OSC">/tempomap/update "0,120,4/4:12351234,240,4/4"</code></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 class="sect1">
- <h2 id="_api_versions_and_behaviour_changes">3. API Versions and Behaviour Changes</h2>
- <div class="sectionbody">
- <div class="paragraph">
- <p>Here we will document all technical changes or differences in behaviour together with their API and
- project version numbers. The term "original" refers to Non Session Manager and "new" refers to New
- Session Manager.</p>
- </div>
- <div class="paragraph">
- <p>Version numbers follow <a href="https://semver.org/spec/v2.0.0.html">Semantic Versioning 2.0.0</a></p>
- </div>
- <div class="listingblock">
- <div class="title">Semantic Versioning Scheme</div>
- <div class="content">
- <pre class="highlight"><code>Given a version number MAJOR.MINOR.PATCH, increment the:
-
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backwards compatible manner, and
- PATCH version when you make backwards compatible bug fixes.</code></pre>
- </div>
- </div>
- <table class="tableblock frame-all grid-all stripes-even stretch">
- <caption class="title">Table 8. NSM Version Numbers</caption>
- <colgroup>
- <col style="width: 50%;">
- <col style="width: 50%;">
- </colgroup>
- <thead>
- <tr>
- <th class="tableblock halign-left valign-top">Subject</th>
- <th class="tableblock halign-left valign-top">Version</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td class="tableblock halign-left valign-top"><p class="tableblock">Non Session Manager at moment of fork</p></td>
- <td class="tableblock halign-left valign-top"><p class="tableblock">1.2 (June 2020)</p></td>
- </tr>
- <tr>
- <td class="tableblock halign-left valign-top"><p class="tableblock">Non Session Manager API</p></td>
- <td class="tableblock halign-left valign-top"><p class="tableblock">1.0 <a href="https://github.com/original-male/non/blob/master/session-manager/src/nsmd.C">NON nsmd.C</a></p></td>
- </tr>
- <tr>
- <td class="tableblock halign-left valign-top"><p class="tableblock">Original API Document</p></td>
- <td class="tableblock halign-left valign-top"><p class="tableblock">1.0 <a href="http://non.tuxfamily.org/nsm/API.html">non.tuxfamily.org/nsm/API.html</a></p></td>
- </tr>
- <tr>
- <td class="tableblock halign-left valign-top"><p class="tableblock">New Session Manager</p></td>
- <td class="tableblock halign-left valign-top"><p class="tableblock">1.6.0</p></td>
- </tr>
- <tr>
- <td class="tableblock halign-left valign-top"><p class="tableblock">New Session Manager API</p></td>
- <td class="tableblock halign-left valign-top"><p class="tableblock">1.1.2 <a href="https://github.com/jackaudio/new-session-manager/blob/master/src/nsmd.cpp">NEW nsmd.cpp</a></p></td>
- </tr>
- <tr>
- <td class="tableblock halign-left valign-top"><p class="tableblock">New API Document</p></td>
- <td class="tableblock halign-left valign-top"><p class="tableblock">1.5.0 <a href="#">Here</a></p></td>
- </tr>
- </tbody>
- </table>
- <div class="sect2">
- <h3 id="_guidelines">3.1. Guidelines</h3>
- <div class="paragraph">
- <p>The most important factor in decision making is to keep client compatibility at 100%.
- No client will ever receive an unrequested OSC message except those in API 1.0.0.</p>
- </div>
- <div class="paragraph">
- <p>Messages that drastically change existing <code>/nsm/client/</code> or <code>/nsm/server</code> behaviour require an
- inrecement to <code>API_VERSION_MAJOR</code>, which we want to avoid.</p>
- </div>
- <div class="paragraph">
- <p><code>nsmd</code> checks if the clients <code>API_VERSION_MAJOR</code> is greater than its own and refuses the client
- with <code>ERR_INCOMPATIBLE_API</code>.</p>
- </div>
- <div class="paragraph">
- <p>All changes (that concern client/server behaviour) that increment <code>API_VERSION_MINOR</code> will be
- request-only or gated by new capabilities (e.g. <code>:optional-gui:</code>). <code>nsmd</code> will not send any
- messages if a capability was not sent by the client in <a href="#_announce"><code>announce</code></a>. This includes
- mostly optional features about requesting extra information.</p>
- </div>
- <div class="paragraph">
- <p>New actions for server-control, for example a hypothetical <code>/nsm/server/save_as</code>, which would be
- triggered by the client and would only be <strong>answered</strong> by the server ("no unrequested message") will
- increment <code>API_VERSION_MINOR</code>.</p>
- </div>
- <div class="paragraph">
- <p>All changes that increment <code>API_VERSION_PATCH</code> will not have any effect on behaviour, except to
- fix clear problems, where "problem" is defined by having a different effect than described in this
- document, which includes technical problems such as crashes.</p>
- </div>
- <div class="paragraph">
- <p>All messages regarding GUI-communication that start with <code>/nsm/gui/…​</code> were undocumented in API
- 1.0.0 and only used by <code>non-session-manager</code> / <code>nsm-legacy-gui</code>. Until properly documented in this
- document this part of the API is considered unstable and may change at any time without notice.
- However, when changing already existing messages and behaviour it MAY increment <code>API_VERSION_MINOR</code>
- or <code>API_VERSION_PATCH</code>. In that case it will appear in the list below.</p>
- </div>
- <div class="paragraph">
- <p>Last factor of compatibility is that any unknown message sent to <code>nsmd</code> will just print a warning
- message to stdout, but will otherwise be ignored. This secures a stable server, even when a client
- misbehaves and sends too-new messages outside of announced :capabilites:</p>
- </div>
- </div>
- <div class="sect2">
- <h3 id="_changes_in_api_version_1_1_0">3.2. Changes in API Version 1.1.0</h3>
- <div class="paragraph">
- <p>Rewritten API document without code changes to adapt to existing code or existing client behaviour:</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>Changed versioning scheme to Semantic Versioning with three positions Major.Minor.Patch</p>
- </li>
- <li>
- <p><a href="#_quit_or_exit">Quit or Exit</a> SHOULD hide instead of exiting when :optional-gui: is supported and MAY not
- act on the quit through menu otherwise.</p>
- </li>
- <li>
- <p><a href="#server-to-client-control-messages-open">Open</a>: Make clear that there are only certain
- possibilities for save paths. We added MUST because the rule was just implied before.</p>
- </li>
- <li>
- <p><a href="#server-to-client-control-messages-open">Open</a>: Make clear that the delimiter for
- multi-jack clients is "/".</p>
- </li>
- <li>
- <p><a href="#_optional_gui">Optional GUI</a> SHOULD start hidden, always after a fresh add to the session. After that saving
- the visibility state may override it for next time.</p>
- </li>
- <li>
- <p><a href="#_progress">Progress</a> MUST be announced in :capabilities: . Before there was a lower case "should",
- which means nothing. Parallel-examples in the specs cleary say that supporting optional features must be announced first.</p>
- <div class="ulist">
- <ul>
- <li>
- <p>Same for <a href="#_dirtiness">Dirtiness</a> and <a href="#_status_messsages">Status Messsages</a>.</p>
- </li>
- </ul>
- </div>
- </li>
- <li>
- <p><a href="#_status_messsages">Status Messsages</a> have priority numbers between 0 and 3, so they MUST send that.
- It was never an arbitrary value.</p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>Code changes:</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p><a href="#_server_control_api">Server Control API</a>: <code>/nsm/server/list</code> chain of single OSC messages, one for each session,
- is now finalized with sending and empty string "" as session name. Previously this was just
- a symbolically irrelevant console message <code>"Done."</code></p>
- </li>
- <li>
- <p>Replies to <code>/nsm/server/save</code> etc. will now be sent back to the sender and not falsely to the last
- client who replied to <code>/nsm/client/save</code>. This alone would only require API_VERSION_PATCH
- increment, but we are already incrementing minor.</p>
- </li>
- <li>
- <p><a href="#_server_control_api">Server Control API</a>: <code>/nsm/server/add</code> was replying with an undocumented error code on success.
- Instead, as this document always specificed, it now sends <code>"/reply", path, "Launched."</code>.
- Again, this would have been just API_VERSION_PATCH on its own.</p>
- </li>
- </ul>
- </div>
- <div class="paragraph">
- <p>Undocumented (Unstable) <code>/nsm/gui</code> protocol</p>
- </div>
- <div class="ulist">
- <ul>
- <li>
- <p>Send client status after a GUI attaches to running server. This
- was not happening before, but it was the intention. It was just broken in nsmd.cpp. This alone
- would only require API_VERSION_PATCH increment, but we are already incrementing minor.</p>
- </li>
- <li>
- <p>Send label "launch error!" when a program is added (or loaded) that
- does not exist in $PATH. This requires no adaptation of any client, server or GUI because labels
- are arbitrary already and this is not meant for automatic parsing, but as user information.</p>
- </li>
- <li>
- <p><code>/nsm/gui/session/name</code> will now always send the same parameter format, regardless of how the session was opened:
- simple-session-name, relative session path with subdirs below session-root.</p>
- </li>
- <li>
- <p>When a GUI announces itself to nsmd it will receive the absolute path to the session directory
- through the message <code>/nsm/gui/session/root</code>. This is not a new addition but was already in
- non-session-manager git.</p>
- </li>
- </ul>
- </div>
- </div>
- <div class="sect2">
- <h3 id="_changes_in_api_version_1_1_1">3.3. Changes in API Version 1.1.1</h3>
- <div class="ulist">
- <ul>
- <li>
- <p>Server-capability :optional-gui: is now mandatory for SERVER implementations. Reasoning:
- This is an important core feature of NSM and thus will be treated as such by guaranteeing it to exist.
- After looking at all currently known clients and server-implementations it turns out that all servers
- support :optional-gui: and the vast majority of clients not only support it, but actually assume it
- and do <em>not</em> test for the server capability, as it was written in this document.
- There are now two choices: Adjust this document to the (good) reality or consider all clients broken.
- Summary: We consider this API document wrong and therefore fix it, thus increasing API version
- patch-level from 1.1.0 to 1.1.1</p>
- </li>
- <li>
- <p>Add API-section "Subdirectories / Hierarchical Structure" that explains the session directory.
- This behaviour was already the case for nsm-legacy-gui and nsmd 1.5.0 was patched to adhere to this
- behaviour more strictly as well, removing false session entries in 3rd party clients such as Agordejo.</p>
- </li>
- </ul>
- </div>
- </div>
- <div class="sect2">
- <h3 id="_changes_in_api_version_1_1_2">3.4. Changes in API Version 1.1.2</h3>
- <div class="ulist">
- <ul>
- <li>
- <p>nsmd now follows the XDG Base Directory Specifications for it’s session root and lock files. This
- if of no consequence to clients but required documentation nevertheless, which was described as
- "background information" in the chapters for lock files and daemon disovery.</p>
- </li>
- <li>
- <p>nsmd now gracefully handles read-only <code>session.nsm</code> files. This theoretically enables read-only
- sessions and session-templates. It is included in the patch-level because this was marked as a
- long-standing <code>FIXME</code> in the code by the original author. Or in other words: just a bug fix.</p>
- </li>
- </ul>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div id="footer">
- <div id="footer-text">
- Version API 1.1.2<br>
- Last updated 2022-04-06 23:25:00 +0200
- </div>
- </div>
- </body>
- </html>
|