def main_func(ip, port):   
    dispatcher = Dispatcher()
    dispatcher.map("/Chordata/r*", data_handler)
    dispatcher.set_default_handler(default_handler)
    
    server = BlockingOSCUDPServer((ip, port), dispatcher)
    server.serve_forever()  # Blocks forever
Esempio n. 2
0
    def __init__(self, address=("127.0.0.1", 9000), listen_port=9001):
        self.beat_callback = None
        self.startup_callback = None
        self.listen_port = listen_port

        #------------------------------------------------------------------------
        # Handler callbacks for particular messages from Live.
        # Used so that other processes can register callbacks when states change.
        #------------------------------------------------------------------------
        self.handlers = {}

        self.osc_address = address
        self.osc_client = SimpleUDPClient(address[0], address[1])
        dispatcher = Dispatcher()
        dispatcher.set_default_handler(self.handler)
        self.osc_server = BlockingOSCUDPServer(("127.0.0.1", listen_port),
                                               dispatcher)
        self.osc_server_thread = None

        self.osc_read_event = None
        self.osc_timeout = 3.0

        self.osc_server_events = {}

        self.query_address = None
        self.query_rv = []

        self.listen()
Esempio n. 3
0
    def InitNetwork(self, client_ip, client_port, listen_port):
        # client
        self.client = udp_client.SimpleUDPClient(client_ip, client_port)
        PrintManager("Connecting client on port {}.".format(client_port), 4)

        # server callbacks
        dispatch = Dispatcher()
        dispatch.map("/move*", self.MoveNozzle)  # /move/extrude and /move
        dispatch.map("/extrude", self.ExtractMaterial)
        dispatch.map("/retract", self.RetractMaterial)
        dispatch.map("/req/nozzle_pos", self.RequestNozzlePosition)
        dispatch.set_default_handler(
            lambda _: PrintManager("Received message.", 1))
        # TODO: Add other functions

        # server
        loop = asyncio.get_event_loop()
        self.server = AsyncIOOSCUDPServer(("127.0.0.1", listen_port), dispatch,
                                          asyncio.get_event_loop())
        PrintManager("Serving on {}:{}".format("127.0.0.1", listen_port), 4)
        self.server.serve()

        # start the event loop for server
        self.osc_thread = threading.Thread(target=loop.run_forever)
        self.osc_thread.daemon = True
        self.osc_thread.start()
Esempio n. 4
0
class OscReceiver(threading.Thread):
    def __init__(self,
                 ip,
                 receive_from_port,
                 quit_event,
                 address_list=["/clock*"],
                 address_handler_list=[None]):
        """
        Constructor for OSC_SENDER CLASS

        :param ip: ip address of client ==> 127.0.0.1 (for local host/ inter app communication on same machine)
        :param receive_from_port: the port on which python listens for incoming data
        """
        super(OscReceiver, self).__init__()
        self.setDaemon(
            True)  # don't forget this line, otherwise, the thread never ends

        self.ip = ip
        self.receiving_from_port = receive_from_port

        self.listening_thread = None

        self.dispatcher = Dispatcher()

        for ix, address in enumerate(address_list):
            self.dispatcher.map(address, address_handler_list[ix])

        self.dispatcher.set_default_handler(self.default_handler)

        self.server = BlockingOSCUDPServer((self.ip, self.receiving_from_port),
                                           self.dispatcher)
        #self.server.request_queue_size = 0
        self.quit_event = quit_event

    def run(self):
        print("running --- waiting for data")
        count = 0
        while not self.quit_event.is_set():

            self.server.handle_request()
            #count = (count+1) #% 8
            #print("count {}".format(count))

    def default_handler(self, address, *args):
        # handler for osc messages with no specific defined decoder/handler
        print(f"DEFAULT {address}: {args}")

    def get_ip(self):
        return self.ip

    def get_receiving_from_port(self):
        return self.receiving_from_port

    def get_server(self):
        return self.server

    def change_ip_port(self, ip, port):
        self.ip = ip
        self.receiving_from_port = port
        self.server = BlockingOSCUDPServer(self.ip, self.receiving_from_port)
Esempio n. 5
0
    def __init__(self,
                 ip: str = "127.0.0.1",
                 port_in: int = 8081,
                 port_out: int = 8080,
                 recv_address: str = "/pyosc",
                 parse_parenthesis_as_list: bool = False,
                 discard_duplicate_arguments: bool = True,
                 send_format: SendFormat = SendFormat.FLATTEN,
                 osc_log_level: Optional[int] = logging.INFO):
        """

        :param ip:
        :param port_in:
        :param port_out:
        :param parse_parenthesis_as_list:
        :param send_format:
        :param osc_log_level: Forward log messages to Max. Will not forward if set to None. To forward only some messages, override _handle_max_osc_error, _handle_type_error or _handle_error
        """
        super(MaxOsc, self).__init__(parse_parenthesis_as_list,
                                     discard_duplicate_arguments)
        self.logger = logging.getLogger(__name__)
        self.sender: Sender = Sender(ip, port_out, send_format)
        if osc_log_level:
            handler: OscLogHandler = OscLogHandler(self.sender, osc_log_level)
            self.logger.addHandler(handler)

        dispatcher = Dispatcher()
        dispatcher.map(recv_address, self.main_callback)
        dispatcher.set_default_handler(self._default_handler)
        self._server = BlockingOSCUDPServer((ip, port_in), dispatcher)
        self.logger.info(
            f"MaxOsc initialized on ip {ip} with incoming port {port_in} and outgoing port {port_out}."
        )
Esempio n. 6
0
 def __init__(self, address, state):
     self.state = state
     dispatcher = Dispatcher()
     dispatcher.set_default_handler(self.msg_handler)
     self.server = OSCClientServer((address, self.XAIR_PORT), dispatcher)
     worker = threading.Thread(target=self.run_server)
     worker.daemon = True
     worker.start()
Esempio n. 7
0
 def _start_server(self):
     dispatcher = Dispatcher()
     self.server = OSCClientServer(("0.0.0.0", self.args.port),
                                   self.ardour_addr, dispatcher,
                                   self._service_action)
     dispatcher.map("/rec_enable_toggle", self.handle_rec_enable_toggle)
     dispatcher.map("/record_tally", self.handle_record_tally)
     dispatcher.map("/heartbeat", self.handle_heartbeat)
     dispatcher.set_default_handler(self.handle_any)
Esempio n. 8
0
def main_func():
    ip = "localhost"
    port = 6565

    dispatcher = Dispatcher()
    dispatcher.set_default_handler(default_handler)

    server = BlockingOSCUDPServer((ip, port), dispatcher)
    server.serve_forever()
