pipewire_python.controller API documentation

Edit on GitHub

# pipewire_python.controller

## Documentation

In the next pages you'll see documentation of each python component `controller.py`.

View Source

    """
    ## Documentation

    In the next pages you'll see documentation of each python component
    `controller.py`.
    """

    import warnings

    # Loading internal functions
    from ._utils import (
        _drop_keys_with_none_values,
        _execute_shell_command,
        _filter_by_type,
        _generate_command_by_dict,
        _generate_dict_interfaces,
        _generate_dict_list_targets,
        _get_dict_from_stdout,
        _print_std,
        _update_dict_by_dict,
    )

    # Loading constants Constants.py
    from ._constants import MESSAGES_ERROR, RECOMMENDED_FORMATS, RECOMMENDED_RATES

    # [DEPRECATED] [FLAKE8] TO_AVOID_F401 PEP8
    # [DEPRECATED] https://stackoverflow.com/a/31079085/10491422
    # NOW USED IN DOCUMENTATION
    # __all__ = [
    #     # Classes and fucntions to doc
    #     'Controller',
    #     # [DEPRECATED] Unused files pylint
    #     # "_print_std",
    #     # "_get_dict_from_stdout",
    #     # "_update_dict_by_dict",
    #     # "_drop_keys_with_none_values",
    #     # "_generate_command_by_dict",
    #     # "_execute_shell_command",
    # ]

    class Controller:
        """
        Class that controls pipewire command line interface
        with shell commands, handling outputs, loading default
        configs and more.
        """

        _pipewire_cli = {  # Help
            "--help": "--help",  # -h
            "--version": "--version",
            "--remote": None,  # -r
        }

        _pipewire_modes = {  # Modes
            "--playback": None,  # -p
            "--record": None,  # -r
            "--midi": None,  # -m
        }

        _pipewire_list_targets = {  # "--list-targets": None,
            "list_playblack": None,
            "list_record": None,
        }

        _pipewire_configs = {  # Configs
            "--media-type": None,  # *default=Audio
            "--media-category": None,  # *default=Playback
            "--media-role": None,  # *default=Music
            "--target": None,  # *default=auto
            "--latency": None,  # *default=100ms (SOURCE FILE if not specified)
            "--rate": None,  # *default=48000
            "--channels": None,  # [1,2] *default=2
            "--channel-map": None,  # ["stereo", "surround-51", "FL,FR"...] *default="FL,FR"
            "--format": None,  # [u8|s8|s16|s32|f32|f64] *default=s16
            "--volume": None,  # [0.0,1.0] *default=1.000
            "--quality": None,  # -q # [0,15] *default=4
            "--verbose": None,  # -v
        }

        _kill_pipewire = {
            "all": ["kill", "$(pidof pw-cat)"],
            "playback": ["kill", "$(pidof pw-play)"],
            "record": ["kill", "$(pidof pw-record)"],
        }

        def __init__(
            self,
            # Debug
            verbose: bool = False,
        ):
            """This constructor load default configs from OS executing
            the following pipewire command

            ```bash
            #!/bin/bash
            # Get defaults from output of:
            pw-cat -h
            ```
            """
            # LOAD ALL DEFAULT PARAMETERS

            mycommand = ["pw-cat", "-h"]

            # get default parameters with help
            stdout, _ = _execute_shell_command(command=mycommand, verbose=verbose)  # stderr
            # convert stdout to dictionary
            dict_default_values = _get_dict_from_stdout(stdout=str(stdout.decode()), verbose=verbose)

            if verbose:
                print(self._pipewire_configs)

            # Save default system configs to our json
            self._pipewire_configs.update(
                ([(key, dict_default_values[key]) for key in dict_default_values])
            )

            if verbose:
                print(self._pipewire_configs)

            # Delete keys with None values
            self._pipewire_configs = _drop_keys_with_none_values(self._pipewire_configs)

            if verbose:
                print(self._pipewire_configs)

            # Load values of list targets
            self.load_list_targets(mode="playback", verbose=verbose)
            self.load_list_targets(mode="record", verbose=verbose)

        def _help_cli(
            self,
            # Debug
            verbose: bool = True,
        ):
            """Get pipewire command line help"""

            mycommand = ["pipewire", self._pipewire_cli["--help"]]

            stdout, _ = _execute_shell_command(command=mycommand, verbose=verbose)  # stderr

            return stdout

        def get_version(
            self,
            # Debug
            verbose: bool = False,
        ):
            """Get version of pipewire installed on OS by executing the following
            code:

            ```bash
            #!/bin/bash
            pw-cli --version
            ```

            Args:
                verbose (bool) : True enable debug logs. *default=False

            Returns:
                - versions (list) : Versions of pipewire compiled
            """

            mycommand = ["pw-cli", "--version"]

            if verbose:
                print(f"[mycommand]{mycommand}")

            stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
            versions = stdout.decode().split("\n")[1:]

            self._pipewire_cli["--version"] = versions

            return versions

        def verbose(
            self,
            status: bool = True,
        ):
            """Get full log of pipewire stream status with the command `pw-cat`

            An example of pw-cli usage is the code below:

            ```bash
            #!/bin/bash
            # For example
            pw-cat --playback beers.wav --verbose
            ```

            that will generate an output like this:

            ```bash
            opened file "beers.wav" format 00010002 channels:2 rate:44100
            using default channel map: FL,FR
            rate=44100 channels=2 fmt=s16 samplesize=2 stride=4 latency=4410 (0.100s)
            connecting playback stream; target_id=4294967295
            stream state changed unconnected -> connecting
            stream param change: id=2
            stream properties:
                media.type = "Audio"
                ...
            now=0 rate=0/0 ticks=0 delay=0 queued=0
            remote 0 is named "pipewire-0"
            core done
            stream state changed connecting -> paused
            stream param change: id=2
            ...
            stream param change: id=15
            stream param change: id=15
            now=13465394419270 rate=1/48000 ticks=35840 delay=512 queued=0
            now=13466525228363 rate=1/48000 ticks=90112 delay=512 queued=0
            ...
            stream drained
            stream state changed streaming -> paused
            stream param change: id=4
            stream state changed paused -> unconnected
            stream param change: id=4
            ```
            """

            if status:
                self._pipewire_configs["--verbose"] = "    "
            else:
                pass

        def get_config(self):
            """Return config dictionary with default or setup variables, remember that
            this object changes only on python-side. Is not updated on real time,
            For real-time, please create and destroy the class.

            Args:
                Nothing

            Returns:
                - _pipewire_configs (`dict`) : dictionary with config values

            """

            return self._pipewire_configs

        def set_config(
            self,
            # configs
            media_type=None,
            media_category=None,
            media_role=None,
            target=None,
            latency=None,
            rate=None,
            channels=None,
            channels_map=None,
            _format=None,
            volume=None,
            quality=None,
            # Debug
            verbose=False,
        ):
            """Method that get args as variables and set them
            to the `json` parameter of the class `_pipewire_configs`,
            then you can use in other method, such as `playback(...)` or
            `record(...)`. This method verifies values to avoid wrong
            settings.

            Args:
                media_type : Set media type
                media_category : Set media category
                media_role : Set media role
                target : Set node target
                latency : Set node latency *example=100ms
                rate : Set sample rate [8000,11025,16000,22050,44100,48000,88200,96000,176400,192000,352800,384000]
                channels : Numbers of channels [1,2]
                channels_map : ["stereo", "surround-51", "FL,FR", ...]
                _format : ["u8", "s8", "s16", "s32", "f32", "f64"]
                volume : Stream volume [0.000, 1.000]
                quality : Resampler quality [0, 15]
                verbose (`bool`): True enable debug logs. *default=False

            Returns:
                - Nothing

            More:
                Check all links listed at the beginning of this page
            """  # 1 - media_type
            if media_type:
                self._pipewire_configs["--media-type"] = str(media_type)
            elif media_type is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[media_type='{media_type}'] EMPTY VALUE"
                )
            # 2 - media_category
            if media_category:
                self._pipewire_configs["--media-category"] = str(media_category)
            elif media_category is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[media_category='{media_category}'] EMPTY VALUE"
                )
            # 3 - media_role
            if media_role:
                self._pipewire_configs["--media-role"] = str(media_role)
            elif media_role is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[media_role='{media_role}'] EMPTY VALUE"
                )
            # 4 - target
            if target:
                self._pipewire_configs["--target"] = str(target)
            elif target is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[target='{target}'] EMPTY VALUE")
            # 5 - latency
            if latency:
                if any(chr.isdigit() for chr in latency):  # Contain numbers
                    self._pipewire_configs["--latency"] = str(latency)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[latency='{latency}'] NO NUMBER IN VARIABLE"
                    )
            elif latency is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[latency='{latency}'] EMPTY VALUE")
            # 6 - rate
            if rate:
                if rate in RECOMMENDED_RATES:
                    self._pipewire_configs["--rate"] = str(rate)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[rate='{rate}']\
                             VALUE NOT IN RECOMMENDED LIST \n{RECOMMENDED_RATES}"
                    )
            elif rate is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[rate='{rate}'] EMPTY VALUE")
            # 7 - channels
            if channels:
                if channels in [1, 2]:  # values
                    self._pipewire_configs["--channels"] = str(channels)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[channels='{channels}']\
                             WRONG VALUE\n ONLY 1 or 2."
                    )
            elif channels is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[channels='{channels}'] EMPTY VALUE")
            # 8 - channels-map
            if channels_map:
                self._pipewire_configs["--channels-map"] = str(channels_map)
            elif channels_map is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[channels_map='{channels_map}'] EMPTY VALUE"
                )
            # 9 - format
            if _format:
                if _format in RECOMMENDED_FORMATS:
                    self._pipewire_configs["--format"] = str(_format)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[_format='{_format}']\
                             VALUE NOT IN RECOMMENDED LIST \n{RECOMMENDED_FORMATS}"
                    )
            elif _format is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[_format='{_format}'] EMPTY VALUE")
            # 10 - volume
            if volume:
                if 0.0 <= volume <= 1.0:
                    self._pipewire_configs["--volume"] = str(volume)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[volume='{volume}']\
                             OUT OF RANGE \n [0.000, 1.000]"
                    )
            elif volume is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[volume='{volume}'] EMPTY VALUE")
            # 11 - quality
            if quality:
                if 0 <= quality <= 15:
                    self._pipewire_configs["--quality"] = str(quality)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[quality='{quality}'] OUT OF RANGE \n [0, 15]"
                    )
            elif quality is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[volume='{volume}'] EMPTY VALUE")

            # 12 - verbose cli
            if verbose:  # True
                self._pipewire_configs["--verbose"] = "    "
            else:
                pass

            if verbose:
                print(self._pipewire_configs)

        def load_list_targets(
            self,
            mode,  # playback or record
            # Debug,
            verbose: bool = False,
        ):
            """Returns a list of targets to playback or record. Then you can use
            the output to select a device to playback or record.
            """

            if mode == "playback":
                mycommand = ["pw-cat", "--playback", "--list-targets"]
                stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
                self._pipewire_list_targets["list_playblack"] = _generate_dict_list_targets(
                    longstring=stdout.decode(), verbose=verbose
                )
            elif mode == "record":
                mycommand = ["pw-cat", "--record", "--list-targets"]
                stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
                self._pipewire_list_targets["list_record"] = _generate_dict_list_targets(
                    longstring=stdout.decode(), verbose=verbose
                )
            else:
                raise AttributeError(MESSAGES_ERROR["ValueError"])

            if verbose:
                print(f"[mycommand]{mycommand}")

        def get_list_targets(
            self,
            # Debug,
            verbose: bool = False,
        ):
            """Returns a list of targets to playback or record. Then you can use
            the output to select a device to playback or record.

            Returns:
                - `_pipewire_list_targets`

            Examples:
            ```python
            >>> Controller().get_list_targets()
            {
            "list_playblack": {
                "86": {
                "description": "Starship/Matisse HD Audio Controller Pro",
                "prior": "936"
                },
                "_list_nodes": [
                "86"
                ],
                "_node_default": [
                "86"
                ],
                "_alsa_node": [
                "alsa_output.pci-0000_0a_00.4.pro-output-0"
                ]
            },
            "list_record": {
                "86": {
                "description": "Starship/Matisse HD Audio Controller Pro",
                "prior": "936"
                },
                "_list_nodes": [
                "86"
                ],
                "_node_default": [
                "86"
                ],
                "_alsa_node": [
                "alsa_output.pci-0000_0a_00.4.pro-output-0"
                ]
            }
            }
            ```
            """
            if verbose:
                print(self._pipewire_list_currently_using)
            return self._pipewire_list_currently_using

        def get_list_interfaces(
            self,
            filtered_by_type: str = True,
            type_interfaces: str = "Client",
            # Debug
            verbose: bool = False,
        ):
            """Returns a list of applications currently using pipewire on Client.
            An example of pw-cli usage is the code below:

            ```bash
            #!/bin/bash
            pw-cli ls Client
            ```
            Args:
                filtered_by_type : If False, returns all. If not, returns a fitered dict
                type_interfaces : Set type of Interface ["Client","Link","Node","Factory","Module","Metadata","Endpoint","Session","Endpoint Stream","EndpointLink","Port"]

            Returns:
                - dict_interfaces_filtered: dictionary with list of interfaces matching conditions

            Examples:
            ```python
            >>> Controller().get_list_interfaces()

            ```
            """
            mycommand = ["pw-cli", "info", "all"]

            # if verbose:
            #     print(f"[mycommand]{mycommand}")

            stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
            dict_interfaces = _generate_dict_interfaces(longstring=stdout.decode(), verbose=verbose)

            if filtered_by_type:
                dict_interfaces_filtered = _filter_by_type(
                    dict_interfaces=dict_interfaces, type_interfaces=type_interfaces
                )
            else:
                dict_interfaces_filtered = dict_interfaces

            return dict_interfaces_filtered

        def playback(
            self,
            audio_filename: str = "myplayback.wav",
            # Debug
            verbose: bool = False,
        ):
            """Execute pipewire command to play an audio file with the following
            command:

            ```bash
            #!/bin/bash
            pw-cat --playback {audio_filename} + {configs}
            # configs are a concatenated params
            ```

            Args:
                audio_filename (`str`): Path of the file to be played. *default='myplayback.wav'
                verbose (`bool`): True enable debug logs. *default=False

            Returns:
                - stdout (`str`): Shell response to the command in stdout format
                - stderr (`str`): Shell response response to the command in stderr format
            """
            warnings.warn("The name of the function may change on future releases", DeprecationWarning)

            mycommand = ["pw-cat", "--playback", audio_filename] + _generate_command_by_dict(
                mydict=self._pipewire_configs, verbose=verbose
            )

            if verbose:
                print(f"[mycommand]{mycommand}")

            stdout, stderr = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
            return stdout, stderr

        def record(
            self,
            audio_filename: str = "myplayback.wav",
            timeout_seconds=5,
            # Debug
            verbose: bool = False,
        ):
            """Execute pipewire command to record an audio file, with a timeout of 5
            seconds with the following code and exiting the shell when tiomeout is over.

            ```bash
            #!/bin/bash
            pw-cat --record {audio_filename}
            # timeout is managed by python3 (when signal CTRL+C is sended)
            ```

            Args:
                audio_filename (`str`): Path of the file to be played. *default='myplayback.wav'
                verbose (`bool`): True enable debug logs. *default=False

            Returns:
                - stdout (`str`): Shell response to the command in stdout format
                - stderr (`str`): Shell response response to the command in stderr format
            """
            warnings.warn("The name of the function may change on future releases", DeprecationWarning)

            mycommand = ["pw-cat", "--record", audio_filename] + _generate_command_by_dict(
                mydict=self._pipewire_configs, verbose=verbose
            )

            if verbose:
                print(f"[mycommand]{mycommand}")

            stdout, stderr = _execute_shell_command(
                command=mycommand, timeout=timeout_seconds, verbose=verbose
            )
            return stdout, stderr

        def clear_devices(
            self,
            mode: str = "all",  # ['all','playback','record']
            # Debug
            verbose: bool = False,
        ):
            """Function to stop process running under pipewire executed by
            python controller and with default process name of `pw-cat`, `pw-play` or `pw-record`.

            Args:
                mode (`str`) : string to kill process under `pw-cat`, `pw-play` or `pw-record`.

            Returns:
                - stdoutdict (`dict`) : a dictionary with keys of `mode`.

            Example with pipewire:
                pw-cat process
            """

            mycommand = self._kill_pipewire[mode]

            if verbose:
                print(f"[mycommands]{mycommand}")

            stdout, _ = _execute_shell_command(command=mycommand, verbose=verbose)

            return {mode: stdout}

