asterisk-misc/transfer_back/mixer.py

191 lines
5.3 KiB
Python
Executable file

#!/usr/bin/env python3
"""
Questo script tiene d'occhio una specifica ConfBridge.
SE c'e' almeno un partecipante, allora cerca di far entrare lo speaker (ovvero
quello che noi chiamiamo "mixer", e che è semplicemente un'estensione PJSIP)
dentro la confbridge
Nella configurazione di asterisk si deve porre attenzione ad un dettaglio: lo
speaker si deve trovare in un contesto diverso da tutti gli altri telefoni, e in
particolare da quello in cui si trovano gli utenti remoti che entrano nella
confbridge in questione. In questo modo si puo' facilmente distinguere lo
speaker.
"""
import logging
from argparse import ArgumentParser
from panoramisk.actions import Action
import asterisk_misc_common
CONFERENCE = "400"
APP = None
log = logging.getLogger("transferback")
async def on_tutto(manager, msg):
for prefix in ["Var", "RTC"]:
if msg.event.startswith(prefix):
return
log.info("... Event %s", msg.event)
async def refresh(manager, *args):
ret = await manager.send_action(
Action({"Action": "ConfbridgeList", "Conference": CONFERENCE}), as_list=False
)
if ret.response == "Error":
await APP.on_users(None, ret)
class ConfbridgeInviter:
def __init__(self, manager):
self.manager = manager
self.users = []
self.tmp_users = []
self.log = logging.getLogger(self.__class__.__name__)
self.manager.register_event("EndpointDetail", self.on_speaker_endpoint_info)
self.on_speaker_endpoint_info_active = False
def get_context(self):
return "from-mixer"
def get_extension(self):
return "9400"
def get_speaker_channel(self):
return "PJSIP/400"
def get_conference(self):
return CONFERENCE
def is_speaker(self, msg):
"""
questo metodo capisce se un utente e' lo speaker.
Si sarebbe potuto fare anche in altri modi, ad esempio guardando il
channel, o la Exten, o utilizzando admin/marked in maniera opportuna.
"""
return msg.context == self.get_context()
async def run(self):
self.log.info("runno")
self.manager.register_event("ConfbridgeList", self.on_user)
self.manager.register_event("ConfbridgeListComplete", self.on_users)
async def on_user(self, _, msg):
if msg.conference != self.get_conference():
return
self.tmp_users.append(msg)
async def on_users(self, _, _msg):
self.users = self.tmp_users
self.tmp_users = []
someone_inside = len(self.users) > 0
speaker_inside = any(True for u in self.users if self.is_speaker(u))
for u in self.users:
self.log.debug(" - %s %s", u.context, u.channel)
self.log.debug(
"%d users - speaker_inside=%s", len(self.users), str(speaker_inside)
)
if not speaker_inside:
if someone_inside:
await self.maybe_invite_speaker()
self.users = []
async def maybe_invite_speaker(self):
self.log.debug("Maybe?")
self.on_speaker_endpoint_info_active = True
ret = await self.manager.send_action(
Action(
{
"Action": "PJSIPShowEndpoint",
"Endpoint": self.get_speaker_channel().split("/")[-1],
}
),
as_list=False,
)
self.on_speaker_endpoint_info_active = ret.actionid
async def on_speaker_endpoint_info(self, _, msg):
self.log.debug("Vediamo")
active = self.on_speaker_endpoint_info_active
if active is False or (type(active) is str and active != msg.actionid):
return
self.on_speaker_endpoint_info_active = False
self.log.debug(" Speaker dev = %s", msg.devicestate)
if msg.devicestate == "Not in use":
self.invite_speaker()
def invite_speaker(self):
cmd = "channel originate {chan} extension {ext}@{ctx}".format(
chan=self.get_speaker_channel(),
ext=self.get_extension(),
ctx=self.get_context(),
)
self.log.debug("CMD = %s", cmd)
self.manager.send_command(cmd)
async def kick_speaker(self):
return
cmd = "confbridge kick {conf} all".format(
conf=self.get_conference(),
)
self.log.debug("CMD = %s", cmd)
ret = await self.manager.send_command(cmd)
return ret
async def run_app(Cls, manager):
global APP
APP = Cls(manager)
await APP.run()
async def init(manager):
manager.register_event("*", on_tutto)
for event in [
"FullyBooted",
"ConfbridgeStart",
"ConfbridgeJoin",
"ConfbridgeLeave",
"ConfbridgeEnd",
"TestEvent",
"Hangup",
"Newstate", # XXX: solo se lo stato che cambia e' quello dello speaker
]:
manager.register_event(event, refresh)
pass
await run_app(ConfbridgeInviter, manager)
async def on_shutdown(m):
pass
def main():
p = ArgumentParser()
asterisk_misc_common.add_arguments(p)
args = p.parse_args()
asterisk_misc_common.do_common_options(args)
manager = asterisk_misc_common.get_manager(args)
asterisk_misc_common.run_manager(
manager, args, on_startup=init, on_shutdown=on_shutdown
)
if __name__ == "__main__":
main()