Esempio n. 9
0
class Osc_Interface(Thread):
    """
    Class used to creat an OSC client to send message to an external synthesiser listening to OSC messages
    """
    def __init__(self,
                 client_host='127.0.0.1',
                 client_port=57120,
                 server_host='127.0.0.1',
                 server_port=57130):
        """
        Class constructor
        :param host: URL used to reach OSC listener
        :param port: port used to reach OSC listener
        """

        # Initiate OSC client
        self._osc_client = udp_client.SimpleUDPClient(client_host, client_port)

        # Register a default dispatcher
        self._dispatcher = Dispatcher()
        self._dispatcher.set_default_handler(self._print_message)

        self._server_host = server_host
        self._server_port = server_port

        # Initiate OSC server
        self.start_server()

    def _print_message(address, *args):
        print(f"DEFAULT {address}: {args}")

    def start_server(self):
        self._running = True
        Thread.__init__(self)

    def run(self):
        self._server = BlockingOSCUDPServer(
            (self._server_host, self._server_port), self._dispatcher)
        self._server.serve_forever()

    def stop(self):
        self._running = False
        self._server.shutdown()

    def is_running(self):
        return self._running

    def add_handler(self, trigger, handler):
        self._dispatcher.map('/' + trigger, handler)

    def send(self, osc_handler, msg):
        """
        Send an OSC message to a synthesiser listening to OSC messages
        :param url: used to trigger right instrument on synthesiser - most of the time this is instrument's name
        :param notes: an array containing notes to play in midi note format
        """
        self._osc_client.send_message('/' + osc_handler, msg)
Esempio n. 10
0
def main_func():
    dispatcher = Dispatcher()
    dispatcher.map("/%/*", data_handler)
    dispatcher.set_default_handler(default_handler)

    ip = "localhost"
    port = 6565

    server = BlockingOSCUDPServer((ip, port), dispatcher)
    server.serve_forever()  # Blocks forever
Esempio n. 11
0
def osc_server():
    dispatcher = Dispatcher()
    dispatcher.map("/lightstick/preset", preset_handler)
    dispatcher.set_default_handler(default_handler)

    ip = "0.0.0.0"
    port = 5000

    server = BlockingOSCUDPServer((ip, port), dispatcher)
    server.serve_forever()
    def configureDispatcher(self):
        # setting the object which receives the messages and decides where to send them
        dispatcher = Dispatcher()
        dispatcher.map("/inputs/key_mapping/*", self.set_keyMappings)
        dispatcher.map("/inputs/key_on/gen_MIDI", self.set_genMIDI)
        dispatcher.map("/inputs/key_on", self.keyOn)
        dispatcher.map("/inputs/key_off", self.keyOff)
        dispatcher.set_default_handler(self.default_handler)

        return dispatcher
Esempio n. 13
0
def main_func():
    global client
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('localhost', 30001))

    dispatcher = Dispatcher()
    dispatcher.map("/%%/*", address_handler)
    dispatcher.map("/%/*", data_handler)
    dispatcher.set_default_handler(default_handler)

    ip = "localhost"
    port = 6565

    server = BlockingOSCUDPServer((ip, port), dispatcher)
    server.serve_forever()  # Blocks forever
Esempio n. 14
0
class MessageReceiver:
    def __init__(self, port):
        print(f'Setting up Receiver with port: {port}')
        self.dispatcher = Dispatcher()
        self.server = BlockingOSCUDPServer(('127.0.0.1', port),
                                           self.dispatcher)
        self.dispatcher.set_default_handler(self.handleMessage)
        self.thread = Thread(target=self.run)
        self.thread.start()

    def run(self):
        self.server.serve_forever()
        print('done with receiver thread')

    def handleMessage(self, adress, *args):
        print(f'handler: {adress}: {args}')
Esempio n. 15
0
class OscServer:
    def __init__(self, ip_adress="127.0.0.1", port=4321):
        self.ip_adress = ip_adress
        self.port = port

        self.dispatcher = Dispatcher()
        self.server = None

    def register_default_handler(self, handler_function: FunctionType):
        self.dispatcher.set_default_handler(handler_function)

    def register_handler(self, route: str, handler_function: FunctionType):
        self.dispatcher.map(route, handler_function)

    def terminate(self):
        self.server.shutdown()

    def serve(self):
        print(f"Listening for OSC messages on {self.ip_adress}:{self.port}")
        self.server = BlockingOSCUDPServer((self.ip_adress, self.port),
                                           self.dispatcher)
        self.server.serve_forever()
Esempio n. 16
0
print("Sending OSC to port", 5005, "on localhost")
client.send_message("/scriptName", CUR_PYTHON_SCRIPT)

osc.defineOscHandlers()

    
#timeout defineOscHandlers
def updateTimeout(*args): t.update() #reset timeout
dispatcher.map("/tick", updateTimeout)

def cancelScript(*args): t.cancel()
dispatcher.map("/cancel", cancelScript)

def unknown_OSC(*args): print("unknown OSC message: ", args)
dispatcher.set_default_handler(unknown_OSC)

####################
#LOOPumjumj
######################

async def loop():
         
    time.sleep(0.1)
    handshakeStatus = 1 
    print("done setup")
    osc.initSynthParams()
    client.send_message("/init", 0)

    while(t.check()): 
        #t.check checks if timeout has triggered to cancel script
