Code Monkey home page Code Monkey logo

sbz-switch's Introduction

sbz-switch

Utility for switching Sound Blaster outputs on Windows

Crates.io License Build Status Docs.rs

The Sound Blaster drivers, at least for the Sound Blaster Z, expose the speaker and headphone outputs as a single audio device to Windows, meaning the normal Windows methods of switching the sound output device will not work. Creative provides a graphical utility for this, but does it does not support hotkeys or anything like that, and it does not maintain a separate volume level for headphones vs speakers.

This is a simple utility that does the following:

  1. Mute the sound output.

  2. Change the Sound Blaster configuration.

  3. Optionally adjust the volume.

  4. Unmute.

It's designed to be easily triggered by a hotkey or something.

This may have bugs. Use at your own risk, especially if you have configured your headphones/speakers in a way that they could be damaged by maximum volume sound output during the switch.

Usage

USAGE:
    sbz-switch.exe [SUBCOMMAND]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    apply           Applies a saved configuration
    dump            Prints out the current configuration
    help            Prints this message or the help of the given subcommand(s)
    list-devices    Prints out the names and IDs of available devices
    set             Sets specific parameters
    watch           Watches for events

List Devices

Find devices to control

USAGE:
    sbz-switch.exe list-devices

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -f <FORMAT>        Select the output format [default: toml]  [possible values: toml, json, yaml]

If the Sound Blaster is not the default audio output, execute list-devices to get the device ID.

[[]]
id = '{0.0.0.00000000}.{cba07706-3492-4789-bb31-0717e228bd14}'
interface = 'Sound Blaster Z'
description = 'Speakers'

[[]]
id = '{0.0.0.00000000}.{baeaa072-e026-44e1-942e-c466170d9d6f}'
interface = 'Steam Streaming Microphone'
description = 'Speakers'

[[]]
id = '{0.0.0.00000000}.{57e7b4bc-c860-4987-aed3-3ee8dd3617b9}'
interface = 'Steam Streaming Speakers'
description = 'Speakers'

[[]]
id = '{0.0.0.00000000}.{128e193d-e35f-40dd-b414-16105e5ec32d}'
interface = '2- USB Audio Device'
description = 'Speakers'

Pass the device ID to other commands: dump -d "{0.0.0.00000000}.{cba07706-3492-4789-bb31-0717e228bd14}".

Set

Set a small number of parameters

