1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-07-15 01:24:29 +02:00

created a dedicated pseudo algorithm for the amixer sget and tried various of strings.

This commit is contained in:
Eden Refael
2024-11-28 00:41:14 +02:00
parent ca62b6a16d
commit 90498052e0

View File

@ -40,6 +40,7 @@ def _process(proc_data: List[Dict]) -> List[Dict]:
# entry[key] = jc.utils.convert_to_int(entry[key])
#
# return proc_data
pass
def parse(
@ -66,131 +67,157 @@ def parse(
# check if string
jc.utils.input_type_check(data)
raw_output = []
lines = list(filter(None, data.splitlines())) # lines=cleandata
data = {}
# Strip and check for the first line to extract the control name directly
# split the output lines \r\n or \n
# raw_output = []
# lines: list = list(filter(None, data.splitlines())) # lines=cleandata
mapping = {}
lines = data.splitlines()
first_line = lines[0].strip()
# Extract the control name from the first line
if first_line.startswith("Simple mixer control"):
# Extract the control name, removing the single quotes
control_name = first_line.split("'")[1] # Extracts the part inside the single quotes
control_name = first_line.split("'")[1]
else:
raise ValueError("Invalid amixer output format: missing control name.")
# map the control name
mapping["control_name"] = control_name
# Add control name to the parsed data as a key
data["control_name"] = control_name
# Parse the rest of the output
# Process subsequent lines for capabilities, channels, limits, and channel-specific mapping.
# gets the lines from the next line - because we already took care the first line.
for line in lines[1:]:
# strip the line (maybe there are white spaces in the begin&end)
line = line.strip()
if line.startswith("Capabilities:"):
data["capabilities"] = line.split(":")[1].strip().split()
mapping["capabilities"] = line.split(":")[1].strip().split()
elif line.startswith("Playback channels:"):
data["playback_channels"] = line.split(":")[1].strip().split(" - ")
mapping["playback_channels"] = line.split(":")[1].strip().split(" - ")
elif line.startswith("Limits:"):
limits = line.split(":")[1].strip().split(" - ")
data["limits"] = {
"playback_min": int(limits[0].split()[1]),
"playback_max": int(limits[1])
mapping["limits"] = {
"playback_min": limits[0].split()[1],
"playback_max": limits[1]
}
elif line.startswith("Mono:") or line.startswith("Front Left:") or line.startswith("Front Right:"):
# Identifying whether it's Mono, Front Left, or Front Right
# Identify the channel name and parse its information
channel_name = line.split(":")[0].strip().lower().replace(" ", "_")
channel_info = line.split(":")[1].strip()
# Example: "Playback 255 [100%] [0.00dB] [on]"
channel_data = channel_info.split(" ")
playback_value = int(channel_data[0])
percentage = channel_data[1][1:-1] # Extract percentage e.g. "100%"
db_value = channel_data[2][1:-3] # Extract dB value e.g. "0.00dB"
status = channel_data[3][1:-1] # Extract status "on" or "off"
if channel_data[0] == "":
continue
playback_value = channel_data[1]
percentage = channel_data[2].strip("[]") # Extract percentage e.g., "100%"
db_value = channel_data[3].strip("[]") # Extract dB value e.g., "0.00dB"
status = channel_data[4].strip("[]") # Extract status e.g., "on" or "off"
# Storing channel data in the dict
data[channel_name] = {
# Store channel mapping in the dictionary
mapping[channel_name] = {
"playback_value": playback_value,
"percentage": percentage,
"dB": db_value,
"status": status
}
return data
return mapping
# if jc.utils.has_data(data):
"""
Input Explained/Rules/Pseudo Algorithm:
1. There will always be the first line which tells the user about the control name.
2. There will always be the Capabilities which include many of capabilities - It will be listed and separated by `" "`.
3. After that we'll need to distinct between the Channel - Could be many of channels - It will be listed and separated
by `" "`.
3a. Capture channels - List of channels
3b. Playback channels - List of channels
4. Limits - We'll always have the minimum limit and the maximum limit.
# remove final Entries row if -v was used
# if cleandata[-1].startswith('Entries:'):
# cleandata.pop(-1)
#
# # detect if freebsd/osx style was used
# if cleandata[0][-1] == ']':
# for line in cleandata:
# splitline = line.split()
# output_line: Dict[str, Any] = {
# 'name': splitline[0],
# 'address': splitline[1].lstrip('(').rstrip(')'),
# 'hwtype': splitline[-1].lstrip('[').rstrip(']'),
# 'hwaddress': splitline[3],
# 'iface': splitline[5]
# }
#
# if 'permanent' in splitline:
# output_line['permanent'] = True
# else:
# output_line['permanent'] = False
#
# if 'expires' in splitline:
# output_line['expires'] = splitline[-3]
#
# raw_output.append(output_line)
#
# # detect if linux style was used
# elif cleandata[0].startswith('Address'):
#
# # fix header row to change Flags Mask to flags_mask
# cleandata[0] = cleandata[0].replace('Flags Mask', 'flags_mask')
# cleandata[0] = cleandata[0].lower()
#
# raw_output = jc.parsers.universal.simple_table_parse(cleandata)
#
# # otherwise, try bsd style
# else:
# for line in cleandata:
# splitline = line.split()
#
# # Ignore AIX bucket information
# if 'bucket:' in splitline[0]:
# continue
# elif 'There' in splitline[0] and 'are' in splitline[1]:
# continue
#
# # AIX uses (incomplete)
# elif '<incomplete>' not in splitline and '(incomplete)' not in splitline:
# output_line = {
# 'name': splitline[0],
# 'address': splitline[1].lstrip('(').rstrip(')'),
# 'hwtype': splitline[4].lstrip('[').rstrip(']'),
# 'hwaddress': splitline[3],
# }
# # Handle permanence and ignore interface in AIX
# if 'permanent' in splitline:
# output_line['permanent'] = True
# elif 'in' not in splitline[6]: # AIX doesn't show interface
# output_line['iface'] = splitline[6]
#
# else:
# output_line = {
# 'name': splitline[0],
# 'address': splitline[1].lstrip('(').rstrip(')'),
# 'hwtype': None,
# 'hwaddress': None,
# }
# # AIX doesn't show interface
# if len(splitline) >= 5:
# output_line['iface'] = splitline[5]
#
# raw_output.append(output_line)
#
# return raw_output if raw else _process(raw_output)
Input Example:
1.user@kazuar-endpoint:~$ amixer sget Capture
Simple mixer control 'Capture',0
Capabilities: cvolume cswitch
Capture channels: Front Left - Front Right
Limits: Capture 0 - 63
Front Left: Capture 63 [100%] [30.00dB] [on]
Front Right: Capture 63 [100%] [30.00dB] [on]
2.user@kazuar-endpoint:~$ amixer sget Master
Simple mixer control 'Master',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 87
Mono: Playback 87 [100%] [0.00dB] [on]
3.user@kazuar-endpoint:~$ amixer sget Speaker
Simple mixer control 'Speaker',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 87
Mono:
Front Left: Playback 87 [100%] [0.00dB] [on]
Front Right: Playback 87 [100%] [0.00dB] [on]
4.user@kazuar-endpoint:~$ amixer sget Headphone
Simple mixer control 'Headphone',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 87
Mono:
Front Left: Playback 0 [0%] [-65.25dB] [off]
Front Right: Playback 0 [0%] [-65.25dB] [off]
"""
if __name__ == '__main__':
data_sget_master = """Simple mixer control 'Master',0
Capabilities: pvolume pvolume-joined pswitch pswitch-joined
Playback channels: Mono
Limits: Playback 0 - 87
Mono: Playback 87 [100%] [0.00dB] [on]"""
data_sget_capture = """Simple mixer control 'Capture',0
Capabilities: cvolume cswitch
Capture channels: Front Left - Front Right
Limits: Capture 0 - 63
Front Left: Capture 63 [100%] [30.00dB] [on]
Front Right: Capture 63 [100%] [30.00dB] [on]"""
data_sget_speakers = """Simple mixer control 'Speaker',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 87
Mono:
Front Left: Playback 87 [100%] [0.00dB] [on]
Front Right: Playback 87 [100%] [0.00dB] [on]"""
data_sget_headphones = """Simple mixer control 'Headphone',0
Capabilities: pvolume pswitch
Playback channels: Front Left - Front Right
Limits: Playback 0 - 87
Mono:
Front Left: Playback 0 [0%] [-65.25dB] [off]
Front Right: Playback 0 [0%] [-65.25dB] [off]"""
output_data_sget_master = parse(data=data_sget_master)
output_data_sget_speakers = parse(data=data_sget_speakers)
output_data_sget_headphones = parse(data=data_sget_headphones)
output_data_sget_capture = parse(data=data_sget_capture)
di = {'master': output_data_sget_master,
'speakers': output_data_sget_speakers,
'headphones': output_data_sget_headphones,
'capture': output_data_sget_capture}
for key, val in di.items():
print(f"[info] for key: {key}")
print(f"[info] the output is: {val}")