class Controller:
View Source

    class Controller:
        """
        Class that controls pipewire command line interface
        with shell commands, handling outputs, loading default
        configs and more.
        """

        _pipewire_cli = {  # Help
            "--help": "--help",  # -h
            "--version": "--version",
            "--remote": None,  # -r
        }

        _pipewire_modes = {  # Modes
            "--playback": None,  # -p
            "--record": None,  # -r
            "--midi": None,  # -m
        }

        _pipewire_list_targets = {  # "--list-targets": None,
            "list_playblack": None,
            "list_record": None,
        }

        _pipewire_configs = {  # Configs
            "--media-type": None,  # *default=Audio
            "--media-category": None,  # *default=Playback
            "--media-role": None,  # *default=Music
            "--target": None,  # *default=auto
            "--latency": None,  # *default=100ms (SOURCE FILE if not specified)
            "--rate": None,  # *default=48000
            "--channels": None,  # [1,2] *default=2
            "--channel-map": None,  # ["stereo", "surround-51", "FL,FR"...] *default="FL,FR"
            "--format": None,  # [u8|s8|s16|s32|f32|f64] *default=s16
            "--volume": None,  # [0.0,1.0] *default=1.000
            "--quality": None,  # -q # [0,15] *default=4
            "--verbose": None,  # -v
        }

        _kill_pipewire = {
            "all": ["kill", "$(pidof pw-cat)"],
            "playback": ["kill", "$(pidof pw-play)"],
            "record": ["kill", "$(pidof pw-record)"],
        }

        def __init__(
            self,
            # Debug
            verbose: bool = False,
        ):
            """This constructor load default configs from OS executing
            the following pipewire command

            ```bash
            #!/bin/bash
            # Get defaults from output of:
            pw-cat -h
            ```
            """
            # LOAD ALL DEFAULT PARAMETERS

            mycommand = ["pw-cat", "-h"]

            # get default parameters with help
            stdout, _ = _execute_shell_command(command=mycommand, verbose=verbose)  # stderr
            # convert stdout to dictionary
            dict_default_values = _get_dict_from_stdout(stdout=str(stdout.decode()), verbose=verbose)

            if verbose:
                print(self._pipewire_configs)

            # Save default system configs to our json
            self._pipewire_configs.update(
                ([(key, dict_default_values[key]) for key in dict_default_values])
            )

            if verbose:
                print(self._pipewire_configs)

            # Delete keys with None values
            self._pipewire_configs = _drop_keys_with_none_values(self._pipewire_configs)

            if verbose:
                print(self._pipewire_configs)

            # Load values of list targets
            self.load_list_targets(mode="playback", verbose=verbose)
            self.load_list_targets(mode="record", verbose=verbose)

        def _help_cli(
            self,
            # Debug
            verbose: bool = True,
        ):
            """Get pipewire command line help"""

            mycommand = ["pipewire", self._pipewire_cli["--help"]]

            stdout, _ = _execute_shell_command(command=mycommand, verbose=verbose)  # stderr

            return stdout

        def get_version(
            self,
            # Debug
            verbose: bool = False,
        ):
            """Get version of pipewire installed on OS by executing the following
            code:

            ```bash
            #!/bin/bash
            pw-cli --version
            ```

            Args:
                verbose (bool) : True enable debug logs. *default=False

            Returns:
                - versions (list) : Versions of pipewire compiled
            """

            mycommand = ["pw-cli", "--version"]

            if verbose:
                print(f"[mycommand]{mycommand}")

            stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
            versions = stdout.decode().split("\n")[1:]

            self._pipewire_cli["--version"] = versions

            return versions

        def verbose(
            self,
            status: bool = True,
        ):
            """Get full log of pipewire stream status with the command `pw-cat`

            An example of pw-cli usage is the code below:

            ```bash
            #!/bin/bash
            # For example
            pw-cat --playback beers.wav --verbose
            ```

            that will generate an output like this:

            ```bash
            opened file "beers.wav" format 00010002 channels:2 rate:44100
            using default channel map: FL,FR
            rate=44100 channels=2 fmt=s16 samplesize=2 stride=4 latency=4410 (0.100s)
            connecting playback stream; target_id=4294967295
            stream state changed unconnected -> connecting
            stream param change: id=2
            stream properties:
                media.type = "Audio"
                ...
            now=0 rate=0/0 ticks=0 delay=0 queued=0
            remote 0 is named "pipewire-0"
            core done
            stream state changed connecting -> paused
            stream param change: id=2
            ...
            stream param change: id=15
            stream param change: id=15
            now=13465394419270 rate=1/48000 ticks=35840 delay=512 queued=0
            now=13466525228363 rate=1/48000 ticks=90112 delay=512 queued=0
            ...
            stream drained
            stream state changed streaming -> paused
            stream param change: id=4
            stream state changed paused -> unconnected
            stream param change: id=4
            ```
            """

            if status:
                self._pipewire_configs["--verbose"] = "    "
            else:
                pass

        def get_config(self):
            """Return config dictionary with default or setup variables, remember that
            this object changes only on python-side. Is not updated on real time,
            For real-time, please create and destroy the class.

            Args:
                Nothing

            Returns:
                - _pipewire_configs (`dict`) : dictionary with config values

            """

            return self._pipewire_configs

        def set_config(
            self,
            # configs
            media_type=None,
            media_category=None,
            media_role=None,
            target=None,
            latency=None,
            rate=None,
            channels=None,
            channels_map=None,
            _format=None,
            volume=None,
            quality=None,
            # Debug
            verbose=False,
        ):
            """Method that get args as variables and set them
            to the `json` parameter of the class `_pipewire_configs`,
            then you can use in other method, such as `playback(...)` or
            `record(...)`. This method verifies values to avoid wrong
            settings.

            Args:
                media_type : Set media type
                media_category : Set media category
                media_role : Set media role
                target : Set node target
                latency : Set node latency *example=100ms
                rate : Set sample rate [8000,11025,16000,22050,44100,48000,88200,96000,176400,192000,352800,384000]
                channels : Numbers of channels [1,2]
                channels_map : ["stereo", "surround-51", "FL,FR", ...]
                _format : ["u8", "s8", "s16", "s32", "f32", "f64"]
                volume : Stream volume [0.000, 1.000]
                quality : Resampler quality [0, 15]
                verbose (`bool`): True enable debug logs. *default=False

            Returns:
                - Nothing

            More:
                Check all links listed at the beginning of this page
            """  # 1 - media_type
            if media_type:
                self._pipewire_configs["--media-type"] = str(media_type)
            elif media_type is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[media_type='{media_type}'] EMPTY VALUE"
                )
            # 2 - media_category
            if media_category:
                self._pipewire_configs["--media-category"] = str(media_category)
            elif media_category is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[media_category='{media_category}'] EMPTY VALUE"
                )
            # 3 - media_role
            if media_role:
                self._pipewire_configs["--media-role"] = str(media_role)
            elif media_role is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[media_role='{media_role}'] EMPTY VALUE"
                )
            # 4 - target
            if target:
                self._pipewire_configs["--target"] = str(target)
            elif target is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[target='{target}'] EMPTY VALUE")
            # 5 - latency
            if latency:
                if any(chr.isdigit() for chr in latency):  # Contain numbers
                    self._pipewire_configs["--latency"] = str(latency)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[latency='{latency}'] NO NUMBER IN VARIABLE"
                    )
            elif latency is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[latency='{latency}'] EMPTY VALUE")
            # 6 - rate
            if rate:
                if rate in RECOMMENDED_RATES:
                    self._pipewire_configs["--rate"] = str(rate)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[rate='{rate}']\
                             VALUE NOT IN RECOMMENDED LIST \n{RECOMMENDED_RATES}"
                    )
            elif rate is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[rate='{rate}'] EMPTY VALUE")
            # 7 - channels
            if channels:
                if channels in [1, 2]:  # values
                    self._pipewire_configs["--channels"] = str(channels)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[channels='{channels}']\
                             WRONG VALUE\n ONLY 1 or 2."
                    )
            elif channels is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[channels='{channels}'] EMPTY VALUE")
            # 8 - channels-map
            if channels_map:
                self._pipewire_configs["--channels-map"] = str(channels_map)
            elif channels_map is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[channels_map='{channels_map}'] EMPTY VALUE"
                )
            # 9 - format
            if _format:
                if _format in RECOMMENDED_FORMATS:
                    self._pipewire_configs["--format"] = str(_format)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[_format='{_format}']\
                             VALUE NOT IN RECOMMENDED LIST \n{RECOMMENDED_FORMATS}"
                    )
            elif _format is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[_format='{_format}'] EMPTY VALUE")
            # 10 - volume
            if volume:
                if 0.0 <= volume <= 1.0:
                    self._pipewire_configs["--volume"] = str(volume)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[volume='{volume}']\
                             OUT OF RANGE \n [0.000, 1.000]"
                    )
            elif volume is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[volume='{volume}'] EMPTY VALUE")
            # 11 - quality
            if quality:
                if 0 <= quality <= 15:
                    self._pipewire_configs["--quality"] = str(quality)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[quality='{quality}'] OUT OF RANGE \n [0, 15]"
                    )
            elif quality is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[volume='{volume}'] EMPTY VALUE")

            # 12 - verbose cli
            if verbose:  # True
                self._pipewire_configs["--verbose"] = "    "
            else:
                pass

            if verbose:
                print(self._pipewire_configs)

        def load_list_targets(
            self,
            mode,  # playback or record
            # Debug,
            verbose: bool = False,
        ):
            """Returns a list of targets to playback or record. Then you can use
            the output to select a device to playback or record.
            """

            if mode == "playback":
                mycommand = ["pw-cat", "--playback", "--list-targets"]
                stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
                self._pipewire_list_targets["list_playblack"] = _generate_dict_list_targets(
                    longstring=stdout.decode(), verbose=verbose
                )
            elif mode == "record":
                mycommand = ["pw-cat", "--record", "--list-targets"]
                stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
                self._pipewire_list_targets["list_record"] = _generate_dict_list_targets(
                    longstring=stdout.decode(), verbose=verbose
                )
            else:
                raise AttributeError(MESSAGES_ERROR["ValueError"])

            if verbose:
                print(f"[mycommand]{mycommand}")

        def get_list_targets(
            self,
            # Debug,
            verbose: bool = False,
        ):
            """Returns a list of targets to playback or record. Then you can use
            the output to select a device to playback or record.

            Returns:
                - `_pipewire_list_targets`

            Examples:
            ```python
            >>> Controller().get_list_targets()
            {
            "list_playblack": {
                "86": {
                "description": "Starship/Matisse HD Audio Controller Pro",
                "prior": "936"
                },
                "_list_nodes": [
                "86"
                ],
                "_node_default": [
                "86"
                ],
                "_alsa_node": [
                "alsa_output.pci-0000_0a_00.4.pro-output-0"
                ]
            },
            "list_record": {
                "86": {
                "description": "Starship/Matisse HD Audio Controller Pro",
                "prior": "936"
                },
                "_list_nodes": [
                "86"
                ],
                "_node_default": [
                "86"
                ],
                "_alsa_node": [
                "alsa_output.pci-0000_0a_00.4.pro-output-0"
                ]
            }
            }
            ```
            """
            if verbose:
                print(self._pipewire_list_currently_using)
            return self._pipewire_list_currently_using

        def get_list_interfaces(
            self,
            filtered_by_type: str = True,
            type_interfaces: str = "Client",
            # Debug
            verbose: bool = False,
        ):
            """Returns a list of applications currently using pipewire on Client.
            An example of pw-cli usage is the code below:

            ```bash
            #!/bin/bash
            pw-cli ls Client
            ```
            Args:
                filtered_by_type : If False, returns all. If not, returns a fitered dict
                type_interfaces : Set type of Interface ["Client","Link","Node","Factory","Module","Metadata","Endpoint","Session","Endpoint Stream","EndpointLink","Port"]

            Returns:
                - dict_interfaces_filtered: dictionary with list of interfaces matching conditions

            Examples:
            ```python
            >>> Controller().get_list_interfaces()

            ```
            """
            mycommand = ["pw-cli", "info", "all"]

            # if verbose:
            #     print(f"[mycommand]{mycommand}")

            stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
            dict_interfaces = _generate_dict_interfaces(longstring=stdout.decode(), verbose=verbose)

            if filtered_by_type:
                dict_interfaces_filtered = _filter_by_type(
                    dict_interfaces=dict_interfaces, type_interfaces=type_interfaces
                )
            else:
                dict_interfaces_filtered = dict_interfaces

            return dict_interfaces_filtered

        def playback(
            self,
            audio_filename: str = "myplayback.wav",
            # Debug
            verbose: bool = False,
        ):
            """Execute pipewire command to play an audio file with the following
            command:

            ```bash
            #!/bin/bash
            pw-cat --playback {audio_filename} + {configs}
            # configs are a concatenated params
            ```

            Args:
                audio_filename (`str`): Path of the file to be played. *default='myplayback.wav'
                verbose (`bool`): True enable debug logs. *default=False

            Returns:
                - stdout (`str`): Shell response to the command in stdout format
                - stderr (`str`): Shell response response to the command in stderr format
            """
            warnings.warn("The name of the function may change on future releases", DeprecationWarning)

            mycommand = ["pw-cat", "--playback", audio_filename] + _generate_command_by_dict(
                mydict=self._pipewire_configs, verbose=verbose
            )

            if verbose:
                print(f"[mycommand]{mycommand}")

            stdout, stderr = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
            return stdout, stderr

        def record(
            self,
            audio_filename: str = "myplayback.wav",
            timeout_seconds=5,
            # Debug
            verbose: bool = False,
        ):
            """Execute pipewire command to record an audio file, with a timeout of 5
            seconds with the following code and exiting the shell when tiomeout is over.

            ```bash
            #!/bin/bash
            pw-cat --record {audio_filename}
            # timeout is managed by python3 (when signal CTRL+C is sended)
            ```

            Args:
                audio_filename (`str`): Path of the file to be played. *default='myplayback.wav'
                verbose (`bool`): True enable debug logs. *default=False

            Returns:
                - stdout (`str`): Shell response to the command in stdout format
                - stderr (`str`): Shell response response to the command in stderr format
            """
            warnings.warn("The name of the function may change on future releases", DeprecationWarning)

            mycommand = ["pw-cat", "--record", audio_filename] + _generate_command_by_dict(
                mydict=self._pipewire_configs, verbose=verbose
            )

            if verbose:
                print(f"[mycommand]{mycommand}")

            stdout, stderr = _execute_shell_command(
                command=mycommand, timeout=timeout_seconds, verbose=verbose
            )
            return stdout, stderr

        def clear_devices(
            self,
            mode: str = "all",  # ['all','playback','record']
            # Debug
            verbose: bool = False,
        ):
            """Function to stop process running under pipewire executed by
            python controller and with default process name of `pw-cat`, `pw-play` or `pw-record`.

            Args:
                mode (`str`) : string to kill process under `pw-cat`, `pw-play` or `pw-record`.

            Returns:
                - stdoutdict (`dict`) : a dictionary with keys of `mode`.

            Example with pipewire:
                pw-cat process
            """

            mycommand = self._kill_pipewire[mode]

            if verbose:
                print(f"[mycommands]{mycommand}")

            stdout, _ = _execute_shell_command(command=mycommand, verbose=verbose)

            return {mode: stdout}

