Latest revision |
Your text |
Line 26: |
Line 26: |
| # Linux boots | | # Linux boots |
| # systemd gives root the current audio device | | # systemd gives root the current audio device |
| # systemd starts espeakup as root | | # systemd starts starts espeakup as root |
| # You can read the login prompt or login as root | | # You can read the login prompt or login as root |
| # You log in as your own user | | # You log in as your own user |
Line 49: |
Line 49: |
| == Existing solutions == | | == Existing solutions == |
| Here are some solutions that kind of work but have severe trade-offs. | | Here are some solutions that kind of work but have severe trade-offs. |
|
| |
| === Running PulseAudio system-wide ===
| |
| Running system-wide PulseAudio allows you to always have espeakup running and talking regardless of who is currently logged in.
| |
|
| |
| However this has a major security concern, mainly that all users can now play and record audio from your sound card and other applications. For more information see [https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/WhatIsWrongWithSystemWide/ What is wrong with system mode?]
| |
|
| |
| Running PipeWire system-wide is a little more complicated: You need to run both the PipeWire daemon and a session manager system-wide. This session manager needs to lock hardware and not give it up on seat switch.
| |
|
| |
| I'm not going to include instructions on how to do this as I can't provide support for it. Sorry.
| |
|
| |
|
| === Running espeakup as your user === | | === Running espeakup as your user === |
| It's possible to run espeakup as your own user by:
| | - udev rule |
|
| |
|
| * Taking control of the audio device away from logind
| | - linger |
| * Giving control of all audio devices to your user
| |
| * Giving control of the softsynth to your user
| |
| * Running espeakup as a daemon as your user
| |
| * Running espeakup at boot as your user
| |
|
| |
|
| I've prepared steps to follow to get this working below.
| | - root can't use it |
|
| |
|
| Paste lines between <code>--- PASTE START ---</code> and <code>--- PASTE END ---</code> in to the file specified or a terminal.
| | - no early boot access |
|
| |
|
| Step 1: Put this in <code>/etc/modules-load.d/speakup.conf</code>
| | - seat switching |
|
| |
|
| --- PASTE START ---
| | === Running PulseAudio system-wide === |
| speakup
| | - pulseaudio runs at boot and all is well |
| speakup_soft
| |
| --- PASTE END ---
| |
| | |
| This will cause the speakup kernel modules to load at boot.
| |
| | |
| Step 2: Put this in <code>/etc/udev/rules.d/99-speakup.rules</code>
| |
| | |
| --- PASTE START ---
| |
| SUBSYSTEM=="sound", TAG-="seat", GROUP="audio"
| |
| KERNEL=="softsynth*", GROUP="audio"
| |
| --- PASTE END ---
| |
| | |
| This will will do three things:
| |
|
| |
|
| # Stop logind managing sound devices
| | https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SystemWide/ |
| # Give users in the audio group access to sound devices
| |
| # Give users in the audio group access to Speakup
| |
|
| |
|
| Step 3: Put this in <code>~/.config/systemd/user/espeakup.service</code>
| | - security!! |
|
| |
|
| --- PASTE START ---
| | TODO: does this even work? |
| [Unit]
| |
| Description=Software speech output for Speakup
| |
| After=pulseaudio.service
| |
| [Service]
| |
| Environment="default_voice= ALSA_CARD="
| |
| ExecStart=/usr/bin/espeakup -d --default-voice=${default_voice}
| |
| Restart=always
| |
| Nice=-10
| |
| OOMScoreAdjust=-900
| |
| [Install]
| |
| WantedBy=default.target
| |
| --- PASTE END ---
| |
|
| |
|
| This is a service that just runs the espeakup daemon. It is set to start after pulseaudio.
| | - no early boot acces |
|
| |
|
| Change <code>pulseaudio.service</code> to <code>pipewire.service</code> if you're using on PipeWire.
| | - unsucessful with pipewire- seat switching still impact whether audio played and whether pipewire had access to the sound device |
|
| |
|
| Step 4: Run these commands in a terminal as your user:
| | - pipewire session manager talks to hardware |
|
| |
|
| --- PASTE START ---
| | - pipewire server does IPC between apps and everything else |
| systemctl --user enable espeakup
| |
| loginctl enable-linger
| |
| sudo gpasswd -a $USER audio
| |
| --- PASTE END ---
| |
|
| |
|
| This does three things:
| | - pipewire server must run as root |
|
| |
|
| # Enable the speakup user service
| | - session manager must run as unprivileged user or something |
| # Enable running user services when logged out
| |
| # Add your user to the audio group
| |
|
| |
|
| Step 5: Reboot and enjoy!
| | - alsa plugins for espeakup |
| | |
| There's two downsides to this method:
| |
| | |
| # Your user can see what other users are reading, including root
| |
| # Other users can't play audio
| |
|
| |
|
| == Ideas == | | == Ideas == |
| There are some ideas I've considered to solve this problem. | | There are some ideas I've considered to solve this problem. |
|
| |
|
| === Loaning PulseAudio to root === | | === Locking PulseAudio after boot === |
| The main case here would be to allow root to use a user's PulseAudio install.
| | TODO: ... |
|
| |
|
| This would have mean that multiple people can privately use a computer, with the exception of one user being able to read root's screen.
| | === Sharing Speakup === |
| | - have a proxy that sits between speakup and espeak |
|
| |
|
| I'm not too sure what this buys compared to using sudo or something to act as root.
| | - send messages to espeakup instances based on current active UID |
|
| |
|
| In practice I'm not sure how easy this would be to implement. You would need to replace the logind hardware management for sound with something else that allows finer grained management of hardware.
| | - during a switch between instances, wait for the current instance to finish talking OR the stop talking control is sent. then start feeding the new instance data |
| === Sharing Speakup between multiple users ===
| |
| Things would be a lot easier if we could run one espeakup instance per user. This is tricky because the Speakup kernel modules don't have concepts of users or sessions.
| |
|
| |
|
| There's a wide list of engineering problems to solve with this:
| | - have a shim that blocks pulseaudio from starting until it has permission, but also don't consume the buffer |
|
| |
|
| * Saving and restoring per-user Speakup settings
| | i do not like how i'm basically reinventing flow control but poorly |
| * Saving and restoring the softsynth state between users
| |
| * Proxying /dev/softsynth so users can't read other's data
| |
| * Restricting access to the fakekey input device
| |
| * Handling graceful handovers from ALSA to PulseAudio
| |
| * Handling forceful handovers from PulseAudio to ALSA
| |
| * Shim PulseAudio so it waits for hardware access before running
| |
| * Flow control to indicate when the proxy is ready to send
| |
| * Flow control to indicate when espeakup is ready to talk
| |
| * Buffering data when espeakup isn't ready
| |
| * Discarding buffered data when speakup signals espeakup to shut up
| |
| * Handling messages sent back from espeakup to speakup and flow control for that
| |
|
| |
|
| There's a lot to untangle here since we're touching multiple levels of abstraction.
| | ok so it turns out i was WRONG: you can't share speakup protocol between multiple synths! the protocol is stateful! ie if you tell it to change voice and switch synth the voice change won't be applied. YAY |
|
| |
|
| === Sharing espeakup output between multiple users === | | === Sharing espeakup === |
| A more practical solution might be to run a root espeakup instance and proxy its PCM output to users.
| | so this makes the only viable solution to send PCM data from a root espeakup instance. |
|
| |
|
| This would cut down the engineering problems to:
| | on top of that this also means i have to modify espeakup to handle some flow control AND output to a buffer instead of the sound card |
|
| |
|
| * Assigning /sys/accessibility/speakup to the current seat
| | === Loaning PulseAudio to root === |
| * Proxying PCM data to stub programs users run
| | - the main case here is with root who doesn't have a pulseaudio setup |
| * Handling graceful handovers from ALSA to PulseAudio
| |
| * Shim PulseAudio so it waits for hardware access before running
| |
| * Flow control to indicate when a proxy is ready to send
| |
| * Buffering data when a stub isn't playing audio
| |
| * Discarding buffered data when espeakup wants to shut up
| |
|
| |
|
| This gives most the benefits of sharing speakup but without saving or restoring state.
| | - doesn't solve sharing speakup but maybe things could take turns? |
| [[Category:Research]]
| |