diff options
Diffstat (limited to 'ctbtw.py')
| -rwxr-xr-x | ctbtw.py | 33 |
1 files changed, 23 insertions, 10 deletions
@@ -497,20 +497,25 @@ class SetFeatureReq(BTReq): return "SetFeatureReq(feature=%s,value=%r)"%(self.feature,self.value) class PairedDevice(NamedTuple): + """Tuple representing a paired bluetooth receiver.""" name: str addr: BTAddr class CTBTWDevice: + """Main class representing a transmitter device.""" # List of messages that can be received MSG_TYPES = [AckMsg, GetNumPairedDevicesMsg, GetPairedDeviceDetailsMsg, GetInquiryDataMsg, GetStateMsg, GetFeatureMsg] + # HID report number used to both receive/send messages REPORT_ID = 3 # Size of this report (hardcoded...) REPORT_SIZE = 64 + # This is the usage page for the above report_id, at least on BT-W6. Some platforms need this to be correct. + USAGE_PAGE = 0xFF01 # Vendor ID to search for - CT_VENDOR_ID = 0x041e + VENDOR_ID = 0x041e # Product IDs to search for. Hardcoded to [BT-W4, BT-W5, BT-W6] - CT_PRODUCT_IDS = [0x312B, 0x3130, 0x3132] + PRODUCT_IDS = [0x312B, 0x3130, 0x3132] def __init__(self, devpath, verbose=False): self._hid = hid.device() @@ -585,8 +590,10 @@ def codec_name(codec): return codec.name def find_device(): - for device in hid.enumerate(vendor_id=CTBTWDevice.CT_VENDOR_ID): - if device['vendor_id'] == CTBTWDevice.CT_VENDOR_ID and device['product_id'] in CTBTWDevice.CT_PRODUCT_IDS: + for device in hid.enumerate(vendor_id=CTBTWDevice.VENDOR_ID): + if (device['vendor_id'] == CTBTWDevice.VENDOR_ID and + device['product_id'] in CTBTWDevice.PRODUCT_IDS and + device['usage_page'] == CTBTWDevice.USAGE_PAGE): return device return None @@ -643,9 +650,8 @@ if __name__ == '__main__': parser = ArgumentParser(prog='ctbtw', description="Control CT BT-W* Bluetooth Audio Trasmitter devices", epilog="With no arguments, show current device state") parser.add_argument('--verbose', '-v', action='store_true', help="print protocol traces") actions = parser.add_mutually_exclusive_group() - actions.add_argument('--aptxll', '-l', action='store_true', help="for aptX, prefer low-latency mode") - actions.add_argument('--aptxhq', '-q', action='store_true', help="for aptX, prefer high-quality mode (also enables aptX lossless)") - actions.add_argument('--devices', '-s', action='store_true', help="list currently paired devices") + actions.add_argument('--aptx', '-x', action='store', choices=["l", "q"], help="prefer (L)atency or (Q)uality for aptX adaptative") + actions.add_argument('--devices', '-l', action='store_true', help="list currently paired devices") actions.add_argument('--connect', '-c', metavar="DEV", action='store', help="connect to (already paired) device with given name/address") actions.add_argument('--disconnect', '-d', metavar="D", action='store', nargs='?', const='*', help="disconnect from device with given name/address, or current device if no %(metavar)s") actions.add_argument('--pair', '-p', nargs='?', metavar="ADDR", const="*", action='store', help='pair with specific bluetooth address, or any device if no %(metavar)s specified') @@ -658,6 +664,13 @@ if __name__ == '__main__': verbose = args.verbose use_color = os.getenv("NO_COLOR", "") == "" and os.getenv("TERM") != "dumb" and sys.stdout.isatty() + if use_color: + try: + from colorama import just_fix_windows_console + just_fix_windows_console() + except Exception: + pass + devinfo = find_device() if not devinfo: print("Could not find device with valid vendor/product IDs") @@ -669,9 +682,9 @@ if __name__ == '__main__': if verbose: print("Opened device '%s'" % devinfo['product_string']) - if args.aptxll or args.aptxhq: - codec = BTCodec.aptXAdaptiveHighQuality if args.aptxhq else BTCodec.aptXAdaptiveLowLatency - print("Switching preferred aptX codec to %s" % codec.name) + if args.aptx: + codec = BTCodec.aptXAdaptiveHighQuality if args.aptx.startswith("q") else BTCodec.aptXAdaptiveLowLatency + print("Switching aptX adaptative preference to %s" % codec.name) msg = SetFeatureReq(BTFeatureSet.PreferredAptXCodecVariant, codec) dev.send_msg(msg) read_and_explain_msgs(dev, timeout_ms=1000) # Use larger timeout to give time to print final codec used, if any |
