Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/osc/oscapi.py
blob: bc26ddb0d258ad618e21ba0a098b81b96918a983 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
""" This file is based on simpleOSC 0.2 by Daniel Holth.
This file has been modified by Simon Schampijer.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
"""


import socket
import errno
import logging
import sys

import osccore


class OscApi(object):
    def __init__(self, port=None, host=None):
        """create the send/receive socket and the callback manager
        bind the socket to a name (host and port) 

        Keyword arguments:
        port -- the port
                if no port is specified the socket will not be bound to an address and
                will only be used for sending
        host -- the host address, can be a dotted decimal address (e.g. '192.168.0.100')
                or a hostname (e.g. 'machine', 'localhost') 
                if you do not specify a hostname the socket will listen on all the
                devices for incoming messages        
        """
        
        self.manager = 0
        self.iosock = 0
        self.iosock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.manager = osccore.CallbackManager()

        self.isserver = 0
        
        if port is not None:
            if host is None:
                host = ""        
            try:        
                self.iosock.bind((host, port))
                self.isserver = 1        
            except socket.error:             
                if errno.EADDRINUSE:
                    logging.error("Port " +str(port)+ " in use." +
                                  " Maybe another oscapi is still or already running?" +
                                  " oscapi can only be used for sending.")
                    self.iosock.close()
                    self.iosock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.iosock.setblocking(0) 


    def addmethod(self, path, types, func):
        '''adds an osc method to the listener

        Keyword arguments:
        func -- the callback function which gets called when the appropriate osc message is received
        path -- the path (identifier) of the osc message
        
        '''        
        self.manager.add(func, path, types)


    def handlemsg(self, data, addr):
        '''give the information read from the socket to the osc message dispatcher

        Keyword arguments:
        data -- the data read from the socket
        addr -- address the message is received from        
        '''
        self.manager.handle(data, addr)     


    def _create_binarymsg(self, path, data):
        """create an OSC message in binary format 

        Keyword arguments:
        path -- the path (identifier) of the osc message
        data -- the data of the message

        return: the osc message in binary format
        """
        m = osccore.OSCMessage()
        m.setAddress(path)

        if len(data) != 0:
            for x in data:  
                m.append(x)

        return m.getBinary()


    def send(self, to, path, data):
        """send an osc message to the address specified
        
        Keyword arguments:
        to -- address of receiver in the form (ipaddr, bundle)
        path -- the path of the osc message
        data -- the data of the message
        """        
        ### resolve host? [a,b,host] = socket.gethostbyaddr(to[0])
        msg = self._create_binarymsg(path, data)
        try:        
            self.iosock.sendto(msg, (to[0],to[1]))         
        except socket.error:
            cla, exc, trbk = sys.exc_info()
            try:
                excArgs = exc.__dict__["args"]
            except KeyError:
                excArgs = "<no args>"
            logging.error('error '+str(excArgs))

    def createbundle(self):
        """create the header of a bundle of OSC messages"""
        b = osccore.OSCMessage()
        b.setAddress("")
        b.append("#bundle")
        b.append(0)
        b.append(0)
        return b

    def appendbundle(self, bundle, path, data):
        """append osc message to the bundle
        
        Keyword arguments:
        bundle -- the bundle to which you want to append a message
        path -- the path of the OSC message
        data -- the data of the message
        """
        msg = self._create_binarymsg(path, data)
        bundle.append(msg, 'b')


    def sendbundle(self, to, bundle):
        """send bundle to the address specified
        
        Keyword arguments:
        to -- address of receiver in the form (ipaddr, bundle)
        bundle -- the bundle to send
        """
        try:
            self.iosock.sendto(bundle.message, to)
        except socket.error:
            cla, exc, trbk = sys.exc_info()
            try:
                excArgs = exc.__dict__["args"]
            except KeyError:
                excArgs = "<no args>"
            logging.error('error '+str(excArgs))