Class that controls pipewire command line interface with shell commands, handling outputs, loading default configs and more.

Controller(verbose: bool = False)
View Source

        def __init__(
            self,
            # Debug
            verbose: bool = False,
        ):
            """This constructor load default configs from OS executing
            the following pipewire command

            ```bash
            #!/bin/bash
            # Get defaults from output of:
            pw-cat -h
            ```
            """
            # LOAD ALL DEFAULT PARAMETERS

            mycommand = ["pw-cat", "-h"]

            # get default parameters with help
            stdout, _ = _execute_shell_command(command=mycommand, verbose=verbose)  # stderr
            # convert stdout to dictionary
            dict_default_values = _get_dict_from_stdout(stdout=str(stdout.decode()), verbose=verbose)

            if verbose:
                print(self._pipewire_configs)

            # Save default system configs to our json
            self._pipewire_configs.update(
                ([(key, dict_default_values[key]) for key in dict_default_values])
            )

            if verbose:
                print(self._pipewire_configs)

            # Delete keys with None values
            self._pipewire_configs = _drop_keys_with_none_values(self._pipewire_configs)

            if verbose:
                print(self._pipewire_configs)

            # Load values of list targets
            self.load_list_targets(mode="playback", verbose=verbose)
            self.load_list_targets(mode="record", verbose=verbose)

