mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-05 01:10:49 +00:00
103 lines
3.0 KiB
Plaintext
103 lines
3.0 KiB
Plaintext
// Copyright 2025 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
#include <mutex>
|
|
|
|
#include <AVFAudio/AVFAudio.h>
|
|
|
|
#include "napi.h"
|
|
|
|
struct InstanceData {
|
|
std::mutex mutex;
|
|
Napi::ThreadSafeFunction on_change;
|
|
};
|
|
|
|
API_AVAILABLE(macos(14.0))
|
|
static Napi::Value GetIsMuted(const Napi::CallbackInfo& info) {
|
|
return Napi::Boolean::New(info.Env(),
|
|
AVAudioApplication.sharedInstance.inputMuted);
|
|
}
|
|
|
|
API_AVAILABLE(macos(14.0))
|
|
static void SetIsMuted(const Napi::CallbackInfo& info) {
|
|
auto value = info[0].As<Napi::Boolean>();
|
|
assert(value.IsBoolean());
|
|
|
|
NSError* err = nil;
|
|
BOOL muted = value.Value() ? YES : NO;
|
|
auto res = [AVAudioApplication.sharedInstance setInputMuted:muted error:&err];
|
|
if (!res || err != nil) {
|
|
Napi::Error::New(info.Env(), err.localizedDescription.UTF8String)
|
|
.ThrowAsJavaScriptException();
|
|
return;
|
|
}
|
|
}
|
|
|
|
API_AVAILABLE(macos(14.0))
|
|
static void OnIsMutedChange(const Napi::CallbackInfo& info) {
|
|
auto env = info.Env();
|
|
|
|
auto callback = info[0].As<Napi::Function>();
|
|
assert(callback.IsFunction());
|
|
|
|
auto data = env.GetInstanceData<InstanceData>();
|
|
{
|
|
std::lock_guard<std::mutex> guard(data->mutex);
|
|
data->on_change = Napi::ThreadSafeFunction::New(
|
|
env, callback, "mute-state-change.onChange", 1, 1);
|
|
data->on_change.Unref(env);
|
|
}
|
|
}
|
|
|
|
static void FinalizeInstance(Napi::Env env, InstanceData* data) {
|
|
if (@available(macos 14.0, *)) {
|
|
[AVAudioApplication.sharedInstance setInputMuteStateChangeHandler:nil
|
|
error:nil];
|
|
}
|
|
delete data;
|
|
}
|
|
|
|
API_AVAILABLE(macos(14.0))
|
|
static void Init(Napi::Env env) {
|
|
auto instanceData = new InstanceData();
|
|
env.SetInstanceData<InstanceData, FinalizeInstance>(instanceData);
|
|
|
|
NSError* err = nil;
|
|
auto res = [AVAudioApplication.sharedInstance
|
|
setInputMuteStateChangeHandler:^(BOOL muted) {
|
|
std::lock_guard<std::mutex> guard(instanceData->mutex);
|
|
instanceData->on_change.NonBlockingCall(
|
|
^(Napi::Env env, Napi::Function fn) {
|
|
fn.Call({});
|
|
});
|
|
return YES;
|
|
}
|
|
error:&err];
|
|
if (!res || err != nil) {
|
|
Napi::Error::New(env, err.localizedDescription.UTF8String)
|
|
.ThrowAsJavaScriptException();
|
|
return;
|
|
}
|
|
|
|
// Setup the observer, otherwise the callback above is never called
|
|
[NSNotificationCenter.defaultCenter
|
|
addObserverForName:AVAudioApplicationInputMuteStateChangeNotification
|
|
object:nil
|
|
queue:nil
|
|
usingBlock:^(NSNotification*){
|
|
}];
|
|
}
|
|
|
|
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
if (@available(macos 14.0, *)) {
|
|
exports["getIsMuted"] = Napi::Function::New(env, &GetIsMuted);
|
|
exports["setIsMuted"] = Napi::Function::New(env, &SetIsMuted);
|
|
exports["onIsMutedChange"] = Napi::Function::New(env, &OnIsMutedChange);
|
|
|
|
Init(env);
|
|
}
|
|
return exports;
|
|
}
|
|
|
|
NODE_API_MODULE(mute - state - change, Init)
|