1
1
mirror of https://github.com/bitgapp/eqMac.git synced 2024-11-30 03:35:04 +03:00

implemented more secure hiding showing of the driver

This commit is contained in:
Nodeful 2020-06-28 23:41:20 +01:00
parent d86e82b849
commit 2ebc3c8385
12 changed files with 106 additions and 53 deletions

View File

@ -7,7 +7,7 @@
<string>com.bitgapp.eqmac.xpc</string>
</array>
<key>BuildMachineOSBuild</key>
<string>19C57</string>
<string>19F101</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
@ -21,7 +21,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.1</string>
<string>1.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
@ -29,7 +29,7 @@
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1.1.1</string>
<string>1.2</string>
<key>CFPlugInFactories</key>
<dict>
<key>7080ba34-76cc-40b2-b2b3-819d28460e7e</key>

View File

@ -20,7 +20,7 @@ target 'eqMac' do
pod 'SwiftLint'
pod 'Sparkle'
pod 'Sentry', '~> 4.1'
pod 'EmitterKit', '~> 5.2'
pod 'EmitterKit', '~> 5.2.2'
pod 'SwiftyJSON', '~> 4.2'
pod 'SwiftyUserDefaults', '4.0'
# pod 'Swifter', '~> 1.4'

View File

@ -26,7 +26,7 @@ DEPENDENCIES:
- Alamofire (~> 5.1)
- AMCoreAudio (~> 3.3.1)
- AudioKit (= 4.9.5)
- EmitterKit (~> 5.2)
- EmitterKit (~> 5.2.2)
- KeychainSwift (~> 13.0)
- ReachabilitySwift
- ReSwift
@ -83,6 +83,6 @@ SPEC CHECKSUMS:
WebViewJavascriptBridge: 7f5bc4d3581e672e8f32bd0f812d54bc69bb8e29
Zip: 8877eede3dda76bcac281225c20e71c25270774c
PODFILE CHECKSUM: 3850edcd366592498848f4adaf654cc1d56c6dc8
PODFILE CHECKSUM: c1a005dd8338743c78b678ca45a079aaeb33bdbc
COCOAPODS: 1.9.1
COCOAPODS: 1.9.3

View File

