#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# **************************************************************************** #
# This file is part of the pdpy project: https://github.com/pdpy-org
# Copyright (C) 2021-22 Fede Camara Halac
# **************************************************************************** #
"""
Msg
===
"""
from ..core.object import Object
from ..core.message import Message
__all__ = [ 'Msg' ]
[docs]class Msg(Object):
""" Representation of a patchable Pd Message box
This class represents a Pd message box with a list of targets.
Each ``target`` is an instance of :class:`Message`.
Parameters
----------
message : :class:`str`, a :class:`list` of :class:`str`, or ``None``
A string or a list of strings with a message.
Each element of the list defaults to the ``outlet`` target.
pd_lines : :class:`str`
A pd-lang string with a message, eg: ``#X msg 10 10 Hello world``
Or, for multiple targets: ``#X msg 10 10 Hello World \\;pd quit``
json : :class:`dict`
A json dictionary with the scope of a Msg.
"""
def __init__(self, message=None, pd_lines=None, json=None):
self.__pdpy__ = self.__class__.__name__
super().__init__(cls='msg',json=json)
if json is None and pd_lines is not None:
super().__init__(*pd_lines[:3], cls='msg')
self.className = self.__cls__
argv = pd_lines[3:]
if len(pd_lines[3:]):
self.addMessages(argv)
if message is not None:
self.addMessages([message] if not isinstance(message, list) else message)
[docs] def addTarget(self, address=None):
""" Add a target to the message target list
"""
if not hasattr(self, "targets"):
self.targets = []
target = Message(address=address)
self.targets.append(target)
return target
[docs] def addMessages(self, argv):
""" Add a new message to its appropriate ``target`` """
if 2 < len(argv) and "f" == argv[-2] and argv[-1].isnumeric():
self.border = self.__num__(argv[-1])
argv = argv[:-2]
argv[-1] = argv[-1].replace(",","")
# log(1, f'adding messages: {argv}')
# parse the argument vector
if len(argv) >= 1: # if there is at least one argument
i = 0 # index of the current argument
msgbuf = [] # buffer for the current message
# add the first target
last_target = None
if "\\;" == argv[i]:
if i + 1 < len(argv):
i += 1
last_target = self.addTarget(argv[i])
i += 1
else:
last_target = self.addTarget()
def _addmsg(msgbuf=msgbuf, target=last_target):
# if the message buffer is not empty
if len(msgbuf):
# if there are targets,
if target is not None:
# add the message buffer to the last target
target.add(msgbuf)
else:
# if there are no targets, add one and fill it with the message
self.addTarget().add(msgbuf)
return []
# we will increment the index i until we reach the end of the arguments
while i < len(argv):
# if the current element is an escaped comma
if "\\," == argv[i]:
msgbuf = _addmsg(msgbuf) # add the message buffer to the last target
i += 1
continue
# if the current element is an escaped semicolon, we have a new TARGET
if "\\;" == argv[i]:
msgbuf = _addmsg(msgbuf) # add the message buffer to the last target
# special case for the first target
# if i == 0:
# last_target = self.addTarget()
if i + 1 < len(argv):
# the next element is the address
i += 1
if argv[i] != '': # if the address is not empty
# add a new target with the address
last_target = self.addTarget(argv[i])
i += 1
continue
# if the current argument is neither escaped comma nor semi,
msgbuf.append(argv[i]) # add the current argument to the message buffer
i += 1 # increment the index
# end loop section while i < len(argv)
# add the message if we still have 1 in the buffer
msgbuf = _addmsg(msgbuf)
return self
def __pd__(self):
""" Return the pd-lang string for this message """
s = ''
for target in getattr(self, "targets", []):
s += target.__pd__()
if hasattr(self, "border"):
s += f', f {self.border}'
return super().__pd__(s) if s else ''
def __xml__(self):
""" Return the XML Element for this message """
x = super().__xml__(scope=self, tag=self.__cls__, attrib='border')
if hasattr(self, 'targets'):
targets = super().__element__(tag='targets')
for target in getattr(self, "targets", []):
super().__subelement__(targets, target.__xml__())
super().__subelement__(x, targets)
return x