This constructor load default configs from OS executing the following pipewire command

    #!/bin/bash
    # Get defaults from output of:
    pw-cat -h

def get_version(self, verbose: bool = False):
View Source

        def get_version(
            self,
            # Debug
            verbose: bool = False,
        ):
            """Get version of pipewire installed on OS by executing the following
            code:

            ```bash
            #!/bin/bash
            pw-cli --version
            ```

            Args:
                verbose (bool) : True enable debug logs. *default=False

            Returns:
                - versions (list) : Versions of pipewire compiled
            """

            mycommand = ["pw-cli", "--version"]

            if verbose:
                print(f"[mycommand]{mycommand}")

            stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
            versions = stdout.decode().split("\n")[1:]

            self._pipewire_cli["--version"] = versions

            return versions

Get version of pipewire installed on OS by executing the following code:

    #!/bin/bash
    pw-cli --version

###### Args

- verbose (bool) : True enable debug logs. *default=False

###### Returns

> - versions (list) : Versions of pipewire compiled

def verbose(self, status: bool = True):
View Source

        def verbose(
            self,
            status: bool = True,
        ):
            """Get full log of pipewire stream status with the command `pw-cat`

            An example of pw-cli usage is the code below:

            ```bash
            #!/bin/bash
            # For example
            pw-cat --playback beers.wav --verbose
            ```

            that will generate an output like this:

            ```bash
            opened file "beers.wav" format 00010002 channels:2 rate:44100
            using default channel map: FL,FR
            rate=44100 channels=2 fmt=s16 samplesize=2 stride=4 latency=4410 (0.100s)
            connecting playback stream; target_id=4294967295
            stream state changed unconnected -> connecting
            stream param change: id=2
            stream properties:
                media.type = "Audio"
                ...
            now=0 rate=0/0 ticks=0 delay=0 queued=0
            remote 0 is named "pipewire-0"
            core done
            stream state changed connecting -> paused
            stream param change: id=2
            ...
            stream param change: id=15
            stream param change: id=15
            now=13465394419270 rate=1/48000 ticks=35840 delay=512 queued=0
            now=13466525228363 rate=1/48000 ticks=90112 delay=512 queued=0
            ...
            stream drained
            stream state changed streaming -> paused
            stream param change: id=4
            stream state changed paused -> unconnected
            stream param change: id=4
            ```
            """

            if status:
                self._pipewire_configs["--verbose"] = "    "
            else:
                pass

