diff --git a/man/meson.build b/man/meson.build
index 0418327b3..5506a356d 100644
--- a/man/meson.build
+++ b/man/meson.build
@@ -23,10 +23,6 @@ if get_option('pipewire-jack')
manpages += [[ 'pw-jack', '1' ]]
endif
-if get_option('pipewire-pulseaudio')
- manpages += [[ 'pw-pulse', '1' ]]
-endif
-
foreach m : manpages
file = m.get(0) + '.' + m.get(1)
infile = file + '.xml.in'
diff --git a/man/pw-jack.1.xml.in b/man/pw-jack.1.xml.in
index 84f5bb751..c28422c43 100644
--- a/man/pw-jack.1.xml.in
+++ b/man/pw-jack.1.xml.in
@@ -63,7 +63,6 @@ This file is part of PipeWire.
,
,
-
diff --git a/man/pw-pulse.1.xml.in b/man/pw-pulse.1.xml.in
deleted file mode 100644
index 5607f6462..000000000
--- a/man/pw-pulse.1.xml.in
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-
-
-
-
-
-
-
- pw-pulse [options ] COMMAND [FILE ]
-
-
-
- pw-pulse modifies the LD_LIBRARY_PATH environment
- variable so that applications will load PipeWire's reimplementation
- of the PulseAudio client libraries instead of PulseAudio's own
- libraries. This results in PulseAudio clients being redirected to
- PipeWire.
-
- If PipeWire's reimplementation of the PulseAudio client libraries
- has been installed as a system-wide replacement for PulseAudio's
- own libraries, then the whole system already behaves in that way,
- in which case pw-pulse has no practical effect.
-
-
-
-
-
- -h
- Show help.
-
-
-
- -r NAME
- The name of the remote instance to connect to. If left
- unspecified, a connection is made to the default PipeWire
- instance.
-
-
-
- -v
- Verbose operation.
-
-
-
-
- pw-pulse gst123 /usr/share/sounds/freedesktop/stereo/bell.oga
-
-
-
- Using PipeWire for audio is currently considered to be
- experimental.
-
-
-
- The PipeWire Developers <@PACKAGE_BUGREPORT@>;
- PipeWire is available from
-
-
-
-
-
diff --git a/meson.build b/meson.build
index 8e783f307..f88b7de49 100644
--- a/meson.build
+++ b/meson.build
@@ -41,9 +41,9 @@ if host_machine.system() == 'linux'
# glibc ld.so interprets ${LIB} in a library loading path with an
# appropriate value for the current architecture, typically something
# like lib, lib64 or lib/x86_64-linux-gnu.
- # This allows the same pw-pulse script to work for both 32- and 64-bit
+ # This allows the same pw-jack script to work for both 32- and 64-bit
# applications on biarch/multiarch distributions, by setting something
- # like LD_LIBRARY_PATH='/usr/${LIB}/pipewire-0.3/pulse'.
+ # like LD_LIBRARY_PATH='/usr/${LIB}/pipewire-0.3/jack'.
# Note that ${LIB} is a special token expanded by the runtime linker,
# not an environment variable, and must be passed through literally.
modules_install_dir_dlopen = join_paths(prefix, '${LIB}', pipewire_name)
@@ -327,7 +327,7 @@ dbus_dep = dependency('dbus-1')
sdl_dep = dependency('sdl2', required : false)
sndfile_dep = dependency('sndfile', version : '>= 1.0.20', required : false)
-if get_option('gstreamer') or get_option('pipewire-pulseaudio')
+if get_option('gstreamer')
glib_dep = dependency('glib-2.0', version : '>=2.32.0')
endif
@@ -364,12 +364,6 @@ if get_option('pipewire-jack')
subdir('pipewire-jack/src')
endif
-if get_option('pipewire-pulseaudio')
- pulseaudio_dep = dependency('libpulse', version : '>= 11.1')
- subdir('pipewire-pulseaudio/src')
- subdir('pipewire-pulseaudio/test')
-endif
-
if get_option('pipewire-alsa')
subdir('pipewire-alsa/alsa-plugins')
subdir('pipewire-alsa/conf')
diff --git a/meson_options.txt b/meson_options.txt
index 4b9e46b83..122820ae1 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -49,13 +49,6 @@ option('pipewire-jack',
option('libjack-path',
description: 'Where to install the libjack.so library',
type: 'string')
-option('pipewire-pulseaudio',
- description: 'Enable pipewire-pulseaudio integration',
- type: 'boolean',
- value: false)
-option('libpulse-path',
- description: 'Where to install the libpulse.so library',
- type: 'string')
option('spa-plugins',
description: 'Enable spa plugins integration',
type: 'boolean',
diff --git a/pipewire-pulseaudio/LICENSE b/pipewire-pulseaudio/LICENSE
deleted file mode 100644
index 19e307187..000000000
--- a/pipewire-pulseaudio/LICENSE
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-(This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.)
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- {description}
- Copyright (C) {year} {fullname}
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random
- Hacker.
-
- {signature of Ty Coon}, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/pipewire-pulseaudio/README.md b/pipewire-pulseaudio/README.md
deleted file mode 100644
index 27b62cf29..000000000
--- a/pipewire-pulseaudio/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# pipewire-pulseaudio
-PulseAudio client library for PipeWire
-
-This is a replacement libpulse.so library. Clients using this library will
-transparently connect to PipeWire.
-
-This is now deprecated in favour of the protocol-pulse module that
-implements the pulseaudio protocol directly. This makes it possible to
-use the standard pulseaudio client library.
diff --git a/pipewire-pulseaudio/src/bitset.c b/pipewire-pulseaudio/src/bitset.c
deleted file mode 100644
index be834f5eb..000000000
--- a/pipewire-pulseaudio/src/bitset.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2009 Lennart Poettering
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-#include
-
-#include "internal.h"
-#include "bitset.h"
-
-void pa_bitset_set(pa_bitset_t *b, unsigned k, bool v) {
- pa_assert(b);
-
- if (v)
- b[k >> 5] |= 1 << (k & 31);
- else
- b[k >> 5] &= ~((uint32_t) (1 << (k & 31)));
-}
-
-bool pa_bitset_get(const pa_bitset_t *b, unsigned k) {
- return !!(b[k >> 5] & (1 << (k & 31)));
-}
-
-bool pa_bitset_equals(const pa_bitset_t *b, unsigned n, ...) {
- va_list ap;
- pa_bitset_t *a;
- bool equal;
-
- a = alloca(PA_BITSET_SIZE(n));
- spa_memzero(a, PA_BITSET_SIZE(n));
-
- va_start(ap, n);
- for (;;) {
- int j = va_arg(ap, int);
-
- if (j < 0)
- break;
-
- pa_bitset_set(a, j, true);
- }
- va_end(ap);
-
- equal = memcmp(a, b, PA_BITSET_SIZE(n)) == 0;
-
- return equal;
-}
diff --git a/pipewire-pulseaudio/src/bitset.h b/pipewire-pulseaudio/src/bitset.h
deleted file mode 100644
index 314dafc2a..000000000
--- a/pipewire-pulseaudio/src/bitset.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef foopulsecorebitsethfoo
-#define foopulsecorebitsethfoo
-
-/***
- This file is part of PulseAudio.
-
- Copyright 2009 Lennart Poettering
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#include
-
-#define PA_BITSET_ELEMENTS(n) (((n)+31)/32)
-#define PA_BITSET_SIZE(n) (PA_BITSET_ELEMENTS(n)*4)
-
-typedef uint32_t pa_bitset_t;
-
-void pa_bitset_set(pa_bitset_t *b, unsigned k, bool v);
-bool pa_bitset_get(const pa_bitset_t *b, unsigned k);
-bool pa_bitset_equals(const pa_bitset_t *b, unsigned n, ...);
-
-#endif
diff --git a/pipewire-pulseaudio/src/channelmap.c b/pipewire-pulseaudio/src/channelmap.c
deleted file mode 100644
index c86bb09f7..000000000
--- a/pipewire-pulseaudio/src/channelmap.c
+++ /dev/null
@@ -1,948 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2005-2006 Lennart Poettering
- Copyright 2006 Pierre Ossman for Cendio AB
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-#include
-#include
-
-#include
-#include
-
-#include "internal.h"
-#include "bitset.h"
-#include "sample-util.h"
-
-const char *const table[PA_CHANNEL_POSITION_MAX] = {
- [PA_CHANNEL_POSITION_MONO] = "mono",
-
- [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center",
- [PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left",
- [PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right",
-
- [PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center",
- [PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left",
- [PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right",
-
- [PA_CHANNEL_POSITION_LFE] = "lfe",
-
- [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center",
- [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center",
-
- [PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left",
- [PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right",
-
- [PA_CHANNEL_POSITION_AUX0] = "aux0",
- [PA_CHANNEL_POSITION_AUX1] = "aux1",
- [PA_CHANNEL_POSITION_AUX2] = "aux2",
- [PA_CHANNEL_POSITION_AUX3] = "aux3",
- [PA_CHANNEL_POSITION_AUX4] = "aux4",
- [PA_CHANNEL_POSITION_AUX5] = "aux5",
- [PA_CHANNEL_POSITION_AUX6] = "aux6",
- [PA_CHANNEL_POSITION_AUX7] = "aux7",
- [PA_CHANNEL_POSITION_AUX8] = "aux8",
- [PA_CHANNEL_POSITION_AUX9] = "aux9",
- [PA_CHANNEL_POSITION_AUX10] = "aux10",
- [PA_CHANNEL_POSITION_AUX11] = "aux11",
- [PA_CHANNEL_POSITION_AUX12] = "aux12",
- [PA_CHANNEL_POSITION_AUX13] = "aux13",
- [PA_CHANNEL_POSITION_AUX14] = "aux14",
- [PA_CHANNEL_POSITION_AUX15] = "aux15",
- [PA_CHANNEL_POSITION_AUX16] = "aux16",
- [PA_CHANNEL_POSITION_AUX17] = "aux17",
- [PA_CHANNEL_POSITION_AUX18] = "aux18",
- [PA_CHANNEL_POSITION_AUX19] = "aux19",
- [PA_CHANNEL_POSITION_AUX20] = "aux20",
- [PA_CHANNEL_POSITION_AUX21] = "aux21",
- [PA_CHANNEL_POSITION_AUX22] = "aux22",
- [PA_CHANNEL_POSITION_AUX23] = "aux23",
- [PA_CHANNEL_POSITION_AUX24] = "aux24",
- [PA_CHANNEL_POSITION_AUX25] = "aux25",
- [PA_CHANNEL_POSITION_AUX26] = "aux26",
- [PA_CHANNEL_POSITION_AUX27] = "aux27",
- [PA_CHANNEL_POSITION_AUX28] = "aux28",
- [PA_CHANNEL_POSITION_AUX29] = "aux29",
- [PA_CHANNEL_POSITION_AUX30] = "aux30",
- [PA_CHANNEL_POSITION_AUX31] = "aux31",
-
- [PA_CHANNEL_POSITION_TOP_CENTER] = "top-center",
-
- [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center",
- [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "top-front-left",
- [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "top-front-right",
-
- [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "top-rear-center",
- [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "top-rear-left",
- [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right"
-};
-
-const char *const pretty_table[PA_CHANNEL_POSITION_MAX] = {
- [PA_CHANNEL_POSITION_MONO] = N_("Mono"),
-
- [PA_CHANNEL_POSITION_FRONT_CENTER] = N_("Front Center"),
- [PA_CHANNEL_POSITION_FRONT_LEFT] = N_("Front Left"),
- [PA_CHANNEL_POSITION_FRONT_RIGHT] = N_("Front Right"),
-
- [PA_CHANNEL_POSITION_REAR_CENTER] = N_("Rear Center"),
- [PA_CHANNEL_POSITION_REAR_LEFT] = N_("Rear Left"),
- [PA_CHANNEL_POSITION_REAR_RIGHT] = N_("Rear Right"),
-
- [PA_CHANNEL_POSITION_LFE] = N_("Subwoofer"),
-
- [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = N_("Front Left-of-center"),
- [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = N_("Front Right-of-center"),
-
- [PA_CHANNEL_POSITION_SIDE_LEFT] = N_("Side Left"),
- [PA_CHANNEL_POSITION_SIDE_RIGHT] = N_("Side Right"),
-
- [PA_CHANNEL_POSITION_AUX0] = N_("Auxiliary 0"),
- [PA_CHANNEL_POSITION_AUX1] = N_("Auxiliary 1"),
- [PA_CHANNEL_POSITION_AUX2] = N_("Auxiliary 2"),
- [PA_CHANNEL_POSITION_AUX3] = N_("Auxiliary 3"),
- [PA_CHANNEL_POSITION_AUX4] = N_("Auxiliary 4"),
- [PA_CHANNEL_POSITION_AUX5] = N_("Auxiliary 5"),
- [PA_CHANNEL_POSITION_AUX6] = N_("Auxiliary 6"),
- [PA_CHANNEL_POSITION_AUX7] = N_("Auxiliary 7"),
- [PA_CHANNEL_POSITION_AUX8] = N_("Auxiliary 8"),
- [PA_CHANNEL_POSITION_AUX9] = N_("Auxiliary 9"),
- [PA_CHANNEL_POSITION_AUX10] = N_("Auxiliary 10"),
- [PA_CHANNEL_POSITION_AUX11] = N_("Auxiliary 11"),
- [PA_CHANNEL_POSITION_AUX12] = N_("Auxiliary 12"),
- [PA_CHANNEL_POSITION_AUX13] = N_("Auxiliary 13"),
- [PA_CHANNEL_POSITION_AUX14] = N_("Auxiliary 14"),
- [PA_CHANNEL_POSITION_AUX15] = N_("Auxiliary 15"),
- [PA_CHANNEL_POSITION_AUX16] = N_("Auxiliary 16"),
- [PA_CHANNEL_POSITION_AUX17] = N_("Auxiliary 17"),
- [PA_CHANNEL_POSITION_AUX18] = N_("Auxiliary 18"),
- [PA_CHANNEL_POSITION_AUX19] = N_("Auxiliary 19"),
- [PA_CHANNEL_POSITION_AUX20] = N_("Auxiliary 20"),
- [PA_CHANNEL_POSITION_AUX21] = N_("Auxiliary 21"),
- [PA_CHANNEL_POSITION_AUX22] = N_("Auxiliary 22"),
- [PA_CHANNEL_POSITION_AUX23] = N_("Auxiliary 23"),
- [PA_CHANNEL_POSITION_AUX24] = N_("Auxiliary 24"),
- [PA_CHANNEL_POSITION_AUX25] = N_("Auxiliary 25"),
- [PA_CHANNEL_POSITION_AUX26] = N_("Auxiliary 26"),
- [PA_CHANNEL_POSITION_AUX27] = N_("Auxiliary 27"),
- [PA_CHANNEL_POSITION_AUX28] = N_("Auxiliary 28"),
- [PA_CHANNEL_POSITION_AUX29] = N_("Auxiliary 29"),
- [PA_CHANNEL_POSITION_AUX30] = N_("Auxiliary 30"),
- [PA_CHANNEL_POSITION_AUX31] = N_("Auxiliary 31"),
-
- [PA_CHANNEL_POSITION_TOP_CENTER] = N_("Top Center"),
-
- [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = N_("Top Front Center"),
- [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = N_("Top Front Left"),
- [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = N_("Top Front Right"),
-
- [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = N_("Top Rear Center"),
- [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = N_("Top Rear Left"),
- [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = N_("Top Rear Right")
-};
-
-SPA_EXPORT
-pa_channel_map* pa_channel_map_init(pa_channel_map *m) {
- unsigned c;
- pa_assert(m);
-
- m->channels = 0;
-
- for (c = 0; c < PA_CHANNELS_MAX; c++)
- m->map[c] = PA_CHANNEL_POSITION_INVALID;
-
- return m;
-}
-
-SPA_EXPORT
-pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) {
- pa_assert(m);
-
- pa_channel_map_init(m);
-
- m->channels = 1;
- m->map[0] = PA_CHANNEL_POSITION_MONO;
- return m;
-}
-
-SPA_EXPORT
-pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
- pa_assert(m);
-
- pa_channel_map_init(m);
-
- m->channels = 2;
- m->map[0] = PA_CHANNEL_POSITION_LEFT;
- m->map[1] = PA_CHANNEL_POSITION_RIGHT;
- return m;
-}
-
-SPA_EXPORT
-pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
- pa_assert(m);
- pa_assert(pa_channels_valid(channels));
- pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
-
- pa_channel_map_init(m);
-
- m->channels = (uint8_t) channels;
-
- switch (def) {
- case PA_CHANNEL_MAP_AIFF:
-
- /* This is somewhat compatible with RFC3551 */
-
- switch (channels) {
- case 1:
- m->map[0] = PA_CHANNEL_POSITION_MONO;
- return m;
-
- case 6:
- m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- m->map[1] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
- m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
- m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- m->map[4] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
- m->map[5] = PA_CHANNEL_POSITION_REAR_CENTER;
- return m;
-
- case 5:
- m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
- m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT;
- m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT;
- SPA_FALLTHROUGH
-
- case 2:
- m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- return m;
-
- case 3:
- m->map[0] = PA_CHANNEL_POSITION_LEFT;
- m->map[1] = PA_CHANNEL_POSITION_RIGHT;
- m->map[2] = PA_CHANNEL_POSITION_CENTER;
- return m;
-
- case 4:
- m->map[0] = PA_CHANNEL_POSITION_LEFT;
- m->map[1] = PA_CHANNEL_POSITION_CENTER;
- m->map[2] = PA_CHANNEL_POSITION_RIGHT;
- m->map[3] = PA_CHANNEL_POSITION_REAR_CENTER;
- return m;
-
- default:
- return NULL;
- }
-
- case PA_CHANNEL_MAP_ALSA:
-
- switch (channels) {
- case 1:
- m->map[0] = PA_CHANNEL_POSITION_MONO;
- return m;
-
- case 8:
- m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
- m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
- SPA_FALLTHROUGH
-
- case 6:
- m->map[5] = PA_CHANNEL_POSITION_LFE;
- SPA_FALLTHROUGH
-
- case 5:
- m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
- SPA_FALLTHROUGH
-
- case 4:
- m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
- m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
- SPA_FALLTHROUGH
-
- case 2:
- m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- return m;
-
- default:
- return NULL;
- }
-
- case PA_CHANNEL_MAP_AUX: {
- unsigned i;
-
- for (i = 0; i < channels; i++)
- m->map[i] = PA_CHANNEL_POSITION_AUX0 + i;
-
- return m;
- }
-
- case PA_CHANNEL_MAP_WAVEEX:
-
- /* Following http://www.microsoft.com/whdc/device/audio/multichaud.mspx#EKLAC */
-
- switch (channels) {
- case 1:
- m->map[0] = PA_CHANNEL_POSITION_MONO;
- return m;
-
- case 18:
- m->map[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
- m->map[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
- m->map[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
- SPA_FALLTHROUGH
-
- case 15:
- m->map[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
- m->map[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
- m->map[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
- SPA_FALLTHROUGH
-
- case 12:
- m->map[11] = PA_CHANNEL_POSITION_TOP_CENTER;
- SPA_FALLTHROUGH
-
- case 11:
- m->map[9] = PA_CHANNEL_POSITION_SIDE_LEFT;
- m->map[10] = PA_CHANNEL_POSITION_SIDE_RIGHT;
- SPA_FALLTHROUGH
-
- case 9:
- m->map[8] = PA_CHANNEL_POSITION_REAR_CENTER;
- SPA_FALLTHROUGH
-
- case 8:
- m->map[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
- m->map[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
- SPA_FALLTHROUGH
-
- case 6:
- m->map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
- m->map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
- SPA_FALLTHROUGH
-
- case 4:
- m->map[3] = PA_CHANNEL_POSITION_LFE;
- SPA_FALLTHROUGH
-
- case 3:
- m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
- SPA_FALLTHROUGH
-
- case 2:
- m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- return m;
-
- default:
- return NULL;
- }
-
- case PA_CHANNEL_MAP_OSS:
-
- switch (channels) {
- case 1:
- m->map[0] = PA_CHANNEL_POSITION_MONO;
- return m;
-
- case 8:
- m->map[6] = PA_CHANNEL_POSITION_REAR_LEFT;
- m->map[7] = PA_CHANNEL_POSITION_REAR_RIGHT;
- SPA_FALLTHROUGH
-
- case 6:
- m->map[4] = PA_CHANNEL_POSITION_SIDE_LEFT;
- m->map[5] = PA_CHANNEL_POSITION_SIDE_RIGHT;
- SPA_FALLTHROUGH
-
- case 4:
- m->map[3] = PA_CHANNEL_POSITION_LFE;
- SPA_FALLTHROUGH
-
- case 3:
- m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
- SPA_FALLTHROUGH
-
- case 2:
- m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- return m;
-
- default:
- return NULL;
- }
-
- default:
- pa_assert_not_reached();
- }
-}
-
-SPA_EXPORT
-pa_channel_map* pa_channel_map_init_extend(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
- unsigned c;
-
- pa_assert(m);
- pa_assert(pa_channels_valid(channels));
- pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
-
- pa_channel_map_init(m);
-
- for (c = channels; c > 0; c--) {
-
- if (pa_channel_map_init_auto(m, c, def)) {
- unsigned i = 0;
-
- for (; c < channels; c++) {
-
- m->map[c] = PA_CHANNEL_POSITION_AUX0 + i;
- i++;
- }
-
- m->channels = (uint8_t) channels;
-
- return m;
- }
- }
-
- return NULL;
-}
-
-SPA_EXPORT
-const char* pa_channel_position_to_string(pa_channel_position_t pos) {
-
- if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
- return NULL;
-
- return table[pos];
-}
-
-SPA_EXPORT
-const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos) {
-
- if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
- return NULL;
-
- pa_init_i18n();
-
- return _(pretty_table[pos]);
-}
-
-SPA_EXPORT
-int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
- unsigned c;
-
- pa_assert(a);
- pa_assert(b);
-
- pa_return_val_if_fail(pa_channel_map_valid(a), 0);
-
- if (PA_UNLIKELY(a == b))
- return 1;
-
- pa_return_val_if_fail(pa_channel_map_valid(b), 0);
-
- if (a->channels != b->channels)
- return 0;
-
- for (c = 0; c < a->channels; c++)
- if (a->map[c] != b->map[c])
- return 0;
-
- return 1;
-}
-
-SPA_EXPORT
-char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
- unsigned channel;
- char *e;
-
- pa_assert(s);
- pa_assert(l > 0);
- pa_assert(map);
-
- pa_init_i18n();
-
- if (!pa_channel_map_valid(map)) {
- pa_snprintf(s, l, _("(invalid)"));
- return s;
- }
-
- *(e = s) = 0;
-
- for (channel = 0; channel < map->channels && l > 1; channel++) {
- l -= pa_snprintf(e, l, "%s%s",
- channel == 0 ? "" : ",",
- pa_channel_position_to_string(map->map[channel]));
-
- e = strchr(e, 0);
- }
-
- return s;
-}
-
-SPA_EXPORT
-pa_channel_position_t pa_channel_position_from_string(const char *p) {
- pa_channel_position_t i;
- pa_assert(p);
-
- /* Some special aliases */
- if (pa_streq(p, "left"))
- return PA_CHANNEL_POSITION_LEFT;
- else if (pa_streq(p, "right"))
- return PA_CHANNEL_POSITION_RIGHT;
- else if (pa_streq(p, "center"))
- return PA_CHANNEL_POSITION_CENTER;
- else if (pa_streq(p, "subwoofer"))
- return PA_CHANNEL_POSITION_SUBWOOFER;
-
- for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++)
- if (pa_streq(p, table[i]))
- return i;
-
- return PA_CHANNEL_POSITION_INVALID;
-}
-
-SPA_EXPORT
-pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
- pa_channel_map map;
- char **tokens;
- int i, n_tokens;
-
- pa_assert(rmap);
- pa_assert(s);
-
- pa_channel_map_init(&map);
-
- /* We don't need to match against the well known channel mapping
- * "mono" here explicitly, because that can be understood as
- * listing with one channel called "mono". */
-
- if (pa_streq(s, "stereo")) {
- map.channels = 2;
- map.map[0] = PA_CHANNEL_POSITION_LEFT;
- map.map[1] = PA_CHANNEL_POSITION_RIGHT;
- goto finish;
- } else if (pa_streq(s, "surround-21")) {
- map.channels = 3;
- map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- map.map[2] = PA_CHANNEL_POSITION_LFE;
- goto finish;
- } else if (pa_streq(s, "surround-40")) {
- map.channels = 4;
- map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
- map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
- goto finish;
- } else if (pa_streq(s, "surround-41")) {
- map.channels = 5;
- map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
- map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
- map.map[4] = PA_CHANNEL_POSITION_LFE;
- goto finish;
- } else if (pa_streq(s, "surround-50")) {
- map.channels = 5;
- map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
- map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
- map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
- goto finish;
- } else if (pa_streq(s, "surround-51")) {
- map.channels = 6;
- map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
- map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
- map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
- map.map[5] = PA_CHANNEL_POSITION_LFE;
- goto finish;
- } else if (pa_streq(s, "surround-71")) {
- map.channels = 8;
- map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
- map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
- map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
- map.map[5] = PA_CHANNEL_POSITION_LFE;
- map.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
- map.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
- goto finish;
- }
-
- map.channels = 0;
-
- tokens = pw_split_strv(s, ",", INT_MAX, &n_tokens);
-
- for (i = 0; i < n_tokens; i++) {
- pa_channel_position_t f;
-
- if (map.channels >= PA_CHANNELS_MAX) {
- pw_free_strv(tokens);
- return NULL;
- }
-
- if ((f = pa_channel_position_from_string(tokens[i])) == PA_CHANNEL_POSITION_INVALID) {
- pw_free_strv(tokens);
- return NULL;
- }
- map.map[map.channels++] = f;
- }
- pw_free_strv(tokens);
-
-finish:
-
- if (!pa_channel_map_valid(&map))
- return NULL;
-
- *rmap = map;
- return rmap;
-}
-
-SPA_EXPORT
-int pa_channel_map_valid(const pa_channel_map *map) {
- unsigned c;
-
- pa_assert(map);
-
- if (!pa_channels_valid(map->channels))
- return 0;
-
- for (c = 0; c < map->channels; c++)
- if (map->map[c] < 0 || map->map[c] >= PA_CHANNEL_POSITION_MAX)
- return 0;
-
- return 1;
-}
-
-SPA_EXPORT
-int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *ss) {
- pa_assert(map);
- pa_assert(ss);
-
- pa_return_val_if_fail(pa_channel_map_valid(map), 0);
- pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
-
- return map->channels == ss->channels;
-}
-
-SPA_EXPORT
-int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
- pa_channel_position_mask_t am, bm;
-
- pa_assert(a);
- pa_assert(b);
-
- pa_return_val_if_fail(pa_channel_map_valid(a), 0);
-
- if (PA_UNLIKELY(a == b))
- return 1;
-
- pa_return_val_if_fail(pa_channel_map_valid(b), 0);
-
- am = pa_channel_map_mask(a);
- bm = pa_channel_map_mask(b);
-
- return (bm & am) == bm;
-}
-
-SPA_EXPORT
-int pa_channel_map_can_balance(const pa_channel_map *map) {
- pa_channel_position_mask_t m;
-
- pa_assert(map);
- pa_return_val_if_fail(pa_channel_map_valid(map), 0);
-
- m = pa_channel_map_mask(map);
-
- return
- (PA_CHANNEL_POSITION_MASK_LEFT & m) &&
- (PA_CHANNEL_POSITION_MASK_RIGHT & m);
-}
-
-SPA_EXPORT
-int pa_channel_map_can_fade(const pa_channel_map *map) {
- pa_channel_position_mask_t m;
-
- pa_assert(map);
- pa_return_val_if_fail(pa_channel_map_valid(map), 0);
-
- m = pa_channel_map_mask(map);
-
- return
- (PA_CHANNEL_POSITION_MASK_FRONT & m) &&
- (PA_CHANNEL_POSITION_MASK_REAR & m);
-}
-
-SPA_EXPORT
-int pa_channel_map_can_lfe_balance(const pa_channel_map *map) {
- pa_channel_position_mask_t m;
-
- pa_assert(map);
- pa_return_val_if_fail(pa_channel_map_valid(map), 0);
-
- m = pa_channel_map_mask(map);
-
- return
- (PA_CHANNEL_POSITION_MASK_LFE & m) &&
- (PA_CHANNEL_POSITION_MASK_HFE & m);
-}
-
-SPA_EXPORT
-const char* pa_channel_map_to_name(const pa_channel_map *map) {
- pa_bitset_t in_map[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)];
- unsigned c;
-
- pa_assert(map);
-
- pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
-
- memset(in_map, 0, sizeof(in_map));
-
- for (c = 0; c < map->channels; c++)
- pa_bitset_set(in_map, map->map[c], true);
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_MONO, -1))
- return "mono";
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, -1))
- return "stereo";
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, -1))
- return "surround-40";
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
- PA_CHANNEL_POSITION_LFE, -1))
- return "surround-41";
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
- PA_CHANNEL_POSITION_FRONT_CENTER, -1))
- return "surround-50";
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
- PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, -1))
- return "surround-51";
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
- PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
- PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, -1))
- return "surround-71";
-
- return NULL;
-}
-
-SPA_EXPORT
-const char* pa_channel_map_to_pretty_name(const pa_channel_map *map) {
- pa_bitset_t in_map[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)];
- unsigned c;
-
- pa_assert(map);
-
- pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
-
- memset(in_map, 0, sizeof(in_map));
-
- for (c = 0; c < map->channels; c++)
- pa_bitset_set(in_map, map->map[c], true);
-
- pa_init_i18n();
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_MONO, -1))
- return _("Mono");
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, -1))
- return _("Stereo");
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, -1))
- return _("Surround 4.0");
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
- PA_CHANNEL_POSITION_LFE, -1))
- return _("Surround 4.1");
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
- PA_CHANNEL_POSITION_FRONT_CENTER, -1))
- return _("Surround 5.0");
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
- PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, -1))
- return _("Surround 5.1");
-
- if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
- PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
- PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
- PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
- PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, -1))
- return _("Surround 7.1");
-
- return NULL;
-}
-
-SPA_EXPORT
-int pa_channel_map_has_position(const pa_channel_map *map, pa_channel_position_t p) {
- unsigned c;
-
- pa_return_val_if_fail(pa_channel_map_valid(map), 0);
- pa_return_val_if_fail(p < PA_CHANNEL_POSITION_MAX, 0);
-
- for (c = 0; c < map->channels; c++)
- if (map->map[c] == p)
- return 1;
-
- return 0;
-}
-
-SPA_EXPORT
-pa_channel_position_mask_t pa_channel_map_mask(const pa_channel_map *map) {
- unsigned c;
- pa_channel_position_mask_t r = 0;
-
- pa_return_val_if_fail(pa_channel_map_valid(map), 0);
-
- for (c = 0; c < map->channels; c++)
- r |= PA_CHANNEL_POSITION_MASK(map->map[c]);
-
- return r;
-}
-
-static const uint32_t audio_channels[] = {
- [PA_CHANNEL_POSITION_MONO] = SPA_AUDIO_CHANNEL_MONO,
-
- [PA_CHANNEL_POSITION_FRONT_LEFT] = SPA_AUDIO_CHANNEL_FL,
- [PA_CHANNEL_POSITION_FRONT_RIGHT] = SPA_AUDIO_CHANNEL_FR,
- [PA_CHANNEL_POSITION_FRONT_CENTER] = SPA_AUDIO_CHANNEL_FC,
-
- [PA_CHANNEL_POSITION_REAR_CENTER] = SPA_AUDIO_CHANNEL_RC,
- [PA_CHANNEL_POSITION_REAR_LEFT] = SPA_AUDIO_CHANNEL_RL,
- [PA_CHANNEL_POSITION_REAR_RIGHT] = SPA_AUDIO_CHANNEL_RR,
-
- [PA_CHANNEL_POSITION_LFE] = SPA_AUDIO_CHANNEL_LFE,
- [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = SPA_AUDIO_CHANNEL_FLC,
- [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = SPA_AUDIO_CHANNEL_FRC,
-
- [PA_CHANNEL_POSITION_SIDE_LEFT] = SPA_AUDIO_CHANNEL_SL,
- [PA_CHANNEL_POSITION_SIDE_RIGHT] = SPA_AUDIO_CHANNEL_SR,
-
- [PA_CHANNEL_POSITION_AUX0] = SPA_AUDIO_CHANNEL_CUSTOM_START + 1,
- [PA_CHANNEL_POSITION_AUX1] = SPA_AUDIO_CHANNEL_CUSTOM_START + 2,
- [PA_CHANNEL_POSITION_AUX2] = SPA_AUDIO_CHANNEL_CUSTOM_START + 3,
- [PA_CHANNEL_POSITION_AUX3] = SPA_AUDIO_CHANNEL_CUSTOM_START + 4,
- [PA_CHANNEL_POSITION_AUX4] = SPA_AUDIO_CHANNEL_CUSTOM_START + 5,
- [PA_CHANNEL_POSITION_AUX5] = SPA_AUDIO_CHANNEL_CUSTOM_START + 6,
- [PA_CHANNEL_POSITION_AUX6] = SPA_AUDIO_CHANNEL_CUSTOM_START + 7,
- [PA_CHANNEL_POSITION_AUX7] = SPA_AUDIO_CHANNEL_CUSTOM_START + 8,
- [PA_CHANNEL_POSITION_AUX8] = SPA_AUDIO_CHANNEL_CUSTOM_START + 9,
- [PA_CHANNEL_POSITION_AUX9] = SPA_AUDIO_CHANNEL_CUSTOM_START + 10,
- [PA_CHANNEL_POSITION_AUX10] = SPA_AUDIO_CHANNEL_CUSTOM_START + 11,
- [PA_CHANNEL_POSITION_AUX11] = SPA_AUDIO_CHANNEL_CUSTOM_START + 12,
- [PA_CHANNEL_POSITION_AUX12] = SPA_AUDIO_CHANNEL_CUSTOM_START + 13,
- [PA_CHANNEL_POSITION_AUX13] = SPA_AUDIO_CHANNEL_CUSTOM_START + 14,
- [PA_CHANNEL_POSITION_AUX14] = SPA_AUDIO_CHANNEL_CUSTOM_START + 15,
- [PA_CHANNEL_POSITION_AUX15] = SPA_AUDIO_CHANNEL_CUSTOM_START + 16,
- [PA_CHANNEL_POSITION_AUX16] = SPA_AUDIO_CHANNEL_CUSTOM_START + 17,
- [PA_CHANNEL_POSITION_AUX17] = SPA_AUDIO_CHANNEL_CUSTOM_START + 18,
- [PA_CHANNEL_POSITION_AUX18] = SPA_AUDIO_CHANNEL_CUSTOM_START + 19,
- [PA_CHANNEL_POSITION_AUX19] = SPA_AUDIO_CHANNEL_CUSTOM_START + 20,
- [PA_CHANNEL_POSITION_AUX20] = SPA_AUDIO_CHANNEL_CUSTOM_START + 21,
- [PA_CHANNEL_POSITION_AUX21] = SPA_AUDIO_CHANNEL_CUSTOM_START + 22,
- [PA_CHANNEL_POSITION_AUX22] = SPA_AUDIO_CHANNEL_CUSTOM_START + 23,
- [PA_CHANNEL_POSITION_AUX23] = SPA_AUDIO_CHANNEL_CUSTOM_START + 24,
- [PA_CHANNEL_POSITION_AUX24] = SPA_AUDIO_CHANNEL_CUSTOM_START + 25,
- [PA_CHANNEL_POSITION_AUX25] = SPA_AUDIO_CHANNEL_CUSTOM_START + 26,
- [PA_CHANNEL_POSITION_AUX26] = SPA_AUDIO_CHANNEL_CUSTOM_START + 27,
- [PA_CHANNEL_POSITION_AUX27] = SPA_AUDIO_CHANNEL_CUSTOM_START + 28,
- [PA_CHANNEL_POSITION_AUX28] = SPA_AUDIO_CHANNEL_CUSTOM_START + 29,
- [PA_CHANNEL_POSITION_AUX29] = SPA_AUDIO_CHANNEL_CUSTOM_START + 30,
- [PA_CHANNEL_POSITION_AUX30] = SPA_AUDIO_CHANNEL_CUSTOM_START + 31,
- [PA_CHANNEL_POSITION_AUX31] = SPA_AUDIO_CHANNEL_CUSTOM_START + 32,
-
- [PA_CHANNEL_POSITION_TOP_CENTER] = SPA_AUDIO_CHANNEL_TC,
-
- [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = SPA_AUDIO_CHANNEL_TFL,
- [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = SPA_AUDIO_CHANNEL_TFR,
- [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = SPA_AUDIO_CHANNEL_TFC,
-
- [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = SPA_AUDIO_CHANNEL_TRL,
- [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = SPA_AUDIO_CHANNEL_TRR,
- [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = SPA_AUDIO_CHANNEL_TRC,
-};
-
-static inline uint32_t channel_pa2id(pa_channel_position_t channel)
-{
- if (channel < 0 || (size_t)channel >= SPA_N_ELEMENTS(audio_channels))
- return SPA_AUDIO_CHANNEL_UNKNOWN;
- return audio_channels[channel];
-}
-
-static inline pa_channel_position_t channel_id2pa(uint32_t id, uint32_t *aux)
-{
- size_t i;
- for (i = 0; i < SPA_N_ELEMENTS(audio_channels); i++) {
- if (id == audio_channels[i])
- return i;
- }
- return PA_CHANNEL_POSITION_AUX0 + (*aux)++;
-}
-
-void pw_channel_map_from_positions(pa_channel_map *map, uint32_t n_pos, const uint32_t *pos)
-{
- uint32_t i, aux = 0;
-
- pa_channel_map_init(map);
- map->channels = n_pos;
- for (i = 0; i < n_pos; i++)
- map->map[i] = channel_id2pa(pos[i], &aux);
-
- if (!pa_channel_map_valid(map))
- pa_channel_map_init_extend(map, n_pos, PA_CHANNEL_MAP_DEFAULT);
-}
-
-void pw_channel_map_to_positions(const pa_channel_map *map, uint32_t *pos)
-{
- int i;
- for (i = 0; i < map->channels; i++)
- pos[i] = channel_pa2id(map->map[i]);
-}
diff --git a/pipewire-pulseaudio/src/context.c b/pipewire-pulseaudio/src/context.c
deleted file mode 100644
index 8bc66dc23..000000000
--- a/pipewire-pulseaudio/src/context.c
+++ /dev/null
@@ -1,2238 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-#include "internal.h"
-
-int pa_context_set_error(PA_CONST pa_context *c, int error) {
- pa_assert(error >= 0);
- pa_assert(error < PA_ERR_MAX);
- if (c) {
- pw_log_debug("context %p: error %d %s", c, error, pa_strerror(error));
- ((pa_context*)c)->error = error;
- }
- return error;
-}
-
-static void global_free(pa_context *c, struct global *g)
-{
- pw_log_debug("context %p: %d", c, g->id);
-
- spa_list_remove(&g->link);
-
- if (g->ginfo && g->ginfo->destroy)
- g->ginfo->destroy(g);
- if (g->stream)
- g->stream->global = NULL;
- if (g->proxy)
- pw_proxy_destroy(g->proxy);
- if (g->props)
- pw_properties_free(g->props);
- free(g->type);
- free(g);
-}
-
-static void context_unlink(pa_context *c)
-{
- pa_stream *s, *t;
- struct global *g;
- pa_operation *o;
- struct module_info *m;
-
- pw_log_debug("context %p: unlink %d", c, c->state);
-
- c->disconnect = true;
- c->state_callback = NULL;
- c->state_userdata = NULL;
-
- spa_list_for_each_safe(s, t, &c->streams, link) {
- pa_stream_set_state(s, c->state == PA_CONTEXT_FAILED ?
- PA_STREAM_FAILED : PA_STREAM_TERMINATED);
- }
- if (c->registry) {
- spa_hook_remove(&c->core_listener),
- pw_proxy_destroy((struct pw_proxy*)c->registry);
- c->registry = NULL;
- }
- if (c->core) {
- spa_hook_remove(&c->core_listener);
- pw_core_disconnect(c->core);
- c->core = NULL;
- }
- spa_list_consume(g, &c->globals, link)
- global_free(c, g);
-
- spa_list_consume(o, &c->operations, link)
- pa_operation_cancel(o);
- spa_list_consume(m, &c->modules, link)
- pw_proxy_destroy(m->proxy);
-}
-
-void pa_context_set_state(pa_context *c, pa_context_state_t st) {
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- if (c->state == st)
- return;
-
- pw_log_debug("context %p: state %d", c, st);
-
- pa_context_ref(c);
-
- c->state = st;
-
- if (c->state_callback)
- c->state_callback(c, c->state_userdata);
-
- if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED)
- context_unlink(c);
-
- pa_context_unref(c);
-}
-
-void pa_context_fail(PA_CONST pa_context *c, int error) {
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- pw_log_debug("context %p: error %d", c, error);
-
- pa_context_set_error(c, error);
- pa_context_set_state((pa_context*)c, PA_CONTEXT_FAILED);
-}
-
-SPA_EXPORT
-pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name)
-{
- return pa_context_new_with_proplist(mainloop, name, NULL);
-}
-
-pa_stream *pa_context_find_stream(pa_context *c, uint32_t idx)
-{
- pa_stream *s;
- spa_list_for_each(s, &c->streams, link) {
- if (s->stream_index == idx)
- return s;
- }
- return NULL;
-}
-
-struct global *pa_context_find_global(pa_context *c, uint32_t id)
-{
- struct global *g;
- spa_list_for_each(g, &c->globals, link) {
- if (g->id == id)
- return g;
- }
- return NULL;
-}
-
-const char *pa_context_find_global_name(pa_context *c, uint32_t id)
-{
- struct global *g;
- const char *name = NULL;
-
- g = pa_context_find_global(c, id & PA_IDX_MASK_MONITOR);
- if (g == NULL)
- return "unknown object";
-
- if (g->mask & (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE)) {
- name = pw_properties_get(g->props, PW_KEY_NODE_NAME);
- }
- if (name == NULL)
- name = "unknown";
- return name;
-}
-
-struct global *pa_context_find_global_by_name(pa_context *c, uint32_t mask, const char *name)
-{
- struct global *g;
- const char *str;
- uint32_t id;
-
- if (strcmp(name, "@DEFAULT_SINK@") == 0 || strcmp("@DEFAULT_MONITOR@", name) == 0)
- id = c->default_sink;
- else if (strcmp(name, "@DEFAULT_SOURCE@") == 0)
- id = c->default_source;
- else
- id = atoi(name);
-
- spa_list_for_each(g, &c->globals, link) {
- if ((g->mask & mask) == 0)
- continue;
- if (g->props != NULL &&
- (str = pw_properties_get(g->props, PW_KEY_NODE_NAME)) != NULL) {
- if (strcmp(str, name) == 0)
- return g;
- if (pa_endswith(name, ".monitor") &&
- strncmp(str, name, strlen(name) - 8) == 0)
- return g;
- }
- if (id == SPA_ID_INVALID || g->id == id || (g->id == (id & PA_IDX_MASK_MONITOR)))
- return g;
- }
- return NULL;
-}
-
-struct global *pa_context_find_linked(pa_context *c, uint32_t idx)
-{
- struct global *g, *f;
-
- spa_list_for_each(g, &c->globals, link) {
- uint32_t src_node_id, dst_node_id;
-
- if (strcmp(g->type, PW_TYPE_INTERFACE_Link) != 0)
- continue;
-
- src_node_id = g->link_info.src->port_info.node_id;
- dst_node_id = g->link_info.dst->port_info.node_id;
-
- pw_log_debug("context %p: %p %d %d %d", c, g, idx,
- src_node_id, dst_node_id);
-
- if (src_node_id == idx)
- f = pa_context_find_global(c, dst_node_id);
- else if (dst_node_id == idx)
- f = pa_context_find_global(c, src_node_id);
- else
- continue;
-
- if (f == NULL ||
- !(f->mask & (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE)))
- continue;
- return f;
- }
- return NULL;
-}
-
-static const char *str_etype(pa_subscription_event_type_t event)
-{
- switch (event & PA_SUBSCRIPTION_EVENT_TYPE_MASK) {
- case PA_SUBSCRIPTION_EVENT_NEW:
- return "new";
- case PA_SUBSCRIPTION_EVENT_CHANGE:
- return "change";
- case PA_SUBSCRIPTION_EVENT_REMOVE:
- return "remove";
- }
- return "invalid";
-}
-
-static const char *str_efac(pa_subscription_event_type_t event)
-{
- switch (event & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
- case PA_SUBSCRIPTION_EVENT_SINK:
- return "sink";
- case PA_SUBSCRIPTION_EVENT_SOURCE:
- return "source";
- case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
- return "sink-input";
- case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
- return "source-output";
- case PA_SUBSCRIPTION_EVENT_MODULE:
- return "module";
- case PA_SUBSCRIPTION_EVENT_CLIENT:
- return "client";
- case PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE:
- return "sample-cache";
- case PA_SUBSCRIPTION_EVENT_SERVER:
- return "server";
- case PA_SUBSCRIPTION_EVENT_AUTOLOAD:
- return "autoload";
- case PA_SUBSCRIPTION_EVENT_CARD:
- return "card";
- }
- return "invalid";
-}
-
-static void emit_event(pa_context *c, struct global *g, pa_subscription_event_type_t event)
-{
- if (c->subscribe_callback && (c->subscribe_mask & g->mask)) {
- pw_log_debug("context %p: obj %d: emit %s:%s", c, g->id,
- str_etype(event), str_efac(g->event));
- c->subscribe_callback(c,
- event | g->event,
- g->id,
- c->subscribe_userdata);
-
- if (g->mask == (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE)) {
- pw_log_debug("context %p: obj %d: emit %s:source", c, g->node_info.monitor,
- str_etype(event));
- c->subscribe_callback(c,
- event | PA_SUBSCRIPTION_EVENT_SOURCE,
- g->node_info.monitor,
- c->subscribe_userdata);
- }
- }
-}
-
-static void do_global_sync(struct global *g)
-{
- pa_subscription_event_type_t event;
-
- pw_log_debug("global %p sync", g);
- if (g->ginfo && g->ginfo->sync)
- g->ginfo->sync(g);
-
- if (g->init) {
- if ((g->mask & (PA_SUBSCRIPTION_MASK_SINK_INPUT | PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT))) {
- if (g->node_info.device_index == SPA_ID_INVALID ||
- (g->stream && g->stream->state != PA_STREAM_READY))
- return;
- }
- g->init = false;
- g->changed++;
- event = PA_SUBSCRIPTION_EVENT_NEW;
- } else {
- event = PA_SUBSCRIPTION_EVENT_CHANGE;
- }
- if (g->changed > 0) {
- emit_event(g->context, g, event);
- g->changed = 0;
- }
-}
-
-
-static void global_sync(struct global *g)
-{
- pa_context *c = g->context;
- if (c->core != NULL)
- c->pending_seq = pw_core_sync(c->core, PW_ID_CORE, c->pending_seq);
- g->sync = true;
-}
-
-static struct param *add_param(struct spa_list *params, uint32_t id, const struct spa_pod *param)
-{
- struct param *p;
-
- if (param == NULL || !spa_pod_is_object(param)) {
- errno = EINVAL;
- return NULL;
- }
- if (id == SPA_ID_INVALID)
- id = SPA_POD_OBJECT_ID(param);
-
- p = malloc(sizeof(struct param) + SPA_POD_SIZE(param));
- if (p == NULL)
- return NULL;
-
- p->id = id;
- p->param = SPA_MEMBER(p, sizeof(struct param), struct spa_pod);
- memcpy(p->param, param, SPA_POD_SIZE(param));
- spa_list_append(params, &p->link);
-
- return p;
-}
-
-static void remove_params(struct spa_list *params, uint32_t id)
-{
- struct param *p, *t;
- spa_list_for_each_safe(p, t, params, link) {
- if (id == SPA_ID_INVALID || p->id == id) {
- spa_list_remove(&p->link);
- free(p);
- }
- }
-}
-
-static void update_device_props(struct global *g)
-{
- pa_card_info *i = &g->card_info.info;
- const char *s;
-
- if ((s = pa_proplist_gets(i->proplist, PW_KEY_DEVICE_ICON_NAME)))
- pa_proplist_sets(i->proplist, PA_PROP_DEVICE_ICON_NAME, s);
-}
-
-
-static void device_event_info(void *object, const struct pw_device_info *info)
-{
- struct global *g = object;
- pa_card_info *i = &g->card_info.info;
- const char *str;
- uint32_t n;
-
- pw_log_debug("global %p: id:%d change-mask:%"PRIu64, g, g->id, info->change_mask);
- info = g->info = pw_device_info_update(g->info, info);
-
- i->index = g->id;
- i->name = info->props ?
- spa_dict_lookup(info->props, PW_KEY_DEVICE_NAME) : "unknown";
- str = info->props ? spa_dict_lookup(info->props, PW_KEY_MODULE_ID) : NULL;
- i->owner_module = str ? (unsigned)atoi(str) : SPA_ID_INVALID;
- if (info->change_mask & PW_DEVICE_CHANGE_MASK_PROPS) {
- i->driver = info->props ?
- spa_dict_lookup(info->props, PW_KEY_DEVICE_API) : NULL;
-
- if (i->proplist)
- pa_proplist_update_dict(i->proplist, info->props);
- else {
- i->proplist = pa_proplist_new_dict(info->props);
- }
- update_device_props(g);
- g->changed++;
- }
- if (info->change_mask & PW_DEVICE_CHANGE_MASK_PARAMS) {
- for (n = 0; n < info->n_params; n++) {
- uint32_t id = info->params[n].id;
- bool do_enum = true;
-
- if (info->params[n].user == 0)
- continue;
-
- info->params[n].user = 0;
-
- switch (id) {
- case SPA_PARAM_EnumProfile:
- if (g->card_info.pending_profiles)
- continue;
- remove_params(&g->card_info.profiles, id);
- g->changed++;
- g->card_info.n_profiles = 0;
- break;
- case SPA_PARAM_EnumRoute:
- if (g->card_info.pending_ports)
- continue;
- remove_params(&g->card_info.ports, id);
- g->changed++;
- g->card_info.n_ports = 0;
- break;
- case SPA_PARAM_Route:
- remove_params(&g->card_info.routes, id);
- g->card_info.n_routes = 0;
- break;
- case SPA_PARAM_Profile:
- break;
- default:
- do_enum = false;
- break;
- }
- if (!(info->params[n].flags & SPA_PARAM_INFO_READ))
- continue;
- if (do_enum) {
- switch (id) {
- case SPA_PARAM_EnumProfile:
- case SPA_PARAM_Profile:
- g->card_info.pending_profiles = true;
- break;
- case SPA_PARAM_EnumRoute:
- case SPA_PARAM_Route:
- g->card_info.pending_ports = true;
- break;
- }
- pw_log_debug("global %p: id:%d do enum %s", g, g->id,
- spa_debug_type_find_name(spa_type_param, id));
- pw_device_enum_params((struct pw_device*)g->proxy,
- 0, id, 0, -1, NULL);
- }
- }
- }
- if (i->driver == NULL)
- i->driver = "PipeWire";
- global_sync(g);
-}
-
-static int parse_props(struct global *g, const struct spa_pod *param, bool device)
-{
- int changed = 0;
- struct spa_pod_prop *prop;
- struct spa_pod_object *obj = (struct spa_pod_object *) param;
-
- SPA_POD_OBJECT_FOREACH(obj, prop) {
- switch (prop->key) {
- case SPA_PROP_volume:
- {
- float vol;
- if (spa_pod_get_float(&prop->value, &vol) >= 0 &&
- g->node_info.volume != vol) {
- g->node_info.volume = vol;
- changed++;
- }
- SPA_FLAG_UPDATE(g->node_info.flags, NODE_FLAG_DEVICE_VOLUME, device);
- SPA_FLAG_UPDATE(g->node_info.flags, NODE_FLAG_HW_VOLUME,
- prop->flags & SPA_POD_PROP_FLAG_HARDWARE);
- break;
- }
- case SPA_PROP_mute:
- {
- bool mute;
- if (spa_pod_get_bool(&prop->value, &mute) >= 0 &&
- g->node_info.mute != mute) {
- g->node_info.mute = mute;
- changed++;
- }
- SPA_FLAG_UPDATE(g->node_info.flags, NODE_FLAG_DEVICE_MUTE, device);
- SPA_FLAG_UPDATE(g->node_info.flags, NODE_FLAG_HW_MUTE,
- prop->flags & SPA_POD_PROP_FLAG_HARDWARE);
- break;
- }
- case SPA_PROP_channelVolumes:
- {
- uint32_t n_vals;
- float vol[SPA_AUDIO_MAX_CHANNELS];
-
- n_vals = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
- vol, SPA_AUDIO_MAX_CHANNELS);
-
- if (n_vals != g->node_info.n_channel_volumes) {
- pw_log_debug("channel change %d->%d, trigger remove",
- g->node_info.n_channel_volumes, n_vals);
- if (!g->init)
- emit_event(g->context, g, PA_SUBSCRIPTION_EVENT_REMOVE);
- g->node_info.n_channel_volumes = n_vals;
- /* mark as init, this will emit the NEW event when the
- * params are updated */
- g->init = g->sync = true;
- changed++;
- }
- if (memcmp(g->node_info.channel_volumes, vol, n_vals * sizeof(float)) != 0) {
- memcpy(g->node_info.channel_volumes, vol, n_vals * sizeof(float));
- changed++;
- }
- SPA_FLAG_UPDATE(g->node_info.flags, NODE_FLAG_DEVICE_VOLUME, device);
- SPA_FLAG_UPDATE(g->node_info.flags, NODE_FLAG_HW_VOLUME,
- prop->flags & SPA_POD_PROP_FLAG_HARDWARE);
- break;
- }
- case SPA_PROP_volumeBase:
- spa_pod_get_float(&prop->value, &g->node_info.base_volume);
- break;
- case SPA_PROP_volumeStep:
- spa_pod_get_float(&prop->value, &g->node_info.volume_step);
- break;
- default:
- break;
- }
- }
- return changed;
-}
-
-static struct global *find_node_for_route(pa_context *c, struct global *card, uint32_t device)
-{
- struct global *n;
- spa_list_for_each(n, &c->globals, link) {
- if (strcmp(n->type, PW_TYPE_INTERFACE_Node) != 0)
- continue;
- pw_log_debug("%d/%d %d/%d",
- n->node_info.device_id, card->id,
- n->node_info.profile_device_id, device);
- if (n->node_info.device_id != card->id)
- continue;
- if (n->node_info.profile_device_id != device)
- continue;
- return n;
- }
- return NULL;
-}
-
-static void device_event_param(void *object, int seq,
- uint32_t id, uint32_t index, uint32_t next,
- const struct spa_pod *param)
-{
- struct global *g = object;
-
- pw_log_debug("update param %d %s", g->id,
- spa_debug_type_find_name(spa_type_param, id));
-
- switch (id) {
- case SPA_PARAM_EnumProfile:
- {
- uint32_t index;
- const char *name;
-
- if (spa_pod_parse_object(param,
- SPA_TYPE_OBJECT_ParamProfile, NULL,
- SPA_PARAM_PROFILE_index, SPA_POD_Int(&index),
- SPA_PARAM_PROFILE_name, SPA_POD_String(&name)) < 0) {
- pw_log_warn("device %d: can't parse profile", g->id);
- return;
- }
- if (add_param(&g->card_info.profiles, id, param))
- g->card_info.n_profiles++;
-
- pw_log_debug("device %d: enum profile %d: \"%s\" n_profiles:%d", g->id,
- index, name, g->card_info.n_profiles);
- break;
- }
- case SPA_PARAM_Profile:
- {
- uint32_t index;
- if (spa_pod_parse_object(param,
- SPA_TYPE_OBJECT_ParamProfile, NULL,
- SPA_PARAM_PROFILE_index, SPA_POD_Int(&index)) < 0) {
- pw_log_warn("device %d: can't parse profile", g->id);
- return;
- }
- pw_log_debug("device %d: current profile %d", g->id, index);
- if (g->card_info.active_profile != index) {
- g->changed++;
- g->card_info.active_profile = index;
- }
- break;
- }
- case SPA_PARAM_EnumRoute:
- {
- uint32_t index;
- const char *name;
-
- if (spa_pod_parse_object(param,
- SPA_TYPE_OBJECT_ParamRoute, NULL,
- SPA_PARAM_ROUTE_index, SPA_POD_Int(&index),
- SPA_PARAM_ROUTE_name, SPA_POD_String(&name)) < 0) {
- pw_log_warn("device %d: can't parse route", g->id);
- return;
- }
- if (add_param(&g->card_info.ports, id, param))
- g->card_info.n_ports++;
-
- pw_log_debug("device %d: enum route %d: \"%s\"", g->id, index, name);
- break;
- }
- case SPA_PARAM_Route:
- {
- uint32_t index, device;
- enum spa_direction direction;
-
- if (spa_pod_parse_object(param,
- SPA_TYPE_OBJECT_ParamRoute, NULL,
- SPA_PARAM_ROUTE_index, SPA_POD_Int(&index),
- SPA_PARAM_ROUTE_direction, SPA_POD_Id(&direction),
- SPA_PARAM_ROUTE_device, SPA_POD_Int(&device)) < 0) {
- pw_log_warn("device %d: can't parse route", g->id);
- return;
- }
- if (add_param(&g->card_info.routes, id, param))
- g->card_info.n_routes++;
-
- pw_log_debug("device %d: active %s route %d device %d", g->id,
- direction == SPA_DIRECTION_OUTPUT ? "output" : "input",
- index, device);
- break;
- }
- default:
- break;
- }
-}
-
-static void device_clear_profiles(struct global *g)
-{
- pa_card_info *i = &g->card_info.info;
- i->n_profiles = 0;
- free(i->profiles);
- i->profiles = NULL;
- free(g->card_info.card_profiles);
- g->card_info.card_profiles = NULL;
- free(i->profiles2);
- i->profiles2 = NULL;
-}
-
-static void device_sync_profiles(struct global *g)
-{
- pa_card_info *i = &g->card_info.info;
- uint32_t n_profiles, j;
- struct param *p;
-
- device_clear_profiles(g);
-
- n_profiles = g->card_info.n_profiles;
-
- i->profiles = calloc(n_profiles, sizeof(pa_card_profile_info));
- g->card_info.card_profiles = calloc(n_profiles, sizeof(pa_card_profile_info2));
- i->profiles2 = calloc(n_profiles + 1, sizeof(pa_card_profile_info2 *));
- i->n_profiles = 0;
-
- pw_log_debug("context %p: info for %d n_profiles:%d", g->context, g->id, n_profiles);
-
- j = 0;
- spa_list_for_each(p, &g->card_info.profiles, link) {
- uint32_t id, priority = 0, available = 0, n_cap = 0, n_play = 0;
- const char *name = NULL;
- const char *description = NULL;
- struct spa_pod *classes = NULL, *info = NULL;
-
- if (spa_pod_parse_object(p->param,
- SPA_TYPE_OBJECT_ParamProfile, NULL,
- SPA_PARAM_PROFILE_index, SPA_POD_Int(&id),
- SPA_PARAM_PROFILE_name, SPA_POD_String(&name),
- SPA_PARAM_PROFILE_description, SPA_POD_OPT_String(&description),
- SPA_PARAM_PROFILE_priority, SPA_POD_OPT_Int(&priority),
- SPA_PARAM_PROFILE_available, SPA_POD_OPT_Id(&available),
- SPA_PARAM_PROFILE_info, SPA_POD_OPT_Pod(&info),
- SPA_PARAM_PROFILE_classes, SPA_POD_OPT_Pod(&classes)) < 0) {
- pw_log_warn("device %d: can't parse profile", g->id);
- continue;
- }
- if (classes != NULL) {
- struct spa_pod *iter;
-
- SPA_POD_STRUCT_FOREACH(classes, iter) {
- struct spa_pod_parser prs;
- struct spa_pod_frame f[1];
- char *class;
- uint32_t count;
-
- spa_pod_parser_pod(&prs, iter);
- if (spa_pod_parser_get_struct(&prs,
- SPA_POD_String(&class),
- SPA_POD_Int(&count)) < 0)
- continue;
-
- if (strcmp(class, "Audio/Sink") == 0)
- n_play += count;
- else if (strcmp(class, "Audio/Source") == 0)
- n_cap += count;
-
- spa_pod_parser_pop(&prs, &f[0]);
- }
- }
- pw_log_debug("profile %d: name:%s", j, name);
-
- i->profiles[j].name = name;
- i->profiles[j].description = description ? description : name;
- i->profiles[j].n_sinks = n_play;
- i->profiles[j].n_sources = n_cap;
- i->profiles[j].priority = priority;
-
- i->profiles2[j] = &g->card_info.card_profiles[j];
- i->profiles2[j]->name = i->profiles[j].name;
- i->profiles2[j]->description = i->profiles[j].description;
- i->profiles2[j]->n_sinks = i->profiles[j].n_sinks;
- i->profiles2[j]->n_sources = i->profiles[j].n_sources;
- i->profiles2[j]->priority = i->profiles[j].priority;
- i->profiles2[j]->available = available != SPA_PARAM_AVAILABILITY_no;
-
- if (g->card_info.active_profile == id) {
- i->active_profile = &i->profiles[j];
- i->active_profile2 = i->profiles2[j];
- }
- j++;
- }
- i->profiles2[j] = NULL;
- i->n_profiles = j;
-}
-
-static void device_clear_ports(struct global *g)
-{
- pa_card_info *i = &g->card_info.info;
- uint32_t n;
-
- pw_log_debug("device %d clear ports %d", g->id, i->n_ports);
-
- for (n = 0; n < i->n_ports; n++) {
- pa_card_port_info *pi = i->ports[n];
- pa_proplist_free(pi->proplist);
- free(pi->profiles2);
- }
-
- i->n_ports = 0;
- free(i->ports);
- i->ports = NULL;
- free(g->card_info.card_ports);
- g->card_info.card_ports = NULL;
- free(g->card_info.port_devices);
- g->card_info.port_devices = NULL;
-}
-
-static void device_sync_ports(struct global *g)
-{
- pa_card_info *i = &g->card_info.info;
- pa_context *c = g->context;
- uint32_t n_ports, j;
- struct param *p;
-
- device_clear_ports(g);
-
- n_ports = g->card_info.n_ports;
- i->ports = calloc(n_ports+1, sizeof(pa_card_port_info *));
- g->card_info.card_ports = calloc(n_ports, sizeof(pa_card_port_info));
- g->card_info.port_devices = calloc(n_ports, sizeof(struct port_device));
- i->n_ports = 0;
-
- pw_log_debug("context %p: info for %d n_ports:%d", g->context, g->id, n_ports);
-
- j = 0;
-
- spa_list_for_each(p, &g->card_info.ports, link) {
- uint32_t id, priority;
- enum spa_direction direction;
- const char *name = NULL, *description = NULL;
- enum spa_param_availability available = SPA_PARAM_AVAILABILITY_unknown;
- struct spa_pod *profiles = NULL, *info = NULL, *devices = NULL;
- pa_card_port_info *pi;
- struct port_device *pd;
-
- if (spa_pod_parse_object(p->param,
- SPA_TYPE_OBJECT_ParamRoute, NULL,
- SPA_PARAM_ROUTE_index, SPA_POD_Int(&id),
- SPA_PARAM_ROUTE_direction, SPA_POD_Id(&direction),
- SPA_PARAM_ROUTE_name, SPA_POD_String(&name),
- SPA_PARAM_ROUTE_description, SPA_POD_OPT_String(&description),
- SPA_PARAM_ROUTE_priority, SPA_POD_OPT_Int(&priority),
- SPA_PARAM_ROUTE_available, SPA_POD_OPT_Id(&available),
- SPA_PARAM_ROUTE_info, SPA_POD_OPT_Pod(&info),
- SPA_PARAM_ROUTE_devices, SPA_POD_OPT_Pod(&devices),
- SPA_PARAM_ROUTE_profiles, SPA_POD_OPT_Pod(&profiles)) < 0) {
- pw_log_warn("device %d: can't parse route", g->id);
- continue;
- }
-
- pw_log_debug("port %d: name:%s available:%d", j, name, available);
-
- pi = i->ports[j] = &g->card_info.card_ports[j];
- spa_zero(*pi);
- pi->name = name;
- pi->description = description;
- pi->priority = priority;
- pi->available = available;
- pi->direction = direction == SPA_DIRECTION_INPUT ? PA_DIRECTION_INPUT : PA_DIRECTION_OUTPUT;
- pi->proplist = pa_proplist_new();
- while (info) {
- struct spa_pod_parser prs;
- struct spa_pod_frame f[1];
- int32_t n, n_items;
- const char *key, *value;
-
- spa_pod_parser_pod(&prs, info);
- if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
- spa_pod_parser_get_int(&prs, &n_items) < 0)
- break;
-
- for (n = 0; n < n_items; n++) {
- if (spa_pod_parser_get(&prs,
- SPA_POD_String(&key),
- SPA_POD_String(&value),
- NULL) < 0)
- break;
- pa_proplist_sets(pi->proplist, key, value);
- }
- spa_pod_parser_pop(&prs, &f[0]);
- break;
- }
- pi->n_profiles = 0;
- pi->profiles = NULL;
- pi->profiles2 = NULL;
- while (profiles) {
- uint32_t *pr, n, n_pr;
-
- pr = spa_pod_get_array(profiles, &n_pr);
- if (pr == NULL)
- break;
-
- pi->n_profiles = n_pr;
- pi->profiles2 = calloc(n_pr + 1, sizeof(pa_card_profile_info2 *));
- for (n = 0; n < n_pr; n++)
- pi->profiles2[n] = i->profiles2[pr[n]];
- pi->profiles2[n_pr] = NULL;
- pi->profiles = (pa_card_profile_info **)pi->profiles2;
- break;
- }
- pd = &g->card_info.port_devices[j];
- pd->n_devices = 0;
- pd->devices = NULL;
- if (devices)
- pd->devices = spa_pod_get_array(devices, &pd->n_devices);
- j++;
- }
- i->ports[j] = NULL;
- i->n_ports = j;
- if (i->n_ports == 0) {
- device_clear_ports(g);
- }
-
- spa_list_for_each(p, &g->card_info.routes, link) {
- struct global *ng;
- uint32_t index, device;
- enum spa_param_availability available = SPA_PARAM_AVAILABILITY_unknown;
- struct spa_pod *props = NULL;
- const char *name;
-
- if (spa_pod_parse_object(p->param,
- SPA_TYPE_OBJECT_ParamRoute, NULL,
- SPA_PARAM_ROUTE_index, SPA_POD_Int(&index),
- SPA_PARAM_ROUTE_name, SPA_POD_String(&name),
- SPA_PARAM_ROUTE_device, SPA_POD_Int(&device),
- SPA_PARAM_ROUTE_available, SPA_POD_OPT_Id(&available),
- SPA_PARAM_ROUTE_props, SPA_POD_OPT_Pod(&props)) < 0) {
- pw_log_warn("device %d: can't parse route", g->id);
- continue;
- }
- ng = find_node_for_route(c, g, device);
- if (ng) {
- int changed = 0;
- pw_log_debug("device: %d port:%d: name:%s available:%d", ng->id,
- index, name, available);
- if (ng->node_info.active_port != index) {
- ng->node_info.active_port = index;
- changed++;
- }
- if (ng->node_info.available_port != available) {
- ng->node_info.available_port = available;
- changed++;
- }
- if (props)
- changed += parse_props(ng, props, true);
- ng->changed += changed;
- if (ng->changed)
- global_sync(ng);
- }
- }
-}
-
-static void device_sync(struct global *g)
-{
- if (g->card_info.pending_profiles) {
- device_sync_profiles(g);
- g->card_info.pending_profiles = false;
- g->card_info.pending_ports = true;
- }
- if (g->card_info.pending_ports) {
- device_sync_ports(g);
- g->card_info.pending_ports = false;
- }
-}
-
-static const struct pw_device_events device_events = {
- PW_VERSION_DEVICE_EVENTS,
- .info = device_event_info,
- .param = device_event_param,
-};
-
-static void device_destroy(void *data)
-{
- struct global *global = data;
-
- pw_log_debug("device %d destroy", global->id);
-
- if (global->card_info.info.proplist)
- pa_proplist_free(global->card_info.info.proplist);
-
- device_clear_ports(global);
- device_clear_profiles(global);
-
- remove_params(&global->card_info.routes, SPA_ID_INVALID);
- remove_params(&global->card_info.ports, SPA_ID_INVALID);
- remove_params(&global->card_info.profiles, SPA_ID_INVALID);
-
- if (global->info)
- pw_device_info_free(global->info);
-}
-
-struct global_info device_info = {
- .version = PW_VERSION_DEVICE,
- .events = &device_events,
- .destroy = device_destroy,
- .sync = device_sync,
-};
-
-static void clear_node_formats(struct global *g)
-{
- pa_format_info **f;
- pw_array_for_each(f, &g->node_info.formats)
- pa_format_info_free(*f);
- pw_array_reset(&g->node_info.formats);
- g->changed++;
-}
-
-static void node_event_info(void *object, const struct pw_node_info *info)
-{
- struct global *g = object;
- const char *str;
- uint32_t i;
-
- pw_log_debug("global %p: id:%d change-mask:%"PRIu64, g, g->id, info->change_mask);
- info = g->info = pw_node_info_update(g->info, info);
-
- if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) {
- if (info->props && (str = spa_dict_lookup(info->props, "card.profile.device")))
- g->node_info.profile_device_id = atoi(str);
- else
- g->node_info.profile_device_id = SPA_ID_INVALID;
- g->changed++;
- }
- if (info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) {
- for (i = 0; i < info->n_params; i++) {
- uint32_t id = info->params[i].id;
- bool do_enum;
-
- if (info->params[i].user == 0)
- continue;
- info->params[i].user = 0;
-
- switch (id) {
- case SPA_PARAM_EnumFormat:
- clear_node_formats(g);
- SPA_FALLTHROUGH
- case SPA_PARAM_Props:
- case SPA_PARAM_Format:
- do_enum = true;
- break;
- default:
- do_enum = false;
- break;
- }
-
- if (!(info->params[i].flags & SPA_PARAM_INFO_READ))
- continue;
-
- if (do_enum) {
- pw_log_debug("global %p: id:%d do enum %s", g, g->id,
- spa_debug_type_find_name(spa_type_param, id));
-
- pw_node_enum_params((struct pw_node*)g->proxy,
- 0, id, 0, -1, NULL);
- }
- }
- }
- global_sync(g);
-}
-
-static void node_event_param(void *object, int seq,
- uint32_t id, uint32_t index, uint32_t next,
- const struct spa_pod *param)
-{
- struct global *g = object;
-
- pw_log_debug("update param %d %s", g->id,
- spa_debug_type_find_name(spa_type_param, id));
-
- switch (id) {
- case SPA_PARAM_Props:
- if (!SPA_FLAG_IS_SET(g->node_info.flags, NODE_FLAG_DEVICE_VOLUME | NODE_FLAG_DEVICE_MUTE))
- parse_props(g, param, false);
- break;
- case SPA_PARAM_EnumFormat:
- {
- pa_format_info *f = pa_format_info_from_param(param);
- if (f) {
- pw_array_add_ptr(&g->node_info.formats, f);
-
- if (g->node_info.channel_map.channels == 0)
- pa_format_info_get_channel_map(f, &g->node_info.channel_map);
-
- if (g->node_info.sample_spec.format == 0 ||
- g->node_info.sample_spec.rate == 0 ||
- g->node_info.sample_spec.channels == 0) {
- pa_format_info_get_sample_format(f, &g->node_info.sample_spec.format);
- pa_format_info_get_rate(f, &g->node_info.sample_spec.rate);
- pa_format_info_get_channels(f, &g->node_info.sample_spec.channels);
- }
- }
- break;
- }
- case SPA_PARAM_Format:
- pa_format_parse_param(param, &g->node_info.sample_spec, &g->node_info.channel_map);
- break;
- default:
- break;
- }
-}
-
-static const struct pw_node_events node_events = {
- PW_VERSION_NODE_EVENTS,
- .info = node_event_info,
- .param = node_event_param,
-};
-
-static void node_destroy(void *data)
-{
- struct global *global = data;
- clear_node_formats(global);
- pw_array_clear(&global->node_info.formats);
- if (global->info)
- pw_node_info_free(global->info);
-}
-
-struct global_info node_info = {
- .version = PW_VERSION_NODE,
- .events = &node_events,
- .destroy = node_destroy,
-};
-
-
-static void module_event_info(void *object, const struct pw_module_info *info)
-{
- struct global *g = object;
- pa_module_info *i = &g->module_info.info;
-
- pw_log_debug("global %p: id:%d change-mask:%"PRIu64, g, g->id, info->change_mask);
-
- info = g->info = pw_module_info_update(g->info, info);
-
- i->index = g->id;
- if (info->change_mask & PW_MODULE_CHANGE_MASK_PROPS) {
- if (i->proplist)
- pa_proplist_update_dict(i->proplist, info->props);
- else
- i->proplist = pa_proplist_new_dict(info->props);
- g->changed++;
- }
- i->name = info->name;
- i->argument = info->args;
- i->n_used = -1;
- i->auto_unload = false;
- global_sync(g);
-}
-
-static const struct pw_module_events module_events = {
- PW_VERSION_MODULE_EVENTS,
- .info = module_event_info,
-};
-
-static void module_destroy(void *data)
-{
- struct global *global = data;
- if (global->module_info.info.proplist)
- pa_proplist_free(global->module_info.info.proplist);
- if (global->info)
- pw_module_info_free(global->info);
-}
-
-struct global_info module_info = {
- .version = PW_VERSION_MODULE,
- .events = &module_events,
- .destroy = module_destroy,
-};
-
-static void client_event_info(void *object, const struct pw_client_info *info)
-{
- struct global *g = object;
- const char *str;
- pa_client_info *i = &g->client_info.info;
-
- pw_log_debug("global %p: id:%d change-mask:%"PRIu64, g, g->id, info->change_mask);
- info = g->info = pw_client_info_update(g->info, info);
-
- i->index = g->id;
- str = info->props ? spa_dict_lookup(info->props, PW_KEY_MODULE_ID) : NULL;
- i->owner_module = str ? (unsigned)atoi(str) : SPA_ID_INVALID;
-
- if (info->change_mask & PW_CLIENT_CHANGE_MASK_PROPS) {
- if (i->proplist)
- pa_proplist_update_dict(i->proplist, info->props);
- else
- i->proplist = pa_proplist_new_dict(info->props);
- i->name = info->props ?
- spa_dict_lookup(info->props, PW_KEY_APP_NAME) : NULL;
- i->driver = info->props ?
- spa_dict_lookup(info->props, PW_KEY_PROTOCOL) : NULL;
- g->changed++;
- }
- if (i->name == NULL)
- i->name = "Unknown";
- if (i->driver == NULL)
- i->name = "PipeWire";
- global_sync(g);
-}
-
-static const struct pw_client_events client_events = {
- PW_VERSION_CLIENT_EVENTS,
- .info = client_event_info,
-};
-
-static void client_destroy(void *data)
-{
- struct global *global = data;
- if (global->client_info.info.proplist)
- pa_proplist_free(global->client_info.info.proplist);
- if (global->info)
- pw_client_info_free(global->info);
-}
-
-struct global_info client_info = {
- .version = PW_VERSION_CLIENT,
- .events = &client_events,
- .destroy = client_destroy,
-};
-
-static int metadata_property(void *object,
- uint32_t subject,
- const char *key,
- const char *type,
- const char *value)
-{
- struct global *global = object;
- pa_context *c = global->context;
- uint32_t val;
- bool changed = false;
-
- if (subject == PW_ID_CORE) {
- val = (key && value) ? (uint32_t)atoi(value) : SPA_ID_INVALID;
- if (key == NULL || strcmp(key, METADATA_DEFAULT_SINK) == 0) {
- changed = c->default_sink != val;
- c->default_sink = val;
- }
- if (key == NULL || strcmp(key, METADATA_DEFAULT_SOURCE) == 0) {
- changed = c->default_source != val;
- c->default_source = val;
- }
- }
- if (changed)
- emit_event(global->context, global, PA_SUBSCRIPTION_EVENT_CHANGE);
-
- return 0;
-}
-
-static const struct pw_metadata_events metadata_events = {
- PW_VERSION_METADATA_EVENTS,
- .property = metadata_property,
-};
-
-static void metadata_destroy(void *data)
-{
- struct global *global = data;
- pa_context *c = global->context;
- if (c->metadata == global)
- c->metadata = NULL;
-}
-
-struct global_info metadata_info = {
- .version = PW_VERSION_METADATA,
- .events = &metadata_events,
- .destroy = metadata_destroy,
-};
-
-static void proxy_removed(void *data)
-{
- struct global *g = data;
- pw_proxy_destroy(g->proxy);
-}
-
-static void proxy_destroy(void *data)
-{
- struct global *g = data;
- spa_hook_remove(&g->proxy_listener);
- spa_hook_remove(&g->object_listener);
- g->proxy = NULL;
-}
-
-static const struct pw_proxy_events proxy_events = {
- PW_VERSION_PROXY_EVENTS,
- .removed = proxy_removed,
- .destroy = proxy_destroy,
-};
-
-static void configure_device(pa_stream *s, struct global *g)
-{
- const char *str;
- uint32_t old = s->device_index;
-
- if (s->direction == PA_STREAM_RECORD) {
- if (g->mask == (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE)) {
- s->device_index = g->node_info.monitor;
- }
- else
- s->device_index = g->id;
- } else {
- s->device_index = g->id;
- }
-
- free(s->device_name);
- if ((str = pw_properties_get(g->props, PW_KEY_NODE_NAME)) == NULL)
- s->device_name = strdup("unknown");
- else
- s->device_name = strdup(str);
-
- pw_log_debug("stream %p: linked to %d '%s'", s, s->device_index, s->device_name);
-
- if (old != SPA_ID_INVALID && old != s->device_index &&
- s->state == PA_STREAM_READY && s->moved_callback)
- s->moved_callback(s, s->moved_userdata);
-}
-
-static void update_link(pa_context *c, uint32_t src_node_id, uint32_t dst_node_id)
-{
- struct global *s, *d;
-
- s = pa_context_find_global(c, src_node_id);
- d = pa_context_find_global(c, dst_node_id);
-
- if (s == NULL || d == NULL)
- return;
-
- if (s->stream && s->stream->direct_on_input == dst_node_id) {
- pw_log_debug("node %d linked to stream %d %p (%d)",
- src_node_id, dst_node_id, s->stream, s->stream->state);
- }
- else if (d->stream && d->stream->direct_on_input == src_node_id) {
- pw_log_debug("node %d linked to stream %d %p (%d)",
- dst_node_id, src_node_id, d->stream, d->stream->state);
- }
- else if ((s->mask & (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE)) &&
- (d->mask & (PA_SUBSCRIPTION_MASK_SINK_INPUT | PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT))) {
- pw_log_debug("node %d linked to device %d", dst_node_id, src_node_id);
- d->node_info.device_index = src_node_id;
- if (d->stream)
- configure_device(d->stream, s);
- if (!d->init)
- emit_event(c, d, PA_SUBSCRIPTION_EVENT_CHANGE);
- } else if ((s->mask & (PA_SUBSCRIPTION_MASK_SINK_INPUT | PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)) &&
- (d->mask & (PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE))) {
- pw_log_debug("node %d linked to device %d", src_node_id, dst_node_id);
- s->node_info.device_index = dst_node_id;
- if (s->stream)
- configure_device(s->stream, d);
- if (!s->init)
- emit_event(c, s, PA_SUBSCRIPTION_EVENT_CHANGE);
- }
-}
-
-static int set_mask(pa_context *c, struct global *g)
-{
- const char *str;
- struct global_info *ginfo = NULL;
-
- if (strcmp(g->type, PW_TYPE_INTERFACE_Device) == 0) {
- if (g->props == NULL)
- return 0;
- if ((str = pw_properties_get(g->props, PW_KEY_MEDIA_CLASS)) == NULL)
- return 0;
- if (strcmp(str, "Audio/Device") != 0)
- return 0;
-
- pw_log_debug("found card %d", g->id);
- g->mask = PA_SUBSCRIPTION_MASK_CARD;
- g->event = PA_SUBSCRIPTION_EVENT_CARD;
- ginfo = &device_info;
- spa_list_init(&g->card_info.profiles);
- spa_list_init(&g->card_info.ports);
- spa_list_init(&g->card_info.routes);
- } else if (strcmp(g->type, PW_TYPE_INTERFACE_Node) == 0) {
- if (g->props == NULL)
- return 0;
-
- if ((str = pw_properties_get(g->props, PW_KEY_PRIORITY_DRIVER)) != NULL)
- g->priority_driver = pw_properties_parse_int(str);
-
- if ((str = pw_properties_get(g->props, PW_KEY_MEDIA_CLASS)) == NULL) {
- pw_log_debug("node %d without "PW_KEY_MEDIA_CLASS, g->id);
- return 0;
- }
-
- if (strcmp(str, "Audio/Sink") == 0) {
- pw_log_debug("found sink %d", g->id);
- g->mask = PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE;
- g->event = PA_SUBSCRIPTION_EVENT_SINK;
- g->node_info.monitor = g->id | PA_IDX_FLAG_MONITOR;
- }
- else if (strcmp(str, "Audio/Source") == 0) {
- pw_log_debug("found source %d", g->id);
- g->mask = PA_SUBSCRIPTION_MASK_SOURCE;
- g->event = PA_SUBSCRIPTION_EVENT_SOURCE;
- }
- else if (strcmp(str, "Stream/Output/Audio") == 0) {
- pw_log_debug("found sink input %d", g->id);
- g->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT;
- g->event = PA_SUBSCRIPTION_EVENT_SINK_INPUT;
- }
- else if (strcmp(str, "Stream/Input/Audio") == 0) {
- pw_log_debug("found source output %d", g->id);
- g->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT;
- g->event = PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT;
- }
- g->stream = pa_context_find_stream(c, g->id);
- if (g->stream) {
- pw_log_debug("global stream %p", g->stream);
- g->stream->global = g;
- }
-
- if ((str = pw_properties_get(g->props, PW_KEY_CLIENT_ID)) != NULL)
- g->node_info.client_id = atoi(str);
- else
- g->node_info.client_id = SPA_ID_INVALID;
-
- if ((str = pw_properties_get(g->props, PW_KEY_DEVICE_ID)) != NULL)
- g->node_info.device_id = atoi(str);
- else
- g->node_info.device_id = SPA_ID_INVALID;
-
- ginfo = &node_info;
- g->node_info.device_index = SPA_ID_INVALID;
- g->node_info.sample_spec.format = PA_SAMPLE_S16NE;
- g->node_info.sample_spec.rate = 44100;
- g->node_info.volume = 1.0f;
- g->node_info.mute = false;
- g->node_info.base_volume = 1.0f;
- g->node_info.volume_step = 1.0f / (PA_VOLUME_NORM+1);
- g->node_info.active_port = SPA_ID_INVALID;
- g->node_info.available_port = SPA_PARAM_AVAILABILITY_unknown;
- pw_array_init(&g->node_info.formats, sizeof(void*) * 4);
- } else if (strcmp(g->type, PW_TYPE_INTERFACE_Port) == 0) {
- if (g->props == NULL)
- return 0;
-
- if ((str = pw_properties_get(g->props, PW_KEY_NODE_ID)) == NULL) {
- pw_log_warn("port %d without "PW_KEY_NODE_ID, g->id);
- return 0;
- }
- g->port_info.node_id = atoi(str);
- pw_log_debug("found port %d node %d", g->id, g->port_info.node_id);
- } else if (strcmp(g->type, PW_TYPE_INTERFACE_Module) == 0) {
- pw_log_debug("found module %d", g->id);
- g->mask = PA_SUBSCRIPTION_MASK_MODULE;
- g->event = PA_SUBSCRIPTION_EVENT_MODULE;
- ginfo = &module_info;
- } else if (strcmp(g->type, PW_TYPE_INTERFACE_Client) == 0) {
- pw_log_debug("found client %d", g->id);
- g->mask = PA_SUBSCRIPTION_MASK_CLIENT;
- g->event = PA_SUBSCRIPTION_EVENT_CLIENT;
- ginfo = &client_info;
- } else if (strcmp(g->type, PW_TYPE_INTERFACE_Link) == 0) {
- uint32_t src_node_id, dst_node_id;
-
- if ((str = pw_properties_get(g->props, PW_KEY_LINK_OUTPUT_PORT)) == NULL)
- return 0;
- g->link_info.src = pa_context_find_global(c, pw_properties_parse_int(str));
- if ((str = pw_properties_get(g->props, PW_KEY_LINK_INPUT_PORT)) == NULL)
- return 0;
- g->link_info.dst = pa_context_find_global(c, pw_properties_parse_int(str));
-
- if (g->link_info.src == NULL || g->link_info.dst == NULL)
- return 0;
-
- src_node_id = g->link_info.src->port_info.node_id;
- dst_node_id = g->link_info.dst->port_info.node_id;
-
- pw_log_debug("link %d:%d->%d:%d",
- src_node_id, g->link_info.src->id,
- dst_node_id, g->link_info.dst->id);
-
- update_link(c, src_node_id, dst_node_id);
- } else if (strcmp(g->type, PW_TYPE_INTERFACE_Metadata) == 0) {
- if (c->metadata == NULL) {
- ginfo = &metadata_info;
- c->metadata = g;
- g->mask = PA_SUBSCRIPTION_MASK_SERVER;
- g->event = PA_SUBSCRIPTION_EVENT_SERVER;
- }
- } else {
- return 0;
- }
-
- pw_log_debug("global %p: id:%u mask %d/%d", g, g->id, g->mask, g->event);
-
- if (ginfo) {
- pw_log_debug("bind %d", g->id);
-
- g->proxy = pw_registry_bind(c->registry, g->id, g->type,
- ginfo->version, 0);
- if (g->proxy == NULL)
- return -ENOMEM;
-
- pw_proxy_add_object_listener(g->proxy, &g->object_listener, ginfo->events, g);
- pw_proxy_add_listener(g->proxy, &g->proxy_listener, &proxy_events, g);
- g->ginfo = ginfo;
- global_sync(g);
- } else {
- emit_event(c, g, PA_SUBSCRIPTION_EVENT_NEW);
- }
-
- return 1;
-}
-
-static inline void insert_global(pa_context *c, struct global *global)
-{
- struct global *g;
- bool found = false;
-
- spa_list_for_each(g, &c->globals, link) {
- if (g->priority_driver < global->priority_driver) {
- g = spa_list_prev(g, link);
- found = true;
- break;
- }
- }
- if (!found)
- spa_list_append(&g->link, &global->link);
- else
- spa_list_prepend(&g->link, &global->link);
-}
-
-static void registry_event_global(void *data, uint32_t id,
- uint32_t permissions, const char *type, uint32_t version,
- const struct spa_dict *props)
-{
- pa_context *c = data;
- struct global *g;
- int res;
-
- g = calloc(1, sizeof(struct global));
- pw_log_debug("context %p: global %d %s %p", c, id, type, g);
- g->context = c;
- g->id = id;
- g->permissions = permissions;
- g->type = strdup(type);
- g->init = true;
- g->props = props ? pw_properties_new_dict(props) : NULL;
-
- res = set_mask(c, g);
- insert_global(c, g);
-
- if (res != 1)
- global_free(c, g);
-}
-
-static void registry_event_global_remove(void *object, uint32_t id)
-{
- pa_context *c = object;
- struct global *g;
-
- pw_log_debug("context %p: remove %d", c, id);
- if ((g = pa_context_find_global(c, id)) == NULL)
- return;
-
- emit_event(c, g, PA_SUBSCRIPTION_EVENT_REMOVE);
-
- pw_log_debug("context %p: free %d %p", c, id, g);
- global_free(c, g);
-}
-
-static const struct pw_registry_events registry_events =
-{
- PW_VERSION_REGISTRY_EVENTS,
- .global = registry_event_global,
- .global_remove = registry_event_global_remove,
-};
-
-static void core_info(void *data, const struct pw_core_info *info)
-{
- pa_context *c = data;
- bool first = c->core_info == NULL;
-
- pw_log_debug("context %p: info", c);
-
- if (first) {
- pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
- pa_context_set_state(c, PA_CONTEXT_SETTING_NAME);
- }
-
- c->core_info = pw_core_info_update(c->core_info, info);
-}
-
-static void core_error(void *data, uint32_t id, int seq, int res, const char *message)
-{
- pa_context *c = data;
-
- pw_log_error("context %p: error id:%u seq:%d res:%d (%s): %s", c,
- id, seq, res, spa_strerror(res), message);
-
- if (id == PW_ID_CORE) {
- if (res == -EPIPE && !c->disconnect)
- pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED);
- }
-}
-
-static void core_done(void *data, uint32_t id, int seq)
-{
- pa_context *c = data;
- pa_operation *o, *t;
- struct global *g;
- struct spa_list ops;
-
- pw_log_debug("done id:%u seq:%d/%d", id, seq, c->pending_seq);
- if (c->pending_seq != seq)
- return;
-
- spa_list_for_each(g, &c->globals, link) {
- if (g->sync) {
- do_global_sync(g);
- g->sync = false;
- }
- }
- if (c->pending_seq != seq)
- return;
-
- spa_list_init(&ops);
- spa_list_consume(o, &c->operations, link) {
- spa_list_remove(&o->link);
- spa_list_append(&ops, &o->link);
- }
- spa_list_for_each_safe(o, t, &ops, link) {
- if (!o->sync)
- continue;
- pa_operation_ref(o);
- pw_log_debug("sync operation %p complete", o);
- if (o->callback)
- o->callback(o, o->userdata);
- pa_operation_unref(o);
- }
- spa_list_consume(o, &ops, link) {
- if (!o->sync) {
- spa_list_remove(&o->link);
- spa_list_append(&c->operations, &o->link);
- continue;
- }
- pw_log_warn("operation %p canceled", o);
- pa_operation_cancel(o);
- }
-}
-
-static const struct pw_core_events core_events = {
- PW_VERSION_CORE_EVENTS,
- .info = core_info,
- .done = core_done,
- .error = core_error
-};
-
-struct success_data {
- pa_context_success_cb_t cb;
- void *userdata;
- int error;
-};
-
-static void on_success(pa_operation *o, void *userdata)
-{
- struct success_data *d = userdata;
- pa_context *c = o->context;
- pw_log_debug("context %p: operation:%p error %d", c, o, d->error);
- if (d->error != 0)
- pa_context_set_error(c, d->error);
- if (d->cb)
- d->cb(c, d->error ? 0 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-struct subscribe_data {
- struct success_data success;
- pa_subscription_mask_t mask;
-};
-
-static void on_subscribe(pa_operation *o, void *userdata)
-{
- struct subscribe_data *d = userdata;
- pa_context *c = o->context;
- c->subscribe_mask = d->mask;
- on_success(o, &d->success);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct subscribe_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: subscribe %08x", c, m);
-
- o = pa_operation_new(c, NULL, on_subscribe, sizeof(struct subscribe_data));
- d = o->userdata;
- d->success.cb = cb;
- d->success.userdata = userdata;
- d->mask = m;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void io_event_cb(pa_mainloop_api*ea, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata)
-{
- int res;
- pa_context *c = userdata;
- if (events & PA_IO_EVENT_INPUT) {
- pw_log_debug("%p: iterate loop %p", c, c->loop);
- pw_loop_enter(c->loop);
- do {
- res = pw_loop_iterate(c->loop, 0);
- } while (res == -EINTR);
- pw_loop_leave(c->loop);
- }
-}
-
-SPA_EXPORT
-pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, PA_CONST pa_proplist *p)
-{
- struct pw_context *context;
- struct pw_loop *loop;
- struct pw_properties *props;
- bool fallback_loop = false;
- pa_context *c;
-
- pa_assert(mainloop);
-
- props = pw_properties_new(NULL, NULL);
- if (name)
- pw_properties_set(props, PA_PROP_APPLICATION_NAME, name);
- pw_properties_set(props, PW_KEY_CLIENT_API, "pulseaudio");
- if (p)
- pw_properties_update_proplist(props, p);
-
- if (pa_mainloop_api_is_our_api(mainloop))
- loop = mainloop->userdata;
- else {
- loop = pw_loop_new(NULL);
- fallback_loop = true;
- }
-
- pw_log_debug("mainloop:%p loop:%p", mainloop, loop);
-
- context = pw_context_new(loop,
- pw_properties_new(
- PW_KEY_CONTEXT_PROFILE_MODULES, "default",
- NULL),
- sizeof(struct pa_context));
- if (context == NULL)
- return NULL;
-
- c = pw_context_get_user_data(context);
- c->props = props;
- c->fallback_loop = fallback_loop;
- c->loop = loop;
- c->context = context;
- c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
- c->refcount = 1;
- c->client_index = PA_INVALID_INDEX;
- c->default_sink = SPA_ID_INVALID;
- c->default_source = SPA_ID_INVALID;
- c->mainloop = mainloop;
- c->error = 0;
- c->state = PA_CONTEXT_UNCONNECTED;
-
- if (c->fallback_loop) {
- c->io = c->mainloop->io_new(c->mainloop,
- pw_loop_get_fd(c->loop),
- PA_IO_EVENT_INPUT,
- io_event_cb, c);
- }
-
- if (name)
- pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
-
- spa_list_init(&c->globals);
-
- spa_list_init(&c->streams);
- spa_list_init(&c->operations);
- spa_list_init(&c->modules);
-
- return c;
-}
-
-static void context_free(pa_context *c)
-{
- struct pw_loop *loop;
- pw_log_debug("context %p: free", c);
-
- context_unlink(c);
-
- pw_properties_free(c->props);
- if (c->proplist)
- pa_proplist_free(c->proplist);
- if (c->core_info)
- pw_core_info_free(c->core_info);
-
- if (c->io)
- c->mainloop->io_free(c->io);
- loop = c->fallback_loop ? c->loop : NULL;
-
- pw_context_destroy(c->context);
-
- if (loop)
- pw_loop_destroy(loop);
-}
-
-SPA_EXPORT
-void pa_context_unref(pa_context *c)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- if (--c->refcount == 0)
- context_free(c);
-}
-
-SPA_EXPORT
-pa_context* pa_context_ref(pa_context *c)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- c->refcount++;
- return c;
-}
-
-SPA_EXPORT
-void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
- return;
-
- c->state_callback = cb;
- c->state_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_context_set_event_callback(pa_context *c, pa_context_event_cb_t cb, void *userdata)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
- return;
-
- c->event_callback = cb;
- c->event_userdata = userdata;
-}
-
-SPA_EXPORT
-int pa_context_errno(PA_CONST pa_context *c)
-{
- if (!c)
- return PA_ERR_INVALID;
-
- pa_assert(c->refcount >= 1);
-
- return c->error;
-}
-
-SPA_EXPORT
-int pa_context_is_pending(PA_CONST pa_context *c)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE);
-
- return !spa_list_is_empty(&c->operations);
-}
-
-SPA_EXPORT
-pa_context_state_t pa_context_get_state(PA_CONST pa_context *c)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- return c->state;
-}
-
-static void on_connected(pa_operation *o, void *userdata)
-{
- pa_context *c = o->context;
- pw_log_debug("context %p: connected", c);
- pa_context_set_state(c, PA_CONTEXT_READY);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-int pa_context_connect(pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api)
-{
- int res = 0;
- pa_operation *o;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(c, !(flags & ~(PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL)), PA_ERR_INVALID);
- PA_CHECK_VALIDITY(c, !server || *server, PA_ERR_INVALID);
-
- pa_context_ref(c);
-
- c->no_fail = !!(flags & PA_CONTEXT_NOFAIL);
-
- pa_context_set_state(c, PA_CONTEXT_CONNECTING);
-
- if (server)
- pw_properties_set(c->props, PW_KEY_REMOTE_NAME, server);
-
- c->core = pw_context_connect(c->context, pw_properties_copy(c->props), 0);
- if (c->core == NULL) {
- pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
- res = -1;
- goto exit;
- }
- pw_core_add_listener(c->core, &c->core_listener, &core_events, c);
-
- c->registry = pw_core_get_registry(c->core,
- PW_VERSION_REGISTRY, 0);
- pw_registry_add_listener(c->registry,
- &c->registry_listener,
- ®istry_events, c);
-
- o = pa_operation_new(c, NULL, on_connected, sizeof(struct success_data));
- pa_operation_sync(o);
- pa_operation_unref(o);
-
-exit:
- pa_context_unref(c);
-
- return res;
-}
-
-SPA_EXPORT
-void pa_context_disconnect(pa_context *c)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- pw_log_debug("%p", c);
-
- c->disconnect = true;
- if (c->registry) {
- spa_hook_remove(&c->registry_listener),
- pw_proxy_destroy((struct pw_proxy*)c->registry);
- c->registry = NULL;
- }
- if (c->core) {
- spa_hook_remove(&c->core_listener),
- pw_core_disconnect(c->core);
- c->core = NULL;
- }
- if (PA_CONTEXT_IS_GOOD(c->state))
- pa_context_set_state(c, PA_CONTEXT_TERMINATED);
-}
-
-struct notify_data {
- pa_context_notify_cb_t cb;
- void *userdata;
-};
-
-static void on_notify(pa_operation *o, void *userdata)
-{
- struct notify_data *d = userdata;
- pa_context *c = o->context;
-
- pw_log_debug("%p", c);
-
- if (d->cb)
- d->cb(c, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct notify_data *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_notify, sizeof(struct notify_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_data *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_data));
- d = o->userdata;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
- pw_log_warn("Not Implemented");
-
- return o;
-}
-
-struct default_node {
- uint32_t mask;
- pa_context_success_cb_t cb;
- void *userdata;
- char *name;
- const char *key;
-};
-
-static void do_default_node(pa_operation *o, void *userdata)
-{
- struct default_node *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error = 0;
-
- pw_log_debug("%p mask:%d name:%s", c, d->mask, d->name);
-
- g = pa_context_find_global_by_name(c, d->mask, d->name);
- if (g == NULL) {
- error = PA_ERR_NOENTITY;
- } else if (!SPA_FLAG_IS_SET(g->permissions, PW_PERM_M) ||
- (c->metadata && !SPA_FLAG_IS_SET(c->metadata->permissions, PW_PERM_W|PW_PERM_X))) {
- error = PA_ERR_ACCESS;
- } else if (c->metadata) {
- char buf[16];
- snprintf(buf, sizeof(buf), "%d", g->id);
- pw_metadata_set_property(c->metadata->proxy,
- PW_ID_CORE, d->key, SPA_TYPE_INFO_BASE"Id", buf);
- } else {
- error = PA_ERR_NOTIMPLEMENTED;
- }
- if (error != 0)
- pa_context_set_error(c, error);
- if (d->cb)
- d->cb(c, error != 0 ? 0 : 1, d->userdata);
- pa_xfree(d->name);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct default_node *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, do_default_node, sizeof(*d));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SINK;
- d->name = pa_xstrdup(name);
- d->key = METADATA_DEFAULT_SINK;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct default_node *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, do_default_node, sizeof(*d));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE;
- d->name = pa_xstrdup(name);
- d->key = METADATA_DEFAULT_SOURCE;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-int pa_context_is_local(PA_CONST pa_context *c)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, -1);
-
- return 1;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata)
-{
- struct spa_dict dict;
- struct spa_dict_item items[1];
- pa_operation *o;
- struct success_data *d;
- int changed;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(name);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- items[0] = SPA_DICT_ITEM_INIT(PA_PROP_APPLICATION_NAME, name);
- dict = SPA_DICT_INIT(items, 1);
- changed = pw_properties_update(c->props, &dict);
-
- if (changed) {
- struct pw_client *client;
-
- client = pw_core_get_client(c->core);
- pw_client_update_properties(client, &c->props->dict);
- }
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-const char* pa_context_get_server(PA_CONST pa_context *c)
-{
- const struct pw_core_info *info;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- info = c->core_info;
- PA_CHECK_VALIDITY_RETURN_NULL(c, info && info->name, PA_ERR_NOENTITY);
-
- return info->name;
-}
-
-SPA_EXPORT
-uint32_t pa_context_get_protocol_version(PA_CONST pa_context *c)
-{
- return PA_PROTOCOL_VERSION;
-}
-
-SPA_EXPORT
-uint32_t pa_context_get_server_protocol_version(PA_CONST pa_context *c)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, PA_INVALID_INDEX);
-
- return PA_PROTOCOL_VERSION;
-}
-
-SPA_EXPORT
-pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, PA_CONST pa_proplist *p, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_data *d;
-
- spa_assert(c);
- spa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, mode == PA_UPDATE_SET ||
- mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pa_proplist_update(c->proplist, mode, p);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_data *d;
-
- spa_assert(c);
- spa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, keys && keys[0], PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_warn("Not Implemented");
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-uint32_t pa_context_get_index(PA_CONST pa_context *c)
-{
- struct pw_client *client;
-
- pa_assert(c);
- spa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
- client = pw_core_get_client(c->core);
- if (client == NULL)
- return PA_INVALID_INDEX;
-
- return pw_proxy_get_bound_id((struct pw_proxy*)client);
-}
-
-SPA_EXPORT
-pa_time_event* pa_context_rttime_new(PA_CONST pa_context *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata)
-{
- struct timeval tv;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(c->mainloop);
-
- if (usec == PA_USEC_INVALID)
- return c->mainloop->time_new(c->mainloop, NULL, cb, userdata);
-
- pa_timeval_rtstore(&tv, usec, !c->fallback_loop);
-
- return c->mainloop->time_new(c->mainloop, &tv, cb, userdata);
-}
-
-SPA_EXPORT
-void pa_context_rttime_restart(PA_CONST pa_context *c, pa_time_event *e, pa_usec_t usec)
-{
- struct timeval tv;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(c->mainloop);
-
- if (usec == PA_USEC_INVALID)
- c->mainloop->time_restart(e, NULL);
- else {
- pa_timeval_rtstore(&tv, usec, !c->fallback_loop);
- c->mainloop->time_restart(e, &tv);
- }
-}
-
-SPA_EXPORT
-size_t pa_context_get_tile_size(PA_CONST pa_context *c, const pa_sample_spec *ss)
-{
- size_t fs, mbs;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_ANY(c, !ss || pa_sample_spec_valid(ss), PA_ERR_INVALID, (size_t) -1);
-
- fs = ss ? pa_frame_size(ss) : 1;
- mbs = PA_ROUND_DOWN(4096, fs);
- return PA_MAX(mbs, fs);
-}
-
-SPA_EXPORT
-int pa_context_load_cookie_from_file(pa_context *c, const char *cookie_file_path)
-{
- return 0;
-}
diff --git a/pipewire-pulseaudio/src/core-format.c b/pipewire-pulseaudio/src/core-format.c
deleted file mode 100644
index 4977a242d..000000000
--- a/pipewire-pulseaudio/src/core-format.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include "core-format.h"
-
-#include
-#include
-
-#include "internal.h"
-
-SPA_EXPORT
-int pa_format_info_get_sample_format(const pa_format_info *f, pa_sample_format_t *sf) {
- int r;
- char *sf_str;
- pa_sample_format_t sf_local;
-
- pa_assert(f);
- pa_assert(sf);
-
- r = pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf_str);
- if (r < 0)
- return r;
-
- sf_local = pa_parse_sample_format(sf_str);
- pa_xfree(sf_str);
-
- if (!pa_sample_format_valid(sf_local)) {
- pa_log_debug("Invalid sample format.");
- return -PA_ERR_INVALID;
- }
-
- *sf = sf_local;
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_format_info_get_rate(const pa_format_info *f, uint32_t *rate) {
- int r;
- int rate_local;
-
- pa_assert(f);
- pa_assert(rate);
-
- r = pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate_local);
- if (r < 0)
- return r;
-
- if (!pa_sample_rate_valid(rate_local)) {
- pa_log_debug("Invalid sample rate: %i", rate_local);
- return -PA_ERR_INVALID;
- }
-
- *rate = rate_local;
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_format_info_get_channels(const pa_format_info *f, uint8_t *channels) {
- int r;
- int channels_local;
-
- pa_assert(f);
- pa_assert(channels);
-
- r = pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels_local);
- if (r < 0)
- return r;
-
- if (!pa_channels_valid(channels_local)) {
- pa_log_debug("Invalid channel count: %i", channels_local);
- return -PA_ERR_INVALID;
- }
-
- *channels = channels_local;
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_format_info_get_channel_map(const pa_format_info *f, pa_channel_map *map) {
- int r;
- char *map_str;
-
- pa_assert(f);
- pa_assert(map);
-
- r = pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &map_str);
- if (r < 0)
- return r;
-
- map = pa_channel_map_parse(map, map_str);
- pa_xfree(map_str);
-
- if (!map) {
- pa_log_debug("Failed to parse channel map.");
- return -PA_ERR_INVALID;
- }
-
- return 0;
-}
-
-SPA_EXPORT
-pa_format_info *pa_format_info_from_sample_spec2(const pa_sample_spec *ss, const pa_channel_map *map, bool set_format,
- bool set_rate, bool set_channels) {
- pa_format_info *format = NULL;
-
- pa_assert(ss);
-
- format = pa_format_info_new();
- format->encoding = PA_ENCODING_PCM;
-
- if (set_format)
- pa_format_info_set_sample_format(format, ss->format);
-
- if (set_rate)
- pa_format_info_set_rate(format, ss->rate);
-
- if (set_channels) {
- pa_format_info_set_channels(format, ss->channels);
-
- if (map) {
- if (map->channels != ss->channels) {
- pa_log_debug("Channel map is incompatible with the sample spec.");
- goto fail;
- }
-
- pa_format_info_set_channel_map(format, map);
- }
- }
-
- return format;
-
-fail:
- if (format)
- pa_format_info_free(format);
-
- return NULL;
-}
-
-SPA_EXPORT
-int pa_format_info_to_sample_spec2(const pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map,
- const pa_sample_spec *fallback_ss, const pa_channel_map *fallback_map) {
- int r, r2;
- pa_sample_spec ss_local;
- pa_channel_map map_local;
-
- pa_assert(f);
- pa_assert(ss);
- pa_assert(map);
- pa_assert(fallback_ss);
- pa_assert(fallback_map);
-
- if (!pa_format_info_is_pcm(f))
- return pa_format_info_to_sample_spec_fake(f, ss, map);
-
- r = pa_format_info_get_sample_format(f, &ss_local.format);
- if (r == -PA_ERR_NOENTITY)
- ss_local.format = fallback_ss->format;
- else if (r < 0)
- return r;
-
- pa_assert(pa_sample_format_valid(ss_local.format));
-
- r = pa_format_info_get_rate(f, &ss_local.rate);
- if (r == -PA_ERR_NOENTITY)
- ss_local.rate = fallback_ss->rate;
- else if (r < 0)
- return r;
-
- pa_assert(pa_sample_rate_valid(ss_local.rate));
-
- r = pa_format_info_get_channels(f, &ss_local.channels);
- r2 = pa_format_info_get_channel_map(f, &map_local);
- if (r == -PA_ERR_NOENTITY && r2 >= 0)
- ss_local.channels = map_local.channels;
- else if (r == -PA_ERR_NOENTITY)
- ss_local.channels = fallback_ss->channels;
- else if (r < 0)
- return r;
-
- pa_assert(pa_channels_valid(ss_local.channels));
-
- if (r2 >= 0 && map_local.channels != ss_local.channels) {
- pa_log_debug("Channel map is not compatible with the sample spec.");
- return -PA_ERR_INVALID;
- }
-
- if (r2 == -PA_ERR_NOENTITY) {
- if (fallback_map->channels == ss_local.channels)
- map_local = *fallback_map;
- else
- pa_channel_map_init_extend(&map_local, ss_local.channels, PA_CHANNEL_MAP_DEFAULT);
- } else if (r2 < 0)
- return r2;
-
- pa_assert(pa_channel_map_valid(&map_local));
- pa_assert(ss_local.channels == map_local.channels);
-
- *ss = ss_local;
- *map = map_local;
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_format_info_to_sample_spec_fake(const pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
- int rate;
-
- pa_assert(f);
- pa_assert(ss);
-
- /* Note: When we add support for non-IEC61937 encapsulated compressed
- * formats, this function should return a non-zero values for these. */
-
- ss->format = PA_SAMPLE_S16LE;
- ss->channels = 2;
-
- if (map)
- pa_channel_map_init_stereo(map);
-
- pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, -PA_ERR_INVALID);
- ss->rate = (uint32_t) rate;
-
- if (f->encoding == PA_ENCODING_EAC3_IEC61937)
- ss->rate *= 4;
-
- return 0;
-}
diff --git a/pipewire-pulseaudio/src/core-format.h b/pipewire-pulseaudio/src/core-format.h
deleted file mode 100644
index 37503041b..000000000
--- a/pipewire-pulseaudio/src/core-format.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef foocoreformathfoo
-#define foocoreformathfoo
-
-/***
- This file is part of PulseAudio.
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#include
-
-#include
-
-/* Gets the sample format stored in the format info. Returns a negative error
- * code on failure. If the sample format property is not set at all, returns
- * -PA_ERR_NOENTITY. */
-int pa_format_info_get_sample_format(const pa_format_info *f, pa_sample_format_t *sf);
-
-/* Gets the sample rate stored in the format info. Returns a negative error
- * code on failure. If the sample rate property is not set at all, returns
- * -PA_ERR_NOENTITY. */
-int pa_format_info_get_rate(const pa_format_info *f, uint32_t *rate);
-
-/* Gets the channel count stored in the format info. Returns a negative error
- * code on failure. If the channels property is not set at all, returns
- * -PA_ERR_NOENTITY. */
-int pa_format_info_get_channels(const pa_format_info *f, uint8_t *channels);
-
-/* Gets the channel map stored in the format info. Returns a negative error
- * code on failure. If the channel map property is not set at all, returns
- * -PA_ERR_NOENTITY. */
-int pa_format_info_get_channel_map(const pa_format_info *f, pa_channel_map *map);
-
-/* Convert a sample spec and an optional channel map to a new PCM format info
- * object (remember to free it). If map is NULL, then the channel map will be
- * left unspecified. If some fields of the sample spec should be ignored, pass
- * false for set_format, set_rate and set_channels as appropriate, then those
- * fields will be left unspecified. This function returns NULL if the input is
- * invalid (for example, setting the sample rate was requested, but the rate
- * in ss is invalid).
- *
- * pa_format_info_from_sample_spec() exists too. This "version 2" was created,
- * because the original function doesn't provide the possibility of ignoring
- * some of the sample spec fields. That functionality can't be added to the
- * original function, because the function is a part of the public API and
- * adding parameters to it would break the API. */
-pa_format_info *pa_format_info_from_sample_spec2(const pa_sample_spec *ss, const pa_channel_map *map, bool set_format,
- bool set_rate, bool set_channels);
-
-/* Convert the format info into a sample spec and a channel map. If the format
- * info doesn't contain some information, the fallback sample spec and channel
- * map are used to populate the output.
- *
- * pa_format_info_to_sample_spec() exists too. This "version 2" was created,
- * because the original function doesn't provide the possibility of specifying
- * a fallback sample spec and channel map. That functionality can't be added to
- * the original function, because the function is part of the public API and
- * adding parameters to it would break the API. */
-int pa_format_info_to_sample_spec2(const pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map,
- const pa_sample_spec *fallback_ss, const pa_channel_map *fallback_map);
-
-/* For compressed formats. Converts the format info into a sample spec and a
- * channel map that an ALSA device can use as its configuration parameters when
- * playing back the compressed data. That is, the returned sample spec doesn't
- * describe the audio content, but the device parameters. */
-int pa_format_info_to_sample_spec_fake(const pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map);
-
-#endif
diff --git a/pipewire-pulseaudio/src/direction.c b/pipewire-pulseaudio/src/direction.c
deleted file mode 100644
index d1dc6d722..000000000
--- a/pipewire-pulseaudio/src/direction.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-#include
-
-#define pa_init_i18n()
-#define _(String) (String)
-
-SPA_EXPORT
-int pa_direction_valid(pa_direction_t direction)
-{
- if (direction != PA_DIRECTION_INPUT
- && direction != PA_DIRECTION_OUTPUT
- && direction != (PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT))
- return 0;
- return 1;
-}
-
-SPA_EXPORT
-const char *pa_direction_to_string(pa_direction_t direction) {
- pa_init_i18n();
-
- if (direction == PA_DIRECTION_INPUT)
- return _("input");
- if (direction == PA_DIRECTION_OUTPUT)
- return _("output");
- if (direction == (PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT))
- return _("bidirectional");
-
- return _("invalid");
-}
diff --git a/pipewire-pulseaudio/src/error.c b/pipewire-pulseaudio/src/error.c
deleted file mode 100644
index abf05b634..000000000
--- a/pipewire-pulseaudio/src/error.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-#include
-
-#include
-
-#include
-#include
-
-#define N_(String) (String)
-#define _(String) (String)
-#define pa_init_i18n()
-
-SPA_EXPORT
-const char*pa_strerror(int error)
-{
- static const char* const errortab[PA_ERR_MAX] = {
- [PA_OK] = N_("OK"),
- [PA_ERR_ACCESS] = N_("Access denied"),
- [PA_ERR_COMMAND] = N_("Unknown command"),
- [PA_ERR_INVALID] = N_("Invalid argument"),
- [PA_ERR_EXIST] = N_("Entity exists"),
- [PA_ERR_NOENTITY] = N_("No such entity"),
- [PA_ERR_CONNECTIONREFUSED] = N_("Connection refused"),
- [PA_ERR_PROTOCOL] = N_("Protocol error"),
- [PA_ERR_TIMEOUT] = N_("Timeout"),
- [PA_ERR_AUTHKEY] = N_("No authentication key"),
- [PA_ERR_INTERNAL] = N_("Internal error"),
- [PA_ERR_CONNECTIONTERMINATED] = N_("Connection terminated"),
- [PA_ERR_KILLED] = N_("Entity killed"),
- [PA_ERR_INVALIDSERVER] = N_("Invalid server"),
- [PA_ERR_MODINITFAILED] = N_("Module initialization failed"),
- [PA_ERR_BADSTATE] = N_("Bad state"),
- [PA_ERR_NODATA] = N_("No data"),
- [PA_ERR_VERSION] = N_("Incompatible protocol version"),
- [PA_ERR_TOOLARGE] = N_("Too large"),
- [PA_ERR_NOTSUPPORTED] = N_("Not supported"),
- [PA_ERR_UNKNOWN] = N_("Unknown error code"),
- [PA_ERR_NOEXTENSION] = N_("No such extension"),
- [PA_ERR_OBSOLETE] = N_("Obsolete functionality"),
- [PA_ERR_NOTIMPLEMENTED] = N_("Missing implementation"),
- [PA_ERR_FORKED] = N_("Client forked"),
- [PA_ERR_IO] = N_("Input/Output error"),
- [PA_ERR_BUSY] = N_("Device or resource busy")
- };
-
- pa_init_i18n();
-
- if (error < 0)
- error = -error;
-
- if (error >= PA_ERR_MAX)
- return NULL;
-
- return _(errortab[error]);
-}
-
diff --git a/pipewire-pulseaudio/src/ext-device-manager.c b/pipewire-pulseaudio/src/ext-device-manager.c
deleted file mode 100644
index 942d627af..000000000
--- a/pipewire-pulseaudio/src/ext-device-manager.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include
-
-#include "internal.h"
-
-struct ext_data {
- pa_context *context;
- pa_ext_device_manager_test_cb_t test_cb;
- pa_ext_device_manager_read_cb_t read_cb;
- pa_context_success_cb_t success_cb;
- int error;
- void *userdata;
-};
-
-static void device_test(pa_operation *o, void *userdata)
-{
- struct ext_data *d = userdata;
- if (d->test_cb)
- d->test_cb(o->context, PA_INVALID_INDEX, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_manager_test(
- pa_context *c,
- pa_ext_device_manager_test_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, device_test, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->test_cb = cb;
- d->userdata = userdata;
- d->error = PA_ERR_NOTIMPLEMENTED;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void device_read(pa_operation *o, void *userdata)
-{
- struct ext_data *d = userdata;
- if (d->read_cb)
- d->read_cb(o->context, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_manager_read(
- pa_context *c,
- pa_ext_device_manager_read_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, device_read, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->read_cb = cb;
- d->userdata = userdata;
- d->error = PA_ERR_NOTIMPLEMENTED;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void on_success(pa_operation *o, void *userdata)
-{
- struct ext_data *d = userdata;
- if (d->success_cb)
- d->success_cb(o->context, d->error, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_manager_set_device_description(
- pa_context *c,
- const char* device,
- const char* description,
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- d->error = PA_ERR_NOTIMPLEMENTED;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_manager_delete(
- pa_context *c,
- const char *const s[],
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- d->error = PA_ERR_NOTIMPLEMENTED;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_manager_enable_role_device_priority_routing(
- pa_context *c,
- int enable,
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- d->error = PA_ERR_NOTIMPLEMENTED;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_manager_reorder_devices_for_role(
- pa_context *c,
- const char* role,
- const char** devices,
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- d->error = PA_ERR_NOTIMPLEMENTED;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_manager_subscribe(
- pa_context *c,
- int enable,
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- d->error = PA_ERR_NOTIMPLEMENTED;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-void pa_ext_device_manager_set_subscribe_cb(
- pa_context *c,
- pa_ext_device_manager_subscribe_cb_t cb,
- void *userdata)
-{
-}
diff --git a/pipewire-pulseaudio/src/ext-device-restore.c b/pipewire-pulseaudio/src/ext-device-restore.c
deleted file mode 100644
index e4b8989fb..000000000
--- a/pipewire-pulseaudio/src/ext-device-restore.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include "internal.h"
-
-#define EXT_VERSION 1
-
-struct ext_data {
- pa_context *context;
- pa_ext_device_restore_test_cb_t test_cb;
- pa_ext_device_restore_read_device_formats_cb_t read_cb;
- pa_context_success_cb_t success_cb;
- void *userdata;
-};
-
-static void restore_test(pa_operation *o, void *userdata)
-{
- struct ext_data *d = userdata;
- if (d->test_cb)
- d->test_cb(o->context, PA_INVALID_INDEX, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_restore_test(
- pa_context *c,
- pa_ext_device_restore_test_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, restore_test, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->test_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void on_success(pa_operation *o, void *userdata)
-{
- struct ext_data *d = userdata;
- if (d->success_cb)
- d->success_cb(o->context, PA_OK, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_restore_subscribe(
- pa_context *c,
- int enable,
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-void pa_ext_device_restore_set_subscribe_cb(
- pa_context *c,
- pa_ext_device_restore_subscribe_cb_t cb,
- void *userdata)
-{
-}
-
-static void read_formats(pa_operation *o, void *userdata)
-{
- struct ext_data *d = userdata;
- if (d->read_cb)
- d->read_cb(o->context, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_restore_read_formats_all(
- pa_context *c,
- pa_ext_device_restore_read_device_formats_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, read_formats, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->read_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_restore_read_formats(
- pa_context *c,
- pa_device_type_t type,
- uint32_t idx,
- pa_ext_device_restore_read_device_formats_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, read_formats, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->read_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_device_restore_save_formats(
- pa_context *c,
- pa_device_type_t type,
- uint32_t idx,
- uint8_t n_formats,
- pa_format_info **formats,
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct ext_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct ext_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
diff --git a/pipewire-pulseaudio/src/ext-stream-restore.c b/pipewire-pulseaudio/src/ext-stream-restore.c
deleted file mode 100644
index bc4001506..000000000
--- a/pipewire-pulseaudio/src/ext-stream-restore.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include "internal.h"
-
-struct stream_data {
- pa_context *context;
- pa_ext_stream_restore_test_cb_t test_cb;
- pa_ext_stream_restore_read_cb_t read_cb;
- pa_context_success_cb_t success_cb;
- void *userdata;
-};
-
-static void restore_test(pa_operation *o, void *userdata)
-{
- struct stream_data *d = userdata;
-
- if (d->test_cb)
- d->test_cb(o->context, PA_INVALID_INDEX, d->userdata);
-
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_stream_restore_test(
- pa_context *c,
- pa_ext_stream_restore_test_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct stream_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, restore_test, sizeof(struct stream_data));
- d = o->userdata;
- d->context = c;
- d->test_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void restore_read(pa_operation *o, void *userdata)
-{
- struct stream_data *d = userdata;
-
- if (d->read_cb)
- d->read_cb(o->context, NULL, 1, d->userdata);
-
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_stream_restore_read(
- pa_context *c,
- pa_ext_stream_restore_read_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct stream_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, restore_read, sizeof(struct stream_data));
- d = o->userdata;
- d->context = c;
- d->read_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void on_success(pa_operation *o, void *userdata)
-{
- struct stream_data *d = userdata;
- if (d->success_cb)
- d->success_cb(o->context, PA_OK, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation *pa_ext_stream_restore_write(
- pa_context *c,
- pa_update_mode_t mode,
- const pa_ext_stream_restore_info data[],
- unsigned n,
- int apply_immediately,
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct stream_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct stream_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-/** Delete entries from the stream database. \since 0.9.12 */
-SPA_EXPORT
-pa_operation *pa_ext_stream_restore_delete(
- pa_context *c,
- const char *const s[],
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct stream_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct stream_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-/** Subscribe to changes in the stream database. \since 0.9.12 */
-SPA_EXPORT
-pa_operation *pa_ext_stream_restore_subscribe(
- pa_context *c,
- int enable,
- pa_context_success_cb_t cb,
- void *userdata)
-{
- pa_operation *o;
- struct stream_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct stream_data));
- d = o->userdata;
- d->context = c;
- d->success_cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-/** Set the subscription callback that is called when
- * pa_ext_stream_restore_subscribe() was called. \since 0.9.12 */
-SPA_EXPORT
-void pa_ext_stream_restore_set_subscribe_cb(
- pa_context *c,
- pa_ext_stream_restore_subscribe_cb_t cb,
- void *userdata)
-{
-}
diff --git a/pipewire-pulseaudio/src/format.c b/pipewire-pulseaudio/src/format.c
deleted file mode 100644
index 1575a4e39..000000000
--- a/pipewire-pulseaudio/src/format.c
+++ /dev/null
@@ -1,915 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2011 Intel Corporation
- Copyright 2011 Collabora Multimedia
- Copyright 2011 Arun Raghavan
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-#include
-
-#include "core-format.h"
-#include "json.h"
-#include "internal.h"
-#include "strbuf.h"
-
-#define PA_JSON_MIN_KEY "min"
-#define PA_JSON_MAX_KEY "max"
-
-static int pa_format_info_prop_compatible(const char *one, const char *two);
-
-static const uint32_t audio_formats[] = {
- [PA_SAMPLE_U8] = SPA_AUDIO_FORMAT_U8,
- [PA_SAMPLE_ALAW] = SPA_AUDIO_FORMAT_UNKNOWN,
- [PA_SAMPLE_ULAW] = SPA_AUDIO_FORMAT_UNKNOWN,
- [PA_SAMPLE_S16NE] = SPA_AUDIO_FORMAT_S16,
- [PA_SAMPLE_S16RE] = SPA_AUDIO_FORMAT_S16_OE,
- [PA_SAMPLE_FLOAT32NE] = SPA_AUDIO_FORMAT_F32,
- [PA_SAMPLE_FLOAT32RE] = SPA_AUDIO_FORMAT_F32_OE,
- [PA_SAMPLE_S32NE] = SPA_AUDIO_FORMAT_S32,
- [PA_SAMPLE_S32RE] = SPA_AUDIO_FORMAT_S32_OE,
- [PA_SAMPLE_S24NE] = SPA_AUDIO_FORMAT_S24,
- [PA_SAMPLE_S24RE] = SPA_AUDIO_FORMAT_S24_OE,
- [PA_SAMPLE_S24_32NE] = SPA_AUDIO_FORMAT_S24_32,
- [PA_SAMPLE_S24_32RE] = SPA_AUDIO_FORMAT_S24_32_OE,
-};
-
-static inline uint32_t format_pa2id(pa_sample_format_t format)
-{
- if (format < 0 || (size_t)format >= SPA_N_ELEMENTS(audio_formats))
- return SPA_AUDIO_FORMAT_UNKNOWN;
- return audio_formats[format];
-}
-
-static inline pa_sample_format_t format_id2pa(uint32_t id)
-{
- size_t i;
- for (i = 0; i < SPA_N_ELEMENTS(audio_formats); i++) {
- if (id == audio_formats[i])
- return i;
- }
- return PA_SAMPLE_INVALID;
-}
-
-static const char* const _encoding_str_table[]= {
- [PA_ENCODING_PCM] = "pcm",
- [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
- [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
- [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
- [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
- [PA_ENCODING_MPEG2_AAC_IEC61937] = "mpeg2-aac-iec61937",
-#if PA_CHECK_VERSION(13, 0, 0)
- [PA_ENCODING_TRUEHD_IEC61937] = "truehd-iec61937",
- [PA_ENCODING_DTSHD_IEC61937] = "dtshd-iec61937",
-#endif
- [PA_ENCODING_ANY] = "any",
-};
-
-SPA_EXPORT
-const char *pa_encoding_to_string(pa_encoding_t e) {
- if (e < 0 || e >= PA_ENCODING_MAX)
- return NULL;
-
- return _encoding_str_table[e];
-}
-
-SPA_EXPORT
-pa_encoding_t pa_encoding_from_string(const char *encoding) {
- pa_encoding_t e;
-
- for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++)
- if (pa_streq(_encoding_str_table[e], encoding))
- return e;
-
- return PA_ENCODING_INVALID;
-}
-
-SPA_EXPORT
-pa_format_info* pa_format_info_new(void) {
- pa_format_info *f = pa_xnew(pa_format_info, 1);
-
- f->encoding = PA_ENCODING_INVALID;
- f->plist = pa_proplist_new();
-
- return f;
-}
-
-SPA_EXPORT
-pa_format_info* pa_format_info_copy(const pa_format_info *src) {
- pa_format_info *dest;
-
- pa_assert(src);
-
- dest = pa_xnew(pa_format_info, 1);
-
- dest->encoding = src->encoding;
-
- if (src->plist)
- dest->plist = pa_proplist_copy(src->plist);
- else
- dest->plist = NULL;
-
- return dest;
-}
-
-SPA_EXPORT
-void pa_format_info_free(pa_format_info *f) {
- pa_assert(f);
-
- pa_proplist_free(f->plist);
- pa_xfree(f);
-}
-
-SPA_EXPORT
-int pa_format_info_valid(const pa_format_info *f) {
- return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
-}
-
-SPA_EXPORT
-int pa_format_info_is_pcm(const pa_format_info *f) {
- return f->encoding == PA_ENCODING_PCM;
-}
-
-SPA_EXPORT
-char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
- char *tmp;
-
- pa_assert(s);
- pa_assert(l > 0);
- pa_assert(f);
-
- pa_init_i18n();
-
- if (!pa_format_info_valid(f))
- pa_snprintf(s, l, _("(invalid)"));
- else {
- tmp = pa_proplist_to_string_sep(f->plist, " ");
- if (tmp[0])
- pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
- else
- pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
- pa_xfree(tmp);
- }
-
- return s;
-}
-
-SPA_EXPORT
-pa_format_info* pa_format_info_from_string(const char *str) {
- pa_format_info *f = pa_format_info_new();
- char *encoding = NULL, *properties = NULL;
- size_t pos;
-
- pos = strcspn(str, ",");
-
- encoding = pa_xstrndup(str, pos);
- f->encoding = pa_encoding_from_string(pa_strip(encoding));
- if (f->encoding == PA_ENCODING_INVALID)
- goto error;
-
- if (pos != strlen(str)) {
- pa_proplist *plist;
-
- properties = pa_xstrdup(&str[pos+1]);
- plist = pa_proplist_from_string(properties);
-
- if (!plist)
- goto error;
-
- pa_proplist_free(f->plist);
- f->plist = plist;
- }
-
-out:
- if (encoding)
- pa_xfree(encoding);
- if (properties)
- pa_xfree(properties);
- return f;
-
-error:
- pa_format_info_free(f);
- f = NULL;
- goto out;
-}
-
-SPA_EXPORT
-int pa_format_info_is_compatible(const pa_format_info *first, const pa_format_info *second) {
- const char *key;
- void *state = NULL;
-
- pa_assert(first);
- pa_assert(second);
-
- if (first->encoding != second->encoding)
- return false;
-
- while ((key = pa_proplist_iterate(first->plist, &state))) {
- const char *value_one, *value_two;
-
- value_one = pa_proplist_gets(first->plist, key);
- value_two = pa_proplist_gets(second->plist, key);
-
- if (!value_two || !pa_format_info_prop_compatible(value_one, value_two))
- return false;
- }
-
- return true;
-}
-
-SPA_EXPORT
-pa_format_info* pa_format_info_from_sample_spec(const pa_sample_spec *ss, const pa_channel_map *map) {
- char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
- pa_format_info *f;
-
- pa_assert(ss && pa_sample_spec_valid(ss));
- pa_assert(!map || pa_channel_map_valid(map));
-
- f = pa_format_info_new();
- f->encoding = PA_ENCODING_PCM;
-
- pa_format_info_set_sample_format(f, ss->format);
- pa_format_info_set_rate(f, ss->rate);
- pa_format_info_set_channels(f, ss->channels);
-
- if (map) {
- pa_channel_map_snprint(cm, sizeof(cm), map);
- pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
- }
-
- return f;
-}
-
-/* For PCM streams */
-SPA_EXPORT
-int pa_format_info_to_sample_spec(const pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
- pa_assert(f);
- pa_assert(ss);
-
- if (!pa_format_info_is_pcm(f))
- return pa_format_info_to_sample_spec_fake(f, ss, map);
-
- if (pa_format_info_get_sample_format(f, &ss->format) < 0)
- return -PA_ERR_INVALID;
- if (pa_format_info_get_rate(f, &ss->rate) < 0)
- return -PA_ERR_INVALID;
- if (pa_format_info_get_channels(f, &ss->channels) < 0)
- return -PA_ERR_INVALID;
- if (map && pa_format_info_get_channel_map(f, map) < 0)
- return -PA_ERR_INVALID;
-
- return 0;
-}
-
-SPA_EXPORT
-pa_prop_type_t pa_format_info_get_prop_type(const pa_format_info *f, const char *key) {
- const char *str;
- pa_json_object *o;
- const pa_json_object *o1;
- pa_prop_type_t type;
-
- pa_assert(f);
- pa_assert(key);
-
- str = pa_proplist_gets(f->plist, key);
- if (!str)
- return PA_PROP_TYPE_INVALID;
-
- o = pa_json_parse(str);
- if (!o)
- return PA_PROP_TYPE_INVALID;
-
- switch (pa_json_object_get_type(o)) {
- case PA_JSON_TYPE_INT:
- type = PA_PROP_TYPE_INT;
- break;
-
- case PA_JSON_TYPE_STRING:
- type = PA_PROP_TYPE_STRING;
- break;
-
- case PA_JSON_TYPE_ARRAY:
- if (pa_json_object_get_array_length(o) == 0) {
- /* Unlikely, but let's account for this anyway. We need at
- * least one element to figure out the array type. */
- type = PA_PROP_TYPE_INVALID;
- break;
- }
-
- o1 = pa_json_object_get_array_member(o, 0);
-
- if (pa_json_object_get_type(o1) == PA_JSON_TYPE_INT)
- type = PA_PROP_TYPE_INT_ARRAY;
- else if (pa_json_object_get_type(o1) == PA_JSON_TYPE_STRING)
- type = PA_PROP_TYPE_STRING_ARRAY;
- else
- type = PA_PROP_TYPE_INVALID;
-
- break;
-
- case PA_JSON_TYPE_OBJECT:
- /* We actually know at this point that it's a int range, but let's
- * confirm. */
- if (!pa_json_object_get_object_member(o, PA_JSON_MIN_KEY)) {
- type = PA_PROP_TYPE_INVALID;
- break;
- }
-
- if (!pa_json_object_get_object_member(o, PA_JSON_MAX_KEY)) {
- type = PA_PROP_TYPE_INVALID;
- break;
- }
-
- type = PA_PROP_TYPE_INT_RANGE;
- break;
-
- default:
- type = PA_PROP_TYPE_INVALID;
- break;
- }
-
- pa_json_object_free(o);
- return type;
-}
-
-SPA_EXPORT
-int pa_format_info_get_prop_int(const pa_format_info *f, const char *key, int *v) {
- const char *str;
- pa_json_object *o;
-
- pa_assert(f);
- pa_assert(key);
- pa_assert(v);
-
- str = pa_proplist_gets(f->plist, key);
- if (!str)
- return -PA_ERR_NOENTITY;
-
- o = pa_json_parse(str);
- if (!o) {
- pa_log_debug("Failed to parse format info property '%s'.", key);
- return -PA_ERR_INVALID;
- }
-
- if (pa_json_object_get_type(o) != PA_JSON_TYPE_INT) {
- pa_log_debug("Format info property '%s' type is not int.", key);
- pa_json_object_free(o);
- return -PA_ERR_INVALID;
- }
-
- *v = pa_json_object_get_int(o);
- pa_json_object_free(o);
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_format_info_get_prop_int_range(const pa_format_info *f, const char *key, int *min, int *max) {
- const char *str;
- pa_json_object *o;
- const pa_json_object *o1;
- int ret = -PA_ERR_INVALID;
-
- pa_assert(f);
- pa_assert(key);
- pa_assert(min);
- pa_assert(max);
-
- str = pa_proplist_gets(f->plist, key);
- if (!str)
- return -PA_ERR_NOENTITY;
-
- o = pa_json_parse(str);
- if (!o) {
- pa_log_debug("Failed to parse format info property '%s'.", key);
- return -PA_ERR_INVALID;
- }
-
- if (pa_json_object_get_type(o) != PA_JSON_TYPE_OBJECT)
- goto out;
-
- if (!(o1 = pa_json_object_get_object_member(o, PA_JSON_MIN_KEY)) ||
- (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT))
- goto out;
-
- *min = pa_json_object_get_int(o1);
-
- if (!(o1 = pa_json_object_get_object_member(o, PA_JSON_MAX_KEY)) ||
- (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT))
- goto out;
-
- *max = pa_json_object_get_int(o1);
-
- ret = 0;
-
-out:
- if (ret < 0)
- pa_log_debug("Format info property '%s' is not a valid int range.", key);
-
- pa_json_object_free(o);
- return ret;
-}
-
-SPA_EXPORT
-int pa_format_info_get_prop_int_array(const pa_format_info *f, const char *key, int **values, int *n_values) {
- const char *str;
- pa_json_object *o;
- const pa_json_object *o1;
- int i, ret = -PA_ERR_INVALID;
-
- pa_assert(f);
- pa_assert(key);
- pa_assert(values);
- pa_assert(n_values);
-
- str = pa_proplist_gets(f->plist, key);
- if (!str)
- return -PA_ERR_NOENTITY;
-
- o = pa_json_parse(str);
- if (!o) {
- pa_log_debug("Failed to parse format info property '%s'.", key);
- return -PA_ERR_INVALID;
- }
-
- if (pa_json_object_get_type(o) != PA_JSON_TYPE_ARRAY)
- goto out;
-
- *n_values = pa_json_object_get_array_length(o);
- *values = pa_xnew(int, *n_values);
-
- for (i = 0; i < *n_values; i++) {
- o1 = pa_json_object_get_array_member(o, i);
-
- if (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT) {
- goto out;
- }
-
- (*values)[i] = pa_json_object_get_int(o1);
- }
-
- ret = 0;
-
-out:
- if (ret < 0)
- pa_log_debug("Format info property '%s' is not a valid int array.", key);
-
- pa_json_object_free(o);
- return ret;
-}
-
-SPA_EXPORT
-int pa_format_info_get_prop_string(const pa_format_info *f, const char *key, char **v) {
- const char *str = NULL;
- pa_json_object *o;
-
- pa_assert(f);
- pa_assert(key);
- pa_assert(v);
-
- str = pa_proplist_gets(f->plist, key);
- if (!str)
- return -PA_ERR_NOENTITY;
-
- o = pa_json_parse(str);
- if (!o) {
- pa_log_debug("Failed to parse format info property '%s'.", key);
- return -PA_ERR_INVALID;
- }
-
- if (pa_json_object_get_type(o) != PA_JSON_TYPE_STRING) {
- pa_log_debug("Format info property '%s' type is not string.", key);
- pa_json_object_free(o);
- return -PA_ERR_INVALID;
- }
-
- *v = pa_xstrdup(pa_json_object_get_string(o));
- pa_json_object_free(o);
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_format_info_get_prop_string_array(const pa_format_info *f, const char *key, char ***values, int *n_values) {
- const char *str;
- pa_json_object *o;
- const pa_json_object *o1;
- int i, ret = -PA_ERR_INVALID;
-
- pa_assert(f);
- pa_assert(key);
- pa_assert(values);
- pa_assert(n_values);
-
- str = pa_proplist_gets(f->plist, key);
- if (!str)
- return -PA_ERR_NOENTITY;
-
- o = pa_json_parse(str);
- if (!o) {
- pa_log_debug("Failed to parse format info property '%s'.", key);
- return -PA_ERR_INVALID;
- }
-
- if (pa_json_object_get_type(o) != PA_JSON_TYPE_ARRAY)
- goto out;
-
- *n_values = pa_json_object_get_array_length(o);
- *values = pa_xnew(char *, *n_values);
-
- for (i = 0; i < *n_values; i++) {
- o1 = pa_json_object_get_array_member(o, i);
-
- if (pa_json_object_get_type(o1) != PA_JSON_TYPE_STRING) {
- goto out;
- }
-
- (*values)[i] = pa_xstrdup(pa_json_object_get_string(o1));
- }
-
- ret = 0;
-
-out:
- if (ret < 0)
- pa_log_debug("Format info property '%s' is not a valid string array.", key);
-
- pa_json_object_free(o);
- return ret;
-}
-
-SPA_EXPORT
-void pa_format_info_free_string_array(char **values, int n_values) {
- int i;
-
- for (i = 0; i < n_values; i++)
- pa_xfree(values[i]);
-
- pa_xfree(values);
-}
-
-SPA_EXPORT
-void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
- pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
-}
-
-SPA_EXPORT
-void pa_format_info_set_rate(pa_format_info *f, int rate) {
- pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
-}
-
-SPA_EXPORT
-void pa_format_info_set_channels(pa_format_info *f, int channels) {
- pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
-}
-
-SPA_EXPORT
-void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
- char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
-
- pa_channel_map_snprint(map_str, sizeof(map_str), map);
-
- pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
-}
-
-SPA_EXPORT
-void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
- pa_assert(f);
- pa_assert(key);
-
- pa_proplist_setf(f->plist, key, "%d", value);
-}
-
-SPA_EXPORT
-void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
- pa_strbuf *buf;
- char *str;
- int i;
-
- pa_assert(f);
- pa_assert(key);
- pa_assert(n_values > 0);
-
- buf = pa_strbuf_new();
-
- pa_strbuf_printf(buf, "[ %d", values[0]);
-
- for (i = 1; i < n_values; i++)
- pa_strbuf_printf(buf, ", %d", values[i]);
-
- pa_strbuf_printf(buf, " ]");
- str = pa_strbuf_to_string_free(buf);
-
- pa_proplist_sets(f->plist, key, str);
- pa_xfree (str);
-}
-
-SPA_EXPORT
-void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
- pa_assert(f);
- pa_assert(key);
-
- pa_proplist_setf(f->plist, key, "{ \"" PA_JSON_MIN_KEY "\": %d, \"" PA_JSON_MAX_KEY "\": %d }",
- min, max);
-}
-
-SPA_EXPORT
-void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
- pa_assert(f);
- pa_assert(key);
-
- pa_proplist_setf(f->plist, key, "\"%s\"", value);
-}
-
-SPA_EXPORT
-void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
- pa_strbuf *buf;
- char *str;
- int i;
-
- pa_assert(f);
- pa_assert(key);
-
- buf = pa_strbuf_new();
-
- pa_strbuf_printf(buf, "[ \"%s\"", values[0]);
-
- for (i = 1; i < n_values; i++)
- pa_strbuf_printf(buf, ", \"%s\"", values[i]);
-
- pa_strbuf_printf(buf, " ]");
- str = pa_strbuf_to_string_free(buf);
-
- pa_proplist_sets(f->plist, key, str);
- pa_xfree (str);
-}
-
-static bool pa_json_is_fixed_type(pa_json_object *o) {
- switch(pa_json_object_get_type(o)) {
- case PA_JSON_TYPE_OBJECT:
- case PA_JSON_TYPE_ARRAY:
- return false;
-
- default:
- return true;
- }
-}
-
-static int pa_format_info_prop_compatible(const char *one, const char *two) {
- pa_json_object *o1 = NULL, *o2 = NULL;
- int i, ret = 0;
-
- o1 = pa_json_parse(one);
- if (!o1)
- goto out;
-
- o2 = pa_json_parse(two);
- if (!o2)
- goto out;
-
- /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
- pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), false);
-
- if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
- ret = pa_json_object_equal(o1, o2);
- goto out;
- }
-
- if (pa_json_is_fixed_type(o1)) {
- pa_json_object *tmp = o2;
- o2 = o1;
- o1 = tmp;
- }
-
- /* o2 is now a fixed type, and o1 is not */
-
- if (pa_json_object_get_type(o1) == PA_JSON_TYPE_ARRAY) {
- for (i = 0; i < pa_json_object_get_array_length(o1); i++) {
- if (pa_json_object_equal(pa_json_object_get_array_member(o1, i), o2)) {
- ret = 1;
- break;
- }
- }
- } else if (pa_json_object_get_type(o1) == PA_JSON_TYPE_OBJECT) {
- /* o1 should be a range type */
- int min, max, v;
- const pa_json_object *o_min = NULL, *o_max = NULL;
-
- if (pa_json_object_get_type(o2) != PA_JSON_TYPE_INT) {
- /* We don't support non-integer ranges */
- goto out;
- }
-
- if (!(o_min = pa_json_object_get_object_member(o1, PA_JSON_MIN_KEY)) ||
- pa_json_object_get_type(o_min) != PA_JSON_TYPE_INT)
- goto out;
-
- if (!(o_max = pa_json_object_get_object_member(o1, PA_JSON_MAX_KEY)) ||
- pa_json_object_get_type(o_max) != PA_JSON_TYPE_INT)
- goto out;
-
- v = pa_json_object_get_int(o2);
- min = pa_json_object_get_int(o_min);
- max = pa_json_object_get_int(o_max);
-
- ret = v >= min && v <= max;
- } else {
- pa_log_warn("Got a format type that we don't support");
- }
-
-out:
- if (o1)
- pa_json_object_free(o1);
- if (o2)
- pa_json_object_free(o2);
-
- return ret;
-}
-
-static void format_info_fill_int(pa_format_info *f, const struct spa_pod *val, const char *key)
-{
- const struct spa_pod *vals;
- int *int_vals;
- uint32_t *uvals, i, n_vals, choice;
- vals = spa_pod_get_values(val, &n_vals, &choice);
- uvals = SPA_POD_BODY(vals);
-
- int_vals = alloca(n_vals * sizeof(int));
- for (i = 0; i < n_vals; i++)
- int_vals[i] = uvals[i];
-
- if (n_vals == 1)
- choice = SPA_CHOICE_None;
-
- switch (choice) {
- case SPA_CHOICE_None:
- if (n_vals > 0)
- pa_format_info_set_prop_int(f,
- key, int_vals[0]);
- break;
-
- case SPA_CHOICE_Enum:
- if (n_vals > 1)
- pa_format_info_set_prop_int_array(f,
- key, &int_vals[1], n_vals-1);
- break;
-
- case SPA_CHOICE_Range:
- if (n_vals > 2)
- pa_format_info_set_prop_int_range(f,
- key, int_vals[1], int_vals[2]);
- break;
- }
-}
-
-static void format_info_fill_format(pa_format_info *f, const struct spa_pod *val, const char *key)
-{
- const struct spa_pod *vals;
- const char **svals;
- uint32_t *uvals, i, j, n_vals, choice;
- vals = spa_pod_get_values(val, &n_vals, &choice);
- uvals = SPA_POD_BODY(vals);
-
- svals = alloca(n_vals * sizeof(char *));
- for (i = 0, j = 0; i < n_vals; i++) {
- pa_sample_format_t fmt = format_id2pa(uvals[i]);
- const char *s = pa_sample_format_to_string(fmt);
- if (s)
- svals[j++] = s;
- }
- n_vals = j;
- if (n_vals == 1)
- choice = SPA_CHOICE_None;
-
- switch (choice) {
- case SPA_CHOICE_None:
- if (n_vals > 0)
- pa_format_info_set_prop_string(f, key, svals[0]);
- break;
-
- case SPA_CHOICE_Enum:
- if (n_vals > 1)
- pa_format_info_set_prop_string_array(f,
- key, &svals[1], n_vals-1);
- break;
- }
-}
-
-pa_format_info* pa_format_info_from_param(const struct spa_pod *param)
-{
- pa_format_info *f = pa_format_info_new();
- struct spa_audio_info info = { 0 };
- const struct spa_pod_object *obj;
- const struct spa_pod_prop *p;
-
- if (param == NULL ||
- !spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Format))
- goto error;
-
- spa_format_parse(param, &info.media_type, &info.media_subtype);
- if (info.media_type != SPA_MEDIA_TYPE_audio)
- goto error;
-
- switch (info.media_subtype) {
- case SPA_MEDIA_SUBTYPE_raw:
- f->encoding = PA_ENCODING_PCM;
- break;
- default:
- goto error;
- }
-
- obj = (const struct spa_pod_object*)param;
- SPA_POD_OBJECT_FOREACH(obj, p) {
- switch (p->key) {
- case SPA_FORMAT_AUDIO_format:
- format_info_fill_format(f, &p->value, PA_PROP_FORMAT_SAMPLE_FORMAT);
- break;
- case SPA_FORMAT_AUDIO_rate:
- format_info_fill_int(f, &p->value, PA_PROP_FORMAT_RATE);
- break;
- case SPA_FORMAT_AUDIO_channels:
- format_info_fill_int(f, &p->value, PA_PROP_FORMAT_CHANNELS);
- break;
- case SPA_FORMAT_AUDIO_position:
- {
- uint32_t pos[SPA_AUDIO_MAX_CHANNELS], n_pos;
-
- n_pos = spa_pod_copy_array(&p->value, SPA_TYPE_Id, pos, SPA_AUDIO_MAX_CHANNELS);
- if (n_pos > 0) {
- char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
- pa_channel_map map;
- pw_channel_map_from_positions(&map, n_pos, pos);
- pa_channel_map_snprint(cm, sizeof(cm), &map);
- pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
- }
- break;
- }
- default:
- break;
- }
- }
- return f;
-error:
- pa_format_info_free(f);
- return NULL;
-}
-
-
-int pa_format_parse_param(const struct spa_pod *param, pa_sample_spec *spec, pa_channel_map *map)
-{
- struct spa_audio_info info = { 0 };
-
- if (param == NULL)
- return -EINVAL;
-
- spa_format_parse(param, &info.media_type, &info.media_subtype);
-
- if (info.media_type != SPA_MEDIA_TYPE_audio ||
- info.media_subtype != SPA_MEDIA_SUBTYPE_raw ||
- spa_format_audio_raw_parse(param, &info.info.raw) < 0 ||
- !SPA_AUDIO_FORMAT_IS_INTERLEAVED(info.info.raw.format)) {
- return -ENOTSUP;
- }
-
- spec->format = format_id2pa(info.info.raw.format);
- if (spec->format == PA_SAMPLE_INVALID)
- return -ENOTSUP;
-
- spec->rate = info.info.raw.rate;
- spec->channels = info.info.raw.channels;
-
- pw_channel_map_from_positions(map, info.info.raw.channels, info.info.raw.position);
-
- return 0;
-}
-
-const struct spa_pod *pa_format_build_param(struct spa_pod_builder *b,
- uint32_t id, pa_sample_spec *spec, pa_channel_map *map)
-{
- struct spa_audio_info_raw info;
-
- info = SPA_AUDIO_INFO_RAW_INIT( .format = format_pa2id(spec->format),
- .channels = spec->channels,
- .rate = spec->rate);
- if (map)
- pw_channel_map_to_positions(map, info.position);
-
- return spa_format_audio_raw_build(b, id, &info);
-}
diff --git a/pipewire-pulseaudio/src/internal.h b/pipewire-pulseaudio/src/internal.h
deleted file mode 100644
index 81156cf32..000000000
--- a/pipewire-pulseaudio/src/internal.h
+++ /dev/null
@@ -1,542 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __PIPEWIRE_PULSEAUDIO_INTERNAL_H__
-#define __PIPEWIRE_PULSEAUDIO_INTERNAL_H__
-
-#include
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-/* Some PulseAudio API added const qualifiers in 13.0 */
-#if PA_MAJOR >= 13
-#define PA_CONST const
-#else
-#define PA_CONST
-#endif
-
-#define PA_MAX_FORMATS (PA_ENCODING_MAX)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define pa_streq(a,b) (!strcmp((a),(b)))
-#define pa_strneq(a,b,n) (!strncmp((a),(b),(n)))
-
-#ifndef PA_LIKELY
-#define PA_UNLIKELY SPA_UNLIKELY
-#define PA_LIKELY SPA_LIKELY
-#endif
-#define PA_MIN SPA_MIN
-#define PA_MAX SPA_MAX
-#define pa_assert spa_assert
-#define pa_assert_se spa_assert_se
-#define pa_return_val_if_fail(expr, val) \
- do { \
- if (SPA_UNLIKELY(!(expr))) { \
- pa_log_debug("Assertion '%s' failed at %s:%u %s()\n", \
- #expr , __FILE__, __LINE__, __func__); \
- return (val); \
- } \
- } while(false)
-
-#define pa_assert_not_reached spa_assert_not_reached
-
-#define PA_INT_TYPE_SIGNED(type) (!!((type) 0 > (type) -1))
-
-#define PA_INT_TYPE_HALF(type) ((type) 1 << (sizeof(type)*8 - 2))
-
-#define PA_INT_TYPE_MAX(type) \
- ((type) (PA_INT_TYPE_SIGNED(type) \
- ? (PA_INT_TYPE_HALF(type) - 1 + PA_INT_TYPE_HALF(type)) \
- : (type) -1))
-
-#define PA_INT_TYPE_MIN(type) \
- ((type) (PA_INT_TYPE_SIGNED(type) \
- ? (-1 - PA_INT_TYPE_MAX(type)) \
- : (type) 0))
-
-
-#ifdef __GNUC__
-#define PA_CLAMP_UNLIKELY(x, low, high) \
- __extension__ ({ \
- typeof(x) _x = (x); \
- typeof(low) _low = (low); \
- typeof(high) _high = (high); \
- (PA_UNLIKELY(_x > _high) ? _high : (PA_UNLIKELY(_x < _low) ? _low : _x)); \
- })
-#else
-#define PA_CLAMP_UNLIKELY(x, low, high) (PA_UNLIKELY((x) > (high)) ? (high) : (PA_UNLIKELY((x) < (low)) ? (low) : (x)))
-#endif
-
-#ifdef __GNUC__
-#define PA_ROUND_DOWN(a, b) \
- __extension__ ({ \
- typeof(a) _a = (a); \
- typeof(b) _b = (b); \
- (_a / _b) * _b; \
- })
-#else
-#define PA_ROUND_DOWN(a, b) (((a) / (b)) * (b))
-#endif
-
-
-#define pa_init_i18n()
-#define _(String) (String)
-#define N_(String) (String)
-
-#define pa_snprintf snprintf
-#define pa_strip(n) pw_strip(n,"\n\r \t")
-
-#define pa_log pw_log_info
-#define pa_log_debug pw_log_debug
-#define pa_log_warn pw_log_warn
-
-static inline void* PA_ALIGN_PTR(const void *p) {
- return (void*) (((size_t) p) & ~(sizeof(void*) - 1));
-}
-
-/* Rounds up */
-static inline size_t PA_ALIGN(size_t l) {
- return ((l + sizeof(void*) - 1) & ~(sizeof(void*) - 1));
-}
-
-static inline const char *pa_strnull(const char *x) {
- return x ? x : "(null)";
-}
-
-int pa_context_set_error(PA_CONST pa_context *c, int error);
-void pa_context_fail(PA_CONST pa_context *c, int error);
-
-#define PA_CHECK_VALIDITY(context, expression, error) \
-do { \
- if (!(expression)) { \
- pw_log_debug("'%s' failed at %s:%u %s()", \
- #expression, __FILE__, __LINE__, __func__); \
- return -pa_context_set_error((context), (error)); \
- } \
-} while(false)
-
-#define PA_CHECK_VALIDITY_RETURN_ANY(context, expression, error, value) \
-do { \
- if (!(expression)) { \
- pw_log_debug("'%s' failed at %s:%u %s()", \
- #expression, __FILE__, __LINE__, __func__); \
- pa_context_set_error((context), (error)); \
- return value; \
- } \
-} while(false)
-
-#define PA_CHECK_VALIDITY_RETURN_NULL(context, expression, error) \
- PA_CHECK_VALIDITY_RETURN_ANY(context, expression, error, NULL)
-
-#define PA_FAIL(context, error) \
- do { \
- pw_log_debug("fail at %s:%u %s()", \
- , __FILE__, __LINE__, __func__); \
- return -pa_context_set_error((context), (error)); \
- } while(false)
-
-#define PA_FAIL_RETURN_ANY(context, error, value) \
- do { \
- pw_log_debug("fail at %s:%u %s()", \
- , __FILE__, __LINE__, __func__); \
- pa_context_set_error((context), (error)); \
- return value; \
- } while(false)
-
-#define PA_FAIL_RETURN_NULL(context, error) \
- PA_FAIL_RETURN_ANY(context, error, NULL)
-
-
-pa_proplist* pa_proplist_new_props(struct pw_properties *props);
-pa_proplist* pa_proplist_new_dict(struct spa_dict *dict);
-int pa_proplist_update_dict(pa_proplist *p, struct spa_dict *dict);
-int pw_properties_update_proplist(struct pw_properties *props, PA_CONST pa_proplist *p);
-
-struct pa_io_event {
- struct spa_source *source;
- struct pa_mainloop *mainloop;
- int fd;
- pa_io_event_flags_t events;
- pa_io_event_cb_t cb;
- void *userdata;
- pa_io_event_destroy_cb_t destroy;
-};
-
-struct pa_time_event {
- struct spa_source *source;
- struct pa_mainloop *mainloop;
- pa_time_event_cb_t cb;
- void *userdata;
- pa_time_event_destroy_cb_t destroy;
-};
-
-struct pa_defer_event {
- struct spa_source *source;
- struct pa_mainloop *mainloop;
- pa_defer_event_cb_t cb;
- void *userdata;
- pa_defer_event_destroy_cb_t destroy;
-};
-
-struct pa_mainloop {
- struct pw_loop *loop;
- struct spa_source *event;
-
- pa_mainloop_api api;
-
- bool quit;
- int retval;
-
- int timeout;
- int n_events;
-
- int fd;
- pa_poll_func poll_func;
- void *poll_func_userdata;
-};
-
-struct param {
- struct spa_list link;
- uint32_t id;
- void *param;
-};
-
-#define PA_IDX_FLAG_MONITOR 0x800000U
-#define PA_IDX_MASK_MONITOR 0x7fffffU
-
-struct port_device {
- uint32_t n_devices;
- uint32_t *devices;
-};
-
-struct global;
-
-struct global_info {
- uint32_t version;
- const void *events;
- pw_destroy_t destroy;
- void (*sync) (struct global *g);
-};
-
-struct global {
- struct spa_list link;
- uint32_t id;
- uint32_t permissions;
- char *type;
- struct pw_properties *props;
-
- pa_context *context;
- pa_subscription_mask_t mask;
- pa_subscription_event_type_t event;
-
- int priority_driver;
- int init:1;
- int sync:1;
-
- int changed;
- void *info;
- struct global_info *ginfo;
-
- struct pw_proxy *proxy;
- struct spa_hook proxy_listener;
- struct spa_hook object_listener;
-
- pa_stream *stream;
-
- union {
- /* for links */
- struct {
- struct global *src;
- struct global *dst;
- } link_info;
- /* for sink/source */
- struct {
- uint32_t client_id; /* if of owner client */
- uint32_t monitor;
-#define NODE_FLAG_HW_VOLUME (1 << 0)
-#define NODE_FLAG_DEVICE_VOLUME (1 << 1)
-#define NODE_FLAG_HW_MUTE (1 << 4)
-#define NODE_FLAG_DEVICE_MUTE (1 << 5)
- uint32_t flags;
- float volume;
- bool mute;
- pa_sample_spec sample_spec;
- pa_channel_map channel_map;
- uint32_t n_channel_volumes;
- float channel_volumes[SPA_AUDIO_MAX_CHANNELS];
- uint32_t device_id; /* id of device (card) */
- uint32_t profile_device_id; /* id in profile */
- float base_volume;
- float volume_step;
- uint32_t active_port;
- enum spa_param_availability available_port;
- uint32_t device_index;
- struct pw_array formats;
- } node_info;
- struct {
- uint32_t node_id;
- } port_info;
- /* for devices */
- struct {
- struct spa_list profiles;
- uint32_t n_profiles;
- uint32_t active_profile;
- struct spa_list ports;
- uint32_t n_ports;
- struct spa_list routes;
- uint32_t n_routes;
- pa_card_info info;
- pa_card_profile_info2 *card_profiles;
- unsigned int pending_profiles:1;
- pa_card_port_info *card_ports;
- unsigned int pending_ports:1;
- struct port_device *port_devices;
- } card_info;
- struct {
- pa_module_info info;
- } module_info;
- struct {
- pa_client_info info;
- } client_info;
- };
-};
-
-struct module_info {
- struct spa_list link; /* link in context modules */
- uint32_t id;
- struct pw_proxy *proxy;
- struct spa_hook listener;
-};
-
-struct pa_context {
- int refcount;
- uint32_t client_index;
-
- pa_io_event *io;
- bool fallback_loop;
- struct pw_loop *loop;
- struct pw_context *context;
-
- struct pw_properties *props;
-
- struct pw_core *core;
- struct spa_hook core_listener;
- struct pw_core_info *core_info;
-
- struct pw_registry *registry;
- struct spa_hook registry_listener;
-
- pa_proplist *proplist;
- pa_mainloop_api *mainloop;
-
- int error;
- pa_context_state_t state;
-
- pa_context_notify_cb_t state_callback;
- void *state_userdata;
- pa_context_event_cb_t event_callback;
- void *event_userdata;
- pa_context_subscribe_cb_t subscribe_callback;
- void *subscribe_userdata;
- pa_subscription_mask_t subscribe_mask;
-
- struct spa_list globals;
-
- struct spa_list streams;
- struct spa_list operations;
- struct spa_list modules;
-
- int no_fail:1;
- int disconnect:1;
-
- int pending_seq;
-
- struct global *metadata;
- uint32_t default_sink;
- uint32_t default_source;
-};
-
-pa_stream *pa_context_find_stream(pa_context *c, uint32_t idx);
-struct global *pa_context_find_global(pa_context *c, uint32_t id);
-const char *pa_context_find_global_name(pa_context *c, uint32_t id);
-struct global *pa_context_find_global_by_name(pa_context *c, uint32_t mask, const char *name);
-struct global *pa_context_find_linked(pa_context *c, uint32_t id);
-
-struct pa_mem {
- struct spa_list link;
- void *data;
- size_t maxsize;
- size_t size;
- size_t offset;
- void *user_data;
-};
-
-struct pa_stream {
- struct spa_list link;
- int refcount;
-
- struct pw_stream *stream;
- struct spa_hook stream_listener;
-
- pa_context *context;
- pa_proplist *proplist;
-
- pa_stream_direction_t direction;
- pa_stream_state_t state;
- pa_stream_flags_t flags;
- bool disconnecting;
-
- pa_sample_spec sample_spec;
- pa_channel_map channel_map;
- uint8_t n_formats;
- pa_format_info *req_formats[PA_MAX_FORMATS];
- pa_format_info *format;
-
- uint32_t stream_index;
- struct global *global;
-
- pa_buffer_attr buffer_attr;
-
- uint32_t device_index;
- char *device_name;
-
- pa_timing_info timing_info;
- uint64_t ticks_base;
- size_t queued_bytes;
-
- uint32_t direct_on_input;
-
- unsigned int suspended:1;
- unsigned int corked:1;
- unsigned int timing_info_valid:1;
- unsigned int have_time:1;
-
- pa_stream_notify_cb_t state_callback;
- void *state_userdata;
- pa_stream_request_cb_t read_callback;
- void *read_userdata;
- pa_stream_request_cb_t write_callback;
- void *write_userdata;
- pa_stream_notify_cb_t overflow_callback;
- void *overflow_userdata;
- pa_stream_notify_cb_t underflow_callback;
- void *underflow_userdata;
- pa_stream_notify_cb_t latency_update_callback;
- void *latency_update_userdata;
- pa_stream_notify_cb_t moved_callback;
- void *moved_userdata;
- pa_stream_notify_cb_t suspended_callback;
- void *suspended_userdata;
- pa_stream_notify_cb_t started_callback;
- void *started_userdata;
- pa_stream_event_cb_t event_callback;
- void *event_userdata;
- pa_stream_notify_cb_t buffer_attr_callback;
- void *buffer_attr_userdata;
-
- size_t maxsize;
- size_t maxblock;
-
- struct pa_mem *mem; /* current mem for playback */
- struct spa_list free; /* free to fill */
- struct spa_list ready; /* ready for playback */
- size_t ready_bytes;
-
- struct pw_buffer *buffer; /* currently reading for capture */
-
- uint32_t n_channel_volumes;
- float channel_volumes[SPA_AUDIO_MAX_CHANNELS];
- bool mute;
- pa_operation *drain;
-};
-
-void pa_stream_set_state(pa_stream *s, pa_stream_state_t st);
-
-typedef void (*pa_operation_cb_t)(pa_operation *o, void *userdata);
-
-struct pa_operation
-{
- struct spa_list link;
-
- int refcount;
- pa_context *context;
- pa_stream *stream;
- unsigned int sync:1;
-
- pa_operation_state_t state;
-
- pa_operation_cb_t callback;
- void *userdata;
-
- pa_operation_notify_cb_t state_callback;
- void *state_userdata;
-};
-
-bool pa_mainloop_api_is_our_api(pa_mainloop_api *api);
-
-#define PA_TIMEVAL_RTCLOCK ((time_t) (1LU << 30))
-struct timeval* pa_rtclock_from_wallclock(struct timeval *tv);
-struct timeval* pa_rtclock_to_wallclock(struct timeval *tv);
-struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, bool rtclock);
-
-bool pa_endswith(const char *s, const char *sfx);
-
-pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, size_t userdata_size);
-void pa_operation_done(pa_operation *o);
-int pa_operation_sync(pa_operation *o);
-
-#define METADATA_DEFAULT_SINK "default.audio.sink"
-#define METADATA_DEFAULT_SOURCE "default.audio.source"
-#define METADATA_TARGET_NODE "target.node"
-
-int pa_metadata_update(struct global *global, uint32_t subject, const char *key,
- const char *type, const char *value);
-int pa_metadata_get(struct global *global, uint32_t subject, const char *key,
- const char **type, const char **value);
-
-void pw_channel_map_from_positions(pa_channel_map *map, uint32_t n_pos, const uint32_t *pos);
-void pw_channel_map_to_positions(const pa_channel_map *map, uint32_t *pos);
-
-int pa_format_parse_param(const struct spa_pod *param,
- pa_sample_spec *spec, pa_channel_map *map);
-const struct spa_pod *pa_format_build_param(struct spa_pod_builder *b,
- uint32_t id, pa_sample_spec *spec, pa_channel_map *map);
-
-pa_format_info* pa_format_info_from_param(const struct spa_pod *param);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __PIPEWIRE_PULSEAUDIO_INTERNAL_H__ */
diff --git a/pipewire-pulseaudio/src/introspect.c b/pipewire-pulseaudio/src/introspect.c
deleted file mode 100644
index c46c91b96..000000000
--- a/pipewire-pulseaudio/src/introspect.c
+++ /dev/null
@@ -1,2905 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include
-#include
-
-#include
-#include
-
-#include "internal.h"
-
-struct success_ack {
- pa_context_success_cb_t cb;
- int error;
- void *userdata;
- uint32_t idx;
-};
-
-static void on_success(pa_operation *o, void *userdata)
-{
- struct success_ack *d = userdata;
- pa_context *c = o->context;
- if (d->error != 0)
- pa_context_set_error(c, d->error);
- if (d->cb)
- d->cb(c, d->error ? 0 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-struct sink_data {
- pa_sink_info_cb_t cb;
- void *userdata;
- char *name;
- uint32_t idx;
-};
-
-static pa_sink_state_t node_state_to_sink(enum pw_node_state s)
-{
- switch(s) {
- case PW_NODE_STATE_ERROR:
- return PA_SINK_UNLINKED;
- case PW_NODE_STATE_CREATING:
- return PA_SINK_INIT;
- case PW_NODE_STATE_SUSPENDED:
- return PA_SINK_SUSPENDED;
- case PW_NODE_STATE_IDLE:
- return PA_SINK_IDLE;
- case PW_NODE_STATE_RUNNING:
- return PA_SINK_RUNNING;
- default:
- return PA_SINK_INVALID_STATE;
- }
-}
-
-static int has_profile(pa_card_profile_info2 **list, pa_card_profile_info2 *active)
-{
- for(;*list; list++) {
- if (*list == active)
- return 1;
- }
- return 0;
-}
-static int has_device(struct port_device *devices, uint32_t id)
-{
- uint32_t i;
-
- if (devices->devices == NULL || devices->n_devices == 0)
- return 1;
-
- for (i = 0; i < devices->n_devices; i++) {
- if (devices->devices[i] == id)
- return 1;
- }
- return 0;
-}
-
-static int sink_callback(pa_context *c, struct global *g, struct sink_data *d)
-{
- struct global *cg;
- struct pw_node_info *info = g->info;
- const char *str;
- uint32_t n, j;
- char monitor_name[1024];
- pa_sink_info i;
-
- spa_zero(i);
- if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_NODE_NAME)))
- i.name = str;
- else
- i.name = "unknown";
- pw_log_debug("sink %d %s monitor %d", g->id, i.name, g->node_info.monitor);
- i.index = g->id;
- if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_NODE_DESCRIPTION)))
- i.description = str;
- else
- i.description = "Unknown";
-
- i.sample_spec = g->node_info.sample_spec;
- if (g->node_info.n_channel_volumes)
- i.sample_spec.channels = g->node_info.n_channel_volumes;
- else
- i.sample_spec.channels = 2;
- if (i.sample_spec.channels == g->node_info.channel_map.channels)
- i.channel_map = g->node_info.channel_map;
- else
- pa_channel_map_init_extend(&i.channel_map,
- i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
- i.owner_module = g->id;
- i.volume.channels = i.sample_spec.channels;
- for (n = 0; n < i.volume.channels; n++)
- i.volume.values[n] = pa_sw_volume_from_linear(g->node_info.volume * g->node_info.channel_volumes[n]);;
- i.mute = g->node_info.mute;
- i.monitor_source = g->node_info.monitor;
- snprintf(monitor_name, sizeof(monitor_name)-1, "%s.monitor", i.name);
- i.monitor_source_name = monitor_name;
- i.latency = 0;
- i.driver = "PipeWire";
- i.flags = PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY |
- PA_SINK_DECIBEL_VOLUME;
- if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_DEVICE_API)))
- i.flags |= PA_SINK_HARDWARE;
- if (SPA_FLAG_IS_SET(g->node_info.flags, NODE_FLAG_HW_VOLUME))
- i.flags |= PA_SINK_HW_VOLUME_CTRL;
- if (SPA_FLAG_IS_SET(g->node_info.flags, NODE_FLAG_HW_MUTE))
- i.flags |= PA_SINK_HW_MUTE_CTRL;
- i.proplist = pa_proplist_new_dict(info->props);
- i.configured_latency = 0;
- i.base_volume = pa_sw_volume_from_linear(g->node_info.base_volume);
- i.n_volume_steps = g->node_info.volume_step * (PA_VOLUME_NORM+1);
- i.state = node_state_to_sink(info->state);
- i.card = g->node_info.device_id;
- i.n_ports = 0;
- i.ports = NULL;
- i.active_port = NULL;
- if ((cg = pa_context_find_global(c, i.card)) != NULL) {
- pa_sink_port_info *spi;
- pa_card_info *ci = &cg->card_info.info;
-
- spi = alloca(ci->n_ports * sizeof(pa_sink_port_info));
- i.ports = alloca((ci->n_ports + 1) * sizeof(pa_sink_port_info *));
-
- for (n = 0,j = 0; n < ci->n_ports; n++) {
- if (ci->ports[n]->direction != PA_DIRECTION_OUTPUT)
- continue;
- if (!has_profile(ci->ports[n]->profiles2, ci->active_profile2))
- continue;
- if (!has_device(&cg->card_info.port_devices[n], g->node_info.profile_device_id))
- continue;
-
- spa_zero(spi[j]);
- i.ports[j] = &spi[j];
- spi[j].name = ci->ports[n]->name;
- spi[j].description = ci->ports[n]->description;
- spi[j].priority = ci->ports[n]->priority;
- spi[j].available = ci->ports[n]->available;
- if (n == g->node_info.active_port)
- i.active_port = i.ports[j];
- j++;
- }
- i.n_ports = j;
- if (i.n_ports == 0)
- i.ports = NULL;
- else
- i.ports[j] = NULL;
- }
- if (i.active_port == NULL && i.n_ports > 0)
- i.active_port = i.ports[0];
- i.n_formats = pw_array_get_len(&g->node_info.formats, pa_format_info *);
- i.formats = g->node_info.formats.data;
- d->cb(c, &i, 0, d->userdata);
- pa_proplist_free(i.proplist);
- return 0;
-}
-
-static void sink_info(pa_operation *o, void *userdata)
-{
- struct sink_data *d = userdata;
- struct global *g;
- pa_context *c = o->context;
- int error = 0;
-
- pw_log_debug("%p name:%s idx:%u", c, d->name, d->idx);
-
- if (d->name) {
- g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_SINK, d->name);
- pa_xfree(d->name);
- } else {
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_SINK))
- g = NULL;
- }
-
- if (g) {
- error = sink_callback(c, g, d);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error)
- pa_context_set_error(c, error);
- d->cb(c, NULL, error ? -1 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct sink_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
- pw_log_debug("%p: name %s", c, name);
-
- o = pa_operation_new(c, NULL, sink_info, sizeof(struct sink_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- d->name = pa_xstrdup(name);
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_sink_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct sink_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("%p: index %u", c, idx);
-
- o = pa_operation_new(c, NULL, sink_info, sizeof(struct sink_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- d->idx = idx;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void sink_info_list(pa_operation *o, void *userdata)
-{
- struct sink_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
-
- spa_list_for_each(g, &c->globals, link) {
- if (!(g->mask & PA_SUBSCRIPTION_MASK_SINK))
- continue;
- sink_callback(c, g, d);
- }
- d->cb(c, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct sink_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p", c);
- o = pa_operation_new(c, NULL, sink_info_list, sizeof(struct sink_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static int set_stream_volume(pa_context *c, pa_stream *s, const pa_cvolume *volume, bool mute)
-{
- uint32_t i, n_channel_volumes;
- float channel_volumes[SPA_AUDIO_MAX_CHANNELS];
- float *vols;
-
- if (volume) {
- for (i = 0; i < volume->channels; i++)
- channel_volumes[i] = pa_sw_volume_to_linear(volume->values[i]);;
- vols = channel_volumes;
- n_channel_volumes = volume->channels;
- } else {
- vols = s->channel_volumes;
- n_channel_volumes = s->n_channel_volumes;
- }
-
- if (n_channel_volumes != s->n_channel_volumes ||
- !memcmp(s->channel_volumes, vols, n_channel_volumes * sizeof(float)) ||
- s->mute != mute) {
- float val = s->mute ? 1.0f : 0.0f;
- pw_stream_set_control(s->stream,
- SPA_PROP_mute, 1, &val,
- SPA_PROP_channelVolumes, n_channel_volumes, vols,
- 0);
- }
- return 0;
-}
-
-static int set_node_volume(pa_context *c, struct global *g, const pa_cvolume *volume, bool mute)
-{
- char buf[1024];
- struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
- uint32_t i, n_channel_volumes;
- float channel_volumes[SPA_AUDIO_MAX_CHANNELS];
- float *vols;
-
- if (volume) {
- for (i = 0; i < volume->channels; i++)
- channel_volumes[i] = pa_sw_volume_to_linear(volume->values[i]);
- vols = channel_volumes;
- n_channel_volumes = volume->channels;
-
- if (n_channel_volumes == g->node_info.n_channel_volumes &&
- memcmp(g->node_info.channel_volumes, vols, n_channel_volumes * sizeof(float)) == 0 &&
- mute == g->node_info.mute)
- return 0;
-
- memcpy(g->node_info.channel_volumes, vols, n_channel_volumes * sizeof(float));
- g->node_info.n_channel_volumes = n_channel_volumes;
- } else {
- n_channel_volumes = g->node_info.n_channel_volumes;
- vols = g->node_info.channel_volumes;
- if (mute == g->node_info.mute)
- return 0;
- }
- g->node_info.mute = mute;
- g->changed++;
-
- if (!SPA_FLAG_IS_SET(g->permissions, PW_PERM_W | PW_PERM_X))
- return PA_ERR_ACCESS;
-
- pw_log_debug("node %p: id:%u", g, g->id);
- pw_node_set_param((struct pw_node*)g->proxy,
- SPA_PARAM_Props, 0,
- spa_pod_builder_add_object(&b,
- SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
- SPA_PROP_mute, SPA_POD_Bool(mute),
- SPA_PROP_channelVolumes, SPA_POD_Array(sizeof(float),
- SPA_TYPE_Float,
- n_channel_volumes,
- vols)));
- return 0;
-}
-
-static int set_device_volume(pa_context *c, struct global *g, struct global *cg, uint32_t id,
- uint32_t device_id, const pa_cvolume *volume, bool mute)
-{
- char buf[1024];
- struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
- struct spa_pod_frame f[2];
- struct spa_pod *param;
- uint32_t i, n_channel_volumes;
- float channel_volumes[SPA_AUDIO_MAX_CHANNELS];
- float *vols;
-
- if (volume) {
- for (i = 0; i < volume->channels; i++)
- channel_volumes[i] = pa_sw_volume_to_linear(volume->values[i]);
- vols = channel_volumes;
- n_channel_volumes = volume->channels;
-
- if (n_channel_volumes == g->node_info.n_channel_volumes &&
- memcmp(g->node_info.channel_volumes, vols, n_channel_volumes * sizeof(float)) == 0 &&
- mute == g->node_info.mute)
- return 0;
-
- memcpy(g->node_info.channel_volumes, vols, n_channel_volumes * sizeof(float));
- g->node_info.n_channel_volumes = n_channel_volumes;
- } else {
- n_channel_volumes = g->node_info.n_channel_volumes;
- vols = g->node_info.channel_volumes;
- if (mute == g->node_info.mute)
- return 0;
- }
- g->node_info.mute = mute;
- g->changed++;
-
- if (!SPA_FLAG_IS_SET(cg->permissions, PW_PERM_W | PW_PERM_X))
- return PA_ERR_ACCESS;
-
- spa_pod_builder_push_object(&b, &f[0],
- SPA_TYPE_OBJECT_ParamRoute, SPA_PARAM_Route);
- spa_pod_builder_add(&b,
- SPA_PARAM_ROUTE_index, SPA_POD_Int(id),
- SPA_PARAM_ROUTE_device, SPA_POD_Int(device_id),
- 0);
- spa_pod_builder_prop(&b, SPA_PARAM_ROUTE_props, 0);
- spa_pod_builder_add_object(&b,
- SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
- SPA_PROP_mute, SPA_POD_Bool(mute),
- SPA_PROP_channelVolumes, SPA_POD_Array(sizeof(float),
- SPA_TYPE_Float,
- n_channel_volumes,
- vols));
- param = spa_pod_builder_pop(&b, &f[0]);
-
- pw_log_debug("device %p: id:%u", cg, cg->id);
- pw_device_set_param((struct pw_node*)cg->proxy,
- SPA_PARAM_Route, 0, param);
-
- return 0;
-}
-
-static int set_volume(pa_context *c, struct global *g, const pa_cvolume *volume, bool mute,
- uint32_t mask)
-{
- struct global *cg;
- uint32_t id = SPA_ID_INVALID, card_id, device_id;
- int res;
-
- card_id = g->node_info.device_id;
- device_id = g->node_info.profile_device_id;
-
- pw_log_debug("card:%u global:%u flags:%08x", card_id, g->id, g->node_info.flags);
-
- if (SPA_FLAG_IS_SET(g->node_info.flags, NODE_FLAG_DEVICE_VOLUME | NODE_FLAG_DEVICE_MUTE) &&
- (cg = pa_context_find_global(c, card_id)) != NULL) {
- id = cg->node_info.active_port;
- }
- if (id != SPA_ID_INVALID && device_id != SPA_ID_INVALID) {
- res = set_device_volume(c, g, cg, id, device_id, volume, mute);
- } else {
- res = set_node_volume(c, g, volume, mute);
- }
- return res;
-}
-
-struct volume_data {
- pa_context_success_cb_t cb;
- uint32_t mask;
- void *userdata;
- char *name;
- uint32_t idx;
- bool have_volume;
- pa_cvolume volume;
- int mute;
-};
-
-static void do_node_volume_mute(pa_operation *o, void *userdata)
-{
- struct volume_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error = 0;
-
- if (d->name) {
- g = pa_context_find_global_by_name(c, d->mask, d->name);
- pa_xfree(d->name);
- } else {
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & d->mask))
- g = NULL;
- }
- if (g) {
- error = set_volume(c, g,
- d->have_volume ? &d->volume : NULL,
- d->have_volume ? g->node_info.mute : d->mute,
- d->mask);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error != 0)
- pa_context_set_error(c, error);
- if (d->cb)
- d->cb(c, error ? 0 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct volume_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
-
- pw_log_debug("context %p: index %d", c, idx);
-
- o = pa_operation_new(c, NULL, do_node_volume_mute, sizeof(struct volume_data));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SINK;
- d->cb = cb;
- d->userdata = userdata;
- d->idx = idx;
- d->volume = *volume;
- d->have_volume = true;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct volume_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
-
- pw_log_debug("context %p: name %s", c, name);
-
- o = pa_operation_new(c, NULL, do_node_volume_mute, sizeof(struct volume_data));
- d = o->userdata;
- d->cb = cb;
- d->mask = PA_SUBSCRIPTION_MASK_SINK;
- d->userdata = userdata;
- d->name = pa_xstrdup(name);
- d->volume = *volume;
- d->have_volume = true;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct volume_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p: index %d", c, idx);
-
- o = pa_operation_new(c, NULL, do_node_volume_mute, sizeof(struct volume_data));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SINK;
- d->cb = cb;
- d->userdata = userdata;
- d->idx = idx;
- d->mute = mute;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct volume_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
- pw_log_debug("context %p: name %s", c, name);
-
- o = pa_operation_new(c, NULL, do_node_volume_mute, sizeof(struct volume_data));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SINK;
- d->cb = cb;
- d->userdata = userdata;
- d->name = pa_xstrdup(name);
- d->mute = mute;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_suspend_sink_by_name(pa_context *c, const char *sink_name, int suspend, pa_context_success_cb_t cb, void* userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: name:%s suspend:%d", c, sink_name, suspend);
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: index:%u suspend:%d", c, idx, suspend);
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static int set_device_route(pa_context *c, struct global *g, const char *port, enum spa_direction direction)
-{
- struct global *cg;
- struct param *p;
- uint32_t id = SPA_ID_INVALID, card_id, device_id;
- char buf[1024];
- struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
-
- card_id = g->node_info.device_id;
- device_id = g->node_info.profile_device_id;
-
- pw_log_info("port \"%s\": card:%u device:%u global:%u", port, card_id, device_id, g->id);
-
- if ((cg = pa_context_find_global(c, card_id)) == NULL || device_id == SPA_ID_INVALID)
- return PA_ERR_NOENTITY;
-
- spa_list_for_each(p, &cg->card_info.ports, link) {
- uint32_t test_id;
- const char *name;
- enum spa_direction test_direction;
-
- if (spa_pod_parse_object(p->param,
- SPA_TYPE_OBJECT_ParamRoute, NULL,
- SPA_PARAM_ROUTE_index, SPA_POD_Int(&test_id),
- SPA_PARAM_ROUTE_direction, SPA_POD_Id(&test_direction),
- SPA_PARAM_ROUTE_name, SPA_POD_String(&name)) < 0) {
- pw_log_warn("device %d: can't parse route", g->id);
- continue;
- }
- pw_log_debug("port id:%u name:\"%s\" dir:%d", test_id, name, test_direction);
- if (test_direction != direction)
- continue;
- if (strcmp(name, port) == 0) {
- id = test_id;
- break;
- }
- }
- pw_log_debug("port %s, id %u", port, id);
- if (id == SPA_ID_INVALID)
- return PA_ERR_NOENTITY;
-
- if (!SPA_FLAG_IS_SET(cg->permissions, PW_PERM_W | PW_PERM_X))
- return PA_ERR_ACCESS;
-
- pw_device_set_param((struct pw_device*)cg->proxy,
- SPA_PARAM_Route, 0,
- spa_pod_builder_add_object(&b,
- SPA_TYPE_OBJECT_ParamRoute, SPA_PARAM_Route,
- SPA_PARAM_ROUTE_index, SPA_POD_Int(id),
- SPA_PARAM_ROUTE_direction, SPA_POD_Id(direction),
- SPA_PARAM_ROUTE_device, SPA_POD_Int(device_id)));
-
- return 0;
-}
-
-struct device_route {
- uint32_t mask;
- pa_context_success_cb_t cb;
- void *userdata;
- char *name;
- uint32_t idx;
- char *port;
- enum spa_direction direction;
-};
-
-static void do_device_route(pa_operation *o, void *userdata)
-{
- struct device_route *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error;
-
- pw_log_debug("%p", c);
-
- if (d->name) {
- g = pa_context_find_global_by_name(c, d->mask, d->name);
- pa_xfree(d->name);
- } else {
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & d->mask))
- g = NULL;
- }
- if (g) {
- error = set_device_route(c, g, d->port, d->direction);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error != 0)
- pa_context_set_error(c, error);
- if (d->cb)
- d->cb(c, error != 0 ? 0 : 1, d->userdata);
- pa_xfree(d->port);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_sink_port_by_index(pa_context *c, uint32_t idx, const char*port, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct device_route *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p: index:%u port:%s", c, idx, port);
- o = pa_operation_new(c, NULL, do_device_route, sizeof(struct device_route));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SINK;
- d->cb = cb;
- d->userdata = userdata;
- d->idx = idx;
- d->port = pa_xstrdup(port);
- d->direction = SPA_DIRECTION_OUTPUT;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_sink_port_by_name(pa_context *c, const char*name, const char*port, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct device_route *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
- pw_log_debug("context %p: name:%s port:%s", c, name, port);
- o = pa_operation_new(c, NULL, do_device_route, sizeof(struct device_route));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SINK;
- d->cb = cb;
- d->userdata = userdata;
- d->name = pa_xstrdup(name);
- d->port = pa_xstrdup(port);
- d->direction = SPA_DIRECTION_OUTPUT;
- pa_operation_sync(o);
- return o;
-}
-
-
-struct source_data {
- pa_source_info_cb_t cb;
- void *userdata;
- char *name;
- uint32_t idx;
-};
-
-static pa_source_state_t node_state_to_source(enum pw_node_state s)
-{
- switch(s) {
- case PW_NODE_STATE_ERROR:
- return PA_SOURCE_UNLINKED;
- case PW_NODE_STATE_CREATING:
- return PA_SOURCE_INIT;
- case PW_NODE_STATE_SUSPENDED:
- return PA_SOURCE_SUSPENDED;
- case PW_NODE_STATE_IDLE:
- return PA_SOURCE_IDLE;
- case PW_NODE_STATE_RUNNING:
- return PA_SOURCE_RUNNING;
- default:
- return PA_SOURCE_INVALID_STATE;
- }
-}
-static int source_callback(pa_context *c, struct global *g, struct source_data *d)
-{
- struct global *cg;
- struct pw_node_info *info = g->info;
- const char *str;
- uint32_t n, j;
- pa_source_info i;
- enum pa_source_flags flags;
- bool monitor;
-
- flags = PA_SOURCE_LATENCY | PA_SOURCE_DYNAMIC_LATENCY |
- PA_SOURCE_DECIBEL_VOLUME;
-
- monitor = (g->mask & PA_SUBSCRIPTION_MASK_SINK) != 0;
-
- spa_zero(i);
-
- i.proplist = pa_proplist_new_dict(info->props);
-
- if (monitor) {
- if ((str = spa_dict_lookup(info->props, PW_KEY_NODE_NAME)))
- pa_proplist_setf(i.proplist, PW_KEY_NODE_NAME, "%s.monitor", str);
- if ((str = spa_dict_lookup(info->props, PW_KEY_NODE_DESCRIPTION)))
- pa_proplist_setf(i.proplist, PW_KEY_NODE_DESCRIPTION, "Monitor of %s", str);
- pa_proplist_setf(i.proplist, PW_KEY_DEVICE_CLASS, "monitor");
- }
-
- if ((str = pa_proplist_gets(i.proplist, PW_KEY_NODE_NAME)))
- i.name = str;
- else
- i.name = "unknown";
-
- pw_log_debug("source %d %s monitor:%d", g->id, i.name, monitor);
-
- if ((str = pa_proplist_gets(i.proplist, PW_KEY_NODE_DESCRIPTION)))
- i.description = str;
- else
- i.description = "unknown";
- i.sample_spec = g->node_info.sample_spec;
- if (g->node_info.n_channel_volumes)
- i.sample_spec.channels = g->node_info.n_channel_volumes;
- else
- i.sample_spec.channels = 2;
- if (i.sample_spec.channels == g->node_info.channel_map.channels)
- i.channel_map = g->node_info.channel_map;
- else
- pa_channel_map_init_extend(&i.channel_map,
- i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
- i.owner_module = g->id;
- i.volume.channels = i.sample_spec.channels;
- for (n = 0; n < i.volume.channels; n++)
- i.volume.values[n] = pa_sw_volume_from_linear(g->node_info.volume * g->node_info.channel_volumes[n]);;
- i.mute = g->node_info.mute;
- if (monitor) {
- i.index = g->node_info.monitor;
- i.monitor_of_sink = g->id;
- i.monitor_of_sink_name = pa_context_find_global_name(c, g->id);
- } else {
- i.index = g->id;
- i.monitor_of_sink = PA_INVALID_INDEX;
- i.monitor_of_sink_name = NULL;
- if (info->props && (str = spa_dict_lookup(info->props, PW_KEY_DEVICE_API)))
- flags |= PA_SOURCE_HARDWARE;
- if (SPA_FLAG_IS_SET(g->node_info.flags, NODE_FLAG_HW_VOLUME))
- flags |= PA_SINK_HW_VOLUME_CTRL;
- if (SPA_FLAG_IS_SET(g->node_info.flags, NODE_FLAG_HW_MUTE))
- flags |= PA_SINK_HW_MUTE_CTRL;
- }
- i.latency = 0;
- i.driver = "PipeWire";
- i.flags = flags;
- i.configured_latency = 0;
- i.base_volume = pa_sw_volume_from_linear(g->node_info.base_volume);
- i.n_volume_steps = g->node_info.volume_step * (PA_VOLUME_NORM+1);
- i.state = node_state_to_source(info->state);
- i.card = g->node_info.device_id;
- i.n_ports = 0;
- i.ports = NULL;
- i.active_port = NULL;
- if (!monitor && (cg = pa_context_find_global(c, i.card)) != NULL) {
- pa_source_port_info *spi;
- pa_card_info *ci = &cg->card_info.info;
-
- spi = alloca(ci->n_ports * sizeof(pa_source_port_info));
- i.ports = alloca((ci->n_ports + 1) * sizeof(pa_source_port_info *));
-
- for (n = 0,j = 0; n < ci->n_ports; n++) {
- if (ci->ports[n]->direction != PA_DIRECTION_INPUT)
- continue;
- if (!has_profile(ci->ports[n]->profiles2, ci->active_profile2))
- continue;
- if (!has_device(&cg->card_info.port_devices[n], g->node_info.profile_device_id))
- continue;
-
- spa_zero(spi[j]);
- i.ports[j] = &spi[j];
- spi[j].name = ci->ports[n]->name;
- spi[j].description = ci->ports[n]->description;
- spi[j].priority = ci->ports[n]->priority;
- spi[j].available = ci->ports[n]->available;
- if (n == g->node_info.active_port)
- i.active_port = i.ports[j];
- j++;
- }
- i.n_ports = j;
- if (i.n_ports == 0)
- i.ports = NULL;
- else
- i.ports[j] = NULL;
- }
- if (i.active_port == NULL && i.n_ports > 0)
- i.active_port = i.ports[0];
- i.n_formats = pw_array_get_len(&g->node_info.formats, pa_format_info *);
- i.formats = g->node_info.formats.data;
- d->cb(c, &i, 0, d->userdata);
- pa_proplist_free(i.proplist);
- return 0;
-}
-
-static void source_info(pa_operation *o, void *userdata)
-{
- struct source_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error;
-
- if (d->name) {
- g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_SOURCE, d->name);
- pa_xfree(d->name);
- } else {
- if (((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE)) &&
- (((g = pa_context_find_global(c, d->idx & PA_IDX_MASK_MONITOR)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE))))
- g = NULL;
- }
-
- if (g) {
- error = source_callback(c, g, d);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error)
- pa_context_set_error(c, error);
- d->cb(c, NULL, error ? -1 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct source_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
- pw_log_debug("context %p: name:%s", c, name);
- o = pa_operation_new(c, NULL, source_info, sizeof(struct source_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- d->name = pa_xstrdup(name);
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, pa_source_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct source_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p: index %d", c, idx);
-
- o = pa_operation_new(c, NULL, source_info, sizeof(struct source_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- d->idx = idx;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void source_info_list(pa_operation *o, void *userdata)
-{
- struct source_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
-
- spa_list_for_each(g, &c->globals, link) {
- if (!(g->mask & PA_SUBSCRIPTION_MASK_SOURCE))
- continue;
- source_callback(c, g, d);
- }
- d->cb(c, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct source_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p", c);
- o = pa_operation_new(c, NULL, source_info_list, sizeof(struct source_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct volume_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
-
- pw_log_debug("context %p: index %d", c, idx);
-
- o = pa_operation_new(c, NULL, do_node_volume_mute, sizeof(struct volume_data));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE;
- d->cb = cb;
- d->userdata = userdata;
- d->idx = idx;
- d->volume = *volume;
- d->have_volume = true;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct volume_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
-
- pw_log_debug("context %p: name %s", c, name);
-
- o = pa_operation_new(c, NULL, do_node_volume_mute, sizeof(struct volume_data));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE;
- d->cb = cb;
- d->userdata = userdata;
- d->name = pa_xstrdup(name);
- d->volume = *volume;
- d->have_volume = true;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct volume_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p: index %d", c, idx);
-
- o = pa_operation_new(c, NULL, do_node_volume_mute, sizeof(struct volume_data));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE;
- d->cb = cb;
- d->userdata = userdata;
- d->idx = idx;
- d->mute = mute;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct volume_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
- pw_log_debug("context %p: name %s", c, name);
-
- o = pa_operation_new(c, NULL, do_node_volume_mute, sizeof(struct volume_data));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE;
- d->cb = cb;
- d->userdata = userdata;
- d->name = pa_xstrdup(name);
- d->mute = mute;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_suspend_source_by_name(pa_context *c, const char *source_name, int suspend, pa_context_success_cb_t cb, void* userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: name:%s", c, source_name);
-
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void* userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: index:%u", c, idx);
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_source_port_by_index(pa_context *c, uint32_t idx, const char*port, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct device_route *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p: idx %d port:%s", c, idx, port);
-
- o = pa_operation_new(c, NULL, do_device_route, sizeof(struct device_route));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE;
- d->cb = cb;
- d->userdata = userdata;
- d->idx = idx;
- d->port = pa_xstrdup(port);
- d->direction = SPA_DIRECTION_INPUT;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_source_port_by_name(pa_context *c, const char*name, const char*port, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct device_route *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
- pw_log_debug("context %p: name %s port:%s", c, name, port);
-
- o = pa_operation_new(c, NULL, do_device_route, sizeof(struct device_route));
- d = o->userdata;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE;
- d->cb = cb;
- d->userdata = userdata;
- d->name = pa_xstrdup(name);
- d->port = pa_xstrdup(port);
- d->direction = SPA_DIRECTION_INPUT;
- pa_operation_sync(o);
- return o;
-}
-
-struct server_data {
- pa_server_info_cb_t cb;
- void *userdata;
- struct global *global;
-};
-
-static const char *get_default_name(pa_context *c, uint32_t mask)
-{
- struct global *g;
- const char *str;
- uint32_t id = SPA_ID_INVALID;
-
-
- if (c->metadata) {
- if (mask & PA_SUBSCRIPTION_MASK_SINK)
- id = c->default_sink;
- else if (mask & PA_SUBSCRIPTION_MASK_SOURCE)
- id = c->default_source;
- else
- return NULL;
- }
- spa_list_for_each(g, &c->globals, link) {
- if ((g->mask & mask) != mask)
- continue;
- if (g->props != NULL &&
- (str = pw_properties_get(g->props, PW_KEY_NODE_NAME)) != NULL &&
- (id == SPA_ID_INVALID || id == g->id))
- return str;
- }
- return "unknown";
-}
-
-static void server_callback(struct server_data *d, pa_context *c)
-{
- const struct pw_core_info *info = c->core_info;
- const char *str;
- pa_server_info i;
- char name[1024];
-
- snprintf(name, sizeof(name)-1, "pulseaudio (on PipeWire %s)", info->version);
-
- spa_zero(i);
- i.user_name = info->user_name;
- i.host_name = info->host_name;
- i.server_version = pa_get_headers_version();
- i.server_name = name;
- i.sample_spec.format = PA_SAMPLE_FLOAT32NE;
- if (info->props && (str = spa_dict_lookup(info->props, "default.clock.rate")) != NULL)
- i.sample_spec.rate = atoi(str);
- else
- i.sample_spec.rate = 44100;
- i.sample_spec.channels = 2;
- i.default_sink_name = get_default_name(c, PA_SUBSCRIPTION_MASK_SINK);
- i.default_source_name = get_default_name(c, PA_SUBSCRIPTION_MASK_SOURCE);
- i.cookie = info->cookie;
- pa_channel_map_init_extend(&i.channel_map, i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
- d->cb(c, &i, d->userdata);
-}
-
-static void server_info(pa_operation *o, void *userdata)
-{
- struct server_data *d = userdata;
- server_callback(d, o->context);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct server_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p", c);
- o = pa_operation_new(c, NULL, server_info, sizeof(struct server_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct module_data {
- uint32_t idx;
- pa_module_info_cb_t cb;
- void *userdata;
-};
-
-static int module_callback(pa_context *c, struct module_data *d, struct global *g)
-{
- d->cb(c, &g->module_info.info, 0, d->userdata);
- return 0;
-}
-
-static void module_info(pa_operation *o, void *userdata)
-{
- struct module_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error;
-
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_MODULE))
- g = NULL;
-
- if (g) {
- error = module_callback(c, d, g);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error)
- pa_context_set_error(c, error);
- d->cb(c, NULL, error ? -1 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct module_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p index:%u", c, idx);
- o = pa_operation_new(c, NULL, module_info, sizeof(struct module_data));
- d = o->userdata;
- d->idx = idx;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void module_info_list(pa_operation *o, void *userdata)
-{
- struct module_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
-
- spa_list_for_each(g, &c->globals, link) {
- if (!(g->mask & PA_SUBSCRIPTION_MASK_MODULE))
- continue;
- module_callback(c, d, g);
- }
- d->cb(c, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct module_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p", c);
- o = pa_operation_new(c, NULL, module_info_list, sizeof(struct module_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct load_module {
- pa_context_index_cb_t cb;
- int error;
- void *userdata;
- uint32_t idx;
- struct pw_properties *props;
- struct pw_proxy *proxy;
- struct spa_hook listener;
-};
-
-static struct module_info *find_module(pa_context *c, uint32_t idx)
-{
- struct module_info *m;
- spa_list_for_each(m, &c->modules, link) {
- if (m->id == idx)
- return m;
- }
- return NULL;
-}
-
-static void on_load_module(pa_operation *o, void *userdata)
-{
- struct load_module *d = userdata;
- pa_context *c = o->context;
- if (d->error != 0)
- pa_context_set_error(c, d->error);
- if (d->cb)
- d->cb(c, d->idx, d->userdata);
- if (d->props)
- pw_properties_free(d->props);
- if (d->proxy)
- spa_hook_remove(&d->listener);
- pa_operation_done(o);
-}
-
-static void module_proxy_removed(void *data)
-{
- struct module_info *m = data;
- pw_proxy_destroy(m->proxy);
-}
-
-static void module_proxy_destroy(void *data)
-{
- struct module_info *m = data;
- spa_hook_remove(&m->listener);
- spa_list_remove(&m->link);
- free(m);
-}
-
-static void module_proxy_bound(void *data, uint32_t global_id)
-{
- struct module_info *m;
- pa_operation *o = data;
- pa_context *c = o->context;
- struct load_module *d = o->userdata;
- static const struct pw_proxy_events proxy_events = {
- .removed = module_proxy_removed,
- .destroy = module_proxy_destroy,
- };
- d->idx = global_id;
-
- m = calloc(1, sizeof(struct module_info));
- m->id = global_id;
- m->proxy = d->proxy;
- pw_proxy_add_listener(m->proxy, &m->listener, &proxy_events, m);
- spa_list_append(&c->modules, &m->link);
- on_load_module(o, d);
-}
-
-static void module_proxy_error(void *data, int seq, int res, const char *message)
-{
- pa_operation *o = data;
- struct load_module *d = o->userdata;
- d->error = res;
- d->idx = PA_INVALID_INDEX;
- pw_proxy_destroy(d->proxy);
- on_load_module(o, d);
-}
-
-static int load_null_sink_module(pa_operation *o)
-{
- struct load_module *d = o->userdata;
- pa_context *c = o->context;
- static const struct pw_proxy_events proxy_events = {
- .bound = module_proxy_bound,
- .error = module_proxy_error,
- };
-
- if (d->proxy != NULL)
- return -EBUSY;
-
- d->proxy = pw_core_create_object(c->core,
- "adapter",
- PW_TYPE_INTERFACE_Node,
- PW_VERSION_NODE,
- d->props ? &d->props->dict : NULL, 0);
- if (d->proxy == NULL)
- return -errno;
-
- pw_proxy_add_listener(d->proxy, &d->listener, &proxy_events, o);
- return 0;
-}
-
-static void add_props(struct pw_properties *props, const char *str)
-{
- char *s = strdup(str), *p = s, *e, f;
- const char *k, *v;
-
- while (*p) {
- e = strchr(p, '=');
- if (e == NULL)
- break;
- *e = '\0';
- k = p;
- p = e+1;
-
- if (*p == '\"') {
- p++;
- f = '\"';
- } else {
- f = ' ';
- }
- e = strchr(p, f);
- if (e == NULL)
- break;
- *e = '\0';
- v = p;
- p = e + 1;
- pw_properties_set(props, k, v);
- }
- free(s);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct load_module *d;
- int error = PA_ERR_NOTIMPLEMENTED;;
- struct pw_properties *props = NULL;
- const char *str;
- bool sync = true;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(name != NULL);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: name:%s arg:%s", c, name, argument);
-
- o = pa_operation_new(c, NULL, on_load_module, sizeof(struct load_module));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- d->idx = PA_INVALID_INDEX;
-
- if (strcmp(name, "module-null-sink") == 0) {
- props = pw_properties_new_string(argument);
- if (props == NULL) {
- error = PA_ERR_INVALID;
- goto done;
- }
- if ((str = pw_properties_get(props, "sink_name")) != NULL) {
- pw_properties_set(props, "node.name", str);
- pw_properties_set(props, "sink_name", NULL);
- } else {
- pw_properties_set(props, "node.name", "null");
- }
- if ((str = pw_properties_get(props, "sink_properties")) != NULL) {
- add_props(props, str);
- pw_properties_set(props, "sink_properties", NULL);
- }
- if ((str = pw_properties_get(props, "device.description")) != NULL) {
- pw_properties_set(props, "node.description", str);
- pw_properties_set(props, "device.description", NULL);
- }
- pw_properties_set(props, "factory.name", "support.null-audio-sink");
-
- d->props = props;
- error = load_null_sink_module(o);
- sync = error < 0;
- }
-done:
- d->error = error;
- if (sync)
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
- struct module_info *m;
- int error;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: %u", c, idx);
- if ((m = find_module(c, idx)) != NULL) {
- pw_proxy_destroy(m->proxy);
- error = 0;
- } else {
- error = PA_ERR_NOENTITY;
- }
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- d->error = error;
- d->idx = idx;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct client_data {
- uint32_t idx;
- pa_client_info_cb_t cb;
- void *userdata;
-};
-
-static int client_callback(pa_context *c, struct client_data *d, struct global *g)
-{
- d->cb(c, &g->client_info.info, 0, d->userdata);
- return 0;
-}
-
-static void client_info(pa_operation *o, void *userdata)
-{
- struct client_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error;
-
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_CLIENT))
- g = NULL;
-
- if (g) {
- error = client_callback(c, d, g);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error)
- pa_context_set_error(c, error);
- d->cb(c, NULL, error ? -1 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct client_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p: index:%u", c, idx);
- o = pa_operation_new(c, NULL, client_info, sizeof(struct client_data));
- d = o->userdata;
- d->idx = idx;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void client_info_list(pa_operation *o, void *userdata)
-{
- struct client_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
-
- spa_list_for_each(g, &c->globals, link) {
- if (!(g->mask & PA_SUBSCRIPTION_MASK_CLIENT))
- continue;
- client_callback(c, d, g);
- }
- d->cb(c, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct client_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p", c);
- o = pa_operation_new(c, NULL, client_info_list, sizeof(struct client_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct kill_client {
- uint32_t idx;
- pa_context_success_cb_t cb;
- void *userdata;
-};
-
-static void do_kill_client(pa_operation *o, void *userdata)
-{
- struct kill_client *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error = 0;
-
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_CLIENT))
- g = NULL;
-
- if (g) {
- pw_registry_destroy(c->registry, g->id);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error != 0)
- pa_context_set_error(c, error);
- if (d->cb)
- d->cb(c, error ? 0 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct kill_client *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p: index:%u", c, idx);
- o = pa_operation_new(c, NULL, do_kill_client, sizeof(struct kill_client));
- d = o->userdata;
- d->idx = idx;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct card_data {
- pa_card_info_cb_t cb;
- pa_context_success_cb_t success_cb;
- char *name;
- uint32_t idx;
- void *userdata;
- char *profile;
-};
-
-static int card_callback(pa_context *c, struct card_data *d, struct global *g)
-{
- pa_card_info *i = &g->card_info.info;
- d->cb(c, i, 0, d->userdata);
- return 0;
-}
-
-static void card_info(pa_operation *o, void *userdata)
-{
- struct card_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error;
-
- if (d->name) {
- g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_CARD, d->name);
- pa_xfree(d->name);
- } else if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_CARD))
- g = NULL;
-
- if (g) {
- error = card_callback(c, d, g);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error != 0)
- pa_context_set_error(c, error);
- if (d->cb)
- d->cb(c, NULL, error ? -1 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_card_info_by_index(pa_context *c, uint32_t idx, pa_card_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct card_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p: index:%u", c, idx);
- o = pa_operation_new(c, NULL, card_info, sizeof(struct card_data));
- d = o->userdata;
- d->idx = idx;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char *name, pa_card_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct card_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
- pw_log_debug("context %p: name:%s", c, name);
- o = pa_operation_new(c, NULL, card_info, sizeof(struct card_data));
- d = o->userdata;
- d->name = pa_xstrdup(name);
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
- return o;
-}
-
-static void card_info_list(pa_operation *o, void *userdata)
-{
- struct card_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
-
- spa_list_for_each(g, &c->globals, link) {
- if (!(g->mask & PA_SUBSCRIPTION_MASK_CARD))
- continue;
- card_callback(c, d, g);
- }
- d->cb(c, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_card_info_list(pa_context *c, pa_card_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct card_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p", c);
- o = pa_operation_new(c, NULL, card_info_list, sizeof(struct card_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void card_profile(pa_operation *o, void *userdata)
-{
- struct card_data *d = userdata;
- struct global *g;
- pa_context *c = o->context;
- int error = 0;
- uint32_t id = SPA_ID_INVALID;
- char buf[1024];
- struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
- struct param *p;
-
- if (d->name) {
- g = pa_context_find_global_by_name(c, PA_SUBSCRIPTION_MASK_CARD, d->name);
- pa_xfree(d->name);
- } else if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_CARD))
- g = NULL;
-
- if (g == NULL) {
- error = PA_ERR_NOENTITY;
- goto done;
- }
-
- spa_list_for_each(p, &g->card_info.profiles, link) {
- uint32_t test_id;
- const char *name;
-
- if (spa_pod_parse_object(p->param,
- SPA_TYPE_OBJECT_ParamProfile, NULL,
- SPA_PARAM_PROFILE_index, SPA_POD_Int(&test_id),
- SPA_PARAM_PROFILE_name, SPA_POD_String(&name)) < 0) {
- pw_log_warn("device %d: can't parse profile", g->id);
- continue;
- }
- if (strcmp(name, d->profile) == 0) {
- id = test_id;
- break;
- }
- }
- if (id == SPA_ID_INVALID) {
- error = PA_ERR_NOENTITY;
- goto done;
- }
-
- if (!SPA_FLAG_IS_SET(g->permissions, PW_PERM_W | PW_PERM_X)) {
- error = PA_ERR_ACCESS;
- goto done;
- }
-
- pw_device_set_param((struct pw_device*)g->proxy,
- SPA_PARAM_Profile, 0,
- spa_pod_builder_add_object(&b,
- SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
- SPA_PARAM_PROFILE_index, SPA_POD_Int(id)));
-done:
- if (error)
- pa_context_set_error(c, error);
- if (d->success_cb)
- d->success_cb(c, error ? 0 : 1, d->userdata);
- free(d->profile);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_card_profile_by_index(pa_context *c, uint32_t idx, const char*profile, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct card_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("%p: index:%u profile:%s", c, idx, profile);
- o = pa_operation_new(c, NULL, card_profile, sizeof(struct card_data));
- d = o->userdata;
- d->idx = idx;
- d->success_cb = cb;
- d->userdata = userdata;
- d->profile = strdup(profile);
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_card_profile_by_name(pa_context *c, const char*name, const char*profile, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct card_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
- pw_log_debug("%p: name:%s profile:%s", c, name, profile);
- o = pa_operation_new(c, NULL, card_profile, sizeof(struct card_data));
- d = o->userdata;
- d->name = pa_xstrdup(name);
- d->success_cb = cb;
- d->userdata = userdata;
- d->profile = strdup(profile);
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_port_latency_offset(pa_context *c, const char *card_name, const char *port_name, int64_t offset, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p: card_name:%s port_name:%s offset:%"PRIi64, c, card_name, port_name, offset);
- o = pa_operation_new(c, NULL, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct sink_input_data {
- pa_sink_input_info_cb_t cb;
- uint32_t idx;
- void *userdata;
-};
-
-static int sink_input_callback(pa_context *c, struct sink_input_data *d, struct global *g)
-{
- struct global *cl;
- struct pw_node_info *info = g->info;
- const char *name = NULL;
- uint32_t n;
- pa_sink_input_info i;
- pa_format_info ii[1];
- pa_stream *s;
-
- if (info == NULL)
- return PA_ERR_INVALID;
-
- s = pa_context_find_stream(c, g->id);
-
- if (info->props) {
- if ((name = spa_dict_lookup(info->props, PW_KEY_MEDIA_NAME)) == NULL &&
- (name = spa_dict_lookup(info->props, PW_KEY_APP_NAME)) == NULL &&
- (name = spa_dict_lookup(info->props, PW_KEY_NODE_NAME)) == NULL)
- name = NULL;
- }
- if (name == NULL)
- name = "unknown";
-
- cl = pa_context_find_global(c, g->node_info.client_id);
-
- spa_zero(i);
- i.index = g->id;
- i.name = name;
- i.owner_module = g->id;
- i.client = g->node_info.client_id;
- if (s)
- i.sink = s->device_index;
- else
- i.sink = g->node_info.device_index;
-
- if (s && s->sample_spec.channels > 0) {
- i.sample_spec = s->sample_spec;
- if (s->channel_map.channels == s->sample_spec.channels)
- i.channel_map = s->channel_map;
- else
- pa_channel_map_init_extend(&i.channel_map,
- i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
- i.format = s->format;
- }
- else {
- i.sample_spec = g->node_info.sample_spec;
- if (g->node_info.n_channel_volumes)
- i.sample_spec.channels = g->node_info.n_channel_volumes;
- else
- i.sample_spec.channels = 2;
- if (i.sample_spec.channels == g->node_info.channel_map.channels)
- i.channel_map = g->node_info.channel_map;
- else
- pa_channel_map_init_extend(&i.channel_map,
- i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
- ii[0].encoding = PA_ENCODING_PCM;
- ii[0].plist = pa_proplist_new();
- i.format = ii;
- }
- pa_cvolume_init(&i.volume);
- i.volume.channels = i.sample_spec.channels;
- for (n = 0; n < i.volume.channels; n++)
- i.volume.values[n] = pa_sw_volume_from_linear(g->node_info.volume * g->node_info.channel_volumes[n]);
-
- i.mute = g->node_info.mute;
- i.buffer_usec = 0;
- i.sink_usec = 0;
- i.resample_method = "PipeWire resampler";
- i.driver = "PipeWire";
- i.proplist = pa_proplist_new_dict(info->props);
- if (cl && cl->client_info.info.proplist)
- pa_proplist_update(i.proplist, PA_UPDATE_MERGE, cl->client_info.info.proplist);
- i.corked = false;
- i.has_volume = true;
- i.volume_writable = true;
-
- pw_log_debug("context %p: sink info for %d sink:%d", c, i.index, i.sink);
-
- d->cb(c, &i, 0, d->userdata);
-
- pa_proplist_free(i.proplist);
- return 0;
-}
-
-static void sink_input_info(pa_operation *o, void *userdata)
-{
- struct sink_input_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error;
-
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_SINK_INPUT))
- g = NULL;
-
- if (g) {
- error = sink_input_callback(c, d, g);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error)
- pa_context_set_error(c, error);
- d->cb(c, NULL, error ? -1 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct sink_input_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("context %p: info for %d", c, idx);
- o = pa_operation_new(c, NULL, sink_input_info, sizeof(struct sink_input_data));
- d = o->userdata;
- d->idx = idx;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void sink_input_info_list(pa_operation *o, void *userdata)
-{
- struct sink_input_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
-
- spa_list_for_each(g, &c->globals, link) {
- if (!(g->mask & PA_SUBSCRIPTION_MASK_SINK_INPUT))
- continue;
- sink_input_callback(c, d, g);
- }
- d->cb(c, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_sink_input_info_list(pa_context *c, pa_sink_input_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct sink_input_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p", c);
- o = pa_operation_new(c, NULL, sink_input_info_list, sizeof(struct sink_input_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct target_node {
- uint32_t idx;
- uint32_t mask;
- uint32_t target_idx;
- uint32_t target_mask;
- char *target_name;
- pa_context_success_cb_t cb;
- void *userdata;
- const char *key;
-};
-
-static void do_target_node(pa_operation *o, void *userdata)
-{
- struct target_node *d = userdata;
- pa_context *c = o->context;
- struct global *g, *t;
- int error = 0;
-
- pw_log_debug("%p", c);
-
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & d->mask)) {
- error = PA_ERR_NOENTITY;
- goto done;
- }
-
- if (d->target_name) {
- t = pa_context_find_global_by_name(c, d->target_mask, d->target_name);
- } else {
- if ((t = pa_context_find_global(c, d->target_idx)) == NULL ||
- !(t->mask & d->target_mask))
- t = NULL;
- }
- if (t == NULL) {
- error = PA_ERR_NOENTITY;
- } else if (!SPA_FLAG_IS_SET(g->permissions, PW_PERM_M) ||
- (c->metadata && !SPA_FLAG_IS_SET(c->metadata->permissions, PW_PERM_W|PW_PERM_X))) {
- error = PA_ERR_ACCESS;
- } else if (c->metadata) {
- char buf[16];
- snprintf(buf, sizeof(buf), "%d", t->id);
- pw_metadata_set_property(c->metadata->proxy,
- g->id, d->key, SPA_TYPE_INFO_BASE "Id", buf);
- } else {
- error = PA_ERR_NOTIMPLEMENTED;
- }
-done:
- if (error != 0)
- pa_context_set_error(c, error);
- if (d->cb)
- d->cb(c, error != 0 ? 0 : 1, d->userdata);
- pa_xfree(d->target_name);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, const char *sink_name, pa_context_success_cb_t cb, void* userdata)
-{
- pa_operation *o;
- struct target_node *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p: index:%u name:%s", c, idx, sink_name);
- o = pa_operation_new(c, NULL, do_target_node, sizeof(struct target_node));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT;
- d->target_name = pa_xstrdup(sink_name);
- d->target_mask = PA_SUBSCRIPTION_MASK_SINK;
- d->key = METADATA_TARGET_NODE;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata)
-{
- pa_operation *o;
- struct target_node *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p: index:%u sink_index:%u", c, idx, sink_idx);
- o = pa_operation_new(c, NULL, do_target_node, sizeof(struct target_node));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT;
- d->target_idx = sink_idx;
- d->target_mask = PA_SUBSCRIPTION_MASK_SINK;
- d->key = METADATA_TARGET_NODE;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct stream_volume {
- uint32_t idx;
- uint32_t mask;
- bool have_volume;
- pa_cvolume volume;
- int mute;
- pa_context_success_cb_t cb;
- void *userdata;
-};
-
-static void do_stream_volume_mute(pa_operation *o, void *userdata)
-{
- struct stream_volume *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error = 0;
- pa_stream *s;
-
- if ((s = pa_context_find_stream(c, d->idx)) == NULL) {
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & d->mask))
- g = NULL;
- }
- if (s) {
- error = set_stream_volume(c, s,
- d->have_volume ? &d->volume : NULL,
- d->have_volume ? s->mute : d->mute);
- } else if (g) {
- error = set_node_volume(c, g,
- d->have_volume ? &d->volume : NULL,
- d->have_volume ? g->node_info.mute : d->mute);
- } else {
- error = PA_ERR_NOENTITY;
- }
-
- if (error != 0)
- pa_context_set_error(c, error);
- if (d->cb)
- d->cb(c, error != 0 ? 0 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct stream_volume *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: index %d", c, idx);
- o = pa_operation_new(c, NULL, do_stream_volume_mute, sizeof(struct stream_volume));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT;
- d->volume = *volume;
- d->have_volume = true;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct stream_volume *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: index %d", c, idx);
- o = pa_operation_new(c, NULL, do_stream_volume_mute, sizeof(struct stream_volume));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT;
- d->mute = mute;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct kill_stream {
- uint32_t idx;
- uint32_t mask;
- pa_context_success_cb_t cb;
- void *userdata;
-};
-
-static void do_kill_stream(pa_operation *o, void *userdata)
-{
- struct kill_stream *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error = 0;
- pa_stream *s;
-
- if ((s = pa_context_find_stream(c, d->idx)) == NULL) {
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & d->mask))
- g = NULL;
- }
- if (s) {
- pw_stream_destroy(s->stream);
- } else if (g) {
- pw_registry_destroy(c->registry, g->id);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error != 0)
- pa_context_set_error(c, error);
- if (d->cb)
- d->cb(c, error != 0 ? 0 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct kill_stream *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: index %d", c, idx);
- o = pa_operation_new(c, NULL, do_kill_stream, sizeof(struct kill_stream));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct source_output_data {
- uint32_t idx;
- pa_source_output_info_cb_t cb;
- void *userdata;
-};
-
-static int source_output_callback(struct source_output_data *d, pa_context *c, struct global *g)
-{
- struct global *cl;
- struct pw_node_info *info = g->info;
- const char *name = NULL;
- uint32_t n;
- pa_source_output_info i;
- pa_format_info ii[1];
- pa_stream *s;
-
- pw_log_debug("index %d", g->id);
- if (info == NULL)
- return PA_ERR_INVALID;
-
- s = pa_context_find_stream(c, g->id);
-
- if (info->props) {
- if ((name = spa_dict_lookup(info->props, PW_KEY_MEDIA_NAME)) == NULL &&
- (name = spa_dict_lookup(info->props, PW_KEY_APP_NAME)) == NULL &&
- (name = spa_dict_lookup(info->props, PW_KEY_NODE_NAME)) == NULL)
- name = NULL;
- }
- if (name == NULL)
- name = "unknown";
-
- cl = pa_context_find_global(c, g->node_info.client_id);
-
- spa_zero(i);
- i.index = g->id;
- i.name = name;
- i.owner_module = g->id;
- i.client = g->node_info.client_id;
- if (s)
- i.source = s->device_index;
- else
- i.source = g->node_info.device_index;
- if (s && s->sample_spec.channels > 0) {
- i.sample_spec = s->sample_spec;
- if (s->channel_map.channels == s->sample_spec.channels)
- i.channel_map = s->channel_map;
- else
- pa_channel_map_init_extend(&i.channel_map,
- i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
- i.format = s->format;
- }
- else {
- i.sample_spec = g->node_info.sample_spec;
- if (g->node_info.n_channel_volumes)
- i.sample_spec.channels = g->node_info.n_channel_volumes;
- else
- i.sample_spec.channels = 2;
- if (i.sample_spec.channels == g->node_info.channel_map.channels)
- i.channel_map = g->node_info.channel_map;
- else
- pa_channel_map_init_extend(&i.channel_map,
- i.sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
- ii[0].encoding = PA_ENCODING_PCM;
- ii[0].plist = pa_proplist_new();
- i.format = ii;
- }
- pa_cvolume_init(&i.volume);
- i.volume.channels = i.sample_spec.channels;
- for (n = 0; n < i.volume.channels; n++)
- i.volume.values[n] = pa_sw_volume_from_linear(g->node_info.volume * g->node_info.channel_volumes[n]);
-
- i.mute = g->node_info.mute;
- i.buffer_usec = 0;
- i.source_usec = 0;
- i.resample_method = "PipeWire resampler";
- i.driver = "PipeWire";
- i.proplist = pa_proplist_new_dict(info->props);
- if (cl && cl->client_info.info.proplist)
- pa_proplist_update(i.proplist, PA_UPDATE_MERGE, cl->client_info.info.proplist);
- i.corked = false;
- i.has_volume = true;
- i.volume_writable = true;
-
- d->cb(c, &i, 0, d->userdata);
-
- pa_proplist_free(i.proplist);
- return 0;
-}
-
-static void source_output_info(pa_operation *o, void *userdata)
-{
- struct source_output_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
- int error;
-
- if ((g = pa_context_find_global(c, d->idx)) == NULL ||
- !(g->mask & PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT))
- g = NULL;
-
- if (g) {
- error = source_output_callback(d, c, g);
- } else {
- error = PA_ERR_NOENTITY;
- }
- if (error)
- pa_context_set_error(c, error);
- d->cb(c, NULL, error ? -1 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_source_output_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct source_output_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
- pw_log_debug("%p: index:%u", c, idx);
- o = pa_operation_new(c, NULL, source_output_info, sizeof(struct source_output_data));
- d = o->userdata;
- d->idx = idx;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-static void source_output_info_list(pa_operation *o, void *userdata)
-{
- struct source_output_data *d = userdata;
- pa_context *c = o->context;
- struct global *g;
-
- spa_list_for_each(g, &c->globals, link) {
- if (!(g->mask & PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT))
- continue;
- source_output_callback(d, c, g);
- }
- d->cb(c, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_source_output_info_list(pa_context *c, pa_source_output_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct source_output_data *d;
-
- pa_assert(c);
- pa_assert(c->refcount >= 1);
- pa_assert(cb);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p", c);
- o = pa_operation_new(c, NULL, source_output_info_list, sizeof(struct source_output_data));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, const char *source_name, pa_context_success_cb_t cb, void* userdata)
-{
- pa_operation *o;
- struct target_node *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p index:%u name:%s", c, idx, source_name);
- o = pa_operation_new(c, NULL, do_target_node, sizeof(struct target_node));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT;
- d->target_name = pa_xstrdup(source_name);
- d->target_mask = PA_SUBSCRIPTION_MASK_SOURCE;
- d->key = METADATA_TARGET_NODE;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx, uint32_t source_idx, pa_context_success_cb_t cb, void* userdata)
-{
- pa_operation *o;
- struct target_node *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p index:%u source_index:%u", c, idx, source_idx);
- o = pa_operation_new(c, NULL, do_target_node, sizeof(struct target_node));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT;
- d->target_idx = source_idx;
- d->target_mask = PA_SUBSCRIPTION_MASK_SOURCE;
- d->key = METADATA_TARGET_NODE;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_source_output_volume(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct stream_volume *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: index %d", c, idx);
- o = pa_operation_new(c, NULL, do_stream_volume_mute, sizeof(struct stream_volume));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT;
- d->volume = *volume;
- d->have_volume = true;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_set_source_output_mute(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct stream_volume *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: index %d", c, idx);
- o = pa_operation_new(c, NULL, do_stream_volume_mute, sizeof(struct stream_volume));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT;
- d->mute = mute;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct kill_stream *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("context %p: index %d", c, idx);
- o = pa_operation_new(c, NULL, do_kill_stream, sizeof(struct kill_stream));
- d = o->userdata;
- d->idx = idx;
- d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct stat_ack {
- pa_stat_info_cb_t cb;
- int error;
- void *userdata;
-};
-
-static void on_stat_info(pa_operation *o, void *userdata)
-{
- struct stat_ack *d = userdata;
- pa_context *c = o->context;
- pa_stat_info i;
- spa_zero(i);
- if (d->error != 0)
- pa_context_set_error(c, d->error);
- if (d->cb)
- d->cb(c, &i, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct stat_ack *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p", c);
- o = pa_operation_new(c, NULL, on_stat_info, sizeof(struct stat_ack));
- d = o->userdata;
- d->cb = cb;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-struct sample_info {
- pa_sample_info_cb_t cb;
- int error;
- void *userdata;
-};
-
-static void on_sample_info(pa_operation *o, void *userdata)
-{
- struct sample_info *d = userdata;
- pa_context *c = o->context;
- if (d->error != 0)
- pa_context_set_error(c, d->error);
- if (d->cb)
- d->cb(c, NULL, d->error ? -1 : 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name, pa_sample_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct sample_info *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p nane:%s", c, name);
- o = pa_operation_new(c, NULL, on_sample_info, sizeof(struct sample_info));
- d = o->userdata;
- d->cb = cb;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, pa_sample_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct sample_info *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p index:%u", c, idx);
- o = pa_operation_new(c, NULL, on_sample_info, sizeof(struct sample_info));
- d = o->userdata;
- d->cb = cb;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-
-static void on_sample_info_list(pa_operation *o, void *userdata)
-{
- struct sample_info *d = userdata;
- pa_context *c = o->context;
- if (d->error != 0)
- pa_context_set_error(c, d->error);
- if (d->cb)
- d->cb(c, NULL, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct sample_info *d;
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("%p", c);
- o = pa_operation_new(c, NULL, on_sample_info_list, sizeof(struct sample_info));
- d = o->userdata;
- d->cb = cb;
- d->error = PA_ERR_NOTIMPLEMENTED;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata)
-{
- pw_log_warn("Deprecated: Not Implemented");
- return NULL;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata)
-{
- pw_log_warn("Deprecated: Not Implemented");
- return NULL;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata)
-{
- pw_log_warn("Deprecated: Not Implemented");
- return NULL;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t cb, void* userdata)
-{
- pw_log_warn("Deprecated: Not Implemented");
- return NULL;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata)
-{
- pw_log_warn("Deprecated: Not Implemented");
- return NULL;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata)
-{
- pw_log_warn("Deprecated: Not Implemented");
- return NULL;
-}
diff --git a/pipewire-pulseaudio/src/json.c b/pipewire-pulseaudio/src/json.c
deleted file mode 100644
index 8704264b0..000000000
--- a/pipewire-pulseaudio/src/json.c
+++ /dev/null
@@ -1,659 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2016 Arun Raghavan
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-
-#include
-
-#include
-#include
-
-#include "internal.h"
-#include "json.h"
-#include "strbuf.h"
-
-#define MAX_NESTING_DEPTH 20 /* Arbitrary number to make sure we don't have a stack overflow */
-
-typedef struct pa_json_item {
- char *key;
- pa_json_object *value;
-} pa_json_item;
-
-struct pa_json_object {
- pa_json_type type;
-
- union {
- int int_value;
- double double_value;
- bool bool_value;
- char *string_value;
- struct pw_array values; /* objects */
- };
-};
-
-static void clear_array(struct pw_array *array)
-{
- pa_json_object **value;
- pw_array_for_each(value, array)
- pa_json_object_free(*value);
- pw_array_clear(array);
-}
-
-static void clear_item(pa_json_item *item)
-{
- free(item->key);
- pa_json_object_free(item->value);
-}
-
-static void clear_object(struct pw_array *array)
-{
- pa_json_item *item;
- pw_array_for_each(item, array)
- clear_item(item);
- pw_array_clear(array);
-}
-
-static const char* parse_value(const char *str, const char *end, pa_json_object **obj, unsigned int depth);
-
-static pa_json_object* json_object_new(void) {
- pa_json_object *obj;
-
- obj = pa_xnew0(pa_json_object, 1);
-
- return obj;
-}
-
-static bool is_whitespace(char c) {
- return c == '\t' || c == '\n' || c == '\r' || c == ' ';
-}
-
-static bool is_digit(char c) {
- return c >= '0' && c <= '9';
-}
-
-static bool is_end(const char c, const char *end) {
- if (!end)
- return c == '\0';
- else {
- while (*end) {
- if (c == *end)
- return true;
- end++;
- }
- }
-
- return false;
-}
-
-static const char* consume_string(const char *str, const char *expect) {
- while (*expect) {
- if (*str != *expect)
- return NULL;
-
- str++;
- expect++;
- }
-
- return str;
-}
-
-static const char* parse_null(const char *str, pa_json_object *obj) {
- str = consume_string(str, "null");
-
- if (str)
- obj->type = PA_JSON_TYPE_NULL;
-
- return str;
-}
-
-static const char* parse_boolean(const char *str, pa_json_object *obj) {
- const char *tmp;
-
- tmp = consume_string(str, "true");
-
- if (tmp) {
- obj->type = PA_JSON_TYPE_BOOL;
- obj->bool_value = true;
- } else {
- tmp = consume_string(str, "false");
-
- if (str) {
- obj->type = PA_JSON_TYPE_BOOL;
- obj->bool_value = false;
- }
- }
-
- return tmp;
-}
-
-static const char* parse_string(const char *str, pa_json_object *obj) {
- pa_strbuf *buf = pa_strbuf_new();
-
- str++; /* Consume leading '"' */
-
- while (*str && *str != '"') {
- if (*str != '\\') {
- /* We only accept ASCII printable characters. */
- if (*str < 0x20 || *str > 0x7E) {
- pa_log("Invalid non-ASCII character: 0x%x", (unsigned int) *str);
- goto error;
- }
-
- /* Normal character, juts consume */
- pa_strbuf_putc(buf, *str);
- } else {
- /* Need to unescape */
- str++;
-
- switch (*str) {
- case '"':
- case '\\':
- case '/':
- pa_strbuf_putc(buf, *str);
- break;
-
- case 'b':
- pa_strbuf_putc(buf, '\b' /* backspace */);
- break;
-
- case 'f':
- pa_strbuf_putc(buf, '\f' /* form feed */);
- break;
-
- case 'n':
- pa_strbuf_putc(buf, '\n' /* new line */);
- break;
-
- case 'r':
- pa_strbuf_putc(buf, '\r' /* carriage return */);
- break;
-
- case 't':
- pa_strbuf_putc(buf, '\t' /* horizontal tab */);
- break;
-
- case 'u':
- pa_log("Unicode code points are currently unsupported");
- goto error;
-
- default:
- pa_log("Unexpected escape value: %c", *str);
- goto error;
- }
- }
-
- str++;
- }
-
- if (*str != '"') {
- pa_log("Failed to parse remainder of string: %s", str);
- goto error;
- }
-
- str++;
-
- obj->type = PA_JSON_TYPE_STRING;
- obj->string_value = pa_strbuf_to_string_free(buf);
-
- return str;
-
-error:
- pa_strbuf_free(buf);
- return NULL;
-}
-
-static const char* parse_number(const char *str, pa_json_object *obj) {
- bool negative = false, has_fraction = false, has_exponent = false, valid = false;
- unsigned int integer = 0;
- unsigned int fraction = 0;
- unsigned int fraction_digits = 0;
- int exponent = 0;
-
- if (*str == '-') {
- negative = true;
- str++;
- }
-
- if (*str == '0') {
- valid = true;
- str++;
- goto fraction;
- }
-
- while (is_digit(*str)) {
- valid = true;
-
- if (integer > ((negative ? INT_MAX : UINT_MAX) / 10)) {
- pa_log("Integer overflow while parsing number");
- goto error;
- }
-
- integer = (integer * 10) + (*str - '0');
- str++;
- }
-
-fraction:
-
- if (!valid) {
- pa_log("Missing digits while parsing number");
- goto error;
- }
-
- if (*str == '.') {
- has_fraction = true;
- str++;
- valid = false;
-
- while (is_digit(*str)) {
- valid = true;
-
- if (fraction > (UINT_MAX / 10)) {
- pa_log("Integer overflow while parsing fractional part of number");
- goto error;
- }
-
- fraction = (fraction * 10) + (*str - '0');
- fraction_digits++;
- str++;
- }
-
- if (!valid) {
- pa_log("No digit after '.' while parsing fraction");
- goto error;
- }
- }
-
- if (*str == 'e' || *str == 'E') {
- bool exponent_negative = false;
-
- has_exponent = true;
- str++;
- valid = false;
-
- if (*str == '-') {
- exponent_negative = true;
- str++;
- } else if (*str == '+')
- str++;
-
- while (is_digit(*str)) {
- valid = true;
-
- if (exponent > (INT_MAX / 10)) {
- pa_log("Integer overflow while parsing exponent part of number");
- goto error;
- }
-
- exponent = (exponent * 10) + (*str - '0');
- str++;
- }
-
- if (!valid) {
- pa_log("No digit in exponent while parsing fraction");
- goto error;
- }
-
- if (exponent_negative)
- exponent *= -1;
- }
-
- if (has_fraction || has_exponent) {
- obj->type = PA_JSON_TYPE_DOUBLE;
- obj->double_value =
- (negative ? -1.0 : 1.0) * (integer + (double) fraction / pow(10, fraction_digits)) * pow(10, exponent);
- } else {
- obj->type = PA_JSON_TYPE_INT;
- obj->int_value = (negative ? -1 : 1) * integer;
- }
-
- return str;
-
-error:
- return NULL;
-}
-
-static const char *parse_object(const char *str, pa_json_object *obj, unsigned int depth) {
- pa_json_object *name = NULL, *value = NULL;
- pa_json_item *item;
-
- obj->values = PW_ARRAY_INIT(64);
-
- while (*str != '}') {
- str++; /* Consume leading '{' or ',' */
-
- str = parse_value(str, ":", &name, depth + 1);
- if (!str || pa_json_object_get_type(name) != PA_JSON_TYPE_STRING) {
- pa_log("Could not parse key for object");
- goto error;
- }
-
- /* Consume the ':' */
- str++;
-
- str = parse_value(str, ",}", &value, depth + 1);
- if (!str) {
- pa_log("Could not parse value for object");
- goto error;
- }
-
- item = pw_array_add(&obj->values, sizeof(pa_json_item));
- item->key = strdup(pa_json_object_get_string(name));
- item->value = value;
- pa_json_object_free(name);
-
- name = NULL;
- value = NULL;
- }
-
- /* Drop trailing '}' */
- str++;
-
- /* We now know the value was correctly parsed */
- obj->type = PA_JSON_TYPE_OBJECT;
-
- return str;
-
-error:
- clear_object(&obj->values);
-
- if (name)
- pa_json_object_free(name);
- if (value)
- pa_json_object_free(value);
-
- return NULL;
-}
-
-static const char *parse_array(const char *str, pa_json_object *obj, unsigned int depth) {
- pa_json_object *value;
-
- obj->values = PW_ARRAY_INIT(64);
-
- while (*str != ']') {
- str++; /* Consume leading '[' or ',' */
-
- /* Need to chew up whitespaces as a special case to deal with the
- * possibility of an empty array */
- while (is_whitespace(*str))
- str++;
-
- if (*str == ']')
- break;
-
- str = parse_value(str, ",]", &value, depth + 1);
- if (!str) {
- pa_log("Could not parse value for array");
- goto error;
- }
-
- pw_array_add_ptr(&obj->values, value);
- }
-
- /* Drop trailing ']' */
- str++;
-
- /* We now know the value was correctly parsed */
- obj->type = PA_JSON_TYPE_ARRAY;
-
- return str;
-
-error:
- clear_array(&obj->values);
- return NULL;
-}
-
-typedef enum {
- JSON_PARSER_STATE_INIT,
- JSON_PARSER_STATE_FINISH,
-} json_parser_state;
-
-static const char* parse_value(const char *str, const char *end, pa_json_object **obj, unsigned int depth) {
- json_parser_state state = JSON_PARSER_STATE_INIT;
- pa_json_object *o;
-
- pa_assert(str != NULL);
-
- o = json_object_new();
-
- if (depth > MAX_NESTING_DEPTH) {
- pa_log("Exceeded maximum permitted nesting depth of objects (%u)", MAX_NESTING_DEPTH);
- goto error;
- }
-
- while (!is_end(*str, end)) {
- switch (state) {
- case JSON_PARSER_STATE_INIT:
- if (is_whitespace(*str)) {
- str++;
- } else if (*str == 'n') {
- str = parse_null(str, o);
- state = JSON_PARSER_STATE_FINISH;
- } else if (*str == 't' || *str == 'f') {
- str = parse_boolean(str, o);
- state = JSON_PARSER_STATE_FINISH;
- } else if (*str == '"') {
- str = parse_string(str, o);
- state = JSON_PARSER_STATE_FINISH;
- } else if (is_digit(*str) || *str == '-') {
- str = parse_number(str, o);
- state = JSON_PARSER_STATE_FINISH;
- } else if (*str == '{') {
- str = parse_object(str, o, depth);
- state = JSON_PARSER_STATE_FINISH;
- } else if (*str == '[') {
- str = parse_array(str, o, depth);
- state = JSON_PARSER_STATE_FINISH;
- } else {
- pa_log("Invalid JSON string: %s", str);
- goto error;
- }
-
- if (!str)
- goto error;
-
- break;
-
- case JSON_PARSER_STATE_FINISH:
- /* Consume trailing whitespaces */
- if (is_whitespace(*str)) {
- str++;
- } else {
- goto error;
- }
- }
- }
-
- if (pa_json_object_get_type(o) == PA_JSON_TYPE_INIT) {
- /* We didn't actually get any data */
- pa_log("No data while parsing json string: '%s' till '%s'", str, pa_strnull(end));
- goto error;
- }
-
- *obj = o;
-
- return str;
-
-error:
- pa_json_object_free(o);
- return NULL;
-}
-
-
-SPA_EXPORT
-pa_json_object* pa_json_parse(const char *str) {
- pa_json_object *obj;
-
- str = parse_value(str, NULL, &obj, 0);
-
- if (!str) {
- pa_log("JSON parsing failed");
- return NULL;
- }
-
- if (*str != '\0') {
- pa_log("Unable to parse complete JSON string, remainder is: %s", str);
- pa_json_object_free(obj);
- return NULL;
- }
-
- return obj;
-}
-
-SPA_EXPORT
-pa_json_type pa_json_object_get_type(const pa_json_object *obj) {
- return obj->type;
-}
-
-SPA_EXPORT
-void pa_json_object_free(pa_json_object *obj) {
-
- switch (pa_json_object_get_type(obj)) {
- case PA_JSON_TYPE_INIT:
- case PA_JSON_TYPE_INT:
- case PA_JSON_TYPE_DOUBLE:
- case PA_JSON_TYPE_BOOL:
- case PA_JSON_TYPE_NULL:
- break;
-
- case PA_JSON_TYPE_STRING:
- pa_xfree(obj->string_value);
- break;
-
- case PA_JSON_TYPE_OBJECT:
- clear_object(&obj->values);
- break;
-
- case PA_JSON_TYPE_ARRAY:
- clear_array(&obj->values);
- break;
-
- default:
- pa_assert_not_reached();
- }
-
- pa_xfree(obj);
-}
-
-SPA_EXPORT
-int pa_json_object_get_int(const pa_json_object *o) {
- pa_assert(pa_json_object_get_type(o) == PA_JSON_TYPE_INT);
- return o->int_value;
-}
-
-SPA_EXPORT
-double pa_json_object_get_double(const pa_json_object *o) {
- pa_assert(pa_json_object_get_type(o) == PA_JSON_TYPE_DOUBLE);
- return o->double_value;
-}
-
-SPA_EXPORT
-bool pa_json_object_get_bool(const pa_json_object *o) {
- pa_assert(pa_json_object_get_type(o) == PA_JSON_TYPE_BOOL);
- return o->bool_value;
-}
-
-SPA_EXPORT
-const char* pa_json_object_get_string(const pa_json_object *o) {
- pa_assert(pa_json_object_get_type(o) == PA_JSON_TYPE_STRING);
- return o->string_value;
-}
-
-SPA_EXPORT
-const pa_json_object* pa_json_object_get_object_member(const pa_json_object *o, const char *name) {
- pa_json_item *item;
- pa_assert(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
- pw_array_for_each(item, &o->values) {
- if (pa_streq(item->key, name))
- return item->value;
- }
- return NULL;
-}
-
-SPA_EXPORT
-int pa_json_object_get_array_length(const pa_json_object *o) {
- pa_assert(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
- return pw_array_get_len(&o->values, const pa_json_object*);
-}
-
-SPA_EXPORT
-const pa_json_object* pa_json_object_get_array_member(const pa_json_object *o, int index) {
- pa_assert(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
- return pw_array_get_unchecked_s(&o->values, index, sizeof(pa_json_object*),
- const pa_json_object);
-}
-
-SPA_EXPORT
-bool pa_json_object_equal(const pa_json_object *o1, const pa_json_object *o2) {
- int i;
-
- if (pa_json_object_get_type(o1) != pa_json_object_get_type(o2))
- return false;
-
- switch (pa_json_object_get_type(o1)) {
- case PA_JSON_TYPE_NULL:
- return true;
-
- case PA_JSON_TYPE_BOOL:
- return o1->bool_value == o2->bool_value;
-
- case PA_JSON_TYPE_INT:
- return o1->int_value == o2->int_value;
-
- case PA_JSON_TYPE_DOUBLE:
- return PA_DOUBLE_IS_EQUAL(o1->double_value, o2->double_value);
-
- case PA_JSON_TYPE_STRING:
- return pa_streq(o1->string_value, o2->string_value);
-
- case PA_JSON_TYPE_ARRAY:
- if (pa_json_object_get_array_length(o1) != pa_json_object_get_array_length(o2))
- return false;
-
- for (i = 0; i < pa_json_object_get_array_length(o1); i++) {
- if (!pa_json_object_equal(pa_json_object_get_array_member(o1, i),
- pa_json_object_get_array_member(o2, i)))
- return false;
- }
-
- return true;
-
- case PA_JSON_TYPE_OBJECT: {
- const pa_json_object *value;
- const pa_json_item *item;
-
- if (o1->values.size != o2->values.size)
- return false;
-
- pw_array_for_each(item, &o1->values) {
- value = pa_json_object_get_object_member(o2, item->key);
- if (!value || !pa_json_object_equal(item->value, value))
- return false;
- }
-
- return true;
- }
-
- default:
- pa_assert_not_reached();
- }
-}
diff --git a/pipewire-pulseaudio/src/json.h b/pipewire-pulseaudio/src/json.h
deleted file mode 100644
index 7759bf2db..000000000
--- a/pipewire-pulseaudio/src/json.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2016 Arun Raghavan
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#include
-
-#define PA_DOUBLE_IS_EQUAL(x, y) (((x) - (y)) < 0.000001 && ((x) - (y)) > -0.000001)
-
-typedef enum {
- PA_JSON_TYPE_INIT = 0,
- PA_JSON_TYPE_NULL,
- PA_JSON_TYPE_INT,
- PA_JSON_TYPE_DOUBLE,
- PA_JSON_TYPE_BOOL,
- PA_JSON_TYPE_STRING,
- PA_JSON_TYPE_ARRAY,
- PA_JSON_TYPE_OBJECT,
-} pa_json_type;
-
-typedef struct pa_json_object pa_json_object;
-
-pa_json_object* pa_json_parse(const char *str);
-pa_json_type pa_json_object_get_type(const pa_json_object *obj);
-void pa_json_object_free(pa_json_object *obj);
-
-/* All pointer members that are returned are valid while the corresponding object is valid */
-
-int pa_json_object_get_int(const pa_json_object *o);
-double pa_json_object_get_double(const pa_json_object *o);
-bool pa_json_object_get_bool(const pa_json_object *o);
-const char* pa_json_object_get_string(const pa_json_object *o);
-
-const pa_json_object* pa_json_object_get_object_member(const pa_json_object *o, const char *name);
-
-int pa_json_object_get_array_length(const pa_json_object *o);
-const pa_json_object* pa_json_object_get_array_member(const pa_json_object *o, int index);
-
-bool pa_json_object_equal(const pa_json_object *o1, const pa_json_object *o2);
diff --git a/pipewire-pulseaudio/src/mainloop-glib.c b/pipewire-pulseaudio/src/mainloop-glib.c
deleted file mode 100644
index 7295256e0..000000000
--- a/pipewire-pulseaudio/src/mainloop-glib.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include
-#include
-
-#include
-#include
-
-#include "internal.h"
-
-struct source {
- GSource base;
- struct pw_loop *loop;
-};
-
-struct pa_glib_mainloop {
- GMainContext *context;
- pa_mainloop *loop;
- struct source *source;
- guint id;
-};
-
-static gboolean source_prepare (GSource *base, int *timeout)
-{
- *timeout = -1;
- return FALSE;
-}
-
-static gboolean source_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
-{
- struct source *s = (struct source *) source;
- int result;
-
- pw_loop_enter (s->loop);
- do {
- result = pw_loop_iterate (s->loop, 0);
- } while (result == -EINTR);
- pw_loop_leave (s->loop);
-
- if (result < 0)
- g_warning ("pipewire_loop_iterate failed: %s", spa_strerror (result));
-
- return TRUE;
-}
-
-static GSourceFuncs source_funcs =
-{
- source_prepare,
- NULL,
- source_dispatch,
- NULL,
- NULL,
- NULL,
-};
-
-SPA_EXPORT
-pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c)
-{
-
- pa_glib_mainloop *loop;
-
- loop = calloc(1, sizeof(pa_glib_mainloop));
- if (loop == NULL)
- goto error;
-
- loop->context = c;
- loop->loop = pa_mainloop_new();
- if (loop->loop == NULL)
- goto error_free;
-
- loop->source = (struct source *) g_source_new(&source_funcs, sizeof(struct source));
- loop->source->loop = loop->loop->loop;
-
- g_source_add_unix_fd (&loop->source->base,
- pw_loop_get_fd(loop->source->loop),
- G_IO_IN | G_IO_ERR);
-
- loop->id = g_source_attach (&loop->source->base, loop->context);
-
- return loop;
-
- error_free:
- free(loop);
- error:
- return NULL;
-
-}
-
-SPA_EXPORT
-void pa_glib_mainloop_free(pa_glib_mainloop* g)
-{
- g_source_destroy(&g->source->base);
- pa_mainloop_free(g->loop);
- free(g);
-}
-
-SPA_EXPORT
-pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g)
-{
- return pa_mainloop_get_api(g->loop);
-}
diff --git a/pipewire-pulseaudio/src/mainloop-signal.c b/pipewire-pulseaudio/src/mainloop-signal.c
deleted file mode 100644
index 19fe31225..000000000
--- a/pipewire-pulseaudio/src/mainloop-signal.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-#include
-
-#include
-#include
-
-#include
-
-#include "internal.h"
-
-
-static pa_mainloop_api *api = NULL;
-static bool have_signals = false;
-static struct spa_list signals;
-static struct pw_loop *loop = NULL;
-
-struct pa_signal_event {
- struct spa_list link;
- struct spa_source *source;
- pa_signal_cb_t callback;
- pa_signal_destroy_cb_t destroy;
- void *userdata;
-};
-
-SPA_EXPORT
-int pa_signal_init(pa_mainloop_api *a)
-{
- pa_assert(a);
- pa_assert(!api);
-
- api = a;
- spa_list_init(&signals);
- loop = a->userdata;
-
- return 0;
-}
-
-SPA_EXPORT
-void pa_signal_done(void)
-{
- pa_signal_event *ev;
-
- if (have_signals) {
- spa_list_consume(ev, &signals, link)
- pa_signal_free(ev);
- }
- api = NULL;
-}
-
-static void source_signal_func (void *data, int signal_number)
-{
- pa_signal_event *ev = data;
- if (ev->callback)
- ev->callback(api, ev, signal_number, ev->userdata);
-}
-
-SPA_EXPORT
-pa_signal_event* pa_signal_new(int sig, pa_signal_cb_t callback, void *userdata)
-{
- pa_signal_event *ev;
-
- pa_assert(sig > 0);
- pa_assert(callback);
-
- ev = calloc(1, sizeof(pa_signal_event));
- ev->source = spa_loop_utils_add_signal(loop->utils, sig, source_signal_func, ev);
- ev->callback = callback;
- ev->userdata = userdata;
-
- if (!have_signals)
- spa_list_init(&signals);
- have_signals = true;
- spa_list_append(&signals, &ev->link);
-
- return ev;
-}
-
-SPA_EXPORT
-void pa_signal_free(pa_signal_event *e)
-{
- pa_assert(e);
-
- spa_list_remove(&e->link);
- spa_loop_utils_destroy_source(loop->utils, e->source);
- if (e->destroy)
- e->destroy(api, e, e->userdata);
- free(e);
-}
-
-SPA_EXPORT
-void pa_signal_set_destroy(pa_signal_event *e, pa_signal_destroy_cb_t callback)
-{
- pa_assert(e);
- e->destroy = callback;
-}
diff --git a/pipewire-pulseaudio/src/mainloop.c b/pipewire-pulseaudio/src/mainloop.c
deleted file mode 100644
index f19257488..000000000
--- a/pipewire-pulseaudio/src/mainloop.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-#include
-
-#include "internal.h"
-
-static void do_stop(void *data, uint64_t count)
-{
- struct pa_mainloop *this = data;
- this->quit = true;
-}
-
-static uint32_t map_flags_to_spa(pa_io_event_flags_t flags) {
- return (uint32_t)
- ((flags & PA_IO_EVENT_INPUT ? SPA_IO_IN : 0) |
- (flags & PA_IO_EVENT_OUTPUT ? SPA_IO_OUT : 0) |
- (flags & PA_IO_EVENT_ERROR ? SPA_IO_ERR : 0) |
- (flags & PA_IO_EVENT_HANGUP ? SPA_IO_HUP : 0));
-}
-
-static pa_io_event_flags_t map_flags_from_spa(uint32_t flags) {
- return (flags & SPA_IO_IN ? PA_IO_EVENT_INPUT : 0) |
- (flags & SPA_IO_OUT ? PA_IO_EVENT_OUTPUT : 0) |
- (flags & SPA_IO_ERR ? PA_IO_EVENT_ERROR : 0) |
- (flags & SPA_IO_HUP ? PA_IO_EVENT_HANGUP : 0);
-}
-
-static void source_io_func(void *data, int fd, uint32_t mask)
-{
- pa_io_event *ev = data;
- if (ev->cb)
- ev->cb(&ev->mainloop->api, ev, ev->fd, map_flags_from_spa(mask), ev->userdata);
-}
-
-static pa_io_event* api_io_new(pa_mainloop_api*a, int fd, pa_io_event_flags_t events, pa_io_event_cb_t cb, void *userdata)
-{
- pa_mainloop *mainloop = SPA_CONTAINER_OF(a, pa_mainloop, api);
- pa_io_event *ev;
-
- pa_assert(a);
- pa_assert(fd >= 0);
- pa_assert(cb);
-
- ev = calloc(1, sizeof(pa_io_event));
- ev->source = pw_loop_add_io(mainloop->loop, fd,
- map_flags_to_spa(events), false, source_io_func, ev);
- ev->fd = fd;
- ev->events = events;
- ev->mainloop = mainloop;
- ev->cb = cb;
- ev->userdata = userdata;
- pw_log_debug("new io %p %p %08x", ev, ev->source, events);
-
- return ev;
-}
-
-static void api_io_enable(pa_io_event* e, pa_io_event_flags_t events)
-{
- pa_assert(e);
-
- if (e->events == events || e->source == NULL)
- return;
-
- pw_log_debug("io %p", e);
- e->events = events;
- pw_loop_update_io(e->mainloop->loop, e->source, map_flags_to_spa(events));
-}
-
-static void api_io_free(pa_io_event* e)
-{
- pa_assert(e);
- pw_log_debug("io %p", e);
- if (e->source)
- pw_loop_destroy_source(e->mainloop->loop, e->source);
- if (e->destroy)
- e->destroy(&e->mainloop->api, e, e->userdata);
- free(e);
-}
-
-static void api_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t cb)
-{
- pa_assert(e);
- e->destroy = cb;
-}
-
-static void source_timer_func(void *data, uint64_t expirations)
-{
- pa_time_event *ev = data;
- struct timeval tv;
- if (ev->cb)
- ev->cb(&ev->mainloop->api, ev, &tv, ev->userdata);
-}
-
-static void set_timer(pa_time_event *ev, const struct timeval *tv)
-{
- pa_mainloop *mainloop = ev->mainloop;
- struct timespec ts;
-
- if (tv == NULL) {
- ts.tv_sec = 0;
- ts.tv_nsec = 1;
- } else {
- struct timeval ttv = *tv;
-
- if ((ttv.tv_usec & PA_TIMEVAL_RTCLOCK) != 0)
- ttv.tv_usec &= ~PA_TIMEVAL_RTCLOCK;
- else
- pa_rtclock_from_wallclock(&ttv);
-
- /* something strange, probably not wallclock time, try to
- * use the timeval directly */
- if (ttv.tv_sec == 0 && ttv.tv_usec == 0)
- ttv = *tv;
-
- ts.tv_sec = ttv.tv_sec;
- ts.tv_nsec = ttv.tv_usec * SPA_NSEC_PER_USEC;
-
- /* make sure we never disable the timer */
- if (ts.tv_sec == 0 && ts.tv_nsec == 0)
- ts.tv_nsec++;
- }
- pw_log_debug("set timer %p %ld %ld", ev, ts.tv_sec, ts.tv_nsec);
- pw_loop_update_timer(mainloop->loop, ev->source, &ts, NULL, true);
-}
-
-static pa_time_event* api_time_new(pa_mainloop_api*a, const struct timeval *tv, pa_time_event_cb_t cb, void *userdata)
-{
- pa_mainloop *mainloop = SPA_CONTAINER_OF(a, pa_mainloop, api);
- pa_time_event *ev;
-
- ev = calloc(1, sizeof(pa_time_event));
- ev->source = pw_loop_add_timer(mainloop->loop, source_timer_func, ev);
- ev->mainloop = mainloop;
- ev->cb = cb;
- ev->userdata = userdata;
- pw_log_debug("new timer %p", ev);
-
- set_timer(ev, tv);
-
- return ev;
-}
-
-static void api_time_restart(pa_time_event* e, const struct timeval *tv)
-{
- pa_assert(e);
- set_timer(e, tv);
-}
-
-static void api_time_free(pa_time_event* e)
-{
- pa_assert(e);
- pw_log_debug("io %p", e);
- pw_loop_destroy_source(e->mainloop->loop, e->source);
- if (e->destroy)
- e->destroy(&e->mainloop->api, e, e->userdata);
- free(e);
-}
-
-static void api_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb)
-{
- pa_assert(e);
- e->destroy = cb;
-}
-
-static void source_idle_func(void *data)
-{
- pa_defer_event *ev = data;
- if (ev->cb)
- ev->cb(&ev->mainloop->api, ev, ev->userdata);
-}
-
-static pa_defer_event* api_defer_new(pa_mainloop_api*a, pa_defer_event_cb_t cb, void *userdata)
-{
- pa_mainloop *mainloop = SPA_CONTAINER_OF(a, pa_mainloop, api);
- pa_defer_event *ev;
-
- pa_assert(a);
- pa_assert(cb);
-
- ev = calloc(1, sizeof(pa_defer_event));
- ev->source = pw_loop_add_idle(mainloop->loop, true, source_idle_func, ev);
- ev->mainloop = mainloop;
- ev->cb = cb;
- ev->userdata = userdata;
- pw_log_debug("new defer %p", ev);
-
- return ev;
-}
-
-static void api_defer_enable(pa_defer_event* e, int b)
-{
- pa_assert(e);
- pw_loop_enable_idle(e->mainloop->loop, e->source, b ? true : false);
-}
-
-static void api_defer_free(pa_defer_event* e)
-{
- pa_assert(e);
- pw_log_debug("io %p", e);
- pw_loop_destroy_source(e->mainloop->loop, e->source);
- if (e->destroy)
- e->destroy(&e->mainloop->api, e, e->userdata);
- free(e);
-}
-
-static void api_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb)
-{
- pa_assert(e);
- e->destroy = cb;
-}
-
-static void api_quit(pa_mainloop_api*a, int retval)
-{
- pa_mainloop *m = SPA_CONTAINER_OF(a, pa_mainloop, api);
- m->quit = true;
- m->retval = retval;
- pa_mainloop_wakeup(m);
-}
-
-static const pa_mainloop_api api =
-{
- .io_new = api_io_new,
- .io_enable = api_io_enable,
- .io_free = api_io_free,
- .io_set_destroy = api_io_set_destroy,
-
- .time_new = api_time_new,
- .time_restart = api_time_restart,
- .time_free = api_time_free,
- .time_set_destroy = api_time_set_destroy,
-
- .defer_new = api_defer_new,
- .defer_enable = api_defer_enable,
- .defer_free = api_defer_free,
- .defer_set_destroy = api_defer_set_destroy,
-
- .quit = api_quit,
-};
-
-SPA_EXPORT
-pa_mainloop *pa_mainloop_new(void)
-{
- pa_mainloop *loop;
-
- if (getenv("PULSE_INTERNAL"))
- return NULL;
-
- loop = calloc(1, sizeof(pa_mainloop));
- if (loop == NULL)
- return NULL;
-
- loop->loop = pw_loop_new(NULL);
- if (loop->loop == NULL)
- goto no_loop;
-
- loop->fd = pw_loop_get_fd(loop->loop);
- loop->event = pw_loop_add_event(loop->loop, do_stop, loop);
- loop->api = api;
- loop->api.userdata = loop->loop;
-
- pw_log_debug("%p: %p fd:%d", loop, loop->loop, loop->fd);
-
- return loop;
-
- no_loop:
- free(loop);
- return NULL;
-}
-
-bool pa_mainloop_api_is_our_api(pa_mainloop_api *api)
-{
- pa_assert(api);
- return api->io_new == api_io_new;
-}
-
-SPA_EXPORT
-void pa_mainloop_free(pa_mainloop* m)
-{
- pw_log_debug("%p", m);
- pw_loop_destroy(m->loop);
- free(m);
-}
-
-SPA_EXPORT
-int pa_mainloop_prepare(pa_mainloop *m, int timeout)
-{
- if (m->quit)
- return -2;
- m->timeout = timeout;
- m->n_events = -EIO;
- return 0;
-}
-
-static int usec_to_timeout(pa_usec_t u)
-{
- if (u == PA_USEC_INVALID)
- return -1;
- return (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC;
-}
-
-/** Execute the previously prepared poll. Returns a negative value on error.*/
-SPA_EXPORT
-int pa_mainloop_poll(pa_mainloop *m)
-{
- int res, timeout;
- bool do_iterate;
-
- if (m->quit)
- return -2;
-
- if (m->poll_func) {
- struct pollfd fds[1];
-
- fds[0].fd = m->fd;
- fds[0].events = POLLIN;
- fds[0].revents = 0;
-
- do {
- res = m->poll_func(fds, 1,
- usec_to_timeout(m->timeout),
- m->poll_func_userdata);
- } while (res == -EINTR);
- do_iterate = res == 1 && SPA_FLAG_IS_SET(fds[0].revents, POLLIN);
- timeout = 0;
- } else {
- do_iterate = true;
- timeout = m->timeout;
- }
-
- if (do_iterate) {
- pw_loop_enter(m->loop);
- do {
- res = pw_loop_iterate(m->loop, timeout);
- } while (res == -EINTR);
- pw_loop_leave(m->loop);
- }
- m->n_events = res;
- return res;
-}
-
-SPA_EXPORT
-int pa_mainloop_dispatch(pa_mainloop *m)
-{
- if (m->quit)
- return -2;
-
- return m->n_events;
-}
-
-SPA_EXPORT
-int pa_mainloop_get_retval(PA_CONST pa_mainloop *m)
-{
- return m->retval;
-}
-
-/** Run a single iteration of the main loop. This is a convenience function
-for pa_mainloop_prepare(), pa_mainloop_poll() and pa_mainloop_dispatch().
-Returns a negative value on error or exit request. If block is nonzero,
-block for events if none are queued. Optionally return the return value as
-specified with the main loop's quit() routine in the integer variable retval points
-to. On success returns the number of sources dispatched in this iteration. */
-SPA_EXPORT
-int pa_mainloop_iterate(pa_mainloop *m, int block, int *retval)
-{
- int r;
- pa_assert(m);
-
- if ((r = pa_mainloop_prepare(m, block ? -1 : 0)) < 0)
- goto quit;
-
- if ((r = pa_mainloop_poll(m)) < 0)
- goto quit;
-
- if ((r = pa_mainloop_dispatch(m)) < 0)
- goto quit;
-
- return r;
-
- quit:
- if ((r == -2) && retval)
- *retval = pa_mainloop_get_retval(m);
- return r;
-}
-
-SPA_EXPORT
-int pa_mainloop_run(pa_mainloop *m, int *retval)
-{
- int r;
-
- while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0)
- ;
-
- if (r == -2)
- return 1;
- else
- return -1;
-}
-
-
-SPA_EXPORT
-pa_mainloop_api* pa_mainloop_get_api(pa_mainloop *m)
-{
- pa_assert(m);
- return &m->api;
-}
-
-SPA_EXPORT
-void pa_mainloop_quit(pa_mainloop *m, int retval)
-{
- pa_assert(m);
- m->api.quit(&m->api, retval);
-}
-
-SPA_EXPORT
-void pa_mainloop_wakeup(pa_mainloop *m)
-{
- pa_assert(m);
- pw_loop_signal_event(m->loop, m->event);
-}
-
-SPA_EXPORT
-void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata)
-{
- pa_assert(m);
- m->poll_func = poll_func;
- m->poll_func_userdata = userdata;
-}
-
-struct once_info {
- void (*callback)(pa_mainloop_api*m, void *userdata);
- void *userdata;
-};
-
-static void once_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
- struct once_info *i = userdata;
-
- pa_assert(m);
- pa_assert(i);
-
- pa_assert(i->callback);
- i->callback(m, i->userdata);
-
- pa_assert(m->defer_free);
- m->defer_free(e);
-}
-
-static void free_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
- struct once_info *i = userdata;
-
- pa_assert(m);
- pa_assert(i);
- pa_xfree(i);
-}
-
-
-SPA_EXPORT
-void pa_mainloop_api_once(pa_mainloop_api* m, void (*callback)(pa_mainloop_api *m, void *userdata), void *userdata) {
- struct once_info *i;
- pa_defer_event *e;
-
- pa_assert(m);
- pa_assert(callback);
-
- pa_init_i18n();
-
- i = pa_xnew(struct once_info, 1);
- i->callback = callback;
- i->userdata = userdata;
-
- pa_assert(m->defer_new);
- pa_assert_se(e = m->defer_new(m, once_callback, i));
- m->defer_set_destroy(e, free_callback);
-}
-
diff --git a/pipewire-pulseaudio/src/map-file b/pipewire-pulseaudio/src/map-file
deleted file mode 100644
index 9b6cba223..000000000
--- a/pipewire-pulseaudio/src/map-file
+++ /dev/null
@@ -1,386 +0,0 @@
-PULSE_0 {
-global:
-pa_ascii_filter;
-pa_ascii_valid;
-pa_bytes_per_second;
-pa_bytes_snprint;
-pa_bytes_to_usec;
-pa_channel_map_can_balance;
-pa_channel_map_can_fade;
-pa_channel_map_can_lfe_balance;
-pa_channel_map_compatible;
-pa_channel_map_equal;
-pa_channel_map_has_position;
-pa_channel_map_init;
-pa_channel_map_init_auto;
-pa_channel_map_init_extend;
-pa_channel_map_init_mono;
-pa_channel_map_init_stereo;
-pa_channel_map_mask;
-pa_channel_map_parse;
-pa_channel_map_snprint;
-pa_channel_map_superset;
-pa_channel_map_to_name;
-pa_channel_map_to_pretty_name;
-pa_channel_map_valid;
-pa_channel_position_from_string;
-pa_channel_position_to_pretty_string;
-pa_channel_position_to_string;
-pa_channels_valid;
-pa_context_add_autoload;
-pa_context_connect;
-pa_context_disconnect;
-pa_context_drain;
-pa_context_errno;
-pa_context_exit_daemon;
-pa_context_get_autoload_info_by_index;
-pa_context_get_autoload_info_by_name;
-pa_context_get_autoload_info_list;
-pa_context_get_card_info_by_index;
-pa_context_get_card_info_by_name;
-pa_context_get_card_info_list;
-pa_context_get_client_info;
-pa_context_get_client_info_list;
-pa_context_get_index;
-pa_context_get_module_info;
-pa_context_get_module_info_list;
-pa_context_get_protocol_version;
-pa_context_get_sample_info_by_index;
-pa_context_get_sample_info_by_name;
-pa_context_get_sample_info_list;
-pa_context_get_server;
-pa_context_get_server_info;
-pa_context_get_server_protocol_version;
-pa_context_get_sink_info_by_index;
-pa_context_get_sink_info_by_name;
-pa_context_get_sink_info_list;
-pa_context_get_sink_input_info;
-pa_context_get_sink_input_info_list;
-pa_context_get_source_info_by_index;
-pa_context_get_source_info_by_name;
-pa_context_get_source_info_list;
-pa_context_get_source_output_info;
-pa_context_get_source_output_info_list;
-pa_context_set_port_latency_offset;
-pa_context_get_state;
-pa_context_get_tile_size;
-pa_context_is_local;
-pa_context_is_pending;
-pa_context_kill_client;
-pa_context_kill_sink_input;
-pa_context_kill_source_output;
-pa_context_load_cookie_from_file;
-pa_context_load_module;
-pa_context_move_sink_input_by_index;
-pa_context_move_sink_input_by_name;
-pa_context_move_source_output_by_index;
-pa_context_move_source_output_by_name;
-pa_context_new;
-pa_context_new_with_proplist;
-pa_context_play_sample;
-pa_context_play_sample_with_proplist;
-pa_context_proplist_remove;
-pa_context_proplist_update;
-pa_context_ref;
-pa_context_remove_autoload_by_index;
-pa_context_remove_autoload_by_name;
-pa_context_remove_sample;
-pa_context_rttime_new;
-pa_context_rttime_restart;
-pa_context_set_card_profile_by_index;
-pa_context_set_card_profile_by_name;
-pa_context_set_default_sink;
-pa_context_set_default_source;
-pa_context_set_event_callback;
-pa_context_set_name;
-pa_context_set_sink_input_mute;
-pa_context_set_sink_input_volume;
-pa_context_set_sink_mute_by_index;
-pa_context_set_sink_mute_by_name;
-pa_context_set_sink_port_by_index;
-pa_context_set_sink_port_by_name;
-pa_context_set_sink_volume_by_index;
-pa_context_set_sink_volume_by_name;
-pa_context_set_source_output_mute;
-pa_context_set_source_output_volume;
-pa_context_set_source_mute_by_index;
-pa_context_set_source_mute_by_name;
-pa_context_set_source_port_by_index;
-pa_context_set_source_port_by_name;
-pa_context_set_source_volume_by_index;
-pa_context_set_source_volume_by_name;
-pa_context_set_state_callback;
-pa_context_set_subscribe_callback;
-pa_context_stat;
-pa_context_subscribe;
-pa_context_suspend_sink_by_index;
-pa_context_suspend_sink_by_name;
-pa_context_suspend_source_by_index;
-pa_context_suspend_source_by_name;
-pa_context_unload_module;
-pa_context_unref;
-pa_cvolume_avg;
-pa_cvolume_avg_mask;
-pa_cvolume_channels_equal_to;
-pa_cvolume_compatible;
-pa_cvolume_compatible_with_channel_map;
-pa_cvolume_dec;
-pa_cvolume_equal;
-pa_cvolume_get_balance;
-pa_cvolume_get_fade;
-pa_cvolume_get_lfe_balance;
-pa_cvolume_get_position;
-pa_cvolume_inc;
-pa_cvolume_inc_clamp;
-pa_cvolume_init;
-pa_cvolume_max;
-pa_cvolume_max_mask;
-pa_cvolume_merge;
-pa_cvolume_min;
-pa_cvolume_min_mask;
-pa_cvolume_remap;
-pa_cvolume_scale;
-pa_cvolume_scale_mask;
-pa_cvolume_set;
-pa_cvolume_set_balance;
-pa_cvolume_set_fade;
-pa_cvolume_set_lfe_balance;
-pa_cvolume_set_position;
-pa_cvolume_snprint;
-pa_cvolume_snprint_verbose;
-pa_cvolume_valid;
-pa_direction_to_string;
-pa_direction_valid;
-pa_encoding_from_string;
-pa_encoding_to_string;
-pa_ext_device_manager_delete;
-pa_ext_device_manager_enable_role_device_priority_routing;
-pa_ext_device_manager_read;
-pa_ext_device_manager_reorder_devices_for_role;
-pa_ext_device_manager_set_device_description;
-pa_ext_device_manager_set_subscribe_cb;
-pa_ext_device_manager_subscribe;
-pa_ext_device_manager_test;
-pa_ext_device_restore_read_formats;
-pa_ext_device_restore_read_formats_all;
-pa_ext_device_restore_save_formats;
-pa_ext_device_restore_set_subscribe_cb;
-pa_ext_device_restore_subscribe;
-pa_ext_device_restore_test;
-pa_ext_stream_restore_delete;
-pa_ext_stream_restore_read;
-pa_ext_stream_restore_set_subscribe_cb;
-pa_ext_stream_restore_subscribe;
-pa_ext_stream_restore_test;
-pa_ext_stream_restore_write;
-pa_format_info_copy;
-pa_format_info_free;
-pa_format_info_from_string;
-pa_format_info_from_sample_spec;
-pa_format_info_get_prop_type;
-pa_format_info_get_prop_int;
-pa_format_info_get_prop_int_range;
-pa_format_info_get_prop_int_array;
-pa_format_info_get_prop_string;
-pa_format_info_get_prop_string_array;
-pa_format_info_free_string_array;
-pa_format_info_is_compatible;
-pa_format_info_is_pcm;
-pa_format_info_new;
-pa_format_info_set_channel_map;
-pa_format_info_set_channels;
-pa_format_info_set_prop_int;
-pa_format_info_set_prop_int_array;
-pa_format_info_set_prop_int_range;
-pa_format_info_set_prop_string;
-pa_format_info_set_prop_string_array;
-pa_format_info_set_rate;
-pa_format_info_set_sample_format;
-pa_format_info_snprint;
-pa_format_info_to_sample_spec;
-pa_format_info_valid;
-pa_frame_size;
-pa_get_binary_name;
-pa_get_fqdn;
-pa_get_home_dir;
-pa_get_host_name;
-pa_get_library_version;
-pa_gettimeofday;
-pa_get_user_name;
-pa_glib_mainloop_free;
-pa_glib_mainloop_get_api;
-pa_glib_mainloop_new;
-pa_locale_to_utf8;
-pa_mainloop_api_once;
-pa_mainloop_dispatch;
-pa_mainloop_free;
-pa_mainloop_get_api;
-pa_mainloop_get_retval;
-pa_mainloop_iterate;
-pa_mainloop_new;
-pa_mainloop_poll;
-pa_mainloop_prepare;
-pa_mainloop_quit;
-pa_mainloop_run;
-pa_mainloop_set_poll_func;
-pa_mainloop_wakeup;
-pa_msleep;
-pa_operation_cancel;
-pa_operation_get_state;
-pa_operation_ref;
-pa_operation_set_state_callback;
-pa_operation_unref;
-pa_parse_sample_format;
-pa_path_get_filename;
-pa_proplist_clear;
-pa_proplist_contains;
-pa_proplist_copy;
-pa_proplist_equal;
-pa_proplist_free;
-pa_proplist_from_string;
-pa_proplist_get;
-pa_proplist_gets;
-pa_proplist_isempty;
-pa_proplist_iterate;
-pa_proplist_key_valid;
-pa_proplist_new;
-pa_proplist_set;
-pa_proplist_setf;
-pa_proplist_setp;
-pa_proplist_sets;
-pa_proplist_size;
-pa_proplist_to_string;
-pa_proplist_to_string_sep;
-pa_proplist_unset;
-pa_proplist_unset_many;
-pa_proplist_update;
-pa_rtclock_now;
-pa_sample_format_is_be;
-pa_sample_format_is_le;
-pa_sample_format_to_string;
-pa_sample_format_valid;
-pa_sample_rate_valid;
-pa_sample_size;
-pa_sample_size_of_format;
-pa_sample_spec_equal;
-pa_sample_spec_init;
-pa_sample_spec_snprint;
-pa_sample_spec_valid;
-pa_signal_done;
-pa_signal_free;
-pa_signal_init;
-pa_signal_new;
-pa_signal_set_destroy;
-pa_simple_drain;
-pa_simple_flush;
-pa_simple_free;
-pa_simple_get_latency;
-pa_simple_new;
-pa_simple_read;
-pa_simple_write;
-pa_stream_begin_write;
-pa_stream_cancel_write;
-pa_stream_connect_playback;
-pa_stream_connect_record;
-pa_stream_connect_upload;
-pa_stream_cork;
-pa_stream_disconnect;
-pa_stream_drain;
-pa_stream_drop;
-pa_stream_finish_upload;
-pa_stream_flush;
-pa_stream_get_buffer_attr;
-pa_stream_get_channel_map;
-pa_stream_get_context;
-pa_stream_get_device_index;
-pa_stream_get_device_name;
-pa_stream_get_format_info;
-pa_stream_get_index;
-pa_stream_get_latency;
-pa_stream_get_monitor_stream;
-pa_stream_get_sample_spec;
-pa_stream_get_state;
-pa_stream_get_time;
-pa_stream_get_timing_info;
-pa_stream_get_underflow_index;
-pa_stream_is_corked;
-pa_stream_is_suspended;
-pa_stream_new;
-pa_stream_new_extended;
-pa_stream_new_with_proplist;
-pa_stream_peek;
-pa_stream_prebuf;
-pa_stream_proplist_remove;
-pa_stream_proplist_update;
-pa_stream_readable_size;
-pa_stream_ref;
-pa_stream_set_buffer_attr;
-pa_stream_set_buffer_attr_callback;
-pa_stream_set_event_callback;
-pa_stream_set_latency_update_callback;
-pa_stream_set_monitor_stream;
-pa_stream_set_moved_callback;
-pa_stream_set_name;
-pa_stream_set_overflow_callback;
-pa_stream_set_read_callback;
-pa_stream_set_started_callback;
-pa_stream_set_state_callback;
-pa_stream_set_suspended_callback;
-pa_stream_set_underflow_callback;
-pa_stream_set_write_callback;
-pa_stream_trigger;
-pa_stream_unref;
-pa_stream_update_sample_rate;
-pa_stream_update_timing_info;
-pa_stream_writable_size;
-pa_stream_write;
-pa_stream_write_ext_free;
-pa_strerror;
-pa_sw_cvolume_divide;
-pa_sw_cvolume_divide_scalar;
-pa_sw_cvolume_multiply;
-pa_sw_cvolume_multiply_scalar;
-pa_sw_cvolume_snprint_dB;
-pa_sw_volume_divide;
-pa_sw_volume_from_dB;
-pa_sw_volume_from_linear;
-pa_sw_volume_multiply;
-pa_sw_volume_snprint_dB;
-pa_sw_volume_to_dB;
-pa_sw_volume_to_linear;
-pa_threaded_mainloop_accept;
-pa_threaded_mainloop_free;
-pa_threaded_mainloop_get_api;
-pa_threaded_mainloop_get_retval;
-pa_threaded_mainloop_in_thread;
-pa_threaded_mainloop_lock;
-pa_threaded_mainloop_new;
-pa_threaded_mainloop_set_name;
-pa_threaded_mainloop_signal;
-pa_threaded_mainloop_start;
-pa_threaded_mainloop_stop;
-pa_threaded_mainloop_unlock;
-pa_threaded_mainloop_wait;
-pa_timeval_add;
-pa_timeval_age;
-pa_timeval_cmp;
-pa_timeval_diff;
-pa_timeval_load;
-pa_timeval_store;
-pa_timeval_sub;
-pa_usec_to_bytes;
-pa_utf8_filter;
-pa_utf8_to_locale;
-pa_utf8_valid;
-pa_volume_snprint;
-pa_volume_snprint_verbose;
-pa_xfree;
-pa_xmalloc;
-pa_xmalloc0;
-pa_xmemdup;
-pa_xrealloc;
-pa_xstrdup;
-pa_xstrndup;
-local:
-*;
-};
diff --git a/pipewire-pulseaudio/src/meson.build b/pipewire-pulseaudio/src/meson.build
deleted file mode 100644
index 1a2d0b68d..000000000
--- a/pipewire-pulseaudio/src/meson.build
+++ /dev/null
@@ -1,103 +0,0 @@
-pipewire_pulseaudio_sources = [
- 'bitset.c',
- 'channelmap.c',
- 'context.c',
- 'core-format.c',
- 'direction.c',
- 'error.c',
- 'ext-device-manager.c',
- 'ext-device-restore.c',
- 'ext-stream-restore.c',
- 'format.c',
- 'introspect.c',
- 'json.c',
- 'mainloop.c',
- 'mainloop-signal.c',
- 'operation.c',
- 'proplist.c',
- 'rtclock.c',
- 'sample.c',
- 'scache.c',
- 'stream.c',
- 'strbuf.c',
- 'subscribe.c',
- 'thread-mainloop.c',
- 'timeval.c',
- 'utf8.c',
- 'util.c',
- 'version.c',
- 'volume.c',
- 'xmalloc.c',
- 'pipewire-pulseaudio.c',
-]
-
-pipewire_mainloop_glib_sources = [
- 'mainloop-glib.c',
-]
-
-pipewire_simple_sources = [
- 'simple.c',
-]
-
-pipewire_pulseaudio_c_args = [
- '-DHAVE_CONFIG_H',
- '-D_GNU_SOURCE',
- '-DPIC',
-]
-
-mapfile = 'map-file'
-vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
-
-libpulse_path = get_option('libpulse-path')
-if libpulse_path == ''
- libpulse_path = join_paths(modules_install_dir, 'pulse')
- libpulse_path_dlopen = join_paths(modules_install_dir_dlopen, 'pulse')
-else
- libpulse_path_dlopen = libpulse_path
-endif
-
-tools_config = configuration_data()
-tools_config.set('LIBPULSE_PATH', libpulse_path_dlopen)
-
-configure_file(input : 'pw-pulse.in',
- output : 'pw-pulse',
- configuration : tools_config,
- install_dir : pipewire_bindir)
-
-pipewire_pulse = shared_library('pulse',
- pipewire_pulseaudio_sources,
- soversion : soversion,
- version : libversion,
- c_args : pipewire_pulseaudio_c_args,
- link_args : vflag,
- include_directories : [configinc],
- dependencies : [pipewire_dep, pulseaudio_dep, mathlib],
- install : true,
- install_dir : libpulse_path,
-)
-
-pipewire_pulse_mainloop_glib = shared_library('pulse-mainloop-glib',
- pipewire_mainloop_glib_sources,
- soversion : soversion,
- version : libversion,
- c_args : pipewire_pulseaudio_c_args,
- link_args : vflag,
- include_directories : [configinc],
- dependencies : [pipewire_dep, pulseaudio_dep, mathlib, glib_dep],
- install : true,
- install_rpath : libpulse_path_dlopen,
- install_dir : libpulse_path,
-)
-
-pipewire_pulse_simple = shared_library('pulse-simple',
- pipewire_simple_sources,
- soversion : soversion,
- version : libversion,
- c_args : pipewire_pulseaudio_c_args,
- link_args : vflag,
- include_directories : [configinc],
- dependencies : [pipewire_dep, pulseaudio_dep, mathlib, glib_dep],
- install : true,
- install_rpath : libpulse_path_dlopen,
- install_dir : libpulse_path,
-)
diff --git a/pipewire-pulseaudio/src/operation.c b/pipewire-pulseaudio/src/operation.c
deleted file mode 100644
index 99c343601..000000000
--- a/pipewire-pulseaudio/src/operation.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include
-
-#include
-
-#include "internal.h"
-
-pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, size_t userdata_size) {
- pa_operation *o;
- pa_assert(c);
-
- o = calloc(1, sizeof(pa_operation) + userdata_size);
-
- o->refcount = 1;
- o->context = c;
- o->stream = s ? pa_stream_ref(s) : NULL;
-
- o->state = PA_OPERATION_RUNNING;
- o->callback = cb;
- o->userdata = SPA_MEMBER(o, sizeof(pa_operation), void);
-
- spa_list_append(&c->operations, &o->link);
- pa_operation_ref(o);
- pw_log_debug("new %p", o);
-
- return o;
-}
-
-int pa_operation_sync(pa_operation *o)
-{
- pa_context *c = o->context;
- if (c->core != NULL)
- c->pending_seq = pw_core_sync(c->core, PW_ID_CORE, 0);
- o->sync = true;
- pw_log_debug("operation %p: sync seq:%d", o, c->pending_seq);
- return 0;
-}
-
-SPA_EXPORT
-pa_operation *pa_operation_ref(pa_operation *o)
-{
- pa_assert(o);
- pa_assert(o->refcount >= 1);
- o->refcount++;
- return o;
-}
-
-static void operation_free(pa_operation *o)
-{
- pa_assert(!o->context);
- pa_assert(!o->stream);
- pw_log_debug("%p", o);
- free(o);
-}
-
-static void operation_unlink(pa_operation *o) {
- pa_assert(o);
-
- pw_log_debug("%p", o);
- if (o->context) {
- pa_assert(o->refcount >= 2);
-
- spa_list_remove(&o->link);
- pa_operation_unref(o);
-
- o->context = NULL;
- }
- if (o->stream)
- pa_stream_unref(o->stream);
- o->stream = NULL;
- o->callback = NULL;
- o->userdata = NULL;
- o->state_callback = NULL;
- o->state_userdata = NULL;
-}
-
-SPA_EXPORT
-void pa_operation_unref(pa_operation *o)
-{
- pa_assert(o);
- pa_assert(o->refcount >= 1);
- pw_log_debug("%p ref:%d", o, o->refcount);
- if (--o->refcount == 0)
- operation_free(o);
-}
-
-static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
- pa_assert(o);
- pa_assert(o->refcount >= 1);
-
- if (st == o->state)
- return;
-
- pa_operation_ref(o);
-
- pw_log_debug("new state %p state:%d", o, st);
- o->state = st;
-
- if (o->state_callback)
- o->state_callback(o, o->state_userdata);
-
- if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED))
- operation_unlink(o);
-
- pa_operation_unref(o);
-}
-
-
-SPA_EXPORT
-void pa_operation_cancel(pa_operation *o)
-{
- pa_assert(o);
- pa_assert(o->refcount >= 1);
- pw_log_debug("%p", o);
- operation_set_state(o, PA_OPERATION_CANCELED);
-}
-
-void pa_operation_done(pa_operation *o) {
- pa_assert(o);
- pa_assert(o->refcount >= 1);
- operation_set_state(o, PA_OPERATION_DONE);
-}
-
-
-SPA_EXPORT
-pa_operation_state_t pa_operation_get_state(PA_CONST pa_operation *o)
-{
- pa_assert(o);
- pa_assert(o->refcount >= 1);
- return o->state;
-}
-
-SPA_EXPORT
-void pa_operation_set_state_callback(pa_operation *o, pa_operation_notify_cb_t cb, void *userdata)
-{
- pa_assert(o);
- pa_assert(o->refcount >= 1);
-
- if (o->state == PA_OPERATION_DONE || o->state == PA_OPERATION_CANCELED)
- return;
-
- o->state_callback = cb;
- o->state_userdata = userdata;
-}
diff --git a/pipewire-pulseaudio/src/pipewire-pulseaudio.c b/pipewire-pulseaudio/src/pipewire-pulseaudio.c
deleted file mode 100644
index 3b3405984..000000000
--- a/pipewire-pulseaudio/src/pipewire-pulseaudio.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include
-
-static void reg(void) __attribute__ ((constructor));
-static void reg(void)
-{
- pw_init(NULL, NULL);
-}
diff --git a/pipewire-pulseaudio/src/proplist.c b/pipewire-pulseaudio/src/proplist.c
deleted file mode 100644
index 79010c30a..000000000
--- a/pipewire-pulseaudio/src/proplist.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include
-#include
-
-#include
-
-#include "internal.h"
-#include "strbuf.h"
-
-struct pa_proplist {
- struct pw_properties *props;
-};
-
-int pa_proplist_update_dict(pa_proplist *p, struct spa_dict *dict)
-{
- const struct spa_dict_item *item;
- spa_dict_for_each(item, dict)
- pa_proplist_sets(p, item->key, item->value);
- return 0;
-}
-
-pa_proplist* pa_proplist_new_dict(struct spa_dict *dict)
-{
- pa_proplist *p;
-
- p = pa_proplist_new();
- if (p == NULL)
- return NULL;
-
- pa_proplist_update_dict(p, dict);
-
- return p;
-}
-pa_proplist* pa_proplist_new_props(struct pw_properties *props)
-{
- return pa_proplist_new_dict(&props->dict);
-}
-
-SPA_EXPORT
-pa_proplist* pa_proplist_new(void)
-{
- pa_proplist *p;
-
- p = calloc(1, sizeof(struct pa_proplist));
- if (p == NULL)
- return NULL;
-
- p->props = pw_properties_new(NULL, NULL);
-
- return p;
-}
-
-SPA_EXPORT
-void pa_proplist_free(pa_proplist* p)
-{
- pw_properties_free(p->props);
- free(p);
-}
-
-SPA_EXPORT
-int pa_proplist_key_valid(const char *key)
-{
- const char *p;
- for (p = key; *p; p++)
- if ((unsigned char) *p >= 128)
- return 0;
-
- if (strlen(key) < 1)
- return 0;
-
- return 1;
-}
-
-SPA_EXPORT
-int pa_proplist_sets(pa_proplist *p, const char *key, const char *value)
-{
- pa_assert(p);
- pa_assert(key);
- pa_assert(value);
-
- if (!pa_proplist_key_valid(key))
- return -1;
-
- pw_properties_set(p->props, key, value);
- return 0;
-}
-
-SPA_EXPORT
-int pa_proplist_setp(pa_proplist *p, const char *pair)
-{
- const char *t;
- char *c;
- int idx;
-
- pa_assert(p);
- pa_assert(pair);
-
- if (!(t = strchr(pair, '=')))
- return -1;
-
- idx = pair - t;
- c = strdup(pair);
- c[idx] = 0;
- pa_proplist_sets(p, c, &c[idx]+1);
- free(c);
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_proplist_setf(pa_proplist *p, const char *key, const char *format, ...)
-{
- va_list varargs;
-
- va_start(varargs, format);
- pw_properties_setva(p->props, key, format, varargs);
- va_end(varargs);
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nbytes)
-{
- pa_assert(p);
- pa_assert(key);
- pa_assert(data || nbytes == 0);
-
- if (!pa_proplist_key_valid(key))
- return -1;
-
- pw_properties_set(p->props, key, data);
- return 0;
-}
-
-SPA_EXPORT
-const char *pa_proplist_gets(PA_CONST pa_proplist *p, const char *key)
-{
- return pw_properties_get(p->props, key);
-}
-
-SPA_EXPORT
-int pa_proplist_get(PA_CONST pa_proplist *p, const char *key, const void **data, size_t *nbytes)
-{
- const char *val;
-
- spa_assert(p);
- spa_assert(key);
-
- val = pw_properties_get(p->props, key);
-
- *data = val;
- *nbytes = val ? strlen(val) : 0;
- return 0;
-}
-
-SPA_EXPORT
-void pa_proplist_update(pa_proplist *p, pa_update_mode_t mode, const pa_proplist *other)
-{
- uint32_t i;
-
- spa_assert(p);
- spa_assert(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE);
- spa_assert(other);
-
- if (mode == PA_UPDATE_REPLACE) {
- pa_proplist_update_dict(p, &other->props->dict);
- return;
- }
-
- if (mode == PA_UPDATE_SET)
- pa_proplist_clear(p);
-
- for (i = 0; i < other->props->dict.n_items; i++) {
- const struct spa_dict_item *oi;
-
- oi = &other->props->dict.items[i];
- if (pw_properties_get(p->props, oi->key) == NULL)
- pw_properties_set(p->props, oi->key, oi->value);
- }
-}
-
-SPA_EXPORT
-int pa_proplist_unset(pa_proplist *p, const char *key)
-{
- spa_assert(p);
- spa_assert(key);
-
- if (!pa_proplist_key_valid(key))
- return -1;
-
- return pw_properties_set(p->props, key, NULL);
-}
-
-SPA_EXPORT
-int pa_proplist_unset_many(pa_proplist *p, const char * const keys[])
-{
- const char * const * k;
- int n = 0;
-
- spa_assert(p);
- spa_assert(keys);
-
- for (k = keys; *k; k++)
- if (!pa_proplist_key_valid(*k))
- return -1;
-
- for (k = keys; *k; k++)
- if (pa_proplist_unset(p, *k) >= 0)
- n++;
- return n;
-}
-
-SPA_EXPORT
-const char *pa_proplist_iterate(PA_CONST pa_proplist *p, void **state)
-{
- spa_assert(p);
- spa_assert(state);
- return pw_properties_iterate(p->props, state);
-}
-
-SPA_EXPORT
-char *pa_proplist_to_string(PA_CONST pa_proplist *p)
-{
- spa_assert(p);
- return pa_proplist_to_string_sep(p, ",");
-}
-
-SPA_EXPORT
-char *pa_proplist_to_string_sep(PA_CONST pa_proplist *p, const char *sep)
-{
- const char *key;
- void *state = NULL;
- pa_strbuf *buf;
-
- spa_assert(p);
- spa_assert(sep);
-
- buf = pa_strbuf_new();
-
- while ((key = pa_proplist_iterate(p, &state))) {
- const char *v;
- const char *t;
-
- if (!pa_strbuf_isempty(buf))
- pa_strbuf_puts(buf, sep);
-
- if ((v = pa_proplist_gets(p, key)) == NULL)
- continue;
-
- pa_strbuf_printf(buf, "%s = \"", key);
-
- for (t = v;;) {
- size_t h;
-
- h = strcspn(t, "\"");
-
- if (h > 0)
- pa_strbuf_putsn(buf, t, h);
-
- t += h;
-
- if (*t == 0)
- break;
-
- pa_assert(*t == '"');
- pa_strbuf_puts(buf, "\\\"");
-
- t++;
- }
- pa_strbuf_puts(buf, "\"");
- }
- return pa_strbuf_to_string_free(buf);
-}
-
-SPA_EXPORT
-pa_proplist *pa_proplist_from_string(const char *str)
-{
- spa_assert(str);
- pw_log_warn("Not Implemented");
- return NULL;
-}
-
-SPA_EXPORT
-int pa_proplist_contains(PA_CONST pa_proplist *p, const char *key)
-{
- spa_assert(p);
- spa_assert(key);
-
- if (!pa_proplist_key_valid(key))
- return -1;
-
- if (pw_properties_get(p->props, key) == NULL)
- return 0;
-
- return 1;
-}
-
-SPA_EXPORT
-void pa_proplist_clear(pa_proplist *p)
-{
- spa_assert(p);
- pw_properties_clear(p->props);
-}
-
-SPA_EXPORT
-pa_proplist* pa_proplist_copy(const pa_proplist *p)
-{
- pa_proplist *c;
-
- spa_assert(p);
-
- c = calloc(1, sizeof(struct pa_proplist));
- if (c == NULL)
- return NULL;
-
- c->props = pw_properties_copy(p->props);
- return c;
-}
-
-SPA_EXPORT
-unsigned pa_proplist_size(PA_CONST pa_proplist *p)
-{
- spa_assert(p);
- return p->props->dict.n_items;
-}
-
-SPA_EXPORT
-int pa_proplist_isempty(PA_CONST pa_proplist *p)
-{
- spa_assert(p);
- return p->props->dict.n_items == 0 ? 1 : 0;
-}
-
-SPA_EXPORT
-int pa_proplist_equal(PA_CONST pa_proplist *a, PA_CONST pa_proplist *b)
-{
- uint32_t i;
-
- spa_assert(a);
- spa_assert(b);
-
- if (a == b)
- return 1;
-
- if (pa_proplist_size(a) != pa_proplist_size(b))
- return 0;
-
- for (i = 0; i < a->props->dict.n_items; i++) {
- const struct spa_dict_item *ai, *bi;
-
- ai = &a->props->dict.items[i];
- bi = spa_dict_lookup_item(&b->props->dict, ai->key);
-
- if (bi == NULL || bi->value == NULL || ai->value == NULL)
- return 0;
- if (strcmp(ai->value, bi->value) != 0)
- return 0;
- }
- return 1;
-}
-
-
-int pw_properties_update_proplist(struct pw_properties *props,
- PA_CONST pa_proplist *p)
-{
- void *state = NULL;
- const char *key, *val;
- int changed = 0;
-
- while (true) {
- key = pa_proplist_iterate(p, &state);
- if (key == NULL)
- break;
-
- val = pa_proplist_gets(p, key);
- if (val == NULL)
- continue;
-
- changed += pw_properties_set(props, key, val);
- }
- return changed;
-}
diff --git a/pipewire-pulseaudio/src/pw-pulse.in b/pipewire-pulseaudio/src/pw-pulse.in
deleted file mode 100755
index a8c470bba..000000000
--- a/pipewire-pulseaudio/src/pw-pulse.in
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-
-# This file is part of PipeWire.
-#
-# Copyright © 2020 Wim Taymans
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice (including the next
-# paragraph) shall be included in all copies or substantial portions of the
-# Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-#
-while getopts 'hr:v' param ; do
- case $param in
- r)
- PIPEWIRE_REMOTE="$OPTARG"
- export PIPEWIRE_REMOTE
- ;;
- v)
- if [ x"$PIPEWIRE_DEBUG" = x ]; then
- PIPEWIRE_DEBUG=3
- else
- PIPEWIRE_DEBUG=$(( $PIPEWIRE_DEBUG + 1 ))
- fi
- export PIPEWIRE_DEBUG
- ;;
- *)
- echo "$0 - run PulseAudio applications on PipeWire"
- echo " "
- echo "$0 [options] application [arguments]"
- echo " "
- echo "options:"
- echo " -h show brief help"
- echo " -r remote daemon name"
- echo " -v verbose debug info"
- exit 0
- ;;
- esac
-done
-
-shift $(( $OPTIND - 1 ))
-
-LD_LIBRARY_PATH='@LIBPULSE_PATH@'"${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}"
-export LD_LIBRARY_PATH
-
-exec "$@"
diff --git a/pipewire-pulseaudio/src/rtclock.c b/pipewire-pulseaudio/src/rtclock.c
deleted file mode 100644
index 0851083f9..000000000
--- a/pipewire-pulseaudio/src/rtclock.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include
-
-#include
-#include
-#include "internal.h"
-
-SPA_EXPORT
-pa_usec_t pa_rtclock_now(void)
-{
- struct timespec ts;
- pa_usec_t res;
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
- res = (ts.tv_sec * SPA_USEC_PER_SEC) + (ts.tv_nsec / SPA_NSEC_PER_USEC);
- return res;
-}
-
-static struct timeval *pa_rtclock_get(struct timeval *tv)
-{
- struct timespec ts;
-
- pa_assert(tv);
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
- tv->tv_sec = ts.tv_sec;
- tv->tv_usec = ts.tv_nsec / PA_NSEC_PER_USEC;
- return tv;
-}
-
-struct timeval* pa_rtclock_from_wallclock(struct timeval *tv)
-{
- struct timeval wc_now, rt_now;
-
- pa_assert(tv);
-
- pa_gettimeofday(&wc_now);
- pa_rtclock_get(&rt_now);
-
- if (pa_timeval_cmp(&wc_now, tv) < 0)
- pa_timeval_add(&rt_now, pa_timeval_diff(tv, &wc_now));
- else
- pa_timeval_sub(&rt_now, pa_timeval_diff(&wc_now, tv));
-
- *tv = rt_now;
-
- return tv;
-}
-
-struct timeval* pa_rtclock_to_wallclock(struct timeval *tv)
-{
- struct timeval wc_now, rt_now;
-
- pa_assert(tv);
-
- pa_gettimeofday(&wc_now);
- pa_rtclock_get(&rt_now);
-
- if (pa_timeval_cmp(&rt_now, tv) < 0)
- pa_timeval_add(&wc_now, pa_timeval_diff(tv, &rt_now));
- else
- pa_timeval_sub(&wc_now, pa_timeval_diff(&rt_now, tv));
-
- *tv = wc_now;
-
- return tv;
-}
-
-struct timeval* pa_timeval_rtstore(struct timeval *tv, pa_usec_t v, bool rtclock)
-{
- pa_assert(tv);
-
- if (v == PA_USEC_INVALID)
- return NULL;
-
- pa_timeval_store(tv, v);
-
- if (rtclock)
- tv->tv_usec |= PA_TIMEVAL_RTCLOCK;
- else
- pa_rtclock_to_wallclock(tv);
-
- return tv;
-}
diff --git a/pipewire-pulseaudio/src/sample-util.h b/pipewire-pulseaudio/src/sample-util.h
deleted file mode 100644
index 45528ef6d..000000000
--- a/pipewire-pulseaudio/src/sample-util.h
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef foosampleutilhfoo
-#define foosampleutilhfoo
-
-/***
- This file is part of PulseAudio.
-
- Copyright 2004-2006 Lennart Poettering
- Copyright 2006 Pierre Ossman for Cendio AB
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-size_t pa_frame_align(size_t l, const pa_sample_spec *ss) PA_GCC_PURE;
-
-bool pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE;
-
-void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n);
-void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n);
-
-void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n);
-
-static inline int32_t pa_mult_s16_volume(int16_t v, int32_t cv) {
-#ifdef HAVE_FAST_64BIT_OPERATIONS
- /* Multiply with 64 bit integers on 64 bit platforms */
- return (v * (int64_t) cv) >> 16;
-#else
- /* Multiplying the 32 bit volume factor with the
- * 16 bit sample might result in an 48 bit value. We
- * want to do without 64 bit integers and hence do
- * the multiplication independently for the HI and
- * LO part of the volume. */
-
- int32_t hi = cv >> 16;
- int32_t lo = cv & 0xFFFF;
- return ((v * lo) >> 16) + (v * hi);
-#endif
-}
-
-pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec);
-size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec);
-
-typedef void (*pa_do_volume_func_t) (void *samples, const void *volumes, unsigned channels, unsigned length);
-
-pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f);
-void pa_set_volume_func(pa_sample_format_t f, pa_do_volume_func_t func);
-
-size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to);
-
-#define PA_CHANNEL_POSITION_MASK_LEFT \
- (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_LEFT)) \
-
-#define PA_CHANNEL_POSITION_MASK_RIGHT \
- (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_RIGHT))
-
-#define PA_CHANNEL_POSITION_MASK_CENTER \
- (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_CENTER))
-
-#define PA_CHANNEL_POSITION_MASK_FRONT \
- (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_CENTER))
-
-#define PA_CHANNEL_POSITION_MASK_REAR \
- (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_CENTER))
-
-#define PA_CHANNEL_POSITION_MASK_LFE \
- PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_LFE)
-
-#define PA_CHANNEL_POSITION_MASK_HFE \
- (PA_CHANNEL_POSITION_MASK_REAR | PA_CHANNEL_POSITION_MASK_FRONT \
- | PA_CHANNEL_POSITION_MASK_LEFT | PA_CHANNEL_POSITION_MASK_RIGHT \
- | PA_CHANNEL_POSITION_MASK_CENTER)
-
-#define PA_CHANNEL_POSITION_MASK_SIDE_OR_TOP_CENTER \
- (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_CENTER))
-
-#define PA_CHANNEL_POSITION_MASK_TOP \
- (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_CENTER) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_LEFT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_RIGHT) \
- | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_CENTER))
-
-#define PA_CHANNEL_POSITION_MASK_ALL \
- ((pa_channel_position_mask_t) (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_MAX)-1))
-
-#endif
diff --git a/pipewire-pulseaudio/src/sample.c b/pipewire-pulseaudio/src/sample.c
deleted file mode 100644
index 07e903219..000000000
--- a/pipewire-pulseaudio/src/sample.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2004-2006 Lennart Poettering
- Copyright 2006 Pierre Ossman for Cendio AB
- Copyright 2018 Wim Taymans
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-#include
-
-#include
-
-#include
-#include
-
-#define pa_init_i18n()
-#define _(String) (String)
-
-static const size_t size_table[] = {
- [PA_SAMPLE_U8] = 1,
- [PA_SAMPLE_ULAW] = 1,
- [PA_SAMPLE_ALAW] = 1,
- [PA_SAMPLE_S16LE] = 2,
- [PA_SAMPLE_S16BE] = 2,
- [PA_SAMPLE_FLOAT32LE] = 4,
- [PA_SAMPLE_FLOAT32BE] = 4,
- [PA_SAMPLE_S32LE] = 4,
- [PA_SAMPLE_S32BE] = 4,
- [PA_SAMPLE_S24LE] = 3,
- [PA_SAMPLE_S24BE] = 3,
- [PA_SAMPLE_S24_32LE] = 4,
- [PA_SAMPLE_S24_32BE] = 4
-};
-
-SPA_EXPORT
-size_t pa_sample_size_of_format(pa_sample_format_t f)
-{
- spa_assert(pa_sample_format_valid(f));
-
- return size_table[f];
-}
-
-SPA_EXPORT
-size_t pa_sample_size(const pa_sample_spec * spec)
-{
- spa_assert(spec);
- spa_assert(pa_sample_spec_valid(spec));
-
- return size_table[spec->format];
-}
-
-SPA_EXPORT
-size_t pa_frame_size(const pa_sample_spec * spec)
-{
- spa_assert(spec);
- spa_assert(pa_sample_spec_valid(spec));
-
- return size_table[spec->format] * spec->channels;
-}
-
-SPA_EXPORT
-size_t pa_bytes_per_second(const pa_sample_spec * spec)
-{
- spa_assert(spec);
- spa_assert(pa_sample_spec_valid(spec));
-
- return spec->rate * size_table[spec->format] * spec->channels;
-}
-
-SPA_EXPORT
-pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec * spec)
-{
- spa_assert(spec);
- spa_assert(pa_sample_spec_valid(spec));
-
- return (((pa_usec_t)
- (length / (size_table[spec->format] * spec->channels))
- * PA_USEC_PER_SEC) / spec->rate);
-}
-
-SPA_EXPORT
-size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec * spec)
-{
- spa_assert(spec);
- spa_assert(pa_sample_spec_valid(spec));
-
- return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) *
- (size_table[spec->format] * spec->channels);
-}
-
-SPA_EXPORT
-pa_sample_spec *pa_sample_spec_init(pa_sample_spec * spec)
-{
- spa_assert(spec);
-
- spec->format = PA_SAMPLE_INVALID;
- spec->rate = 0;
- spec->channels = 0;
-
- return spec;
-}
-
-SPA_EXPORT
-int pa_sample_format_valid(unsigned format)
-{
- return format < PA_SAMPLE_MAX;
-}
-
-SPA_EXPORT
-int pa_sample_rate_valid(uint32_t rate)
-{
- /* The extra 1% is due to module-loopback: it temporarily sets
- * a higher-than-nominal rate to get rid of excessive buffer
- * latency */
- return rate > 0 && rate <= PA_RATE_MAX * 101 / 100;
-}
-
-SPA_EXPORT
-int pa_channels_valid(uint8_t channels)
-{
- return channels > 0 && channels <= PA_CHANNELS_MAX;
-}
-
-SPA_EXPORT
-int pa_sample_spec_valid(const pa_sample_spec * spec)
-{
- spa_assert(spec);
-
- if (SPA_UNLIKELY(!pa_sample_rate_valid(spec->rate) ||
- !pa_channels_valid(spec->channels) ||
- !pa_sample_format_valid(spec->format)))
- return 0;
-
- return 1;
-}
-
-SPA_EXPORT
-int pa_sample_spec_equal(const pa_sample_spec * a, const pa_sample_spec * b)
-{
- spa_assert(a);
- spa_assert(b);
-
- spa_return_val_if_fail(pa_sample_spec_valid(a), 0);
-
- if (SPA_UNLIKELY(a == b))
- return 1;
-
- spa_return_val_if_fail(pa_sample_spec_valid(b), 0);
-
- return
- (a->format == b->format) &&
- (a->rate == b->rate) && (a->channels == b->channels);
-}
-
-SPA_EXPORT
-const char *pa_sample_format_to_string(pa_sample_format_t f)
-{
- static const char *const table[] = {
- [PA_SAMPLE_U8] = "u8",
- [PA_SAMPLE_ALAW] = "aLaw",
- [PA_SAMPLE_ULAW] = "uLaw",
- [PA_SAMPLE_S16LE] = "s16le",
- [PA_SAMPLE_S16BE] = "s16be",
- [PA_SAMPLE_FLOAT32LE] = "float32le",
- [PA_SAMPLE_FLOAT32BE] = "float32be",
- [PA_SAMPLE_S32LE] = "s32le",
- [PA_SAMPLE_S32BE] = "s32be",
- [PA_SAMPLE_S24LE] = "s24le",
- [PA_SAMPLE_S24BE] = "s24be",
- [PA_SAMPLE_S24_32LE] = "s24-32le",
- [PA_SAMPLE_S24_32BE] = "s24-32be",
- };
-
- if (!pa_sample_format_valid(f))
- return NULL;
-
- return table[f];
-}
-
-SPA_EXPORT
-char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec * spec)
-{
- spa_assert(s);
- spa_assert(l > 0);
- spa_assert(spec);
-
- pa_init_i18n();
-
- if (!pa_sample_spec_valid(spec))
- snprintf(s, l, _("(invalid)"));
- else
- snprintf(s, l, _("%s %uch %uHz"),
- pa_sample_format_to_string(spec->format),
- spec->channels, spec->rate);
-
- return s;
-}
-
-SPA_EXPORT
-char *pa_bytes_snprint(char *s, size_t l, unsigned v)
-{
- spa_assert(s);
- spa_assert(l > 0);
-
- pa_init_i18n();
-
- if (v >= ((unsigned)1024) * 1024 * 1024)
- snprintf(s, l, _("%0.1f GiB"),
- ((double)v) / 1024 / 1024 / 1024);
- else if (v >= ((unsigned)1024) * 1024)
- snprintf(s, l, _("%0.1f MiB"), ((double)v) / 1024 / 1024);
- else if (v >= (unsigned)1024)
- snprintf(s, l, _("%0.1f KiB"), ((double)v) / 1024);
- else
- snprintf(s, l, _("%u B"), (unsigned)v);
-
- return s;
-}
-
-SPA_EXPORT
-pa_sample_format_t pa_parse_sample_format(const char *format)
-{
- spa_assert(format);
-
- if (strcasecmp(format, "s16le") == 0)
- return PA_SAMPLE_S16LE;
- else if (strcasecmp(format, "s16be") == 0)
- return PA_SAMPLE_S16BE;
- else if (strcasecmp(format, "s16ne") == 0
- || strcasecmp(format, "s16") == 0
- || strcasecmp(format, "16") == 0)
- return PA_SAMPLE_S16NE;
- else if (strcasecmp(format, "s16re") == 0)
- return PA_SAMPLE_S16RE;
- else if (strcasecmp(format, "u8") == 0 || strcasecmp(format, "8") == 0)
- return PA_SAMPLE_U8;
- else if (strcasecmp(format, "float32") == 0
- || strcasecmp(format, "float32ne") == 0
- || strcasecmp(format, "float") == 0)
- return PA_SAMPLE_FLOAT32NE;
- else if (strcasecmp(format, "float32re") == 0)
- return PA_SAMPLE_FLOAT32RE;
- else if (strcasecmp(format, "float32le") == 0)
- return PA_SAMPLE_FLOAT32LE;
- else if (strcasecmp(format, "float32be") == 0)
- return PA_SAMPLE_FLOAT32BE;
- else if (strcasecmp(format, "ulaw") == 0
- || strcasecmp(format, "mulaw") == 0)
- return PA_SAMPLE_ULAW;
- else if (strcasecmp(format, "alaw") == 0)
- return PA_SAMPLE_ALAW;
- else if (strcasecmp(format, "s32le") == 0)
- return PA_SAMPLE_S32LE;
- else if (strcasecmp(format, "s32be") == 0)
- return PA_SAMPLE_S32BE;
- else if (strcasecmp(format, "s32ne") == 0
- || strcasecmp(format, "s32") == 0
- || strcasecmp(format, "32") == 0)
- return PA_SAMPLE_S32NE;
- else if (strcasecmp(format, "s32re") == 0)
- return PA_SAMPLE_S24RE;
- else if (strcasecmp(format, "s24le") == 0)
- return PA_SAMPLE_S24LE;
- else if (strcasecmp(format, "s24be") == 0)
- return PA_SAMPLE_S24BE;
- else if (strcasecmp(format, "s24ne") == 0
- || strcasecmp(format, "s24") == 0
- || strcasecmp(format, "24") == 0)
- return PA_SAMPLE_S24NE;
- else if (strcasecmp(format, "s24re") == 0)
- return PA_SAMPLE_S24RE;
- else if (strcasecmp(format, "s24-32le") == 0)
- return PA_SAMPLE_S24_32LE;
- else if (strcasecmp(format, "s24-32be") == 0)
- return PA_SAMPLE_S24_32BE;
- else if (strcasecmp(format, "s24-32ne") == 0
- || strcasecmp(format, "s24-32") == 0)
- return PA_SAMPLE_S24_32NE;
- else if (strcasecmp(format, "s24-32re") == 0)
- return PA_SAMPLE_S24_32RE;
-
- return PA_SAMPLE_INVALID;
-}
-
-SPA_EXPORT
-int pa_sample_format_is_le(pa_sample_format_t f)
-{
- spa_assert(pa_sample_format_valid(f));
-
- switch (f) {
- case PA_SAMPLE_S16LE:
- case PA_SAMPLE_S24LE:
- case PA_SAMPLE_S32LE:
- case PA_SAMPLE_S24_32LE:
- case PA_SAMPLE_FLOAT32LE:
- return 1;
-
- case PA_SAMPLE_S16BE:
- case PA_SAMPLE_S24BE:
- case PA_SAMPLE_S32BE:
- case PA_SAMPLE_S24_32BE:
- case PA_SAMPLE_FLOAT32BE:
- return 0;
-
- default:
- return -1;
- }
-}
-
-SPA_EXPORT
-int pa_sample_format_is_be(pa_sample_format_t f)
-{
- int r;
-
- if ((r = pa_sample_format_is_le(f)) < 0)
- return r;
-
- return !r;
-}
diff --git a/pipewire-pulseaudio/src/scache.c b/pipewire-pulseaudio/src/scache.c
deleted file mode 100644
index 0feeb78bc..000000000
--- a/pipewire-pulseaudio/src/scache.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include "internal.h"
-
-SPA_EXPORT
-int pa_stream_connect_upload(pa_stream *s, size_t length)
-{
- pw_log_warn("Not Implemented");
- return 0;
-}
-
-SPA_EXPORT
-int pa_stream_finish_upload(pa_stream *s)
-{
- pw_log_warn("Not Implemented");
- return 0;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata)
-{
- pw_log_warn("Not Implemented: name:%s", name);
- return NULL;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_play_sample(pa_context *c, const char *name, const char *dev,
- pa_volume_t volume, pa_context_success_cb_t cb, void *userdata)
-{
- pw_log_warn("Not Implemented: name:%s dev:%s", name, dev);
- return NULL;
-}
-
-SPA_EXPORT
-pa_operation* pa_context_play_sample_with_proplist(pa_context *c, const char *name,
- const char *dev, pa_volume_t volume, PA_CONST pa_proplist *proplist,
- pa_context_play_sample_cb_t cb, void *userdata)
-{
- pw_log_warn("Not Implemented: name:%s dev:%s", name, dev);
- return NULL;
-}
diff --git a/pipewire-pulseaudio/src/simple.c b/pipewire-pulseaudio/src/simple.c
deleted file mode 100644
index b3137922f..000000000
--- a/pipewire-pulseaudio/src/simple.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2004-2006 Lennart Poettering
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-/*Modefied for pipewire by Jan Koester 2020*/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include "internal.h"
-
-SPA_EXPORT
-struct pa_simple {
- pa_threaded_mainloop *mainloop;
- pa_context *context;
- pa_stream *stream;
- pa_stream_direction_t direction;
-
- const void *read_data;
- size_t read_index, read_length;
-
- int operation_success;
-};
-
-typedef struct pa_simple pa_simple;
-
-#define CHECK_VALIDITY_RETURN_ANY(rerror, expression, error, ret) \
- do { \
- if (!(expression)) { \
- if (rerror) \
- *(rerror) = error; \
- return (ret); \
- } \
- } while(false);
-
-#define CHECK_SUCCESS_GOTO(p, rerror, expression, label) \
- do { \
- if (!(expression)) { \
- if (rerror) \
- *(rerror) = pa_context_errno((p)->context); \
- goto label; \
- } \
- } while(false);
-
-#define CHECK_DEAD_GOTO(p, rerror, label) \
- do { \
- if (!(p)->context || !PA_CONTEXT_IS_GOOD(pa_context_get_state((p)->context)) || \
- !(p)->stream || !PA_STREAM_IS_GOOD(pa_stream_get_state((p)->stream))) { \
- if (((p)->context && pa_context_get_state((p)->context) == PA_CONTEXT_FAILED) || \
- ((p)->stream && pa_stream_get_state((p)->stream) == PA_STREAM_FAILED)) { \
- if (rerror) \
- *(rerror) = pa_context_errno((p)->context); \
- } else \
- if (rerror) \
- *(rerror) = PA_ERR_BADSTATE; \
- goto label; \
- } \
- } while(false);
-
-static void context_state_cb(pa_context *c, void *userdata) {
- pa_simple *p = userdata;
- pa_assert(c);
- pa_assert(p);
-
- switch (pa_context_get_state(c)) {
- case PA_CONTEXT_READY:
- case PA_CONTEXT_TERMINATED:
- case PA_CONTEXT_FAILED:
- pa_threaded_mainloop_signal(p->mainloop, 0);
- break;
-
- case PA_CONTEXT_UNCONNECTED:
- case PA_CONTEXT_CONNECTING:
- case PA_CONTEXT_AUTHORIZING:
- case PA_CONTEXT_SETTING_NAME:
- break;
- }
-}
-
-static void stream_state_cb(pa_stream *s, void * userdata) {
- pa_simple *p = userdata;
- pa_assert(s);
- pa_assert(p);
-
- switch (pa_stream_get_state(s)) {
-
- case PA_STREAM_READY:
- case PA_STREAM_FAILED:
- case PA_STREAM_TERMINATED:
- pa_threaded_mainloop_signal(p->mainloop, 0);
- break;
-
- case PA_STREAM_UNCONNECTED:
- case PA_STREAM_CREATING:
- break;
- }
-}
-
-static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
- pa_simple *p = userdata;
- pa_assert(p);
-
- pa_threaded_mainloop_signal(p->mainloop, 0);
-}
-
-static void stream_latency_update_cb(pa_stream *s, void *userdata) {
- pa_simple *p = userdata;
-
- pa_assert(p);
-
- pa_threaded_mainloop_signal(p->mainloop, 0);
-}
-
-SPA_EXPORT
-void pa_simple_free(pa_simple *s) {
- pa_assert(s);
-
- if (s->mainloop)
- pa_threaded_mainloop_stop(s->mainloop);
-
- if (s->stream)
- pa_stream_unref(s->stream);
-
- if (s->context) {
- pa_context_disconnect(s->context);
- pa_context_unref(s->context);
- }
-
- if (s->mainloop)
- pa_threaded_mainloop_free(s->mainloop);
-
- pa_xfree(s);
-}
-
-SPA_EXPORT
-pa_simple* pa_simple_new(
- const char *server,
- const char *name,
- pa_stream_direction_t dir,
- const char *dev,
- const char *stream_name,
- const pa_sample_spec *ss,
- const pa_channel_map *map,
- const pa_buffer_attr *attr,
- int *rerror) {
-
- pa_simple *p;
- int error = PA_ERR_INTERNAL, r;
-
- CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL);
- CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL);
- CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL);
- CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL);
- CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, NULL)
-
- p = pa_xnew0(pa_simple, 1);
- p->direction = dir;
-
- if (!(p->mainloop = pa_threaded_mainloop_new()))
- goto fail;
-
- if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
- goto fail;
-
- pa_context_set_state_callback(p->context, context_state_cb, p);
-
- if (pa_context_connect(p->context, server, 0, NULL) < 0) {
- error = pa_context_errno(p->context);
- goto fail;
- }
-
- pa_threaded_mainloop_lock(p->mainloop);
-
- if (pa_threaded_mainloop_start(p->mainloop) < 0)
- goto unlock_and_fail;
-
- for (;;) {
- pa_context_state_t state;
-
- state = pa_context_get_state(p->context);
-
- if (state == PA_CONTEXT_READY)
- break;
-
- if (!PA_CONTEXT_IS_GOOD(state)) {
- error = pa_context_errno(p->context);
- goto unlock_and_fail;
- }
-
- /* Wait until the context is ready */
- pa_threaded_mainloop_wait(p->mainloop);
- }
-
- if (!(p->stream = pa_stream_new(p->context, stream_name, ss, map))) {
- error = pa_context_errno(p->context);
- goto unlock_and_fail;
- }
-
- pa_stream_set_state_callback(p->stream, stream_state_cb, p);
- pa_stream_set_read_callback(p->stream, stream_request_cb, p);
- pa_stream_set_write_callback(p->stream, stream_request_cb, p);
- pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p);
-
- if (dir == PA_STREAM_PLAYBACK)
- r = pa_stream_connect_playback(p->stream, dev, attr,
- PA_STREAM_INTERPOLATE_TIMING
- |PA_STREAM_ADJUST_LATENCY
- |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
- else
- r = pa_stream_connect_record(p->stream, dev, attr,
- PA_STREAM_INTERPOLATE_TIMING
- |PA_STREAM_ADJUST_LATENCY
- |PA_STREAM_AUTO_TIMING_UPDATE);
-
- if (r < 0) {
- error = pa_context_errno(p->context);
- goto unlock_and_fail;
- }
-
- for (;;) {
- pa_stream_state_t state;
-
- state = pa_stream_get_state(p->stream);
-
- if (state == PA_STREAM_READY)
- break;
-
- if (!PA_STREAM_IS_GOOD(state)) {
- error = pa_context_errno(p->context);
- goto unlock_and_fail;
- }
-
- /* Wait until the stream is ready */
- pa_threaded_mainloop_wait(p->mainloop);
- }
-
- pa_threaded_mainloop_unlock(p->mainloop);
-
- return p;
-
-unlock_and_fail:
- pa_threaded_mainloop_unlock(p->mainloop);
-
-fail:
- if (rerror)
- *rerror = error;
- pa_simple_free(p);
- return NULL;
-}
-
-SPA_EXPORT
-int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
- pa_assert(p);
-
- CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
- CHECK_VALIDITY_RETURN_ANY(rerror, data, PA_ERR_INVALID, -1);
- CHECK_VALIDITY_RETURN_ANY(rerror, length > 0, PA_ERR_INVALID, -1);
-
- pa_threaded_mainloop_lock(p->mainloop);
-
- CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
-
- while (length > 0) {
- size_t l;
- int r;
-
- while (!(l = pa_stream_writable_size(p->stream))) {
- pa_threaded_mainloop_wait(p->mainloop);
- CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
- }
-
- CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail);
-
- if (l > length)
- l = length;
-
- r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
- CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail);
-
- data = (const uint8_t*) data + l;
- length -= l;
- }
-
- pa_threaded_mainloop_unlock(p->mainloop);
- return 0;
-
-unlock_and_fail:
- pa_threaded_mainloop_unlock(p->mainloop);
- return -1;
-}
-
-SPA_EXPORT
-int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
- pa_assert(p);
-
- CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1);
- CHECK_VALIDITY_RETURN_ANY(rerror, data, PA_ERR_INVALID, -1);
- CHECK_VALIDITY_RETURN_ANY(rerror, length > 0, PA_ERR_INVALID, -1);
-
- pa_threaded_mainloop_lock(p->mainloop);
-
- CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
-
- while (length > 0) {
- size_t l;
-
- while (!p->read_data) {
- int r;
-
- r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
- CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
-
- if (p->read_length <= 0) {
- pa_threaded_mainloop_wait(p->mainloop);
- CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
- } else if (!p->read_data) {
- /* There's a hole in the stream, skip it. We could generate
- * silence, but that wouldn't work for compressed streams. */
- r = pa_stream_drop(p->stream);
- CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
- } else
- p->read_index = 0;
- }
-
- l = p->read_length < length ? p->read_length : length;
- memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
-
- data = (uint8_t*) data + l;
- length -= l;
-
- p->read_index += l;
- p->read_length -= l;
-
- if (!p->read_length) {
- int r;
-
- r = pa_stream_drop(p->stream);
- p->read_data = NULL;
- p->read_length = 0;
- p->read_index = 0;
-
- CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
- }
- }
-
- pa_threaded_mainloop_unlock(p->mainloop);
- return 0;
-
-unlock_and_fail:
- pa_threaded_mainloop_unlock(p->mainloop);
- return -1;
-}
-
-static void success_cb(pa_stream *s, int success, void *userdata) {
- pa_simple *p = userdata;
-
- pa_assert(s);
- pa_assert(p);
-
- p->operation_success = success;
- pa_threaded_mainloop_signal(p->mainloop, 0);
-}
-
-SPA_EXPORT
-int pa_simple_drain(pa_simple *p, int *rerror) {
- pa_operation *o = NULL;
-
- pa_assert(p);
-
- CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
-
- pa_threaded_mainloop_lock(p->mainloop);
- CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
-
- o = pa_stream_drain(p->stream, success_cb, p);
- CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
-
- p->operation_success = 0;
- while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
- pa_threaded_mainloop_wait(p->mainloop);
- CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
- }
- CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
-
- pa_operation_unref(o);
- pa_threaded_mainloop_unlock(p->mainloop);
-
- return 0;
-
-unlock_and_fail:
-
- if (o) {
- pa_operation_cancel(o);
- pa_operation_unref(o);
- }
-
- pa_threaded_mainloop_unlock(p->mainloop);
- return -1;
-}
-
-SPA_EXPORT
-int pa_simple_flush(pa_simple *p, int *rerror) {
- pa_operation *o = NULL;
-
- pa_assert(p);
-
- pa_threaded_mainloop_lock(p->mainloop);
- CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
-
- o = pa_stream_flush(p->stream, success_cb, p);
- CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
-
- p->operation_success = 0;
- while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
- pa_threaded_mainloop_wait(p->mainloop);
- CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
- }
- CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
-
- pa_operation_unref(o);
- pa_threaded_mainloop_unlock(p->mainloop);
-
- return 0;
-
-unlock_and_fail:
-
- if (o) {
- pa_operation_cancel(o);
- pa_operation_unref(o);
- }
-
- pa_threaded_mainloop_unlock(p->mainloop);
- return -1;
-}
-
-SPA_EXPORT
-pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
- pa_usec_t t;
-
- pa_assert(p);
-
- pa_threaded_mainloop_lock(p->mainloop);
-
- for (;;) {
- int negative;
-
- CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
-
- if (pa_stream_get_latency(p->stream, &t, &negative) >= 0) {
- if (p->direction == PA_STREAM_RECORD) {
- pa_usec_t already_read;
-
- /* pa_simple_read() calls pa_stream_peek() to get the next
- * chunk of audio. If the next chunk is larger than what the
- * pa_simple_read() caller wanted, the leftover data is stored
- * in p->read_data until pa_simple_read() is called again.
- * pa_stream_drop() won't be called until the whole chunk has
- * been consumed, which means that pa_stream_get_latency() will
- * return too large values, because the whole size of the
- * partially read chunk is included in the latency. Therefore,
- * we need to subtract the already-read amount from the
- * latency. */
- already_read = pa_bytes_to_usec(p->read_index, pa_stream_get_sample_spec(p->stream));
-
- if (!negative) {
- if (t > already_read)
- t -= already_read;
- else
- t = 0;
- }
- }
-
- /* We don't have a way to report negative latencies from
- * pa_simple_get_latency(). If the latency is negative, let's
- * report zero. */
- if (negative)
- t = 0;
-
- break;
- }
-
- CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail);
-
- /* Wait until latency data is available again */
- pa_threaded_mainloop_wait(p->mainloop);
- }
-
- pa_threaded_mainloop_unlock(p->mainloop);
-
- return t;
-
-unlock_and_fail:
-
- pa_threaded_mainloop_unlock(p->mainloop);
- return (pa_usec_t) -1;
-}
diff --git a/pipewire-pulseaudio/src/strbuf.c b/pipewire-pulseaudio/src/strbuf.c
deleted file mode 100644
index 9e281d578..000000000
--- a/pipewire-pulseaudio/src/strbuf.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2004-2006 Lennart Poettering
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include "internal.h"
-#include "strbuf.h"
-
-/* A chunk of the linked list that makes up the string */
-struct chunk {
- struct chunk *next;
- size_t length;
-};
-
-#define CHUNK_TO_TEXT(c) ((char*) (c) + PA_ALIGN(sizeof(struct chunk)))
-
-struct pa_strbuf {
- size_t length;
- struct chunk *head, *tail;
-};
-
-pa_strbuf *pa_strbuf_new(void) {
- pa_strbuf *sb;
-
- sb = pa_xnew(pa_strbuf, 1);
- sb->length = 0;
- sb->head = sb->tail = NULL;
-
- return sb;
-}
-
-void pa_strbuf_free(pa_strbuf *sb) {
- pa_assert(sb);
-
- while (sb->head) {
- struct chunk *c = sb->head;
- sb->head = sb->head->next;
- pa_xfree(c);
- }
-
- pa_xfree(sb);
-}
-
-/* Make a C string from the string buffer. The caller has to free
- * string with pa_xfree(). */
-char *pa_strbuf_to_string(pa_strbuf *sb) {
- char *t, *e;
- struct chunk *c;
-
- pa_assert(sb);
-
- e = t = pa_xmalloc(sb->length+1);
-
- for (c = sb->head; c; c = c->next) {
- pa_assert((size_t) (e-t) <= sb->length);
- memcpy(e, CHUNK_TO_TEXT(c), c->length);
- e += c->length;
- }
-
- /* Trailing NUL */
- *e = 0;
-
- pa_assert(e == t+sb->length);
-
- return t;
-}
-
-/* Combination of pa_strbuf_free() and pa_strbuf_to_string() */
-char *pa_strbuf_to_string_free(pa_strbuf *sb) {
- char *t;
-
- pa_assert(sb);
- t = pa_strbuf_to_string(sb);
- pa_strbuf_free(sb);
-
- return t;
-}
-
-/* Append a string to the string buffer */
-void pa_strbuf_puts(pa_strbuf *sb, const char *t) {
-
- pa_assert(sb);
- pa_assert(t);
-
- pa_strbuf_putsn(sb, t, strlen(t));
-}
-
-/* Append a character to the string buffer */
-void pa_strbuf_putc(pa_strbuf *sb, char c) {
- pa_assert(sb);
-
- pa_strbuf_putsn(sb, &c, 1);
-}
-
-/* Append a new chunk to the linked list */
-static void append(pa_strbuf *sb, struct chunk *c) {
- pa_assert(sb);
- pa_assert(c);
-
- if (sb->tail) {
- pa_assert(sb->head);
- sb->tail->next = c;
- } else {
- pa_assert(!sb->head);
- sb->head = c;
- }
-
- sb->tail = c;
- sb->length += c->length;
- c->next = NULL;
-}
-
-/* Append up to l bytes of a string to the string buffer */
-void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t l) {
- struct chunk *c;
-
- pa_assert(sb);
- pa_assert(t);
-
- if (!l)
- return;
-
- c = pa_xmalloc(PA_ALIGN(sizeof(struct chunk)) + l);
- c->length = l;
- memcpy(CHUNK_TO_TEXT(c), t, l);
-
- append(sb, c);
-}
-
-/* Append a printf() style formatted string to the string buffer. */
-/* The following is based on an example from the GNU libc documentation */
-size_t pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) {
- size_t size = 100;
- struct chunk *c = NULL;
-
- pa_assert(sb);
- pa_assert(format);
-
- for(;;) {
- va_list ap;
- int r;
-
- c = pa_xrealloc(c, PA_ALIGN(sizeof(struct chunk)) + size);
-
- va_start(ap, format);
- r = vsnprintf(CHUNK_TO_TEXT(c), size, format, ap);
- CHUNK_TO_TEXT(c)[size-1] = 0;
- va_end(ap);
-
- if (r > -1 && (size_t) r < size) {
- c->length = (size_t) r;
- append(sb, c);
- return (size_t) r;
- }
-
- if (r > -1) /* glibc 2.1 */
- size = (size_t) r+1;
- else /* glibc 2.0 */
- size *= 2;
- }
-}
-
-bool pa_strbuf_isempty(pa_strbuf *sb) {
- pa_assert(sb);
-
- return sb->length <= 0;
-}
diff --git a/pipewire-pulseaudio/src/strbuf.h b/pipewire-pulseaudio/src/strbuf.h
deleted file mode 100644
index f5d9921e6..000000000
--- a/pipewire-pulseaudio/src/strbuf.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef foostrbufhfoo
-#define foostrbufhfoo
-
-/***
- This file is part of PulseAudio.
-
- Copyright 2004-2006 Lennart Poettering
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#include
-
-typedef struct pa_strbuf pa_strbuf;
-
-pa_strbuf *pa_strbuf_new(void);
-void pa_strbuf_free(pa_strbuf *sb);
-char *pa_strbuf_to_string(pa_strbuf *sb);
-char *pa_strbuf_to_string_free(pa_strbuf *sb);
-
-size_t pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3);
-void pa_strbuf_puts(pa_strbuf *sb, const char *t);
-void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t m);
-void pa_strbuf_putc(pa_strbuf *sb, char c);
-
-bool pa_strbuf_isempty(pa_strbuf *sb);
-
-#endif
diff --git a/pipewire-pulseaudio/src/stream.c b/pipewire-pulseaudio/src/stream.c
deleted file mode 100644
index 18fff4687..000000000
--- a/pipewire-pulseaudio/src/stream.c
+++ /dev/null
@@ -1,1952 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-#include "core-format.h"
-#include "internal.h"
-
-#define MIN_SAMPLES 24u
-#define MIN_BUFFERS 8u
-#define MAX_BUFFERS 64u
-
-#define MAX_BUFFER_SAMPLES (8*1024u)
-#define MAX_SIZE (4*1024*1024u)
-
-static void dump_buffer_attr(pa_stream *s, pa_buffer_attr *attr)
-{
- char b[1024];
- pw_log_debug("stream %p: sample: %s", s, pa_sample_spec_snprint(b, sizeof(b), &s->sample_spec));
- pw_log_debug("stream %p: stride: %zu", s, pa_frame_size(&s->sample_spec));
- pw_log_debug("stream %p: maxlength: %u", s, attr->maxlength);
- pw_log_debug("stream %p: tlength: %u", s, attr->tlength);
- pw_log_debug("stream %p: minreq: %u", s, attr->minreq);
- pw_log_debug("stream %p: prebuf: %u", s, attr->prebuf);
- pw_log_debug("stream %p: fragsize: %u", s, attr->fragsize);
-}
-
-static void stream_destroy(void *data)
-{
- pa_stream *s = data;
- s->stream = NULL;
-}
-
-static void stream_state_changed(void *data, enum pw_stream_state old,
- enum pw_stream_state state, const char *error)
-{
- pa_stream *s = data;
- pa_context *c = s->context;
-
- pw_log_debug("stream %p: state '%s'->'%s' (%d)", s, pw_stream_state_as_string(old),
- pw_stream_state_as_string(state), s->state);
-
- if (s->state == PA_STREAM_TERMINATED || c == NULL)
- return;
-
- switch(state) {
- case PW_STREAM_STATE_ERROR:
- pa_stream_set_state(s, PA_STREAM_FAILED);
- break;
- case PW_STREAM_STATE_UNCONNECTED:
- if (!s->disconnecting) {
- pa_context_set_error(c, PA_ERR_KILLED);
- pa_stream_set_state(s, PA_STREAM_FAILED);
- }
- break;
- case PW_STREAM_STATE_CONNECTING:
- pa_stream_set_state(s, PA_STREAM_CREATING);
- break;
- case PW_STREAM_STATE_PAUSED:
- s->stream_index = pw_stream_get_node_id(s->stream);
- if (!s->suspended) {
- s->suspended = true;
- if (!c->disconnect && !s->corked && s->state == PA_STREAM_READY && s->suspended_callback)
- s->suspended_callback(s, s->suspended_userdata);
- }
- break;
- case PW_STREAM_STATE_STREAMING:
- if (s->suspended) {
- s->suspended = false;
- if (!c->disconnect && !s->corked && s->state == PA_STREAM_READY && s->started_callback)
- s->started_callback(s, s->started_userdata);
- }
- break;
- }
-}
-
-static const struct spa_pod *get_buffers_param(pa_stream *s, pa_buffer_attr *attr, struct spa_pod_builder *b)
-{
- const struct spa_pod *param;
- uint32_t blocks, buffers, size, maxsize, stride;
-
- blocks = 1;
- stride = pa_frame_size(&s->sample_spec);
-
- maxsize = attr->tlength;
- size = attr->minreq;
- buffers = SPA_CLAMP(maxsize / size, MIN_BUFFERS, MAX_BUFFERS);
-
- pw_log_info("stream %p: stride %d maxsize %d size %u buffers %d", s, stride, maxsize,
- size, buffers);
-
- param = spa_pod_builder_add_object(b,
- SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
- SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(buffers, MIN_BUFFERS, MAX_BUFFERS),
- SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(blocks),
- SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int(
- size, size, maxsize),
- SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride),
- SPA_PARAM_BUFFERS_align, SPA_POD_Int(16));
- return param;
-}
-
-static void patch_buffer_attr(pa_stream *s, pa_buffer_attr *attr, pa_stream_flags_t *flags) {
- const char *e, *str;
- char buf[100];
- uint32_t stride, period;
-
- pa_assert(s);
- pa_assert(attr);
-
- e = getenv("PULSE_LATENCY_MSEC");
- if (e == NULL) {
- str = getenv("PIPEWIRE_LATENCY");
- if (str) {
- int num, denom;
- if (sscanf(str, "%u/%u", &num, &denom) == 2 && denom != 0) {
- snprintf(buf, sizeof(buf)-1, "%"PRIu64, num * PA_MSEC_PER_SEC / denom);
- e = buf;
- }
- }
- }
-
- if (e) {
- uint32_t ms;
- pa_sample_spec ss;
-
- pa_sample_spec_init(&ss);
-
- if (pa_sample_spec_valid(&s->sample_spec))
- ss = s->sample_spec;
- else if (s->n_formats == 1)
- pa_format_info_to_sample_spec(s->req_formats[0], &ss, NULL);
-
- if ((ms = atoi(e)) == 0) {
- pa_log_debug("Failed to parse $PULSE_LATENCY_MSEC: %s", e);
- }
- else if (!pa_sample_spec_valid(&ss)) {
- pa_log_debug("Ignoring $PULSE_LATENCY_MSEC: %s (invalid sample spec)", e);
- }
- else {
- attr->maxlength = (uint32_t) -1;
- attr->tlength = pa_usec_to_bytes(ms * PA_USEC_PER_MSEC, &ss);
- attr->minreq = (uint32_t) -1;
- attr->prebuf = (uint32_t) -1;
- attr->fragsize = attr->tlength;
-
- if (flags)
- *flags |= PA_STREAM_ADJUST_LATENCY;
- }
- }
-
- if (flags && !SPA_FLAG_IS_SET(*flags, PA_STREAM_ADJUST_LATENCY)) {
- if (attr->maxlength == 0)
- attr->maxlength = -1;
- if (attr->tlength == 0)
- attr->tlength = -1;
- if (attr->minreq == 0)
- attr->minreq = -1;
- if (attr->prebuf == 0)
- attr->prebuf = -1;
- if (attr->fragsize == 0)
- attr->fragsize = -1;
- period = 100;
- } else {
- period = 20;
- }
-
- dump_buffer_attr(s, attr);
-
- stride = pa_frame_size(&s->sample_spec);
- if (attr->maxlength == (uint32_t) -1 || attr->maxlength == 0)
- attr->maxlength = MAX_SIZE; /* 4MB is the maximum queue length PulseAudio <= 0.9.9 supported. */
- attr->maxlength -= attr->maxlength % stride;
- attr->maxlength = SPA_MAX(attr->maxlength, stride);
-
- if (attr->tlength == (uint32_t) -1)
- attr->tlength = (uint32_t) pa_usec_to_bytes(2*PA_USEC_PER_SEC, &s->sample_spec);
- attr->tlength = SPA_MIN(attr->tlength, attr->maxlength);
- attr->tlength -= attr->tlength % stride;
-
- if (attr->minreq == (uint32_t) -1)
- attr->minreq = pa_usec_to_bytes(period*PA_USEC_PER_MSEC, &s->sample_spec);
- attr->minreq = SPA_MIN(attr->minreq, attr->tlength / 4);
- attr->minreq = SPA_MAX(attr->minreq, MIN_SAMPLES * stride);
- attr->minreq -= attr->minreq % stride;
- attr->minreq = SPA_MAX(attr->minreq, stride);
-
- attr->tlength = SPA_MAX(attr->tlength, attr->minreq * 4);
-
- if (attr->prebuf == (uint32_t) -1)
- attr->prebuf = attr->tlength - attr->minreq;
- attr->prebuf = SPA_MIN(attr->prebuf, attr->tlength - attr->minreq);
- attr->prebuf -= attr->prebuf % stride;
- attr->prebuf = SPA_MAX(attr->prebuf, stride);
-
- if (attr->fragsize == (uint32_t) -1)
- attr->fragsize = pa_usec_to_bytes(period*PA_USEC_PER_MSEC, &s->sample_spec);
- attr->fragsize = SPA_MIN(attr->fragsize, attr->tlength / 4);
- attr->fragsize -= attr->fragsize % stride;
- attr->fragsize = SPA_MAX(attr->fragsize, stride);
-
- dump_buffer_attr(s, attr);
-}
-
-static void stream_param_changed(void *data, uint32_t id, const struct spa_pod *param)
-{
- pa_stream *s = data;
- const struct spa_pod *params[4];
- uint32_t n_params = 0, stride, latency;
- uint8_t buffer[4096];
- struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
- struct spa_dict_item items[1];
- char str[64];
- int res;
-
- if (param == NULL || id != SPA_PARAM_Format)
- return;
-
- if ((res = pa_format_parse_param(param, &s->sample_spec, &s->channel_map)) < 0) {
- pw_stream_set_error(s->stream, res, "unhandled format");
- return;
- }
-
- if (s->format)
- pa_format_info_free(s->format);
- s->format = pa_format_info_from_sample_spec(&s->sample_spec, &s->channel_map);
- if (s->format == NULL) {
- pw_stream_set_error(s->stream, -errno, "unhandled format");
- return;
- }
-
- patch_buffer_attr(s, &s->buffer_attr, &s->flags);
-
- pa_stream_set_state(s, PA_STREAM_READY);
-
- if (s->corked)
- pw_stream_set_active(s->stream, false);
-
- stride = pa_frame_size(&s->sample_spec);
-
- if (s->direction == PA_STREAM_RECORD) {
- latency = s->buffer_attr.fragsize / stride;
- } else {
- latency = s->buffer_attr.minreq * 2 / stride;
- }
- snprintf(str, sizeof(str), "%u/%u", latency, s->sample_spec.rate);
- items[0] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, str);
- pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 1));
-
- params[n_params++] = get_buffers_param(s, &s->buffer_attr, &b);
- pw_stream_update_params(s->stream, params, n_params);
-}
-
-static void stream_control_info(void *data, uint32_t id, const struct pw_stream_control *control)
-{
- pa_stream *s = data;
-
- pw_log_debug("stream %p: control %d", s, id);
- switch (id) {
- case SPA_PROP_mute:
- if (control->n_values > 0)
- s->mute = control->values[0] >= 0.5f;
- break;
- case SPA_PROP_channelVolumes:
- s->n_channel_volumes = SPA_MAX(SPA_AUDIO_MAX_CHANNELS, control->n_values);
- memcpy(s->channel_volumes, control->values, s->n_channel_volumes * sizeof(float));
- break;
- default:
- break;
- }
-}
-
-static void stream_add_buffer(void *data, struct pw_buffer *buffer)
-{
- pa_stream *s = data;
- uint32_t maxsize = buffer->buffer->datas[0].maxsize;
- buffer->size = 0;
- s->maxsize += maxsize;
- s->maxblock = SPA_MIN(maxsize, s->maxblock);
-}
-
-static void stream_remove_buffer(void *data, struct pw_buffer *buffer)
-{
- pa_stream *s = data;
- struct pa_mem *m = buffer->user_data;
- s->maxsize -= buffer->buffer->datas[0].maxsize;
- s->maxblock = INT_MAX;
- if (m != NULL) {
- spa_list_append(&s->free, &m->link);
- m->user_data = NULL;
- buffer->user_data = NULL;
- pw_log_trace("remove %p", m);
- }
-}
-
-static void update_timing_info(pa_stream *s)
-{
- struct pw_time pwt;
- pa_timing_info *ti = &s->timing_info;
- size_t stride = pa_frame_size(&s->sample_spec);
- int64_t delay, pos;
-
- pw_stream_get_time(s->stream, &pwt);
- s->timing_info_valid = false;
-
- pa_timeval_store(&ti->timestamp, pwt.now / SPA_NSEC_PER_USEC);
- ti->synchronized_clocks = true;
- ti->transport_usec = 0;
- ti->playing = 1;
- ti->write_index_corrupt = false;
- ti->read_index_corrupt = false;
-
- if (pwt.rate.denom > 0) {
- uint64_t ticks = pwt.ticks;
- if (!s->have_time)
- s->ticks_base = ticks;
- if (ticks > s->ticks_base)
- pos = ((ticks - s->ticks_base) * s->sample_spec.rate / pwt.rate.denom) * stride;
- else
- pos = 0;
- delay = pwt.delay * SPA_USEC_PER_SEC / pwt.rate.denom;
- s->have_time = true;
- } else {
- pos = delay = 0;
- s->have_time = false;
- }
- if (s->direction == PA_STREAM_PLAYBACK) {
- ti->sink_usec = delay;
- ti->configured_sink_usec = delay;
- ti->read_index = pos;
- } else {
- ti->source_usec = delay;
- ti->configured_source_usec = delay;
- ti->write_index = pos;
- }
- s->queued_bytes = pwt.queued;
- s->timing_info_valid = true;
-
- pw_log_trace("stream %p: %"PRIu64" rate:%d/%d ticks:%"PRIu64" pos:%"PRIu64" delay:%"PRIi64 " read:%"PRIu64
- " write:%"PRIu64" queued:%"PRIi64,
- s, pwt.queued, s->sample_spec.rate, pwt.rate.denom, pwt.ticks, pos, pwt.delay,
- ti->read_index, ti->write_index, ti->read_index - ti->write_index);
-}
-
-static void queue_output(pa_stream *s)
-{
- struct pa_mem *m, *t, *old;
- struct pw_buffer *buf;
-
- spa_list_for_each_safe(m, t, &s->ready, link) {
- buf = pw_stream_dequeue_buffer(s->stream);
- if (buf == NULL)
- break;
-
- if ((old = buf->user_data) != NULL) {
- pw_log_trace("queue %p", old);
- spa_list_append(&s->free, &old->link);
- old->user_data = NULL;
- }
-
- pw_log_trace("queue %p", m);
- spa_list_remove(&m->link);
- s->ready_bytes -= m->size;
- s->queued_bytes += m->size;
-
- buf->buffer->datas[0].maxsize = m->maxsize;
- buf->buffer->datas[0].data = m->data;
- buf->buffer->datas[0].chunk->offset = m->offset;
- buf->buffer->datas[0].chunk->size = m->size;
- buf->user_data = m;
- buf->size = m->size;
- m->user_data = buf;
-
- pw_stream_queue_buffer(s->stream, buf);
- }
-}
-
-struct pa_mem *alloc_mem(pa_stream *s, size_t len)
-{
- struct pa_mem *m;
- if (spa_list_is_empty(&s->free)) {
- if (len > s->maxblock)
- len = s->maxblock;
- m = calloc(1, sizeof(struct pa_mem) + len);
- if (m == NULL)
- return NULL;
- m->data = SPA_MEMBER(m, sizeof(struct pa_mem), void);
- m->maxsize = len;
- pw_log_trace("alloc %p", m);
- } else {
- m = spa_list_first(&s->free, struct pa_mem, link);
- spa_list_remove(&m->link);
- pw_log_trace("reuse %p", m);
- }
- return m;
-}
-
-static void pull_input(pa_stream *s)
-{
- struct pw_buffer *buf;
- struct pa_mem *m;
-
- while ((buf = pw_stream_dequeue_buffer(s->stream)) != NULL) {
- if ((m = alloc_mem(s, 0)) == NULL) {
- pw_log_error("stream %p: Can't alloc mem: %m", s);
- pw_stream_queue_buffer(s->stream, buf);
- continue;
- }
- m->data = buf->buffer->datas[0].data;
- m->maxsize = buf->buffer->datas[0].maxsize;
- m->offset = buf->buffer->datas[0].chunk->offset;
- m->size = buf->buffer->datas[0].chunk->size;
- m->user_data = buf;
- buf->user_data = m;
-
- pw_log_trace("input %p, size:%zd ready:%zd", m, m->size, s->ready_bytes);
- spa_list_append(&s->ready, &m->link);
- s->ready_bytes += m->size;
- }
-}
-
-
-static inline uint32_t queued_size(const pa_stream *s, uint64_t elapsed)
-{
- uint64_t queued;
- const pa_timing_info *i = &s->timing_info;
- queued = i->write_index - SPA_MIN(i->read_index, i->write_index);
- queued -= SPA_MIN(queued, elapsed);
- return queued;
-}
-static inline uint32_t target_queue(const pa_stream *s)
-{
- return s->buffer_attr.tlength;
-}
-
-static inline uint32_t wanted_size(const pa_stream *s, uint32_t queued, uint32_t target)
-{
- return target - SPA_MIN(queued, target);
-}
-
-static inline uint32_t required_size(const pa_stream *s)
-{
- return s->buffer_attr.minreq;
-}
-
-static inline uint32_t writable_size(const pa_stream *s, uint64_t elapsed)
-{
- uint32_t queued, target, wanted, required;
-
- queued = queued_size(s, elapsed);
- target = target_queue(s);
- wanted = wanted_size(s, queued, target);
- required = required_size(s);
-
- pw_log_trace("stream %p, queued:%u target:%u wanted:%u required:%u",
- s, queued, target, wanted, required);
- if (SPA_FLAG_IS_SET(s->flags, PA_STREAM_ADJUST_LATENCY))
- if (queued >= wanted)
- wanted = 0;
- if (wanted < required)
- wanted = 0;
-
- return wanted;
-}
-
-static void stream_process(void *data)
-{
- pa_stream *s = data;
-
- pw_log_trace("stream %p:", s);
- update_timing_info(s);
-
- if (s->direction == PA_STREAM_PLAYBACK) {
- uint32_t writable;
-
- queue_output(s);
-
- writable = writable_size(s, 0);
-
- if (s->write_callback && s->state == PA_STREAM_READY && writable > 0)
- s->write_callback(s, writable, s->write_userdata);
- }
- else {
- pull_input(s);
-
- if (s->read_callback && s->ready_bytes > 0 && s->state == PA_STREAM_READY)
- s->read_callback(s, s->ready_bytes, s->read_userdata);
- }
-}
-
-static void stream_drained(void *data)
-{
- pa_stream *s = data;
-
- pw_log_debug("drained");
-
- if (s->drain) {
- pa_operation *o = s->drain;
- pa_operation_ref(o);
- if (o->callback)
- o->callback(o, o->userdata);
- pa_operation_unref(o);
- s->drain = NULL;
- }
-}
-
-static const struct pw_stream_events stream_events =
-{
- PW_VERSION_STREAM_EVENTS,
- .destroy = stream_destroy,
- .state_changed = stream_state_changed,
- .param_changed = stream_param_changed,
- .control_info = stream_control_info,
- .add_buffer = stream_add_buffer,
- .remove_buffer = stream_remove_buffer,
- .process = stream_process,
- .drained = stream_drained,
-};
-
-static pa_stream* stream_new(pa_context *c, const char *name,
- const pa_sample_spec *ss, const pa_channel_map *map,
- pa_format_info * const * formats, unsigned int n_formats,
- pa_proplist *p)
-{
- pa_stream *s;
- char str[1024];
- unsigned int i;
-
- spa_assert(c);
- spa_assert(c->refcount >= 1);
- pa_assert((ss == NULL && map == NULL) || (formats == NULL && n_formats == 0));
- pa_assert(n_formats < PA_MAX_FORMATS);
-
- PA_CHECK_VALIDITY_RETURN_NULL(c, name ||
- (p && pa_proplist_contains(p, PA_PROP_MEDIA_NAME)), PA_ERR_INVALID);
-
- s = calloc(1, sizeof(pa_stream));
- if (s == NULL)
- return NULL;
-
- s->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
- if (name)
- pa_proplist_sets(s->proplist, PA_PROP_MEDIA_NAME, name);
- else
- name = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME);
-
- s->refcount = 1;
- s->context = c;
- spa_list_init(&s->free);
- spa_list_init(&s->ready);
-
- s->direction = PA_STREAM_NODIRECTION;
- s->state = PA_STREAM_UNCONNECTED;
- s->flags = 0;
- s->have_time = false;
-
- if (ss)
- s->sample_spec = *ss;
- else
- pa_sample_spec_init(&s->sample_spec);
-
- if (map)
- s->channel_map = *map;
- else
- pa_channel_map_init(&s->channel_map);
-
- pw_log_debug("stream %p: channel map: %p %s", s,
- map, pa_channel_map_snprint(str, sizeof(str), &s->channel_map));
-
- s->n_formats = 0;
- if (formats) {
- s->n_formats = n_formats;
- for (i = 0; i < n_formats; i++) {
- s->req_formats[i] = pa_format_info_copy(formats[i]);
- pw_log_debug("format %d: %s", i,
- pa_format_info_snprint(str, sizeof(str), formats[i]));
- }
- }
- s->format = NULL;
-
- s->direct_on_input = PA_INVALID_INDEX;
-
- s->stream_index = PA_INVALID_INDEX;
- s->maxblock = INT_MAX;
-
- s->device_index = PA_INVALID_INDEX;
- s->device_name = NULL;
-
- spa_list_append(&c->streams, &s->link);
- pa_stream_ref(s);
-
- return s;
-}
-
-SPA_EXPORT
-pa_stream* pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss,
- const pa_channel_map *map)
-{
- return stream_new(c, name, ss, map, NULL, 0, NULL);
-}
-
-SPA_EXPORT
-pa_stream* pa_stream_new_with_proplist(pa_context *c, const char *name,
- const pa_sample_spec *ss, const pa_channel_map *map, pa_proplist *p)
-{
- pa_channel_map tmap;
-
- if (!map)
- PA_CHECK_VALIDITY_RETURN_NULL(c, map = pa_channel_map_init_extend(&tmap,
- ss->channels, PA_CHANNEL_MAP_DEFAULT), PA_ERR_INVALID);
-
- return stream_new(c, name, ss, map, NULL, 0, p);
-}
-
-SPA_EXPORT
-pa_stream *pa_stream_new_extended(pa_context *c, const char *name,
- pa_format_info * const * formats, unsigned int n_formats, pa_proplist *p)
-{
- return stream_new(c, name, NULL, NULL, formats, n_formats, p);
-}
-
-static void stream_unlink(pa_stream *s)
-{
- pa_context *c = s->context;
- pa_operation *o, *t;
-
- if (c == NULL)
- return;
-
- pw_log_debug("stream %p: unlink %d", s, s->refcount);
-
- spa_list_for_each_safe(o, t, &c->operations, link) {
- if (o->stream == s)
- pa_operation_cancel(o);
- }
- s->drain = NULL;
-
- spa_list_remove(&s->link);
- if (s->stream)
- pw_stream_set_active(s->stream, false);
-
- s->context = NULL;
- pa_stream_unref(s);
-}
-
-static void stream_free(pa_stream *s)
-{
- int i;
- struct pa_mem *m;
-
- pw_log_debug("stream %p", s);
-
-
- if (s->stream) {
- spa_hook_remove(&s->stream_listener);
- pw_stream_destroy(s->stream);
- }
- if (s->global)
- s->global->stream = NULL;
-
- spa_list_consume(m, &s->free, link) {
- pw_log_trace("free %p", m);
- spa_list_remove(&m->link);
- free(m);
- }
- if (s->proplist)
- pa_proplist_free(s->proplist);
-
- for (i = 0; i < s->n_formats; i++)
- pa_format_info_free(s->req_formats[i]);
-
- if (s->format)
- pa_format_info_free(s->format);
-
- free(s->device_name);
- free(s);
-}
-
-SPA_EXPORT
-void pa_stream_unref(pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- pw_log_debug("stream %p: ref %d", s, s->refcount);
- if (--s->refcount == 0)
- stream_free(s);
-}
-
-SPA_EXPORT
-pa_stream *pa_stream_ref(pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- s->refcount++;
- pw_log_debug("stream %p: ref %d", s, s->refcount);
- return s;
-}
-
-SPA_EXPORT
-pa_stream_state_t pa_stream_get_state(PA_CONST pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- return s->state;
-}
-
-SPA_EXPORT
-pa_context* pa_stream_get_context(PA_CONST pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- return s->context;
-}
-
-SPA_EXPORT
-uint32_t pa_stream_get_index(PA_CONST pa_stream *s)
-{
- uint32_t idx;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- idx = s->stream_index;
- pw_log_debug("stream %p: index %u", s, idx);
- return idx;
-}
-
-void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) {
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == st)
- return;
-
- pa_stream_ref(s);
-
- pw_log_debug("stream %p: state %d -> %d", s, s->state, st);
- s->state = st;
-
- if (s->state_callback)
- s->state_callback(s, s->state_userdata);
-
- if ((st == PA_STREAM_FAILED || st == PA_STREAM_TERMINATED))
- stream_unlink(s);
-
- pa_stream_unref(s);
-}
-
-
-SPA_EXPORT
-uint32_t pa_stream_get_device_index(PA_CONST pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY,
- PA_ERR_BADSTATE, PA_INVALID_INDEX);
- PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_UPLOAD,
- PA_ERR_BADSTATE, PA_INVALID_INDEX);
- PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->device_index != PA_INVALID_INDEX,
- PA_ERR_BADSTATE, PA_INVALID_INDEX);
-
- pw_log_trace("stream %p: %d", s, s->device_index);
- return s->device_index;
-}
-
-SPA_EXPORT
-const char *pa_stream_get_device_name(PA_CONST pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->device_name, PA_ERR_BADSTATE);
-
- pw_log_trace("stream %p: %s %d", s, s->device_name, s->device_index);
- return s->device_name;
-}
-
-SPA_EXPORT
-int pa_stream_is_suspended(PA_CONST pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- return s->suspended && !s->corked;
-}
-
-SPA_EXPORT
-int pa_stream_is_corked(PA_CONST pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- pw_log_trace("stream %p: corked %d", s, s->corked);
- return s->corked;
-}
-
-static int create_stream(pa_stream_direction_t direction,
- pa_stream *s,
- const char *dev,
- const pa_buffer_attr *attr,
- pa_stream_flags_t flags,
- const pa_cvolume *volume,
- pa_stream *sync_stream)
-{
- int res;
- enum pw_stream_flags fl;
- const struct spa_pod *params[PA_MAX_FORMATS+1];
- uint32_t i, n_params = 0;
- uint8_t buffer[4096];
- struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
- const char *str;
- uint32_t devid, n_items;
- struct spa_dict_item items[7];
- bool monitor, no_remix;
- const char *name;
- pa_context *c = s->context;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- spa_assert(direction == PA_STREAM_PLAYBACK || direction == PA_STREAM_RECORD);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direct_on_input == PA_INVALID_INDEX || direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, !(flags & ~(PA_STREAM_START_CORKED|
- PA_STREAM_INTERPOLATE_TIMING|
- PA_STREAM_NOT_MONOTONIC|
- PA_STREAM_AUTO_TIMING_UPDATE|
- PA_STREAM_NO_REMAP_CHANNELS|
- PA_STREAM_NO_REMIX_CHANNELS|
- PA_STREAM_FIX_FORMAT|
- PA_STREAM_FIX_RATE|
- PA_STREAM_FIX_CHANNELS|
- PA_STREAM_DONT_MOVE|
- PA_STREAM_VARIABLE_RATE|
- PA_STREAM_PEAK_DETECT|
- PA_STREAM_START_MUTED|
- PA_STREAM_ADJUST_LATENCY|
- PA_STREAM_EARLY_REQUESTS|
- PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND|
- PA_STREAM_START_UNMUTED|
- PA_STREAM_FAIL_ON_SUSPEND|
- PA_STREAM_RELATIVE_VOLUME|
- PA_STREAM_PASSTHROUGH)), PA_ERR_INVALID);
-
- PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, direction == PA_STREAM_RECORD || !(flags & (PA_STREAM_PEAK_DETECT)), PA_ERR_INVALID);
- PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID);
- PA_CHECK_VALIDITY(s->context, (flags & (PA_STREAM_ADJUST_LATENCY|PA_STREAM_EARLY_REQUESTS)) != (PA_STREAM_ADJUST_LATENCY|PA_STREAM_EARLY_REQUESTS), PA_ERR_INVALID);
-
-
- pw_log_info("stream %p: connect %s %08x", s, dev, flags);
-
- name = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME);
-
- s->stream = pw_stream_new(c->core,
- name, pw_properties_copy(c->props));
- pw_stream_add_listener(s->stream, &s->stream_listener, &stream_events, s);
-
- s->direction = direction;
- s->timing_info_valid = false;
- s->disconnecting = false;
- if (volume) {
- for (i = 0; i < volume->channels; i++)
- s->channel_volumes[i] = pa_sw_volume_to_linear(volume->values[i]);
- s->n_channel_volumes = volume->channels;
- } else {
- for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
- s->channel_volumes[i] = 1.0;
- s->n_channel_volumes = 0;
- }
- s->mute = false;
- s->flags = flags;
-
- pa_stream_set_state(s, PA_STREAM_CREATING);
-
- fl = PW_STREAM_FLAG_AUTOCONNECT |
- PW_STREAM_FLAG_MAP_BUFFERS;
-
- s->corked = SPA_FLAG_IS_SET(flags, PA_STREAM_START_CORKED);
-
- if (flags & PA_STREAM_PASSTHROUGH)
- fl |= PW_STREAM_FLAG_EXCLUSIVE;
- if (flags & PA_STREAM_DONT_MOVE)
- fl |= PW_STREAM_FLAG_DONT_RECONNECT;
- monitor = (flags & PA_STREAM_PEAK_DETECT);
- no_remix = (flags & PA_STREAM_NO_REMIX_CHANNELS);
-
- if (attr)
- s->buffer_attr = *attr;
-
- if (pa_sample_spec_valid(&s->sample_spec)) {
- params[n_params++] = pa_format_build_param(&b, SPA_PARAM_EnumFormat,
- &s->sample_spec, &s->channel_map);
- }
- else {
- pa_sample_spec ss;
- pa_channel_map chmap;
- int i;
-
- for (i = 0; i < s->n_formats; i++) {
- if ((res = pa_format_info_to_sample_spec(s->req_formats[i], &ss, NULL)) < 0) {
- char buf[4096];
- pw_log_warn("can't convert format %d %s", res,
- pa_format_info_snprint(buf, sizeof(buf), s->req_formats[i]));
- continue;
- }
- if (pa_format_info_get_channel_map(s->req_formats[i], &chmap) < 0)
- pa_channel_map_init_extend(&chmap, ss.channels, PA_CHANNEL_MAP_DEFAULT);
-
- params[n_params++] = pa_format_build_param(&b, SPA_PARAM_EnumFormat,
- &ss, &chmap);
- }
- }
-
- if (direction == PA_STREAM_RECORD)
- devid = s->direct_on_input;
- else
- devid = PW_ID_ANY;
-
- if (dev == NULL && devid == PW_ID_ANY) {
- dev = getenv("PIPEWIRE_NODE");
- }
- else if (dev != NULL && devid == PW_ID_ANY) {
- if ((devid = atoi(dev)) == 0)
- devid = PW_ID_ANY;
- else if (devid & PA_IDX_FLAG_MONITOR)
- devid &= PA_IDX_MASK_MONITOR;
-
- if (devid == PW_ID_ANY) {
- if (pa_endswith(dev, ".monitor"))
- dev = strndupa(dev, strlen(dev) - 8);
- }
- }
-
- if ((str = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_ROLE)) != NULL) {
- if (strcmp(str, "video") == 0)
- str = "Movie";
- else if (strcmp(str, "music") == 0)
- str = "Music";
- else if (strcmp(str, "game") == 0)
- str = "Game";
- else if (strcmp(str, "event") == 0)
- str = "Notification";
- else if (strcmp(str, "phone") == 0)
- str = "Communication";
- else if (strcmp(str, "animation") == 0)
- str = "Movie";
- else if (strcmp(str, "production") == 0)
- str = "Production";
- else if (strcmp(str, "a11y") == 0)
- str = "Accessibility";
- else if (strcmp(str, "test") == 0)
- str = "Test";
- else
- str = "Music";
- }
-
- n_items = 0;
- items[n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_MEDIA_TYPE, "Audio");
- items[n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_MEDIA_CATEGORY,
- direction == PA_STREAM_PLAYBACK ?
- "Playback" : monitor ? "Monitor" : "Capture");
- if (str != NULL)
- items[n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_MEDIA_ROLE, str);
- if (monitor)
- items[n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_STREAM_MONITOR, "true");
- if (no_remix)
- items[n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_STREAM_DONT_REMIX, "true");
- if (devid == PW_ID_ANY && dev != NULL)
- items[n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_TARGET, dev);
- pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, n_items));
-
- res = pw_stream_connect(s->stream,
- direction == PA_STREAM_PLAYBACK ?
- PW_DIRECTION_OUTPUT :
- PW_DIRECTION_INPUT,
- devid,
- fl,
- params, n_params);
-
- return res;
-}
-
-SPA_EXPORT
-int pa_stream_connect_playback(
- pa_stream *s,
- const char *dev,
- const pa_buffer_attr *attr,
- pa_stream_flags_t flags,
- const pa_cvolume *volume,
- pa_stream *sync_stream)
-{
- return create_stream(PA_STREAM_PLAYBACK, s, dev, attr, flags, volume, sync_stream);
-}
-
-SPA_EXPORT
-int pa_stream_connect_record(
- pa_stream *s,
- const char *dev,
- const pa_buffer_attr *attr,
- pa_stream_flags_t flags)
-{
- return create_stream(PA_STREAM_RECORD, s, dev, attr, flags, NULL, NULL);
-}
-
-static void on_disconnected(pa_operation *o, void *userdata)
-{
- pa_stream *s = o->stream;
- pw_log_debug("stream %p", s);
- pa_stream_set_state(s, PA_STREAM_TERMINATED);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-int pa_stream_disconnect(pa_stream *s)
-{
- pa_operation *o;
- pa_context *c = s->context;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY(c, c != NULL, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
- pw_log_debug("stream %p: disconnect", s);
- pa_stream_ref(s);
-
- s->disconnecting = true;
- s->stream_index = PA_INVALID_INDEX;
- pw_stream_disconnect(s->stream);
-
- o = pa_operation_new(c, s, on_disconnected, 0);
- pa_operation_sync(o);
- pa_operation_unref(o);
- pa_stream_unref(s);
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_stream_begin_write(
- pa_stream *s,
- void **data,
- size_t *nbytes)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK ||
- s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, data, PA_ERR_INVALID);
- PA_CHECK_VALIDITY(s->context, nbytes && *nbytes != 0, PA_ERR_INVALID);
-
- if (s->mem == NULL)
- s->mem = alloc_mem(s, *nbytes);
- if (s->mem == NULL) {
- *data = NULL;
- *nbytes = 0;
- return -errno;
- }
- s->mem->offset = s->mem->size = 0;
- *data = s->mem->data;
- *nbytes = *nbytes != (size_t)-1 ? SPA_MIN(*nbytes, s->mem->maxsize) : s->mem->maxsize;
-
- pw_log_trace("buffer %p %zd %p", *data, *nbytes, s->mem);
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_stream_cancel_write(pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK ||
- s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- if (s->mem == NULL)
- return 0;
-
- pw_log_trace("cancel %p %p %zd", s->mem, s->mem->data, s->mem->size);
-
- spa_list_prepend(&s->free, &s->mem->link);
- s->mem = NULL;
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_stream_write(pa_stream *s,
- const void *data,
- size_t nbytes,
- pa_free_cb_t free_cb,
- int64_t offset,
- pa_seek_mode_t seek)
-{
- return pa_stream_write_ext_free(s, data, nbytes, free_cb, (void*) data, offset, seek);
-}
-
-SPA_EXPORT
-int pa_stream_write_ext_free(pa_stream *s,
- const void *data,
- size_t nbytes,
- pa_free_cb_t free_cb,
- void *free_cb_data,
- int64_t offset,
- pa_seek_mode_t seek)
-{
- const void *src = data;
- size_t towrite;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- spa_assert(data);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK ||
- s->direction == PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, seek <= PA_SEEK_RELATIVE_END, PA_ERR_INVALID);
- PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_PLAYBACK ||
- (seek == PA_SEEK_RELATIVE && offset == 0), PA_ERR_INVALID);
- PA_CHECK_VALIDITY(s->context,
- s->mem == NULL ||
- ((data >= s->mem->data) &&
- ((const char*) data + nbytes <= (const char*) s->mem->data + s->mem->maxsize)),
- PA_ERR_INVALID);
- PA_CHECK_VALIDITY(s->context, offset % pa_frame_size(&s->sample_spec) == 0, PA_ERR_INVALID);
- PA_CHECK_VALIDITY(s->context, nbytes % pa_frame_size(&s->sample_spec) == 0, PA_ERR_INVALID);
- PA_CHECK_VALIDITY(s->context, !free_cb || !s->buffer, PA_ERR_INVALID);
-
- pw_log_trace("stream %p: write %zd bytes", s, nbytes);
-
- towrite = nbytes;
- while (towrite > 0) {
- size_t dsize = towrite;
- if (s->mem == NULL) {
- void *dst;
- if (pa_stream_begin_write(s, &dst, &dsize) < 0 ||
- dst == NULL || dsize == 0) {
- pw_log_error("stream %p: out of buffers, wanted %zd bytes", s, nbytes);
- break;
- }
- memcpy(dst, src, dsize);
- src = SPA_MEMBER(src, dsize, void);
- } else {
- s->mem->offset = SPA_PTRDIFF(src, s->mem->data);
- }
- towrite -= dsize;
- s->mem->size = dsize;
- if (s->mem->size >= s->mem->maxsize || towrite == 0) {
- spa_list_append(&s->ready, &s->mem->link);
- s->ready_bytes += s->mem->size;
- s->mem = NULL;
- queue_output(s);
- }
- }
- if (free_cb)
- free_cb(free_cb_data);
-
- s->timing_info.write_index += nbytes;
- s->timing_info.since_underrun += nbytes;
- pw_log_trace("stream %p: written %zd bytes", s, nbytes);
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_stream_peek(pa_stream *s,
- const void **data,
- size_t *nbytes)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- spa_assert(data);
- spa_assert(nbytes);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
-
- if (spa_list_is_empty(&s->ready)) {
- errno = EPIPE;
- pw_log_error("stream %p: no buffer: %m", s);
- *data = NULL;
- *nbytes = 0;
- return 0;
- }
- s->mem = spa_list_first(&s->ready, struct pa_mem, link);
- pw_log_trace("peek %p", s->mem);
-
- *data = SPA_MEMBER(s->mem->data, s->mem->offset, void);
- *nbytes = s->mem->size;
-
- pw_log_trace("stream %p: %p %zd", s, *data, *nbytes);
-
- return 0;
-}
-
-SPA_EXPORT
-int pa_stream_drop(pa_stream *s)
-{
- size_t nbytes;
- struct pw_buffer *buf;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->mem, PA_ERR_BADSTATE);
-
- nbytes = s->mem->size;
-
- pw_log_trace("stream %p %zd", s, nbytes);
- spa_list_remove(&s->mem->link);
- s->ready_bytes -= nbytes;
-
- s->timing_info.read_index += nbytes;
-
- buf = s->mem->user_data;
- pw_stream_queue_buffer(s->stream, buf);
- buf->user_data = NULL;
-
- pw_log_trace("drop %p", s->mem);
- spa_list_append(&s->free, &s->mem->link);
- s->mem->user_data = NULL;
- s->mem = NULL;
-
- return 0;
-}
-
-SPA_EXPORT
-size_t pa_stream_writable_size(PA_CONST pa_stream *s)
-{
- const pa_timing_info *i;
- uint64_t now, then, elapsed;
- struct timespec ts;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY,
- PA_ERR_BADSTATE, (size_t) -1);
- PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_RECORD,
- PA_ERR_BADSTATE, (size_t) -1);
-
- i = &s->timing_info;
-
- if (s->have_time) {
- clock_gettime(CLOCK_MONOTONIC, &ts);
- now = SPA_TIMESPEC_TO_USEC(&ts);
- then = SPA_TIMEVAL_TO_USEC(&i->timestamp);
- elapsed = now > then ? pa_usec_to_bytes(now - then, &s->sample_spec) : 0;
- } else {
- elapsed = 0;
- }
-
- return writable_size(s, elapsed);
-}
-
-SPA_EXPORT
-size_t pa_stream_readable_size(PA_CONST pa_stream *s)
-{
- uint64_t readable;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY,
- PA_ERR_BADSTATE, (size_t) -1);
- PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction == PA_STREAM_RECORD,
- PA_ERR_BADSTATE, (size_t) -1);
-
- readable = s->ready_bytes;
- pw_log_trace("stream %p: readable:%"PRIu64" fragsize:%u", s, readable, s->buffer_attr.fragsize);
-
- return readable;
-}
-
-struct success_ack {
- pa_stream_success_cb_t cb;
- void *userdata;
-};
-
-static void on_success(pa_operation *o, void *userdata)
-{
- struct success_ack *d = userdata;
- pa_stream *s = o->stream;
- if (d->cb)
- d->cb(s, 1, d->userdata);
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
-
- pw_log_debug("stream %p", s);
- if (s->corked) {
- s->corked = false;
- pw_stream_set_active(s->stream, true);
- }
- pw_stream_flush(s->stream, true);
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- if (s->drain)
- pa_operation_cancel(s->drain);
- s->drain = o;
-
- return o;
-}
-
-static void on_timing_success(pa_operation *o, void *userdata)
-{
- struct success_ack *d = userdata;
- pa_stream *s = o->stream;
-
- update_timing_info(s);
-
- if (s->latency_update_callback)
- s->latency_update_callback(s, s->latency_update_userdata);
-
- if (d->cb)
- d->cb(s, s->timing_info_valid, d->userdata);
-
- pa_operation_done(o);
-}
-
-SPA_EXPORT
-pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- pw_log_debug("stream %p", s);
- o = pa_operation_new(s->context, s, on_timing_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->state_callback = cb;
- s->state_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_stream_set_write_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_stream_set_read_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->overflow_callback = cb;
- s->overflow_userdata = userdata;
-}
-
-SPA_EXPORT
-int64_t pa_stream_get_underflow_index(PA_CONST pa_stream *s)
-{
- pw_log_warn("Not Implemented");
- return 0;
-}
-
-SPA_EXPORT
-void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->underflow_callback = cb;
- s->underflow_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_stream_set_started_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->started_callback = cb;
- s->started_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->latency_update_callback = cb;
- s->latency_update_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_stream_set_moved_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->moved_callback = cb;
- s->moved_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_stream_set_suspended_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->suspended_callback = cb;
- s->suspended_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_stream_set_event_callback(pa_stream *s, pa_stream_event_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->event_callback = cb;
- s->event_userdata = userdata;
-}
-
-SPA_EXPORT
-void pa_stream_set_buffer_attr_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
- return;
-
- s->buffer_attr_callback = cb;
- s->buffer_attr_userdata = userdata;
-}
-
-SPA_EXPORT
-pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- pw_log_debug("stream %p: cork %d->%d", s, s->corked, b);
- s->corked = b;
- pw_stream_set_active(s->stream, !b);
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
- struct pa_mem *m;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- pw_log_debug("stream %p:", s);
- pw_stream_flush(s->stream, false);
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
-
- spa_list_consume(m, &s->ready, link) {
- struct pw_buffer *b = m->user_data;
- pw_log_trace("flush %p", m);
- spa_list_remove(&m->link);
- spa_list_append(&s->free, &m->link);
- m->user_data = NULL;
- if (b)
- b->user_data = NULL;
- }
- s->ready_bytes = 0;
- s->queued_bytes = 0;
- s->timing_info.write_index = s->timing_info.read_index = 0;
- s->have_time = false;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
-
- pw_log_debug("%p", s);
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
-
- pw_log_debug("%p", s);
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
- struct spa_dict dict;
- struct spa_dict_item items[1];
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- spa_assert(name);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- items[0] = SPA_DICT_ITEM_INIT(PW_KEY_MEDIA_NAME, name);
- dict = SPA_DICT_INIT(items, 1);
- pw_stream_update_properties(s->stream, &dict);
-
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
-
- return o;
-}
-
-SPA_EXPORT
-int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec)
-{
- struct timespec ts;
- uint64_t now, then, res;
- pa_timing_info *i;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- i = &s->timing_info;
-
- if (s->direction == PA_STREAM_PLAYBACK) {
- res = pa_bytes_to_usec((uint64_t) i->read_index, &s->sample_spec);
- res -= SPA_MIN(res, i->sink_usec);
- } else {
- res = pa_bytes_to_usec((uint64_t) i->write_index, &s->sample_spec);
- res += i->source_usec;
- }
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
- now = SPA_TIMESPEC_TO_USEC(&ts);
- then = SPA_TIMEVAL_TO_USEC(&i->timestamp);
- if (s->have_time && now > then)
- res += now - then;
-
- if (r_usec)
- *r_usec = res;
-
- pw_log_trace("stream %p: now:%"PRIu64" diff:%"PRIi64
- " write-index:%"PRIi64" read_index:%"PRIi64" rw-diff:%"PRIi64" res:%"PRIu64,
- s, now, now - res, i->write_index, i->read_index,
- i->write_index - i->read_index, res);
- return 0;
-}
-
-static pa_usec_t time_counter_diff(const pa_stream *s, pa_usec_t a, pa_usec_t b, int *negative) {
- pa_assert(s);
- pa_assert(s->refcount >= 1);
-
- if (negative)
- *negative = 0;
-
- if (a >= b)
- return a-b;
- else {
- if (negative && s->direction == PA_STREAM_RECORD) {
- *negative = 1;
- return b-a;
- } else
- return 0;
- }
-}
-
-SPA_EXPORT
-int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative)
-{
- pa_usec_t t, c;
- int64_t cindex;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- spa_assert(r_usec);
-
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- pa_stream_get_time(s, &t);
-
- if (s->direction == PA_STREAM_PLAYBACK)
- cindex = s->timing_info.write_index;
- else
- cindex = s->timing_info.read_index;
-
- if (cindex < 0)
- cindex = 0;
-
- c = pa_bytes_to_usec((uint64_t) cindex, &s->sample_spec);
-
- if (s->direction == PA_STREAM_PLAYBACK)
- *r_usec = time_counter_diff(s, c, t, negative);
- else
- *r_usec = time_counter_diff(s, t, c, negative);
-
- pw_log_trace("stream %p: now:%"PRIu64" stream:%"PRIu64" cindex:%"PRIi64
- " res:%"PRIu64, s, t, c, cindex, *r_usec);
-
- return 0;
-}
-
-SPA_EXPORT
-const pa_timing_info* pa_stream_get_timing_info(pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- pw_log_trace("stream %p: %"PRIi64" %"PRIi64" %"PRIi64, s,
- s->timing_info.write_index, s->timing_info.read_index,
- (s->timing_info.write_index - s->timing_info.read_index));
-
- return &s->timing_info;
-}
-
-SPA_EXPORT
-const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- return &s->sample_spec;
-}
-
-SPA_EXPORT
-const pa_channel_map* pa_stream_get_channel_map(pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- return &s->channel_map;
-}
-
-SPA_EXPORT
-const pa_format_info* pa_stream_get_format_info(PA_CONST pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
-
- return s->format;
-}
-
-SPA_EXPORT
-const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- return &s->buffer_attr;
-}
-
-SPA_EXPORT
-pa_operation *pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
- spa_assert(attr);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- pw_log_warn("Not Implemented");
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, pa_sample_rate_valid(rate), PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->flags & PA_STREAM_VARIABLE_RATE, PA_ERR_BADSTATE);
-
- pw_log_warn("Not Implemented");
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_stream_proplist_update(pa_stream *s, pa_update_mode_t mode, pa_proplist *p, pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, mode == PA_UPDATE_SET ||
- mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- pa_proplist_update(s->proplist, mode, p);
-
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[], pa_stream_success_cb_t cb, void *userdata)
-{
- pa_operation *o;
- struct success_ack *d;
-
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, keys && keys[0], PA_ERR_INVALID);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
- pw_log_warn("Not Implemented");
- o = pa_operation_new(s->context, s, on_success, sizeof(struct success_ack));
- d = o->userdata;
- d->cb = cb;
- d->userdata = userdata;
- pa_operation_sync(o);
- return o;
-}
-
-SPA_EXPORT
-int pa_stream_set_monitor_stream(pa_stream *s, uint32_t sink_input_idx)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- PA_CHECK_VALIDITY(s->context, sink_input_idx != PA_INVALID_INDEX, PA_ERR_INVALID);
- PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
-
- pw_log_debug("stream %p: Set monitor stream %u", s, sink_input_idx);
- s->direct_on_input = sink_input_idx;
- return 0;
-}
-
-SPA_EXPORT
-uint32_t pa_stream_get_monitor_stream(PA_CONST pa_stream *s)
-{
- spa_assert(s);
- spa_assert(s->refcount >= 1);
-
- pw_log_debug("stream %p: get monitor stream %u", s, s->direct_on_input);
- PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direct_on_input != PA_INVALID_INDEX,
- PA_ERR_BADSTATE, PA_INVALID_INDEX);
-
- return s->direct_on_input;
-}
diff --git a/pipewire-pulseaudio/src/subscribe.c b/pipewire-pulseaudio/src/subscribe.c
deleted file mode 100644
index 4ccdc7c70..000000000
--- a/pipewire-pulseaudio/src/subscribe.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-#include "internal.h"
-
-struct subscribe_data
-{
- pa_context_success_cb_t cb;
- void *userdata;
-};
-
-SPA_EXPORT
-void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t cb, void *userdata)
-{
- pa_assert(c);
- pa_assert(c->refcount >= 1);
-
- if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
- return;
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
-}
diff --git a/pipewire-pulseaudio/src/thread-mainloop.c b/pipewire-pulseaudio/src/thread-mainloop.c
deleted file mode 100644
index 70aeb8a26..000000000
--- a/pipewire-pulseaudio/src/thread-mainloop.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-#include
-
-#include
-#include
-
-#include "internal.h"
-
-struct pa_threaded_mainloop
-{
- pa_mainloop *loop;
- struct pw_thread_loop *tloop;
-};
-
-SPA_EXPORT
-pa_threaded_mainloop *pa_threaded_mainloop_new(void)
-{
- pa_threaded_mainloop *m;
-
- m = calloc(1, sizeof(pa_threaded_mainloop));
- if (m == NULL)
- return NULL;
-
- m->loop = pa_mainloop_new();
- if (m->loop == NULL)
- goto no_mem;
-
- m->tloop = pw_thread_loop_new_full(m->loop->loop, "pipewire-pulse", NULL);
- if (m->tloop == NULL)
- goto no_mem;
-
- return m;
-
- no_mem:
- if (m->loop)
- pa_mainloop_free(m->loop);
- free(m);
- return NULL;
-}
-
-SPA_EXPORT
-void pa_threaded_mainloop_free(pa_threaded_mainloop* m)
-{
- spa_return_if_fail(m != NULL);
- pw_thread_loop_destroy(m->tloop);
- pa_mainloop_free(m->loop);
- free(m);
-}
-
-SPA_EXPORT
-int pa_threaded_mainloop_start(pa_threaded_mainloop *m)
-{
- spa_return_val_if_fail(m != NULL, -EINVAL);
- return pw_thread_loop_start(m->tloop);
-}
-
-SPA_EXPORT
-void pa_threaded_mainloop_stop(pa_threaded_mainloop *m)
-{
- spa_return_if_fail(m != NULL);
- pw_thread_loop_stop(m->tloop);
-}
-
-SPA_EXPORT
-void pa_threaded_mainloop_lock(pa_threaded_mainloop *m)
-{
- spa_return_if_fail(m != NULL);
- pw_thread_loop_lock(m->tloop);
-}
-
-SPA_EXPORT
-void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m)
-{
- spa_return_if_fail(m != NULL);
- pw_thread_loop_unlock(m->tloop);
-}
-
-SPA_EXPORT
-void pa_threaded_mainloop_wait(pa_threaded_mainloop *m)
-{
- spa_return_if_fail(m != NULL);
- pw_thread_loop_wait(m->tloop);
-}
-
-SPA_EXPORT
-void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept)
-{
- spa_return_if_fail(m != NULL);
- pw_thread_loop_signal(m->tloop, wait_for_accept);
-}
-
-SPA_EXPORT
-void pa_threaded_mainloop_accept(pa_threaded_mainloop *m)
-{
- spa_return_if_fail(m != NULL);
- pw_thread_loop_accept(m->tloop);
-}
-
-SPA_EXPORT
-int pa_threaded_mainloop_get_retval(PA_CONST pa_threaded_mainloop *m)
-{
- spa_return_val_if_fail(m != NULL, -EINVAL);
- return pa_mainloop_get_retval(m->loop);
-}
-
-SPA_EXPORT
-pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m)
-{
- spa_return_val_if_fail(m != NULL, NULL);
- return pa_mainloop_get_api(m->loop);
-}
-
-SPA_EXPORT
-int pa_threaded_mainloop_in_thread(pa_threaded_mainloop *m)
-{
- spa_return_val_if_fail(m != NULL, -EINVAL);
- return pw_thread_loop_in_thread(m->tloop);
-}
-
-SPA_EXPORT
-void pa_threaded_mainloop_set_name(pa_threaded_mainloop *m, const char *name)
-{
- spa_return_if_fail(m != NULL);
- spa_return_if_fail(name != NULL);
-}
diff --git a/pipewire-pulseaudio/src/timeval.c b/pipewire-pulseaudio/src/timeval.c
deleted file mode 100644
index e8ca09a9d..000000000
--- a/pipewire-pulseaudio/src/timeval.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2004-2006 Lennart Poettering
- Copyright 2006 Pierre Ossman for Cendio AB
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with PulseAudio; if not, see .
-***/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-#include
-
-#ifdef HAVE_WINDOWS_H
-#include
-#endif
-
-#include
-
-#include "internal.h"
-
-#define HAVE_GETTIMEOFDAY
-
-SPA_EXPORT
-struct timeval *pa_gettimeofday(struct timeval *tv) {
- pa_assert(tv);
-
-#if defined(OS_IS_WIN32)
- /*
- * Copied from implementation by Steven Edwards (LGPL).
- * Found on wine mailing list.
- */
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-#define EPOCHFILETIME (116444736000000000i64)
-#else
-#define EPOCHFILETIME (116444736000000000LL)
-#endif
-{
- FILETIME ft;
- LARGE_INTEGER li;
- int64_t t;
-
- GetSystemTimeAsFileTime(&ft);
- li.LowPart = ft.dwLowDateTime;
- li.HighPart = ft.dwHighDateTime;
- t = li.QuadPart; /* In 100-nanosecond intervals */
- t -= EPOCHFILETIME; /* Offset to the Epoch time */
- t /= 10; /* In microseconds */
- tv->tv_sec = (time_t) (t / PA_USEC_PER_SEC);
- tv->tv_usec = (suseconds_t) (t % PA_USEC_PER_SEC);
-}
-#elif defined(HAVE_GETTIMEOFDAY)
- pa_assert_se(gettimeofday(tv, NULL) == 0);
-#else
-#error "Platform lacks gettimeofday() or equivalent function."
-#endif
-
- return tv;
-}
-
-SPA_EXPORT
-pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
- pa_usec_t r;
-
- pa_assert(a);
- pa_assert(b);
-
- /* Check which is the earlier time and swap the two arguments if required. */
- if (PA_UNLIKELY(pa_timeval_cmp(a, b) < 0)) {
- const struct timeval *c;
- c = a;
- a = b;
- b = c;
- }
-
- /* Calculate the second difference*/
- r = ((pa_usec_t) a->tv_sec - (pa_usec_t) b->tv_sec) * PA_USEC_PER_SEC;
-
- /* Calculate the microsecond difference */
- if (a->tv_usec > b->tv_usec)
- r += (pa_usec_t) a->tv_usec - (pa_usec_t) b->tv_usec;
- else if (a->tv_usec < b->tv_usec)
- r -= (pa_usec_t) b->tv_usec - (pa_usec_t) a->tv_usec;
-
- return r;
-}
-
-SPA_EXPORT
-int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) {
- pa_assert(a);
- pa_assert(b);
-
- if (a->tv_sec < b->tv_sec)
- return -1;
-
- if (a->tv_sec > b->tv_sec)
- return 1;
-
- if (a->tv_usec < b->tv_usec)
- return -1;
-
- if (a->tv_usec > b->tv_usec)
- return 1;
-
- return 0;
-}
-
-SPA_EXPORT
-pa_usec_t pa_timeval_age(const struct timeval *tv) {
- struct timeval now;
- pa_assert(tv);
-
- return pa_timeval_diff(pa_gettimeofday(&now), tv);
-}
-
-SPA_EXPORT
-struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
- time_t secs;
- pa_assert(tv);
-
- secs = (time_t) (v/PA_USEC_PER_SEC);
-
- if (PA_UNLIKELY(tv->tv_sec > PA_INT_TYPE_MAX(time_t) - secs))
- goto overflow;
-
- tv->tv_sec += secs;
- v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
- tv->tv_usec += (suseconds_t) v;
-
- /* Normalize */
- while ((pa_usec_t) tv->tv_usec >= PA_USEC_PER_SEC) {
-
- if (PA_UNLIKELY(tv->tv_sec >= PA_INT_TYPE_MAX(time_t)))
- goto overflow;
-
- tv->tv_sec++;
- tv->tv_usec -= (suseconds_t) PA_USEC_PER_SEC;
- }
-
- return tv;
-
-overflow:
- tv->tv_sec = PA_INT_TYPE_MAX(time_t);
- tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
- return tv;
-}
-
-SPA_EXPORT
-struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
- time_t secs;
- pa_assert(tv);
-
- secs = (time_t) (v/PA_USEC_PER_SEC);
-
- if (PA_UNLIKELY(tv->tv_sec < secs))
- goto underflow;
-
- tv->tv_sec -= secs;
- v -= (pa_usec_t) secs * PA_USEC_PER_SEC;
-
- if (tv->tv_usec >= (suseconds_t) v)
- tv->tv_usec -= (suseconds_t) v;
- else {
-
- if (PA_UNLIKELY(tv->tv_sec <= 0))
- goto underflow;
-
- tv->tv_sec --;
- tv->tv_usec += (suseconds_t) (PA_USEC_PER_SEC - v);
- }
-
- return tv;
-
-underflow:
- tv->tv_sec = 0;
- tv->tv_usec = 0;
- return tv;
-}
-
-SPA_EXPORT
-struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
- pa_assert(tv);
-
- if (PA_UNLIKELY(v == PA_USEC_INVALID)) {
- tv->tv_sec = PA_INT_TYPE_MAX(time_t);
- tv->tv_usec = (suseconds_t) (PA_USEC_PER_SEC-1);
-
- return tv;
- }
-
- tv->tv_sec = (time_t) (v / PA_USEC_PER_SEC);
- tv->tv_usec = (suseconds_t) (v % PA_USEC_PER_SEC);
-
- return tv;
-}
-
-SPA_EXPORT
-pa_usec_t pa_timeval_load(const struct timeval *tv) {
-
- if (PA_UNLIKELY(!tv))
- return PA_USEC_INVALID;
-
- return
- (pa_usec_t) tv->tv_sec * PA_USEC_PER_SEC +
- (pa_usec_t) tv->tv_usec;
-}
diff --git a/pipewire-pulseaudio/src/utf8.c b/pipewire-pulseaudio/src/utf8.c
deleted file mode 100644
index 35e4b6d5f..000000000
--- a/pipewire-pulseaudio/src/utf8.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2006 Lennart Poettering
- Copyright 2006 Pierre Ossman for Cendio AB
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with PulseAudio; if not, see .
-***/
-
-/* This file is based on the GLIB utf8 validation functions. The
- * original license text follows. */
-
-/* gutf8.c - Operations on UTF-8 strings.
- *
- * Copyright (C) 1999 Tom Tromey
- * Copyright (C) 2000 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see .
- */
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-#include
-#include
-#include
-
-#ifdef HAVE_ICONV
-#include
-#endif
-
-#include
-#include
-
-#include "internal.h"
-
-#define FILTER_CHAR '_'
-
-static inline bool is_unicode_valid(uint32_t ch) {
-
- if (ch >= 0x110000) /* End of unicode space */
- return false;
- if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */
- return false;
- if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */
- return false;
- if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */
- return false;
-
- return true;
-}
-
-static inline bool is_continuation_char(uint8_t ch) {
- if ((ch & 0xc0) != 0x80) /* 10xxxxxx */
- return false;
- return true;
-}
-
-static inline void merge_continuation_char(uint32_t *u_ch, uint8_t ch) {
- *u_ch <<= 6;
- *u_ch |= ch & 0x3f;
-}
-
-static char* utf8_validate(const char *str, char *output) {
- uint32_t val = 0;
- uint32_t min = 0;
- const uint8_t *p, *last;
- int size;
- uint8_t *o;
-
- pa_assert(str);
-
- o = (uint8_t*) output;
- for (p = (const uint8_t*) str; *p; p++) {
- if (*p < 128) {
- if (o)
- *o = *p;
- } else {
- last = p;
-
- if ((*p & 0xe0) == 0xc0) { /* 110xxxxx two-char seq. */
- size = 2;
- min = 128;
- val = (uint32_t) (*p & 0x1e);
- goto ONE_REMAINING;
- } else if ((*p & 0xf0) == 0xe0) { /* 1110xxxx three-char seq.*/
- size = 3;
- min = (1 << 11);
- val = (uint32_t) (*p & 0x0f);
- goto TWO_REMAINING;
- } else if ((*p & 0xf8) == 0xf0) { /* 11110xxx four-char seq */
- size = 4;
- min = (1 << 16);
- val = (uint32_t) (*p & 0x07);
- } else
- goto error;
-
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
-TWO_REMAINING:
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
-ONE_REMAINING:
- p++;
- if (!is_continuation_char(*p))
- goto error;
- merge_continuation_char(&val, *p);
-
- if (val < min)
- goto error;
-
- if (!is_unicode_valid(val))
- goto error;
-
- if (o) {
- memcpy(o, last, (size_t) size);
- o += size;
- }
-
- continue;
-
-error:
- if (o) {
- *o = FILTER_CHAR;
- p = last; /* We retry at the next character */
- } else
- goto failure;
- }
-
- if (o)
- o++;
- }
-
- if (o) {
- *o = '\0';
- return output;
- }
-
- return (char*) str;
-
-failure:
- return NULL;
-}
-
-SPA_EXPORT
-char* pa_utf8_valid (const char *str) {
- return utf8_validate(str, NULL);
-}
-
-SPA_EXPORT
-char* pa_utf8_filter (const char *str) {
- char *new_str;
-
- pa_assert(str);
- new_str = pa_xmalloc(strlen(str) + 1);
- return utf8_validate(str, new_str);
-}
-
-#ifdef HAVE_ICONV
-
-static char* iconv_simple(const char *str, const char *to, const char *from) {
- char *new_str;
- size_t len, inlen;
- iconv_t cd;
- ICONV_CONST char *inbuf;
- char *outbuf;
- size_t res, inbytes, outbytes;
-
- pa_assert(str);
- pa_assert(to);
- pa_assert(from);
-
- cd = iconv_open(to, from);
- if (cd == (iconv_t)-1)
- return NULL;
-
- inlen = len = strlen(str) + 1;
- new_str = pa_xmalloc(len);
-
- for (;;) {
- inbuf = (ICONV_CONST char*) str; /* Brain dead prototype for iconv() */
- inbytes = inlen;
- outbuf = new_str;
- outbytes = len;
-
- res = iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes);
-
- if (res != (size_t)-1)
- break;
-
- if (errno != E2BIG) {
- pa_xfree(new_str);
- new_str = NULL;
- break;
- }
-
- pa_assert(inbytes != 0);
-
- len += inbytes;
- new_str = pa_xrealloc(new_str, len);
- }
-
- iconv_close(cd);
-
- return new_str;
-}
-
-SPA_EXPORT
-char* pa_utf8_to_locale (const char *str) {
- return iconv_simple(str, "", "UTF-8");
-}
-
-SPA_EXPORT
-char* pa_locale_to_utf8 (const char *str) {
- return iconv_simple(str, "UTF-8", "");
-}
-
-#else
-
-SPA_EXPORT
-char* pa_utf8_to_locale (const char *str) {
- pa_assert(str);
-
- return pa_ascii_filter(str);
-}
-
-SPA_EXPORT
-char* pa_locale_to_utf8 (const char *str) {
- pa_assert(str);
-
- if (pa_utf8_valid(str))
- return pa_xstrdup(str);
-
- return NULL;
-}
-
-#endif
-
-SPA_EXPORT
-char *pa_ascii_valid(const char *str) {
- const char *p;
- pa_assert(str);
-
- for (p = str; *p; p++)
- if ((unsigned char) *p >= 128)
- return NULL;
-
- return (char*) str;
-}
-
-SPA_EXPORT
-char *pa_ascii_filter(const char *str) {
- char *r, *s, *d;
- pa_assert(str);
-
- r = pa_xstrdup(str);
-
- for (s = r, d = r; *s; s++)
- if ((unsigned char) *s < 128)
- *(d++) = *s;
-
- *d = 0;
-
- return r;
-}
diff --git a/pipewire-pulseaudio/src/util.c b/pipewire-pulseaudio/src/util.c
deleted file mode 100644
index 66d9baa33..000000000
--- a/pipewire-pulseaudio/src/util.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-#include
-#include
-
-#include
-#include
-
-#include
-
-#include "internal.h"
-
-#define PA_PATH_SEP_CHAR '/'
-
-SPA_EXPORT
-char *pa_get_user_name(char *s, size_t l)
-{
- return strncpy(s, pw_get_user_name(), l);
-}
-
-
-SPA_EXPORT
-char *pa_get_host_name(char *s, size_t l)
-{
- return strncpy(s, pw_get_host_name(), l);
-}
-
-SPA_EXPORT
-char *pa_get_fqdn(char *s, size_t l)
-{
- return strncpy(s, pw_get_host_name(), l);
-}
-
-SPA_EXPORT
-char *pa_get_home_dir(char *s, size_t l)
-{
- const char *home;
- home = getenv("HOME");
- if (home == NULL)
- home = getenv("USERPROFILE");
- if (home == NULL) {
- struct passwd pwd, *result = NULL;
- char buffer[4096];
- if (getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &result) == 0)
- home = result ? result->pw_dir : NULL;
- }
- if (home) {
- strncpy(s, home, l);
- s[l] = 0;
- }
- return home ? s : NULL;
-}
-
-SPA_EXPORT
-char *pa_get_runtime_dir(void)
-{
- const char *runtime;
- runtime = getenv("PULSE_RUNTIME_PATH");
- if (runtime == NULL)
- runtime = getenv("XDG_RUNTIME_DIR");
- if (runtime == NULL) {
- char buffer[4096];
- runtime = pa_get_home_dir(buffer, sizeof(buffer));
- }
- return runtime ? strdup(runtime) : NULL;
-
-}
-
-SPA_EXPORT
-char *pa_get_binary_name(char *s, size_t l)
-{
- return strncpy(s, pw_get_prgname(), l);
-}
-
-SPA_EXPORT
-char *pa_path_get_filename(const char *p)
-{
- char *fn;
-
- if (!p)
- return NULL;
-
- if ((fn = strrchr(p, PA_PATH_SEP_CHAR)))
- return fn+1;
-
- return (char*) p;
-}
-
-SPA_EXPORT
-int pa_msleep(unsigned long t)
-{
- struct timespec ts;
-
- ts.tv_sec = (time_t) (t / SPA_MSEC_PER_SEC);
- ts.tv_nsec = (long) ((t % SPA_MSEC_PER_SEC) * SPA_NSEC_PER_MSEC);
-
- return nanosleep(&ts, NULL);
-}
-
-bool pa_endswith(const char *s, const char *sfx)
-{
- size_t l1, l2;
- l1 = strlen(s);
- l2 = strlen(sfx);
- return l1 >= l2 && pa_streq(s + l1 - l2, sfx);
-}
diff --git a/pipewire-pulseaudio/src/version.c b/pipewire-pulseaudio/src/version.c
deleted file mode 100644
index 69e269c2a..000000000
--- a/pipewire-pulseaudio/src/version.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-
-#include
-
-SPA_EXPORT
-const char* pa_get_library_version(void)
-{
- return pa_get_headers_version();
-}
-
-SPA_EXPORT
-bool pa_is_pipewire(void)
-{
- return true;
-}
diff --git a/pipewire-pulseaudio/src/volume.c b/pipewire-pulseaudio/src/volume.c
deleted file mode 100644
index 35527ba75..000000000
--- a/pipewire-pulseaudio/src/volume.c
+++ /dev/null
@@ -1,1037 +0,0 @@
-/***
- This file is part of PulseAudio.
-
- Copyright 2004-2006 Lennart Poettering
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, see .
-***/
-
-#ifdef HAVE_CONFIG_H
-#include
-#endif
-
-#include
-#include
-#include
-
-#include
-
-#include "internal.h"
-#include "sample-util.h"
-
-SPA_EXPORT
-int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
- int i;
- pa_assert(a);
- pa_assert(b);
-
- pa_return_val_if_fail(pa_cvolume_valid(a), 0);
-
- if (PA_UNLIKELY(a == b))
- return 1;
-
- pa_return_val_if_fail(pa_cvolume_valid(b), 0);
-
- if (a->channels != b->channels)
- return 0;
-
- for (i = 0; i < a->channels; i++)
- if (a->values[i] != b->values[i])
- return 0;
-
- return 1;
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_init(pa_cvolume *a) {
- unsigned c;
-
- pa_assert(a);
-
- a->channels = 0;
-
- for (c = 0; c < PA_CHANNELS_MAX; c++)
- a->values[c] = PA_VOLUME_INVALID;
-
- return a;
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
- int i;
-
- pa_assert(a);
- pa_assert(pa_channels_valid(channels));
-
- a->channels = (uint8_t) channels;
-
- for (i = 0; i < a->channels; i++)
- /* Clamp in case there is stale data that exceeds the current
- * PA_VOLUME_MAX */
- a->values[i] = PA_CLAMP_VOLUME(v);
-
- return a;
-}
-
-SPA_EXPORT
-pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {
- uint64_t sum = 0;
- unsigned c;
-
- pa_assert(a);
- pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
-
- for (c = 0; c < a->channels; c++)
- sum += a->values[c];
-
- sum /= a->channels;
-
- return (pa_volume_t) sum;
-}
-
-SPA_EXPORT
-pa_volume_t pa_cvolume_avg_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
- uint64_t sum = 0;
- unsigned c, n;
-
- pa_assert(a);
-
- if (!cm)
- return pa_cvolume_avg(a);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
-
- for (c = n = 0; c < a->channels; c++) {
-
- if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
- continue;
-
- sum += a->values[c];
- n ++;
- }
-
- if (n > 0)
- sum /= n;
-
- return (pa_volume_t) sum;
-}
-
-SPA_EXPORT
-pa_volume_t pa_cvolume_max(const pa_cvolume *a) {
- pa_volume_t m = PA_VOLUME_MUTED;
- unsigned c;
-
- pa_assert(a);
- pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
-
- for (c = 0; c < a->channels; c++)
- if (a->values[c] > m)
- m = a->values[c];
-
- return m;
-}
-
-SPA_EXPORT
-pa_volume_t pa_cvolume_min(const pa_cvolume *a) {
- pa_volume_t m = PA_VOLUME_MAX;
- unsigned c;
-
- pa_assert(a);
- pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
-
- for (c = 0; c < a->channels; c++)
- if (a->values[c] < m)
- m = a->values[c];
-
- return m;
-}
-
-SPA_EXPORT
-pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
- pa_volume_t m = PA_VOLUME_MUTED;
- unsigned c;
-
- pa_assert(a);
-
- if (!cm)
- return pa_cvolume_max(a);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
-
- for (c = 0; c < a->channels; c++) {
-
- if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
- continue;
-
- if (a->values[c] > m)
- m = a->values[c];
- }
-
- return m;
-}
-
-SPA_EXPORT
-pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
- pa_volume_t m = PA_VOLUME_MAX;
- unsigned c;
-
- pa_assert(a);
-
- if (!cm)
- return pa_cvolume_min(a);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
-
- for (c = 0; c < a->channels; c++) {
-
- if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
- continue;
-
- if (a->values[c] < m)
- m = a->values[c];
- }
-
- return m;
-}
-
-SPA_EXPORT
-pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
- uint64_t result;
-
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(a), PA_VOLUME_INVALID);
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), PA_VOLUME_INVALID);
-
- /* cbrt((a/PA_VOLUME_NORM)^3*(b/PA_VOLUME_NORM)^3)*PA_VOLUME_NORM = a*b/PA_VOLUME_NORM */
-
- result = ((uint64_t) a * (uint64_t) b + (uint64_t) PA_VOLUME_NORM / 2ULL) / (uint64_t) PA_VOLUME_NORM;
-
- if (result > (uint64_t)PA_VOLUME_MAX)
- pa_log_warn("pa_sw_volume_multiply: Volume exceeds maximum allowed value and will be clipped. Please check your volume settings.");
-
- return (pa_volume_t) PA_CLAMP_VOLUME(result);
-}
-
-SPA_EXPORT
-pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
- uint64_t result;
-
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(a), PA_VOLUME_INVALID);
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), PA_VOLUME_INVALID);
-
- if (b <= PA_VOLUME_MUTED)
- return 0;
-
- result = ((uint64_t) a * (uint64_t) PA_VOLUME_NORM + (uint64_t) b / 2ULL) / (uint64_t) b;
-
- if (result > (uint64_t)PA_VOLUME_MAX)
- pa_log_warn("pa_sw_volume_divide: Volume exceeds maximum allowed value and will be clipped. Please check your volume settings.");
-
- return (pa_volume_t) PA_CLAMP_VOLUME(result);
-}
-
-/* Amplitude, not power */
-static double linear_to_dB(double v) {
- return 20.0 * log10(v);
-}
-
-static double dB_to_linear(double v) {
- return pow(10.0, v / 20.0);
-}
-
-SPA_EXPORT
-pa_volume_t pa_sw_volume_from_dB(double dB) {
- if (isinf(dB) < 0 || dB <= PA_DECIBEL_MININFTY)
- return PA_VOLUME_MUTED;
-
- return pa_sw_volume_from_linear(dB_to_linear(dB));
-}
-
-SPA_EXPORT
-double pa_sw_volume_to_dB(pa_volume_t v) {
-
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), PA_DECIBEL_MININFTY);
-
- if (v <= PA_VOLUME_MUTED)
- return PA_DECIBEL_MININFTY;
-
- return linear_to_dB(pa_sw_volume_to_linear(v));
-}
-
-SPA_EXPORT
-pa_volume_t pa_sw_volume_from_linear(double v) {
-
- if (v <= 0.0)
- return PA_VOLUME_MUTED;
-
- /*
- * We use a cubic mapping here, as suggested and discussed here:
- *
- * http://www.robotplanet.dk/audio/audio_gui_design/
- * http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-May/thread.html#23151
- *
- * We make sure that the conversion to linear and back yields the
- * same volume value! That's why we need the lround() below!
- */
-
- return (pa_volume_t) PA_CLAMP_VOLUME((uint64_t) lround(cbrt(v) * PA_VOLUME_NORM));
-}
-
-SPA_EXPORT
-double pa_sw_volume_to_linear(pa_volume_t v) {
- double f;
-
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0.0);
-
- if (v <= PA_VOLUME_MUTED)
- return 0.0;
-
- if (v == PA_VOLUME_NORM)
- return 1.0;
-
- f = ((double) v / PA_VOLUME_NORM);
-
- return f*f*f;
-}
-
-SPA_EXPORT
-char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
- unsigned channel;
- bool first = true;
- char *e;
-
- pa_assert(s);
- pa_assert(l > 0);
- pa_assert(c);
-
- pa_init_i18n();
-
- if (!pa_cvolume_valid(c)) {
- pa_snprintf(s, l, _("(invalid)"));
- return s;
- }
-
- *(e = s) = 0;
-
- for (channel = 0; channel < c->channels && l > 1; channel++) {
- l -= pa_snprintf(e, l, "%s%u: %3u%%",
- first ? "" : " ",
- channel,
- (unsigned)(((uint64_t)c->values[channel] * 100 + (uint64_t)PA_VOLUME_NORM / 2) / (uint64_t)PA_VOLUME_NORM));
-
- e = strchr(e, 0);
- first = false;
- }
-
- return s;
-}
-
-SPA_EXPORT
-char *pa_volume_snprint(char *s, size_t l, pa_volume_t v) {
- pa_assert(s);
- pa_assert(l > 0);
-
- pa_init_i18n();
-
- if (!PA_VOLUME_IS_VALID(v)) {
- pa_snprintf(s, l, _("(invalid)"));
- return s;
- }
-
- pa_snprintf(s, l, "%3u%%", (unsigned)(((uint64_t)v * 100 + (uint64_t)PA_VOLUME_NORM / 2) / (uint64_t)PA_VOLUME_NORM));
- return s;
-}
-
-SPA_EXPORT
-char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
- unsigned channel;
- bool first = true;
- char *e;
-
- pa_assert(s);
- pa_assert(l > 0);
- pa_assert(c);
-
- pa_init_i18n();
-
- if (!pa_cvolume_valid(c)) {
- pa_snprintf(s, l, _("(invalid)"));
- return s;
- }
-
- *(e = s) = 0;
-
- for (channel = 0; channel < c->channels && l > 1; channel++) {
- double f = pa_sw_volume_to_dB(c->values[channel]);
-
- l -= pa_snprintf(e, l, "%s%u: %0.2f dB",
- first ? "" : " ",
- channel,
- isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
-
- e = strchr(e, 0);
- first = false;
- }
-
- return s;
-}
-
-SPA_EXPORT
-char *pa_cvolume_snprint_verbose(char *s, size_t l, const pa_cvolume *c, const pa_channel_map *map, int print_dB) {
- char *current = s;
- bool first = true;
-
- pa_assert(s);
- pa_assert(l > 0);
- pa_assert(c);
-
- pa_init_i18n();
-
- if (!pa_cvolume_valid(c)) {
- pa_snprintf(s, l, _("(invalid)"));
- return s;
- }
-
- pa_assert(!map || (map->channels == c->channels));
- pa_assert(!map || pa_channel_map_valid(map));
-
- current[0] = 0;
-
- for (unsigned channel = 0; channel < c->channels && l > 1; channel++) {
- char channel_position[32];
- size_t bytes_printed;
- char buf[PA_VOLUME_SNPRINT_VERBOSE_MAX];
-
- if (map)
- pa_snprintf(channel_position, sizeof(channel_position), "%s", pa_channel_position_to_string(map->map[channel]));
- else
- pa_snprintf(channel_position, sizeof(channel_position), "%u", channel);
-
- bytes_printed = pa_snprintf(current, l, "%s%s: %s",
- first ? "" : ", ",
- channel_position,
- pa_volume_snprint_verbose(buf, sizeof(buf), c->values[channel], print_dB));
- l -= bytes_printed;
- current += bytes_printed;
- first = false;
- }
-
- return s;
-}
-
-SPA_EXPORT
-char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) {
- double f;
-
- pa_assert(s);
- pa_assert(l > 0);
-
- pa_init_i18n();
-
- if (!PA_VOLUME_IS_VALID(v)) {
- pa_snprintf(s, l, _("(invalid)"));
- return s;
- }
-
- f = pa_sw_volume_to_dB(v);
- pa_snprintf(s, l, "%0.2f dB", isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
-
- return s;
-}
-
-SPA_EXPORT
-char *pa_volume_snprint_verbose(char *s, size_t l, pa_volume_t v, int print_dB) {
- char dB[PA_SW_VOLUME_SNPRINT_DB_MAX];
-
- pa_assert(s);
- pa_assert(l > 0);
-
- pa_init_i18n();
-
- if (!PA_VOLUME_IS_VALID(v)) {
- pa_snprintf(s, l, _("(invalid)"));
- return s;
- }
-
- pa_snprintf(s, l, "%" PRIu32 " / %3u%%%s%s",
- v,
- (unsigned)(((uint64_t)v * 100 + (uint64_t)PA_VOLUME_NORM / 2) / (uint64_t)PA_VOLUME_NORM),
- print_dB ? " / " : "",
- print_dB ? pa_sw_volume_snprint_dB(dB, sizeof(dB), v) : "");
-
- return s;
-}
-
-SPA_EXPORT
-int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
- unsigned c;
- pa_assert(a);
-
- pa_return_val_if_fail(pa_cvolume_valid(a), 0);
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0);
-
- for (c = 0; c < a->channels; c++)
- if (a->values[c] != v)
- return 0;
-
- return 1;
-}
-
-SPA_EXPORT
-pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
- unsigned i;
-
- pa_assert(dest);
- pa_assert(a);
- pa_assert(b);
-
- pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
- pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
-
- dest->channels = PA_MIN(a->channels, b->channels);
-
- for (i = 0; i < dest->channels; i++)
- dest->values[i] = pa_sw_volume_multiply(a->values[i], b->values[i]);
-
- return dest;
-}
-
-SPA_EXPORT
-pa_cvolume *pa_sw_cvolume_multiply_scalar(pa_cvolume *dest, const pa_cvolume *a, pa_volume_t b) {
- unsigned i;
-
- pa_assert(dest);
- pa_assert(a);
-
- pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), NULL);
-
- for (i = 0; i < a->channels; i++)
- dest->values[i] = pa_sw_volume_multiply(a->values[i], b);
-
- dest->channels = (uint8_t) i;
-
- return dest;
-}
-
-SPA_EXPORT
-pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
- unsigned i;
-
- pa_assert(dest);
- pa_assert(a);
- pa_assert(b);
-
- pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
- pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
-
- dest->channels = PA_MIN(a->channels, b->channels);
-
- for (i = 0; i < dest->channels; i++)
- dest->values[i] = pa_sw_volume_divide(a->values[i], b->values[i]);
-
- return dest;
-}
-
-SPA_EXPORT
-pa_cvolume *pa_sw_cvolume_divide_scalar(pa_cvolume *dest, const pa_cvolume *a, pa_volume_t b) {
- unsigned i;
-
- pa_assert(dest);
- pa_assert(a);
-
- pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), NULL);
-
- for (i = 0; i < a->channels; i++)
- dest->values[i] = pa_sw_volume_divide(a->values[i], b);
-
- dest->channels = (uint8_t) i;
-
- return dest;
-}
-
-SPA_EXPORT
-int pa_cvolume_valid(const pa_cvolume *v) {
- unsigned c;
-
- pa_assert(v);
-
- if (!pa_channels_valid(v->channels))
- return 0;
-
- for (c = 0; c < v->channels; c++)
- if (!PA_VOLUME_IS_VALID(v->values[c]))
- return 0;
-
- return 1;
-}
-
-static bool on_left(pa_channel_position_t p) {
- return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_LEFT);
-}
-
-static bool on_right(pa_channel_position_t p) {
- return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_RIGHT);
-}
-
-static bool on_center(pa_channel_position_t p) {
- return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_CENTER);
-}
-
-static bool on_hfe(pa_channel_position_t p) {
- return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_HFE);
-}
-
-static bool on_lfe(pa_channel_position_t p) {
- return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_LFE);
-}
-
-static bool on_front(pa_channel_position_t p) {
- return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_FRONT);
-}
-
-static bool on_rear(pa_channel_position_t p) {
- return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_REAR);
-}
-
-SPA_EXPORT
-pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa_channel_map *to) {
- int a, b;
- pa_cvolume result;
-
- pa_assert(v);
- pa_assert(from);
- pa_assert(to);
-
- pa_return_val_if_fail(pa_channel_map_valid(to), NULL);
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, from), NULL);
-
- if (pa_channel_map_equal(from, to))
- return v;
-
- result.channels = to->channels;
-
- for (b = 0; b < to->channels; b++) {
- pa_volume_t k = 0;
- int n = 0;
-
- for (a = 0; a < from->channels; a++)
- if (from->map[a] == to->map[b]) {
- k += v->values[a];
- n ++;
- }
-
- if (n <= 0) {
- for (a = 0; a < from->channels; a++)
- if ((on_left(from->map[a]) && on_left(to->map[b])) ||
- (on_right(from->map[a]) && on_right(to->map[b])) ||
- (on_center(from->map[a]) && on_center(to->map[b])) ||
- (on_lfe(from->map[a]) && on_lfe(to->map[b]))) {
-
- k += v->values[a];
- n ++;
- }
- }
-
- if (n <= 0)
- k = pa_cvolume_avg(v);
- else
- k /= n;
-
- result.values[b] = k;
- }
-
- *v = result;
- return v;
-}
-
-SPA_EXPORT
-int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) {
-
- pa_assert(v);
- pa_assert(ss);
-
- pa_return_val_if_fail(pa_cvolume_valid(v), 0);
- pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
-
- return v->channels == ss->channels;
-}
-
-SPA_EXPORT
-int pa_cvolume_compatible_with_channel_map(const pa_cvolume *v, const pa_channel_map *cm) {
- pa_assert(v);
- pa_assert(cm);
-
- pa_return_val_if_fail(pa_cvolume_valid(v), 0);
- pa_return_val_if_fail(pa_channel_map_valid(cm), 0);
-
- return v->channels == cm->channels;
-}
-
-/*
- * Returns the average volume of l and r, where l and r are two disjoint sets of channels
- * (e g left and right, or front and rear).
- */
-static void get_avg(const pa_channel_map *map, const pa_cvolume *v, pa_volume_t *l, pa_volume_t *r,
- bool (*on_l)(pa_channel_position_t), bool (*on_r)(pa_channel_position_t)) {
- int c;
- pa_volume_t left = 0, right = 0;
- unsigned n_left = 0, n_right = 0;
-
- pa_assert(v);
- pa_assert(map);
- pa_assert(map->channels == v->channels);
- pa_assert(l);
- pa_assert(r);
-
- for (c = 0; c < map->channels; c++) {
- if (on_l(map->map[c])) {
- left += v->values[c];
- n_left++;
- } else if (on_r(map->map[c])) {
- right += v->values[c];
- n_right++;
- }
- }
-
- if (n_left <= 0)
- *l = PA_VOLUME_NORM;
- else
- *l = left / n_left;
-
- if (n_right <= 0)
- *r = PA_VOLUME_NORM;
- else
- *r = right / n_right;
-}
-
-SPA_EXPORT
-float pa_cvolume_get_balance(const pa_cvolume *v, const pa_channel_map *map) {
- pa_volume_t left, right;
-
- pa_assert(v);
- pa_assert(map);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
-
- if (!pa_channel_map_can_balance(map))
- return 0.0f;
-
- get_avg(map, v, &left, &right, on_left, on_right);
-
- if (left == right)
- return 0.0f;
-
- /* 1.0, 0.0 => -1.0
- 0.0, 1.0 => 1.0
- 0.0, 0.0 => 0.0
- 0.5, 0.5 => 0.0
- 1.0, 0.5 => -0.5
- 1.0, 0.25 => -0.75
- 0.75, 0.25 => -0.66
- 0.5, 0.25 => -0.5 */
-
- if (left > right)
- return -1.0f + ((float) right / (float) left);
- else
- return 1.0f - ((float) left / (float) right);
-}
-
-static pa_cvolume* set_balance(pa_cvolume *v, const pa_channel_map *map, float new_balance,
- bool (*on_l)(pa_channel_position_t), bool (*on_r)(pa_channel_position_t)) {
-
- pa_volume_t left, nleft, right, nright, m;
- unsigned c;
-
- get_avg(map, v, &left, &right, on_l, on_r);
-
- m = PA_MAX(left, right);
-
- if (new_balance <= 0) {
- nright = (new_balance + 1.0f) * m;
- nleft = m;
- } else {
- nleft = (1.0f - new_balance) * m;
- nright = m;
- }
-
- for (c = 0; c < map->channels; c++) {
- if (on_l(map->map[c])) {
- if (left == 0)
- v->values[c] = nleft;
- else
- v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) nleft) / (uint64_t) left);
- } else if (on_r(map->map[c])) {
- if (right == 0)
- v->values[c] = nright;
- else
- v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) nright) / (uint64_t) right);
- }
- }
-
- return v;
-}
-
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, float new_balance) {
- pa_assert(map);
- pa_assert(v);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
- pa_return_val_if_fail(new_balance >= -1.0f, NULL);
- pa_return_val_if_fail(new_balance <= 1.0f, NULL);
-
- if (!pa_channel_map_can_balance(map))
- return v;
-
- return set_balance(v, map, new_balance, on_left, on_right);
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {
- unsigned c;
- pa_volume_t t = 0;
-
- pa_assert(v);
-
- pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(max), NULL);
-
- t = pa_cvolume_max(v);
-
- if (t <= PA_VOLUME_MUTED)
- return pa_cvolume_set(v, v->channels, max);
-
- for (c = 0; c < v->channels; c++)
- v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) max) / (uint64_t) t);
-
- return v;
-}
-
-SPA_EXPORT
-#if PA_CHECK_VERSION(12, 0, 0)
-pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
-#else
-pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, pa_channel_map *cm, pa_channel_position_mask_t mask) {
-#endif
- unsigned c;
- pa_volume_t t = 0;
-
- pa_assert(v);
-
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(max), NULL);
-
- if (!cm)
- return pa_cvolume_scale(v, max);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, cm), NULL);
-
- t = pa_cvolume_max_mask(v, cm, mask);
-
- if (t <= PA_VOLUME_MUTED)
- return pa_cvolume_set(v, v->channels, max);
-
- for (c = 0; c < v->channels; c++)
- v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) max) / (uint64_t) t);
-
- return v;
-}
-
-SPA_EXPORT
-float pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) {
- pa_volume_t rear, front;
-
- pa_assert(v);
- pa_assert(map);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
-
- if (!pa_channel_map_can_fade(map))
- return 0.0f;
-
- get_avg(map, v, &rear, &front, on_rear, on_front);
-
- if (front == rear)
- return 0.0f;
-
- if (rear > front)
- return -1.0f + ((float) front / (float) rear);
- else
- return 1.0f - ((float) rear / (float) front);
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float new_fade) {
- pa_assert(map);
- pa_assert(v);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
- pa_return_val_if_fail(new_fade >= -1.0f, NULL);
- pa_return_val_if_fail(new_fade <= 1.0f, NULL);
-
- if (!pa_channel_map_can_fade(map))
- return v;
-
- return set_balance(v, map, new_fade, on_rear, on_front);
-}
-
-SPA_EXPORT
-float pa_cvolume_get_lfe_balance(const pa_cvolume *v, const pa_channel_map *map) {
- pa_volume_t hfe, lfe;
-
- pa_assert(v);
- pa_assert(map);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
-
- if (!pa_channel_map_can_lfe_balance(map))
- return 0.0f;
-
- get_avg(map, v, &hfe, &lfe, on_hfe, on_lfe);
-
- if (hfe == lfe)
- return 0.0f;
-
- if (hfe > lfe)
- return -1.0f + ((float) lfe / (float) hfe);
- else
- return 1.0f - ((float) hfe / (float) lfe);
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_set_lfe_balance(pa_cvolume *v, const pa_channel_map *map, float new_balance) {
- pa_assert(map);
- pa_assert(v);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
- pa_return_val_if_fail(new_balance >= -1.0f, NULL);
- pa_return_val_if_fail(new_balance <= 1.0f, NULL);
-
- if (!pa_channel_map_can_lfe_balance(map))
- return v;
-
- return set_balance(v, map, new_balance, on_hfe, on_lfe);
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_set_position(
- pa_cvolume *cv,
- const pa_channel_map *map,
- pa_channel_position_t t,
- pa_volume_t v) {
-
- unsigned c;
- bool good = false;
-
- pa_assert(cv);
- pa_assert(map);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), NULL);
- pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, NULL);
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), NULL);
-
- for (c = 0; c < map->channels; c++)
- if (map->map[c] == t) {
- cv->values[c] = v;
- good = true;
- }
-
- return good ? cv : NULL;
-}
-
-SPA_EXPORT
-pa_volume_t pa_cvolume_get_position(
- PA_CONST pa_cvolume *cv,
- const pa_channel_map *map,
- pa_channel_position_t t) {
-
- unsigned c;
- pa_volume_t v = PA_VOLUME_MUTED;
-
- pa_assert(cv);
- pa_assert(map);
-
- pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), PA_VOLUME_MUTED);
- pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, PA_VOLUME_MUTED);
-
- for (c = 0; c < map->channels; c++)
- if (map->map[c] == t)
- if (cv->values[c] > v)
- v = cv->values[c];
-
- return v;
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_merge(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
- unsigned i;
-
- pa_assert(dest);
- pa_assert(a);
- pa_assert(b);
-
- pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
- pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
-
- dest->channels = PA_MIN(a->channels, b->channels);
-
- for (i = 0; i < dest->channels; i++)
- dest->values[i] = PA_MAX(a->values[i], b->values[i]);
-
- return dest;
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_inc_clamp(pa_cvolume *v, pa_volume_t inc, pa_volume_t limit) {
- pa_volume_t m;
-
- pa_assert(v);
-
- pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(inc), NULL);
-
- m = pa_cvolume_max(v);
-
- if (m >= limit - inc)
- m = limit;
- else
- m += inc;
-
- return pa_cvolume_scale(v, m);
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) {
- return pa_cvolume_inc_clamp(v, inc, PA_VOLUME_MAX);
-}
-
-SPA_EXPORT
-pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) {
- pa_volume_t m;
-
- pa_assert(v);
-
- pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
- pa_return_val_if_fail(PA_VOLUME_IS_VALID(dec), NULL);
-
- m = pa_cvolume_max(v);
-
- if (m <= PA_VOLUME_MUTED + dec)
- m = PA_VOLUME_MUTED;
- else
- m -= dec;
-
- return pa_cvolume_scale(v, m);
-}
diff --git a/pipewire-pulseaudio/src/xmalloc.c b/pipewire-pulseaudio/src/xmalloc.c
deleted file mode 100644
index 79f4a6790..000000000
--- a/pipewire-pulseaudio/src/xmalloc.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/* PipeWire
- * Copyright (C) 2018 Wim Taymans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include
-#include
-
-#include
-
-#include
-
-#define MAX_ALLOC_SIZE (1024*1024*96) /* 96MB */
-
-static void oom(void) {
- static const char e[] = "Not enough memory\n";
- if (write(STDERR_FILENO, e, sizeof(e)-1) < 0)
- perror("write");
-#ifdef SIGQUIT
- raise(SIGQUIT);
-#endif
- _exit(1);
-}
-
-SPA_EXPORT
-void* pa_xmalloc(size_t l)
-{
- void *p;
- spa_assert(l > 0);
- spa_assert(l < MAX_ALLOC_SIZE);
-
- if (!(p = malloc(l)))
- oom();
-
- return p;
-}
-
-SPA_EXPORT
-void *pa_xmalloc0(size_t l)
-{
- void *p;
- spa_assert(l > 0);
- spa_assert(l < MAX_ALLOC_SIZE);
-
- if (!(p = calloc(1, l)))
- oom();
-
- return p;
-}
-
-SPA_EXPORT
-void *pa_xrealloc(void *ptr, size_t size)
-{
- void *p;
- spa_assert(size > 0);
- spa_assert(size < MAX_ALLOC_SIZE);
-
- if (!(p = realloc(ptr, size)))
- oom();
- return p;
-}
-
-SPA_EXPORT
-void pa_xfree(void *p)
-{
- int saved_errno;
- if (!p)
- return;
- saved_errno = errno;
- free(p);
- errno = saved_errno;
-}
-
-SPA_EXPORT
-char *pa_xstrdup(const char *s)
-{
- if (!s)
- return NULL;
- return pa_xmemdup(s, strlen(s)+1);
-}
-
-SPA_EXPORT
-char *pa_xstrndup(const char *s, size_t l)
-{
- char *e, *r;
-
- if (!s)
- return NULL;
-
- if ((e = memchr(s, 0, l)))
- return pa_xmemdup(s, (size_t) (e-s+1));
-
- r = pa_xmalloc(l+1);
- memcpy(r, s, l);
- r[l] = 0;
- return r;
-}
-
-SPA_EXPORT
-void* pa_xmemdup(const void *p, size_t l)
-{
- if (!p)
- return NULL;
- else {
- char *r = pa_xmalloc(l);
- memcpy(r, p, l);
- return r;
- }
-}
diff --git a/pipewire-pulseaudio/test/meson.build b/pipewire-pulseaudio/test/meson.build
deleted file mode 100644
index 6bbcaff3a..000000000
--- a/pipewire-pulseaudio/test/meson.build
+++ /dev/null
@@ -1,7 +0,0 @@
-executable('test-volume',
- 'test-volume.c',
- c_args : [ '-D_GNU_SOURCE' ],
- install : installed_tests_enabled,
- install_dir : join_paths(installed_tests_execdir, 'examples'),
- dependencies : [pipewire_dep, mathlib, pulseaudio_dep],
-)
diff --git a/pipewire-pulseaudio/test/test-volume.c b/pipewire-pulseaudio/test/test-volume.c
deleted file mode 100644
index 4fcc934e3..000000000
--- a/pipewire-pulseaudio/test/test-volume.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* PipeWire
- *
- * Copyright © 2020 Wim Taymans
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-struct data {
- pa_mainloop *loop;
- pa_context *context;
- pa_time_event *timer;
-
- int n_channels;
- int cycle;
-};
-
-static void time_event_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata)
-{
- struct data *data = userdata;
- pa_cvolume volume;
- pa_volume_t vol;
-
- if (data->cycle++ & 1)
- vol = PA_VOLUME_NORM / 2;
- else
- vol = PA_VOLUME_NORM / 3;
-
- pa_cvolume_set(&volume, data->n_channels, vol);
-
- fprintf(stderr, "set volume\n");
- pa_context_set_sink_volume_by_name(data->context,
- "@DEFAULT_SINK@", &volume, NULL, NULL);
-}
-
-static void start_timer(struct data *data)
-{
- struct timeval tv;
- pa_mainloop_api *api = pa_mainloop_get_api(data->loop);
-
- pa_gettimeofday(&tv);
- pa_timeval_add(&tv, 1 * PA_USEC_PER_SEC);
-
- if (data->timer == NULL) {
- data->timer = api->time_new(api, &tv, time_event_cb, data);
- } else {
- api->time_restart(data->timer, &tv);
- }
-}
-
-static void context_state_callback(pa_context *c, void *userdata)
-{
- struct data *data = userdata;
-
- fprintf(stderr, "context state: %d\n", pa_context_get_state(c));
-
- switch (pa_context_get_state(c)) {
- case PA_CONTEXT_CONNECTING:
- case PA_CONTEXT_AUTHORIZING:
- case PA_CONTEXT_SETTING_NAME:
- break;
- case PA_CONTEXT_READY:
- pa_context_subscribe(data->context,
- PA_SUBSCRIPTION_MASK_SINK|
- PA_SUBSCRIPTION_MASK_SOURCE|
- PA_SUBSCRIPTION_MASK_CLIENT|
- PA_SUBSCRIPTION_MASK_SINK_INPUT|
- PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT|
- PA_SUBSCRIPTION_MASK_CARD|
- PA_SUBSCRIPTION_MASK_MODULE|
- PA_SUBSCRIPTION_MASK_SERVER,
- NULL, NULL);
- start_timer(data);
- break;
- case PA_CONTEXT_TERMINATED:
- case PA_CONTEXT_FAILED:
- default:
- pa_mainloop_quit(data->loop, -1);
- break;
- }
-}
-
-static const char *str_etype(pa_subscription_event_type_t event)
-{
- switch (event & PA_SUBSCRIPTION_EVENT_TYPE_MASK) {
- case PA_SUBSCRIPTION_EVENT_NEW:
- return "new";
- case PA_SUBSCRIPTION_EVENT_CHANGE:
- return "change";
- case PA_SUBSCRIPTION_EVENT_REMOVE:
- return "remove";
- }
- return "invalid";
-}
-
-static const char *str_efac(pa_subscription_event_type_t event)
-{
- switch (event & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
- case PA_SUBSCRIPTION_EVENT_SINK:
- return "sink";
- case PA_SUBSCRIPTION_EVENT_SOURCE:
- return "source";
- case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
- return "sink-input";
- case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
- return "source-output";
- case PA_SUBSCRIPTION_EVENT_MODULE:
- return "module";
- case PA_SUBSCRIPTION_EVENT_CLIENT:
- return "client";
- case PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE:
- return "sample-cache";
- case PA_SUBSCRIPTION_EVENT_SERVER:
- return "server";
- case PA_SUBSCRIPTION_EVENT_AUTOLOAD:
- return "autoload";
- case PA_SUBSCRIPTION_EVENT_CARD:
- return "card";
- }
- return "invalid";
-}
-
-static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
-{
- struct data *data = userdata;
- char v[1024];
-
- if (eol < 0) {
- fprintf(stderr, "sink info: error:%s", pa_strerror(pa_context_errno(c)));
- return;
- }
- if (eol)
- return;
-
- fprintf(stderr, "sink info: index:%d\n", i->index);
- fprintf(stderr, "\tname:%s\n", i->name);
- fprintf(stderr, "\tdescription:%s\n", i->description);
- fprintf(stderr, "\tmute:%s\n", i->mute ? "yes" : "no");
- fprintf(stderr, "\tvolume:%s\n", pa_cvolume_snprint_verbose(v, sizeof(v),
- &i->volume, &i->channel_map, i->flags & PA_SINK_DECIBEL_VOLUME));
- fprintf(stderr, "\tbalance:%0.2f\n", pa_cvolume_get_balance(&i->volume, &i->channel_map));
- fprintf(stderr, "\tbase:%s\n", pa_volume_snprint_verbose(v, sizeof(v),
- i->base_volume, i->flags & PA_SINK_DECIBEL_VOLUME));
-
- data->n_channels = i->volume.channels;
-
- start_timer(data);
-}
-
-static void context_subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata)
-{
- struct data *data = userdata;
-
- fprintf(stderr, "subscribe event %d (%s|%s), idx:%d\n", t,
- str_etype(t), str_efac(t), idx);
-
- switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
- case PA_SUBSCRIPTION_EVENT_SINK:
- pa_context_get_sink_info_by_name(data->context,
- "@DEFAULT_SINK@", sink_info_cb, data);
- break;
- }
-}
-
-int main(int argc, char *argv[])
-{
- struct data data = { 0, };
- pa_mainloop_api *api;
- int ret;
-
- data.loop = pa_mainloop_new();
- data.n_channels = 1;
-
- api = pa_mainloop_get_api(data.loop);
- data.context = pa_context_new(api, "test-volume");
-
- pa_context_set_state_callback(data.context, context_state_callback, &data);
-
- if (pa_context_connect(data.context, NULL, 0, NULL) < 0) {
- fprintf(stderr, "pa_context_connect() failed.\n");
- return -1;
- }
- pa_context_set_subscribe_callback(data.context, context_subscribe_cb, &data);
-
- pa_mainloop_run(data.loop, &ret);
-
- return 0;
-}