Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default System Output #16

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 40 additions & 6 deletions MultiSoundChanger.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 52;
objects = {

/* Begin PBXBuildFile section */
4743EFAB1E91493B0032F5AA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4743EFAA1E91493B0032F5AA /* AppDelegate.swift */; };
6985C6FE251951F8003C2FDB /* OSD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6985C6FD251951F8003C2FDB /* OSD.framework */; };
D914CAC52698095C00FB55D2 /* SimplyCoreAudio in Frameworks */ = {isa = PBXBuildFile; productRef = D914CAC42698095C00FB55D2 /* SimplyCoreAudio */; };
E4FFDC0757FD125F92CC0F62 /* Pods_MultiSoundChanger.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C34C05E9BD81D579A0C4957 /* Pods_MultiSoundChanger.framework */; };
F312C54E25B3741C00205846 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F373D8C02561D24600642274 /* Main.storyboard */; };
F312C55025B3742200205846 /* Volume.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F373D8BC2561D22000642274 /* Volume.storyboard */; };
Expand Down Expand Up @@ -62,6 +63,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D914CAC52698095C00FB55D2 /* SimplyCoreAudio in Frameworks */,
6985C6FE251951F8003C2FDB /* OSD.framework in Frameworks */,
E4FFDC0757FD125F92CC0F62 /* Pods_MultiSoundChanger.framework in Frameworks */,
);
Expand Down Expand Up @@ -242,6 +244,9 @@
dependencies = (
);
name = MultiSoundChanger;
packageProductDependencies = (
D914CAC42698095C00FB55D2 /* SimplyCoreAudio */,
);
productName = DynamicsIllusion;
productReference = 4743EFA71E91493B0032F5AA /* MultiSoundChanger.app */;
productType = "com.apple.product-type.application";
Expand Down Expand Up @@ -271,6 +276,9 @@
Base,
);
mainGroup = 4743EF9E1E91493B0032F5AA;
packageReferences = (
D914CAC32698095C00FB55D2 /* XCRemoteSwiftPackageReference "SimplyCoreAudio" */,
);
productRefGroup = 4743EFA81E91493B0032F5AA /* Products */;
projectDirPath = "";
projectRoot = "";
Expand Down Expand Up @@ -500,7 +508,8 @@
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
};
name = Release;
Expand All @@ -520,8 +529,11 @@
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = MultiSoundChanger/Other/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.12;
MARKETING_VERSION = 1.0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.rlxone.multisoundchanger;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -546,8 +558,11 @@
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = MultiSoundChanger/Other/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.10;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.12;
MARKETING_VERSION = 1.0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.rlxone.multisoundchanger;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -579,6 +594,25 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */

/* Begin XCRemoteSwiftPackageReference section */
D914CAC32698095C00FB55D2 /* XCRemoteSwiftPackageReference "SimplyCoreAudio" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/rnine/SimplyCoreAudio";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.0.1;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
D914CAC42698095C00FB55D2 /* SimplyCoreAudio */ = {
isa = XCSwiftPackageProductDependency;
package = D914CAC32698095C00FB55D2 /* XCRemoteSwiftPackageReference "SimplyCoreAudio" */;
productName = SimplyCoreAudio;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 4743EF9F1E91493B0032F5AA /* Project object */;
}
24 changes: 23 additions & 1 deletion MultiSoundChanger/Sources/Classes/ApplicationController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Foundation
import MediaKeyTap
import SimplyCoreAudio

// MARK: - Protocols

