Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS support and fixes #2201

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,99 @@ jobs:
- name: Unit Tests Mini
run: meson test -C output/mini

build-macos:
strategy:
matrix:
compiler: [clang]
include:
- compiler: clang
os: macos-latest
cc: clang
cxx: clang++
brew_packages: >
meson ninja
ccache
expat
fmt
googletest
ffmpeg
libupnp
libid3tag
chromaprint
libsamplerate
libsoxr
flac
opus
libvorbis
faad2
wavpack
libmpdclient
meson_options: --force-fallback-for=fmt,gtest

runs-on: ${{ matrix.os }}

env:
CC: ccache ${{ matrix.cc }}
CXX: ccache ${{ matrix.cxx }}

steps:
- id: checkout
uses: actions/checkout@v4

- name: Install dependencies
run: |
brew update
brew install \
${{ matrix.brew_packages }}

- id: cache-ccache
uses: hendrikmuhs/[email protected]
with:
key: ${{ matrix.compiler }}

- name: Configure
run: |
meson setup \
-Ddocumentation=disabled \
-Dtest=true \
-Dpcre=enabled \
--wrap-mode nofallback \
${{ matrix.meson_options }} \
output/full

- name: Build
run: meson compile -C output/full --verbose

- name: Unit Tests
run: meson test -C output/full

- name: Configure Mini
run: |
meson setup \
-Dbuildtype=minsize \
-Dauto_features=disabled \
-Dtest=true \
-Ddaemon=false \
-Dinotify=false -Depoll=false -Deventfd=false \
-Dsignalfd=false \
-Dtcp=false \
-Ddsd=false \
-Ddatabase=false \
-Dneighbor=false \
-Dcue=false \
-Dfifo=false \
-Dhttpd=false -Dpipe=false -Drecorder=false \
-Dsnapcast=false \
--wrap-mode nofallback \
${{ matrix.meson_options }} \
output/mini

- name: Build Mini
run: meson compile -C output/mini --verbose

- name: Unit Tests Mini
run: meson test -C output/mini

build-msys2:
strategy:
matrix:
Expand Down
1 change: 0 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ ver 0.24 (not yet released)
- build with libsamplerate
- remove JACK DLL support
* remove Haiku support
* remove macOS support
* remove Boost dependency
* require libfmt 9 or later
* documentation: switch to sphinx-rtd-theme
Expand Down
2 changes: 1 addition & 1 deletion doc/mpd.conf.5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ follow_inside_symlinks <yes or no>
database after changing this option. The default is "yes".

zeroconf_enabled <yes or no>
If yes, and MPD has been compiled with support for Avahi, service
If yes, and MPD has been compiled with support for Avahi or Bonjour, service
information will be published with Zeroconf. The default is yes.

