Merge ~stanley31/checkbox-support:0909_modify_audio_settings into checkbox-support:master

Proposed by StanleyHuang
Status: Merged
Approved by: Jonathan Cave
Approved revision: 319abca420c49214796fc7f4dbd5c658afa5c7b7
Merged at revision: b136d7c36518807fc15cfa8d30c98b84f9ccdfe2
Proposed branch: ~stanley31/checkbox-support:0909_modify_audio_settings
Merge into: checkbox-support:master
Diff against target: 313 lines (+87/-57)
2 files modified
checkbox_support/scripts/audio_settings.py (+82/-55)
checkbox_support/scripts/tests/test_audio_settings.py (+5/-2)
Reviewer Review Type Date Requested Status
Jonathan Cave (community) Approve
Devices Certification Bot Needs Fixing
Maciej Kisielewski Approve
Review via email: mp+408339@code.launchpad.net

Commit message

A fixed for lp:1940391

Description of the change

I have validated the audio_settings script could parse the volume from mono/stereo audio interface.

Test this script on a system with input (mono) audio and output (stereo) audio.

detail audio information:
{'name': 'bluez_source.14_3F_A6_62_7C_02.headset_head_unit', 'muted': 'no', 'volumes': {'mono': 100}, 'max_volume': 100}
{'name': 'alsa_output.pci-0000_00_1f.3.analog-stereo', 'muted': 'no', 'volumes': {'front-left': 64, 'front-right': 40}, 'max_volume': 64}

I have ran the store_audio_settings function directly, please see following contents:
default_source: bluez_source.14_3F_A6_62_7C_02.headset_head_unit
source_muted: no
source_volume: 100%
default_sink: alsa_output.pci-0000_00_1f.3.analog-stereo
sink_muted: no
sink_volume: 64%

To post a comment you must log in.
Revision history for this message
Maciej Kisielewski (kissiel) wrote :

I found one problem with the regex string, see below.

Nitpicking: There are at least three ways that string interpolation is used in this code (overall audio_settings.py, not just your patch):
+
.format
""%()

And I think it's pretty yucky. I'm not asking anyone to do a small revolution and fix all that, but I would prefer not to cultivate bad habits.

review: Needs Fixing
Revision history for this message
StanleyHuang (stanley31) wrote :

@Maciej,

May I have your suggestion for the way to format string?
option 1: use .format
option 2: use f"" string

If the script would only run under Python 3.6 up, I think the option 2 is a better solution due to it makes the string more readable.

Thanks.

Revision history for this message
StanleyHuang (stanley31) wrote :

I think the ".format" might be a option due to we need to replace string for some pattern variables.

Revision history for this message
StanleyHuang (stanley31) wrote :

Two commits for this MR.

first one is to change the way to parse audio volumes.
second one is to unified the format string method.

And it has been tested on my laptop with stereo and mono audio devices.
the stereo logs:
>>> print(get_audio_settings("source"))
{'name': 'alsa_input.pci-0000_00_1f.3.analog-stereo', 'muted': 'no', 'volumes': {'front-left': 26, 'front-right': 26}, 'max_volume': 26}
>>> print(get_audio_settings("sink"))
{'name': 'alsa_output.pci-0000_00_1f.3.hdmi-stereo-extra1', 'muted': 'no', 'volumes': {'front-left': 88, 'front-right': 88}, 'max_volume': 88}

the mono logs:
>>> print(get_audio_settings("source"))
{'name': 'bluez_source.74_5C_4B_D4_EB_94.headset_head_unit', 'muted': 'no', 'volumes': {'mono': 59}, 'max_volume': 59}
>>> print(get_audio_settings("sink"))
{'name': 'bluez_sink.74_5C_4B_D4_EB_94.headset_head_unit', 'muted': 'no', 'volumes': {'mono': 69}, 'max_volume': 69}

Revision history for this message
Maciej Kisielewski (kissiel) wrote :

