--- /dev/null
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--- /dev/null
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = 'musicpdaio'
+copyright = '2024, kaliko'
+author = 'kaliko'
+release = '0.0.1'
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.intersphinx',
+ 'sphinx.ext.viewcode',
+ 'sphinx.ext.todo',
+]
+
+templates_path = ['_templates']
+exclude_patterns = []
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_theme = 'alabaster'
+html_static_path = ['_static']
+html_theme_options = {
+ 'page_width' : '1024px',
+ 'fixed_sidebar': 'true',
+ }
+
+# -- Options for intersphinx extension ---------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#configuration
+
+intersphinx_mapping = {
+ 'python': ('https://docs.python.org/3', None),
+}
--- /dev/null
+.. _explanations:
+
+Explanations
+============
+
+What is musicpdaio?
+-------------------
+
+ | « Concurrency is about dealing with lots of things at once. »
+ | Concurrency is not Parallelism -- Rob Pike
+
+**musicpdaio** is the asyncio_ port of python-musicpd_.
+
+The goal of this project is to keep python-musicpd_ simplicity and provide
+asyncio_ support.
+
+Should I use it?
+----------------
+
+ * If you need a plain MPD client to manage you MPD server, then stick with
+ no-ansynio module python-musicpd_
+ * If you're building a interactive client, concurrent access to MPD or plugin
+ into another asyncio project then use musicpdaio.
+
+
+Using the client library
+-------------------------
+
+The client library can be used as follows:
+
+.. code-block:: python
+
+ client = mpdaio.MPDClient() # create client object
+ await client.ping() # test the connection, using default host/port, cf. Reference
+ print(client.version) # print the MPD protocol version
+ await client.setvol('42') # sets the volume
+ await client.close() # disconnect from the server
+
+The MPD command protocol exchanges line-based text records. The client emits a
+command with optional arguments. In the example above the client sends a
+`setvol` command with the string argument `42`.
+
+MPD commands are exposed as :py:class:`mpdaio.MPDClient` methods. Methods
+**arguments are python strings**. Some commands are composed of more than one word
+(ie "**tagtypes [disable|enable|all]**"), for these use a `snake case`_ style to
+access the method. Then **"tagtypes enable"** command is called with
+**"tagtypes_enable"**.
+
+Remember MPD protocol is text based, then all MPD command arguments are UTF-8
+strings. In the example above, an integer can be used as argument for the
+`setvol` command, but it is then evaluated as a string when the command is
+written to the socket. To avoid confusion use regular string instead of relying
+on object string representation.
+
+:py:class:`mpdaio.MPDClient` methods returns different kinds of objects
+depending on the command. Could be :py:obj:`None`, a single object as a
+:py:obj:`str` or a :py:obj:`dict`, a list of :py:obj:`dict`.
+
+Then :py:class:`mpdaio.MPDClient` **methods signatures** are not hard coded
+within this module since the protocol is handled on the server side. Please
+refer to the protocol and MPD commands in `MPD protocol documentation`_ to
+learn how to call commands and what kind of arguments they expect.
+
+Some examples are provided for the most common cases, see :ref:`tutorial`.
+
+For a list of currently supported commands in this python module see
+:ref:`commands`.
+
+**musicpdaio** tries to come with sane defaults, then running
+:py:class:`mpdaio.MPDClient` with no explicit argument will try defaults values
+to connect to MPD. Cf. :ref:`reference` for more about defaults.
+
+
+.. _environment_variables:
+
+
+.. _snake case: https://en.wikipedia.org/wiki/Snake_case
+.. _MPD protocol documentation: http://www.musicpd.org/doc/protocol/
+.. _asyncio: https://docs.python.org/3/library/asyncio.html
+.. _python-musicpd: https://kaliko.gitlab.io/python-musicpd
+
+.. vim: spell spelllang=en
--- /dev/null
+Welcome to musicpdaio's documentation!
+======================================
+
+The documentation is structured by following the `Diátaxis`_ principles:
+tutorials and explanation are mainly useful to discover and learn, howtos and
+reference are more useful when you are familiar with musicpdaio already and you
+have some specific action to perform or goal to achieve.
+
+.. toctree::
+ :maxdepth: 2
+
+ tutorial
+ explanations
+ reference
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+.. _Diátaxis: https://diataxis.fr/
--- /dev/null
+.. _reference:
+
+Reference
+=========
+
+Environment variables
+---------------------
+
+:py:class:`mpdaio.MPDClient` honors the following environment variables:
+
+.. envvar:: MPD_HOST
+
+ MPD host (:abbr:`FQDN (fully qualified domain name)`, IP, socket path or abstract socket) and password.
+
+ | To define a **password** set :envvar:`MPD_HOST` to "*password@host*" (password only "*password@*")
+ | For **abstract socket** use "@" as prefix : "*@socket*" and then with a password "*pass@@socket*"
+ | Regular **unix socket** are set with an absolute path: "*/run/mpd/socket*"
+
+.. envvar:: MPD_PORT
+
+ MPD port, relevant for TCP socket only
+
+.. envvar:: MPD_TIMEOUT
+
+ socket timeout when connecting to MPD and waiting for MPD’s response (in seconds)
+
+.. envvar:: XDG_RUNTIME_DIR
+
+ path to look for potential socket
+
+.. _default_settings:
+
+Default settings
+----------------
+
+Default host:
+ * use :envvar:`MPD_HOST` environment variable if set, extract password if present,
+ * else looks for an existing file in :envvar:`${XDG_RUNTIME_DIR:-/run/}/mpd/socket`
+ * else set host to ``localhost``
+
+Default port:
+ * use :envvar:`MPD_PORT` environment variable is set
+ * else use ``6600``
+
+Default timeout:
+ * use :envvar:`MPD_TIMEOUT` is set
+ * else use :py:obj:`mpdaio.CONNECTION_TIMEOUT`
+
+
+Changelog
+---------
+
+No release yet
--- /dev/null
+.. _tutorial:
+
+Tutorials
+=========
+
+Install
+-------
+
+For now the code is in early development stage. No releases are made.
+
+.. code:: bash
+
+ # Use a virtualenv
+ python -m venv .../path/to/my/venv
+ . .../path/to/my/venv/bin/activate
+ pip install git+https://codeberg.org/MusicPlayerDaemon/python-musicpdaio.git@main
+
+
+.. todo::
+
+ Updating a previous installation via `pip install git+https`.
+
+Getting started
+----------------
+
+
+.. literalinclude:: tutorial/tutorial-00.py
+
+
+Concurrency
+-----------
+
+.. literalinclude:: tutorial/tutorial-01.py
+
+
+.. vim: spell spelllang=en
--- /dev/null
+../../../mpdaio
\ No newline at end of file
--- /dev/null
+import asyncio
+import logging
+
+from mpdaio.client import MPDClient
+
+# Configure loggers
+logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
+logging.getLogger("asyncio").setLevel(logging.WARNING)
+# debug level level will show where defaults settings come from
+log = logging.getLogger('mpdaio.client')
+log.setLevel(logging.DEBUG)
+
+
+async def run():
+ # Explicit host declaration
+ #client = MPDClient(host='example.org', port='6601')
+
+ # Use defaults
+ client = MPDClient()
+ # MPDClient use MPD_HOST/MPD_PORT env var if set
+ # else test ${XDG_RUNTIME_DIR}/mpd/socket for existence
+ # finnally fallback to localhost:6600
+
+ # Make an initial connection to MPD server
+ # The connection is kept open an reused for later commands
+ await client.ping()
+
+ status = await client.status()
+ if status.get('state') == 'play':
+ current_song_id = status.get('songid')
+ current_song = await client.playlistid(current_song_id)
+ log.info(f'Playing : {current_song[0].get("file")}')
+ next_song_id = status.get('nextsongid', None)
+ if next_song_id:
+ next_song = await client.playlistid(next_song_id)
+ log.info(f'Next song : {next_song[0].get("file")}')
+ else:
+ log.info('Not playing')
+
+ # Closes any remaining connections to MPD server
+ await client.close()
+
+
+if __name__ == '__main__':
+ asyncio.run(run())
--- /dev/null
+import asyncio
+import logging
+
+from mpdaio.client import MPDClient
+
+# Configure loggers
+logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
+logging.getLogger("asyncio").setLevel(logging.WARNING)
+# debug level level will show where defaults settings come from
+log = logging.getLogger('mpdaio.client')
+log.setLevel(logging.DEBUG)
+
+
+async def run():
+ # Use defaults to access MPD server
+ client = MPDClient()
+
+ # Make an initial connection to MPD server
+ # The connection is kept open an reused for later commands
+ await client.ping()
+
+ # Each task gathered here will run with it's own connection
+ await asyncio.gather(...)
+
+ # Closes all connections to MPD server
+ await client.close()
+
+
+if __name__ == '__main__':
+ asyncio.run(run())