mirror of
https://github.com/SFML/CSFML.git
synced 2026-10-26 13:06:13 +01:00
Add sfPlaybackDevice to manage the audio playback device
This commit is contained in:
7 files changed
+374
No files matched your search
@@ -62,9 +62,13 @@ jobs:
|
||||
BUILD_TYPE: ${{ matrix.type.name }}
|
||||
CMAKE_FLAGS: ${{ matrix.platform.flags }} ${{ matrix.config.flags }}
|
||||
run: |
|
||||
# Let the installed SFML libraries find each other, same as tools/nuget/build.linux.sh
|
||||
RPATH_FLAGS=()
|
||||
if [ "$RUNNER_OS" = "Linux" ]; then RPATH_FLAGS=('-DCMAKE_INSTALL_RPATH=$ORIGIN'); fi
|
||||
cmake -S SFML -B SFML/build \
|
||||
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DCMAKE_INSTALL_PREFIX=SFML/install \
|
||||
"${RPATH_FLAGS[@]}" \
|
||||
$CMAKE_FLAGS
|
||||
|
||||
- name: Build SFML
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <CSFML/Audio/Listener.h>
|
||||
#include <CSFML/Audio/Music.h>
|
||||
#include <CSFML/Audio/PlaybackDevice.h>
|
||||
#include <CSFML/Audio/Sound.h>
|
||||
#include <CSFML/Audio/SoundBuffer.h>
|
||||
#include <CSFML/Audio/SoundBufferRecorder.h>
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2026 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <CSFML/Audio/Export.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Enumeration of the playback device notifications
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef enum
|
||||
{
|
||||
sfPlaybackDeviceStarted, ///< Playback device has been started
|
||||
sfPlaybackDeviceStopped, ///< Playback device has been stopped
|
||||
sfPlaybackDeviceRerouted, ///< Playback device has been rerouted (Generated on platforms that support automatic stream routing)
|
||||
sfPlaybackDeviceInterruptionBegan, ///< Playback device interruption has begun (Generated on Apple mobile platforms)
|
||||
sfPlaybackDeviceInterruptionEnded, ///< Playback device interruption has ended (Generated on Apple mobile platforms)
|
||||
sfPlaybackDeviceUnlocked ///< Playback device has been unlocked (Generated by Emscripten/WebAudio)
|
||||
} sfPlaybackDeviceNotification;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Callback that is called to notify of changes to the playback device state
|
||||
///
|
||||
/// \param notification The notification
|
||||
/// \param userData User data passed to sfPlaybackDevice_setNotificationCallback
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef void (*sfPlaybackDeviceNotificationCallback)(sfPlaybackDeviceNotification notification, void* userData);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get a list of the names of all available audio playback devices
|
||||
///
|
||||
/// If the operating system reports multiple devices with
|
||||
/// the same name, a number will be appended to the name
|
||||
/// of all subsequent devices to distinguish them from each
|
||||
/// other. This guarantees that every entry returned by this
|
||||
/// function will represent a unique device.
|
||||
///
|
||||
/// The default device, if one is marked as such, will be
|
||||
/// placed at the beginning of the list.
|
||||
///
|
||||
/// The returned array and strings stay valid until the next
|
||||
/// call to this function.
|
||||
///
|
||||
/// \param count Pointer to a variable that will be filled with the number of devices
|
||||
///
|
||||
/// \return An array of strings containing the device names or NULL if no devices are available
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_AUDIO_API const char* const* sfPlaybackDevice_getAvailableDevices(size_t* count);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the name of the default audio playback device
|
||||
///
|
||||
/// Note that depending on when this function is called, the
|
||||
/// default device reported by the operating system might
|
||||
/// change e.g. when a USB audio device is plugged into or
|
||||
/// unplugged from the system.
|
||||
///
|
||||
/// The returned string stays valid until the next call to
|
||||
/// this function.
|
||||
///
|
||||
/// \return The name of the default audio playback device or NULL if there is none
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_AUDIO_API const char* sfPlaybackDevice_getDefaultDevice(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the audio playback device
|
||||
///
|
||||
/// This function sets the audio playback device to the device
|
||||
/// with the given name. It can be called on the fly (i.e:
|
||||
/// while sounds are playing).
|
||||
///
|
||||
/// If there are sounds playing when the audio playback
|
||||
/// device is switched, the sounds will continue playing
|
||||
/// uninterrupted on the new audio playback device.
|
||||
///
|
||||
/// \param name The name of the audio playback device
|
||||
///
|
||||
/// \return True, if it was able to set the requested device
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_AUDIO_API bool sfPlaybackDevice_setDevice(const char* name);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the audio playback device to the default
|
||||
///
|
||||
/// This function sets the audio playback device to the
|
||||
/// default device. It can be called on the fly (i.e:
|
||||
/// while sounds are playing).
|
||||
///
|
||||
/// When certain backends are used, using the default device
|
||||
/// will enable automatic stream routing. When automatic
|
||||
/// stream routing is enabled, audio data is automatically
|
||||
/// sent to whichever physical audio device is currently
|
||||
/// marked as the default on the system.
|
||||
///
|
||||
/// Automatic stream routing is currently supported when using
|
||||
/// the WASAPI or DirectSound backend on Windows or the
|
||||
/// Core Audio backend on macOS and iOS.
|
||||
///
|
||||
/// \return True, if it was able to set the audio playback device to the default device
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_AUDIO_API bool sfPlaybackDevice_setDeviceToDefault(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set the audio playback device to the null device
|
||||
///
|
||||
/// This function sets the audio playback device to the
|
||||
/// null device. It can be called on the fly (i.e:
|
||||
/// while sounds are playing).
|
||||
///
|
||||
/// Audio data routed to the null device will be discarded
|
||||
/// by the backend. This can be used to keep sounds playing
|
||||
/// without having them actually output on a physical
|
||||
/// audio playback device.
|
||||
///
|
||||
/// \return True, if it was able to set the audio playback device to the null device
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_AUDIO_API bool sfPlaybackDevice_setDeviceToNull(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the name of the current audio playback device
|
||||
///
|
||||
/// The returned string stays valid until the next call to
|
||||
/// this function.
|
||||
///
|
||||
/// \return The name of the current audio playback device or NULL if there is none
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_AUDIO_API const char* sfPlaybackDevice_getDevice(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the sample rate of the current audio playback device
|
||||
///
|
||||
/// \return The sample rate of the current audio playback device or 0 if there is none
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_AUDIO_API uint32_t sfPlaybackDevice_getDeviceSampleRate(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check if the current playback device is the default device
|
||||
///
|
||||
/// This function will return false if there is no
|
||||
/// current playback device.
|
||||
///
|
||||
/// \return True, if the current playback device is the default device
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_AUDIO_API bool sfPlaybackDevice_isDefaultDevice(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Set a callback that should be called to notify of changes to the playback device state
|
||||
///
|
||||
/// Warning: Do not attempt to alter the device state from
|
||||
/// within this callback. This includes changing the device
|
||||
/// and even creating/destroying sound objects since that
|
||||
/// could indirectly cause the playback device to be
|
||||
/// created/destroyed. Also do not attempt to set the
|
||||
/// notification callback from within this callback. Doing
|
||||
/// so will result in a deadlock.
|
||||
///
|
||||
/// When receiving a notification via this callback, store
|
||||
/// the information somewhere and react on it from another
|
||||
/// thread e.g. the main thread within the application.
|
||||
///
|
||||
/// \param callback The callback to be called, pass NULL to remove the current callback
|
||||
/// \param userData User data that will be passed to the callback
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_AUDIO_API void sfPlaybackDevice_setNotificationCallback(sfPlaybackDeviceNotificationCallback callback, void* userData);
|
||||
@@ -11,6 +11,8 @@ set(SRC
|
||||
${SRCROOT}/Music.cpp
|
||||
${SRCROOT}/MusicStruct.hpp
|
||||
${INCROOT}/Music.h
|
||||
${SRCROOT}/PlaybackDevice.cpp
|
||||
${INCROOT}/PlaybackDevice.h
|
||||
${SRCROOT}/Sound.cpp
|
||||
${SRCROOT}/SoundStruct.hpp
|
||||
${INCROOT}/Sound.h
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2026 Laurent Gomila (laurent@sfml-dev.org)
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <CSFML/Audio/PlaybackDevice.h>
|
||||
|
||||
#include <SFML/Audio/PlaybackDevice.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Helper function for returning optional strings
|
||||
[[nodiscard]] const char* toCString(std::string& storage, const std::optional<std::string>& string)
|
||||
{
|
||||
if (!string)
|
||||
return nullptr;
|
||||
|
||||
storage = *string;
|
||||
return storage.c_str();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const char* const* sfPlaybackDevice_getAvailableDevices(size_t* count)
|
||||
{
|
||||
static std::vector<std::string> stringDevices;
|
||||
static std::vector<const char*> devices;
|
||||
|
||||
stringDevices = sf::PlaybackDevice::getAvailableDevices();
|
||||
devices.clear();
|
||||
devices.reserve(stringDevices.size());
|
||||
for (const auto& stringDevice : stringDevices)
|
||||
devices.push_back(stringDevice.c_str());
|
||||
|
||||
if (count)
|
||||
*count = devices.size();
|
||||
|
||||
return !devices.empty() ? devices.data() : nullptr;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const char* sfPlaybackDevice_getDefaultDevice()
|
||||
{
|
||||
static std::string defaultDevice;
|
||||
return toCString(defaultDevice, sf::PlaybackDevice::getDefaultDevice());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool sfPlaybackDevice_setDevice(const char* name)
|
||||
{
|
||||
assert(name);
|
||||
return sf::PlaybackDevice::setDevice(name);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool sfPlaybackDevice_setDeviceToDefault()
|
||||
{
|
||||
return sf::PlaybackDevice::setDeviceToDefault();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool sfPlaybackDevice_setDeviceToNull()
|
||||
{
|
||||
return sf::PlaybackDevice::setDeviceToNull();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const char* sfPlaybackDevice_getDevice()
|
||||
{
|
||||
static std::string device;
|
||||
return toCString(device, sf::PlaybackDevice::getDevice());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
uint32_t sfPlaybackDevice_getDeviceSampleRate()
|
||||
{
|
||||
return sf::PlaybackDevice::getDeviceSampleRate().value_or(0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool sfPlaybackDevice_isDefaultDevice()
|
||||
{
|
||||
return sf::PlaybackDevice::isDefaultDevice();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void sfPlaybackDevice_setNotificationCallback(sfPlaybackDeviceNotificationCallback callback, void* userData)
|
||||
{
|
||||
if (!callback)
|
||||
{
|
||||
sf::PlaybackDevice::setNotificationCallback({});
|
||||
return;
|
||||
}
|
||||
|
||||
sf::PlaybackDevice::setNotificationCallback(
|
||||
[callback, userData](sf::PlaybackDevice::Notification notification)
|
||||
{ callback(static_cast<sfPlaybackDeviceNotification>(notification), userData); });
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include <CSFML/Audio/PlaybackDevice.h>
|
||||
|
||||
#include <SFML/Audio/PlaybackDevice.hpp>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
TEST_CASE("[Audio] sfPlaybackDevice")
|
||||
{
|
||||
SECTION("sfPlaybackDeviceNotification")
|
||||
{
|
||||
STATIC_CHECK(sfPlaybackDeviceStarted == static_cast<int>(sf::PlaybackDevice::Notification::DeviceStarted));
|
||||
STATIC_CHECK(sfPlaybackDeviceStopped == static_cast<int>(sf::PlaybackDevice::Notification::DeviceStopped));
|
||||
STATIC_CHECK(sfPlaybackDeviceRerouted == static_cast<int>(sf::PlaybackDevice::Notification::DeviceRerouted));
|
||||
STATIC_CHECK(sfPlaybackDeviceInterruptionBegan ==
|
||||
static_cast<int>(sf::PlaybackDevice::Notification::DeviceInterruptionBegan));
|
||||
STATIC_CHECK(sfPlaybackDeviceInterruptionEnded ==
|
||||
static_cast<int>(sf::PlaybackDevice::Notification::DeviceInterruptionEnded));
|
||||
STATIC_CHECK(sfPlaybackDeviceUnlocked == static_cast<int>(sf::PlaybackDevice::Notification::DeviceUnlocked));
|
||||
}
|
||||
|
||||
SECTION("sfPlaybackDevice_setNotificationCallback")
|
||||
{
|
||||
sfPlaybackDevice_setNotificationCallback([](sfPlaybackDeviceNotification, void*) {}, nullptr);
|
||||
sfPlaybackDevice_setNotificationCallback(nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,7 @@ set_target_warnings(test-csfml-network)
|
||||
catch_discover_tests(test-csfml-network)
|
||||
|
||||
add_executable(test-csfml-audio
|
||||
Audio/PlaybackDevice.test.cpp
|
||||
Audio/SoundChannel.test.cpp
|
||||
)
|
||||
target_link_libraries(test-csfml-audio PRIVATE csfml-audio Catch2::Catch2WithMain SFML::Audio)
|
||||
|
||||
Reference in new issue
Block a user