Get full log of pipewire stream status with the command `pw-cat`

An example of pw-cli usage is the code below:

    #!/bin/bash
    # For example
    pw-cat --playback beers.wav --verbose

that will generate an output like this:

    opened file "beers.wav" format 00010002 channels:2 rate:44100
    using default channel map: FL,FR
    rate=44100 channels=2 fmt=s16 samplesize=2 stride=4 latency=4410 (0.100s)
    connecting playback stream; target_id=4294967295
    stream state changed unconnected -> connecting
    stream param change: id=2
    stream properties:
        media.type = "Audio"
        ...
    now=0 rate=0/0 ticks=0 delay=0 queued=0
    remote 0 is named "pipewire-0"
    core done
    stream state changed connecting -> paused
    stream param change: id=2
    ...
    stream param change: id=15
    stream param change: id=15
    now=13465394419270 rate=1/48000 ticks=35840 delay=512 queued=0
    now=13466525228363 rate=1/48000 ticks=90112 delay=512 queued=0
    ...
    stream drained
    stream state changed streaming -> paused
    stream param change: id=4
    stream state changed paused -> unconnected
    stream param change: id=4

def get_config(self):
View Source

        def get_config(self):
            """Return config dictionary with default or setup variables, remember that
            this object changes only on python-side. Is not updated on real time,
            For real-time, please create and destroy the class.

            Args:
                Nothing

            Returns:
                - _pipewire_configs (`dict`) : dictionary with config values

            """

            return self._pipewire_configs

Return config dictionary with default or setup variables, remember that this object changes only on python-side. Is not updated on real time, For real-time, please create and destroy the class.

###### Args

- Nothing

###### Returns

> - _pipewire_configs (`dict`) : dictionary with config values

def set_config( self, media_type=None, media_category=None, media_role=None, target=None, latency=None, rate=None, channels=None, channels_map=None, _format=None, volume=None, quality=None, verbose=False ):
View Source

        def set_config(
            self,
            # configs
            media_type=None,
            media_category=None,
            media_role=None,
            target=None,
            latency=None,
            rate=None,
            channels=None,
            channels_map=None,
            _format=None,
            volume=None,
            quality=None,
            # Debug
            verbose=False,
        ):
            """Method that get args as variables and set them
            to the `json` parameter of the class `_pipewire_configs`,
            then you can use in other method, such as `playback(...)` or
            `record(...)`. This method verifies values to avoid wrong
            settings.

            Args:
                media_type : Set media type
                media_category : Set media category
                media_role : Set media role
                target : Set node target
                latency : Set node latency *example=100ms
                rate : Set sample rate [8000,11025,16000,22050,44100,48000,88200,96000,176400,192000,352800,384000]
                channels : Numbers of channels [1,2]
                channels_map : ["stereo", "surround-51", "FL,FR", ...]
                _format : ["u8", "s8", "s16", "s32", "f32", "f64"]
                volume : Stream volume [0.000, 1.000]
                quality : Resampler quality [0, 15]
                verbose (`bool`): True enable debug logs. *default=False

            Returns:
                - Nothing

            More:
                Check all links listed at the beginning of this page
            """  # 1 - media_type
            if media_type:
                self._pipewire_configs["--media-type"] = str(media_type)
            elif media_type is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[media_type='{media_type}'] EMPTY VALUE"
                )
            # 2 - media_category
            if media_category:
                self._pipewire_configs["--media-category"] = str(media_category)
            elif media_category is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[media_category='{media_category}'] EMPTY VALUE"
                )
            # 3 - media_role
            if media_role:
                self._pipewire_configs["--media-role"] = str(media_role)
            elif media_role is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[media_role='{media_role}'] EMPTY VALUE"
                )
            # 4 - target
            if target:
                self._pipewire_configs["--target"] = str(target)
            elif target is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[target='{target}'] EMPTY VALUE")
            # 5 - latency
            if latency:
                if any(chr.isdigit() for chr in latency):  # Contain numbers
                    self._pipewire_configs["--latency"] = str(latency)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[latency='{latency}'] NO NUMBER IN VARIABLE"
                    )
            elif latency is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[latency='{latency}'] EMPTY VALUE")
            # 6 - rate
            if rate:
                if rate in RECOMMENDED_RATES:
                    self._pipewire_configs["--rate"] = str(rate)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[rate='{rate}']\
                             VALUE NOT IN RECOMMENDED LIST \n{RECOMMENDED_RATES}"
                    )
            elif rate is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[rate='{rate}'] EMPTY VALUE")
            # 7 - channels
            if channels:
                if channels in [1, 2]:  # values
                    self._pipewire_configs["--channels"] = str(channels)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[channels='{channels}']\
                             WRONG VALUE\n ONLY 1 or 2."
                    )
            elif channels is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[channels='{channels}'] EMPTY VALUE")
            # 8 - channels-map
            if channels_map:
                self._pipewire_configs["--channels-map"] = str(channels_map)
            elif channels_map is None:
                pass
            else:
                raise ValueError(
                    f"{MESSAGES_ERROR['ValueError']}[channels_map='{channels_map}'] EMPTY VALUE"
                )
            # 9 - format
            if _format:
                if _format in RECOMMENDED_FORMATS:
                    self._pipewire_configs["--format"] = str(_format)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[_format='{_format}']\
                             VALUE NOT IN RECOMMENDED LIST \n{RECOMMENDED_FORMATS}"
                    )
            elif _format is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[_format='{_format}'] EMPTY VALUE")
            # 10 - volume
            if volume:
                if 0.0 <= volume <= 1.0:
                    self._pipewire_configs["--volume"] = str(volume)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[volume='{volume}']\
                             OUT OF RANGE \n [0.000, 1.000]"
                    )
            elif volume is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[volume='{volume}'] EMPTY VALUE")
            # 11 - quality
            if quality:
                if 0 <= quality <= 15:
                    self._pipewire_configs["--quality"] = str(quality)
                else:
                    raise ValueError(
                        f"{MESSAGES_ERROR['ValueError']}[quality='{quality}'] OUT OF RANGE \n [0, 15]"
                    )
            elif quality is None:
                pass
            else:
                raise ValueError(f"{MESSAGES_ERROR['ValueError']}[volume='{volume}'] EMPTY VALUE")

            # 12 - verbose cli
            if verbose:  # True
                self._pipewire_configs["--verbose"] = "    "
            else:
                pass

            if verbose:
                print(self._pipewire_configs)