Esempio n. 17
0
class ResQueue:
    def __init__(self):

        #User configurable parameters
        self.limit = 4
        self.tour_video_layer = 17
        self.tour_video_clip = 2
        self.tour_video_button_id = 0

        self.box_video_layer = 16
        self.box_video_start_column = 10
        self.box_waiting_video_layer = 15

        self.blank_waiting_video_column = 10

        #OSC related
        self.osc_client = SimpleUDPClient("127.0.0.1", 7000)
        self.osc_dispatcher = Dispatcher()
        self.osc_dispatcher.map("/composition/layers/*/clips/*/connected",
                                self.video_handler)
        self.osc_dispatcher.set_default_handler(self.debug_handler)

        #Internal variables
        self.items = []
        self.current_clip = 0
        self.current_layer = 0
        self.playing_tour_video = False
        self.playing_idle_video = False
        self.loop = asyncio.get_running_loop()
        self.current_box_waiting_video_layer = 0
        self.waiting_list = []

    async def startOSCserver(self):
        self.osc_server = AsyncIOOSCUDPServer(("127.0.0.1", 7001),
                                              self.osc_dispatcher, self.loop)
        transport, protocol = await self.osc_server.create_serve_endpoint(
        )  # Create datagram endpoint and start serving

    def clear(self):
        self.items = []

    def inQueue(self, item):
        return (item in self.items)

    def isEmpty(self):
        return not self.items

    def enqueue(self, item):

        #Disable the queue if the tour video is playing
        if self.playing_tour_video == True:
            return

        if item == self.tour_video_button_id:
            self.play_tour_video()
            return

        if item not in self.items:
            if self.size() < self.limit:
                #Only play the waiting box video if something is in the queue
                if not self.isEmpty():
                    self.play_box_waiting_video(item)
                else:
                    self.play_box_video(item)
                log.info(f"Added item to queue {item}")
                self.items.insert(0, item)  # list function
            else:
                log.info("Cant add: Queue is full...")

    def play_tour_video(self):
        self.playing_idle_video = False
        self.clear()  #Empty the queue (It could be made to resume queue)
        #Do we need to do anything about a potential waiting video that is playing or will mike handle that
        log.info("Playing Tour video")
        self.playing_tour_video = True
        self._play_clip(self.tour_video_layer, self.tour_video_clip)

    def play_box_video(self, box):
        self.playing_idle_video = False
        log.info("Playing box video %d", box)
        self._play_clip(self.box_video_layer,
                        self.box_video_start_column + box)

    def play_box_waiting_video(self, box):

        log.info(
            f"Starting waiting video layer: {self.current_box_waiting_video_layer}"
        )
        self.waiting_list.append(self.current_box_waiting_video_layer)
        log.debug(f"Waiting list {self.waiting_list}")
        self._play_waiting(self.current_box_waiting_video_layer,
                           self.box_video_start_column + box)

        #Check below
        self.current_box_waiting_video_layer = self.current_box_waiting_video_layer + 1
        if self.current_box_waiting_video_layer == (self.limit - 1):
            self.current_box_waiting_video_layer = 0

    def stop_box_waiting_video(self):
        log.debug("Stopping waiting video")
        #Check below
        self._play_waiting(self.waiting_list[0],
                           self.blank_waiting_video_column)
        self.waiting_list.pop(0)
        log.debug(f"Waiting list {self.waiting_list}")

        #self._play_waiting(self.current_box_waiting_video_layer, self.blank_waiting_video_column)

    def play_idle_video(self, delay=0):
        if (self.playing_idle_video == False):
            log.info("Playing Idle video in %d seconds", delay)
            self.loop.call_later(delay, self._play_idle_video)
            #Note: Assume no callback for this video and it loops forever in resolume?
            #Would a callback be better?
        self.playing_idle_video = True

    def _play_idle_video(self):
        log.info("Playing idle video")
        self._play_column(3)

    def _change_deck(self, deck):
        self.osc_client.send_message(f"/composition/decks/{deck}/select", 1)

    def _play_column(self, column):
        self.osc_client.send_message(f"/composition/columns/{column}/connect",
                                     1)

        #self.osc_client.send_message("/composition/selectedcolumn/connect",1)

    def _play_waiting(self, layers, clip):
        layer = self.box_waiting_video_layer - layers
        #log.debug("Waiting layer %d",layer)
        #log.debug(f"/composition/layers/{layer}/clips/{clip}/connect")
        self.osc_client.send_message(
            f"/composition/layers/{layer}/clips/{clip}/connect", 1)

    def _play_clip(self, layers, clip):
        self.osc_client.send_message(
            f"/composition/layers/{layers}/clips/{clip}/connect", 1)
        self.current_layer = layers
        self.current_clip = clip

    def dequeue(self):
        try:
            self.items.pop()  # list function
        except IndexError:
            print("Queue empty...")

    def size(self):
        return len(self.items)

    def item_list(self):
        return list(self.items)

    def print_queue(self):
        log.info(f"Queue: {self.items}")
        # for items in self.items:
        # print(items)

    # not first in first out, this will remove the first value it finds from the value given
    def dequeue_remove(self, item):
        # print(f"Item number: {item}")
        # print(f"Current Queue: {self.items}")
        try:
            self.items.remove(item)
        except ValueError:
            log.warning("Button ID does not exist in queue...")

        #Calback from resolume to say a video has finished playing
    def debug_handler(self, address, *args):

        #log.warning (f"Unhandled OSC from Resolume {address}: {args}")
        pass

        #Calback from resolume to say a video has finished playing
        #Format of "/composition/layers/*/clips/*/connected"
    def video_handler(self, address, *args):

        log.debug(f"Handling OSC from Resolume {address}: {args}")

        data = address.split("/")
        try:
            layer = int(data[3])
            clip = int(data[5])
        except:
            log.error(f"Could not process address: {address}")
            return

        #Tour video handling
        if self.playing_tour_video == True:
            if (layer == self.tour_video_layer) and (
                    clip == self.tour_video_clip) and (args[0] == 1):
                self.playing_tour_video = False
                log.info("Finished playing Tour Video")
                self.play_idle_video(5)
            return

        #ignore any callbacks when the idle video is active
        if self.playing_idle_video == True:
            return

        if (layer == self.current_layer) and (clip == self.current_clip) and (
                args[0] == 1):
            #Remove item just played
            self.dequeue()

            #check queue
            if not self.isEmpty():

                #Stop playing the last waiting video
                self.stop_box_waiting_video()

                #Play the next video
                self.play_box_video(self.items[-1])
            else:
                self.playing_idle_video = True
                log.info("Finished playing queue")
Esempio n. 18
0
class Query(LoggingObject):
    """ Object responsible for passing OSC queries to the LiveOSC server,
    parsing and proxying responses.

    This object is a singleton, under the assumption that only one Live instance
    can be running, so only one global Live Query object should be needed.

    Following this assumption, static helper functions also exist:

        live.query(path, *args)
        live.cmd(path, *args)
    """
    def __init__(self, address=("127.0.0.1", 9900), listen_port=9002):
        self.beat_callback = None
        self.startup_callback = None
        self.listen_port = listen_port

        #------------------------------------------------------------------------
        # Handler callbacks for particular messages from Live.
        # Used so that other processes can register callbacks when states change.
        #------------------------------------------------------------------------
        self.handlers = {}

        self.osc_address = address
        if OSC_BACKEND == 'liblo':
            self.osc_target = liblo.Address(address[0], address[1])
            self.osc_server = liblo.Server(listen_port)
            self.osc_server.add_method(None, None, self.handler)
            self.osc_server.add_bundle_handlers(self.start_bundle_handler,
                                                self.end_bundle_handler)

        elif OSC_BACKEND == 'pythonosc':
            # TODO how to deal w/ bundles? even necessary?
            # (the handlers seem to be just logging...)
            # (i think only some of the clip code refers to bundles at all)

            ip = address[0]
            self.osc_client = SimpleUDPClient(ip, address[1])

            self.dispatcher = Dispatcher()
            self.dispatcher.set_default_handler(self.pythonosc_handler_wrapper)

            # TODO TODO may need to take more care that this, or the other
            # pythonosc objects, actually close all of their connections before
            # exit / atexit
            # for some reason, maybe most likely something else, there seem to
            # be less frequent apparent "connection" issues with liblo than with
            # pythonosc...
            self.osc_server = ThreadingOSCUDPServer((ip, listen_port),
                                                    self.dispatcher)

        self.osc_server_thread = None

        self.osc_read_event = None
        self.osc_timeout = 3.0

        self.osc_server_events = {}

        self.query_address = None
        self.query_rv = []

        self.listen()

    def osc_server_read(self):
        assert OSC_BACKEND == 'liblo'
        while True:
            self.osc_server.recv(10)

    def listen(self):
        if OSC_BACKEND == 'liblo':
            target = self.osc_server_read
        elif OSC_BACKEND == 'pythonosc':
            target = self.osc_server.serve_forever

        self.osc_server_thread = threading.Thread(target=target)
        self.osc_server_thread.setDaemon(True)
        self.osc_server_thread.start()

    def stop(self):
        """ Terminate this query object and unbind from OSC listening. """
        pass

    def cmd(self, msg, *args):
        """ Send a Live command without expecting a response back:

            live.cmd("/live/tempo", 110.0) """

        self.log_debug("OSC output: %s %s", msg, args)
        try:
            if OSC_BACKEND == 'liblo':
                liblo.send(self.osc_target, msg, *args)

            elif OSC_BACKEND == 'pythonosc':
                # not clear on whether this unpacking in len(1) case in
                # necessary, just trying to make it look like examples in docs
                if len(args) == 1:
                    args = args[0]

                self.osc_client.send_message(msg, args)

        # TODO TODO need to modify pythonosc client call / handling so it will
        # also raise an error in this case? (probably)
        except Exception as e:
            self.log_debug(f"During cmd({msg}, {args})")
            raise LiveConnectionError(
                "Couldn't send message to Live (is LiveOSC present and activated?)"
            )

    # TODO maybe compute something like the average latency for a response to
    # arrive for a query (maybe weighted by recency) for debugging whether the
    # timeout is reasonable?
    # TODO + number of commands already processed / sent maybe + maybe log
    # whether particular commands always fail?

    def query(self, msg, *args, **kwargs):
        """ Send a Live command and synchronously wait for its response:

            return live.query("/live/tempo")

        Returns a list of values. """

        #------------------------------------------------------------------------
        # Use **kwargs because we want to be able to specify an optional kw
        # arg after variable-length args --
        # eg live.query("/set/freq", 440, 1.0, response_address = "/verify/freq")
        #
        # http://stackoverflow.com/questions/5940180/python-default-keyword-arguments-after-variable-length-positional-arguments
        #------------------------------------------------------------------------

        #------------------------------------------------------------------------
        # Some calls produce responses at different addresses
        # (eg /live/device -> /live/deviceall). Specify a response_address to
        # take account of this.
        #------------------------------------------------------------------------
        response_address = kwargs.get("response_address", None)
        if response_address:
            response_address = response_address
        else:
            response_address = msg

        #------------------------------------------------------------------------
        # Create an Event to block the thread until this response has been
        # triggered.
        #------------------------------------------------------------------------
        self.osc_server_events[response_address] = threading.Event()

        #------------------------------------------------------------------------
        # query_rv will be populated by the callback, storing the return value
        # of the OSC query.
        #------------------------------------------------------------------------
        self.query_address = response_address
        self.query_rv = []
        self.cmd(msg, *args)

        #------------------------------------------------------------------------
        # Wait for a response.
        #------------------------------------------------------------------------
        timeout = kwargs.get("timeout", self.osc_timeout)
        rv = self.osc_server_events[response_address].wait(timeout)

        if not rv:
            self.log_debug(f"Timeout during query({msg}, {args}, {kwargs})")
            # TODO could change error message to not question whether LiveOSC
            # is setup correctly if there has been any successful communication
            # so far...
            raise LiveConnectionError(
                "Timed out waiting for response from LiveOSC. Is Live running and LiveOSC installed?"
            )

        return self.query_rv

    # TODO maybe pythonosc.osc_bundle_builder / osc_message_builder could
    # replace some of what these are doing (in OSC_BACKEND == 'pythonosc' case)?
    # (though not clear these are critical...)
    def start_bundle_handler(self, *args):
        assert OSC_BACKEND == 'liblo'
        self.log_debug("OSC: start bundle")

    def end_bundle_handler(self, *args):
        assert OSC_BACKEND == 'liblo'
        self.log_debug("OSC: end bundle")

    def pythonosc_handler_wrapper(self, address, *args):
        assert OSC_BACKEND == 'pythonosc'
        # TODO may need to unwrap len(args) == 0 case or something like that
        self.handler(address, args, None)

    def handler(self, address, data, types):
        self.log_debug("OSC input: %s %s" % (address, data))

        #------------------------------------------------------------------------
        # Execute any callbacks that have been registered for this message
        #------------------------------------------------------------------------
        if address in self.handlers:
            for handler in self.handlers[address]:
                handler(*data)

        #------------------------------------------------------------------------
        # If this message is awaiting a synchronous return, trigger the
        # thread event and update our return value.
        #------------------------------------------------------------------------
        if address == self.query_address:
            self.query_rv += data
            self.osc_server_events[address].set()
            return

        if address == "/live/beat":
            if self.beat_callback is not None:
                #------------------------------------------------------------------------
                # Beat callbacks are used if we want to trigger an event on each beat,
                # to synchronise with the timing of the Live set.
                #
                # Callbacks may take one argument: the current beat count.
                # If not specified, call with 0 arguments.
                #------------------------------------------------------------------------
                has_arg = False
                try:
                    signature = inspect.signature(self.beat_callback)
                    has_arg = len(signature.parameters) > 0
                except:
                    # Python 2
                    argspec = inspect.getargspec(self.beat_callback)
                    has_arg = len(
                        argspec.args) > 0 and argspec.args[-1] != "self"

                if has_arg:
                    self.beat_callback(data[0])
                else:
                    self.beat_callback()

        elif address == "/remix/oscserver/startup":
            if self.startup_callback is not None:
                self.startup_callback()

    def add_handler(self, address, handler):
        if not address in self.handlers:
            self.handlers[address] = []
        self.handlers[address].append(handler)
Esempio n. 19
0
class ThreadCommunication(ThreadCommunicationBase):
    """Base class for all OSC communication

    The 'listen' method is called in the superclass in a while loop with,
    error handling.

    Provides a method for composing the command string out of the command obj
    as well as method to listen for answers or status messages of the device.
    Both are meant to be overwritten to adjust the for new devices

    """

    def __init__(self, target_ip, target_port, stop_event=None):
        super().__init__(target_ip, target_port, stop_event=stop_event)
        self._dispatcher = Dispatcher()
        self._dispatcher.set_default_handler(self._analyse)
        self.last_composed = None

    # noinspection PyProtectedMember,PyProtectedMember
    def _main(self):

        client = _SimpleUDPClient(self.target_ip, self.target_port)

        server = _ThreadingOSCUDPServer(client.sock_connection, self._dispatcher)
        server.timeout = 0.01

        self.logger.debug(f"osc client connection: {client.sock_connection}")
        self.logger.debug(f"osc server connection: {server.sock_connection}")

        while not self.stop_event.is_set():  # while loop of thread

            while self._queue_command.empty():
                server.handle_request()
                if self.stop_event.is_set():
                    return

            command_item = self._queue_command.get()
            if not command_item:
                # used if subclass does decides at compose time not to send the command
                continue
            address, value = self._compose(command_item)
            if not address:
                continue
            if address is TypeError:
                # address and value are none when error occurred during composing
                cai = CommandRecvItem(
                    self.device_name, command_item.command, (), ComType.failed
                )
                self._put_into_answer_queue(cai)
                continue
            client.send_message(address, value)

    def _compose(self, command_item):
        """parse arguments to address and arguments returning OSC message parts.

        First counts the fields in the address string and inserts the arguments into it
        if there are one. Rest of the arguments are returned as new tuple.

        Args:
            command_item (CommandSendItem): CommandItem to be composed from.

        """

        command_template = self.dict_command_template[command_item.command]
        if command_item.request:
            address = command_template.request_composition
        else:
            address = command_template.command_composition

        if isinstance(command_item.arguments, dict):
            arguments = command_template.sorted_tuple_from_dict(command_item.arguments)
        else:
            arguments = command_item.arguments

        try:
            address_arg_count = format_arg_count(address)
            arg_address_tuple = arguments[:address_arg_count]
            arg_argument_tuple = arguments[address_arg_count:]
            if arg_address_tuple:
                address = address.format(*arg_address_tuple)

            self.last_composed = command_item

            if len(arg_argument_tuple) == 0:
                return address, ""
            if len(arg_argument_tuple) == 1:
                return address, arg_argument_tuple[0]
            return address, list(arg_argument_tuple)

        except TypeError as ex:
            self.logger.warning(
                f"error composing message {address}:{command_item.arguments}. Error "
                f"Message: {ex}"
            )
            return TypeError, TypeError

    def _analyse(self, address, *args):

        self.logger.debug(f"analyzing {address} with args {args}")

        m = None
        cmd_template = None
        in_last_composed = False

        try:
            command_template_last = self.dict_command_template[
                self.last_composed.command
            ]
            if command_template_last.answer_analysis:
                m = re.search(command_template_last.answer_analysis, address)
                cmd_template = command_template_last
                in_last_composed = True

            if not m:
                for name, command_template in self.dict_command_template.items():
                    if not command_template.answer_analysis:
                        continue
                    m = re.search(command_template.answer_analysis, address)
                    if m:
                        cmd_template = command_template
                        break

            values = None
            if cmd_template:
                if m:
                    values = cmd_template.create_arg_dict(tuple(m.groups()) + args)
                else:
                    values = cmd_template.create_arg_dict(args)

            if in_last_composed:  # match was found in self.last_composed
                command = self.last_composed.command
                if self.last_composed.request:
                    mt = ComType.request_success
                else:
                    mt = ComType.command_success
            elif m:  # match was found in dict_command_template
                command = cmd_template.name
                mt = ComType.message_status
            else:  # address could not be associated with any command
                command = None
                values = (address, args)
                mt = ComType.unidentifiable

            cai = CommandRecvItem(self.name, command, values, mt)

            self._put_into_answer_queue(cai)

        except TypeError as ex:
            self.logger.warning(
                f"error analyzing message {address}:{args}. Error Message: {ex}"
            )
            cai = CommandRecvItem(
                self.name, None, (address, *args), ComType.unidentifiable
            )
            self._put_into_answer_queue(cai)
            return
