Audio library API review


I'm developing bliss, a library that performs audio analysis of songs, and uses them to make playlists that sound "right".

Some people used it to make plugins for audio players, but they all slightly differ on the way to analyze, store songs, etc.

So, I made a module to normalize it: it includes helpers to make a "song library", that aims at easing the work of people trying to use bliss for audio players (it also contains tests, so people can be "fairly" confident it works :smiley: ).

I have no experience designing that though, so I'm wondering, how do you feel this API could be improved? Let's say you had an audio player with functions such as get_songs() -> Vec<PathBuf> to get the paths of songs in your player, as well as play_songs(songs: Vec<PathBuf>), would these helpers really ease your life?

I have several pain points in mind, but there are probably a lot of others, so feel free to just browse and tell me everything that doesn't feel right :slight_smile: :

  • The discoverability: people would most likely hit this page GitHub - Polochon-street/bliss-rs: A song analysis library for making playlists, and my idea would be to make interested people go to bliss_audio::library - Rust - would there be better way to "advertise" that functionality than what I currently do?
  • The documentation: there is this page bliss_audio::library - Rust, but also some examples, as well as a "reference implementation"
  • I currently have a main Library struct, that basically performs all the operations, contains the configuration, etc. However, people will most likely will want to extend it with fields that don't go into configuration, and other functions (for example, if you want a connection to the music server, etc). One way to do that would be to have for instance an MPDLibrary { library: Library, extra_info: ... }. Are there better ways to do that?
  • Should this part of the library really use anyhow errors? Or should it have more "detailed" error types?
  • The current wait to initialize a configuration struct is to do Config::new(config_path, database_path, number_cores), which are all Options with valid defaults. Are there more idiomatic ways to do that?

There are again probably a ton of other somehow weird things happening in the API, so don't hesitate to point them out :sweat_smile: