Dev docs: Music Provider (#559)
authorMarvin Schenkel <marvinschenkel@gmail.com>
Wed, 22 Mar 2023 15:48:22 +0000 (16:48 +0100)
committerGitHub <noreply@github.com>
Wed, 22 Mar 2023 15:48:22 +0000 (16:48 +0100)
* Add music provider docs

DEVELOPMENT.md

index fb4f566f42033dda3e58a1d9d91178db7d5ed651..6a0b197e832446a2b334fd50859ac4900eb3d00c 100644 (file)
@@ -16,8 +16,39 @@ With this repository cloned locally, execute the following commands in a termina
 * Hit (Fn +) F5 to start Music Assistant locally
 * The pre-compiled UI of Music Assistant will be available at `localhost:8095` đźŽ‰
 
+All code is linted and verified using [pre-commit](https://pre-commit.com/). To make sure that all these checks are executed successfully *before* you push your code:
+* `pip install pre-commit`
+* `pre-commit install`
+This ensures that the pre-commit checks kick in when you create a commit locally.
+
+The Music Assistant server is fully built in Python. The Python language has no real supported for multi-threading. This is why Music Assistant heavily relies on asyncio to handle blocking IO. It is important to get a good understanding of asynchronous programming before building your first provider. [This](https://www.youtube.com/watch?v=M-UcUs7IMIM) video is an excellent first step in the world of asyncio.
+
 ## đźŽµ Building your own Music Provider
-Will follow soon™
+A Music Provider is one of the provider types that adds support for a 'source of music' to Music Assistant. Spotify and Youtube Music are examples of a Music Provider, but also Filesystem and SMB can be put in the Music Provider category. All Music Providers can be found in the `music_assistant/server/providers` folder.
+
+**Adding the necessary files for a new Music Provider**
+
+Add a new folder to the `providers` folder with the name of provider. Add two files inside:
+1. `__init__.py`. This file contains the Python code of your provider.
+2. `manifest.json`. This file contains metadata and configuration for your provider.
+
+**Configuring the manifest.json file**
+
+The easiest way to get start is to copy the contents of the manifest of an existing Music Provider, e.g. Spotify or Youtube Music. See [the manifest section](#⚙️-manifest-file) for all available properties.
+
+**Creating the provider**
+
+Create a file called `__init__.py` inside the folder of your provider. This file will contain the logic for the provider. All Music Providers must inherit from the [`MusicProvider`](./music_assistant/server/models/music_provider.py) base class and override the necessary functions where applicable. A few things to note:
+* The `setup()` function is called by Music Assistant upon initialization of the provider. It gives you the opportunity the prepare the provider for usage. For example, logging in a user or obtaining a token can be done in this function.
+* A provider should let Music Assistant know which [`ProviderFeatures`](./music_assistant/common/models/enums.py) it supports by implementing the property `supported_features`, which returns a list of `ProviderFeatures`.
+* The actual playback of audio in Music Assistant happens in two phases:
+    1. `get_stream_details()` is called to obtain information about the audio, like the quality, format, # of channels etc.
+    2. `get_audio_stream()` is called to stream raw bytes of audio to the player. There are a few [helpers](./music_assistant/server/helpers/audio.py) to help you with this. Note that this function is not applicable to direct url streams.
+* Examples:
+    1. Streaming raw bytes using an external executable (librespot) to get audio, see the [Spotify](./music_assistant/server/providers/spotify/__init__.py) provider as an example
+    2. Streaming a direct URL, see the [Youtube Music](.//music_assistant/server/providers/ytmusic/__init__.py) provider as an example
+    3. Streaming an https stream that uses an expiring URL, see the [Qobuz](./music_assistant/server/providers/qobuz/__init__.py) provider as an example
+
 
 ## â–¶ď¸Ź Building your own Player Provider
 Will follow soon™
@@ -27,3 +58,22 @@ Will follow soon™
 
 ## đź”Ś Building your own Plugin Provider
 Will follow soon™
+
+## âš™ď¸Ź Manifest file
+The manifest file contains metadata and configuration about a provider. The supported properties are:
+| Name  | Description  | Type  |
+|---|---|---|
+| type  | `music`, `player`, `metadata` or `plugin`  | string  |
+| domain  | The internal unique id of the provider, e.g. `spotify` or `ytmusic`  | string  |
+| name  | The full name of the provider, e.g. `Spotify` or `Youtube Music`  | string  |
+| description  | The full description of the provider  | string  |
+| codeowners  | List of Github names of the codeowners of the provider  | array[string]  |
+| config_entries  | List of configurable properties for the provider, e.g. `username` or `password`*. | array[object]  |
+| config_entries.key  | The unique key of the config entry, used to obtain the value in the provider code  | string  |
+| config_entries.type  | The type of the config entry. Possible values: `string`, `secure_string` (for passwords), `boolean`, `float`, `integer`, `label` (for a single line of text in the settings page)  | string  |
+| config_entries.label | The label of the config entry. Used in the settings page | string |
+| requirements | List of requirements for the provider in pip string format. Supported values are `package==version` and `git+https://gitrepoforpackage` | array[string]
+| documentation | URL to the Github discussion containing the documentation for the provider. | string |
+| multi_instances | Whether multiple instances of the configuration are supported, e.g. multiple user accounts for Spotify | boolean |
+
+\* These `config_entries` are used to automatically generate the settings page for the provider in the front-end. The values can be obtained via `self.config.get_value(key)`.