diff --git a/Main.hs b/Main.hs index c26d0de..b8d8042 100644 --- a/Main.hs +++ b/Main.hs @@ -88,8 +88,7 @@ tilingShell = -- scripts taken from ubersicht status widget via chunkwm sample ubersicht volumeShell :: Text -volumeShell = - [r| /Users/bkase/barbq2/getvolume/.build/release/getvolume |] +volumeShell = "barbq-getvolume" externalIpShell :: Text externalIpShell = "curl -s icanhazip.com | tr -d '\n' || true" diff --git a/barbq2.cabal b/barbq.cabal similarity index 91% rename from barbq2.cabal rename to barbq.cabal index 8ec3c21..94137ac 100644 --- a/barbq2.cabal +++ b/barbq.cabal @@ -1,8 +1,8 @@ cabal-version: >=1.10 --- Initial package description 'barbq2.cabal' generated by 'cabal init'. +-- Initial package description 'barbq.cabal' generated by 'cabal init'. -- For further documentation, see http://haskell.org/cabal/users-guide/ -name: barbq2 +name: barbq version: 0.1.0.0 -- synopsis: -- description: @@ -16,7 +16,7 @@ version: 0.1.0.0 build-type: Simple extra-source-files: CHANGELOG.md -executable barbq2 +executable barbq main-is: Main.hs ghc-options: -O2 -flate-specialise -fspecialise-aggressively -threaded -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -Wno-name-shadowing other-modules: Barbq.Types Barbq.UI.Framework Barbq.UI.Runtime Barbq.UI.Components diff --git a/default.nix b/default.nix index baa88ab..2104f2b 100644 --- a/default.nix +++ b/default.nix @@ -1,7 +1,7 @@ { compiler ? "ghc865", pkgs ? import {} }: let - + getvolume = pkgs.callPackage ./getvolume/default.nix { }; packageSet = pkgs.haskell.packages.${compiler}; haskellPackages = packageSet.override { @@ -9,28 +9,25 @@ let { ghc = super.ghc // { withPackages = super.ghc.withHoogle; }; ghcWithPackages = self.ghc.withPackages; - - polysemy = self.polysemy_1_2_1_0; - async-timer = pkgs.haskell.lib.dontCheck super.async-timer; - - polysemy-plugin = pkgs.haskell.lib.dontCheck (super.polysemy-plugin.override { polysemy = self.polysemy_1_2_1_0; }); } ); }; - drv = haskellPackages.callCabal2nix "barbq2" ./. {}; + raw = haskellPackages.callCabal2nix "barbq" ./. {}; + drv = pkgs.symlinkJoin { + name = "barbq"; + paths = [ raw getvolume ]; + }; in { barbq = drv; barbq-shell = haskellPackages.shellFor { - packages = p: [drv]; + packages = p: [raw]; shellHook = '' export HIE_HOOGLE_DATABASE="$(cat $(which hoogle) | sed -n -e 's|.*--database \(.*\.hoo\).*|\1|p')" - - pushd getvolume && swift build -c release && popd ''; - buildInputs = with pkgs; [ cabal-install hlint ghcid ] ++ (if pkgs.stdenv.isDarwin then [] else [ swift ]) ; + buildInputs = with pkgs; [ cabal-install hlint ghcid getvolume ] ; }; } diff --git a/getvolume/Package.swift b/getvolume/Package.swift deleted file mode 100644 index 4f4b5f8..0000000 --- a/getvolume/Package.swift +++ /dev/null @@ -1,22 +0,0 @@ -// swift-tools-version:5.1 -// The swift-tools-version declares the minimum version of Swift required to build this package. - -import PackageDescription - -let package = Package( - name: "getvolume", - dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), - ], - targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages which this package depends on. - .target( - name: "getvolume", - dependencies: []), - .testTarget( - name: "getvolumeTests", - dependencies: ["getvolume"]), - ] -) diff --git a/getvolume/README.md b/getvolume/README.md deleted file mode 100644 index 96f1dbb..0000000 --- a/getvolume/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# getvolume - -A description of this package. diff --git a/getvolume/Sources/getvolume/main.swift b/getvolume/Sources/getvolume/main.swift deleted file mode 100644 index b52b7c6..0000000 --- a/getvolume/Sources/getvolume/main.swift +++ /dev/null @@ -1,52 +0,0 @@ -import AudioToolbox -import Darwin - -var defaultOutputDeviceID = AudioDeviceID(0) -var defaultOutputDeviceIDSize = UInt32(MemoryLayout.size(ofValue: defaultOutputDeviceID)) - -var getDefaultOutputDevicePropertyAddress = AudioObjectPropertyAddress( - mSelector: kAudioHardwarePropertyDefaultOutputDevice, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: AudioObjectPropertyElement(kAudioObjectPropertyElementMaster)) - -let status1 = AudioObjectGetPropertyData( - AudioObjectID(kAudioObjectSystemObject), - &getDefaultOutputDevicePropertyAddress, - 0, - nil, - &defaultOutputDeviceIDSize, - &defaultOutputDeviceID) - -if status1 != 0 { fputs("status1 failed \(status1)\n", stderr); exit(-1) } - -var propAddr = AudioObjectPropertyAddress( - mSelector: AudioObjectPropertySelector(kAudioDevicePropertyMute), - mScope: AudioObjectPropertyScope(kAudioObjectPropertyScopeOutput), - mElement: AudioObjectPropertyElement(kAudioObjectPropertyElementMaster)) - -var isMuted: uint32 = 0 -var propSize = UInt32(MemoryLayout.size(ofValue: isMuted)) - -let status2 = AudioObjectGetPropertyData(defaultOutputDeviceID, &propAddr, 0, nil, &propSize, &isMuted) - -if status2 != 0 { fputs("status2 failed \(status2)\n", stderr); exit(-1) } - -var volume = Float32(0.0) -var volumeSize = UInt32(MemoryLayout.size(ofValue: volume)) - -var volumePropertyAddress = AudioObjectPropertyAddress( - mSelector: kAudioHardwareServiceDeviceProperty_VirtualMasterVolume, - mScope: kAudioDevicePropertyScopeOutput, - mElement: kAudioObjectPropertyElementMaster) - -let status3 = AudioObjectGetPropertyData( - defaultOutputDeviceID, - &volumePropertyAddress, - 0, - nil, - &volumeSize, - &volume) - -if status3 != 0 { fputs("status3 failed \(status3)\n", stderr); exit(-1) } - -print(String(Int(round(volume * 100))) + "," + String(isMuted != 0)) diff --git a/getvolume/Tests/LinuxMain.swift b/getvolume/Tests/LinuxMain.swift deleted file mode 100644 index 1b32abe..0000000 --- a/getvolume/Tests/LinuxMain.swift +++ /dev/null @@ -1,7 +0,0 @@ -import XCTest - -import getvolumeTests - -var tests = [XCTestCaseEntry]() -tests += getvolumeTests.allTests() -XCTMain(tests) diff --git a/getvolume/Tests/getvolumeTests/XCTestManifests.swift b/getvolume/Tests/getvolumeTests/XCTestManifests.swift deleted file mode 100644 index a177494..0000000 --- a/getvolume/Tests/getvolumeTests/XCTestManifests.swift +++ /dev/null @@ -1,9 +0,0 @@ -import XCTest - -#if !canImport(ObjectiveC) -public func allTests() -> [XCTestCaseEntry] { - return [ - testCase(getvolumeTests.allTests), - ] -} -#endif diff --git a/getvolume/Tests/getvolumeTests/getvolumeTests.swift b/getvolume/Tests/getvolumeTests/getvolumeTests.swift deleted file mode 100644 index fd5b774..0000000 --- a/getvolume/Tests/getvolumeTests/getvolumeTests.swift +++ /dev/null @@ -1,47 +0,0 @@ -import XCTest -import class Foundation.Bundle - -final class getvolumeTests: XCTestCase { - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct - // results. - - // Some of the APIs that we use below are available in macOS 10.13 and above. - guard #available(macOS 10.13, *) else { - return - } - - let fooBinary = productsDirectory.appendingPathComponent("getvolume") - - let process = Process() - process.executableURL = fooBinary - - let pipe = Pipe() - process.standardOutput = pipe - - try process.run() - process.waitUntilExit() - - let data = pipe.fileHandleForReading.readDataToEndOfFile() - let output = String(data: data, encoding: .utf8) - - XCTAssertEqual(output, "Hello, world!\n") - } - - /// Returns path to the built products directory. - var productsDirectory: URL { - #if os(macOS) - for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") { - return bundle.bundleURL.deletingLastPathComponent() - } - fatalError("couldn't find the products directory") - #else - return Bundle.main.bundleURL - #endif - } - - static var allTests = [ - ("testExample", testExample), - ] -} diff --git a/getvolume/default.nix b/getvolume/default.nix new file mode 100644 index 0000000..71b8cd8 --- /dev/null +++ b/getvolume/default.nix @@ -0,0 +1,14 @@ +{pkgs ? import {} }: +pkgs.stdenv.mkDerivation rec { + name = "barbq-getvolume"; + version = "0.2"; + src = ./.; + buildPhase = '' + clang main.c -framework CoreAudio -framework AudioToolbox + ''; + installPhase = '' + mkdir -p $out/bin + mv a.out $out/bin/barbq-getvolume + ''; + buildInputs = [ pkgs.darwin.apple_sdk.frameworks.CoreAudio pkgs.darwin.apple_sdk.frameworks.AudioToolbox ]; +} diff --git a/getvolume/main.c b/getvolume/main.c new file mode 100644 index 0000000..c1480ea --- /dev/null +++ b/getvolume/main.c @@ -0,0 +1,72 @@ +#include +#include +#include + +AudioDeviceID getCurrentlySelectedDeviceID() { + UInt32 propertySize; + AudioDeviceID deviceID = kAudioDeviceUnknown; + + AudioObjectPropertyAddress pa; + pa.mScope = kAudioObjectPropertyScopeGlobal; + pa.mElement = kAudioObjectPropertyElementMaster; + pa.mSelector = kAudioHardwarePropertyDefaultOutputDevice; + + // get the default output device + propertySize = sizeof(deviceID); + + OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0, NULL, &propertySize, &deviceID); + if (err != noErr) { + fprintf(stderr, "Failed to get default deviceid\n"); + } + return deviceID; +} + +UInt32 isMuted(AudioDeviceID deviceID) { + UInt32 propertySize; + + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyMute; + pa.mScope = kAudioObjectPropertyScopeOutput; + pa.mElement = kAudioObjectPropertyElementMaster; + + UInt32 isMuted = 0; + propertySize = sizeof(isMuted); + + OSStatus err = AudioObjectGetPropertyData(deviceID, &pa, 0, NULL, &propertySize, &isMuted); + if (err != noErr) { + fprintf(stderr, "Failed to get mute data\n"); + } + + return isMuted; +} + +void getDeviceVolume(AudioDeviceID deviceID, float *volume) { + UInt32 propertySize = sizeof(float); + + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioHardwareServiceDeviceProperty_VirtualMasterVolume; + pa.mScope = kAudioDevicePropertyScopeOutput; + pa.mElement = kAudioObjectPropertyElementMaster; + + OSStatus err = AudioObjectGetPropertyData( + deviceID, + &pa, + 0, + NULL, + &propertySize, + volume); + if (err != noErr) { + fprintf(stderr, "Failed to get volume data\n"); + return; + } +} + +int main() { + AudioDeviceID deviceID = getCurrentlySelectedDeviceID(); + UInt32 mute = isMuted(deviceID); + float volume = 100.0; + getDeviceVolume(deviceID, &volume); + printf("%d,%d\n", (int)round(volume*100.0), mute); + return 0; +} + diff --git a/hie.yaml b/hie.yaml index e048147..0812e0d 100644 --- a/hie.yaml +++ b/hie.yaml @@ -1,8 +1,8 @@ cradle: cabal: - component: "exe:barbq2" + component: "exe:barbq" dependencies: - - barbq2.cabal + - barbq.cabal - shell.nix - default.nix