Expand All @@ -18,13 +19,34 @@ protocol ApplicationController: class {
// MARK: - Implementation

final class ApplicationControllerImp: ApplicationController {
private lazy var simplyCA: SimplyCoreAudio = SimplyCoreAudio()
private lazy var audioManager: AudioManager = AudioManagerImpl()
private lazy var mediaManager: MediaManager = MediaManagerImpl(delegate: self)
private lazy var statusBarController: StatusBarController = StatusBarControllerImpl(audioManager: audioManager)
private lazy var statusBarController: StatusBarController = StatusBarControllerImpl(audioManager: audioManager, simplyCoreAudio: simplyCA)

var observers: [NSObjectProtocol] = []

func start() {
statusBarController.createMenu()
mediaManager.listenMediaKeyTaps()

observers.append(NotificationCenter.default.addObserver(forName: .deviceListChanged,
object: nil,
queue: .main) { [weak self] _ in
self?.statusBarController.createMenu()
})

observers.append(NotificationCenter.default.addObserver(forName: .defaultOutputDeviceChanged,
object: nil,
queue: .main) { [weak self] _ in
self?.statusBarController.createMenu()
})
}

deinit {
for observer in observers {
NotificationCenter.default.removeObserver(observer)
}
}
}

Expand Down
24 changes: 18 additions & 6 deletions MultiSoundChanger/Sources/Classes/AudioManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import Foundation
// MARK: - Protocols

protocol AudioManager: class {
func getDefaultOutputDevice() -> AudioDeviceID
func getOutputDevices() -> [AudioDeviceID: String]?
func selectDevice(deviceID: AudioDeviceID)
func getSelectedDeviceVolume() -> Float?
func setSelectedDeviceVolume(masterChannelLevel: Float, leftChannelLevel: Float, rightChannelLevel: Float)
Expand All @@ -27,14 +25,28 @@ protocol AudioManager: class {

final class AudioManagerImpl: AudioManager {
private let audio: Audio = AudioImpl()
private let devices: [AudioDeviceID: String]?
private var devices: [AudioDeviceID: String]?
private var selectedDevice: AudioDeviceID?


private lazy var observer = NotificationCenter.default.addObserver(forName: .deviceListChanged,
object: nil,
queue: .main) { [weak self] _ in
self?.refreshDevices()
}

init() {
devices = audio.getOutputDevices()
printDevices()
refreshDevices()
}

deinit {
NotificationCenter.default.removeObserver(observer)
}

func refreshDevices() {
self.devices = audio.getOutputDevices()
self.printDevices()
}

func getDefaultOutputDevice() -> AudioDeviceID {
return audio.getDefaultOutputDevice()
}
Expand Down
32 changes: 21 additions & 11 deletions MultiSoundChanger/Sources/Classes/StatusBarController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Copyright © 2020 Dmitry Medyuho. All rights reserved.
//

import SimplyCoreAudio
import AudioToolbox
import Cocoa

Expand Down Expand Up @@ -37,9 +38,11 @@ final class StatusBarControllerImpl: StatusBarController {
private let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
private let volumeController: VolumeViewController
private let audioManager: AudioManager
private let simplyCA: SimplyCoreAudio

init(audioManager: AudioManager) {
init(audioManager: AudioManager, simplyCoreAudio: SimplyCoreAudio) {
self.audioManager = audioManager
self.simplyCA = simplyCoreAudio

self.volumeController = Stories.volume.controller(VolumeViewController.self)
self.volumeController.audioManager = audioManager
Expand All @@ -51,7 +54,8 @@ final class StatusBarControllerImpl: StatusBarController {
button.image = Images.volumeImage1
}

let menu = NSMenu()
let menu = statusItem.menu ?? NSMenu()
menu.removeAllItems()
menu.autoenablesItems = false

let volumeItem = getMenuItem(by: .volume)
Expand Down Expand Up @@ -135,32 +139,38 @@ final class StatusBarControllerImpl: StatusBarController {
}

private func setOutputDeviceList(for menu: NSMenu) {
guard let devices = audioManager.getOutputDevices() else {
return
}
let devices = simplyCA.allOutputDevices

let defaultDevice = audioManager.getDefaultOutputDevice()
let defaultDevice = simplyCA.defaultOutputDevice

for device in devices {
let item = NSMenuItem(
title: truncate(device.value, length: Constants.optionMaxLength),
title: truncate(device.name, length: Constants.optionMaxLength),
action: #selector(menuItemAction),
keyEquivalent: String()
)
item.target = self
item.tag = Int(device.key)
item.tag = Int(device.id)

if device.key == defaultDevice {
if device.id == defaultDevice?.id {
item.state = .on
selectDevice(device: defaultDevice)
selectDevice(device: device.id)
}

menu.addItem(item)
}
}

private func selectDevice(device: AudioDeviceID) {
audioManager.selectDevice(deviceID: device)
guard let new_device = simplyCA.allDevices.first(where: { $0.id == device }) else {
return
}
new_device.isDefaultOutputDevice = true
new_device.isDefaultSystemOutputDevice = true
if new_device.isOutputOnlyDevice == false {
new_device.isDefaultInputDevice = true
}

guard let volume = audioManager.getSelectedDeviceVolume() else {
return
}
Expand Down