Sound.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C)2013-2016 Philemon <mmgen-py@yandex.com>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. mmgen_node_tools.Sound: audio-related functions for MMGen node tools
  20. """
  21. import sys,os,time
  22. from mmgen.util import die
  23. from mmgen_node_tools.Util import do_system
  24. _alsa_config_file = '/tmp/alsa-config-' + os.path.basename(sys.argv[0])
  25. _dvols = { 'Master': 78, 'Speaker': 78, 'Headphone': 15, 'PCM': 190 }
  26. def timespec2secs(ts):
  27. import re
  28. mul = { 's': 1, 'm': 60, 'h': 60*60, 'd': 60*60*24 }
  29. pat = r'^([0-9]+)([smhd]*)$'
  30. m = re.match(pat,ts)
  31. if m == None:
  32. die(2,"'%s': invalid time specifier" % ts)
  33. a,b = m.groups()
  34. return int(a) * (mul[b] if b else 1)
  35. def parse_repeat_spec(rs):
  36. return [(timespec2secs(i),timespec2secs(j))
  37. for i,j in [a.split(':') for a in rs.split(',')]]
  38. def init_sound():
  39. def _restore_sound():
  40. # msg('Restoring sound volume')
  41. do_system('sudo alsactl restore -f ' + _alsa_config_file)
  42. os.unlink(_alsa_config_file)
  43. import atexit
  44. atexit.register(_restore_sound)
  45. do_system('sudo alsactl store -f ' + _alsa_config_file)
  46. def play_sound(fn,vol,repeat_spec='',remote_host='',kill_flg=None,testing=False):
  47. if not remote_host:
  48. do_system('sudo alsactl store -f ' + _alsa_config_file)
  49. for k in 'Master','Speaker','Headphone':
  50. do_system(('sudo amixer -q set %s on' % k),testing)
  51. # do_system('amixer -q set Headphone off')
  52. vols = dict([(k,int(_dvols[k] * float(vol) / 100)) for k in _dvols])
  53. for k in vols:
  54. do_system('sudo amixer -q set %s %s' % (k,vols[k]),testing)
  55. fn = os.path.expanduser(fn)
  56. cmd = (
  57. 'aplay -q %s' % fn,
  58. 'ssh %s mmnode-play-sound -v%d %s' % (remote_host,vol,fn)
  59. )[bool(remote_host)]
  60. if repeat_spec and kill_flg:
  61. for interval,duration in parse_repeat_spec(repeat_spec):
  62. start = time.time()
  63. while time.time() < start + duration:
  64. do_system(cmd,testing)
  65. if kill_flg.wait(interval):
  66. if not remote_host:
  67. do_system('sudo alsactl restore -f ' + _alsa_config_file)
  68. return
  69. else: # Play once
  70. do_system(cmd,testing)
  71. if not remote_host:
  72. do_system('sudo alsactl restore -f ' + _alsa_config_file)