Sophie

Sophie

distrib > Mageia > 5 > i586 > media > core-release > by-pkgid > 406d9b580cc28afca9442eab7324087d > files > 411

libalsa2-docs-1.0.28-1.mga5.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.7"/>
<title>ALSA project - the C library reference: Sequencer interface</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td style="padding-left: 0.5em;">
   <div id="projectname">ALSA project - the C library reference
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.7 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="pages.html"><span>Related&#160;Pages</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
      <li><a href="examples.html"><span>Examples</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Data Structures</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Typedefs</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Enumerations</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(7)"><span class="SelectionMark">&#160;</span>Enumerator</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(8)"><span class="SelectionMark">&#160;</span>Macros</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(9)"><span class="SelectionMark">&#160;</span>Groups</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(10)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Sequencer interface </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h1><a class="anchor" id="seq_general"></a>
General</h1>
<p>The ALSA sequencer interface is designed to deliver the MIDI-like events between clients/ports. A typical usage is the MIDI patch-bay. A MIDI application can be connected arbitrarily from/to the other MIDI clients. The routing between clients can be changed dynamically, so the application can handle incoming or outgoing MIDI events regardless of the devices or the application connections.</p>
<p>The sequencer core stuff only takes care of two things: scheduling events and dispatching them to the destination at the right time. All processing of MIDI events has to be done within the clients. The event can be dispatched immediately without queueing, too. The event scheduling can be done either on a MIDI tempo queue or on a wallclock-time queue.</p>
<h1><a class="anchor" id="seq_client"></a>
Client and Port</h1>
<p>A <em>client</em> is created at each time <a class="el" href="group___sequencer.html#ga95462dc59c0319e186cda713ecfb4ed3" title="Open the ALSA sequencer. ">snd_seq_open()</a> is called. Later on, the attributes of client such as its name string can be changed via <a class="el" href="group___seq_client.html#ga109f62fb356c322533ddde4a6ce2c587" title="set the current client information ">snd_seq_set_client_info()</a>. There are helper functions for ease of use, e.g. <a class="el" href="group___seq_middle.html#gaec3acab3bfb3df3f0c9ccc4903570b9d" title="set client name ">snd_seq_set_client_name()</a> and <a class="el" href="group___seq_middle.html#ga888bf17bbc8141d1624f7bbef52dddce" title="add client event filter ">snd_seq_set_client_event_filter()</a>. A typical code would be like below: </p><div class="fragment"><div class="line"><span class="comment">// create a new client</span></div>
<div class="line"><a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *open_client()</div>
<div class="line">{</div>
<div class="line">        <a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *handle;</div>
<div class="line">        <span class="keywordtype">int</span> err;</div>
<div class="line">        err = <a class="code" href="group___sequencer.html#ga95462dc59c0319e186cda713ecfb4ed3">snd_seq_open</a>(&amp;handle, <span class="stringliteral">&quot;default&quot;</span>, <a class="code" href="group___sequencer.html#gaaf1cded61cf90f4d37caf910192ef513">SND_SEQ_OPEN_INPUT</a>, 0);</div>
<div class="line">        <span class="keywordflow">if</span> (err &lt; 0)</div>
<div class="line">                <span class="keywordflow">return</span> NULL;</div>
<div class="line">        <a class="code" href="group___seq_middle.html#gaec3acab3bfb3df3f0c9ccc4903570b9d">snd_seq_set_client_name</a>(handle, <span class="stringliteral">&quot;My Client&quot;</span>);</div>
<div class="line">    <span class="keywordflow">return</span> handle;</div>
<div class="line">}</div>
</div><!-- fragment --><p>You'll need to know the id number of the client eventually, for example, when accessing to a certain port (see the section <a class="el" href="seq.html#seq_subs">Subscription</a>). The client id can be obtained by <a class="el" href="group___sequencer.html#ga2cdaded101f041b9a0930b665ac44b93" title="Get the client id. ">snd_seq_client_id()</a> function.</p>
<p>A client can have one or more <em>ports</em> to communicate between other clients. A port is corresponding to the MIDI port in the case of MIDI device, but in general it is nothing but the access point between other clients. Each port may have capability flags, which specify the read/write accessibility and subscription permissions of the port. For creation of a port, call <a class="el" href="group___seq_port.html#gab40867ed02d9d6e40a75f929b5adf24d" title="create a sequencer port on the current client ">snd_seq_create_port()</a> with the appropriate port attribute specified in <a class="el" href="group___seq_port.html#ga122b704fdab734223ef90b5e26f358e9">snd_seq_port_info_t</a> record.</p>
<p>For creating a port for the normal use, there is a helper function <a class="el" href="group___seq_middle.html#ga9368266bde7b5c0f8d5ddeaf64914719" title="create a port - simple version ">snd_seq_create_simple_port()</a>. An example with this function is like below. </p><div class="fragment"><div class="line"><span class="comment">// create a new port; return the port id</span></div>
<div class="line"><span class="comment">// port will be writable and accept the write-subscription.</span></div>
<div class="line"><span class="keywordtype">int</span> my_new_port(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *handle)</div>
<div class="line">{</div>
<div class="line">    <span class="keywordflow">return</span> <a class="code" href="group___seq_middle.html#ga9368266bde7b5c0f8d5ddeaf64914719">snd_seq_create_simple_port</a>(handle, <span class="stringliteral">&quot;my port&quot;</span>,</div>
<div class="line">            <a class="code" href="group___seq_port.html#gae8afb5ac8f546461b4bab25454972aeb">SND_SEQ_PORT_CAP_WRITE</a>|<a class="code" href="group___seq_port.html#ga52ff1c51578166e67936cfb826c966c0">SND_SEQ_PORT_CAP_SUBS_WRITE</a>,</div>
<div class="line">            <a class="code" href="group___seq_port.html#ga0f89faac8be715b9e2d9d885c7f644a0">SND_SEQ_PORT_TYPE_MIDI_GENERIC</a>);</div>
<div class="line">}</div>
</div><!-- fragment --><h1><a class="anchor" id="seq_memory"></a>
Memory Pool</h1>
<p>Each client owns memory pools on kernel space for each input and output events. Here, input and output mean input (read) from other clients and output (write) to others, respectively. Since memory pool of each client is independent from others, it avoids such a situation that a client eats the whole events pool and interfere other clients' response.</p>
<p>The all scheduled output events or input events from dispatcher are stored on these pools until delivered to other clients or extracted to user space. The size of input/output pools can be changed independently. The output pool has also a room size, which is used to wake up the thread when it falls into sleep in blocking write mode.</p>
<p>Note that ports on the same client share the same memory pool. If a port fills the memory pool, another can't use it any more. For avoiding this, multiple clients can be used.</p>
<p>For chancing the pool size and the condition, access to <a class="el" href="group___seq_client.html#gadc7ce8adaec84d42695492f0ba2515af">snd_seq_client_pool_t</a> record. There are helper functions, <a class="el" href="group___seq_middle.html#ga38e40d84154122798c9fad8e56c60a0f" title="change the output pool size of the given client ">snd_seq_set_client_pool_output()</a>, <a class="el" href="group___seq_middle.html#ga597d2417e0fd512f56d31464cc2ea7d7" title="change the output room size of the given client ">snd_seq_set_client_pool_output_room()</a> and <a class="el" href="group___seq_middle.html#ga1344c7aadb847bd409093c179557732d" title="change the input pool size of the given client ">snd_seq_set_client_pool_input()</a>, for setting the total output-pool size, the output-room size and the input-pool size, respectively.</p>
<h1><a class="anchor" id="seq_subs"></a>
Subscription</h1>
<p>One of the new features in ALSA sequencer system is <em>subscription</em> of ports. In general, subscription is a connection between two sequencer ports. Even though an event can be delivered to a port without subscription using an explicit destination address, the subscription mechanism provides us more abstraction.</p>
<p>Suppose a MIDI input device which sends events from a keyboard. The port associated with this device has READ capability - which means this port is readable from other ports. If a user program wants to capture events from keyboard and store them as MIDI stream, this program must subscribe itself to the MIDI port for read. Then, a connection from MIDI input port to this program is established. From this time, events from keyboard are automatically sent to this program. Timestamps will be updated according to the subscribed queue. </p><div class="fragment"><div class="line">MIDI input port (keyboard)</div>
<div class="line">    |</div>
<div class="line">    V</div>
<div class="line">ALSA sequencer - update timestamp</div>
<div class="line">    |</div>
<div class="line">    V</div>
<div class="line">application port</div>
</div><!-- fragment --><p>There is another subscription type for opposite direction: Suppose a MIDI sequencer program which sends events to a MIDI output device. In ALSA system, MIDI device is not opened until the associated MIDI port is accessed. Thus, in order to activate MIDI device, we have to subscribe to MIDI port for write. After this connection is established, events will be properly sent to MIDI output device. </p><div class="fragment"><div class="line">application port</div>
<div class="line">    |</div>
<div class="line">    V</div>
<div class="line">ALSA sequencer - events are scheduled</div>
<div class="line">    |</div>
<div class="line">    V</div>
<div class="line">MIDI output port (WaveTable etc.)</div>
</div><!-- fragment --><p>From the viewpoint of subscription, the examples above are special cases. Basically, subscription means the connection between two arbitrary ports. For example, imagine a filter application which modifies the MIDI events like program, velocity or chorus effects. This application can accept arbitrary MIDI input and send to arbitrary port, just like a Unix pipe application using stdin and stdout files. We can even connect several filter applications which work individually in order to process the MIDI events. Subscription can be used for this purpose. The connection between ports can be done also by the "third" client. Thus, filter applications have to manage only input and output events regardless of receiver/sender addresses. </p><div class="fragment"><div class="line">sequencer port #1</div>
<div class="line">    |</div>
<div class="line">    V</div>
<div class="line">ALSA sequencer (scheduled or real-time)</div>
<div class="line">    |</div>
<div class="line">    V</div>
<div class="line">sequencer port #2</div>
</div><!-- fragment --><p>For the detail about subscription, see the section <a class="el" href="seq.html#seq_subs_more">More inside the subscription</a>.</p>
<h1><a class="anchor" id="seq_events"></a>
Sequencer Events</h1>
<p>Messaging between clients is performed by sending events from one client to another. These events contain high-level MIDI oriented messages or sequencer specific messages.</p>
<p>All the sequencer events are stored in a sequencer event record, <a class="el" href="structsnd__seq__event__t.html">snd_seq_event_t</a> type. Application can send and receive these event records to/from other clients via sequencer. An event has several storage types according to its usage. For example, a SYSEX message is stored on the variable length event, and a large synth sample data is delivered using a user-space data pointer.</p>
<h2><a class="anchor" id="seq_ev_struct"></a>
Structure of an event</h2>
<p>An event consists of the following items: </p><ul>
<li>
The type of the event </li>
<li>
Event flags. It describes various conditions: <ul>
<li>
time stamp; "real time" / "song ticks" </li>
<li>
time mode; "absolute" / "relative to current time" </li>
</ul>
</li>
<li>
Timestamp of the event. </li>
<li>
Scheduling queue id. </li>
<li>
Source address of the event, given by the combination of client id and port id numbers. </li>
<li>
Destination address of the event. </li>
<li>
The actual event data. (up to 12 bytes) </li>
</ul>
<p>The actual record is shown in <a class="el" href="structsnd__seq__event__t.html">snd_seq_event_t</a>. The type field contains the type of the event (1 byte). The flags field consists of bit flags which describe several conditions of the event (1 byte). It includes the time-stamp mode, data storage type, and scheduling priority. The tag field is an arbitrary tag. This tag can used for removing a distinct event from the event queue via <a class="el" href="group___seq_event.html#ga7ed1109642fdb8dbd9f8a20564e40362" title="remove events on input/output buffers and pools ">snd_seq_remove_events()</a>. The queue field is the queue id for scheduling. The source and dest fields are source and destination addresses. The data field is a union of event data.</p>
<h2><a class="anchor" id="seq_ev_queue"></a>
Scheduling queue</h2>
<p>An event can be delivered either on scheduled or direct dispatch mode. On the scheduling mode, an event is once stored on the priority queue and delivered later (or even immediately) to the destination, whereas on the direct dispatch mode, an event is passed to the destination without any queue.</p>
<p>For a scheduled delivery, a queue to process the event must exist. Usually, a client creates its own queue by <a class="el" href="group___seq_queue.html#ga036e62b321b56bee2e8d2e8280a6416a" title="allocate a queue ">snd_seq_alloc_queue()</a> function. Alternatively, a queue may be shared among several clients. For scheduling an event on the specified queue, a client needs to fill queue field with the preferred queue id.</p>
<p>Meanwhile, for dispatching an event directly, just use <a class="el" href="group___seq_queue.html#ga2a5be7ea9ad68adc9a7288ba25850245">SND_SEQ_QUEUE_DIRECT</a> as the target queue id. A macro <a class="el" href="group___seq_middle.html#gae2674210b5601e8aa3e787c1ddbdcb62" title="set direct passing mode (without queued) ">snd_seq_ev_set_direct()</a> is provided for ease and compatibility.</p>
<p>Note that scheduling at the current or earlier time is different from the direct dispatch mode even though the event is delivered immediately. On the former scheme, an event is once stored on priority queue, then delivered actually. Thus, it acquires a space from memory pool. On the other hand, the latter is passed without using memory pool. Although the direct dispatched event needs less memory, it means also that the event cannot be resent if the destination is unable to receive it momentarily.</p>
<h2><a class="anchor" id="seq_ev_time"></a>
Time stamp</h2>
<p>The timestamp of the event can either specified in <em>real time</em> or in <em>song ticks</em>. The former means the wallclock time while the latter corresponds to the MIDI ticks. Which format is used is determined by the event flags.</p>
<p>The resolution of real-time value is in nano second. Since 64 bit length is required for the actual time calculation, it is represented by a structure of pair of second and nano second defined as <a class="el" href="structsnd__seq__real__time__t.html">snd_seq_real_time_t</a> type. The song tick is defined simply as a 32 bit integer, defined as <a class="el" href="group___seq_events.html#gaa6a1e0c4394f9b26cc55e0181a5e2cb8">snd_seq_tick_time_t</a> type. The time stored in an event record is a union of these two different time values.</p>
<p>Note that the time format used for real time events is very similar to timeval struct used for Unix system time. The absurd resolution of the timestamps allows us to perform very accurate conversions between songposition and real time. Round-off errors can be neglected.</p>
<p>If a timestamp with a <em>relative</em> timestamp is delivered to ALSA, the specified timestamp will be used as an offset to the current time of the queue the event is sent into. An <em>absolute</em> timestamp is on the contrary the time counted from the moment when the queue started.</p>
<p>An client that relies on these relative timestamps is the MIDI input port. As each sequencer queue has it's own clock the only way to deliver events at the right time is by using the relative timestamp format. When the event arrives at the queue it is normalized to absolute format.</p>
<p>The timestamp format is specified in the flag bitfield masked by <a class="el" href="group___seq_events.html#gac7da1e1965e86a68f663babec22a99ba">SND_SEQ_TIME_STAMP_MASK</a>. To schedule the event in a real-time queue or in a tick queue, macros <a class="el" href="group___seq_middle.html#ga713370bf29736477532e791b4ad92530" title="set real-time-scheduling mode on queue ">snd_seq_ev_schedule_real()</a> and <a class="el" href="group___seq_middle.html#ga589469c27715bfae205ce26d5801d8b1" title="set tick-scheduling mode on queue ">snd_seq_ev_schedule_tick()</a> are provided, respectively.</p>
<h2><a class="anchor" id="seq_ev_addr"></a>
Source and destination addresses</h2>
<p>To identify the source and destination of an event, the addressing field contains a combination of client id and port id numbers, defined as <a class="el" href="structsnd__seq__addr__t.html">snd_seq_addr_t</a> type. When an event is passed to sequencer from a client, sequencer fills source.client field with the sender's id automatically. It is the responsibility of sender client to fill the port id of source.port and both client and port of dest field.</p>
<p>If an existing address is set to the destination, the event is simply delivered to it. When <a class="el" href="group___sequencer.html#ga383b235d2afbe48704952edfd3a33eed">SND_SEQ_ADDRESS_SUBSCRIBERS</a> is set to the destination client id, the event is delivered to all the clients connected to the source port.</p>
<p>A sequencer core has two pre-defined system ports on the system client <a class="el" href="group___sequencer.html#ga5437f98c59679c92ee4d940ac643169e">SND_SEQ_CLIENT_SYSTEM</a>: <a class="el" href="group___seq_port.html#ga02870ceddec24d3cc5609ec728b0cb92">SND_SEQ_PORT_SYSTEM_TIMER</a> and <a class="el" href="group___seq_port.html#gaf12ff6ca6077edc7c6027a3fb1d0664b">SND_SEQ_PORT_SYSTEM_ANNOUNCE</a>. The <a class="el" href="group___seq_port.html#ga02870ceddec24d3cc5609ec728b0cb92">SND_SEQ_PORT_SYSTEM_TIMER</a> is the system timer port, and <a class="el" href="group___seq_port.html#gaf12ff6ca6077edc7c6027a3fb1d0664b">SND_SEQ_PORT_SYSTEM_ANNOUNCE</a> is the system announce port. In order to control a queue from a client, client should send a queue-control event like start, stop and continue queue, change tempo, etc. to the system timer port. Then the sequencer system handles the queue according to the received event. This port supports subscription. The received timer events are broadcasted to all subscribed clients.</p>
<p>The latter port does not receive messages but supports subscription. When each client or port is attached, detached or modified, an announcement is sent to subscribers from this port.</p>
<h2><a class="anchor" id="seq_ev_data"></a>
Data storage type</h2>
<p>Some events like SYSEX message, however, need larger data space than the standard data. For such events, ALSA sequencer provides several different data storage types. The data type is specified in the flag bits masked by <a class="el" href="group___seq_events.html#ga69fa938ef7ebc12e3d1b8758b39b7967">SND_SEQ_EVENT_LENGTH_MASK</a>. The following data types are available:</p>
<dl class="section user"><dt>Fixed size data</dt><dd>Normal events stores their parameters on data field (12 byte). The flag-bit type is <a class="el" href="group___seq_events.html#ga35b6aacb44080053e0ca0eeaefbe8dc2">SND_SEQ_EVENT_LENGTH_FIXED</a>. A macro <a class="el" href="group___seq_middle.html#ga8c949038f36fd3e27de8b8e419978793" title="set fixed data ">snd_seq_ev_set_fixed()</a> is provided to set this type.</dd></dl>
<dl class="section user"><dt>Variable length data</dt><dd>SYSEX or a returned error use this type. The actual data is stored on an extra allocated space. On sequencer kernel, the whole extra-data is duplicated, so that the event can be scheduled on queue. The data contains only the length and the pointer of extra-data. The flag-bit type is <a class="el" href="group___seq_events.html#ga273f82dce70a0284a4dcabd34f1bfe7d">SND_SEQ_EVENT_LENGTH_VARIABLE</a>. A macro <a class="el" href="group___seq_middle.html#ga12ac15c961d96d3122f7c2f6a0849fb1" title="set variable data ">snd_seq_ev_set_variable()</a> is provided to set this type.</dd></dl>
<dl class="section user"><dt>User-space data</dt><dd>This type refers also an extra data space like variable length data, but the extra-data is not duplicated but but referred as a user-space data on kernel, so that it reduces the time and resource for transferring large bulk of data like synth sample wave. This data type, however, can be used only for direct dispatch mode, and supposed to be used only for a special purpose like a bulk data transfer. The data length and pointer are stored also in data.ext field as well as variable length data. The flag-bit type is <a class="el" href="group___seq_events.html#ga5e38e6cf87f023332b797c30b74223b1">SND_SEQ_EVENT_LENGTH_VARUSR</a>. A macro <a class="el" href="group___seq_middle.html#ga993e1f46d8122a227fa0072a73af813e" title="set varusr data ">snd_seq_ev_set_varusr()</a> is provided to set this type.</dd></dl>
<h2><a class="anchor" id="seq_ev_sched"></a>
Scheduling priority</h2>
<p>There are two priorities for scheduling: </p><dl class="section user"><dt>Normal priority</dt><dd>If an event with the same scheduling time is already present on the queue, the new event is appended to the older. </dd></dl>
<dl class="section user"><dt>High priority</dt><dd>If an event with the same scheduling time is already present on the queue, the new event is inserted before others.</dd></dl>
<p>The scheduling priority is set in the flag bitfeld masked by <a class="el" href="group___seq_events.html#gaea7b84a517451282036dad991a45239c">SND_SEQ_PRIORITY_MASK</a>. A macro <a class="el" href="group___seq_middle.html#ga9b6fba99052fb11977559f15192581d4" title="set event priority ">snd_seq_ev_set_priority()</a> is provided to set the mode type.</p>
<h1><a class="anchor" id="seq_queue"></a>
Event Queues</h1>
<h2><a class="anchor" id="seq_ev_control"></a>
Creation of a queue</h2>
<p>Creating a queue is done usually by calling <a class="el" href="group___seq_queue.html#ga036e62b321b56bee2e8d2e8280a6416a" title="allocate a queue ">snd_seq_alloc_queue</a>. You can create a queue with a certain name by <a class="el" href="group___seq_queue.html#ga8efa821e0fc96fd05460306808e8fb7d" title="allocate a queue with the specified name ">snd_seq_alloc_named_queue()</a>, too. </p><div class="fragment"><div class="line"><span class="comment">// create a queue and return its id</span></div>
<div class="line"><span class="keywordtype">int</span> my_queue(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *handle)</div>
<div class="line">{</div>
<div class="line">    <span class="keywordflow">return</span> <a class="code" href="group___seq_queue.html#ga8efa821e0fc96fd05460306808e8fb7d">snd_seq_alloc_named_queue</a>(handle, <span class="stringliteral">&quot;my queue&quot;</span>);</div>
<div class="line">}</div>
</div><!-- fragment --><p> These functions are the wrapper to the function <a class="el" href="group___seq_queue.html#ga05fc43229e94aecbb4379909200aeeae" title="create a queue ">snd_seq_create_queue()</a>. For releasing the allocated queue, call <a class="el" href="group___seq_queue.html#ga5b2cf5082861776ac9f7f986459cbccf" title="delete the specified queue ">snd_seq_free_queue()</a> with the obtained queue id.</p>
<p>Once when a queue is created, the two queues are associated to that queue record in fact: one is the realtime queue and another is the tick queue. These two queues are bound together to work synchronously. Hence, when you schedule an event, you have to choose which queue type is used as described in the section <a class="el" href="seq.html#seq_ev_time">Time stamp</a>.</p>
<h2><a class="anchor" id="seq_ev_tempo"></a>
Setting queue tempo</h2>
<p>The tempo (or the speed) of the scheduling queue is variable. In the case of <em>tick</em> queue, the tempo is controlled in the manner of MIDI. There are two parameters to define the actual tempo, PPQ (pulse per quarter note) and MIDI tempo. The former defines the base resolution of the ticks, while the latter defines the beat tempo in microseconds. As default, 96 PPQ and 120 BPM are used, respectively. That is, the tempo is set to 500000 (= 60 * 1000000 / 120). Note that PPQ cannot be changed while the queue is running. It must be set before the queue is started.</p>
<p>On the other hand, in the case of <em>realtime</em> queue, the time resolution is fixed to nanoseconds. There is, however, a parameter to change the speed of this queue, called <em>skew</em>. You can make the queue faster or slower by setting the skew value bigger or smaller. In the API, the skew is defined by two values, the skew base and the skew value. The actual skew is the fraction of them, <em>value/base</em>. As default, the skew base is set to 16bit (0x10000) and the skew value is the identical, so that the queue is processed as well as in the real world.</p>
<p>When the tempo of realtime queue is changed, the tempo of the associated tick queue is changed together, too. That's the reason why two queues are created always. This feature can be used to synchronize the event queue with the external synchronization source like SMPTE. In such a case, the realtime queue is skewed to match with the external source, so that both the realtime timestamp and the MIDI timestamp are synchronized.</p>
<p>For setting these tempo parameters, use <a class="el" href="group___seq_queue.html#ga8cef04796cda140f86f8e6298f26b4da">snd_seq_queue_tempo_t</a> record. For example, to set the tempo of the queue <code>q</code> to 48 PPQ, 60 BPM, </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> set_tempo(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *handle)</div>
<div class="line">{</div>
<div class="line">        <a class="code" href="group___seq_queue.html#ga8cef04796cda140f86f8e6298f26b4da">snd_seq_queue_tempo_t</a> *tempo;</div>
<div class="line">        <a class="code" href="group___seq_queue.html#ga8b8349b2bce37cde49359bbbcd47f765">snd_seq_queue_tempo_alloca</a>(&amp;tempo);</div>
<div class="line">        <a class="code" href="group___seq_queue.html#ga4b0488b65a0ca46460c92d80afa53681">snd_seq_queue_tempo_set_tempo</a>(tempo, 1000000); <span class="comment">// 60 BPM</span></div>
<div class="line">        <a class="code" href="group___seq_queue.html#ga69e4bf372ce3fb49b8fa60130472ba47">snd_seq_queue_tempo_set_ppq</a>(tempo, 48); <span class="comment">// 48 PPQ</span></div>
<div class="line">        <a class="code" href="group___seq_queue.html#ga84793898d689520441a4c1164a8c0c77">snd_seq_set_queue_tempo</a>(handle, tempo);</div>
<div class="line">}</div>
</div><!-- fragment --><p>For changing the (running) queue's tempo on the fly, you can either set the tempo via <a class="el" href="group___seq_queue.html#ga84793898d689520441a4c1164a8c0c77" title="set the tempo of the queue ">snd_seq_set_queue_tempo()</a> or send a MIDI tempo event to the system timer port. For example, </p><div class="fragment"><div class="line"><span class="keywordtype">int</span> change_tempo(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *handle, <span class="keywordtype">int</span> q, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> tempo)</div>
<div class="line">{</div>
<div class="line">    <a class="code" href="structsnd__seq__event__t.html">snd_seq_event_t</a> ev;</div>
<div class="line">    <a class="code" href="group___seq_middle.html#gafa496482a21b231621b385d1f1675b58">snd_seq_ev_clear</a>(&amp;ev);</div>
<div class="line">    ev.<a class="code" href="structsnd__seq__event__t.html#adcdb44ac09b5f7ca6f791740fee5e51c">dest</a>.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = <a class="code" href="group___sequencer.html#ga5437f98c59679c92ee4d940ac643169e">SND_SEQ_CLIENT_SYSTEM</a>;</div>
<div class="line">    ev.<a class="code" href="structsnd__seq__event__t.html#adcdb44ac09b5f7ca6f791740fee5e51c">dest</a>.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = <a class="code" href="group___seq_port.html#ga02870ceddec24d3cc5609ec728b0cb92">SND_SEQ_PORT_SYSTEM_TIMER</a>;</div>
<div class="line">    ev.<a class="code" href="structsnd__seq__event__t.html#a7043d2583446dfcb3da764d803b4a03a">source</a>.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = my_client_id;</div>
<div class="line">    ev.<a class="code" href="structsnd__seq__event__t.html#a7043d2583446dfcb3da764d803b4a03a">source</a>.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = my_port_id;</div>
<div class="line">    ev.<a class="code" href="structsnd__seq__event__t.html#a3357b5c3701e93e62eff0bb43f10b6e0">queue</a> = <a class="code" href="group___seq_queue.html#ga2a5be7ea9ad68adc9a7288ba25850245">SND_SEQ_QUEUE_DIRECT</a>; <span class="comment">// no scheduling</span></div>
<div class="line">    ev.<a class="code" href="structsnd__seq__event__t.html#a650448b8f926bddb313dd4c34ff5eeae">data</a>.<a class="code" href="structsnd__seq__event__t.html#a3357b5c3701e93e62eff0bb43f10b6e0">queue</a>.queue = q;    <span class="comment">// affected queue id</span></div>
<div class="line">    ev.<a class="code" href="structsnd__seq__event__t.html#a650448b8f926bddb313dd4c34ff5eeae">data</a>.<a class="code" href="structsnd__seq__event__t.html#a3357b5c3701e93e62eff0bb43f10b6e0">queue</a>.value = tempo;    <span class="comment">// new tempo in microsec.</span></div>
<div class="line">    <span class="keywordflow">return</span> <a class="code" href="group___seq_event.html#ga0360e41b946c9948ad717beef7c5ab61">snd_seq_event_output</a>(handle, &amp;ev);</div>
<div class="line">}</div>
</div><!-- fragment --><p> There is a helper function to do this easily, <a class="el" href="group___seq_middle.html#gab77f13c0b39dec12ef983eb706925d00" title="change the tempo of the specified queue ">snd_seq_change_queue_tempo()</a>. Set NULL to the last argument, if you don't need any special settings.</p>
<p>In the above example, the tempo is changed immediately after the buffer is flushed by <a class="el" href="group___seq_event.html#ga64a0ed5488504ef91b5b6b92172bc0aa" title="drain output buffer to sequencer ">snd_seq_drain_output()</a> call. You can schedule the event in a certain queue so that the tempo change happens at the scheduled time, too.</p>
<h2><a class="anchor" id="seq_ev_start"></a>
Starting and stopping a queue</h2>
<p>To start, stop, or continue a queue, you need to send a queue-control event to the system timer port as well. There are helper functions, <a class="el" href="group___seq_middle.html#ga0c7a86bb19188a00c5a3b4907d558058" title="start the specified queue ">snd_seq_start_queue()</a>, <a class="el" href="group___seq_middle.html#gab62a2e964135fdff96d21835d4cddad6" title="stop the specified queue ">snd_seq_stop_queue()</a> and <a class="el" href="group___seq_middle.html#gad6b0c90be37eeb583318c9077f095b86" title="continue the specified queue ">snd_seq_continue_queue()</a>. Note that if the last argument of these functions is NULL, the event is sent (i.e. operated) immediately after the buffer flush. If you want to schedule the event at the certain time, set up the event record and provide the pointer of that event record as the argument.</p>
<p>Only calling these functions doesn't deliver the event to the sequencer core but only put to the output buffer. You'll need to call <a class="el" href="group___seq_event.html#ga64a0ed5488504ef91b5b6b92172bc0aa" title="drain output buffer to sequencer ">snd_seq_drain_output()</a> eventually.</p>
<h1><a class="anchor" id="seq_subs_more"></a>
More inside the subscription</h1>
<h2><a class="anchor" id="seq_subs_perm"></a>
Permissions</h2>
<p>Each ALSA port can have capability flags. The most basic capability flags are <a class="el" href="group___seq_port.html#ga81a7a5385af746364b757eb7911ec2f0">SND_SEQ_PORT_CAP_READ</a> and <a class="el" href="group___seq_port.html#gae8afb5ac8f546461b4bab25454972aeb">SND_SEQ_PORT_CAP_WRITE</a>. The former means that the port allows to send events to other ports, whereas the latter capability means that the port allows to receive events from other ports. You may have noticed that meanings of <code>READ</code> and <code>WRITE</code> are permissions of the port from the viewpoint of other ports.</p>
<p>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, <a class="el" href="group___seq_port.html#ga4b8aa6cbeb3c99c3ad033f4ce69c06e2">SND_SEQ_PORT_CAP_SUBS_READ</a> and <a class="el" href="group___seq_port.html#ga52ff1c51578166e67936cfb826c966c0">SND_SEQ_PORT_CAP_SUBS_WRITE</a> are used, respectively. For example, the port with MIDI input device always has <a class="el" href="group___seq_port.html#ga4b8aa6cbeb3c99c3ad033f4ce69c06e2">SND_SEQ_PORT_CAP_SUBS_READ</a> capability, and the port with MIDI output device always has <a class="el" href="group___seq_port.html#ga52ff1c51578166e67936cfb826c966c0">SND_SEQ_PORT_CAP_SUBS_WRITE</a> capability together with <a class="el" href="group___seq_port.html#ga81a7a5385af746364b757eb7911ec2f0">SND_SEQ_PORT_CAP_READ</a> and <a class="el" href="group___seq_port.html#gae8afb5ac8f546461b4bab25454972aeb">SND_SEQ_PORT_CAP_WRITE</a> capabilities, respectively. Obviously, these flags have no influence if <code>READ</code> or <code>WRITE&gt;</code> capability is not set.</p>
<p>Note that these flags are not necessary if the client subscribes itself to the specified port. For example, when a port makes READ subscription to MIDI input port, this port must have <a class="el" href="group___seq_port.html#gae8afb5ac8f546461b4bab25454972aeb">SND_SEQ_PORT_CAP_WRITE</a> capability, but no <a class="el" href="group___seq_port.html#ga52ff1c51578166e67936cfb826c966c0">SND_SEQ_PORT_CAP_SUBS_WRITE</a> capability is required. Only MIDI input port must have <a class="el" href="group___seq_port.html#ga4b8aa6cbeb3c99c3ad033f4ce69c06e2">SND_SEQ_PORT_CAP_SUBS_READ</a> capability.</p>
<p>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 <a class="el" href="group___seq_port.html#gaa0a63e34744ed9faedf64fe0b364bfd4">SND_SEQ_PORT_CAP_NO_EXPORT</a> 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.</p>
<h2><a class="anchor" id="seq_subs_handle"></a>
Subscription handlers</h2>
<p>In ALSA library, subscription is done via <a class="el" href="group___seq_subscribe.html#ga2b216ec66cd724af31d376398e7b4863" title="subscribe a port connection ">snd_seq_subscribe_port()</a> function. It takes the argument of <a class="el" href="group___seq_subscribe.html#gafdf1b5614ce0d591c86bfcd3f369fa38">snd_seq_port_subscribe_t</a> record pointer. Suppose that you have a client which will receive data from a MIDI input device. The source and destination addresses are like the below; </p><div class="fragment"><div class="line"><a class="code" href="structsnd__seq__addr__t.html">snd_seq_addr_t</a> sender, dest;</div>
<div class="line">sender.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = MIDI_input_client;</div>
<div class="line">sender.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = MIDI_input_port;</div>
<div class="line">dest.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = my_client;</div>
<div class="line">dest.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = my_port;</div>
</div><!-- fragment --><p> To set these values as the connection call like this. </p><div class="fragment"><div class="line"><a class="code" href="group___seq_subscribe.html#gafdf1b5614ce0d591c86bfcd3f369fa38">snd_seq_port_subscribe_t</a> *subs;</div>
<div class="line"><a class="code" href="group___seq_subscribe.html#ga1ce0255bad553e69da93b929279e6e88">snd_seq_port_subscribe_alloca</a>(&amp;subs);</div>
<div class="line"><a class="code" href="group___seq_subscribe.html#gabda2bb1e51927155ad1df1701a337f50">snd_seq_port_subscribe_set_sender</a>(subs, &amp;sender);</div>
<div class="line"><a class="code" href="group___seq_subscribe.html#ga0ab685bdf4e1f0dd8be756cb5f089765">snd_seq_port_subscribe_set_dest</a>(subs, &amp;dest);</div>
<div class="line"><a class="code" href="group___seq_subscribe.html#ga2b216ec66cd724af31d376398e7b4863">snd_seq_subscribe_port</a>(handle, subs);</div>
</div><!-- fragment --><p>When the connection should be exclusively done only between a certain pair, set <em>exclusive</em> attribute to the subscription record before calling <a class="el" href="group___seq_subscribe.html#ga2b216ec66cd724af31d376398e7b4863" title="subscribe a port connection ">snd_seq_subscribe_port</a>. </p><div class="fragment"><div class="line"><a class="code" href="group___seq_subscribe.html#ga10b7e0184afa49bed2b871bcd1c310c0">snd_seq_port_subscribe_set_exclusive</a>(subs, 1);</div>
</div><!-- fragment --><p> The succeeding subscriptions will be refused.</p>
<p>The timestamp can be updated independently on each connection. When set up, the timestamp of incoming queue to the destination port is updated automatically to the time of the specified queue. </p><div class="fragment"><div class="line"><a class="code" href="group___seq_subscribe.html#ga9ae181ecaea97317fa724a80e8ce4f21">snd_seq_port_subscribe_set_time_update</a>(subs, 1);</div>
<div class="line"><a class="code" href="group___seq_subscribe.html#ga79a030e6155c66afe94b81f77b8575cf">snd_seq_port_subscribe_set_queue</a>(subs, q);</div>
</div><!-- fragment --><p> For getting the wallclock time (sec/nsec pair), set <em>real</em> attribute: </p><div class="fragment"><div class="line"><a class="code" href="group___seq_subscribe.html#ga14bac64ec25eb4acbfc828657ad8d25d">snd_seq_port_subscribe_set_time_real</a>(subs, 1);</div>
</div><!-- fragment --><p> 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.</p>
<p>Note that an outsider client may connect other ports. In this case, however, the subscription may be refused if <a class="el" href="group___seq_port.html#gaa0a63e34744ed9faedf64fe0b364bfd4">SND_SEQ_PORT_CAP_NO_EXPORT</a> capability is set in either sender or receiver port.</p>
<h1><a class="anchor" id="seq_subs_ex"></a>
Examples of subscription</h1>
<h2><a class="anchor" id="seq_subs_ex_capt"></a>
Capture from keyboard</h2>
<p>Assume MIDI input port = 64:0, application port = 128:0, and queue for timestamp = 1 with real-time stamp. The application port must have capability <a class="el" href="group___seq_port.html#gae8afb5ac8f546461b4bab25454972aeb">SND_SEQ_PORT_CAP_WRITE</a>. </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> capture_keyboard(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *seq)</div>
<div class="line">{</div>
<div class="line">        <a class="code" href="structsnd__seq__addr__t.html">snd_seq_addr_t</a> sender, dest;</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#gafdf1b5614ce0d591c86bfcd3f369fa38">snd_seq_port_subscribe_t</a> *subs;</div>
<div class="line">        sender.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = 64;</div>
<div class="line">        sender.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = 0;</div>
<div class="line">        dest.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = 128;</div>
<div class="line">        dest.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = 0;</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga1ce0255bad553e69da93b929279e6e88">snd_seq_port_subscribe_alloca</a>(&amp;subs);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#gabda2bb1e51927155ad1df1701a337f50">snd_seq_port_subscribe_set_sender</a>(subs, &amp;sender);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga0ab685bdf4e1f0dd8be756cb5f089765">snd_seq_port_subscribe_set_dest</a>(subs, &amp;dest);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga79a030e6155c66afe94b81f77b8575cf">snd_seq_port_subscribe_set_queue</a>(subs, 1);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga9ae181ecaea97317fa724a80e8ce4f21">snd_seq_port_subscribe_set_time_update</a>(subs, 1);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga14bac64ec25eb4acbfc828657ad8d25d">snd_seq_port_subscribe_set_time_real</a>(subs, 1);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga2b216ec66cd724af31d376398e7b4863">snd_seq_subscribe_port</a>(seq, subs);</div>
<div class="line">}</div>
</div><!-- fragment --><h2><a class="anchor" id="seq_subs_ex_out"></a>
Output to MIDI device</h2>
<p>Assume MIDI output port = 65:1 and application port = 128:0. The application port must have capability <a class="el" href="group___seq_port.html#ga81a7a5385af746364b757eb7911ec2f0">SND_SEQ_PORT_CAP_READ</a>. </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> subscribe_output(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *seq)</div>
<div class="line">{</div>
<div class="line">        <a class="code" href="structsnd__seq__addr__t.html">snd_seq_addr_t</a> sender, dest;</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#gafdf1b5614ce0d591c86bfcd3f369fa38">snd_seq_port_subscribe_t</a> *subs;</div>
<div class="line">        sender.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = 128;</div>
<div class="line">        sender.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = 0;</div>
<div class="line">        dest.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = 65;</div>
<div class="line">        dest.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = 1;</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga1ce0255bad553e69da93b929279e6e88">snd_seq_port_subscribe_alloca</a>(&amp;subs);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#gabda2bb1e51927155ad1df1701a337f50">snd_seq_port_subscribe_set_sender</a>(subs, &amp;sender);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga0ab685bdf4e1f0dd8be756cb5f089765">snd_seq_port_subscribe_set_dest</a>(subs, &amp;dest);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga2b216ec66cd724af31d376398e7b4863">snd_seq_subscribe_port</a>(seq, subs);</div>
<div class="line">}</div>
</div><!-- fragment --><p> This example can be simplified by using <a class="el" href="group___seq_middle.html#gab39e210c5d93e96c241644f334c6c9ca" title="simple subscription (w/o exclusive & time conversion) ">snd_seq_connect_to()</a> function. </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> subscribe_output(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *seq)</div>
<div class="line">{</div>
<div class="line">        <a class="code" href="group___seq_middle.html#gab39e210c5d93e96c241644f334c6c9ca">snd_seq_connect_to</a>(seq, 0, 65, 1);</div>
<div class="line">}</div>
</div><!-- fragment --><h2><a class="anchor" id="seq_subs_ex_arbit"></a>
Arbitrary connection</h2>
<p>Assume connection from application 128:0 to 129:0, and that subscription is done by the third application (130:0). The sender must have capabilities both <a class="el" href="group___seq_port.html#ga81a7a5385af746364b757eb7911ec2f0">SND_SEQ_PORT_CAP_READ</a> and <a class="el" href="group___seq_port.html#ga4b8aa6cbeb3c99c3ad033f4ce69c06e2">SND_SEQ_PORT_CAP_SUBS_READ</a>, and the receiver <a class="el" href="group___seq_port.html#gae8afb5ac8f546461b4bab25454972aeb">SND_SEQ_PORT_CAP_WRITE</a> and <a class="el" href="group___seq_port.html#ga52ff1c51578166e67936cfb826c966c0">SND_SEQ_PORT_CAP_SUBS_WRITE</a>, respectively. </p><div class="fragment"><div class="line"><span class="comment">// ..in the third application (130:0) ..</span></div>
<div class="line"><span class="keywordtype">void</span> coupling(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *seq)</div>
<div class="line">{</div>
<div class="line">        <a class="code" href="structsnd__seq__addr__t.html">snd_seq_addr_t</a> sender, dest;</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#gafdf1b5614ce0d591c86bfcd3f369fa38">snd_seq_port_subscribe_t</a> *subs;</div>
<div class="line">        sender.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = 128;</div>
<div class="line">        sender.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = 0;</div>
<div class="line">        dest.<a class="code" href="structsnd__seq__addr__t.html#aaf81b043e95acd9a939dbb8bae4e9d81">client</a> = 129;</div>
<div class="line">        dest.<a class="code" href="structsnd__seq__addr__t.html#a2bc35b6df26bf6b37e4c032b8522873d">port</a> = 0;</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga1ce0255bad553e69da93b929279e6e88">snd_seq_port_subscribe_alloca</a>(&amp;subs);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#gabda2bb1e51927155ad1df1701a337f50">snd_seq_port_subscribe_set_sender</a>(subs, &amp;sender);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga0ab685bdf4e1f0dd8be756cb5f089765">snd_seq_port_subscribe_set_dest</a>(subs, &amp;dest);</div>
<div class="line">        <a class="code" href="group___seq_subscribe.html#ga2b216ec66cd724af31d376398e7b4863">snd_seq_subscribe_port</a>(seq, subs);</div>
<div class="line">}</div>
</div><!-- fragment --><h1><a class="anchor" id="seq_ex_event"></a>
Event Processing</h1>
<h2><a class="anchor" id="seq_ex_address"></a>
Addressing</h2>
<p>Now, two ports are connected by subscription. Then how to send events?</p>
<p>The subscribed port doesn't have to know the exact sender address. Instead, there is a special address for subscribers, <a class="el" href="group___sequencer.html#ga383b235d2afbe48704952edfd3a33eed">SND_SEQ_ADDRESS_SUBSCRIBERS</a>. The sender must set this value as the destination client. Destination port is ignored.</p>
<p>The other values in source and destination addresses are identical with the normal event record. If the event is scheduled, proper queue and timestamp values must be set.</p>
<p>There is a convenient function to set the address in an event record. In order to set destination as subscribers, use <a class="el" href="group___seq_middle.html#ga1eb546b3a1a23044d0ba7818731ed6d7" title="set broadcasting to subscribers ">snd_seq_ev_set_subs()</a>.</p>
<h2><a class="anchor" id="Scheduled"></a>
Delivery</h2>
<p>If we send an event at the scheduled time <code>t</code> (tick) on the queue <code>Q</code>, the sender must set both schedule queue and time in the event record. The program appears like this: </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> schedule_event(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *seq)</div>
<div class="line">{</div>
<div class="line">        <a class="code" href="structsnd__seq__event__t.html">snd_seq_event_t</a> ev;</div>
<div class="line"></div>
<div class="line">        <a class="code" href="group___seq_middle.html#gafa496482a21b231621b385d1f1675b58">snd_seq_ev_clear</a>(&amp;ev);</div>
<div class="line">        <a class="code" href="group___seq_middle.html#ga457525dcca4a8a7e8cdb599a8ad6e8ff">snd_seq_ev_set_source</a>(&amp;ev, my_port);</div>
<div class="line">        <a class="code" href="group___seq_middle.html#ga1eb546b3a1a23044d0ba7818731ed6d7">snd_seq_ev_set_subs</a>(&amp;ev);</div>
<div class="line">        <a class="code" href="group___seq_middle.html#ga589469c27715bfae205ce26d5801d8b1">snd_seq_ev_schedule_tick</a>(&amp;ev, Q, 0, t);</div>
<div class="line">        ... <span class="comment">// set event type, data, so on..</span></div>
<div class="line"></div>
<div class="line">        <a class="code" href="group___seq_event.html#ga0360e41b946c9948ad717beef7c5ab61">snd_seq_event_output</a>(seq, &amp;ev);</div>
<div class="line">        ...</div>
<div class="line">        <a class="code" href="group___seq_event.html#ga64a0ed5488504ef91b5b6b92172bc0aa">snd_seq_drain_output</a>(seq);  <span class="comment">// if necessary</span></div>
<div class="line">}</div>
</div><!-- fragment --><p> Of course, you can use realtime stamp, too.</p>
<h2><a class="anchor" id="seq_ex_direct"></a>
Direct Delivery</h2>
<p>If the event is sent immediately without enqueued, the sender doesn't take care of queue and timestamp. As well as the case above, there is a function to set the direct delivery, <a class="el" href="group___seq_middle.html#gae2674210b5601e8aa3e787c1ddbdcb62" title="set direct passing mode (without queued) ">snd_seq_ev_set_direct()</a>. The program can be more simplified as follows: </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> direct_delivery(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *seq)</div>
<div class="line">{</div>
<div class="line">        <a class="code" href="structsnd__seq__event__t.html">snd_seq_event_t</a> ev;</div>
<div class="line"></div>
<div class="line">        <a class="code" href="group___seq_middle.html#gafa496482a21b231621b385d1f1675b58">snd_seq_ev_clear</a>(&amp;ev);</div>
<div class="line">        <a class="code" href="group___seq_middle.html#ga457525dcca4a8a7e8cdb599a8ad6e8ff">snd_seq_ev_set_source</a>(&amp;ev, port);</div>
<div class="line">        <a class="code" href="group___seq_middle.html#ga1eb546b3a1a23044d0ba7818731ed6d7">snd_seq_ev_set_subs</a>(&amp;ev);</div>
<div class="line">        <a class="code" href="group___seq_middle.html#gae2674210b5601e8aa3e787c1ddbdcb62">snd_seq_ev_set_direct</a>(&amp;ev);</div>
<div class="line">        ... <span class="comment">// set event type, data, so on..</span></div>
<div class="line"></div>
<div class="line">        <a class="code" href="group___seq_event.html#ga0360e41b946c9948ad717beef7c5ab61">snd_seq_event_output</a>(seq, &amp;ev);</div>
<div class="line">        <a class="code" href="group___seq_event.html#ga64a0ed5488504ef91b5b6b92172bc0aa">snd_seq_drain_output</a>(seq);</div>
<div class="line">}</div>
</div><!-- fragment --><p> You should flush event soon after output event. Otherwise, the event is enqueued on output queue of ALSA library (not in the kernel!), and will be never processed until this queue becomes full.</p>
<h2><a class="anchor" id="seq_ex_filter"></a>
Filter Application</h2>
<p>A typical filter program, which receives an event and sends it immediately after some modification, will appear as following: </p><div class="fragment"><div class="line"><span class="keywordtype">void</span> event_filter(<a class="code" href="group___sequencer.html#gae141149958a7458806152ed5942a1acd">snd_seq_t</a> *seq, <a class="code" href="structsnd__seq__event__t.html">snd_seq_event_t</a> *ev)</div>
<div class="line">{</div>
<div class="line">        <span class="keywordflow">while</span> (<a class="code" href="group___seq_event.html#ga6421feafcd6f116d34531d6b54177c17">snd_seq_event_input</a>(seq, &amp;ev) &gt;= 0) {</div>
<div class="line">                <span class="comment">//.. modify input event ..</span></div>
<div class="line"></div>
<div class="line">                <a class="code" href="group___seq_middle.html#ga457525dcca4a8a7e8cdb599a8ad6e8ff">snd_seq_ev_set_source</a>(ev, my_port);</div>
<div class="line">                <a class="code" href="group___seq_middle.html#ga1eb546b3a1a23044d0ba7818731ed6d7">snd_seq_ev_set_subs</a>(ev);</div>
<div class="line">                <a class="code" href="group___seq_middle.html#gae2674210b5601e8aa3e787c1ddbdcb62">snd_seq_ev_set_direct</a>(ev);</div>
<div class="line">                <a class="code" href="group___seq_event.html#ga0360e41b946c9948ad717beef7c5ab61">snd_seq_event_output</a>(seq, ev);</div>
<div class="line">                <a class="code" href="group___seq_event.html#ga64a0ed5488504ef91b5b6b92172bc0aa">snd_seq_drain_output</a>(seq);</div>
<div class="line">        }</div>
<div class="line">}</div>
</div><!-- fragment --> </div></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Wed Jun 18 2014 05:47:49 for ALSA project - the C library reference by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.7
</small></address>
</body>
</html>