summaryrefslogtreecommitdiff
path: root/voctocore/lib/commands.py
blob: 21b8de888b12a65c41dc738493966d3316b5a939 (plain)
  1. #!/usr/bin/python3
  2. import logging
  3. import json
  4. from lib.config import Config
  5. from lib.videomix import CompositeModes
  6. from lib.response import NotifyResponse, OkResponse
  7. def decodeName(items, name_or_id):
  8. try:
  9. name_or_id = int(name_or_id)
  10. if name_or_id < 0 or name_or_id >= len(items):
  11. raise IndexError("unknown index %d" % name_or_id)
  12. return name_or_id
  13. except ValueError as e:
  14. try:
  15. return items.index(name_or_id)
  16. except ValueError as e:
  17. raise IndexError("unknown name %s" % name_or_id)
  18. def decodeEnumName(enum, name_or_id):
  19. try:
  20. name_or_id = int(name_or_id)
  21. if name_or_id < 0 or name_or_id >= len(enum):
  22. raise IndexError("unknown index %d" % name_or_id)
  23. return name_or_id
  24. except ValueError as e:
  25. try:
  26. return enum[name_or_id]
  27. except KeyError as e:
  28. raise IndexError("unknown name %s" % name_or_id)
  29. def encodeName(items, id):
  30. try:
  31. return items[id]
  32. except IndexError as e:
  33. raise IndexError("unknown index %d" % id)
  34. def encodeEnumName(enum, id):
  35. try:
  36. return enum(id).name
  37. except ValueError as e:
  38. raise IndexError("unknown index %d" % id)
  39. class ControlServerCommands(object):
  40. def __init__(self, pipeline):
  41. self.log = logging.getLogger('ControlServerCommands')
  42. self.pipeline = pipeline
  43. self.sources = Config.getlist('mix', 'sources')
  44. self.blankerSources = Config.getlist('stream-blanker', 'sources')
  45. # Commands are defined below. Errors are sent to the clients by throwing
  46. # exceptions, they will be turned into messages outside.
  47. def message(self, *args):
  48. return NotifyResponse('message', *args)
  49. def _get_video_status(self):
  50. a = encodeName( self.sources, self.pipeline.vmix.getVideoSourceA() )
  51. b = encodeName( self.sources, self.pipeline.vmix.getVideoSourceB() )
  52. return [a, b]
  53. def get_video(self):
  54. status = self._get_video_status()
  55. return OkResponse('video_status', *status)
  56. def set_video_a(self, src_name_or_id):
  57. src_id = decodeName(self.sources, src_name_or_id)
  58. self.pipeline.vmix.setVideoSourceA(src_id)
  59. status = self._get_video_status()
  60. return NotifyResponse('video_status', *status)
  61. def set_video_b(self, src_name_or_id):
  62. src_id = decodeName(self.sources, src_name_or_id)
  63. self.pipeline.vmix.setVideoSourceB(src_id)
  64. status = self._get_video_status()
  65. return NotifyResponse('video_status', *status)
  66. def _get_audio_status(self):
  67. src_id = self.pipeline.amix.getAudioSource()
  68. return encodeName(self.sources, src_id)
  69. def get_audio(self):
  70. status = self._get_audio_status()
  71. return OkResponse('audio_status', status)
  72. def set_audio(self, src_name_or_id):
  73. src_id = decodeName(self.sources, src_name_or_id)
  74. self.pipeline.amix.setAudioSource(src_id)
  75. status = self._get_audio_status()
  76. return NotifyResponse('audio_status', status)
  77. def _get_composite_status(self):
  78. mode = self.pipeline.vmix.getCompositeMode()
  79. return encodeEnumName(CompositeModes, mode)
  80. def get_composite_mode(self):
  81. status = self._get_composite_status()
  82. return OkResponse('composite_mode', status)
  83. def set_composite_mode(self, mode_name_or_id):
  84. mode = decodeEnumName(CompositeModes, mode_name_or_id)
  85. self.pipeline.vmix.setCompositeMode(mode)
  86. status = self._get_composite_status()
  87. return NotifyResponse('composite_mode', status)
  88. def set_videos_and_composite(self, src_a_name_or_id, src_b_name_or_id, mode_name_or_id):
  89. if src_a_name_or_id != '*':
  90. src_a_id = decodeName(self.sources, src_a_name_or_id)
  91. self.pipeline.vmix.setVideoSourceA(src_a_id)
  92. if src_b_name_or_id != '*':
  93. src_b_id = decodeName(self.sources, src_b_name_or_id)
  94. self.pipeline.vmix.setVideoSourceB(src_b_id)
  95. if mode_name_or_id != '*':
  96. mode = decodeEnumName(CompositeModes, mode_name_or_id)
  97. self.pipeline.vmix.setCompositeMode(mode)
  98. composite_status = self._get_composite_status()
  99. video_status = self._get_video_status()
  100. return [
  101. NotifyResponse('composite_mode', composite_status),
  102. NotifyResponse('video_status', *video_status)
  103. ]
  104. def _get_stream_status(self):
  105. blankSource = self.pipeline.streamblanker.blankSource
  106. if blankSource is None:
  107. return ('live',)
  108. return 'blank', encodeName(self.blankerSources, blankSource)
  109. def get_stream_status(self):
  110. status = self._get_stream_status()
  111. return OkResponse('stream_status', *status)
  112. def set_stream_blank(self, source_name_or_id):
  113. src_id = decodeName(self.blankerSources, source_name_or_id)
  114. self.pipeline.streamblanker.setBlankSource(src_id)
  115. status = self._get_stream_status()
  116. return NotifyResponse('stream_status', *status)
  117. def set_stream_live(self):
  118. self.pipeline.streamblanker.setBlankSource(None)
  119. status = self._get_stream_status()
  120. return NotifyResponse('stream_status', *status)
  121. def get_config(self):
  122. confdict = {header: dict(section) for header, section in dict(Config).items()}
  123. return OkResponse('server_config', json.dumps(confdict))