roc-streaming / roc-toolkit

Real-time audio streaming over the network.
https://roc-streaming.org
Mozilla Public License 2.0
1.02k stars 203 forks source link

Split main() into a few functions #656

Open gavv opened 7 months ago

gavv commented 7 months ago

CLI tools main() became too large and needs refactoring. We could extract several functions, e.g.: building io config, building pipeline config, running pump.

This should be done for all three tools: roc-send, roc-recv, roc-copy.

Code: https://github.com/roc-streaming/roc-toolkit/tree/develop/src/tools Docs: https://roc-streaming.org/toolkit/docs/manuals.html

nolan-veed commented 6 months ago

I'll do.

gavv commented 6 months ago

Great!

nolan-veed commented 6 months ago

I'm having a hard time understanding the dependencies. I'm looking at roc_send main.cpp for example.

Various objects needs to be setup using args, and also depend on each other. So, any pointers on how to approach this will help. Right now, I'm a bit lost.

gavv commented 6 months ago

Yeah, that code definitely needs more love. Here is a little overview, HTH, and hopefully your refactoring will make it clearer.

High level goal of roc-send and roc-recv is to build source, sink, and pump.

Source is from where you can read samples. Sink is where you can write samples. Pump transfers samples from source to sink.

In roc-send, source is implemented by roc_sndio, and reads samples from file or device. And sink is provided by roc_node, specifically node::Sender, which sends samples written to it to remote receiver.

Internally, node::Sender creates pipeline (pipeline::SenderLoop) and network loop (netio::NetworkLoop) and connects them together.

pipeline::SenderLoop implements sink interface. When you write samples to it, it produces packets, which are then written to network loop and queued for sending.

main() builds two configs: pipeline::SenderConfig (for sending sink) and sndio::Config (for file/device source). I think building these two configs can be extracted into two functions.

Then main() parses endpoints and tells node::Sender to use them. This probably can also be extracted into a function.

The, finally, main() constructs Pump and tells it to transfer samples from source to sink. This can become a function as well.

Feel free to ask specific questions if you'll have more.

See also https://github.com/roc-streaming/roc-toolkit/blob/develop/docs%2Fsphinx%2Finternals%2Faudio_backends.rst

and https://roc-streaming.org/toolkit/docs/internals/code_structure.html

nolan-veed commented 4 months ago

Hey, thanks for the pointers. I didn't manage to spend a lot of time last month, so I'm looking at this now.

gavv commented 4 months ago

Cool, welcome back! :)