Esempio n. 20
0
class OSCServer(XClock):
    """
    Extends the clock to have OSC control. Functions are documented in the README
    """

    def __init__(self, *args, **kwargs):
        super(OSCServer, self).__init__(*args, **kwargs)
        self.parser.add_argument("--ip", help="IP for the OSC Server to listen on", default="0.0.0.0")
        self.parser.add_argument("--port", help="Port for the OSC Server to listen on", default=1337)

        self.dispatcher = Dispatcher()
        self.dispatcher.set_default_handler(self.osc_recv)

    def get_server(self):
        return AsyncIOOSCUDPServer((self.args.ip, self.args.port), self.dispatcher, asyncio.get_event_loop())

    @property
    def state(self):
        """
        Vestige. Had an idea to save state in the event of a crash... Gave up on that.
        """
        return {
            'real_time'      : time.time(),
            'current_time'   : self.current_time.isoformat(),
            'glitch_mode'    : self.glitch_mode,
            'glitch_freq'    : self.glitch_freq,
            'x_glitch_mode'  : self.x_glitch_mode,
            'x_glitch_freq'  : self.x_glitch_freq,
            'x_glitch_number': self.x_glitch_number,
            'x_glitch_frames': self.x_glitch_frames,
            'x_color'        : self.x_color,
            'text_color'     : self.text_color,
        }

    def osc_recv(self, cmd, *args):
        """
        Handle incoming OSC command
        """
        logging.info(f'Command received {cmd} ({args})')
        cmd = os.path.basename(cmd)
        try:
            getattr(self, f'set_{cmd}')(*args)
        except AttributeError:
            logging.error(f'Invalid command received {cmd}')

    def set_random_glitch(self, freq=100, intensity=4):
        self.glitch_intensity = intensity
        if freq == -1:
            self.glitch_mode = self.GLITCH_MODE_ON
        elif freq == 0:
            self.glitch_mode = self.GLITCH_MODE_OFF
        else:
            self.glitch_mode = self.GLITCH_MODE_RANDOM
            self.glitch_freq = freq

    def set_random_x_glitch(self, freq, num=1, frames=1, color=None):
        if freq == 0:
            self.x_glitch_mode = self.GLITCH_MODE_OFF
            return
        self.set_single_x_glitch(num, frames, color)
        self.x_glitch_freq = freq
        self.x_glitch_mode = self.GLITCH_MODE_RANDOM

    def set_single_x_glitch(self, num=1, frames=1, color=None):
        self.set_x_color(color)
        self.x_glitch_number = num
        self.x_glitch_frames = frames
        self.x_glitch_mode = self.GLITCH_MODE_SINGLE

    def set_x_color(self, color):
        if color:
            self.x_color = color_to_rgb(color) or self.x_color

    def set_x_positions(self, positions='0000', color=None):
        if len(positions) != 4:
            logging.warning(f'Must specify four positions! {positions}')
            return
        self.x_glitch_mode = self.GLITCH_MODE_OFF
        self.x_glitch_step = 0
        positions_array = []
        for idx, pos in enumerate(positions):
            if pos == 'X':
                positions_array.append(idx)
        self.set_x_color(color)
        self.x_positions = positions_array

    def set_color(self, color):
        self.text_color = color_to_rgb(color)

    def set_bg(self, color):
        self.background = color_to_rgb(color)

    def set_time(self, hour, minute):
        self.current_time = self.current_time.replace(
            hour=hour,
            minute=minute,
            second=0
        )
        self.freeze_time = None

    def set_freeze(self, enabled=1):
        if not enabled and self.freeze_time:
            self.current_time = self.freeze_time
            self.freeze_time = None
        elif enabled and not self.freeze_time:
            self.freeze_time = self.current_time

    def set_glitch_to(self, hour, minute, frames=5):
        self.set_time(hour, minute)
        self.numbers_glitch_step = frames

    def set_normal(self):
        self.x_glitch_mode = self.GLITCH_MODE_OFF
        self.set_freeze(0)
        self.set_blink_all(0)
        self.set_blink_dots(1)
        self.glitch_mode = self.GLITCH_MODE_OFF
        self.time_dilation_factor = 1
        self.current_time = self.current_time.replace(second=0)
        self.x_positions = []
        self.x_color = self.text_color

    def set_brightness(self, target, duration=0):
        self.last_brightness = self.brightness
        self.target_brightness = max(min(target, 100), 0)
        if duration == 0:
            self.brightness = target
            return
        self.fade_elapsed = 0
        self.fade_time = duration

    def set_fadesnap(self, hour, minute, duration=1, clear_x=False):
        self.fade_snap_next_brightness = self.brightness
        self.fade_snap_time = self.current_time.replace(
            hour=hour,
            minute=minute,
            second=0
        )
        self.set_brightness(0, duration)
        self.fade_snap_clear_x = clear_x
        self.freeze_time = None

    def set_time_dilation(self, factor=1):
        self.time_dilation_factor = factor

    def set_increment_time(self, minutes):
        self.current_time += datetime.timedelta(minutes=minutes)
        self.current_time = self.current_time.replace(second=0)

    def set_framerate(self, rate=0.05):
        self.framerate = rate

    def set_blink_dots(self, enabled=1):
        self.blink_dots = True if enabled == 1 else False
        self.show_dots = not self.blink_dots

    def set_blink_all(self, enabled=1):
        self.blink_all = True if enabled == 1 else False
        self.show_numbers = not self.blink_all

    def set_timenow(self, reset_dilation=None):
        if reset_dilation:
            self.time_dilation_factor = 1
        self.current_time = datetime.datetime.now()
Esempio n. 21
0
oled = ssd1306(serial)
print("OLED connected!")

screen = Screen(oled, fps=25)

def oled_handler(address, *args):
    #print("{}: {}".format(address, args))
    global screen
    line = address.split("/")[-1]
    if line in screen.data.keys():
        screen.data[line] = " ".join(str(arg) for arg in args)


dispatcher = Dispatcher()
dispatcher.map("/oled/line*", oled_handler)
dispatcher.set_default_handler(print)


async def display():
    while True:
        screen.draw()
        await asyncio.sleep(1/screen.fps)


async def main():
    address = (OSC_HOST, OSC_PORT)
    server = AsyncIOOSCUDPServer(address, dispatcher, asyncio.get_event_loop())
    transport, protocol = await server.create_serve_endpoint()
    print(f"OSC server running at port {OSC_PORT}")
    await display()
    transport.close()
Esempio n. 22
0
import logging

playing = []
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.INFO)

global video 

def handler_function(address, *args):
    log.info (f"{address}: {args}")
    global playing
    playing.append(address)

dispatcher = Dispatcher()
dispatcher.set_default_handler(handler_function)
client = SimpleUDPClient("127.0.0.1", 7001)

ip = "127.0.0.1"
port = 7000


async def loop():

    global playing
    """Example main loop that only runs for 10 iterations before finishing"""
    while True:
        await asyncio.sleep(5)
        if playing:
            await asyncio.sleep(5)
Esempio n. 23
0
File: osc.py Progetto: zetof/bar
class Osc_Interface(Thread):
    """
    Class used to create:
      - an OSC client used to send messages to SuperCollider
      - an OSC server to listen to messages coming from SuperCollider
    """

    def __init__(self, client_host='127.0.0.1', client_port=57120, server_host='127.0.0.1', server_port=57130):
        """
        Class constructor
        :param client_host: URL used to reach OSC listener of SuperCollider
        :param client_port: port used to reach OSC listener of SuperCollider
        :param server_host: URL used to reach this running OSC server instance
        :param server_port: port used to reach this running OSC server instance
        """

        # Initiate OSC client
        self._osc_client = udp_client.SimpleUDPClient(client_host, client_port)

        # Register a default dispatcher
        self._dispatcher = Dispatcher()
        self._dispatcher.set_default_handler(self._print_message)

        # Save some init params to the class
        self._server_host = server_host
        self._server_port = server_port

        # Initiate OSC server
        self._start_server()

    def _print_message(address, *args):
        """
        Default handler, prints unhandled messages as they come
        :param args: any data passed in the OSC frame
        """
        print(f"DEFAULT {address}: {args}")

    def _start_server(self):
        """
        Start the OSC server
        """
        self._running = True
        self._server = None
        Thread.__init__(self)

    def run(self):
        """
        OSC server thread startup method
        """
        self._server = BlockingOSCUDPServer((self._server_host, self._server_port), self._dispatcher)
        self._server.serve_forever()

    def stop(self):
        """
        Stop the running OSC server (if it is running)
        """
        self._running = False
        if self._server:
            self._server.shutdown()

    def is_running(self):
        """
        Boldly checks if the OSC server is running
        """
        return self._running

    def add_handler(self, trigger, handler):
        """
        Àdds an OSC handler to the server instance
        :param trigger: name of the trigger in the OSC message coming from SuperCollider
        :param handler: the claas.method that will receive data and process it
        """
        self._dispatcher.map('/' + trigger, handler)

    def send(self, osc_handler, msg):
        """
        Send an OSC message to SuperCollider
        :param osc_handler: name of the handler defined in SuperCollider that will process the message data
        :param msg: message data
        """
        self._osc_client.send_message('/' + osc_handler, msg)
class OSC:
    def __init__(self):
        # IP address, if you want to communicate with a device on the same network, you probably need to change stuff here.
        # especially differentiate between the PC and the device IP. However, this allows you to run processing on android
        # but do optimization on desktop and still have wireless communication.

        self.ip = "127.0.0.1"

        # the port we receive data from processing on
        self.receiving_port = 12001

        # the port where processing expects data to be send.
        self.sending_port = 12000

        # OSC works with addresses. Basically we can filter on the incoming address and have different handler based on an address.
        # in a case we dont recoginize the address, we use the default handler.
        self.dispatcher = Dispatcher()
        self.dispatcher.map("/filter", self.print_handler)
        self.dispatcher.map("/quit", self.quit_handler)
        self.dispatcher.set_default_handler(self.default_handler)

        # the client we use for sending data.
        self.sending_client = SimpleUDPClient(
            self.ip, self.sending_port)  # Create client

        # a boolean to see whether we need to quit the server based on incoming messages.
        self.run = True

    def send_message(self, address, message, verbose=True):
        # send a message to processing.
        # adress needs to be a string.

        self.sending_client.send_message(address, message)
        if verbose:
            print(f"send {message} to {address}")

    # the different handlers. You can easily add your own here, and add them to the dispatcher.
    def print_handler(self, address, *args):
        print(f"{address}: {args}")

    def quit_handler(self, address, *args):
        print("QUITING")
        self.run = False

    def default_handler(self, address, *args):
        print(f"DEFAULT {address}: {args}")

    # This is the main loop, anything you wanna do, you should do it in here.
    # If you are doing time intensive stuff, you need to start thinking about threading
    # because anything you do in here blocks receiving new messages.
    async def loop(self):
        direction_x = 10
        direction_y = 10
        max_x = 400 - direction_y
        max_y = 400 - direction_y
        x = 0
        y = 0
        size = 10
        size_step = 1
        max_size = 30
        min_size = 10
        while self.run:
            # ------ DO YOUR STUFF HERE ------- #
            # move rect

            if x > max_x or x < 0:
                print()
                direction_x *= -1
                y += direction_y
                osc.send_message("y", y)

            if y > max_y or y < 0:
                direction_y *= -1

            if size < min_size or size > max_size:
                size_step *= -1

            size += size_step

            x += direction_x
            osc.send_message("x", x)
            osc.send_message("w", size)
            osc.send_message("h", size)

            #
            # # other stuff
            # osc.send_message("/test/int", 1)
            # osc.send_message("/test/float", 1.1)
            # osc.send_message("/test/list", [1, 2, 3, 4])
            # osc.send_message("/test/arbitrary/stuff", [1, 2.3, 3.1415, "hello world"])

            await asyncio.sleep(
                0.1
            )  # we need some time to process whether we have incoming data.

    # setup a non-blocking receiving server.
    async def init_main(self):
        server = AsyncIOOSCUDPServer((self.ip, self.receiving_port),
                                     self.dispatcher, asyncio.get_event_loop())
        (
            transport,
            protocol,
        ) = (await server.create_serve_endpoint()
             )  # Create datagram endpoint and start serving
        await self.loop()  # Enter main loop of program
        transport.close()  # Clean up serve endpoint

    # start everything
    def start(self):
        asyncio.run(self.init_main())
