Commit 9601ac58 authored by David Boddie's avatar David Boddie
Browse files

Merge branch 'sound-apis' into 'master'

Add documentation and example showing how to play sounds

See merge request Librem5/developer.puri.sm!384
parents 3e2fe48a 5edff69f
......@@ -28,3 +28,6 @@
[submodule "Apps/Examples/General/Simple_Weather/app"]
path = Apps/Examples/General/Simple_Weather/app
url = https://source.puri.sm/Librem5/example-apps/simple-weather-app.git
[submodule "Apps/Examples/Audio/Play_Sounds/app"]
path = Apps/Examples/Audio/Play_Sounds/app
url = https://source.puri.sm/Librem5/example-apps/play-sounds.git
.. |main-file| replace:: ``play-sounds.in``
.. |executable| replace:: ``play-sounds``
.. |desktop-entry-in| replace:: ``com.example.play_sounds.desktop.in``
.. |desktop-entry| replace:: ``com.example.play_sounds.desktop``
.. |desktop-entry-ref| replace:: desktop entry file
.. |svg-file| replace:: ``com.example.play_sounds.svg``
.. include:: /Apps/Examples/common/Building_the_App.txt
.. _Audio_Play_Sounds_example_data:
Data Files
==========
The application relies on standard sound files for two of its sounds. It also requires two additional sound files to be installed. These data files are described in files that are processed by the Meson_ build tool.
Describing the Files
--------------------
The ``data/sounds`` directory contains the custom sound files that the application needs at run-time. These are installed with the rest of the application's code and resources in a standard location, then :ref:`accessed when required <Audio_Play_Sounds_example_Playing_Sounds>`.
In the repository, the files are simply stored within the ``data/sounds`` directory. The ``meson.build`` file contains the following rule to copy them into the application's data directory when the application is installed:
.. literalinclude:: app/data/meson.build
:language: python3
:start-at: install_subdir('sounds',
:end-at: )
The location of the data directory is provided to the application by the ``config`` Python module that is generated when the application is installed.
.. include:: /links.txt
.. |project| replace:: https://source.puri.sm/Librem5/example-apps
.. |repo| replace:: play-sounds.git
.. |project-repo| replace:: ``https://source.puri.sm/Librem5/example-apps/play-sounds.git``
.. include:: /Apps/Examples/common/Getting_the_App.txt
.. |manifest| replace:: ``com.example.play_sounds.json``
.. |manifest-path| replace:: app/com.example.play_sounds.json
.. |app-id| replace:: com.example.play_sounds
.. |extra-permissions-info| replace:: We also specify the ``--socket=pulseaudio`` permission to request access to the phone's sound system, as described in the :ref:`flatpak_app_permissions_guide` guide.
.. |meson-app-module| replace:: play_sounds
.. |extra-module-info| replace:: The application's module follows the entry for the ``gsound`` library in the manifest because it is not included in the GNOME 3.34 runtime the application uses.
.. include:: ../../common/Packaging_the_App.txt
.. _Audio_Play_Sounds_example_src:
Source Files
============
Most of the code for the application is included in a single ``main.py`` file which contains a single ``Application`` class to manage the running of the application and a ``main`` function to start it.
.. contents::
:local:
Much of the code is very similar to other examples and tutorials. We will focus on the parts that are specific to this example.
Relevant Modules
----------------
We use the ``GSound`` module to enable us to play sounds in a simple way. This module is imported in the same way as the ``Gtk`` module:
.. literalinclude:: app/src/main.py
:language: python3
:start-at: import os
:end-at: config
The ``config`` module contains a few definitions that allow us to locate the supplied sound files so that they can be played.
Setting up the User Interface
-----------------------------
The application provides an ``Application`` class with the usual methods to set up the application and perform tasks when it is run. The window is defined in a UI file, created using :ref:`gnome_glade`, but used in a different way to the UI file included with the :ref:`Treasure example <examples_Treasure_user_interface>`.
In this example, we use the ``Gtk.Template`` decorator to make a ``Window`` class that represents the window defined in the UI file. An instance of this class is created in the ``Application`` class. The ``Window`` class begins by relating the definition with objects that represent its child widgets:
.. literalinclude:: app/src/main.py
:language: python3
:start-at: @Gtk.Template
:end-at: invader_button
In the ``__init__`` method, the state of these child widgets is determined by whether it is possible to initialize a sound context, represented by an instance of the `GSound.Context`_ class:
.. literalinclude:: app/src/main.py
:language: python3
:start-at: def __init__
:end-at: invader_button
If a sound context cannot be initialized, all of these buttons will be non-interactive. With an initialized context, any of the buttons can be clicked to cause a sound to play. This is handled by a collection of callback methods that are automatically connected to signals defined in the UI file.
.. _Audio_Play_Sounds_example_Playing_Sounds:
Playing Sounds
--------------
Each of the buttons are connected to a callback where an appropriate sound is played. The first of these plays a standard sound that is usually associated with a desktop event:
.. literalinclude:: app/src/main.py
:language: python3
:start-at: @Gtk.Template.Callback()
:end-before: #1
The `play_simple`_ method of the sound context that was created earlier is used to play the standard “complete” sound. The method accepts a dictionary that describes the sound to be played, and the `ATTR_EVENT_ID`_ key is used to specify that an event sound is to be played, with the value being the name of the sound.
We also want to play custom sounds, and we do this in a very similar way, using the same `play_simple`_ method. However, we pass a dictionary containing the `ATTR_MEDIA_FILENAME`_ key to indicate that the sound is supplied in a file, and with a value that is the name of the file itself:
.. literalinclude:: app/src/main.py
:language: python3
:start-after: #2
:end-before: #3
As a result, when the user clicks the appropriate button, the ``fanfare.ogg`` file is loaded and played. To obtain the location of this file, we use the value held by the ``config.pkgdatadir`` constant. This is provided by the ``config`` Python module that is generated when the application is installed.
Summary
-------
One of the simplest ways to play sounds is by creating a `GSound.Context`_ object, initializing it before it is used, then using its `play_simple`_ method to play sounds. Both standard event sounds and custom sound files can be played.
The dictionary passed to this method is used to specify which kind of sound will be played, where `ATTR_EVENT_ID`_ is useful for playing simple sounds provided with the system, and `ATTR_MEDIA_FILENAME`_ is used to play custom sounds provided with the application.
.. include:: /links.txt
.. _`ATTR_EVENT_ID`: https://lazka.github.io/pgi-docs/#GSound-1.0/constants.html#GSound.ATTR_EVENT_ID
.. _`play_simple`: https://lazka.github.io/pgi-docs/#GSound-1.0/classes/Context.html#GSound.Context.play_simple
.. _`ATTR_MEDIA_FILENAME`: https://lazka.github.io/pgi-docs/#GSound-1.0/constants.html#GSound.ATTR_MEDIA_FILENAME
.. _examples_Audio_Play_Sounds_summary:
Summary
=======
Applications can play sounds from a standard collection of event sounds using the `GSound.Context` API. This API also allows sound files packaged with the application to be played. These files are supplied as additional data files and are installed into locations on the phone's filing system.
When distributed as a flatpak, the manifest needs to include the ``--socket=pulseaudio`` permission that allows the application to access the phone's sound system.
.. include:: /links.txt
.. _`play_simple`: https://lazka.github.io/pgi-docs/#GSound-1.0/classes/Context.html#GSound.Context.play_simple
Subproject commit 8778def5a1f8cbfa45496e423a005967ed65a9bf
.. _examples_Audio_Play_Sounds:
Play Sounds
===========
This example demonstrates a simple way to play sound files. When run, the application presents allows a small set of sounds to be played by pressing a number of buttons.
.. image:: images/screenshot.png
:scale: 50%
:align: center
:alt: A screenshot of the application running in the phone environment
In :ref:`Audio_Play_Sounds_example_src` we focus on the parts of the application that respond to user input by playing the sound files. In :ref:`Audio_Play_Sounds_example_data` we describe how the sound files are handled by the build system.
.. toctree::
:maxdepth: 1
Getting_the_App
Source_Code
Data_Files
Building_the_App
Packaging_the_App
Summary
.. include:: /links.txt
......@@ -3,5 +3,7 @@
.. |app-id| replace:: com.example.pictures
.. |extra-permissions-info| replace:: We also specify the ``--filesystem=xdg-pictures`` permission to request access to the user's *Pictures* directory, as described in the :ref:`flatpak_app_permissions_guide` guide.
.. |meson-app-module| replace:: pictures
.. |extra-module-info| replace:: The application's module follows the entry for the `libhandy library`_:
.. include:: ../../common/Packaging_the_App.txt
.. include:: /links.txt
......@@ -3,5 +3,6 @@
.. |app-id| replace:: com.example.simple_weather
.. |extra-permissions-info| replace:: The applications also requires access to the network. Other permissions will be required if you want to store and modify settings for your application, access peripherals, and perform other tasks that require the user's consent.
.. |meson-app-module| replace:: simple_weather
.. |extra-module-info| replace:: The application's module follows the entries for the other dependencies:
.. include:: ../../common/Packaging_the_App.txt
......@@ -3,5 +3,7 @@
.. |app-id| replace:: com.example.treasure
.. |extra-permissions-info| replace:: Other permissions will be required if you want to store and modify settings for your application, access peripherals, and perform other tasks that require the user's consent.
.. |meson-app-module| replace:: treasure
.. |extra-module-info| replace:: The application's module follows the entry for the `libhandy library`_:
.. include:: ../../common/Packaging_the_App.txt
.. include:: /links.txt
......@@ -3,5 +3,6 @@
.. |app-id| replace:: com.example.network_state
.. |extra-permissions-info| replace:: We also specify the ``--share=network`` permission so that the application can access the network.
.. |meson-app-module| replace:: network_state
.. |extra-module-info| replace:: The application's module is usually the last in the list:
.. include:: ../../common/Packaging_the_App.txt
......@@ -54,7 +54,7 @@ Modules
The ``modules`` list describes the application components (or modules),
including any dependencies that need to be bundled with it, in a list of
dictionaries. The application's module is usually the last in the list:
dictionaries. |extra-module-info|
.. include-par:: |manifest-path|
:start-at: "name": "|meson-app-module|"
......
......@@ -22,6 +22,7 @@ information about the APIs used by applications.
Networking/NetworkState/index
Files/Pictures/index
Audio/Play_Sounds/index
General/Treasure/index
General/Simple_Weather/index
......
.. _audio_guide:
Working with Audio
==================
The Librem 5 phone is supplied with various peripherals for playing and recording audio. This guide provides an overview of how the system manages audio and describes how to use audio features in applications.
.. contents::
:local:
Overview
--------
.. note:: This section will cover the use of audio in general and the APIs available. It will also cover the sound devices (speaker, headphones, microphone, modem) and specific APIs used to interact with them.
Playing Sounds
--------------
Applications written using Python and GTK can play sounds using the `GSound`_ API that is used for playing sounds when system events occur. The :ref:`examples_Audio_Play_Sounds` example uses this API to play both standard event sounds and sound files provided with the application.
.. include:: /links.txt
......@@ -10,6 +10,7 @@ to encounter. We aim to add more guides to this collection over time.
.. toctree::
:maxdepth: 1
Audio/index
Design/index
Networking/index
Permissions/index
......
......@@ -58,6 +58,8 @@
.. _`g_set_application_name`: https://developer.gnome.org/glib/stable/glib-Miscellaneous-Utility-Functions.html#g-set-application-name
.. _`GSimpleAction`: https://developer.gnome.org/gio/2.60/GSimpleAction.html
.. _`GSettings`: https://developer.gnome.org/gio/stable/GSettings.html
.. _`GSound`: https://lazka.github.io/pgi-docs/#GSound-1.0
.. _`GSound.Context`: https://lazka.github.io/pgi-docs/#GSound-1.0/classes/Context.html
.. _`GTK 3 documentation`: https://developer.gnome.org/gtk3/stable/
.. _GtkApplication: https://developer.gnome.org/gtk3/stable/GtkApplication.html
.. _`Gtk.Application`: https://lazka.github.io/pgi-docs/#Gtk-3.0/classes/Application.html
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment