conan-io / conan-center-index

Recipes for the ConanCenter repository
https://conan.io/center
MIT License
922 stars 1.67k forks source link

[request] portaudio/19.7.0 #16335

Open dimi309 opened 1 year ago

dimi309 commented 1 year ago

Package Name/Version

portaudio/19.7.0

Webpage

http://www.portaudio.com/

Source code

https://github.com/PortAudio/portaudio

Description of the library/tool

(quoted from the portaudio web page): PortAudio is a free, cross-platform, open-source, audio I/O library. It lets you write simple audio programs in 'C' or C++ that will compile and run on many platforms including Windows, Macintosh OS X, and Unix (OSS/ALSA). It is intended to promote the exchange of audio software between developers on different platforms. Many applications use PortAudio for Audio I/O.

dimi309 commented 1 year ago

I can provide the recipe. I have been using a copy of the bincrafters recipe for years for my own projects. Some time ago I proposed an improvement via a pull request but there was not much interest in it, but I was using it in my own projects because, without this improvement, portaudio would not work on Linux (it would compile, but there was no sound). Over time, in order to be able to use and evolve the recipe with more flexibility I made my own copy. The bincrafters version seems to not be maintained anymore (its last commit is in September 2021 at the time of writing). I have upgraded my version to conan 2.0. I have also cloned the conan center index and integrated the recipe into my clone via this commit. I would like to introduce a pull request and contribute it to the conan center index if I am granted access.

Croydon commented 1 year ago

The problem with your PR to the Bincrafters recipe was that it changed default values + introduced more system packages.

I think we still have many unanswered questions today about the handling of audio on Linux or at least I have. (And audio on Linux seems to be generally a mess, hopefully, pipewire solves this long-term)

Your copy of the recipe won't be allowed in this form in CCI as we don't allow the installation of system_packages at all in regular recipes. We have the concept of system packages (name/system, see xorg/system) that can do that, but there needs to be a good reasoning for such package to exist.

dimi309 commented 1 year ago

Thanks for your feedback @Croydon . I have just provided more feedback in answer to your comments on my initial pull request on bincrafters. In general, I have used this version (of my potential pull request) on many linux systems and I got it to produce sound every time. But I understand what you say, that it is not conformant to the relevant guidelines. I just thought to propose it, in case it helps 😄

dimi309 commented 1 year ago

Just in case something had changed over the years, I have tried building the portaudio package with the latest libalsa conan package version, 1.2.7.2. Unfortunately the problem persists. I have just noted this on the issue I had opened back then about the libalsa package: https://github.com/conan-io/conan-center-index/issues/7526

dimi309 commented 1 year ago

I was also just looking at the recipe of the original bincrafter's portaudio package, before I had cloned and modified it. @Croydon you mentioned above that my modifications introduced more system packages, but I see that the original recipe contained libjack-dev for apt and glibmm24.i686, glibc-devel.i686 and jack-audio-connection-kit-devel for yum. The only additional system packages in my recipe are the said libasound2-dev package for apt and the corresponding alsa-lib-devel for yum.

Would this mean that, even if we manage to fix the conan libalsa package and get rid of my system alsa package requirement, the portaudio recipe would still not be eligible for conan center? Personally I can keep using my fork of the portaudio package and it won't change much for my projects. But at the same time, isn't it a pity that there could be a working portaudio package in conancenter and there isn't one?

dimi309 commented 1 year ago

Following this and other discussions, I have withdrawn my pull request containing the portaudio package and have deleted my clone of conan-center-index with the relevant modifications. Since there is no portaudio package at conan-center-index at the time of writing and the one available at bincrafters does not produce sound on Linux as far as I have been able to find out, for whoever needs it, please feel free to use my variation (it has been migrated to conan 2.0):

https://github.com/dimi309/portaudio-conan

dimi309 commented 1 year ago

Dear @Croydon and other conan co-travellers :smiley: ,

I was looking into the alsa library today. I was hoping that perhaps I could fix its conan center index package (please see the issue I have mentioned above). My idea was to also try to provide a conan package of the jack library and reference the two from my portaudio package variation, so that then perhaps, portaudio could also be accepted into the conan center index since it would no longer be using these two libraries in the form of system packages which you do not allow in most cases, as far as I have understood.

While trying to do these things however, I have noticed something which I find is quite important. The jack and alsa libraries are licensed under GPL2 and LGPL2 respectively (jack: https://github.com/jackaudio/jack2/blob/develop/COPYING, alsa: https://github.com/alsa-project/alsa-lib/blob/master/COPYING). Therefore, if portaudio were to reference them as conan packages, especially when compiled statically, any client application using portaudio would need to provide its source code too in the first case due to GPL "contamination" and the situation in the latter case would only be marginally better.

Portaudio in itself is now pretty much licensed under an MIT license: http://www.portaudio.com/license.html so it seems to me that the (L)GPL2 licenses from alsa and jack would be limiting the usage potential of a conan portaudio package. The way I see it, it would be quite useful to have a portaudio package that does not depend on the alsa or jack conan packages, but rather uses these as system libraries provided by the linux distro it runs on. This way the portaudio package could be used for any project, open or closed source, without legal concerns about its licensing model. This is what my aforementioned variation of the portaudio package does (https://github.com/dimi309/portaudio-conan).

In light of this, if I reincorporate this portaudio package variation into the conan-center-index source code, adapting it of course to the standard practices used there, would you reconsider accepting a pull request to incorporate portaudio into the conan center index? If you would consider it, I would of course be willing to follow all your instructions on declaring and handling the use of the jack and alsa system packages it would be referencing.

bheisch commented 10 months ago

Hi, this seems all quite Interesting. We considering to use conan, but we would also need Portaudio. How can we proceed (Speacially that PortAudio can also fetched via cmake, but i would prefer to use conan for that.) Would be happy about an update on the current Situation.

dimi309 commented 10 months ago

Hi @bheisch

As you can see my proposal for adding a working version of portaudio to conan center did not get much traction, but I have been using my own package for quite some time without any problems on Linux, Windows and MacOS. If you would like to, you are more than welcome to try it out:

https://github.com/dimi309/portaudio-conan

The only inconvenience is that you will have to clone the repository and export the package locally, instead of just linking to it from conan center where it does not exist at the time of writing.

bheisch commented 10 months ago

aye, i saw that but i tried to get some more attention here (speacially because portaudio was working pretty out of the box for me, so i was a little irritated) Thanks i will have a look. If i can assist the conan Team further i will be willingly to help :)

dimi309 commented 10 months ago

I understand that my solution does not conform to certain conan center rules. But I do not know what else can be done without spending a considerable amount of time trying to investigate what is going on and there is no sound on Linux, probably because of the alsa package...

bheisch commented 10 months ago

I agree, may someone from the conan team might give us some hints, about what to do next? Or how can move portaudio in the center conan library, because i think its quite well known and would be a great package to have in :) @Croydon what can we do? Can we somehow implementent an defaul cci implementation without some fancy changes? (sth. like just call cmake and build it)

bheisch commented 10 months ago

anyway i want to thank you for the cool pr @dimi309 . I realy appriciate your work and maybe we can get it working (since i also must run it on linux and mingw windows).

dimi309 commented 10 months ago

Thank you @bheisch ! Please note that I have been updating my own repository of the individual package (https://github.com/dimi309/portaudio-conan) after introducing and consequently closing my pull request, so the recipe there is more robust. But feel free to copy paste and use the code wherever you like, in its entirety, combining it with the pull request, or even directly in your own version of the package 😄

Chnossos commented 7 months ago

Just found out about this thread, a few hours after I made my own recipe for 19.7.0.

While it doesn't handle MacOS at all (don't have any available), it has a bit more options handled from the original package, feel free to use it:

from conan                              import ConanFile
from conan.errors                       import ConanInvalidConfiguration
from conan.tools.cmake                  import CMake, CMakeToolchain
from conan.tools.files                  import collect_libs, download, rm, rmdir, unzip
from conan.tools.microsoft              import is_msvc, is_msvc_static_runtime
from conan.tools.scm.git                import Git
from conan.tools.system.package_manager import Apt, Dnf, Yum
from os.path                            import join