Esempio n. 25
0
#
# ORAC UDP client
#

oracClient = SimpleUDPClient(ORAC_IP, ORAC_PORT)  # Create client

#
# ORAC UDP listener
#


def oracMessageHandler(address, *args):
    asyncio.ensure_future(sio.emit(address[1:], args))

dispatcher = Dispatcher()
dispatcher.set_default_handler(oracMessageHandler)

oracServerTransport = None

async def runUdpServer():
    print('Starting OSC UDP server')
    server = AsyncIOOSCUDPServer(
        (SOCKET_LISTEN_IP, ORAC_LISTEN_PORT), dispatcher, loop)
    global oracServerTransport
    oracServerTransport, protocol = await server.create_serve_endpoint()
    print('OSC UDP server started')


async def stopUdpServer():
    print('Stopping OSC UDP server')
    oracServerTransport.close()  # Clean up serve endpoint
Esempio n. 26
0
class TestDispatcher(unittest.TestCase):

  def setUp(self):
    super().setUp()
    self.dispatcher = Dispatcher()

  def sortAndAssertSequenceEqual(self, expected, result):
    def sort(lst):
      return sorted(lst, key=lambda x: x.callback)
    return self.assertSequenceEqual(sort(expected), sort(result))

  def test_empty_by_default(self):
    self.sortAndAssertSequenceEqual([], self.dispatcher.handlers_for_address('/test'))

  def test_use_default_handler_when_set_and_no_match(self):
    handler = object()
    self.dispatcher.set_default_handler(handler)

    self.sortAndAssertSequenceEqual([Handler(handler, [])], self.dispatcher.handlers_for_address('/test'))

  def test_simple_map_and_match(self):
    handler = object()
    self.dispatcher.map('/test', handler, 1, 2, 3)
    self.dispatcher.map('/test2', handler)
    self.sortAndAssertSequenceEqual(
        [Handler(handler, [1, 2, 3])], self.dispatcher.handlers_for_address('/test'))
    self.sortAndAssertSequenceEqual(
        [Handler(handler, [])], self.dispatcher.handlers_for_address('/test2'))

  def test_example_from_spec(self):
    addresses = [
        "/first/this/one",
        "/second/1",
        "/second/2",
        "/third/a",
        "/third/b",
        "/third/c",
    ]
    for index, address in enumerate(addresses):
      self.dispatcher.map(address, index)

    for index, address in enumerate(addresses):
      self.sortAndAssertSequenceEqual(
          [Handler(index, [])], self.dispatcher.handlers_for_address(address))

    self.sortAndAssertSequenceEqual(
        [Handler(1, []), Handler(2, [])], self.dispatcher.handlers_for_address("/second/?"))

    self.sortAndAssertSequenceEqual(
        [Handler(3, []), Handler(4, []), Handler(5, [])],
        self.dispatcher.handlers_for_address("/third/*"))

  def test_do_not_match_over_slash(self):
    self.dispatcher.map('/foo/bar/1', 1)
    self.dispatcher.map('/foo/bar/2', 2)

    self.sortAndAssertSequenceEqual(
        [], self.dispatcher.handlers_for_address("/*"))

  def test_match_middle_star(self):
    self.dispatcher.map('/foo/bar/1', 1)
    self.dispatcher.map('/foo/bar/2', 2)

    self.sortAndAssertSequenceEqual(
        [Handler(2, [])], self.dispatcher.handlers_for_address("/foo/*/2"))

  def test_match_multiple_stars(self):
    self.dispatcher.map('/foo/bar/1', 1)
    self.dispatcher.map('/foo/bar/2', 2)

    self.sortAndAssertSequenceEqual(
        [Handler(1, []), Handler(2, [])], self.dispatcher.handlers_for_address("/*/*/*"))

  def test_match_address_contains_plus_as_character(self):
    self.dispatcher.map('/footest/bar+tender/1', 1)

    self.sortAndAssertSequenceEqual(
        [Handler(1, [])], self.dispatcher.handlers_for_address("/foo*/bar+*/*"))
    self.sortAndAssertSequenceEqual(
        [Handler(1, [])], self.dispatcher.handlers_for_address("/foo*/bar*/*"))

  def test_call_correct_dispatcher_on_star(self):
    self.dispatcher.map('/a+b', 1)
    self.dispatcher.map('/aaab', 2)
    self.sortAndAssertSequenceEqual(
        [Handler(2, [])], self.dispatcher.handlers_for_address('/aaab'))
    self.sortAndAssertSequenceEqual(
        [Handler(1, [])], self.dispatcher.handlers_for_address('/a+b'))

  def test_map_star(self):
    self.dispatcher.map('/starbase/*', 1)
    self.sortAndAssertSequenceEqual(
        [Handler(1, [])], self.dispatcher.handlers_for_address("/starbase/bar"))

  def test_map_root_star(self):
    self.dispatcher.map('/*', 1)
    self.sortAndAssertSequenceEqual(
        [Handler(1, [])], self.dispatcher.handlers_for_address("/anything/matches"))

  def test_map_double_stars(self):
    self.dispatcher.map('/foo/*/bar/*', 1)
    self.sortAndAssertSequenceEqual(
        [Handler(1, [])], self.dispatcher.handlers_for_address("/foo/wild/bar/wild"))
    self.sortAndAssertSequenceEqual(
        [], self.dispatcher.handlers_for_address("/foo/wild/nomatch/wild"))

  def test_multiple_handlers(self):
    self.dispatcher.map('/foo/bar', 1)
    self.dispatcher.map('/foo/bar', 2)
    self.sortAndAssertSequenceEqual(
        [Handler(1, []), Handler(2, [])], self.dispatcher.handlers_for_address("/foo/bar"))

  def test_multiple_handlers_with_wildcard_map(self):
    self.dispatcher.map('/foo/bar', 1)
    self.dispatcher.map('/*', 2)
    self.sortAndAssertSequenceEqual(
        [Handler(1, []), Handler(2, [])], self.dispatcher.handlers_for_address("/foo/bar"))
