android: add oboe audio sink
This commit is contained in:
		@@ -142,6 +142,9 @@ if (YUZU_USE_BUNDLED_VCPKG)
 | 
				
			|||||||
    if (ENABLE_WEB_SERVICE)
 | 
					    if (ENABLE_WEB_SERVICE)
 | 
				
			||||||
        list(APPEND VCPKG_MANIFEST_FEATURES "web-service")
 | 
					        list(APPEND VCPKG_MANIFEST_FEATURES "web-service")
 | 
				
			||||||
    endif()
 | 
					    endif()
 | 
				
			||||||
 | 
					    if (ANDROID)
 | 
				
			||||||
 | 
					        list(APPEND VCPKG_MANIFEST_FEATURES "android")
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    include(${CMAKE_SOURCE_DIR}/externals/vcpkg/scripts/buildsystems/vcpkg.cmake)
 | 
					    include(${CMAKE_SOURCE_DIR}/externals/vcpkg/scripts/buildsystems/vcpkg.cmake)
 | 
				
			||||||
elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
 | 
					elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -253,6 +253,17 @@ if (ENABLE_SDL2)
 | 
				
			|||||||
    target_compile_definitions(audio_core PRIVATE HAVE_SDL2)
 | 
					    target_compile_definitions(audio_core PRIVATE HAVE_SDL2)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (ANDROID)
 | 
				
			||||||
 | 
					    target_sources(audio_core PRIVATE
 | 
				
			||||||
 | 
					        sink/oboe_sink.cpp
 | 
				
			||||||
 | 
					        sink/oboe_sink.h
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # FIXME: this port seems broken, it cannot be imported with find_package(oboe REQUIRED)
 | 
				
			||||||
 | 
					    target_link_libraries(audio_core PRIVATE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/liboboe.a")
 | 
				
			||||||
 | 
					    target_compile_definitions(audio_core PRIVATE HAVE_OBOE)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (YUZU_USE_PRECOMPILED_HEADERS)
 | 
					if (YUZU_USE_PRECOMPILED_HEADERS)
 | 
				
			||||||
    target_precompile_headers(audio_core PRIVATE precompiled_headers.h)
 | 
					    target_precompile_headers(audio_core PRIVATE precompiled_headers.h)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										184
									
								
								src/audio_core/sink/oboe_sink.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								src/audio_core/sink/oboe_sink.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,184 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <span>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <oboe/Oboe.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "audio_core/common/common.h"
 | 
				
			||||||
 | 
					#include "audio_core/sink/oboe_sink.h"
 | 
				
			||||||
 | 
					#include "audio_core/sink/sink_stream.h"
 | 
				
			||||||
 | 
					#include "common/logging/log.h"
 | 
				
			||||||
 | 
					#include "common/scope_exit.h"
 | 
				
			||||||
 | 
					#include "core/core.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace AudioCore::Sink {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class OboeSinkStream final : public SinkStream,
 | 
				
			||||||
 | 
					                             public oboe::AudioStreamDataCallback,
 | 
				
			||||||
 | 
					                             public oboe::AudioStreamErrorCallback {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    explicit OboeSinkStream(Core::System& system_, StreamType type_, const std::string& name_,
 | 
				
			||||||
 | 
					                            u32 device_channels_, u32 system_channels_)
 | 
				
			||||||
 | 
					        : SinkStream(system_, type_) {
 | 
				
			||||||
 | 
					        name = name_;
 | 
				
			||||||
 | 
					        system_channels = system_channels_;
 | 
				
			||||||
 | 
					        device_channels = device_channels_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this->OpenStream();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ~OboeSinkStream() override {
 | 
				
			||||||
 | 
					        LOG_DEBUG(Audio_Sink, "Destructing Oboe stream {}", name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Finalize() override {
 | 
				
			||||||
 | 
					        this->Stop();
 | 
				
			||||||
 | 
					        m_stream.reset();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Start(bool resume = false) override {
 | 
				
			||||||
 | 
					        if (!m_stream || !paused) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        paused = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_stream->start() != oboe::Result::OK) {
 | 
				
			||||||
 | 
					            LOG_CRITICAL(Audio_Sink, "Error starting Oboe stream");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Stop() override {
 | 
				
			||||||
 | 
					        if (!m_stream || paused) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this->SignalPause();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (m_stream->stop() != oboe::Result::OK) {
 | 
				
			||||||
 | 
					            LOG_CRITICAL(Audio_Sink, "Error stopping Oboe stream");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					    oboe::DataCallbackResult onAudioReady(oboe::AudioStream*, void* audio_data,
 | 
				
			||||||
 | 
					                                          s32 num_buffer_frames) override {
 | 
				
			||||||
 | 
					        const size_t num_channels = this->GetDeviceChannels();
 | 
				
			||||||
 | 
					        const size_t frame_size = num_channels;
 | 
				
			||||||
 | 
					        const size_t num_frames = static_cast<size_t>(num_buffer_frames);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (type == StreamType::In) {
 | 
				
			||||||
 | 
					            std::span<const s16> input_buffer{reinterpret_cast<const s16*>(audio_data),
 | 
				
			||||||
 | 
					                                              num_frames * frame_size};
 | 
				
			||||||
 | 
					            this->ProcessAudioIn(input_buffer, num_frames);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            std::span<s16> output_buffer{reinterpret_cast<s16*>(audio_data),
 | 
				
			||||||
 | 
					                                         num_frames * frame_size};
 | 
				
			||||||
 | 
					            this->ProcessAudioOutAndRender(output_buffer, num_frames);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return oboe::DataCallbackResult::Continue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void onErrorAfterClose(oboe::AudioStream*, oboe::Result) override {
 | 
				
			||||||
 | 
					        LOG_INFO(Audio_Sink, "Audio stream closed, reinitializing");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this->OpenStream()) {
 | 
				
			||||||
 | 
					            m_stream->start();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    bool OpenStream() {
 | 
				
			||||||
 | 
					        const auto direction = [&]() {
 | 
				
			||||||
 | 
					            switch (type) {
 | 
				
			||||||
 | 
					            case StreamType::In:
 | 
				
			||||||
 | 
					                return oboe::Direction::Input;
 | 
				
			||||||
 | 
					            case StreamType::Out:
 | 
				
			||||||
 | 
					            case StreamType::Render:
 | 
				
			||||||
 | 
					                return oboe::Direction::Output;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                ASSERT(false);
 | 
				
			||||||
 | 
					                return oboe::Direction::Output;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto channel_mask = [&]() {
 | 
				
			||||||
 | 
					            switch (device_channels) {
 | 
				
			||||||
 | 
					            case 1:
 | 
				
			||||||
 | 
					                return oboe::ChannelMask::Mono;
 | 
				
			||||||
 | 
					            case 2:
 | 
				
			||||||
 | 
					                return oboe::ChannelMask::Stereo;
 | 
				
			||||||
 | 
					            case 6:
 | 
				
			||||||
 | 
					                return oboe::ChannelMask::CM5Point1;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                ASSERT(false);
 | 
				
			||||||
 | 
					                return oboe::ChannelMask::Unspecified;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        oboe::AudioStreamBuilder builder;
 | 
				
			||||||
 | 
					        const auto result = builder.setDirection(direction)
 | 
				
			||||||
 | 
					                                ->setSampleRate(TargetSampleRate)
 | 
				
			||||||
 | 
					                                ->setChannelCount(device_channels)
 | 
				
			||||||
 | 
					                                ->setChannelMask(channel_mask)
 | 
				
			||||||
 | 
					                                ->setFormat(oboe::AudioFormat::I16)
 | 
				
			||||||
 | 
					                                ->setFormatConversionAllowed(true)
 | 
				
			||||||
 | 
					                                ->setDataCallback(this)
 | 
				
			||||||
 | 
					                                ->setErrorCallback(this)
 | 
				
			||||||
 | 
					                                ->openStream(m_stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ASSERT(result == oboe::Result::OK);
 | 
				
			||||||
 | 
					        return result == oboe::Result::OK;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<oboe::AudioStream> m_stream{};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OboeSink::OboeSink() {
 | 
				
			||||||
 | 
					    // TODO: how do we get the number of channels, or device list?
 | 
				
			||||||
 | 
					    // This seems to be missing from NDK.
 | 
				
			||||||
 | 
					    device_channels = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OboeSink::~OboeSink() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SinkStream* OboeSink::AcquireSinkStream(Core::System& system, u32 system_channels,
 | 
				
			||||||
 | 
					                                        const std::string& name, StreamType type) {
 | 
				
			||||||
 | 
					    SinkStreamPtr& stream = sink_streams.emplace_back(
 | 
				
			||||||
 | 
					        std::make_unique<OboeSinkStream>(system, type, name, device_channels, system_channels));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return stream.get();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void OboeSink::CloseStream(SinkStream* to_remove) {
 | 
				
			||||||
 | 
					    sink_streams.remove_if([&](auto& stream) { return stream.get() == to_remove; });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void OboeSink::CloseStreams() {
 | 
				
			||||||
 | 
					    sink_streams.clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					f32 OboeSink::GetDeviceVolume() const {
 | 
				
			||||||
 | 
					    if (sink_streams.empty()) {
 | 
				
			||||||
 | 
					        return 1.0f;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return sink_streams.front()->GetDeviceVolume();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void OboeSink::SetDeviceVolume(f32 volume) {
 | 
				
			||||||
 | 
					    for (auto& stream : sink_streams) {
 | 
				
			||||||
 | 
					        stream->SetDeviceVolume(volume);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void OboeSink::SetSystemVolume(f32 volume) {
 | 
				
			||||||
 | 
					    for (auto& stream : sink_streams) {
 | 
				
			||||||
 | 
					        stream->SetSystemVolume(volume);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace AudioCore::Sink
 | 
				
			||||||
							
								
								
									
										75
									
								
								src/audio_core/sink/oboe_sink.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/audio_core/sink/oboe_sink.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "audio_core/sink/sink.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Core {
 | 
				
			||||||
 | 
					class System;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace AudioCore::Sink {
 | 
				
			||||||
 | 
					class SinkStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class OboeSink final : public Sink {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    explicit OboeSink();
 | 
				
			||||||
 | 
					    ~OboeSink() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a new sink stream.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param system          - Core system.
 | 
				
			||||||
 | 
					     * @param system_channels - Number of channels the audio system expects.
 | 
				
			||||||
 | 
					     *                          May differ from the device's channel count.
 | 
				
			||||||
 | 
					     * @param name            - Name of this stream.
 | 
				
			||||||
 | 
					     * @param type            - Type of this stream, render/in/out.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return A pointer to the created SinkStream
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    SinkStream* AcquireSinkStream(Core::System& system, u32 system_channels,
 | 
				
			||||||
 | 
					                                  const std::string& name, StreamType type) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Close a given stream.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param stream - The stream to close.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void CloseStream(SinkStream* stream) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Close all streams.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void CloseStreams() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the device volume. Set from calls to the IAudioDevice service.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return Volume of the device.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    f32 GetDeviceVolume() const override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set the device volume. Set from calls to the IAudioDevice service.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param volume - New volume of the device.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void SetDeviceVolume(f32 volume) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set the system volume. Comes from the audio system using this stream.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param volume - New volume of the system.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void SetSystemVolume(f32 volume) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    /// List of streams managed by this sink
 | 
				
			||||||
 | 
					    std::list<SinkStreamPtr> sink_streams{};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace AudioCore::Sink
 | 
				
			||||||
@@ -7,6 +7,9 @@
 | 
				
			|||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "audio_core/sink/sink_details.h"
 | 
					#include "audio_core/sink/sink_details.h"
 | 
				
			||||||
 | 
					#ifdef HAVE_OBOE
 | 
				
			||||||
 | 
					#include "audio_core/sink/oboe_sink.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifdef HAVE_CUBEB
 | 
					#ifdef HAVE_CUBEB
 | 
				
			||||||
#include "audio_core/sink/cubeb_sink.h"
 | 
					#include "audio_core/sink/cubeb_sink.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -36,6 +39,16 @@ struct SinkDetails {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// sink_details is ordered in terms of desirability, with the best choice at the top.
 | 
					// sink_details is ordered in terms of desirability, with the best choice at the top.
 | 
				
			||||||
constexpr SinkDetails sink_details[] = {
 | 
					constexpr SinkDetails sink_details[] = {
 | 
				
			||||||
 | 
					#ifdef HAVE_OBOE
 | 
				
			||||||
 | 
					    SinkDetails{
 | 
				
			||||||
 | 
					        Settings::AudioEngine::Oboe,
 | 
				
			||||||
 | 
					        [](std::string_view device_id) -> std::unique_ptr<Sink> {
 | 
				
			||||||
 | 
					            return std::make_unique<OboeSink>();
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        [](bool capture) { return std::vector<std::string>{"Default"}; },
 | 
				
			||||||
 | 
					        []() { return true; },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifdef HAVE_CUBEB
 | 
					#ifdef HAVE_CUBEB
 | 
				
			||||||
    SinkDetails{
 | 
					    SinkDetails{
 | 
				
			||||||
        Settings::AudioEngine::Cubeb,
 | 
					        Settings::AudioEngine::Cubeb,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,16 +82,15 @@ enum class AudioEngine : u32 {
 | 
				
			|||||||
    Cubeb,
 | 
					    Cubeb,
 | 
				
			||||||
    Sdl2,
 | 
					    Sdl2,
 | 
				
			||||||
    Null,
 | 
					    Null,
 | 
				
			||||||
 | 
					    Oboe,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <>
 | 
					template <>
 | 
				
			||||||
inline std::vector<std::pair<std::string, AudioEngine>>
 | 
					inline std::vector<std::pair<std::string, AudioEngine>>
 | 
				
			||||||
EnumMetadata<AudioEngine>::Canonicalizations() {
 | 
					EnumMetadata<AudioEngine>::Canonicalizations() {
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
        {"auto", AudioEngine::Auto},
 | 
					        {"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl2", AudioEngine::Sdl2},
 | 
				
			||||||
        {"cubeb", AudioEngine::Cubeb},
 | 
					        {"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe},
 | 
				
			||||||
        {"sdl2", AudioEngine::Sdl2},
 | 
					 | 
				
			||||||
        {"null", AudioEngine::Null},
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,15 @@
 | 
				
			|||||||
                    "platform": "windows"
 | 
					                    "platform": "windows"
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "android": {
 | 
				
			||||||
 | 
					            "description": "Enable Android dependencies",
 | 
				
			||||||
 | 
					            "dependencies": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "oboe",
 | 
				
			||||||
 | 
					                    "platform": "android"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "overrides": [
 | 
					    "overrides": [
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user