Great stuff! Thank you for all the patches. As for which string interpolation option, I think .format() is great. One thing to note, though, is for logging calls the %s should be used, as this prevents formatting from happening unless the logging call is on the right level (it's evaluated lazily). You can read more here: https://stackoverflow.com/questions/34619790/pylint-message-logging-format-interpolation

I'm +1 on landing this.

review: Approve
Revision history for this message
Devices Certification Bot (ce-certification-qa) wrote :

The merge was fine but running tests failed.

"10.38.105.54"
"10.38.105.108"
"10.38.105.197"
[xenial] [14:06:01] starting container
Device project added to xenial-testing
"10.38.105.54"
[xenial] [14:07:16] provisioning container
[xenial] [14:09:26] Starting tests...
[xenial] Found a test script: ./requirements/container-tests-checkbox-support
[bionic] [14:09:52] starting container
Device project added to bionic-testing
[xenial] [14:10:03] container-tests-checkbox-support: FAIL
[xenial] output:
[xenial] [14:10:03] Fixing file permissions in source directory
[xenial] [14:10:04] Destroying container
[focal] [14:10:28] starting container
Device project added to focal-testing
"10.38.105.115"
[bionic] [14:10:41] provisioning container
"10.38.105.137"
[focal] [14:10:59] provisioning container
[bionic] [14:11:09] Starting tests...
[bionic] Found a test script: ./requirements/container-tests-checkbox-support
[focal] [14:11:29] Starting tests...
[focal] Found a test script: ./requirements/container-tests-checkbox-support
[bionic] [14:11:48] container-tests-checkbox-support: FAIL
[bionic] output:
[bionic] [14:11:48] Fixing file permissions in source directory
[bionic] [14:11:48] Destroying container
[focal] [14:12:03] container-tests-checkbox-support: FAIL
[focal] output:
[focal] [14:12:03] Fixing file permissions in source directory
[focal] [14:12:03] Destroying container

review: Needs Fixing
Revision history for this message
Devices Certification Bot (ce-certification-qa) wrote :

The merge was fine but running tests failed.

"10.38.105.54"
"10.38.105.108"
"10.38.105.197"
[xenial] [14:40:43] starting container
[bionic] [14:40:45] starting container
[focal] [14:40:52] starting container
Device project added to xenial-testing
Device project added to bionic-testing
"10.38.105.54"
[xenial] [14:41:02] provisioning container
Device project added to focal-testing
"10.38.105.141"
[bionic] [14:41:06] provisioning container
"10.38.105.142"
[focal] [14:41:13] provisioning container
[bionic] [14:41:44] Starting tests...
[bionic] Found a test script: ./requirements/container-tests-checkbox-support
[focal] [14:41:51] Starting tests...
[focal] Found a test script: ./requirements/container-tests-checkbox-support
[bionic] [14:42:17] container-tests-checkbox-support: FAIL
[bionic] output:
[bionic] [14:42:17] Fixing file permissions in source directory
[bionic] [14:42:18] Destroying container
[xenial] [14:42:18] Starting tests...
[xenial] Found a test script: ./requirements/container-tests-checkbox-support
[focal] [14:42:21] container-tests-checkbox-support: FAIL
[focal] output:
[focal] [14:42:21] Fixing file permissions in source directory
[focal] [14:42:22] Destroying container
[xenial] [14:42:50] container-tests-checkbox-support: FAIL
[xenial] output:
[xenial] [14:42:50] Fixing file permissions in source directory
[xenial] [14:42:50] Destroying container

review: Needs Fixing
Revision history for this message
Devices Certification Bot (ce-certification-qa) wrote :

The merge was fine but running tests failed.

"10.38.105.54"
"10.38.105.108"
"10.38.105.197"
[xenial] [17:35:38] starting container
[focal] [17:35:44] starting container
Device project added to xenial-testing
Device project added to focal-testing
"10.38.105.54"
[xenial] [17:35:56] provisioning container
"10.38.105.151"
[focal] [17:36:06] provisioning container
[bionic] [17:36:07] starting container
Device project added to bionic-testing
"10.38.105.154"
[bionic] [17:36:26] provisioning container
[focal] [17:36:38] Starting tests...
[focal] Found a test script: ./requirements/container-tests-checkbox-support
[bionic] [17:36:55] Starting tests...
[bionic] Found a test script: ./requirements/container-tests-checkbox-support
[focal] [17:37:08] container-tests-checkbox-support: FAIL
[focal] output: https://paste.ubuntu.com/p/8Mf4pRdRnj/
[focal] [17:37:11] Fixing file permissions in source directory
[focal] [17:37:11] Destroying container
[xenial] [17:37:20] Starting tests...
[xenial] Found a test script: ./requirements/container-tests-checkbox-support
[bionic] [17:37:28] container-tests-checkbox-support: FAIL
[bionic] output: https://paste.ubuntu.com/p/xDMQrgJyJN/
[bionic] [17:37:30] Fixing file permissions in source directory
[bionic] [17:37:31] Destroying container
[xenial] [17:37:52] container-tests-checkbox-support: FAIL
[xenial] output: https://paste.ubuntu.com/p/Sy353V7jcJ/
[xenial] [17:37:54] Fixing file permissions in source directory
[xenial] [17:37:54] Destroying container

review: Needs Fixing
Revision history for this message
Jonathan Cave (jocave) wrote :

@Stanley the unit tests need updating for this script. See the pastebins above for failure

review: Needs Fixing
Revision history for this message
StanleyHuang (stanley31) wrote :

attached test results of the unit test:

test_volume_regex_trusty (test_audio_settings.RegexTest)
Testing pactl 4.0 output ... ok
test_volume_regex_xenial (test_audio_settings.RegexTest)
Testing pactl 8.0 output ... ok
test_desktop_bionic_x13 (test_audio_settings.SetProfileTest)
Bionic system with a Intel UHD Graphics chipset, it's DMIC system. ... ok
test_desktop_precise_radeon_available (test_audio_settings.SetProfileTest)
Home-made system running Precise with a Radeon card. ... ok
test_desktop_precise_radeon_not_available (test_audio_settings.SetProfileTest)
Home-made system running Precise with a Radeon card. ... ok
test_desktop_precise_xps1340 (test_audio_settings.SetProfileTest)
Precise system with a Nvidia chipset. ... ok
test_desktop_raring_t430s_available (test_audio_settings.SetProfileTest)
Raring system with a Mini-DisplayPort. ... ok
test_desktop_raring_t430s_not_available (test_audio_settings.SetProfileTest)
Raring system with a Mini-DisplayPort. ... ok

----------------------------------------------------------------------
Ran 8 tests in 7.784s

OK

Revision history for this message
Jonathan Cave (jocave) wrote :

Hmmm I'm wondering why they are passing for you because I'm seeing:

======================================================================
ERROR: test_volume_regex_trusty (checkbox_support.scripts.tests.test_audio_settings.RegexTest)
Testing pactl 4.0 output
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/ubuntu/host/checkbox-project/checkbox-support/checkbox_support/scripts/tests/test_audio_settings.py", line 179, in test_volume_regex_trusty
    volume_regex = re.compile(volume_pattern % "0", re.DOTALL)
TypeError: not all arguments converted during string formatting

======================================================================
ERROR: test_volume_regex_xenial (checkbox_support.scripts.tests.test_audio_settings.RegexTest)
Testing pactl 8.0 output
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/ubuntu/host/checkbox-project/checkbox-support/checkbox_support/scripts/tests/test_audio_settings.py", line 187, in test_volume_regex_xenial
    volume_regex = re.compile(volume_pattern % "front-left", re.DOTALL)
TypeError: not all arguments converted during string formatting

Revision history for this message
StanleyHuang (stanley31) wrote :

Interesting, I guess it related to the python version.
I am going to take a look how does the audio_settings scripts works in trusty and xenial (with default python environment.

> Hmmm I'm wondering why they are passing for you because I'm seeing:
>
> ======================================================================
> ERROR: test_volume_regex_trusty
> (checkbox_support.scripts.tests.test_audio_settings.RegexTest)
> Testing pactl 4.0 output
> ----------------------------------------------------------------------
> Traceback (most recent call last):
> File "/home/ubuntu/host/checkbox-project/checkbox-
> support/checkbox_support/scripts/tests/test_audio_settings.py", line 179, in
> test_volume_regex_trusty
> volume_regex = re.compile(volume_pattern % "0", re.DOTALL)
> TypeError: not all arguments converted during string formatting
>
> ======================================================================
> ERROR: test_volume_regex_xenial
> (checkbox_support.scripts.tests.test_audio_settings.RegexTest)
> Testing pactl 8.0 output
> ----------------------------------------------------------------------
> Traceback (most recent call last):
> File "/home/ubuntu/host/checkbox-project/checkbox-
> support/checkbox_support/scripts/tests/test_audio_settings.py", line 187, in
> test_volume_regex_xenial
> volume_regex = re.compile(volume_pattern % "front-left", re.DOTALL)
> TypeError: not all arguments converted during string formatting

Revision history for this message
StanleyHuang (stanley31) wrote :

I have modified the way to format string, and run the unittest on focal and impish.
@jocave, please give it a try on your test environment. Thanks.

Revision history for this message
Jonathan Cave (jocave) wrote :

Yep, this works for me now. Attempting to land...

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/checkbox_support/scripts/audio_settings.py b/checkbox_support/scripts/audio_settings.py
index 6c00743..2cf6a3f 100644
--- a/checkbox_support/scripts/audio_settings.py
+++ b/checkbox_support/scripts/audio_settings.py
@@ -36,13 +36,16 @@ from checkbox_support.snap_utils.system import in_classic_snap
36TYPES = ("source", "sink")36TYPES = ("source", "sink")
37DIRECTIONS = {"source": "input", "sink": "output"}37DIRECTIONS = {"source": "input", "sink": "output"}
3838
39# use %s string format to compatible with other python version
39default_pattern = "(?<=Default %s: ).*"40default_pattern = "(?<=Default %s: ).*"
40index_regex = re.compile("(?<=Sink Input #)[0-9]*")41index_regex = re.compile("(?<=Sink Input #)[0-9]*")
41muted_regex = re.compile("(?<=Mute: ).*")42muted_regex = re.compile("(?<=Mute: ).*")
42volume_regex = re.compile("Volume: (?:0|front-left):[\s\/0-9]*\s([0-9]*)")
43name_regex = re.compile("(?<=Name:).*")43name_regex = re.compile("(?<=Name:).*")
44channel_map_regex = re.compile("(?<=Channel Map: ).*")
4445
46# use %s string format to compatible with other python version
45entry_pattern = "Name: %s.*?(?=Properties)"47entry_pattern = "Name: %s.*?(?=Properties)"
48volume_pattern = r"Volume: .*(?:%s):[\w\/0-9 ]* ([0-9]*)%%"
4649
4750
48def unlocalized_env(reset={"LANG": "POSIX.UTF-8"}):51def unlocalized_env(reset={"LANG": "POSIX.UTF-8"}):
@@ -144,8 +147,8 @@ def set_profile_hdmi():
144 try:147 try:
145 check_call(["pactl", "set-card-profile", card, profile])148 check_call(["pactl", "set-card-profile", card, profile])
146 except CalledProcessError as error:149 except CalledProcessError as error:
147 logging.error("Failed setting audio output to:%s: %s" %150 logging.error("Failed setting audio output to:{}: {}".format(
148 (profile, error))151 profile, error))
149152
150153
151def get_current_profiles_settings(profiles_file):154def get_current_profiles_settings(profiles_file):
@@ -156,8 +159,8 @@ def get_current_profiles_settings(profiles_file):
156 config = configparser.ConfigParser()159 config = configparser.ConfigParser()
157160
158 for match in re.finditer(161 for match in re.finditer(
159 "(?P<card_id>Card #\d+)\n\tName:\s+(?P<card_name>.*?)\n.*?"162 r"(?P<card_id>Card #\d+)\n\tName:\s+(?P<card_name>.*?)\n.*?"
160 "Active\sProfile:\s+(?P<profile>.*?)\n", pactl_list, re.M | re.S163 r"Active\sProfile:\s+(?P<profile>.*?)\n", pactl_list, re.M | re.S
161 ):164 ):
162 config[match.group('card_id')] = {165 config[match.group('card_id')] = {
163 'name': match.group('card_name'),166 'name': match.group('card_name'),
@@ -168,8 +171,8 @@ def get_current_profiles_settings(profiles_file):
168 with open(profiles_file, 'w') as active_profiles:171 with open(profiles_file, 'w') as active_profiles:
169 config.write(active_profiles)172 config.write(active_profiles)
170 except IOError:173 except IOError:
171 logging.error("Failed to save active profiles information: %s" %174 logging.error("Failed to save active profiles information: {}".format(
172 sys.exc_info()[1])175 sys.exc_info()[1]))
173176
174177
175def restore_profiles_settings(profiles_file):178def restore_profiles_settings(profiles_file):
@@ -184,9 +187,9 @@ def restore_profiles_settings(profiles_file):
184 check_call(["pactl", "set-card-profile", config[card]['name'],187 check_call(["pactl", "set-card-profile", config[card]['name'],
185 config[card]['profile']])188 config[card]['profile']])
186 except CalledProcessError as error:189 except CalledProcessError as error:
187 logging.error("Failed setting card <%s> profile to <%s>: %s" %190 logging.error(
188 (config[card]['name'],191 "Failed setting card <{}> profile to <{}>: {}".format(
189 config[card]['profile'], error))192 config[card]['name'], config[card]['profile'], error))
190193
191194
192def move_sinks(name):195def move_sinks(name):
@@ -201,49 +204,68 @@ def move_sinks(name):
201 check_call(["pactl", "move-sink-input", input_index, name],204 check_call(["pactl", "move-sink-input", input_index, name],
202 stdout=DEVNULL)205 stdout=DEVNULL)
203 except CalledProcessError:206 except CalledProcessError:
204 logging.error("Failed to move input %d to sink %d" %207 logging.error("Failed to move input {} to sink {}".format(
205 (input_index, name))208 input_index, name))
206 sys.exit(1)209 sys.exit(1)
207210
208211
212def get_audio_settings(type, name="default"):
213 if name == "default":
214 pactl_status = check_output(["pactl", "info"],
215 universal_newlines=True,
216 env=unlocalized_env())
217 default_regex = re.compile(default_pattern % type.title())
218 name = default_regex.search(pactl_status).group()
219
220 pactl_list = check_output(["pactl", "list", "{}s".format(type)],
221 universal_newlines=True,
222 env=unlocalized_env())
223 entry_regex = re.compile(entry_pattern % name, re.DOTALL)
224 entry = entry_regex.search(pactl_list).group()
225
226 muted = muted_regex.search(entry).group()
227
228 volumes = {}
229 max_volume = 0
230 channels = channel_map_regex.search(entry).group()
231 for channel in channels.split(","):
232 volume_regex = re.compile(volume_pattern % channel, re.DOTALL)
233 _volume = int(volume_regex.search(entry).group(1).strip())
234 volumes.update({channel: _volume})
235 max_volume = max(_volume, max_volume)
236
237 return {
238 "name": name,
239 "muted": muted,
240 "volumes": volumes,
241 "max_volume": max_volume
242 }
243
244
209def store_audio_settings(file):245def store_audio_settings(file):
210 logging.info("[ Saving audio settings ]".center(80, '='))246 logging.info("[ Saving audio settings ]".center(80, '='))
211 try:247 try:
212 settings_file = open(file, 'w')248 settings_file = open(file, 'w')
213 except IOError:249 except IOError:
214 logging.error("Failed to save settings: %s" % sys.exc_info()[1])250 logging.error("Failed to save settings: {}".format(sys.exc_info()[1]))
215 sys.exit(1)251 sys.exit(1)
216252
217 for type in TYPES:253 for type in TYPES:
218 pactl_status = check_output(["pactl", "info"],254 audio_settings = get_audio_settings(type)
219 universal_newlines=True,255 print("default_{}: {}".format(type, audio_settings["name"]),
220 env=unlocalized_env())
221 default_regex = re.compile(default_pattern % type.title())
222 default = default_regex.search(pactl_status).group()
223
224 print("default_%s: %s" % (type, default), file=settings_file)
225
226 pactl_list = check_output(["pactl", "list", type + 's'],
227 universal_newlines=True,
228 env=unlocalized_env())
229
230 entry_regex = re.compile(entry_pattern % default, re.DOTALL)
231 entry = entry_regex.search(pactl_list).group()
232
233 muted = muted_regex.search(entry)
234 print("%s_muted: %s" % (type, muted.group().strip()),
235 file=settings_file)256 file=settings_file)
236257 print("{}_muted: {}".format(type, audio_settings["muted"].strip()),
237 volume = int(volume_regex.search(entry).group(1).strip())
238
239 print("%s_volume: %s%%" % (type, str(volume)),
240 file=settings_file)258 file=settings_file)
259 print("{}_volume: {}%".format(
260 type, str(audio_settings["max_volume"])),
261 file=settings_file)
262
241 settings_file.close()263 settings_file.close()
242264
243265
244def set_audio_settings(device, mute, volume):266def set_audio_settings(device, mute, volume):
245 for type in TYPES:267 for type in TYPES:
246 pactl_entries = check_output(["pactl", "list", type + 's'],268 pactl_entries = check_output(["pactl", "list", "{}s".format(type)],
247 universal_newlines=True,269 universal_newlines=True,
248 env=unlocalized_env())270 env=unlocalized_env())
249271
@@ -257,10 +279,12 @@ def set_audio_settings(device, mute, volume):
257 logging.info("[ Fallback sink ]".center(80, '='))279 logging.info("[ Fallback sink ]".center(80, '='))
258 logging.info("Name: {}".format(name))280 logging.info("Name: {}".format(name))
259 with open(os.devnull, 'wb') as DEVNULL:281 with open(os.devnull, 'wb') as DEVNULL:
260 check_call(["pactl", "set-default-%s" % type, name],282 check_call(["pactl",
283 "set-default-{}".format(type),
284 name],
261 stdout=DEVNULL)285 stdout=DEVNULL)
262 except CalledProcessError:286 except CalledProcessError:
263 logging.error("Failed to set default %s" % type)287 logging.error("Failed to set default {}".format(type))
264 sys.exit(1)288 sys.exit(1)
265289
266 if type == "sink":290 if type == "sink":
@@ -268,16 +292,18 @@ def set_audio_settings(device, mute, volume):
268292
269 try:293 try:
270 check_call(["pactl",294 check_call(["pactl",
271 "set-%s-mute" % type, name, str(int(mute))])295 "set-{}-mute".format(type),
296 name,
297 str(int(mute))])
272 except:298 except:
273 logging.error("Failed to set mute for %s" % name)299 logging.error("Failed to set mute for {}".format(name))
274 sys.exit(1)300 sys.exit(1)
275301
276 try:302 try:
277 check_call(["pactl", "set-%s-volume" % type,303 check_call(["pactl", "set-{}-volume".format(type),
278 name, str(volume) + '%'])304 name, "{}%".format(str(volume))])
279 except:305 except:
280 logging.error("Failed to set volume for %s" % name)306 logging.error("Failed to set volume for {}".format(name))
281 sys.exit(1)307 sys.exit(1)
282308
283309
@@ -287,8 +313,8 @@ def restore_audio_settings(file):
287 with open(file) as f:313 with open(file) as f:
288 settings_file = f.read().split()314 settings_file = f.read().split()
289 except IOError:315 except IOError:
290 logging.error("Unable to open existing settings file: %s" %316 logging.error("Unable to open existing settings file: {}".format(
291 sys.exc_info()[1])317 sys.exc_info()[1]))
292 return 1318 return 1
293319
294 for type in TYPES:320 for type in TYPES:
@@ -297,10 +323,11 @@ def restore_audio_settings(file):
297 # is incorrect, so we just abort.323 # is incorrect, so we just abort.
298 try:324 try:
299 name = settings_file[325 name = settings_file[
300 settings_file.index("default_%s:" % type) + 1]326 settings_file.index("default_{}:".format(type)) + 1]
301 muted = settings_file[settings_file.index("%s_muted:" % type) + 1]327 muted = settings_file[
328 settings_file.index("{}_muted:".format(type)) + 1]
302 volume = settings_file[329 volume = settings_file[
303 settings_file.index("%s_volume:" % type) + 1]330 settings_file.index("{}_volume:".format(type)) + 1]
304 except ValueError:331 except ValueError:
305 logging.error("Unable to restore settings because settings "332 logging.error("Unable to restore settings because settings "
306 "file is invalid")333 "file is invalid")
@@ -308,25 +335,25 @@ def restore_audio_settings(file):
308335
309 try:336 try:
310 with open(os.devnull, 'wb') as DEVNULL:337 with open(os.devnull, 'wb') as DEVNULL:
311 check_call(["pactl", "set-default-%s" % type, name],338 check_call(["pactl", "set-default-{}".format(type), name],
312 stdout=DEVNULL)339 stdout=DEVNULL)
313 except CalledProcessError:340 except CalledProcessError:
314 logging.error("Failed to restore default %s" % name)341 logging.error("Failed to restore default {}".format(name))
315 return 1342 return 1
316343
317 if type == "sink":344 if type == "sink":
318 move_sinks(name)345 move_sinks(name)
319346
320 try:347 try:
321 check_call(["pactl", "set-%s-mute" % type, name, muted])348 check_call(["pactl", "set-{}-mute".format(type), name, muted])
322 except:349 except:
323 logging.error("Failed to restore mute for %s" % name)350 logging.error("Failed to restore mute for {}".format(name))
324 return 1351 return 1
325352
326 try:353 try:
327 check_call(["pactl", "set-%s-volume" % type, name, volume])354 check_call(["pactl", "set-{}-volume".format(type), name, volume])
328 except:355 except:
329 logging.error("Failed to restore volume for %s" % name)356 logging.error("Failed to restore volume for {}".format(name))
330 return 1357 return 1
331358
332359
@@ -359,7 +386,7 @@ def main():
359 logging.error("No file specified to store audio settings!")386 logging.error("No file specified to store audio settings!")
360 return 1387 return 1
361 settings_file = args.file388 settings_file = args.file
362 profiles_file = args.file + ".profiles"389 profiles_file = "{}.profiles".format(args.file)
363390
364 if args.verbose:391 if args.verbose:
365 logging.basicConfig(format='%(levelname)s:%(message)s',392 logging.basicConfig(format='%(levelname)s:%(message)s',
@@ -383,7 +410,7 @@ def main():
383 set_profile_hdmi()410 set_profile_hdmi()
384 set_audio_settings(args.device, args.mute, args.volume)411 set_audio_settings(args.device, args.mute, args.volume)
385 else:412 else:
386 logging.error(args.action + "is not a valid action")413 logging.error("{} is not a valid action".format(args.action))
387 return 1414 return 1
388415
389 return 0416 return 0
diff --git a/checkbox_support/scripts/tests/test_audio_settings.py b/checkbox_support/scripts/tests/test_audio_settings.py
index 9f81f97..6a6b0ba 100644
--- a/checkbox_support/scripts/tests/test_audio_settings.py
+++ b/checkbox_support/scripts/tests/test_audio_settings.py
@@ -22,9 +22,10 @@ from __future__ import print_function
22from __future__ import unicode_literals22from __future__ import unicode_literals
2323
24import os24import os
25import re
25import unittest26import unittest
2627
27from checkbox_support.scripts.audio_settings import _guess_hdmi_profile, volume_regex28from checkbox_support.scripts.audio_settings import _guess_hdmi_profile, volume_pattern
28from checkbox_support.parsers.tests.test_pactl import PactlDataMixIn29from checkbox_support.parsers.tests.test_pactl import PactlDataMixIn
2930
3031
@@ -171,10 +172,11 @@ class SetProfileTest(unittest.TestCase, PactlDataMixIn):
171 ('0', 'Hdmi2'))172 ('0', 'Hdmi2'))
172173
173class RegexTest(unittest.TestCase):174class RegexTest(unittest.TestCase):
174 175
175 def test_volume_regex_trusty(self):176 def test_volume_regex_trusty(self):
176 """Testing pactl 4.0 output"""177 """Testing pactl 4.0 output"""
177 pactl_volume = " Volume: 0: 47% 1: 47%"178 pactl_volume = " Volume: 0: 47% 1: 47%"
179 volume_regex = re.compile(volume_pattern % "0", re.DOTALL)
178 volume = int(volume_regex.search(pactl_volume).group(1).strip())180 volume = int(volume_regex.search(pactl_volume).group(1).strip())
179 self.assertEqual(volume, 47)181 self.assertEqual(volume, 47)
180182
@@ -182,5 +184,6 @@ class RegexTest(unittest.TestCase):
182 """Testing pactl 8.0 output"""184 """Testing pactl 8.0 output"""
183 # See lp:1595380 for more info185 # See lp:1595380 for more info
184 pactl_volume = " Volume: front-left: 65536 / 100% / 0.00 dB, front-right: 65536 / 100% / 0.00 dB"186 pactl_volume = " Volume: front-left: 65536 / 100% / 0.00 dB, front-right: 65536 / 100% / 0.00 dB"
187 volume_regex = re.compile(volume_pattern % "front-left", re.DOTALL)
185 volume = int(volume_regex.search(pactl_volume).group(1).strip())188 volume = int(volume_regex.search(pactl_volume).group(1).strip())
186 self.assertEqual(volume, 100)189 self.assertEqual(volume, 100)

Subscribers

People subscribed via source and target branches