USAGE:
    sbz-switch.exe set [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -b <FEATURE> <PARAMETER> <true|false>        Sets a boolean value
    -d, --device <DEVICE_ID>                     Specify the device to act on (get id from list-devices)
    -f <FEATURE> <PARAMETER> <VALUE>             Sets a floating-point value
    -i <FEATURE> <PARAMETER> <VALUE>             Sets an integer value
    -m <true|false>                              Temporarily mutes while changing parameters [default: true]
    -v, --volume <VOLUME>                        Sets the volume, in percent

Switch to speakers at 60% volume with effects turned on:

sbz-switch set -i "Device Control" SelectOutput 1 -b EfxMasterControl "THXEfx Master OnOff" true -v 60

Switch to headphones at 10% volume with effects turned off:

sbz-switch set -i "Device Control" SelectOutput 0 -b EfxMasterControl "THXEfx Master OnOff" false -v 10

Dump

See or save the current parameters

USAGE:
    sbz-switch.exe dump [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -d, --device <DEVICE_ID>    Specify the device to act on (get id from list-devices)
    -f <FORMAT>                 Select the output format [default: toml]  [possible values: toml, json, yaml]
    -o, --output <FILE>         Saves the current settings to a file

See the current settings:

sbz-switch dump

Save the current settings to headphones.toml:

sbz-switch dump -o headphones.toml

Note: saving parameters this way will include many parameters, some of which may not actually be settable when used with the apply command. It is recommended to remove unnecessary settings to speed up the transition and avoid errors.

Apply

Set many parameters at once

USAGE:
    sbz-switch.exe apply [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -d, --device <DEVICE_ID>    Specify the device to act on (get id from list-devices)
    -i <FILE>                   Reads the settings from a file instead of stdin
    -f <FORMAT>                 Select the input format [default: toml]  [possible values: toml, json, yaml]
    -m <true|false>             Temporarily mutes while changing parameters [default: true]

Apply the previously saved headphones.toml file:

sbz-switch apply -i headphones.toml

Omitting the -i parameter will cause sbz-switch to read settings from stdin.

Partial dumps are acceptable (and recommended) input for the apply command, in which case the other parameters are left as is. This means it's possible to use a small toml files like these:

headphones.toml

[creative."Device Control"]
SelectOutput = 0

[creative.EfxMasterControl]
"THXEfx Master OnOff" = false

[endpoint]
volume = 0.1

speakers.toml

[creative."Device Control"]
SelectOutput = 1

[creative.EfxMasterControl]
"THXEfx Master OnOff" = true

[endpoint]
volume = 0.6

Watch

Watch for events such as parameter changes

USAGE:
    sbz-switch.exe watch [OPTIONS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -d, --device <DEVICE_ID>    Specify the device to act on (get id from list-devices)

Known issues

There may be a pop during the switch, or applications outputting audio may get confused. This seems to be a problem on Creative's end and happens for me even when switching using the official software.

Some parameters are only valid if another parameter has been set or when using certain hardware, e.g. 7.1 surround sound speaker configuration. Unfortunately, these parameters will be included in a full parameter dump and may lead to errors when reapplying the settings later. It should be generally safe to ignore such errors, but they can be avoided by removing the offending settings from the dump file.

Order matters when setting parameters. This program make no attempt to order the parameters correctly itself. Additionally, toml files are read using toml 0.4 which does not maintain the order of parameters.

sbz-switch's People

Contributors

mdonoughe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sbz-switch's Issues

Minor Feature Request: Hide terminal/console window

Just a minor feature request.
When using sbz-switch with a shortcut it opens a terminal/console window for a short time which can be annoying at times.
Could there be just an additional -hide switch be added?

sbz-switch watch: Unexpected error

Sound Blaster Command 3.5.8.0
Driver version 6.0.105.64
cmd as administrator, sbz-switch 4.1.0

sbz-switch.exe watch

CRIT Unexpected error: SoundCore not supported, module: sbz_switch:172

sbz-switch.exe list-devices
id = '{0.0.0.00000000}.{88db5ddc-9d0b-4d9d-9906-ba14f2837b90}'
interface = 'Sound BlasterX AE-5'

Autohotkey Example

When I came across this repo, I wanted to make some keyboard macro to make use of the executable. Perhaps providing an example would be useful in the readme or wiki?

I currently have an autohotkey switcher example available:

#SingleInstance Ignore

+NumpadSub::
    {
        RunWait "sbz-switch.exe dump -o _dump.toml",,"Min"
        Dump := FileRead("_dump.toml")
        RegExMatch(Dump, "SelectOutput = (\d)", &SubPat)

        Output := "0"
        IF (SubPat[1] = "0") {
            Output := "1"
        }
        ELSE {
            Output := "0"
        }

        RunWait Format("sbz-switch.exe set -i `"Device Control`" SelectOutput {1}", Output),,"Min"

        RunWait "taskkill /f /im `"NVIDIA Broadcast UI.exe`"",,"Min"
        RunWait "taskkill /f /im `"NVIDIA Broadcast.exe`"",,"Min"
        Run "C:\Program Files\NVIDIA Corporation\NVIDIA Broadcast\NVIDIA Broadcast UI.exe",,"Min"
    }

This will switch audio and restart NVIDIA broadcast (which seems to die when I switch sometimes)

Unexpected HRESULT: 80004005

Running sbz-switch dump crashes, with:

CRIT Unexpected error: Unexpected HRESULT: 80004005, module: sbz_switch:172

80004005 being "E_FAIL": "Unspecified error." (very cool)

This is with a Sound Blaster X7 running as the primary device, but calling dump with the id does the same.
I am running this on Windows 11.

Happy to provide any additional information/run debug builds, would love to have this app work.

Full debug run log:

Spoiler
❯ cargo run -- list-devices
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s
     Running `target\i686-pc-windows-msvc\debug\sbz-switch.exe list-devices`
Sep 17 17:18:53.092 DEBG Querying endpoint {0.0.0.00000000}.{01862bd4-f4f2-4e72-b547-64d10ad654af}..., module: sbz_switch:94
Sep 17 17:18:53.093[[]]
id = '{0.0.0.00000000}.{01862bd4-f4f2-4e72-b547-64d10ad654af}'
interface = 'AMD High Definition Audio Device'
description = '6 - LG ULTRAGEAR'

[[]]
id = '{0.0.0.00000000}.{af46a412-f9eb-4b94-bd89-ce5196aef924}'
interface = 'Sound Blaster X7'
description = 'Speakers'
 DEBG Querying endpoint {0.0.0.00000000}.{af46a412-f9eb-4b94-bd89-ce5196aef924}..., module: sbz_switch:94
Sep 17 17:18:53.094 DEBG Completed successfully, module: sbz_switch:168
❯ cargo run -- dump
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s
     Running `target\i686-pc-windows-msvc\debug\sbz-switch.exe dump`
Sep 17 17:19:41.964 DEBG Getting volume..., module: sbz_switch::media:229
Sep 17 17:19:41.966 DEBG volume = 0.1499588, module: sbz_switch::media:236
Sep 17 17:19:41.966 DEBG Found device {0.0.0.00000000}.{af46a412-f9eb-4b94-bd89-ce5196aef924}, module: sbz_switch:129
Sep 17 17:19:41.968 DEBG Found clsid {495E4C24-85ED-4F19-885E-C2D01D7EA26C}, module: sbz_switch:131
Sep 17 17:19:42.184 DEBG 01000001 Malcolm Device Control, module: sbz_switch:151
Sep 17 17:19:42.185 DEBG   14 EnumMultiplexOutputs, module: sbz_switch:156
Sep 17 17:19:42.186 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.186 DEBG     size:       8, module: sbz_switch:159
Sep 17 17:19:42.186 DEBG   15 MultiplexOutput, module: sbz_switch:156
Sep 17 17:19:42.187 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.189 DEBG     minimum:    U32(0), module: sbz_switch:176
Sep 17 17:19:42.190 DEBG     maximum:    U32(0), module: sbz_switch:177
Sep 17 17:19:42.190 DEBG     step:       U32(0), module: sbz_switch:178
Sep 17 17:19:42.191 DEBG     value:      U32(1), module: sbz_switch:179
Sep 17 17:19:42.191 DEBG   16 HeadphoneLoadSelect, module: sbz_switch:156
Sep 17 17:19:42.192 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.195 DEBG     minimum:    U32(0), module: sbz_switch:176
Sep 17 17:19:42.195 DEBG     maximum:    U32(0), module: sbz_switch:177
Sep 17 17:19:42.196 DEBG     step:       U32(0), module: sbz_switch:178
Sep 17 17:19:42.196 DEBG     value:      U32(0), module: sbz_switch:179
Sep 17 17:19:42.197 DEBG   22 AutoSleepMode, module: sbz_switch:156
Sep 17 17:19:42.197 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.200 DEBG     value:      Bool(false), module: sbz_switch:166
Sep 17 17:19:42.200 DEBG 01000002 Processing Control, module: sbz_switch:151
Sep 17 17:19:42.207 DEBG   0 SpeakerConfig, module: sbz_switch:156
Sep 17 17:19:42.207 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.208 DEBG     minimum:    U32(0), module: sbz_switch:176
Sep 17 17:19:42.208 DEBG     maximum:    U32(0), module: sbz_switch:177
Sep 17 17:19:42.209 DEBG     step:       U32(0), module: sbz_switch:178
Sep 17 17:19:42.209 DEBG     value:      U32(12291), module: sbz_switch:179
Sep 17 17:19:42.210 DEBG   1 PhysicalSpeakerConfig, module: sbz_switch:156
Sep 17 17:19:42.210 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.211 DEBG     minimum:    U32(0), module: sbz_switch:176
Sep 17 17:19:42.212 DEBG     maximum:    U32(0), module: sbz_switch:177
Sep 17 17:19:42.212 DEBG     step:       U32(0), module: sbz_switch:178
Sep 17 17:19:42.213 DEBG     value:      U32(3), module: sbz_switch:179
Sep 17 17:19:42.213 DEBG   2 SizeSpeakerConfig, module: sbz_switch:156
Sep 17 17:19:42.214 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.236 DEBG     minimum:    U32(0), module: sbz_switch:176
Sep 17 17:19:42.237 DEBG     maximum:    U32(0), module: sbz_switch:177
Sep 17 17:19:42.237 DEBG     step:       U32(0), module: sbz_switch:178
Sep 17 17:19:42.238 DEBG     value:      U32(11), module: sbz_switch:179
Sep 17 17:19:42.238 DEBG   3 EnumSpeakerConfig, module: sbz_switch:156
Sep 17 17:19:42.239 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.239 DEBG     size:       8, module: sbz_switch:159
Sep 17 17:19:42.240 DEBG   7 DirectMode, module: sbz_switch:156
Sep 17 17:19:42.240 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.241 DEBG     minimum:    U32(0), module: sbz_switch:176
Sep 17 17:19:42.241 DEBG     maximum:    U32(0), module: sbz_switch:177
Sep 17 17:19:42.242 DEBG     step:       U32(0), module: sbz_switch:178
Sep 17 17:19:42.242 DEBG     value:      U32(1), module: sbz_switch:179
Sep 17 17:19:42.243 DEBG   9 SPDIFInPassThrough, module: sbz_switch:156
Sep 17 17:19:42.243 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.244 DEBG     minimum:    U32(0), module: sbz_switch:176
Sep 17 17:19:42.245 DEBG     maximum:    U32(0), module: sbz_switch:177
Sep 17 17:19:42.245 DEBG     step:       U32(0), module: sbz_switch:178
Sep 17 17:19:42.246 DEBG     value:      U32(0), module: sbz_switch:179
Sep 17 17:19:42.246 DEBG   11 HighPowerAmplifier, module: sbz_switch:156
Sep 17 17:19:42.247 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.247 DEBG     minimum:    U32(0), module: sbz_switch:176
Sep 17 17:19:42.248 DEBG     maximum:    U32(0), module: sbz_switch:177
Sep 17 17:19:42.248 DEBG     step:       U32(0), module: sbz_switch:178
Sep 17 17:19:42.249 DEBG     value:      U32(0), module: sbz_switch:179
Sep 17 17:19:42.249 DEBG   14 SpeakersModel, module: sbz_switch:156
Sep 17 17:19:42.250 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.250 DEBG     minimum:    U32(0), module: sbz_switch:176
Sep 17 17:19:42.251 DEBG     maximum:    U32(0), module: sbz_switch:177
Sep 17 17:19:42.251 DEBG     step:       U32(0), module: sbz_switch:178
Sep 17 17:19:42.252 DEBG     value:      U32(0), module: sbz_switch:179
Sep 17 17:19:42.252 DEBG   16 SpeakersPreset, module: sbz_switch:156
Sep 17 17:19:42.253 DEBG     attributes: 0, module: sbz_switch:157
Sep 17 17:19:42.253 CRIT Unexpected error: Unexpected HRESULT: 80004005, module: sbz_switch:172
error: process didn't exit successfully: `target\i686-pc-windows-msvc\debug\sbz-switch.exe dump` (exit code: 1)

Bug: Only works when soundcard is set as the default

When using sbz-switch with a virtual audio cable or in conjunction with other soundcards (multiple wdm output/playback devices) and not having the soundblaster set as the windows default it will throw an error:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: NotSupported', src\libcore\result.rs:906:4 note: Run with `RUST_BACKTRACE=1` for a backtrace. Jul 16 18:07:33.568 INFO Setting muted to true..., module: sbz_switch::media:163 Jul 16 18:07:33.570 INFO Setting muted to false..., module: sbz_switch::media:163

It seems that it doesn't try to find the right output (wdm playback device) and only uses the default, which in this case is a virtual audio cable.
Setting the soundcard (soundblaster) as the default will remedy this of course.

Requires update to the SoundCore CLSID to work with other cards

Hello Matthew,

First off, thank you for this. I love this. I found it randomly and use it for toggling my speakers/headphones. I have an SBZ and it works great. I recently posted this on the SoundBlaster sub and recommended it as an option for anyone looking for this functionality without having to do mouse/keyboard manipulation (with AHK or other). Someone there tried to use it with an AE-5 and could not get it to work (SoundCore not supported error). Turns out the SoundCore CLSID is tied to the driver so the AE-5 does not work...unless you change the SoundCore CLSID in the code (consts.rs). I went ahead and changed the CLSID and recompiled...and voila, it worked for the person in question.

My change:

DEFINE_PROPERTYKEY! {PKEY_SOUNDCORECTL_CLSID,
0xd8570091, 0xaf3f, 0x4615,0x9f, 0xaa, 0xa2, 0x48, 0x45, 0xd1, 0x09, 0x36,
0}

Not sure if you want to expand the code to account for multiple cards but it would be nice. Alternatively, you could even set a parameter to override the CLSID (if there are other CLSIDs for other Creative cards that utilize SoundCore) so then you don't have to account for each CLSID.

Thanks again! I appreciate your work on this.

Richard

feature request: encoder switch

Hi there, firstly -- thank you for making this utility, it's an absolute godsend!

I was wondering if it would be possible/feasible to add as an update at some point the ability to toggle the encoder option. What I've noticed on my rig is that certain applications (namely overlays; such as the snipping tool in windows, or steam's overlay -- as well as a few gaming titles ) cause sound issues: Crackling/distortions until the output is toggled between speakers and headphones, and additionally changing/toggling the encoder option between Dolby and DTS.

Currently the listen option does not pick up on this change, and I'm unsure if the encoder change is accessible via the same methods as the output state,. but it would be an incredibly helpful ability :)

Cheers!

sbz-switch dump: Unexpected HRESULT

sbz-switch dump
gives me
Aug 31 11:27:17.540 CRIT Unexpected error: Win32Error: Unexpected HRESULT: 80040154, module: sbz_switch:172
I use cmd as administrator. sbz-switch 4.1.0

sbz-switch.exe list-devices
id = '{0.0.0.00000000}.{348a9b84-d557-4951-ad6b-06f946c1d8c8}'
interface = 'Sound BlasterX G6'
sbz-switch.exe dump -d "{0.0.0.00000000}.{348a9b84-d557-4951-ad6b-06f946c1d8c8}"
Aug 31 11:29:43.942 CRIT Unexpected error: Win32Error: Unexpected HRESULT: 80040154, module: sbz_switch:172

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.