From 97a5174c278d70dffaae6f1b1ce7f75e1957602e Mon Sep 17 00:00:00 2001 From: Gabriele Svelto Date: Tue, 21 Dec 2021 11:34:52 +0000 Subject: [PATCH] Bug 1201598 - Add a midir-based implementation for WebMIDI r=padenot Differential Revision: https://phabricator.services.mozilla.com/D131351 --- Cargo.lock | 11 + Cargo.toml | 1 + dom/midi/MIDIPlatformService.cpp | 15 +- dom/midi/midirMIDIPlatformService.cpp | 152 +++++++++++ dom/midi/midirMIDIPlatformService.h | 59 +++++ dom/midi/midir_impl/Cargo.toml | 13 + dom/midi/midir_impl/cbindgen.toml | 18 ++ dom/midi/midir_impl/moz.build | 17 ++ dom/midi/midir_impl/src/lib.rs | 334 +++++++++++++++++++++++++ dom/midi/moz.build | 12 +- old-configure.in | 2 +- toolkit/library/rust/shared/Cargo.toml | 1 + toolkit/library/rust/shared/lib.rs | 3 + tools/lint/clippy.yml | 1 + 14 files changed, 633 insertions(+), 6 deletions(-) create mode 100644 dom/midi/midirMIDIPlatformService.cpp create mode 100644 dom/midi/midirMIDIPlatformService.h create mode 100644 dom/midi/midir_impl/Cargo.toml create mode 100644 dom/midi/midir_impl/cbindgen.toml create mode 100644 dom/midi/midir_impl/moz.build create mode 100644 dom/midi/midir_impl/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 7a7bb4ecd9fe..05fd0b221b2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2015,6 +2015,7 @@ dependencies = [ "mapped_hyph", "mdns_service", "midir", + "midir_impl", "mozurl", "mp4parse_capi", "neqo_glue", @@ -3074,6 +3075,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "midir_impl" +version = "0.1.0" +dependencies = [ + "midir", + "nsstring", + "thin-vec", + "uuid", +] + [[package]] name = "mime" version = "0.3.16" diff --git a/Cargo.toml b/Cargo.toml index 4bf661789e67..4c521137d008 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,7 @@ chardetng = { git = "https://github.com/hsivonen/chardetng", rev="302c995f91f44c chardetng_c = { git = "https://github.com/hsivonen/chardetng_c", rev="ed8a4c6f900a90d4dbc1d64b856e61490a1c3570" } libudev-sys = { path = "dom/webauthn/libudev-sys" } packed_simd = { git = "https://github.com/hsivonen/packed_simd", rev="8b4bd7d8229660a749dbe419a57ea01df9de5453" } +midir = { git = "https://github.com/mozilla/midir.git", rev = "dc87afbd4361ae5ec192e1fab0a6409dd13d4011" } minidump_writer_linux = { git = "https://github.com/msirringhaus/minidump_writer_linux.git", rev = "029ac0d54b237f27dc7d8d4e51bc0fb076e5e852" } # Patch mio 0.6 to use winapi 0.3 and miow 0.3, getting rid of winapi 0.2. diff --git a/dom/midi/MIDIPlatformService.cpp b/dom/midi/MIDIPlatformService.cpp index 70239dc3af9e..8a9090d30d53 100644 --- a/dom/midi/MIDIPlatformService.cpp +++ b/dom/midi/MIDIPlatformService.cpp @@ -7,6 +7,9 @@ #include "MIDIPlatformService.h" #include "MIDIMessageQueue.h" #include "TestMIDIPlatformService.h" +#ifndef MOZ_WIDGET_ANDROID +# include "midirMIDIPlatformService.h" +#endif // MOZ_WIDGET_ANDROID #include "mozilla/ErrorResult.h" #include "mozilla/StaticPrefs_midi.h" #include "mozilla/StaticPtr.h" @@ -179,10 +182,14 @@ MIDIPlatformService* MIDIPlatformService::Get() { MOZ_ASSERT(XRE_IsParentProcess()); ::mozilla::ipc::AssertIsOnBackgroundThread(); if (!IsRunning()) { - // Uncomment once we have an actual platform library to test. - // - // if (StaticPrefs::midi_testing()) { - gMIDIPlatformService = new TestMIDIPlatformService(); + if (StaticPrefs::midi_testing()) { + gMIDIPlatformService = new TestMIDIPlatformService(); + } +#ifndef MOZ_WIDGET_ANDROID + else { + gMIDIPlatformService = new midirMIDIPlatformService(); + } +#endif // MOZ_WIDGET_ANDROID gMIDIPlatformService->Init(); } return gMIDIPlatformService; diff --git a/dom/midi/midirMIDIPlatformService.cpp b/dom/midi/midirMIDIPlatformService.cpp new file mode 100644 index 000000000000..5367a5da2413 --- /dev/null +++ b/dom/midi/midirMIDIPlatformService.cpp @@ -0,0 +1,152 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "midirMIDIPlatformService.h" +#include "mozilla/StaticMutex.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/dom/MIDIPort.h" +#include "mozilla/dom/MIDITypes.h" +#include "mozilla/dom/MIDIPortInterface.h" +#include "mozilla/dom/MIDIPortParent.h" +#include "mozilla/dom/MIDIPlatformRunnables.h" +#include "mozilla/dom/MIDIUtils.h" +#include "mozilla/ipc/BackgroundParent.h" +#include "mozilla/Unused.h" +#include "nsIThread.h" + +using namespace mozilla; +using namespace mozilla::dom; +using namespace mozilla::ipc; + +static_assert(sizeof(TimeStamp) == sizeof(GeckoTimeStamp)); + +/** + * Runnable used for to send messages asynchronously on the I/O thread. + */ +class SendRunnable : public MIDIBackgroundRunnable { + public: + explicit SendRunnable(const nsAString& aPortID) + : MIDIBackgroundRunnable("SendRunnable"), mPortID(aPortID) {} + ~SendRunnable() = default; + virtual void RunInternal() { + AssertIsOnBackgroundThread(); + midirMIDIPlatformService* srv = + static_cast(MIDIPlatformService::Get()); + srv->SendMessages(mPortID); + } + + private: + nsString mPortID; + nsTArray mMsgs; +}; + +// static +StaticMutex midirMIDIPlatformService::gBackgroundThreadMutex; + +// static +nsCOMPtr midirMIDIPlatformService::gBackgroundThread; + +midirMIDIPlatformService::midirMIDIPlatformService() + : mIsInitialized(false), mImplementation(nullptr) { + StaticMutexAutoLock lock(gBackgroundThreadMutex); + gBackgroundThread = NS_GetCurrentThread(); +} + +midirMIDIPlatformService::~midirMIDIPlatformService() { + midir_impl_shutdown(mImplementation); + StaticMutexAutoLock lock(gBackgroundThreadMutex); + gBackgroundThread = nullptr; +} + +// static +void midirMIDIPlatformService::AddPort(const nsString* aId, + const nsString* aName, bool aInput) { + MIDIPortType type = aInput ? MIDIPortType::Input : MIDIPortType::Output; + MIDIPortInfo port(*aId, *aName, u""_ns, u""_ns, static_cast(type)); + MIDIPlatformService::Get()->AddPortInfo(port); +} + +void midirMIDIPlatformService::Init() { + if (mIsInitialized) { + return; + } + + mImplementation = midir_impl_init(); + + if (mImplementation) { + mIsInitialized = true; + midir_impl_enum_ports(mImplementation, AddPort); + MIDIPlatformService::Get()->SendPortList(); + } +} + +// static +void midirMIDIPlatformService::CheckAndReceive(const nsString* aId, + const uint8_t* aData, + size_t aLength, + const GeckoTimeStamp* aTimeStamp, + uint64_t aMicros) { + nsTArray data; + for (size_t i = 0; i < aLength; i++) { + data.AppendElement(aData[i]); + } + const TimeStamp* openTime = reinterpret_cast(aTimeStamp); + TimeStamp timestamp = + *openTime + TimeDuration::FromMicroseconds(static_cast(aMicros)); + MIDIMessage message(data, timestamp); + nsTArray messages; + messages.AppendElement(message); + + nsCOMPtr r(new ReceiveRunnable(*aId, messages)); + StaticMutexAutoLock lock(gBackgroundThreadMutex); + if (gBackgroundThread) { + gBackgroundThread->Dispatch(r, NS_DISPATCH_NORMAL); + } +} + +void midirMIDIPlatformService::Open(MIDIPortParent* aPort) { + MOZ_ASSERT(aPort); + nsString id = aPort->MIDIPortInterface::Id(); + TimeStamp openTimeStamp = TimeStamp::Now(); + if (midir_impl_open_port(mImplementation, &id, + reinterpret_cast(&openTimeStamp), + CheckAndReceive)) { + nsCOMPtr r(new SetStatusRunnable( + aPort->MIDIPortInterface::Id(), aPort->DeviceState(), + MIDIPortConnectionState::Open)); + NS_DispatchToCurrentThread(r); + } +} + +void midirMIDIPlatformService::Stop() { + // Nothing to do here AFAIK +} + +void midirMIDIPlatformService::ScheduleSend(const nsAString& aPortId) { + nsCOMPtr r(new SendRunnable(aPortId)); + StaticMutexAutoLock lock(gBackgroundThreadMutex); + if (gBackgroundThread) { + gBackgroundThread->Dispatch(r, NS_DISPATCH_NORMAL); + } +} + +void midirMIDIPlatformService::ScheduleClose(MIDIPortParent* aPort) { + MOZ_ASSERT(aPort); + nsString id = aPort->MIDIPortInterface::Id(); + if (aPort->ConnectionState() == MIDIPortConnectionState::Open) { + midir_impl_close_port(mImplementation, &id); + nsCOMPtr r(new SetStatusRunnable( + aPort->MIDIPortInterface::Id(), aPort->DeviceState(), + MIDIPortConnectionState::Closed)); + NS_DispatchToCurrentThread(r); + } +} + +void midirMIDIPlatformService::SendMessages(const nsAString& aPortId) { + nsTArray messages; + GetMessages(aPortId, messages); + for (const auto& message : messages) { + midir_impl_send(mImplementation, &aPortId, &message.data()); + } +} diff --git a/dom/midi/midirMIDIPlatformService.h b/dom/midi/midirMIDIPlatformService.h new file mode 100644 index 000000000000..21177b7b3635 --- /dev/null +++ b/dom/midi/midirMIDIPlatformService.h @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_midirMIDIPlatformService_h +#define mozilla_dom_midirMIDIPlatformService_h + +#include "mozilla/StaticMutex.h" +#include "mozilla/dom/MIDIPlatformService.h" +#include "mozilla/dom/MIDITypes.h" +#include "mozilla/dom/midi/midir_impl_ffi_generated.h" + +class nsIThread; +struct MidirWrapper; + +namespace mozilla::dom { + +class MIDIPortInterface; + +/** + * Platform service implementation using the midir crate. + */ +class midirMIDIPlatformService : public MIDIPlatformService { + public: + midirMIDIPlatformService(); + virtual void Init() override; + virtual void Open(MIDIPortParent* aPort) override; + virtual void Stop() override; + virtual void ScheduleSend(const nsAString& aPort) override; + virtual void ScheduleClose(MIDIPortParent* aPort) override; + + void SendMessages(const nsAString& aPort); + + private: + virtual ~midirMIDIPlatformService(); + + static void AddPort(const nsString* aId, const nsString* aName, bool aInput); + static void CheckAndReceive(const nsString* aId, const uint8_t* aData, + size_t aLength, const GeckoTimeStamp* aTimeStamp, + uint64_t aMicros); + + // True if server has been brought up already. + bool mIsInitialized; + + // Wrapper around the midir Rust implementation. + MidirWrapper* mImplementation; + + // midir has its own internal threads and we can't execute jobs directly on + // them, instead we forward them to the background thread the service was + // created in. + static StaticMutex gBackgroundThreadMutex; + static nsCOMPtr gBackgroundThread; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_midirMIDIPlatformService_h diff --git a/dom/midi/midir_impl/Cargo.toml b/dom/midi/midir_impl/Cargo.toml new file mode 100644 index 000000000000..7628fb4a6826 --- /dev/null +++ b/dom/midi/midir_impl/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "midir_impl" +version = "0.1.0" +authors = ["Gabriele Svelto"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +midir = "0.7.0" +nsstring = { path = "../../../xpcom/rust/nsstring/" } +uuid = { version = "0.8", features = ["v4"] } +thin-vec = { version = "0.2.1", features = ["gecko-ffi"] } diff --git a/dom/midi/midir_impl/cbindgen.toml b/dom/midi/midir_impl/cbindgen.toml new file mode 100644 index 000000000000..1b80a85e4539 --- /dev/null +++ b/dom/midi/midir_impl/cbindgen.toml @@ -0,0 +1,18 @@ +header = """/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */""" +autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen. See RunCbindgen.py */ +""" +include_version = true +braces = "SameLine" +line_length = 100 +tab_width = 2 +language = "C++" +include_guard = "midir_impl_ffi_generated_h" +includes = ["nsStringFwd.h", "nsTArrayForwardDeclare.h"] + +[defines] +"target_os = windows" = "XP_WIN" + +[export.rename] +"ThinVec" = "nsTArray" diff --git a/dom/midi/midir_impl/moz.build b/dom/midi/midir_impl/moz.build new file mode 100644 index 000000000000..f079022906f8 --- /dev/null +++ b/dom/midi/midir_impl/moz.build @@ -0,0 +1,17 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +if CONFIG["COMPILE_ENVIRONMENT"]: + # This tells mach to run cbindgen and that this header-file should be created + CbindgenHeader( + "midir_impl_ffi_generated.h", + inputs=["/dom/midi/midir_impl"], + ) + + # This tells mach to copy that generated file to obj/dist/includes/mozilla/dom/midi + EXPORTS.mozilla.dom.midi += [ + "!midir_impl_ffi_generated.h", + ] diff --git a/dom/midi/midir_impl/src/lib.rs b/dom/midi/midir_impl/src/lib.rs new file mode 100644 index 000000000000..d70b90ac5484 --- /dev/null +++ b/dom/midi/midir_impl/src/lib.rs @@ -0,0 +1,334 @@ +extern crate thin_vec; + +use midir::{ + InitError, MidiInput, MidiInputConnection, MidiInputPort, MidiOutput, MidiOutputConnection, + MidiOutputPort, +}; +use nsstring::{nsAString, nsString}; +use std::boxed::Box; +use std::ptr; +use thin_vec::ThinVec; +use uuid::Uuid; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ +extern crate midir; + +#[cfg(target_os = "windows")] +#[repr(C)] +#[derive(Clone, Copy)] +pub struct GeckoTimeStamp { + gtc: u64, + qpc: u64, + + is_null: u8, + has_qpc: u8, +} + +#[cfg(not(target_os = "windows"))] +#[repr(C)] +#[derive(Clone, Copy)] +pub struct GeckoTimeStamp { + value: u64, +} + +enum MidiConnection { + Input(MidiInputConnection), + Output(MidiOutputConnection), +} + +struct MidiConnectionWrapper { + id: String, + connection: MidiConnection, +} + +enum MidiPort { + Input(MidiInputPort), + Output(MidiOutputPort), +} + +struct MidiPortWrapper { + id: String, + name: String, + port: MidiPort, +} + +pub struct MidirWrapper { + ports: Vec, + connections: Vec, +} + +struct CallbackData { + nsid: nsString, + open_timestamp: GeckoTimeStamp, +} + +impl MidirWrapper { + fn open_port( + self: &mut MidirWrapper, + nsid: &nsString, + timestamp: GeckoTimeStamp, + callback: unsafe extern "C" fn( + id: &nsString, + data: *const u8, + length: usize, + timestamp: &GeckoTimeStamp, + micros: u64, + ), + ) -> Result<(), ()> { + let id = nsid.to_string(); + let ports = &self.ports; + let connections = &mut self.connections; + let port = ports.iter().find(|e| e.id.eq(&id)); + if let Some(port) = port { + match &port.port { + MidiPort::Input(port) => { + let input = MidiInput::new("WebMIDI input").map_err(|_err| ())?; + let data = CallbackData { + nsid: nsid.clone(), + open_timestamp: timestamp, + }; + let connection = input + .connect( + port, + "Input connection", + move |stamp, message, data| unsafe { + callback( + &data.nsid, + message.as_ptr(), + message.len(), + &data.open_timestamp, + stamp, + ); + }, + data, + ) + .map_err(|_err| ())?; + let connection_wrapper = MidiConnectionWrapper { + id: id.clone(), + connection: MidiConnection::Input(connection), + }; + connections.push(connection_wrapper); + return Ok(()); + } + MidiPort::Output(port) => { + let output = MidiOutput::new("WebMIDI output").map_err(|_err| ())?; + let connection = output + .connect(port, "Output connection") + .map_err(|_err| ())?; + let connection_wrapper = MidiConnectionWrapper { + connection: MidiConnection::Output(connection), + id: id.clone(), + }; + connections.push(connection_wrapper); + return Ok(()); + } + } + } + + Err(()) + } + + fn close_port(self: &mut MidirWrapper, id: &str) { + let connections = &mut self.connections; + let index = connections.iter().position(|e| e.id.eq(id)).unwrap(); + let connection_wrapper = connections.remove(index); + + match connection_wrapper.connection { + MidiConnection::Input(connection) => { + connection.close(); + } + MidiConnection::Output(connection) => { + connection.close(); + } + } + } + + fn send(self: &mut MidirWrapper, id: &str, data: &[u8]) -> Result<(), ()> { + let connections = &mut self.connections; + let index = connections.iter().position(|e| e.id.eq(id)).unwrap(); + let connection_wrapper = connections.get_mut(index).unwrap(); + + match &mut connection_wrapper.connection { + MidiConnection::Output(connection) => { + connection.send(data).map_err(|_err| ())?; + } + _ => { + panic!("Sending on an input port!"); + } + } + + Ok(()) + } +} + +impl MidirWrapper { + fn new() -> Result { + let input = MidiInput::new("WebMIDI input")?; + let output = MidiOutput::new("WebMIDI output")?; + let mut ports: Vec = Vec::new(); + collect_input_ports(&input, &mut ports); + collect_output_ports(&output, &mut ports); + let connections: Vec = Vec::new(); + Ok(MidirWrapper { ports, connections }) + } +} + +/// Create the C++ wrapper that will be used to talk with midir. +/// +/// This function will be exposed to C++ +/// +/// # Safety +/// +/// This function deliberately leaks the wrapper because ownership is +/// transfered to the C++ code. Use [midir_impl_shutdown()] to free it. +#[no_mangle] +pub unsafe extern "C" fn midir_impl_init() -> *mut MidirWrapper { + if let Ok(midir_impl) = MidirWrapper::new() { + let midir_box = Box::new(midir_impl); + // Leak the object as it will be owned by the C++ code from now on + Box::leak(midir_box) as *mut _ + } else { + ptr::null_mut() + } +} + +/// Shutdown midir and free the C++ wrapper. +/// +/// This function will be exposed to C++ +/// +/// # Safety +/// +/// `wrapper` must be the pointer returned by [midir_impl_init()]. After this +/// has been called the wrapper object will be destoyed and cannot be accessed +/// anymore. +#[no_mangle] +pub unsafe extern "C" fn midir_impl_shutdown(wrapper: *mut MidirWrapper) { + // The MidirImpl object will be automatically destroyed when the contents + // of this box are automatically dropped at the end of the function + let _midir_box = Box::from_raw(wrapper); +} + +/// Enumerate the available MIDI ports. +/// +/// This function will be exposed to C++ +/// +/// # Safety +/// +/// `wrapper` must be the pointer returned by [midir_impl_init()]. +#[no_mangle] +pub unsafe extern "C" fn midir_impl_enum_ports( + wrapper: *mut MidirWrapper, + callback: unsafe extern "C" fn(id: &nsString, name: &nsString, input: bool), +) { + iterate_ports(&(*wrapper).ports, callback); +} + +/// Open a MIDI port. +/// +/// This function will be exposed to C++ +/// +/// # Safety +/// +/// `wrapper` must be the pointer returned by [midir_impl_init()]. +#[no_mangle] +pub unsafe extern "C" fn midir_impl_open_port( + wrapper: *mut MidirWrapper, + nsid: *mut nsString, + timestamp: *mut GeckoTimeStamp, + callback: unsafe extern "C" fn( + id: &nsString, + data: *const u8, + length: usize, + timestamp: &GeckoTimeStamp, + micros: u64, + ), +) -> bool { + (*wrapper) + .open_port(nsid.as_ref().unwrap(), *timestamp, callback) + .is_ok() +} + +/// Close a MIDI port. +/// +/// This function will be exposed to C++ +/// +/// # Safety +/// +/// `wrapper` must be the pointer returned by [midir_impl_init()]. +#[no_mangle] +pub unsafe extern "C" fn midir_impl_close_port(wrapper: *mut MidirWrapper, id: *mut nsString) { + (*wrapper).close_port(&(*id).to_string()); +} + +/// Send a message over a MIDI output port. +/// +/// This function will be exposed to C++ +/// +/// # Safety +/// +/// `wrapper` must be the pointer returned by [midir_impl_init()]. +#[no_mangle] +pub unsafe extern "C" fn midir_impl_send( + wrapper: *mut MidirWrapper, + id: *const nsAString, + data: *const ThinVec, +) -> bool { + (*wrapper) + .send(&(*id).to_string(), (*data).as_slice()) + .is_ok() +} + +fn collect_input_ports(input: &MidiInput, wrappers: &mut Vec) { + let ports = input.ports(); + for port in ports { + let id = Uuid::new_v4() + .to_hyphenated() + .encode_lower(&mut Uuid::encode_buffer()) + .to_owned(); + let name = input + .port_name(&port) + .unwrap_or_else(|_| "unknown input port".to_string()); + let port = MidiPortWrapper { + id, + name, + port: MidiPort::Input(port), + }; + wrappers.push(port); + } +} + +fn collect_output_ports(output: &MidiOutput, wrappers: &mut Vec) { + let ports = output.ports(); + for port in ports { + let id = Uuid::new_v4() + .to_hyphenated() + .encode_lower(&mut Uuid::encode_buffer()) + .to_owned(); + let name = output + .port_name(&port) + .unwrap_or_else(|_| "unknown input port".to_string()); + let port = MidiPortWrapper { + id, + name, + port: MidiPort::Output(port), + }; + wrappers.push(port); + } +} + +unsafe fn iterate_ports( + ports: &[MidiPortWrapper], + callback: unsafe extern "C" fn(id: &nsString, name: &nsString, input: bool), +) { + for port in ports { + let id = nsString::from(&port.id); + let name = nsString::from(&port.name); + let input = match port.port { + MidiPort::Input(_) => true, + MidiPort::Output(_) => false, + }; + callback(&id, &name, input); + } +} diff --git a/dom/midi/moz.build b/dom/midi/moz.build index 97d51875ee8f..8a3ad035f1fd 100644 --- a/dom/midi/moz.build +++ b/dom/midi/moz.build @@ -4,6 +4,9 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +if CONFIG["OS_TARGET"] != "Android": + DIRS += ["midir_impl"] + IPDL_SOURCES += [ "MIDITypes.ipdlh", "PMIDIManager.ipdl", @@ -31,7 +34,7 @@ EXPORTS.mozilla.dom += [ "MIDIUtils.h", ] -UNIFIED_SOURCES = [ +UNIFIED_SOURCES += [ "MIDIAccess.cpp", "MIDIAccessManager.cpp", "MIDIInput.cpp", @@ -56,8 +59,15 @@ UNIFIED_SOURCES = [ include("/ipc/chromium/chromium-config.mozbuild") if CONFIG["OS_TARGET"] == "Linux": + OS_LIBS += ["asound"] # Required by midir UNIFIED_SOURCES += ["AlsaCompatibility.cpp"] + +if CONFIG["OS_TARGET"] != "Android": + UNIFIED_SOURCES += [ + "midirMIDIPlatformService.cpp", + ] + FINAL_LIBRARY = "xul" LOCAL_INCLUDES += [ "/dom/base", diff --git a/old-configure.in b/old-configure.in index 51fd37a2fab9..3d9e15af237f 100644 --- a/old-configure.in +++ b/old-configure.in @@ -1270,7 +1270,7 @@ cocoa) LDFLAGS="$LDFLAGS -framework Cocoa" # Use -Wl as a trick to avoid -framework and framework names from # being separated by AC_SUBST_LIST. - TK_LIBS='-Wl,-framework,Foundation -Wl,-framework,CoreFoundation -Wl,-framework,CoreLocation -Wl,-framework,QuartzCore -Wl,-framework,Carbon -Wl,-framework,CoreAudio -Wl,-framework,CoreVideo -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,AddressBook -Wl,-framework,OpenGL -Wl,-framework,Security -Wl,-framework,ServiceManagement -Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -Wl,-framework,AppKit' + TK_LIBS='-Wl,-framework,Foundation -Wl,-framework,CoreFoundation -Wl,-framework,CoreLocation -Wl,-framework,QuartzCore -Wl,-framework,Carbon -Wl,-framework,CoreAudio -Wl,-framework,CoreVideo -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,AddressBook -Wl,-framework,OpenGL -Wl,-framework,Security -Wl,-framework,ServiceManagement -Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -Wl,-framework,AppKit -Wl,-framework,CoreMIDI' TK_CFLAGS="" CFLAGS="$CFLAGS $TK_CFLAGS" CXXFLAGS="$CXXFLAGS $TK_CFLAGS" diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml index 5febab6ea6ab..d0b16c7ddadd 100644 --- a/toolkit/library/rust/shared/Cargo.toml +++ b/toolkit/library/rust/shared/Cargo.toml @@ -73,6 +73,7 @@ qcms = { path = "../../../../gfx/qcms", features = ["c_bindings", "neon"], defau viaduct = { git = "https://github.com/mozilla/application-services", rev = "c51b63595a27a6ef45161012323e0261475c10c9"} webext_storage_bridge = { path = "../../../components/extensions/storage/webext_storage_bridge" } midir = { git = "https://github.com/mozilla/midir.git", rev = "dc87afbd4361ae5ec192e1fab0a6409dd13d4011" } +midir_impl = { path = "../../../../dom/midi/midir_impl" } # https://github.com/mozilla/audioipc-2/commits/master [target.'cfg(not(target_os = "macos"))'.dependencies] diff --git a/toolkit/library/rust/shared/lib.rs b/toolkit/library/rust/shared/lib.rs index c56a80163c43..bd30d79be3b0 100644 --- a/toolkit/library/rust/shared/lib.rs +++ b/toolkit/library/rust/shared/lib.rs @@ -82,6 +82,9 @@ extern crate viaduct; #[cfg(not(target_os = "android"))] extern crate midir; +#[cfg(not(target_os = "android"))] +extern crate midir_impl; + extern crate gecko_logger; #[cfg(feature = "oxidized_breakpad")] diff --git a/tools/lint/clippy.yml b/tools/lint/clippy.yml index c4a51f349cfb..8be4739317a0 100644 --- a/tools/lint/clippy.yml +++ b/tools/lint/clippy.yml @@ -3,6 +3,7 @@ clippy: description: Lint rust include: - build/workspace-hack/ + - dom/midi/midir_impl/ - dom/media/gtest/ - dom/webauthn/libudev-sys/ - gfx/webrender_bindings/