Method that get args as variables and set them to the `json` parameter of the class `_pipewire_configs`, then you can use in other method, such as `playback(...)` or `record(...)`. This method verifies values to avoid wrong settings.

###### Args

- media_type : Set media type
- media_category : Set media category
- media_role : Set media role
- target : Set node target
- latency : Set node latency *example=100ms
- rate : Set sample rate [8000,11025,16000,22050,44100,48000,88200,96000,176400,192000,352800,384000]
- channels : Numbers of channels [1,2]
- channels_map : ["stereo", "surround-51", "FL,FR", ...]
- _format : ["u8", "s8", "s16", "s32", "f32", "f64"]
- volume : Stream volume [0.000, 1.000]
- quality : Resampler quality [0, 15]
- verbose (`bool`): True enable debug logs. *default=False

###### Returns

> - Nothing

###### More

> Check all links listed at the beginning of this page

def load_list_targets(self, mode, verbose: bool = False):
View Source

        def load_list_targets(
            self,
            mode,  # playback or record
            # Debug,
            verbose: bool = False,
        ):
            """Returns a list of targets to playback or record. Then you can use
            the output to select a device to playback or record.
            """

            if mode == "playback":
                mycommand = ["pw-cat", "--playback", "--list-targets"]
                stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
                self._pipewire_list_targets["list_playblack"] = _generate_dict_list_targets(
                    longstring=stdout.decode(), verbose=verbose
                )
            elif mode == "record":
                mycommand = ["pw-cat", "--record", "--list-targets"]
                stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
                self._pipewire_list_targets["list_record"] = _generate_dict_list_targets(
                    longstring=stdout.decode(), verbose=verbose
                )
            else:
                raise AttributeError(MESSAGES_ERROR["ValueError"])

            if verbose:
                print(f"[mycommand]{mycommand}")

Returns a list of targets to playback or record. Then you can use the output to select a device to playback or record.

def get_list_targets(self, verbose: bool = False):
View Source

        def get_list_targets(
            self,
            # Debug,
            verbose: bool = False,
        ):
            """Returns a list of targets to playback or record. Then you can use
            the output to select a device to playback or record.

            Returns:
                - `_pipewire_list_targets`

            Examples:
            ```python
            >>> Controller().get_list_targets()
            {
            "list_playblack": {
                "86": {
                "description": "Starship/Matisse HD Audio Controller Pro",
                "prior": "936"
                },
                "_list_nodes": [
                "86"
                ],
                "_node_default": [
                "86"
                ],
                "_alsa_node": [
                "alsa_output.pci-0000_0a_00.4.pro-output-0"
                ]
            },
            "list_record": {
                "86": {
                "description": "Starship/Matisse HD Audio Controller Pro",
                "prior": "936"
                },
                "_list_nodes": [
                "86"
                ],
                "_node_default": [
                "86"
                ],
                "_alsa_node": [
                "alsa_output.pci-0000_0a_00.4.pro-output-0"
                ]
            }
            }
            ```
            """
            if verbose:
                print(self._pipewire_list_currently_using)
            return self._pipewire_list_currently_using

Returns a list of targets to playback or record. Then you can use the output to select a device to playback or record.

###### Returns

> - `_pipewire_list_targets`

Examples:

    >>> Controller().get_list_targets()
    {
    "list_playblack": {
        "86": {
        "description": "Starship/Matisse HD Audio Controller Pro",
        "prior": "936"
        },
        "_list_nodes": [
        "86"
        ],
        "_node_default": [
        "86"
        ],
        "_alsa_node": [
        "alsa_output.pci-0000_0a_00.4.pro-output-0"
        ]
    },
    "list_record": {
        "86": {
        "description": "Starship/Matisse HD Audio Controller Pro",
        "prior": "936"
        },
        "_list_nodes": [
        "86"
        ],
        "_node_default": [
        "86"
        ],
        "_alsa_node": [
        "alsa_output.pci-0000_0a_00.4.pro-output-0"
        ]
    }
    }

