Document authors:
-
Jonathan Moore Liles (revisions from 1 to revision 1.2 from 2013-04-06)
-
Nils Hilbricht (2020-07 initial adaptation of the NON project version)
-
Nedko Arnaudov (2022 onward, as part of LADI project)
api_version_major |
1 |
api_version_minor |
0 |
This document describes the NON Session Manager OSC API as defined and implemented by NON project. The only difference is server-control capability which was fixed in NON project codebase before the New Session Manager schism but as of when this document is written, is not fixed at the NSM API URL, see http://non.tuxfamily.org/nsm/API.html for more info.
For definition of the new-session-manager OSC API, see https://new-session-manager.jackaudio.org/api/index.html
The Non Session Management API is used by the various components of the Non audio production suite to allow any number of independent programs to be managed together as part of a logical session (i.e. a song). Thus, operations such as loading and saving are synchronized.
The API comprises a simple Open Sound Control (OSC) based protocol, along with some behavioral guidelines, which can easily be implemented by various applications.
The Non project contains an program called nsmd
which is an implementation of the server side of
the NSM API. nsmd
is controlled by the non-session-manager
GUI. However, the same server-side
API can also be implemented by other session managers (such as LADISH), although consistency and
robustness will likely suffer if non-NSM compliant clients are allowed to participate in a session.
The only dependency for client implementations liblo
(the OSC library), which several Linux audio
applications already link to or plan to link to in the future.
The aim of this project is to thoroughly define the behavior required of clients. This is an area where other attempts at session management (LASH and JACK-Session) have failed. Often the difficulty with these systems has been not in implementing support for them, but in attempting to interpret the confusing, ambiguous, or ill-conceived API documentation. For these reasons and more all previous attempts at Linux audio session management protocols are considered harmful.
You WILL see some unambiguous and emphatic language in this document. For the good of the user, these rules are meant to be followed and are non-negotiable. If an application does not conform to this specification it should be considered broken. Consistency across applications under session management is very important for a good user experience.
Most graphical applications make available to the user a common set of file operations, typically presented under a File or Project menu.
These are: New, Open, Save, Save As, Close and Quit or Exit.
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
announce
handshake described in the NSM OSC Protocol section. In order to provide a
consistent and predictable user experience, it is critically important for applications to adhere
to these guidelines.
This option may empty/reset the current file or project (possibly after user confirmation). UNDER NO CIRCUMSTANCES should it allow the user to create a new project/file in another location.
This option MUST be disabled.
The application may, however, elect to implement an option called 'Import into Session', creates a copy of a file/project which is then saved at the session path provided by NSM.
This option should behave as normal, saving the current file/project as established by the NSM
open
message.
UNDER NO CIRCUMSTANCES should this option present the user with a choice of where to save the file.
This option MUST be disabled.
The application may, however, 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.
This option MUST be disabled unless its meaning is to disconnect the application from session management.
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).
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)
All message parameters are REQUIRED. All messages MUST be sent from the same socket as the announce
message, using the lo_send_from
method of liblo or its equivalent, as the server uses the return
addresses to distinguish between clients.
Clients MUST create thier OSC servers using the same protocol (UDP,TCP) as found in NSM_URL
. liblo
is lacking a robust TCP implementation at the time of writing, but in the future it may be useful.
At launch, the client MUST check the environment for the value of NSM_URL
. If present, the client
MUST send the following message to the provided address as soon as it is ready to respond to the
/nsm/client/open
event:
/nsm/server/announce s:application_name s:capabilities s:executable_name i:api_version_major i:api_version_minor i:pid
If NSM_URL
is undefined, invalid, or unreachable, then the client should proceed assuming that
session management is unavailable.
api_version_major
and api_version_minor
must be the two parts of the version number of the NSM API
as defined by this document.
Note that if the application intends to register JACK clients, application_name
MUST be the same as
the name that would normally be passed to jack_client_open
. For example, Non-Mixer sends
"Non-Mixer" as its application_name
. Applications MUST NOT register their JACK clients until
receiving an open
message; the open
message will provide a unique client name prefix suitable for
passing to JACK. This is probably the most complex requirement of the NSM API, but it isn’t
difficult to implement, especially if the application simply wishes to delay its initialization
process breifly while awaiting the announce
reply and subsequent open
message.
capabilities
MUST be a string containing a colon separated list of the special capabilities the
client possesses. e.g. :dirty:switch:progress:
executable_name
MUST be the executable name that the program was launched with. For C programs,
this is simply the value of argv[0]
. 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.
Name | Description |
---|---|
switch |
client is capable of responding to multiple |
dirty |
client knows when it has unsaved changes |
progress |
client can send progress updates during time-consuming operations |
message |
client can send textual status updates |
optional-gui |
client has an optional GUI |
The server will respond to the client’s announce message with the following message:
/reply "/nsm/server/announce" s:message s:name_of_session_manager s:capabilities
message
is a welcome message.
The value of name_of_session_manager
will depend on the implementation of the NSM server. It might
say "Non Session Manager", or it might say "LADISH". This is for display to the user.
capabilities
will be a string containing a colon separated list of special server capabilities.
Presently, the server capabilities
are:
Name | Description |
---|---|
server-control |
client-to-server control |
broadcast |
server responds to /nsm/server/broadcast message |
optional-gui |
server responds to optional-gui messages—if this capability is not present then clients with optional-guis MUST always keep them visible |
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.
If there is an error, a reply of the following form will be sent to the client:
/error "/nsm/server/announce" i:error_code s:error_message
The following table defines possible values of error_code
:
Code | Meaning |
---|---|
ERR_GENERAL |
General Error |
ERR_INCOMPATIBLE_API |
Incompatible API version |
ERR_BLACKLISTED |
Client has been blacklisted. |
Compliant clients MUST accept the client control messages described in this section. All client
control messages REQUIRE a response. Responses MUST be delivered back to the sender (NSM) from the
same socket used by the client in its announce
message (by using lo_send_from
) AFTER the action has
been completed or if an error is encountered. The required response is described in the subsection
for each message.
If there is an error and the action cannot be completed, then error_code
MUST be set to a valid
error code (see Error Code Definitions) and message
to a string describing the problem
(suitable for display to the user).
The reply can take one of the following two forms, where path MUST be the path
of the message being
replied to (e.g. "nsm/client/save":
/reply s:path s:message
/error s:path i:error_code s:message
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 save
message.
/nsm/client/open s:path_to_instance_specific_project s:display_name s:client_id
path_to_instance_specific_project
is a path name assigned to the client for storing its project
data.
The client may append to the path, creating a sub-directory, e.g. '/song.foo' or simply append the client’s native file extension (e.g. '.non' or '.XML'). The same transformation MUST be applied to the name when opening an existing project, as NSM will only provide the instance specific part of the path.
If a project exists at the path, the client MUST immediately open it.
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 save
message.
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.
For clients which HAVE NOT specified the :switch:
capability, the open
message will only be
delivered once, immediately following the announce
response.
For clients which HAVE specified the :switch:
capability, the client MUST immediately switch to the
specified project or create a new one if it doesn’t exist.
Clients which are incapable of switching projects or are prone to crashing upon switching MUST NOT
include :switch:
in their capability string.
If the user the is allowed to run two or more instances of the application simultaneously (that is
to say, there is no technical limitation preventing them from doing so, even if it doesn’t make
sense to the author), then such an application MUST PRE-PEND the provided client_id
string to any
names it registers with common subsystems (e.g. JACK client names). This ensures that multiple
instances of the same application can be restored in any order without scrambling the JACK
connections or causing other conflicts. The provided client_id
will be a concatenation of the value
of application_name
sent by the client in its announce
message and a unique identifier. Therefore,
applications which create single JACK clients can use the value of client_id
directly as their JACK
client name. Applications which register multiple JACK clients (e.g. Non-Mixer) MUST PRE-PEND
client_id
value to the client names they register with JACK and the application determined part
MUST be unique for that (JACK) client.
For example, a suitable JACK client name would be: $CLIENT_ID/track-1
Note that this means that the application MUST NOT register with JACK (or any
other subsystem requiring unique names) until it receives an open
message from NSM. Likewise,
applications with the :switch:
capability should close their JACK clients and re-create them with
using the new client_id
. Re-registering is necessary because the JACK API does currently support
renaming existing clients, although this is a sorely needed addition.
A response is REQUIRED as soon as the open operation has been completed. Ongoing progress may be
indicated by sending messages to /nsm/client/progress
.
The client MUST respond to the 'open' message with:
/reply "/nsm/client/open" s:message
Or
/error "/nsm/client/open" i:error_code s:message
Code | Meaning |
---|---|
ERR |
General Error |
ERR_BAD_PROJECT |
An existing project file was found to be corrupt |
ERR_CREATE_FAILED |
A new project could not be created |
ERR_UNSAVED_CHANGES |
Unsaved changes would be lost |
ERR_NOT_NOW |
Operation cannot be completed at this time |
/nsm/client/save
This message will only be delivered after a previous open
message, and may be sent any number of
times within the course of a session (including zero, if the user aborts the session).
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.
/nsm/client/session_is_loaded
This message does not require a response.
If the client has specified the optional-gui
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.
/nsm/client/show_optional_gui
/nsm/client/hide_optional_gui
No response is message is required.
If the client has specified the optional-gui
capability, then it MUST send this message whenever
the state of visibility of the optional GUI has changed. It also MUST send this message after it’s
announce message to indicate the initial visibility state of the optional GUI.
It is the responsibility of the client to remember the visibility state of its GUI across session loads.
/nsm/client/gui_is_hidden
/nsm/client/gui_is_shown
No response will be delivered.
/nsm/client/progress f:progress
For potentially time-consuming operations, such as save
and open
, 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.
The server will not send a response to these messages, but will relay the information to the user.
Note that even when using the progress
feature, the final response to the save
or open
message is still REQUIRED.
Clients which intend to send progress messages should include :progress:
in their announce
capability string.
/nsm/client/is_dirty
/nsm/client/is_clean
Some clients may be able to inform the server when they have unsaved changes pending. Such clients
may optionally send is_dirty
and is_clean
messages.
Clients which have this capability should include :dirty:
in their announce
capability string.
/nsm/client/message i:priority s:message
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. priority
should be a number from 0
to 3, 3 being the most important.
Clients which have this capability should include :message:
in their announce
capability
string.
Symbolic Name | Integer Value |
---|---|
ERR_GENERAL |
-1 |
ERR_INCOMPATIBLE_API |
-2 |
ERR_BLACKLISTED |
-3 |
ERR_LAUNCH_FAILED |
-4 |
ERR_NO_SUCH_FILE |
-5 |
ERR_NO_SESSION_OPEN |
-6 |
ERR_UNSAVED_CHANGES |
-7 |
ERR_NOT_NOW |
-8 |
ERR_BAD_PROJECT |
-9 |
ERR_CREATE_FAILED |
-10 |
If the server publishes the :server-control:
capability, then clients can also initiate action by
the server. For example, a client might implement a 'Save All' option which sends a
/nsm/server/save
message to the server, rather than requiring the user to switch to the session
management interface to effect the save.
The session manager not only manages clients via OSC, but it is itself controlled via OSC messages. The server responds to the following messages.
All of the following messages will be responded to, at the sender’s address, with one of the two following messages:
/reply s:path s:message
/error s:path i:error_code s:message
The first parameter of the reply is the path to the message being replied to. The /error
reply
includes an integer error code (non-zero indicates error). message
will be a description of the
error.
The possible errors are:
Code | Meaning |
---|---|
ERR_GENERAL |
General Error |
ERR_LAUNCH_FAILED |
Launch failed |
ERR_NO_SUCH_FILE |
No such file |
ERR_NO_SESSION |
No session is open |
ERR_UNSAVED_CHANGES |
Unsaved changes would be lost |
-
/nsm/server/duplicate s:new_project
-
Saves and closes the current session, makes a copy, and opens it.
-
If the server includes :broadcast:
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
/nsm/server/broadcast
.
The format of this message is as follows:
/nsm/server/broadcast s:path [arguments...]
The message will then be relayed to all clients in the session at the path path
(with the
arguments shifted by one).
For example the message:
/nsm/server/broadcast /tempomap/update "0,120,4/4:12351234,240,4/4"
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.
/tempomap/update "0,120,4/4:12351234,240,4/4"
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.