# Lower the volume of my computer over time in Python

I wrote a program to gradually lower the volume of my computer when I go to sleep so I can fall asleep with TV or music on. This was my first time using argparse and I feel like there should be a cleaner way to deal with default values of optional arguments. Any other feedback of course also welcomed.

import vol
from time import sleep
from subprocess import call, check_output
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-d", "--delay", help="time (in minutes) until volume begins to lower", type=int)
parser.add_argument("-m", "--minutes_until_mute", help="time (in minutes) to set the volume to mute", type=int)
a = parser.parse_args()
minutes_until_mute = a.minutes_until_mute if a.minutes_until_mute else 30
delay = a.delay if a.delay else 0
sleep(delay*60)
current_volume = check_output(['osascript', '-e', 'set ovol to output volume of (get volume settings)'])

for i in range(minutes_until_mute):
percent_of_volume = (-1.0/(minutes_until_mute**2))*(i**2) + 1 #quadratic function with maximum at (0, 100%) and crossing at (minutes_until_mute, 0)
new_volume = int(float(current_volume) * percent_of_volume)
call(["vol", "out", str(new_volume)])
call(["vol", "info"])
sleep(60)

call(["vol", "mute"]) #rounding errors mean we don't get exactly to 0

• As you ask for any other comments, I will say: think to the planet and shutdown your computer at the end of the delay ! (this question caught my eye because I love to go to sleep with music and I used for years a python script to turn off my computer after a specified time or another to turn it off once my vlc playlist is completed) Well maybe it's not a computer that you shutdown anyway :)
– mgc
Feb 7, 2016 at 20:03

"I feel like there should be a cleaner way to deal with default values of optional arguments"

Yes, there is. Per the documentation of ArgParse, you can specify a keyword argument default and give it the value you want.


parser.add_argument("-d", "--delay", help="Delay in minutes until starting mute", type=int, default=0)


Documentation here
Tutorial here

• Duh. I must've looked right at that a bunch of times. Feb 5, 2016 at 12:14

Conversion

You could convert current_volume to its relevant and usable type (float) at you get it instead of reconverting it everytime you use it.

current_volume = float(check_output(['osascript', '-e', 'set ovol to output volume of (get volume settings)']))
...
new_volume = int(current_volume * percent_of_volume)


Off-by-one error

This may or may not be an error depending on what you had in mind.

You've defined a function which is supposed to return 100% initially and 0% at the end.

Your function reaches 0 when (-1.0/(minutes_until_mute**2))*(i**2) + 1 which is when i == minutes_until_mute. Unfortunately, this is not the last value of your loop : the last value of range(n) is n-1.

• Eh. Technically an error, although not one that really affects anything. For best practices, though, best to just do range(minutes+1)? Feb 5, 2016 at 12:19