def get_list_interfaces( self, filtered_by_type: str = True, type_interfaces: str = 'Client', verbose: bool = False ):
View Source

        def get_list_interfaces(
            self,
            filtered_by_type: str = True,
            type_interfaces: str = "Client",
            # Debug
            verbose: bool = False,
        ):
            """Returns a list of applications currently using pipewire on Client.
            An example of pw-cli usage is the code below:

            ```bash
            #!/bin/bash
            pw-cli ls Client
            ```
            Args:
                filtered_by_type : If False, returns all. If not, returns a fitered dict
                type_interfaces : Set type of Interface ["Client","Link","Node","Factory","Module","Metadata","Endpoint","Session","Endpoint Stream","EndpointLink","Port"]

            Returns:
                - dict_interfaces_filtered: dictionary with list of interfaces matching conditions

            Examples:
            ```python
            >>> Controller().get_list_interfaces()

            ```
            """
            mycommand = ["pw-cli", "info", "all"]

            # if verbose:
            #     print(f"[mycommand]{mycommand}")

            stdout, _ = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
            dict_interfaces = _generate_dict_interfaces(longstring=stdout.decode(), verbose=verbose)

            if filtered_by_type:
                dict_interfaces_filtered = _filter_by_type(
                    dict_interfaces=dict_interfaces, type_interfaces=type_interfaces
                )
            else:
                dict_interfaces_filtered = dict_interfaces

            return dict_interfaces_filtered

Returns a list of applications currently using pipewire on Client. An example of pw-cli usage is the code below:

    #!/bin/bash
    pw-cli ls Client

###### Args

- filtered_by_type : If False, returns all. If not, returns a fitered dict
- type_interfaces : Set type of Interface ["Client","Link","Node","Factory","Module","Metadata","Endpoint","Session","Endpoint Stream","EndpointLink","Port"]

###### Returns

> - dict_interfaces_filtered: dictionary with list of interfaces matching conditions

Examples:

    >>> Controller().get_list_interfaces()

def playback(self, audio_filename: str = 'myplayback.wav', verbose: bool = False):
View Source

        def playback(
            self,
            audio_filename: str = "myplayback.wav",
            # Debug
            verbose: bool = False,
        ):
            """Execute pipewire command to play an audio file with the following
            command:

            ```bash
            #!/bin/bash
            pw-cat --playback {audio_filename} + {configs}
            # configs are a concatenated params
            ```

            Args:
                audio_filename (`str`): Path of the file to be played. *default='myplayback.wav'
                verbose (`bool`): True enable debug logs. *default=False

            Returns:
                - stdout (`str`): Shell response to the command in stdout format
                - stderr (`str`): Shell response response to the command in stderr format
            """
            warnings.warn("The name of the function may change on future releases", DeprecationWarning)

            mycommand = ["pw-cat", "--playback", audio_filename] + _generate_command_by_dict(
                mydict=self._pipewire_configs, verbose=verbose
            )

            if verbose:
                print(f"[mycommand]{mycommand}")

            stdout, stderr = _execute_shell_command(command=mycommand, timeout=-1, verbose=verbose)
            return stdout, stderr

Execute pipewire command to play an audio file with the following command:

    #!/bin/bash
    pw-cat --playback {audio_filename} + {configs}
    # configs are a concatenated params

###### Args

- audio_filename (`str`): Path of the file to be played. *default='myplayback.wav'
- verbose (`bool`): True enable debug logs. *default=False

###### Returns

> - stdout (`str`): Shell response to the command in stdout format
> - stderr (`str`): Shell response response to the command in stderr format

def record( self, audio_filename: str = 'myplayback.wav', timeout_seconds=5, verbose: bool = False ):
View Source

        def record(
            self,
            audio_filename: str = "myplayback.wav",
            timeout_seconds=5,
            # Debug
            verbose: bool = False,
        ):
            """Execute pipewire command to record an audio file, with a timeout of 5
            seconds with the following code and exiting the shell when tiomeout is over.

            ```bash
            #!/bin/bash
            pw-cat --record {audio_filename}
            # timeout is managed by python3 (when signal CTRL+C is sended)
            ```

            Args:
                audio_filename (`str`): Path of the file to be played. *default='myplayback.wav'
                verbose (`bool`): True enable debug logs. *default=False

            Returns:
                - stdout (`str`): Shell response to the command in stdout format
                - stderr (`str`): Shell response response to the command in stderr format
            """
            warnings.warn("The name of the function may change on future releases", DeprecationWarning)

            mycommand = ["pw-cat", "--record", audio_filename] + _generate_command_by_dict(
                mydict=self._pipewire_configs, verbose=verbose
            )

            if verbose:
                print(f"[mycommand]{mycommand}")

            stdout, stderr = _execute_shell_command(
                command=mycommand, timeout=timeout_seconds, verbose=verbose
            )
            return stdout, stderr

Execute pipewire command to record an audio file, with a timeout of 5 seconds with the following code and exiting the shell when tiomeout is over.

    #!/bin/bash
    pw-cat --record {audio_filename}
    # timeout is managed by python3 (when signal CTRL+C is sended)

###### Args

- audio_filename (`str`): Path of the file to be played. *default='myplayback.wav'
- verbose (`bool`): True enable debug logs. *default=False

###### Returns

> - stdout (`str`): Shell response to the command in stdout format
> - stderr (`str`): Shell response response to the command in stderr format

def clear_devices(self, mode: str = 'all', verbose: bool = False):
View Source

        def clear_devices(
            self,
            mode: str = "all",  # ['all','playback','record']
            # Debug
            verbose: bool = False,
        ):
            """Function to stop process running under pipewire executed by
            python controller and with default process name of `pw-cat`, `pw-play` or `pw-record`.

            Args:
                mode (`str`) : string to kill process under `pw-cat`, `pw-play` or `pw-record`.

            Returns:
                - stdoutdict (`dict`) : a dictionary with keys of `mode`.

            Example with pipewire:
                pw-cat process
            """

            mycommand = self._kill_pipewire[mode]

            if verbose:
                print(f"[mycommands]{mycommand}")

            stdout, _ = _execute_shell_command(command=mycommand, verbose=verbose)

            return {mode: stdout}

Function to stop process running under pipewire executed by python controller and with default process name of `pw-cat`, `pw-play` or `pw-record`.

###### Args

- mode (`str`) : string to kill process under `pw-cat`, `pw-play` or `pw-record`.

###### Returns

> - stdoutdict (`dict`) : a dictionary with keys of `mode`.

###### Example with pipewire

> pw-cat process