Sound.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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_node_tools.Util import *
  23. _alsa_config_file = '/tmp/alsa-config-' + os.path.basename(sys.argv[0])
  24. _dvols = { 'Master': 78, 'Speaker': 78, 'Headphone': 15, 'PCM': 190 }
  25. def timespec2secs(ts):
  26. import re
  27. mul = { 's': 1, 'm': 60, 'h': 60*60, 'd': 60*60*24 }
  28. pat = r'^([0-9]+)([smhd]*)$'
  29. m = re.match(pat,ts)
  30. if m == None:
  31. die(2,"'%s': invalid time specifier" % ts)
  32. a,b = m.groups()
  33. return int(a) * (mul[b] if b else 1)
  34. def parse_repeat_spec(rs):
  35. return [(timespec2secs(i),timespec2secs(j))
  36. for i,j in [a.split(':') for a in rs.split(',')]]
  37. def init_sound():
  38. def _restore_sound():
  39. # msg('Restoring sound volume')
  40. do_system('sudo alsactl restore -f ' + _alsa_config_file)
  41. os.unlink(_alsa_config_file)
  42. import atexit
  43. atexit.register(_restore_sound)
  44. do_system('sudo alsactl store -f ' + _alsa_config_file)
  45. def play_sound(fn,vol,repeat_spec='',remote_host='',kill_flg=None,testing=False):
  46. if not remote_host:
  47. do_system('sudo alsactl store -f ' + _alsa_config_file)
  48. for k in 'Master','Speaker','Headphone':
  49. do_system(('sudo amixer -q set %s on' % k),testing)
  50. # do_system('amixer -q set Headphone off')
  51. vols = dict([(k,int(_dvols[k] * float(vol) / 100)) for k in _dvols])
  52. for k in vols:
  53. do_system('sudo amixer -q set %s %s' % (k,vols[k]),testing)
  54. fn = os.path.expanduser(fn)
  55. cmd = (
  56. 'aplay -q %s' % fn,
  57. 'ssh %s mmnode-play-sound -v%d %s' % (remote_host,vol,fn)
  58. )[bool(remote_host)]
  59. if repeat_spec and kill_flg:
  60. for interval,duration in parse_repeat_spec(repeat_spec):
  61. start = time.time()
  62. while time.time() < start + duration:
  63. do_system(cmd,testing)
  64. if kill_flg.wait(interval):
  65. if not remote_host:
  66. do_system('sudo alsactl restore -f ' + _alsa_config_file)
  67. return
  68. else: # Play once
  69. do_system(cmd,testing)
  70. if not remote_host:
  71. do_system('sudo alsactl restore -f ' + _alsa_config_file)