@ -75,6 +75,7 @@ class Application {
// AudioKit Engine fucks with Driver installation, eqMac doesn't use it's engine anyway
try? AudioKit.stop()
try? AudioKit.shutdown()
AKSettings.audioInputEnabled = false
AKSettings.enableRouteChangeHandling = false
AKSettings.notificationsEnabled = false
@ -195,9 +196,8 @@ class Application {
private static var showPasshtroughDeviceChecks: Int = 0
private static var showPassthroughDeviceCheckQueue: DispatchQueue?
private static func showPassthroughDevice (_ completion: @escaping() -> Void) {
let driverIsHidden = Driver.getDeviceIsHidden(device: .passthrough)
if (driverIsHidden) {
Driver.showDevice(device: .passthrough)
if (Driver.hidden) {
Driver.shown = true
showPasshtroughDeviceChecks = 0
showPassthroughDeviceCheckQueue = DispatchQueue(label: "check-driver-shown", qos: .userInteractive)
showPassthroughDeviceCheckQueue!.asyncAfter(deadline: .now() + .milliseconds(500)) {
@ -504,7 +504,7 @@ class Application {
stopListeners()
stopEngines()
switchBackToLastKnownDevice()
Driver.hideDevice(device: .passthrough)
Driver.hidden = true
Storage.synchronize()
NSApp.terminate(nil)
}

View File

@ -24,6 +24,7 @@ enum DriverDeviceIsActiveProperty: String {
enum CustomProperties: String {
case kAudioDeviceCustomPropertyLatency = "cltc"
case kAudioDeviceCustomPropertySafetyOffset = "csfo"
case kAudioDeviceCustomPropertyShown = "shwn"
}
class Driver {
@ -108,7 +109,7 @@ class Driver {
]
}
static func getDeviceIsShown (device: DriverDevice) -> Bool {
static func getDeviceIsActive (device: DriverDevice) -> Bool {
if Driver.device != nil { return true }
if let pluginId = self.pluginId {
var address = AudioObjectPropertyAddress(
@ -127,26 +128,6 @@ class Driver {
return false
}
static func getDeviceIsHidden (device: DriverDevice) -> Bool {
return !getDeviceIsShown(device: device)
}
static func hideDevice (device: DriverDevice) {
return setDeviceIsHidden(device: device, true)
}
static func showDevice (device: DriverDevice) {
return setDeviceIsShown(device: device, true)
}
static func setDeviceIsShown (device: DriverDevice, _ shown: Bool) {
return setDeviceIsHidden(device: device, !shown)
}
static func setDeviceIsHidden (device: DriverDevice, _ hidden: Bool) {
return setDeviceIsActive(device: device, !hidden)
}
private static func setDeviceIsActive (device: DriverDevice, _ active: Bool) {
if let pluginId = self.pluginId {
var mSelector: AudioObjectPropertySelector = getPropertySelectorFromString(getDeviceIsActiveProperty(device).rawValue)
@ -225,6 +206,43 @@ class Driver {
}
}
static var shown: Bool {
get {
if Driver.device == nil { return false }
var address = AudioObjectPropertyAddress(
mSelector: getPropertySelectorFromString(CustomProperties.kAudioDeviceCustomPropertyShown.rawValue),
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMaster
)
var size: UInt32 = UInt32(MemoryLayout<CFBoolean>.size)
var shown = kCFBooleanFalse
checkErr(AudioObjectGetPropertyData(Driver.device!.id, &address, 0, nil, &size, &shown))
return CFBooleanGetValue(shown!)
}
set {
if Driver.device == nil { return }
var address = AudioObjectPropertyAddress(
mSelector: getPropertySelectorFromString(CustomProperties.kAudioDeviceCustomPropertyShown.rawValue),
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMaster
)
let size: UInt32 = UInt32(MemoryLayout<CFBoolean>.size)
var shown: CFBoolean = newValue.cfBooleanValue
checkErr(AudioObjectSetPropertyData(Driver.device!.id, &address, 0, nil, size, &shown))
}
}
static var hidden: Bool {
get { return !shown }
set { shown = !newValue }
}
static var device: AudioDevice? {
return AudioDevice.lookup(by: Constants.PASSTHROUGH_DEVICE_UID)
}

View File

@ -597,7 +597,7 @@
CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1.1.1;
CURRENT_PROJECT_VERSION = 1.2;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = JZA6C97KJA;
GCC_C_LANGUAGE_STANDARD = "compiler-default";
@ -610,7 +610,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
MARKETING_VERSION = 1.1.1;
MARKETING_VERSION = 1.2;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.bitgapp.eqmac.driver;
@ -637,7 +637,7 @@
CODE_SIGN_IDENTITY = "Developer ID Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1.1.1;
CURRENT_PROJECT_VERSION = 1.2;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = JZA6C97KJA;
ENABLE_NS_ASSERTIONS = NO;
@ -650,7 +650,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = "$(SRCROOT)/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
MARKETING_VERSION = 1.1.1;
MARKETING_VERSION = 1.2;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.bitgapp.eqmac.driver;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -7,10 +7,10 @@ fi
if [ "${CONFIGURATION}" = "Debug" ]; then
export SUDO_ASKPASS=~/askpass.sh
# Uninstall any new driver leftovers
sudo rm -rf /Library/Audio/Plug-Ins/HAL/eqMac.driver/
sudo -A rm -rf /Library/Audio/Plug-Ins/HAL/eqMac.driver/
# Install the new driver
sudo cp -f -r "$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME" /Library/Audio/Plug-Ins/HAL/
sudo -A cp -f -r "$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME" /Library/Audio/Plug-Ins/HAL/
# Restart CoreAudio
sudo launchctl kickstart -kp system/com.apple.audio.coreaudiod
sudo -A launchctl kickstart -kp system/com.apple.audio.coreaudiod
fi

View File

@ -68,14 +68,14 @@ void EQM_Device::StaticInitializer()
kObjectID_Mute_Output_Master);
sInstance->Activate();
if (
!EQM_Utils::process_at_path_running("/Applications/eqMac.app/Contents/MacOS/eqMac")
&& !EQM_Utils::process_at_path_running("/Applications/Xcode.app/Contents/MacOS/Xcode")
) {
// Activate the Driver only if eqMac or Xcode are running from /Application folder
sInstance->Deactivate();
} else {
}
// if (
// !EQM_Utils::process_at_path_running("/Applications/eqMac.app/Contents/MacOS/eqMac")
// && !EQM_Utils::process_at_path_running("/Applications/Xcode.app/Contents/MacOS/Xcode")
// ) {
// // Activate the Driver only if eqMac or Xcode are running from /Application folder
// sInstance->Deactivate();
// } else {
// }
// The instance for system (UI) sounds.
sUISoundsInstance = new EQM_Device(kObjectID_Device_UI_Sounds,
@ -139,6 +139,7 @@ mMuteControl(inOutputMuteControlID, GetObjectID(), kAudioObjectPropertyScopeOutp
SetSampleRate(kSampleRateDefault);
SetSafetyOffset(kSafetyOffsetDefault);
SetLatency(kLatencyDefault);
SetShown(kShownDefault);
}
EQM_Device::~EQM_Device()
@ -323,6 +324,7 @@ bool EQM_Device::Device_HasProperty(AudioObjectID inObjectID, pid_t inClientPID,
case kAudioDevicePropertySafetyOffset:
case kAudioDeviceCustomPropertyLatency:
case kAudioDeviceCustomPropertySafetyOffset:
case kAudioDeviceCustomPropertyShown:
theAnswer = true;
break;
@ -368,6 +370,7 @@ bool EQM_Device::Device_IsPropertySettable(AudioObjectID inObjectID, pid_t inCli
case kAudioDeviceCustomPropertyEnabledOutputControls:
case kAudioDeviceCustomPropertyLatency:
case kAudioDeviceCustomPropertySafetyOffset:
case kAudioDeviceCustomPropertyShown:
theAnswer = true;
break;
@ -454,7 +457,7 @@ UInt32 EQM_Device::Device_GetPropertyDataSize(AudioObjectID inObjectID, pid_t in
break;
case kAudioObjectPropertyCustomPropertyInfoList:
theAnswer = sizeof(AudioServerPlugInCustomPropertyInfo) * 8;
theAnswer = sizeof(AudioServerPlugInCustomPropertyInfo) * 9;
break;
case kAudioDeviceCustomPropertyDeviceAudibleState:
@ -488,6 +491,10 @@ UInt32 EQM_Device::Device_GetPropertyDataSize(AudioObjectID inObjectID, pid_t in
theAnswer = sizeof(CFNumberRef);
break;
case kAudioDeviceCustomPropertyShown:
theAnswer = sizeof(CFBooleanRef);
break;
default:
theAnswer = EQM_AbstractDevice::GetPropertyDataSize(inObjectID, inClientPID, inAddress, inQualifierDataSize, inQualifierData);
break;
@ -675,7 +682,7 @@ void EQM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
"kAudioDevicePropertyDeviceCanBeDefaultDevice for the device");
// TODO: Add a field for this and set it in EQM_Device::StaticInitializer so we don't
// have to handle a specific instance differently here.
*reinterpret_cast<UInt32*>(outData) = (GetObjectID() == kObjectID_Device_UI_Sounds ? 0 : 1);
*reinterpret_cast<UInt32*>(outData) = mShown ? 1 : 0;
outDataSize = sizeof(UInt32);
break;
@ -903,9 +910,9 @@ void EQM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
theNumberItemsToFetch = inDataSize / sizeof(AudioServerPlugInCustomPropertyInfo);
// clamp it to the number of items we have
if(theNumberItemsToFetch > 8)
if(theNumberItemsToFetch > 9)
{
theNumberItemsToFetch = 8;
theNumberItemsToFetch = 9;
}
if(theNumberItemsToFetch > 0)
@ -958,6 +965,13 @@ void EQM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
((AudioServerPlugInCustomPropertyInfo*)outData)[6].mQualifierDataType = kAudioServerPlugInCustomPropertyDataTypeNone;
}
if(theNumberItemsToFetch > 8)
{
((AudioServerPlugInCustomPropertyInfo*)outData)[6].mSelector = kAudioDeviceCustomPropertyShown;
((AudioServerPlugInCustomPropertyInfo*)outData)[6].mPropertyDataType = kAudioServerPlugInCustomPropertyDataTypeCFPropertyList;
((AudioServerPlugInCustomPropertyInfo*)outData)[6].mQualifierDataType = kAudioServerPlugInCustomPropertyDataTypeNone;
}
outDataSize = theNumberItemsToFetch * sizeof(AudioServerPlugInCustomPropertyInfo);
break;
@ -1064,6 +1078,17 @@ void EQM_Device::Device_SetPropertyData(AudioObjectID inObjectID, pid_t inClient
break;
}
case kAudioDeviceCustomPropertyShown:
{
ThrowIf(inDataSize < sizeof(CFBooleanRef),
CAException(kAudioHardwareBadPropertySizeError),
"EQM_Device::Device_SetPropertyData: wrong size for the data for kAudioDeviceCustomPropertyShown");
CFBooleanRef shownRef = *reinterpret_cast<const CFBooleanRef*>(inData);
bool shown = CFBooleanGetValue(shownRef);
SetShown(shown);
break;
}
case kAudioDevicePropertyNominalSampleRate: {
ThrowIf(inDataSize < sizeof(Float64),
CAException(kAudioHardwareBadPropertySizeError),
@ -1846,6 +1871,12 @@ void EQM_Device::SetLatency(UInt32 inLatency)
mLatency = inLatency;
}
void EQM_Device::SetShown(bool shown)
{
CAMutex::Locker theStateLocker(mStateMutex);
mShown = shown;
}
bool EQM_Device::IsStreamID(AudioObjectID inObjectID) const noexcept
{
return (inObjectID == mInputStream.GetObjectID()) || (inObjectID == mOutputStream.GetObjectID());

View File

@ -156,6 +156,7 @@ private:
void SetSampleRate(Float64 inNewSampleRate, bool force = false);
void SetSafetyOffset(UInt32 inNewSafetyOffset);
void SetLatency(UInt32 inNewLatency);
void SetShown(bool shown);
/*! @return True if inObjectID is the ID of one of this device's streams. */
inline bool IsStreamID(AudioObjectID inObjectID) const noexcept;
@ -214,6 +215,7 @@ private:
const Float64 kSampleRateDefault = 44100.0;
const UInt32 kSafetyOffsetDefault = 0;
const UInt32 kLatencyDefault = 0;
const bool kShownDefault = false;
// Before we can change sample rate, the host has to stop the device. The new sample rate is
// stored here while it does.
Float64 mPendingSampleRate;
@ -228,6 +230,7 @@ private:
Float64 mLoopbackSampleRate;
UInt32 mSafetyOffset;
UInt32 mLatency;
bool mShown;
Float32 mLoopbackRingBuffer[kLoopbackRingBufferFrameSize * 2];
// TODO: a comment explaining why we need a clock for loopback-only mode
struct {

View File

@ -105,7 +105,8 @@ enum
// by default. This property is settable. See the array indices below for more info.
kAudioDeviceCustomPropertyEnabledOutputControls = 'bgct',
kAudioDeviceCustomPropertyLatency = 'cltc',
kAudioDeviceCustomPropertySafetyOffset = 'csfo'
kAudioDeviceCustomPropertySafetyOffset = 'csfo',
kAudioDeviceCustomPropertyShown = 'shwn'
};
// The number of silent/audible frames before EQMDriver will change kAudioDeviceCustomPropertyDeviceAudibleState

2
ui/package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "eqmac",
"version": "1.1.0",
"version": "1.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {