From 079c0cc1aa089c865768b232003570fa73fc52fa Mon Sep 17 00:00:00 2001
From: Markus Otto <otto@fs.tum.de>
Date: Fri, 14 Aug 2015 19:01:05 +0200
Subject: add protocol features and minor fixes

---
 voctocore/lib/audiomix.py            |  3 ++
 voctocore/lib/commands.py            | 64 ++++++++++++++++++++++++++++++++----
 voctocore/lib/controlserver.py       | 11 ++++---
 voctocore/lib/tcpmulticonnection.py  |  3 --
 voctocore/lib/tcpsingleconnection.py |  2 --
 voctocore/lib/videomix.py            |  9 +++++
 6 files changed, 76 insertions(+), 16 deletions(-)

(limited to 'voctocore')

diff --git a/voctocore/lib/audiomix.py b/voctocore/lib/audiomix.py
index 294155b..17bc1fb 100644
--- a/voctocore/lib/audiomix.py
+++ b/voctocore/lib/audiomix.py
@@ -74,6 +74,9 @@ class AudioMix(object):
 		self.selectedSource = source
 		self.updateMixerState()
 
+	def getAudioSource(self):
+		return self.selectedSource
+
 	def on_eos(self, bus, message):
 		self.log.debug('Received End-of-Stream-Signal on Mixing-Pipeline')
 
diff --git a/voctocore/lib/commands.py b/voctocore/lib/commands.py
index f0b8011..664a6ca 100644
--- a/voctocore/lib/commands.py
+++ b/voctocore/lib/commands.py
@@ -1,5 +1,7 @@
 #!/usr/bin/python3
 import logging
+import json
+
 
 from lib.config import Config
 from lib.videomix import CompositeModes
@@ -22,6 +24,12 @@ class ControlServerCommands():
 		if src_name_or_id < 0 or src_name_or_id >= len(self.sources):
 			raise IndexError("source %s unknown" % src_name_or_id)
 
+	def encodeSourceName(self, src_id):
+		try:
+			return self.sources[src_id]
+		except Exception as e:
+			raise IndexError("source %s unknown" % src_id)
+
 	def decodeBlankerSourceName(self, src_name_or_id):
 		if isinstance(src_name_or_id, str):
 			try:
@@ -32,6 +40,12 @@ class ControlServerCommands():
 		if src_name_or_id < 0 or src_name_or_id >= len(self.blankersources):
 			raise IndexError("source %s unknown" % src_name_or_id)
 
+	def encodeBlankerSourceName(self, src_id):
+		try:
+			return self.blankersources[src_id]
+		except Exception as e:
+			raise IndexError("source %s unknown" % src_id)
+
 
 	def message(self, *args):
 		return True
@@ -41,16 +55,28 @@ class ControlServerCommands():
 		self.pipeline.vmix.setVideoSourceA(src_id)
 		return True
 
+	def get_video_a(self):
+		src_id = self.pipeline.vmix.getVideoSourceA()
+		return (True, self.encodeSourceName(src_id))
+
 	def set_video_b(self, src_name_or_id):
 		src_id = self.decodeSourceName(src_name_or_id)
 		self.pipeline.vmix.setVideoSourceB(src_id)
 		return True
 
+	def get_video_b(self):
+		src_id = self.pipeline.vmix.getVideoSourceB()
+		return (True, self.encodeSourceName(src_id))
+
 	def set_audio(self, src_name_or_id):
 		src_id = self.decodeSourceName(src_name_or_id)
 		self.pipeline.amix.setAudioSource(src_id)
 		return True
 
+	def get_audio(self):
+		src_id = self.pipeline.amix.getAudioSource()
+		return (True, self.encodeSourceName(src_id))
+
 	def set_composite_mode(self, composite_mode):
 		try:
 			mode = CompositeModes[composite_mode]
@@ -60,11 +86,35 @@ class ControlServerCommands():
 		self.pipeline.vmix.setCompositeMode(mode)
 		return True
 
-	def set_stream_blank(self, src_name_or_id):
-		src_id = self.decodeBlankerSourceName(src_name_or_id)
-		self.pipeline.streamblanker.setBlankSource(src_id)
-		return True
+	def get_composite_mode(self):
+		try:
+			mode = self.pipeline.vmix.getCompositeMode()
+			return (True, mode.name)
+		except Exception as e:
+			raise KeyError("composite-mode %s unknown" % mode)
+
+	def set_stream_status(self, *args):
+		try:
+			if args[0] == "live":
+				self.pipeline.streamblanker.setBlankSource(None)
+				return True
+			elif args [0] == "blank":
+				src_id = self.decodeBlankerSourceName(args[1])
+				self.pipeline.streamblanker.setBlankSource(src_id)
+				return True
+			else:
+				return (False, "invocation: set_stream_status (live | blank <mode>)")
+		except IndexError as e:
+			return (False, "invocation: set_stream_status (live | blank <mode>)")
+
+	def get_stream_status(self):
+		if self.pipeline.streamblanker.blankSource is None:
+			return (True, "live")
+
+		name = self.encodeBlankerSourceName(self.pipeline.streamblanker.blankSource)
+		return (True, "blank " + name)
+
+	def get_config(self):
+		confdict = {k: dict(v) for k, v in dict(Config).items()}
+		return (True, json.dumps(confdict))
 
-	def set_stream_live(self):
-		self.pipeline.streamblanker.setBlankSource(None)
-		return True
diff --git a/voctocore/lib/controlserver.py b/voctocore/lib/controlserver.py
index c457fee..1a75a49 100644
--- a/voctocore/lib/controlserver.py
+++ b/voctocore/lib/controlserver.py
@@ -46,7 +46,7 @@ class ControlServer(TCPMultiConnection):
 		# process the received line
 		success, msg = self.processLine(conn, line)
 
-		# success = False -> error 
+		# success = False -> error
 		if success == False:
 			# on error-responses the message is mandatory
 			if msg is None:
@@ -71,8 +71,9 @@ class ControlServer(TCPMultiConnection):
 
 	def processLine(self, conn, line):
 		# split line into command and optional args
-		command, argstring = (line+' ').split(' ', 1)
-		args = argstring.strip().split()
+		words = line.split()
+		command = words[0]
+		args = words[1:]
 
 		# log function-call as parsed
 		self.log.info("Read Function-Call from %s: %s( %s )", conn.getpeername(), command, args)
@@ -90,7 +91,9 @@ class ControlServer(TCPMultiConnection):
 			ret = f(*args)
 
 			# signal method call to all other connected clients
-			self.signal(conn, command, args)
+			# only signal set_* commands
+			if command.split('_')[0] in ["set", "message"]:
+				self.signal(conn, command, args)
 
 			# if it returned an iterable, probably (Success, Message), pass that on
 			if hasattr(ret, '__iter__'):
diff --git a/voctocore/lib/tcpmulticonnection.py b/voctocore/lib/tcpmulticonnection.py
index fd2a633..927ac06 100644
--- a/voctocore/lib/tcpmulticonnection.py
+++ b/voctocore/lib/tcpmulticonnection.py
@@ -9,9 +9,6 @@ class TCPMultiConnection(object):
 		if not hasattr(self, 'log'):
 			self.log = logging.getLogger('TCPMultiConnection')
 
-		self.port = port
-		self.port = None
-
 		self.boundSocket = None
 		self.currentConnections = []
 
diff --git a/voctocore/lib/tcpsingleconnection.py b/voctocore/lib/tcpsingleconnection.py
index 886318f..d08f430 100644
--- a/voctocore/lib/tcpsingleconnection.py
+++ b/voctocore/lib/tcpsingleconnection.py
@@ -9,8 +9,6 @@ class TCPSingleConnection(object):
 		if not hasattr(self, 'log'):
 			self.log = logging.getLogger('TCPMultiConnection')
 
-		self.port = port
-
 		self.log.debug('Binding to Source-Socket on [::]:%u', port)
 		self.boundSocket = socket.socket(socket.AF_INET6)
 		self.boundSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
diff --git a/voctocore/lib/videomix.py b/voctocore/lib/videomix.py
index 3964783..3f92255 100644
--- a/voctocore/lib/videomix.py
+++ b/voctocore/lib/videomix.py
@@ -331,6 +331,9 @@ class VideoMix(object):
 		self.sourceA = source
 		self.recalculateMixerState()
 
+	def getVideoSourceA(self):
+		return self.sourceA
+
 	def setVideoSourceB(self, source):
 		# swap if required
 		if self.sourceA == source:
@@ -339,6 +342,12 @@ class VideoMix(object):
 		self.sourceB = source
 		self.recalculateMixerState()
 
+	def getVideoSourceB(self):
+		return self.sourceB
+
 	def setCompositeMode(self, mode):
 		self.compositeMode = mode
 		self.recalculateMixerState()
+
+	def getCompositeMode(self):
+		return self.compositeMode
-- 
cgit v1.2.3