Esempio n. 27
0
class TestDispatcher(unittest.TestCase):
    def setUp(self):
        super().setUp()
        self.dispatcher = Dispatcher()

    def sortAndAssertSequenceEqual(self, expected, result):
        def sort(lst):
            return sorted(lst, key=lambda x: x.callback)

        return self.assertSequenceEqual(sort(expected), sort(result))

    def test_empty_by_default(self):
        self.sortAndAssertSequenceEqual(
            [], self.dispatcher.handlers_for_address('/test'))

    def test_use_default_handler_when_set_and_no_match(self):
        handler = object()
        self.dispatcher.set_default_handler(handler)

        self.sortAndAssertSequenceEqual(
            [Handler(handler, [])],
            self.dispatcher.handlers_for_address('/test'))

    def test_simple_map_and_match(self):
        handler = object()
        self.dispatcher.map('/test', handler, 1, 2, 3)
        self.dispatcher.map('/test2', handler)
        self.sortAndAssertSequenceEqual(
            [Handler(handler, [1, 2, 3])],
            self.dispatcher.handlers_for_address('/test'))
        self.sortAndAssertSequenceEqual(
            [Handler(handler, [])],
            self.dispatcher.handlers_for_address('/test2'))

    def test_example_from_spec(self):
        addresses = [
            "/first/this/one",
            "/second/1",
            "/second/2",
            "/third/a",
            "/third/b",
            "/third/c",
        ]
        for index, address in enumerate(addresses):
            self.dispatcher.map(address, index)

        for index, address in enumerate(addresses):
            self.sortAndAssertSequenceEqual(
                [Handler(index, [])],
                self.dispatcher.handlers_for_address(address))

        self.sortAndAssertSequenceEqual(
            [Handler(1, []), Handler(2, [])],
            self.dispatcher.handlers_for_address("/second/?"))

        self.sortAndAssertSequenceEqual(
            [Handler(3, []), Handler(4, []),
             Handler(5, [])], self.dispatcher.handlers_for_address("/third/*"))

    def test_do_not_match_over_slash(self):
        self.dispatcher.map('/foo/bar/1', 1)
        self.dispatcher.map('/foo/bar/2', 2)

        self.sortAndAssertSequenceEqual(
            [], self.dispatcher.handlers_for_address("/*"))

    def test_match_middle_star(self):
        self.dispatcher.map('/foo/bar/1', 1)
        self.dispatcher.map('/foo/bar/2', 2)

        self.sortAndAssertSequenceEqual(
            [Handler(2, [])], self.dispatcher.handlers_for_address("/foo/*/2"))

    def test_match_multiple_stars(self):
        self.dispatcher.map('/foo/bar/1', 1)
        self.dispatcher.map('/foo/bar/2', 2)

        self.sortAndAssertSequenceEqual(
            [Handler(1, []), Handler(2, [])],
            self.dispatcher.handlers_for_address("/*/*/*"))

    def test_match_address_contains_plus_as_character(self):
        self.dispatcher.map('/footest/bar+tender/1', 1)

        self.sortAndAssertSequenceEqual(
            [Handler(1, [])],
            self.dispatcher.handlers_for_address("/foo*/bar+*/*"))
        self.sortAndAssertSequenceEqual(
            [Handler(1, [])],
            self.dispatcher.handlers_for_address("/foo*/bar*/*"))

    def test_call_correct_dispatcher_on_star(self):
        self.dispatcher.map('/a+b', 1)
        self.dispatcher.map('/aaab', 2)
        self.sortAndAssertSequenceEqual(
            [Handler(2, [])], self.dispatcher.handlers_for_address('/aaab'))
        self.sortAndAssertSequenceEqual(
            [Handler(1, [])], self.dispatcher.handlers_for_address('/a+b'))

    def test_map_star(self):
        self.dispatcher.map('/starbase/*', 1)
        self.sortAndAssertSequenceEqual(
            [Handler(1, [])],
            self.dispatcher.handlers_for_address("/starbase/bar"))

    def test_map_root_star(self):
        self.dispatcher.map('/*', 1)
        self.sortAndAssertSequenceEqual(
            [Handler(1, [])],
            self.dispatcher.handlers_for_address("/anything/matches"))

    def test_map_double_stars(self):
        self.dispatcher.map('/foo/*/bar/*', 1)
        self.sortAndAssertSequenceEqual(
            [Handler(1, [])],
            self.dispatcher.handlers_for_address("/foo/wild/bar/wild"))
        self.sortAndAssertSequenceEqual(
            [], self.dispatcher.handlers_for_address("/foo/wild/nomatch/wild"))

    def test_multiple_handlers(self):
        self.dispatcher.map('/foo/bar', 1)
        self.dispatcher.map('/foo/bar', 2)
        self.sortAndAssertSequenceEqual(
            [Handler(1, []), Handler(2, [])],
            self.dispatcher.handlers_for_address("/foo/bar"))

    def test_multiple_handlers_with_wildcard_map(self):
        self.dispatcher.map('/foo/bar', 1)
        self.dispatcher.map('/*', 2)
        self.sortAndAssertSequenceEqual(
            [Handler(1, []), Handler(2, [])],
            self.dispatcher.handlers_for_address("/foo/bar"))
    else:
        # OTHER ========================================================
        print(f"Control unknown {address}: {args}")
        logging.info(f"Control unknown {address}: {args}")

# Default message catch
# ++++++++++++++++++++++++++++++++++++++++++++++++
def default_handler(address, *args):
    print(f"DEFAULT {address}: {args}")
# ------------------------------------------------


# ================================================
dispatcher = Dispatcher()
dispatcher.map("/control/*", getControl)
dispatcher.set_default_handler(default_handler)

# Init controls
I2CControl.printControls()

# Init server ------------------------------------
try:
    ip = "192.168.0.101"
    port = 9000
    
#     server = BlockingOSCUDPServer((ip, port), dispatcher)
#
#     logging.info('Launch server OSC ' + ip + ":" + str(port))
#
#     print("Server started ++")
#     server.serve_forever()  # Blocks forever
Esempio n. 29
0
class OSCResponder(Logged):
    def __init__(self, host='0.0.0.0', port=7401, **kwargs):

        self._host = host
        self._port = port
        self._client = None
        self._server = None
        self._server_thread = None

        Logged.__init__(self, **kwargs)

        self._dispatcher = Dispatcher()
        self._dispatcher.set_default_handler(self.receive)

        self._routes = {}
        for osc_path, callback in find_routes(self):
            self._dispatcher.map(osc_path, callback)
            self._routes[osc_path] = callback

    def start(self, *args):

        if self._server is not None:
            return

        self._server = ThreadingOSCUDPServer(
            (self._host, self._port),
            self._dispatcher,
        )
        self._server_thread = Thread(target=self._server.serve_forever,
                                     name=str(self),
                                     daemon=True)
        self._server_thread.start()

        self._host, self._port = self._server.socket.getsockname()

        self.debug('responder thread started.')

    def stop(self, *args):

        if self._server is not None:
            self._server.shutdown()

        if self._server_thread is not None:
            self._server_thread.join()
            self.debug('responder thread stopped.')

    def send(self, route, message, to=None):

        if self._client is None:
            return

        if not isinstance(self._client, dict):
            self._client.send_message(route, message)
            return

        if to is not None:
            if not isinstance(to, (tuple, list)):
                to = (to, )
            for name in filter(lambda key: key in self._client, to):
                self._client[name].send_message(route, message)
            return

        for client in self._client.values():
            client.send_message(route, message)

    def receive(self, route, source, *messages):

        self.info(f'[osc] {source[0]}:{source[1]} {route}')
        for message in messages:
            self.info(message)

    # @route('/connect')
    # def on_connect(self, route, source, data):
    #     """ Handle a connection call over OSC """
    #
    #     host, port = source
    #     client = self.connect(host, data)
    #     if not isinstance(self._client, dict):
    #         self._client = client
    #     else:
    #         self._client[port] = client
    #
    #     self.connected(host, port, data)

    @staticmethod
    def connect(host='localhost', port=7402):
        """ Open an OSC client for network communication """
        return SimpleUDPClient(host, port)

    def connected(self, host, port, data):
        """ Callback after an OSC connection created """
        self.info(f'client connection, from {host}:{port}, port {data}')

    @property
    def client(self):
        return self._client

    def __str__(self):
        return f'{self.__class__.__name__}@{self._host}:{self._port}'

    def __repr__(self):
        return f'<{self}>'