123 lines
3.5 KiB
Plaintext
123 lines
3.5 KiB
Plaintext
@startuml
|
|
!theme plain
|
|
hide empty description
|
|
|
|
title Placed audio player - command loop and worker detail
|
|
|
|
skinparam backgroundColor transparent
|
|
skinparam shadowing false
|
|
skinparam roundcorner 14
|
|
skinparam ArrowThickness 1.2
|
|
skinparam DefaultFontName "DejaVu Sans"
|
|
skinparam DefaultFontSize 13
|
|
|
|
skinparam state {
|
|
BackgroundColor #F8F8F8
|
|
BorderColor #555555
|
|
FontColor #222222
|
|
StartColor #555555
|
|
EndColor #555555
|
|
|
|
BackgroundColor<<blue>> #DCEEFF
|
|
BorderColor<<blue>> #3A7FC4
|
|
FontColor<<blue>> #123A63
|
|
|
|
BackgroundColor<<green>> #E3F6E3
|
|
BorderColor<<green>> #3C9D40
|
|
FontColor<<green>> #1E5C22
|
|
|
|
BackgroundColor<<orange>> #FFE8CC
|
|
BorderColor<<orange>> #D8842A
|
|
FontColor<<orange>> #7A4A12
|
|
|
|
BackgroundColor<<red>> #FFE5E5
|
|
BorderColor<<red>> #CC3333
|
|
FontColor<<red>> #7A1F1F
|
|
|
|
BackgroundColor<<gray>> #F2F2F2
|
|
BorderColor<<gray>> #888888
|
|
FontColor<<gray>> #444444
|
|
}
|
|
|
|
state "Command loop:\nreplace active worker" as A <<gray>> {
|
|
[*] -down-> CurrentWorkerActive
|
|
|
|
state "Current worker active" as CurrentWorkerActive <<orange>>
|
|
state "Interrupt requested" as InterruptRequested <<green>>
|
|
state "Waiting for worker" as WaitingForWorker <<green>>
|
|
state "Starting new worker" as StartingNewWorker <<orange>>
|
|
state "New worker active" as NewWorkerActive <<orange>>
|
|
|
|
InterruptRequested : entry / feed-interrupted := #t
|
|
InterruptRequested : entry / ao-clear-async
|
|
InterruptRequested : entry / player-state := stopped
|
|
InterruptRequested : entry / audio-stop
|
|
|
|
WaitingForWorker : do / wait until feeding-audio = #f
|
|
|
|
StartingNewWorker : entry / thread-wait
|
|
StartingNewWorker : entry / audio-open
|
|
StartingNewWorker : entry / player-state := playing
|
|
StartingNewWorker : entry / spawn worker
|
|
|
|
CurrentWorkerActive -down-> InterruptRequested : open(new)
|
|
InterruptRequested -down-> WaitingForWorker
|
|
WaitingForWorker -down-> StartingNewWorker : ready
|
|
StartingNewWorker -down-> NewWorkerActive
|
|
|
|
NewWorkerActive -down-> [*]
|
|
}
|
|
|
|
state "Worker thread lifecycle" as B <<gray>> {
|
|
[*] -down-> WorkerIdle
|
|
|
|
state "WorkerIdle" as WorkerIdle <<blue>>
|
|
state "WorkerExited" as WorkerExited <<blue>>
|
|
state "WorkerFailed" as WorkerFailed <<red>>
|
|
|
|
WorkerIdle -down-> C : open(file)\n/ audio-open\nspawn worker
|
|
|
|
state "Worker active" as C <<orange>> {
|
|
C : entry / feeding-audio := #t
|
|
C : exit / feeding-audio := #f
|
|
|
|
[*] -right-> Reading
|
|
|
|
state "Reading" as Reading <<orange>>
|
|
state "DrainingAO" as DrainingAO <<green>>
|
|
state "MarkStopped" as MarkStopped <<blue>>
|
|
state "WorkerDone" as WorkerDone <<blue>>
|
|
|
|
Reading : do / audio-read
|
|
Reading : pause #t / ao-pause #t and wait
|
|
Reading : pause #f / ao-pause #f
|
|
|
|
DrainingAO : do / wait until AO queue drains
|
|
DrainingAO : pause #t / ao-pause #t
|
|
DrainingAO : pause #f / ao-pause #f
|
|
|
|
Reading -right-> DrainingAO : audio-read returns\n[not feed-interrupted]\n/ emit audio-done
|
|
DrainingAO -right-> MarkStopped : [AO queue empty\nand file-id is current]
|
|
MarkStopped -right-> WorkerDone : / player-state := stopped
|
|
WorkerDone -right-> [*]
|
|
|
|
Reading -down-> WorkerDone : [feed-interrupted]\n/ feed-interrupted := #f
|
|
DrainingAO -down-> WorkerDone : [AO closed,\nqueue grows,\nor old file-id]
|
|
|
|
note bottom of DrainingAO
|
|
The file-id check prevents an old worker
|
|
from stopping a newly opened file.
|
|
end note
|
|
}
|
|
|
|
C -down-> WorkerExited : worker exits
|
|
C -down-> WorkerFailed : exception\n/ emit exception\nplayer-state := stopped
|
|
|
|
WorkerExited -down-> [*]
|
|
WorkerFailed -down-> [*]
|
|
}
|
|
|
|
A -[hidden]right-> B
|
|
|
|
|
|
@enduml |