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