class PortAudioConan(ConanFile):
    name          = "portaudio"
    version       = "19.7.0"
    homepage      = "https://www.portaudio.com/"
    url           = "https://github.com/PortAudio/portaudio"
    description   = "Cross-platform, open-source C library for real-time audio input and output."
    settings      = "os", "compiler", "build_type", "arch"
    options       = {
        "shared": [False, True],
        "fPIC": [False, True],
        "debug_output": [False, True],
        "unicode": [False, True],
        "use_alsa": [False, True],
        "use_alsa_dynamic": [False, True],
        "use_asio": [False, True],
        "use_directsound": [False, True],
        "use_jack": [False, True],
        "use_wasapi": [False, True],
        "use_wdmks": [False, True],
        "use_wdmks_device_info": [False, True],
        "use_wmme": [False, True],
    }
    default_options = {
        "shared": False,
        "fPIC": True,
        "debug_output": False,
        "unicode": True,
        "use_alsa": True,
        "use_alsa_dynamic": False,
        "use_asio": True,
        "use_directsound": True,
        "use_jack": True,
        "use_wasapi": True,
        "use_wdmks": True,
        "use_wdmks_device_info": True,
        "use_wmme": True,
    }
    generators     = "CMakeDeps"
    no_copy_source = True

    def config_options(self):
        if self.settings.os == "Windows":
            del self.options.fPIC
            del self.options.use_alsa
            del self.options.use_alsa_dynamic
            del self.options.use_jack

        if self.settings.os == "Linux":
            del self.options.unicode
            del self.options.use_asio
            del self.options.use_directsound
            del self.options.use_wasapi
            del self.options.use_wdmks
            del self.options.use_wdmks_device_info
            del self.options.use_wmme

    def configure(self):
        if self.settings.os == "Windows" and not self.options.use_wdmks:
            del self.options.use_wdmks_device_info

        if self.settings.os == "Linux" and not self.options.use_alsa:
            del self.options.use_alsa_dynamic

        if self.options.shared:
            self.options.rm_safe("fPIC")

    def validate(self):
        if self.settings.os not in ["Windows", "Linux"]:
            raise ConanInvalidConfiguration(f"{self.settings.os} is not currently supported")

    def source(self):
        Git(self).clone(self.url, self.name,
                        ["-b", f"v{self.version}", "--single-branch", "--depth", "1"])

        if self.settings.os == "Windows" and self.options.use_asio:
            download(self, "https://www.steinberg.net/asiosdk", filename="asiosdk.zip")
            unzip(self, "asiosdk.zip", "asiosdk", pattern="*.h",   strip_root=True)
            unzip(self, "asiosdk.zip", "asiosdk", pattern="*.cpp", strip_root=True)
            rm(self, "*.zip", self.source_folder)

    def system_requirements(self):
        packages = {
            "apt": ["libasound2-dev"],
            "dnf": ["alsa-lib-devel"],
            "yum": ["alsa-lib-devel"],
        }

        if self.options.get_safe("use_jack"):
            packages["apt"].append("libjack-dev")
            packages["yum"].append("jack-audio-connection-kit-devel")
            # Needed for Fedora >= 35
            Dnf(self).install_substitutes([["jack-audio-connection-kit-devel"],
                                           ["pipewire-jack-audio-connection-kit-devel"]])

        Apt(self).install(packages["apt"])
        Dnf(self).install(packages["dnf"])
        Yum(self).install(packages["yum"])

    def generate(self):
        tc = CMakeToolchain(self)
        tc.cache_variables["PA_BUILD_SHARED"       ] = self.options.shared
        tc.cache_variables["PA_BUILD_STATIC"       ] = not self.options.shared
        tc.cache_variables["PA_ENABLE_DEBUG_OUTPUT"] = self.options.debug_output

        if self.settings.os == "Windows":
            tc.cache_variables["PA_UNICODE_BUILD"] = self.options.unicode
            tc.cache_variables["PA_USE_ASIO"     ] = self.options.use_asio
            tc.cache_variables["PA_USE_DS"       ] = self.options.use_directsound
            tc.cache_variables["PA_USE_WASAPI"   ] = self.options.use_wasapi
            tc.cache_variables["PA_USE_WDMKS"    ] = self.options.use_wdmks
            tc.cache_variables["PA_USE_WMME"     ] = self.options.use_wmme

            if self.options.use_asio:
                tc.cache_variables["ASIOSDK_ROOT_DIR"] = join(self.source_folder, "asiosdk")

            if self.options.use_wdmks:
                tc.cache_variables["PA_USE_WDMKS_DEVICE_INFO"] = self.options.use_wdmks_device_info

            if is_msvc(self):
                tc.cache_variables["PA_DLL_LINK_WITH_STATIC_RUNTIME"] = is_msvc_static_runtime(self)

        if self.settings.os == "Linux":
            tc.cache_variables["PA_USE_ALSA"] = self.options.use_alsa
            tc.cache_variables["PA_USE_JACK"] = self.options.use_jack

            if self.options.use_alsa:
                tc.cache_variables["PA_ALSA_DYNAMIC"] = self.options.use_alsa_dynamic

        tc.generate()

    def build(self):
        cmake = CMake(self)
        cmake.configure(build_script_folder=self.name)
        cmake.build()

    def package(self):
        CMake(self).install()
        rmdir(self, join(self.package_folder, "lib", "pkgconfig"))

    def package_info(self):
        self.cpp_info.libs = collect_libs(self)
        self.cpp_info.set_property("cmake_find_mode", "none")  # Do not generate custom files
        self.cpp_info.builddirs.append(join("lib", "cmake"))   # Use provided cmake files instead

        if self.settings.os == "Windows":
            if self.settings.compiler == "gcc" and not self.options.shared:
                self.cpp_info.system_libs.append("winmm")

        if self.settings.os == "Linux":
            self.cpp_info.system_libs += ["rt", "m", "pthread"]

            if self.options.use_alsa and not self.options.use_alsa_dynamic:
                self.cpp_info.system_libs.append("asound")

            if self.options.use_jack:
                self.cpp_info.system_libs.append("jack")
dimi309 commented 7 months ago

Nice! Thanks @Chnossos !!