Each ALSA port can have capability flags. The most basic capability flags are SND_SEQ_PORT_CAP_READ and SND_SEQ_PORT_CAP_WRITE. The former means that the port allows to send events to other ports, whereas the latter capability menas that the port allows to receive events from other ports. You may have noticed that meanings of READ and WRITE are permissions of the port from the viewpoint of other ports.
For allowing subscription from/to other clients, another capability flags must be set together with read/write capabilities above. For allowing read and write subscriptions, SND_SEQ_PORT_READ_SUBS and SND_SEQ_PORT_WRITE_SUBS are used, respectively. For example, the port with MIDI input device always has READ_SUBS capability, and the port with MIDI output device always has WRITE_SUBS capability together with READ and WRITE capabilities, respectively. Obviously, these flags have no influence if READ or WRITE capability is not set.
Note that these flags are not necessary if the client subscribes itself to the spcified port. For example, when a port makes READ subscription to MIDI input port, this port must have WRITE capability, but no WRITE_SUBS capability is required. Only MIDI input port must have READ_SUBS capability.
As default, the connection of ports via the third client is always allowed if proper read and write (subscription) capabilities are set both to the source and destination ports. For prohibiting this behavior, set a capability SND_SEQ_PORT_CAP_NO_EXPORT to the port. If this flag is set, subscription must be done by sender or receiver client itself. It is useful to avoid unexpected disconnection. The ports which won't accept subscription should have this capability for better security.
Each ALSA client and port have group field for specifying a group name. The access permission above can be defined also for the group. The "group" permission is checked only when access or subscription to "all" is refused.
In ALSA library, subscription is done via snd_seq_subscribe_port() function. The argument has the following record:
typedef struct { snd_seq_addr_t sender; /* sender address */ snd_seq_addr_t dest; /* destination address */ unsigned char queue; /* input time-stamp queue (optional) */ int exclusive: 1, /* exclusive mode */ realtime: 1, /* realtime timestamp */ convert_time: 1; /* convert timestamp */ int midi_channels; /* midi channels setup */ int midi_voices; /* midi voices setup */ int synth_voices; /* synth voices setup */ char reserved[32]; /* for future use */ } snd_seq_port_subscribe_t;The sender and dest fields are source and destination port addresses for connection, respectively. For example, to connect from MIDI input port to the self port, set the following values:
sender.client = MIDI_input_client; sender.port = MIDI_input_port; dest.client = my_client; dest.port = my_port;The queue value is necessary if convert_time flag is true. (See below).
The exclusive field indicates that the connection is exclusive and no other ports can subscribe connection to the destination port. The succeeding subscriptions will be refused.
If convert_time is true, the timestamp through subscribed connections will be automatically converted to the current time on the specified queue. The queue must be specified in queue field. If realtime is true, the timestamp is converted to realt-ime structure (sec/nsec pair). Otherwise, the timestamp is stored in tick unit. This feature is useful when receiving events from MIDI input device. The event time is automatically set in the event record.
Note that an outsider client may connect other ports. In this case, however, the subscription may be refused if NO_EXPORT capability is set in either sender or receiver port.