| digraph { |
| // This specifies a diagram using the DOT language. It can be interactively |
| // viewed with xdot or can generate an image using |
| // `dot -Tpng alsa_fsm.dot > alsa_fsm.png` |
| |
| // This was build out of the state transition information from |
| // linux/sound/core/pcm_native.c and linux/sound/core/pcm_lib.c. Since it is |
| // intended to help with writing software which uses ALSA's PCM interface, it |
| // includes every possible transition, even if they are unlikely, rather than |
| // trying to model a more typical software path. |
| |
| // snd_pcm_hw_free is called as a result of snd_pcm_close |
| // snd_pcm_hwsync is called before querying any hardware state such as in |
| // snd_pcm_avail. |
| |
| // From the perspective of the state machine, snd_pcm_capture_rewind and |
| // snd_pcm_playback rewind are the same function so they are not |
| // distinguished in this diagram. This also holds for the forward |
| // functions. |
| |
| // For all states the a SND_PCM_STATE_ prefix has been omitted to clarify |
| // the state machine. |
| |
| // For all transitions the snd_pcm_ prefix has been omitted to clarify |
| // the state machine. |
| |
| rankdir=BT; |
| |
| // Bulk processing |
| ANY [label = "any state"]; |
| ANY -> SUSPENDED [label = suspend]; |
| SUSPENDED -> ANY [label = resume]; |
| |
| // snd_pcm_dev_disconnect is the only kernel-only ALSA function included in |
| // this diagram because it is the only way to transition into the |
| // SNDRV_PCM_STATE_DISCONNECTED state and that state should be accounted for |
| // when designing code which directly interacts with ALSA and might use USB |
| // audio devices which may be disconnected in use. |
| ANY -> DISCONNECTED [label = dev_disconnect]; |
| ANY -> ANY [label = "info/hw_refine/unlink/sync_ptr/tstamp"]; |
| |
| NOT_OPEN [label = "any state but OPEN"] |
| NOT_OPEN -> NOT_OPEN [label = "sw_params/channel_info/link"]; |
| |
| // State-specific transitions. |
| unitialized [label="", shape=none]; |
| unitialized -> OPEN [label = open]; |
| |
| OPEN -> OPEN [label = hw_params]; |
| OPEN -> SETUP [label = hw_params]; |
| |
| SETUP -> OPEN [label = hw_free]; |
| SETUP -> SETUP [label = "hw_params/drain/drop"]; |
| SETUP -> PREPARED [label = prepare]; |
| |
| PREPARED -> OPEN [label = "hw_free/reset"]; |
| PREPARED -> SETUP [label = "hw_params/drop"]; |
| PREPARED -> PREPARED [label = "prepare/rewind/forward/hwsync/delay"]; |
| PREPARED -> RUNNING [label = "start/writei"]; |
| PREPARED -> DRAINING [label = drain]; |
| |
| RUNNING -> OPEN [label = reset]; |
| RUNNING -> SETUP [label = "drain/drop"]; |
| RUNNING -> RUNNING [label = "rewind/forward/hwsync/delay/writei"]; |
| RUNNING -> XRUN [label = "xrun/hwsync/writei"]; |
| RUNNING -> DRAINING [label = drain]; |
| RUNNING -> PAUSED [label = pause]; |
| |
| // snd_pcm_xrun is called if an xrun is detected by |
| // snd_pcm_hw_avail_update. It puts the kernel-based ALSA code into the |
| // SNDRV_PCM_STATE_XRUN state. |
| XRUN -> SETUP[label = "drain/drop"]; |
| XRUN -> PREPARED [label = prepare]; |
| XRUN -> XRUN [label = xrun]; |
| |
| DRAINING -> SETUP [label = "sw_params/status/drain/drop/delay"]; |
| DRAINING -> PREPARED [label = prepare]; |
| DRAINING -> DRAINING [label = "drain/rewind/forward"]; |
| |
| PAUSED -> OPEN [label = reset]; |
| PAUSED -> SETUP [label = "drain/drop"]; |
| PAUSED -> PREPARED [label = prepare]; |
| PAUSED -> RUNNING [label = pause]; |
| PAUSED -> DRAINING [label = drain]; |
| PAUSED -> PAUSED [label = "forward/writei"]; |
| |
| SUSPENDED -> OPEN [label = reset]; |
| SUSPENDED -> PREPARED [label = prepare]; |
| SUSPENDED -> SUSPENDED [label = "hwsync/delay"]; |
| |
| } |