zeroconf_name <name>
Expand Down
9 changes: 9 additions & 0 deletions doc/mpdconf.example
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,15 @@ input {
# mixer_type "hardware"
#}
#
# An example of an OS X output:
#
#audio_output {
# type "osx"
# name "My OS X Device"
## device "Built-in Output" # optional
## channel_map "-1,-1,0,1" # optional
#}
#
## Example "pipe" output:
#
#audio_output {
Expand Down
23 changes: 22 additions & 1 deletion doc/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,27 @@ The "OpenAL" plugin uses `libopenal <http://kcat.strangesoft.net/openal.html>`_.
* - **device NAME**
- Sets the device which should be used. This can be any valid OpenAL device name. If not specified, then libopenal will choose a default device.

osx
---
The "Mac OS X" plugin uses Apple's CoreAudio API.

.. list-table::
:widths: 20 80
:header-rows: 1

* - Setting
- Description
* - **device NAME**
- Sets the device which should be used. Uses device names as listed in the "Audio Devices" window of "Audio MIDI Setup".
* - **hog_device yes|no**
- Hog the device. This means that it takes exclusive control of the audio output device it is playing through, and no other program can access it.
* - **dop yes|no**
- If set to yes, then DSD over PCM according to the `DoP standard <http://dsd-guide.com/dop-open-standard>`_ is enabled. This wraps DSD samples in fake 24 bit PCM, and is understood by some DSD capable products, but may be harmful to other hardware. Therefore, the default is no and you can enable the option at your own risk. Under macOS you must make sure to select a physical mode on the output device which supports at least 24 bits per channel as the Mac OS X plugin only changes the sample rate.
* - **channel_map SOURCE,SOURCE,...**
- Specifies a channel map. If your audio device has more than two outputs this allows you to route audio to auxillary outputs. For predictable results you should also specify a "format" with a fixed number of channels, e.g. "*:*:2". The number of items in the channel map must match the number of output channels of your output device. Each list entry specifies the source for that output channel; use "-1" to silence an output. For example, if you have a four-channel output device and you wish to send stereo sound (format "*:*:2") to outputs 3 and 4 while leaving outputs 1 and 2 silent then set the channel map to "-1,-1,0,1". In this example '0' and '1' denote the left and right channel respectively.

The channel map may not refer to outputs that do not exist according to the format. If the format is "*:*:1" (mono) and you have a four-channel sound card then "-1,-1,0,0" (dual mono output on the second pair of sound card outputs) is a valid channel map but "-1,-1,0,1" is not because the second channel ('1') does not exist when the output is mono.

pipe
----

Expand Down Expand Up @@ -1256,7 +1277,7 @@ You must set a format.
bind on all addresses on port :samp:`1704`.
* - **zeroconf yes|no**
- Publish the Snapcast server as service type ``_snapcast._tcp``
via Zeroconf (Avahi). Default is :samp:`yes`.
via Zeroconf (Avahi or Bonjour). Default is :samp:`yes`.


solaris
Expand Down
8 changes: 2 additions & 6 deletions doc/user.rst
Original file line number Diff line number Diff line change
Expand Up @@ -491,11 +491,7 @@ More information can be found in the :ref:`encoder_plugins` reference.
Configuring audio outputs
-------------------------

Audio outputs are devices which actually play the audio chunks
produced by :program:`MPD`. You can configure any number of audio
output devices, but there must be at least one. If none is configured,
:program:`MPD` attempts to auto-detect. Usually, this works quite well
with ALSA and OSS.
Audio outputs are devices which actually play the audio chunks produced by :program:`MPD`. You can configure any number of audio output devices, but there must be at least one. If none is configured, :program:`MPD` attempts to auto-detect. Usually, this works quite well with ALSA, OSS and on Mac OS X.

To configure an audio output manually, add one or more
:code:`audio_output` blocks to :file:`mpd.conf`:
Expand Down Expand Up @@ -965,7 +961,7 @@ Do not change these unless you know what you are doing.
Zeroconf
^^^^^^^^

If Zeroconf support (`Avahi <http://avahi.org/>`_
If Zeroconf support (`Avahi <http://avahi.org/>`_ or Apple's Bonjour)
was enabled at compile time with :code:`-Dzeroconf=...`,
:program:`MPD` can announce its presence on the network. The following
settings control this feature:
Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,8 @@ subdir('src/net')
subdir('src/event')
subdir('src/win32')

subdir('src/apple')

subdir('src/fs/glue')

subdir('src/config')
Expand Down
2 changes: 1 addition & 1 deletion meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,6 @@ option('yajl', type: 'feature', description: 'libyajl for YAML support')
option('zlib', type: 'feature', description: 'zlib support (for database compression)')

option('zeroconf', type: 'combo',
choices: ['auto', 'avahi', 'disabled'],
choices: ['auto', 'avahi', 'bonjour', 'disabled'],
value: 'auto',
description: 'Zeroconf support')
21 changes: 20 additions & 1 deletion python/build/cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,26 @@ def __write_cmake_toolchain_file(f: TextIO, toolchain: AnyToolchain) -> None:
__write_cmake_compiler(f, 'C', toolchain.cc)
__write_cmake_compiler(f, 'CXX', toolchain.cxx)

if cmake_system_name == 'Windows':
if cmake_system_name == 'Darwin':
# On macOS, cmake forcibly adds an "-isysroot" flag even if
# one is already present in the flags variable; this breaks
# cross-compiling for iOS, and can be worked around by setting
# the CMAKE_OSX_SYSROOT variable
# (https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_SYSROOT.html).
m = re.search(r'-isysroot +(\S+)', toolchain.cflags)
if m:
sysroot = m.group(1)

print(f'set(CMAKE_OSX_SYSROOT {sysroot})', file=f)

# search libraries and headers only in the sysroot, not on
# the build host
f.write(f"""
set(CMAKE_FIND_ROOT_PATH "{toolchain.install_prefix};{sysroot}")
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
""")
elif cmake_system_name == 'Windows':
# search libraries and headers only in the sysroot, not on
# the build host
f.write(f"""
Expand Down
14 changes: 14 additions & 0 deletions src/apple/AudioObject.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: BSD-2-Clause
// author: Max Kellermann <[email protected]>

#include "AudioObject.hxx"
#include "StringRef.hxx"

Apple::StringRef
AudioObjectGetStringProperty(AudioObjectID inObjectID,
const AudioObjectPropertyAddress &inAddress)
{
auto s = AudioObjectGetPropertyDataT<CFStringRef>(inObjectID,
inAddress);
return Apple::StringRef(s);
}
79 changes: 79 additions & 0 deletions src/apple/AudioObject.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: BSD-2-Clause
// author: Max Kellermann <[email protected]>

#ifndef APPLE_AUDIO_OBJECT_HXX
#define APPLE_AUDIO_OBJECT_HXX

#include "Throw.hxx"
#include "util/AllocatedArray.hxx"

#include <CoreAudio/AudioHardware.h>

#include <cstddef>

namespace Apple {
class StringRef;
}

inline std::size_t
AudioObjectGetPropertyDataSize(AudioObjectID inObjectID,
const AudioObjectPropertyAddress &inAddress)
{
UInt32 size;
OSStatus status = AudioObjectGetPropertyDataSize(inObjectID,
&inAddress,
0, nullptr, &size);
if (status != noErr)
Apple::ThrowOSStatus(status);

return size;
}

template<typename T>
T
AudioObjectGetPropertyDataT(AudioObjectID inObjectID,
const AudioObjectPropertyAddress &inAddress)
{
OSStatus status;
UInt32 size = sizeof(T);
T value;

status = AudioObjectGetPropertyData(inObjectID, &inAddress,
0, nullptr,
&size, &value);
if (status != noErr)
Apple::ThrowOSStatus(status);

return value;
}

Apple::StringRef
AudioObjectGetStringProperty(AudioObjectID inObjectID,
const AudioObjectPropertyAddress &inAddress);

template<typename T>
AllocatedArray<T>
AudioObjectGetPropertyDataArray(AudioObjectID inObjectID,
const AudioObjectPropertyAddress &inAddress)
{
OSStatus status;
UInt32 size;

status = AudioObjectGetPropertyDataSize(inObjectID,
&inAddress,
0, nullptr, &size);
if (status != noErr)
Apple::ThrowOSStatus(status);

AllocatedArray<T> result(size / sizeof(T));

status = AudioObjectGetPropertyData(inObjectID, &inAddress,
0, nullptr,
&size, result.data());
if (status != noErr)
Apple::ThrowOSStatus(status);

return result;
}

#endif
Loading