pyliblo-0.10.0/ 0000775 0001750 0001750 00000000000 12513144230 012577 5 ustar das das 0000000 0000000 pyliblo-0.10.0/doc/ 0000775 0001750 0001750 00000000000 12513144230 013344 5 ustar das das 0000000 0000000 pyliblo-0.10.0/doc/theme/ 0000775 0001750 0001750 00000000000 12513144230 014446 5 ustar das das 0000000 0000000 pyliblo-0.10.0/doc/theme/pydoctheme/ 0000775 0001750 0001750 00000000000 12513144230 016607 5 ustar das das 0000000 0000000 pyliblo-0.10.0/doc/theme/pydoctheme/static/ 0000775 0001750 0001750 00000000000 12513144230 020076 5 ustar das das 0000000 0000000 pyliblo-0.10.0/doc/theme/pydoctheme/static/pydoctheme.css 0000644 0001750 0001750 00000005145 12501131656 022761 0 ustar das das 0000000 0000000 @import url("default.css");
body {
background-color: white;
margin-left: 1em;
margin-right: 1em;
}
div.related {
margin-bottom: 1.2em;
padding: 0.5em 0;
border-top: 1px solid #ccc;
margin-top: 0.5em;
}
div.related a:hover {
color: #0095C4;
}
div.related:first-child {
border-top: 0;
border-bottom: 1px solid #ccc;
}
div.sphinxsidebar {
background-color: #eeeeee;
border-radius: 5px;
line-height: 130%;
font-size: smaller;
}
div.sphinxsidebar h3, div.sphinxsidebar h4 {
margin-top: 1.5em;
}
div.sphinxsidebarwrapper > h3:first-child {
margin-top: 0.2em;
}
div.sphinxsidebarwrapper > ul > li > ul > li {
margin-bottom: 0.4em;
}
div.sphinxsidebar a:hover {
color: #0095C4;
}
div.sphinxsidebar input {
font-family: 'Lucida Grande',Arial,sans-serif;
border: 1px solid #999999;
font-size: smaller;
border-radius: 3px;
}
div.sphinxsidebar input[type=text] {
max-width: 150px;
}
div.body {
padding: 0 0 0 1.2em;
}
div.body p {
line-height: 140%;
}
div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 {
margin: 0;
border: 0;
padding: 0.3em 0;
}
div.body hr {
border: 0;
background-color: #ccc;
height: 1px;
}
div.body pre {
border-radius: 3px;
border: 1px solid #ac9;
}
div.body div.admonition, div.body div.impl-detail {
border-radius: 3px;
}
div.body div.impl-detail > p {
margin: 0;
}
div.body div.seealso {
border: 1px solid #dddd66;
}
div.body a {
color: #00608f;
}
div.body a:visited {
color: #30306f;
}
div.body a:hover {
color: #00B0E4;
}
tt, pre {
font-family: monospace, sans-serif;
font-size: 96.5%;
}
div.body tt {
border-radius: 3px;
}
div.body tt.descname {
font-size: 120%;
}
div.body tt.xref, div.body a tt {
font-weight: normal;
}
.deprecated {
border-radius: 3px;
}
table.docutils {
border: 1px solid #ddd;
min-width: 20%;
border-radius: 3px;
margin-top: 10px;
margin-bottom: 10px;
}
table.docutils td, table.docutils th {
border: 1px solid #ddd !important;
border-radius: 3px;
}
table p, table li {
text-align: left !important;
}
table.docutils th {
background-color: #eee;
padding: 0.3em 0.5em;
}
table.docutils td {
background-color: white;
padding: 0.3em 0.5em;
}
table.footnote, table.footnote td {
border: 0 !important;
}
div.footer {
line-height: 150%;
margin-top: -2em;
text-align: right;
width: auto;
margin-right: 10px;
}
div.footer a:hover {
color: #0095C4;
}
.refcount {
color: #060;
}
.stableabi {
color: #229;
}
pyliblo-0.10.0/doc/theme/pydoctheme/theme.conf 0000644 0001750 0001750 00000001023 12501131656 020557 0 ustar das das 0000000 0000000 [theme]
inherit = default
stylesheet = pydoctheme.css
pygments_style = sphinx
[options]
bodyfont = 'Lucida Grande', Arial, sans-serif
headfont = 'Lucida Grande', Arial, sans-serif
footerbgcolor = white
footertextcolor = #555555
relbarbgcolor = white
relbartextcolor = #666666
relbarlinkcolor = #444444
sidebarbgcolor = white
sidebartextcolor = #444444
sidebarlinkcolor = #444444
bgcolor = white
textcolor = #222222
linkcolor = #0090c0
visitedlinkcolor = #00608f
headtextcolor = #1a1a1a
headbgcolor = white
headlinkcolor = #aaaaaa
pyliblo-0.10.0/doc/theme/nasophon/ 0000775 0001750 0001750 00000000000 12513144230 016273 5 ustar das das 0000000 0000000 pyliblo-0.10.0/doc/theme/nasophon/static/ 0000775 0001750 0001750 00000000000 12513144230 017562 5 ustar das das 0000000 0000000 pyliblo-0.10.0/doc/theme/nasophon/static/nasophon.css 0000644 0001750 0001750 00000007442 12501131656 022133 0 ustar das das 0000000 0000000 @import url("default.css");
body {
background-color: white;
margin-left: 1em;
margin-right: 1em;
width: 68em;
margin: 0 auto;
font-size: 95%;
}
div.related {
margin-bottom: 1.2em;
padding: 0.5em 0;
border-top: 1px solid #ccc;
margin-top: 0.5em;
}
div.related:first-child {
border-top: 0;
border-bottom: 1px solid #ccc;
}
div.sphinxsidebar {
background-color: #f4f4f4;
border-radius: 5px;
line-height: 110%;
}
div.sphinxsidebar ul,
div.sphinxsidebar ul ul {
list-style: none;
}
div.sphinxsidebar li {
margin-bottom: 0.5em;
}
div.sphinxsidebar li > ul {
margin-top: 0.5em;
}
div.sphinxsidebar h3, div.sphinxsidebar h4 {
margin-top: 1.5em;
}
div.sphinxsidebarwrapper > h3:first-child {
margin-top: 0.2em;
}
div.sphinxsidebarwrapper {
padding: 10px 10px 0px 10px;
}
div.sphinxsidebarwrapper > ul {
margin-left: 0px;
margin-right: 0px;
}
div.sphinxsidebar li.current {
background: #fff;
width: auto;
border-radius: 3px;
padding-bottom: 1px;
}
div.sphinxsidebar a.current {
font-weight: bold;
color: #fff;
background: #52576a;
border: 3px solid #52576a;
border-radius: 3px;
width: auto;
display: block;
}
div.sphinxsidebar input {
font-family: 'Lucida Grande',Arial,sans-serif;
border: 1px solid #999999;
font-size: smaller;
border-radius: 3px;
}
div.sphinxsidebar input[type=text] {
max-width: 150px;
}
div.body {
padding: 0 0.6em 0 2.2em;
}
div.body p {
line-height: 140%;
}
div.body h1 {
margin: 0 -0.4em 0 -0.6em;
border: 0;
color: #ffffff;
background: #52576a;
border-radius: 5px;
font-size: 150%;
}
div.body h1 a, div.body h1 a:visited {
color: #ffffff;
}
div.body h2 {
margin: 1.5em -0.45em 0 -0.65em;
border: 0;
color: #111111;
background: #eeeeee;
border-radius: 5px;
font-size: 135%;
}
div.body h3 {
font-weight: bold;
color: #444;
border: 0;
font-size: 105%;
padding-left: 1.25em;
margin-right: 0em;
padding-bottom: 0em;
margin-bottom: 0em;
}
div.body hr {
border: 0;
background-color: #ccc;
height: 1px;
}
div.body pre {
border-radius: 3px;
border: 1px solid #ac9;
}
div.body div.admonition, div.body div.impl-detail {
border-radius: 3px;
}
div.body div.impl-detail > p {
margin: 0;
}
div.body div.seealso {
border: 1px solid #dddd66;
}
div.body div.note {
background-color: #ffc;
border: 1px solid #dd6;
}
div.body div.note tt {
background: transparent;
}
div.body a {
color: #127;
}
div.body a:visited {
color: #127;
}
tt, pre {
font-family: monospace, sans-serif;
font-size: 93%;
}
div.body tt {
border-radius: 3px;
}
div.body tt.descname {
font-size: 100%;
}
div.body tt.xref, div.body a tt {
}
.deprecated {
border-radius: 3px;
}
table.docutils {
border: 1px solid #ddd;
min-width: 20%;
border-radius: 3px;
margin-top: 10px;
margin-bottom: 10px;
}
table.docutils td, table.docutils th {
border: 1px solid #ddd !important;
border-radius: 3px;
}
table p, table li {
text-align: left !important;
}
table.docutils th {
background-color: #eee;
padding: 0.3em 0.5em;
}
table.docutils td {
background-color: white;
padding: 0.3em 0.5em;
}
table.footnote, table.footnote td {
border: 0 !important;
}
div.footer {
line-height: 150%;
margin-top: -2em;
text-align: right;
width: auto;
margin-right: 10px;
}
/* fix space below last line in multi-line table cells */
td .line-block {
margin-bottom: 0;
}
/* No line break before first line of parameter description */
td.field-body strong+p {
display: inline;
}
/* No blank lines within parameter lists */
dd, dl {
margin-bottom: 0px;
}
a.headerlink {
float: right;
}
pyliblo-0.10.0/doc/theme/nasophon/theme.conf 0000644 0001750 0001750 00000000763 12501131656 020255 0 ustar das das 0000000 0000000 [theme]
inherit = default
stylesheet = nasophon.css
pygments_style = sphinx
[options]
bodyfont = 'Lucida Grande', Arial, sans-serif
headfont = 'Lucida Grande', Arial, sans-serif
footerbgcolor = white
footertextcolor = #555
relbarbgcolor = #fff
relbartextcolor = #666
relbarlinkcolor = #444
sidebarbgcolor = white
sidebartextcolor = #111
sidebarlinkcolor = #111
bgcolor = white
textcolor = #222
linkcolor = #127
visitedlinkcolor = #0127
headtextcolor = #111
headbgcolor = white
headlinkcolor = #aaa
pyliblo-0.10.0/doc/Makefile 0000644 0001750 0001750 00000000362 12501131656 015010 0 ustar das das 0000000 0000000 SPHINXOPTS =
SPHINXBUILD = sphinx-build
BUILDDIR = build
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(SPHINXOPTS) .
.PHONY: clean html
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
clean:
-rm -rf $(BUILDDIR)/*
pyliblo-0.10.0/doc/index.rst 0000644 0001750 0001750 00000005736 12501167470 015226 0 ustar das das 0000000 0000000 .. module:: liblo
##############################
pyliblo 0.10 API Documentation
##############################
Homepage: http://das.nasophon.de/pyliblo/
The latest version of this manual can be found at
http://dsacre.github.io/pyliblo/doc/.
For the most part, pyliblo is just a thin wrapper around
`liblo `_, which does
all the real work.
For questions not answered here, also see the
`liblo documentation `_
and the `OSC spec `_.
Module-level Functions
======================
.. autofunction:: send
.. autofunction:: time
OSC Server Classes
==================
.. autoclass:: Server
:no-members:
.. automethod:: __init__
.. automethod:: recv
.. automethod:: send
.. automethod:: add_method
.. automethod:: del_method
.. automethod:: register_methods
.. automethod:: add_bundle_handlers
.. autoattribute:: url
.. autoattribute:: port
.. autoattribute:: protocol
.. automethod:: fileno
.. automethod:: free
-------
.. autoclass:: ServerThread
:no-members:
.. automethod:: __init__
.. automethod:: start
.. automethod:: stop
.. autoclass:: make_method
.. automethod:: __init__
Utility Classes
===============
.. autoclass:: Address
:no-members:
.. automethod:: __init__
.. autoattribute:: url
.. autoattribute:: hostname
.. autoattribute:: port
.. autoattribute:: protocol
-------
.. autoclass:: Message
.. automethod:: __init__
.. autoclass:: Bundle
.. automethod:: __init__
-------
.. autoexception:: ServerError
.. autoexception:: AddressError
Mapping between OSC and Python data types
=========================================
When constructing a message, pyliblo automatically converts
arguments to an appropriate OSC data type.
To explicitly specify the OSC data type to be transmitted, pass a
``(typetag, data)`` tuple instead. Some types can't be unambiguously
recognized, so they can only be sent that way.
The mapping between OSC and Python data types is shown in the following table:
========= =============== ====================================================
typetag OSC data type Python data type
========= =============== ====================================================
``'i'`` int32 :class:`int`
``'h'`` int64 :class:`long` (Python 2.x), :class:`int` (Python 3.x)
``'f'`` float :class:`float`
``'d'`` double :class:`float`
``'c'`` char :class:`str` (single character)
``'s'`` string :class:`str`
``'S'`` symbol :class:`str`
``'m'`` midi :class:`tuple` of four :class:`int`\ s
``'t'`` timetag :class:`float`
``'T'`` true
``'F'`` false
``'N'`` nil
``'I'`` infinitum
``'b'`` blob :class:`list` of :class:`int`\ s (Python 2.x), :class:`bytes` (Python 3.x)
========= =============== ====================================================
pyliblo-0.10.0/doc/conf.py 0000644 0001750 0001750 00000004467 12501131656 014661 0 ustar das das 0000000 0000000 # -*- coding: utf-8 -*-
#
import sys, os
sys.path.insert(0, os.path.abspath('..'))
#extensions = ['sphinx.ext.autodoc', 'sphinxcontrib.fulltoc']
extensions = ['sphinx.ext.autodoc']
templates_path = ['templates']
html_theme_path = ['theme']
exclude_patterns = ['build']
source_suffix = '.rst'
master_doc = 'index'
project = u'pyliblo'
copyright = u'2007-2014, Dominic Sacré'
version = '0.10.0'
release = ''
html_theme = 'nasophon'
html_copy_source = False
pygments_style = 'sphinx'
add_module_names = False
autodoc_member_order = 'bysource'
autodoc_default_flags = ['members', 'undoc-members']
from sphinx.ext.autodoc import py_ext_sig_re
from sphinx.util.docstrings import prepare_docstring
from sphinx.domains.python import PyClassmember, PyObject, py_sig_re
def process_docstring(app, what, name, obj, options, lines):
"""
Remove leading function signatures from docstring.
"""
while len(lines) and py_ext_sig_re.match(lines[0]) is not None:
del lines[0]
def process_signature(app, what, name, obj,
options, signature, return_annotation):
"""
Replace function signature with those specified in the docstring.
"""
if hasattr(obj, '__doc__') and obj.__doc__ is not None:
lines = prepare_docstring(obj.__doc__)
siglines = []
for line in lines:
if py_ext_sig_re.match(line) is not None:
siglines.append(line)
else:
break
if len(siglines):
siglines[0] = siglines[0][siglines[0].index('('):]
return ('\n'.join(siglines), None)
return (signature, return_annotation)
# monkey-patch PyClassmember.handle_signature() to replace __init__
# with the class name.
handle_signature_orig = PyClassmember.handle_signature
def handle_signature(self, sig, signode):
if '__init__' in sig:
m = py_sig_re.match(sig)
name_prefix, name, arglist, retann = m.groups()
sig = sig.replace('__init__', name_prefix[:-1])
return handle_signature_orig(self, sig, signode)
PyClassmember.handle_signature = handle_signature
# prevent exception fields from collapsing
PyObject.doc_field_types[2].can_collapse = False
def setup(app):
app.connect('autodoc-process-docstring', process_docstring)
app.connect('autodoc-process-signature', process_signature)
pyliblo-0.10.0/scripts/ 0000775 0001750 0001750 00000000000 12513144230 014266 5 ustar das das 0000000 0000000 pyliblo-0.10.0/scripts/send_osc.1 0000644 0001750 0001750 00000001333 12343704354 016155 0 ustar das das 0000000 0000000 .TH send_osc 1
.SH NAME
send_osc \- Sends a single OSC message
.SH SYNOPSIS
.B send_osc
\fIport\fP \fIpath\fP [,\fItypes\fP] [\fIargs\fP...]
.SH DESCRIPTION
.B send_osc
sends an OSC message to the specified \fIport\fP (UDP port number, or any
other address string supported by liblo).
The message is delivered to \fIpath\fP.
If the first argument following the path starts with a comma, it's interpreted
as a type string, specifying the OSC data types to be used for sending the
message arguments.
Otherwise, send_osc automatically tries to use appropriate data types.
Valid integer and float values are sent as such, anything else is sent as a
string.
.SH AUTHOR
Dominic Sacre
.SH SEE ALSO
dump_osc(1)
pyliblo-0.10.0/scripts/dump_osc.py 0000755 0001750 0001750 00000004121 12406137264 016462 0 ustar das das 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# pyliblo - Python bindings for the liblo OSC library
#
# Copyright (C) 2007-2011 Dominic Sacré
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
import sys
import liblo
class DumpOSC:
def blob_to_hex(self, b):
return " ".join([ (hex(v/16).upper()[-1] + hex(v%16).upper()[-1]) for v in b ])
def callback(self, path, args, types, src):
write = sys.stdout.write
## print source
#write("from " + src.get_url() + ": ")
# print path
write(path + " ,")
# print typespec
write(types)
# loop through arguments and print them
for a, t in zip(args, types):
write(" ")
if t == None:
#unknown type
write("[unknown type]")
elif t == 'b':
# it's a blob
write("[" + self.blob_to_hex(a) + "]")
else:
# anything else
write(str(a))
write('\n')
def __init__(self, port = None):
# create server object
try:
self.server = liblo.Server(port)
except liblo.ServerError as err:
sys.exit(str(err))
print("listening on URL: " + self.server.get_url())
# register callback function for all messages
self.server.add_method(None, None, self.callback)
def run(self):
# just loop and dispatch messages every 10ms
while True:
self.server.recv(10)
if __name__ == '__main__':
# display help
if len(sys.argv) == 1 or sys.argv[1] in ("-h", "--help"):
sys.exit("Usage: " + sys.argv[0] + " port")
# require one argument (port number)
if len(sys.argv) < 2:
sys.exit("please specify a port or URL")
app = DumpOSC(sys.argv[1])
try:
app.run()
except KeyboardInterrupt:
del app
pyliblo-0.10.0/scripts/dump_osc.1 0000644 0001750 0001750 00000000501 12343704354 016165 0 ustar das das 0000000 0000000 .TH dump_osc 1
.SH NAME
dump_osc \- Prints incoming OSC messages
.SH SYNOPSIS
.B dump_osc
\fIport\fP
.SH DESCRIPTION
.B dump_osc
prints all OSC messages received on \fIport\fP (UDP port number, or any other
address string supported by liblo).
.SH AUTHOR
Dominic Sacre
.SH SEE ALSO
send_osc(1)
pyliblo-0.10.0/scripts/send_osc.py 0000755 0001750 0001750 00000003345 12406136626 016456 0 ustar das das 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# pyliblo - Python bindings for the liblo OSC library
#
# Copyright (C) 2007-2011 Dominic Sacré
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
import sys
import liblo
def make_message_auto(path, *args):
msg = liblo.Message(path)
for a in args:
try: v = int(a)
except ValueError:
try: v = float(a)
except ValueError:
v = a
msg.add(v)
return msg
def make_message_manual(path, types, *args):
if len(types) != len(args):
sys.exit("length of type string doesn't match number of arguments")
msg = liblo.Message(path)
try:
for a, t in zip(args, types):
msg.add((t, a))
except Exception as e:
sys.exit(str(e))
return msg
if __name__ == '__main__':
# display help
if len(sys.argv) == 1 or sys.argv[1] in ("-h", "--help"):
sys.exit("Usage: " + sys.argv[0] + " port path [,types] [args...]")
# require at least two arguments (target port/url and message path)
if len(sys.argv) < 2:
sys.exit("please specify a port or URL")
if len(sys.argv) < 3:
sys.exit("please specify a message path")
if len(sys.argv) > 3 and sys.argv[3].startswith(','):
msg = make_message_manual(sys.argv[2], sys.argv[3][1:], *sys.argv[4:])
else:
msg = make_message_auto(*sys.argv[2:])
try:
liblo.send(sys.argv[1], msg)
except IOError as e:
sys.exit(str(e))
else:
sys.exit(0)
pyliblo-0.10.0/PKG-INFO 0000664 0001750 0001750 00000000401 12513144230 013667 0 ustar das das 0000000 0000000 Metadata-Version: 1.0
Name: pyliblo
Version: 0.10.0
Summary: Python bindings for the liblo OSC library
Home-page: http://das.nasophon.de/pyliblo/
Author: Dominic Sacré
Author-email: dominic.sacre@gmx.de
License: LGPL
Description: UNKNOWN
Platform: UNKNOWN
pyliblo-0.10.0/pyliblo.egg-info/ 0000775 0001750 0001750 00000000000 12513144230 015743 5 ustar das das 0000000 0000000 pyliblo-0.10.0/pyliblo.egg-info/PKG-INFO 0000664 0001750 0001750 00000000401 12513144227 017041 0 ustar das das 0000000 0000000 Metadata-Version: 1.0
Name: pyliblo
Version: 0.10.0
Summary: Python bindings for the liblo OSC library
Home-page: http://das.nasophon.de/pyliblo/
Author: Dominic Sacré
Author-email: dominic.sacre@gmx.de
License: LGPL
Description: UNKNOWN
Platform: UNKNOWN
pyliblo-0.10.0/pyliblo.egg-info/not-zip-safe 0000664 0001750 0001750 00000000001 12513144227 020177 0 ustar das das 0000000 0000000
pyliblo-0.10.0/pyliblo.egg-info/SOURCES.txt 0000664 0001750 0001750 00000001174 12513144230 017632 0 ustar das das 0000000 0000000 COPYING
MANIFEST.in
NEWS
README
setup.py
doc/Makefile
doc/conf.py
doc/index.rst
doc/theme/nasophon/theme.conf
doc/theme/nasophon/static/nasophon.css
doc/theme/pydoctheme/theme.conf
doc/theme/pydoctheme/static/pydoctheme.css
examples/example_client.py
examples/example_server.py
examples/example_server_deco.py
examples/test_server_thread.py
pyliblo.egg-info/PKG-INFO
pyliblo.egg-info/SOURCES.txt
pyliblo.egg-info/dependency_links.txt
pyliblo.egg-info/not-zip-safe
pyliblo.egg-info/top_level.txt
scripts/dump_osc.1
scripts/dump_osc.py
scripts/send_osc.1
scripts/send_osc.py
src/liblo.pxd
src/liblo.pyx
test/__init__.py
test/test_liblo.py pyliblo-0.10.0/pyliblo.egg-info/top_level.txt 0000664 0001750 0001750 00000000006 12513144227 020477 0 ustar das das 0000000 0000000 liblo
pyliblo-0.10.0/pyliblo.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 12513144227 022017 0 ustar das das 0000000 0000000
pyliblo-0.10.0/setup.cfg 0000664 0001750 0001750 00000000073 12513144230 014420 0 ustar das das 0000000 0000000 [egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
pyliblo-0.10.0/setup.py 0000775 0001750 0001750 00000003342 12513140145 014317 0 ustar das das 0000000 0000000 #!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
from distutils.command.build_scripts import build_scripts
from distutils import util, log
try:
from setuptools import setup, Extension
args = {
'test_suite': 'test',
'zip_safe': False,
}
except ImportError:
from distutils.core import setup, Extension
args = {}
from Cython.Distutils import build_ext
class build_scripts_rename(build_scripts):
def copy_scripts(self):
build_scripts.copy_scripts(self)
# remove the .py extension from scripts
for s in self.scripts:
f = util.convert_path(s)
before = os.path.join(self.build_dir, os.path.basename(f))
after = os.path.splitext(before)[0]
log.info("renaming %s -> %s" % (before, after))
os.rename(before, after)
cmdclass = {
'build_scripts': build_scripts_rename,
'build_ext': build_ext,
}
ext_modules = [
Extension(
'liblo',
['src/liblo.pyx'],
extra_compile_args = [
'-fno-strict-aliasing',
'-Werror-implicit-function-declaration',
'-Wfatal-errors',
],
libraries = ['lo'],
)
]
setup(
name = 'pyliblo',
version = '0.10.0',
author = 'Dominic Sacré',
author_email = 'dominic.sacre@gmx.de',
url = 'http://das.nasophon.de/pyliblo/',
description = 'Python bindings for the liblo OSC library',
license = 'LGPL',
scripts = [
'scripts/send_osc.py',
'scripts/dump_osc.py',
],
data_files = [
('share/man/man1', [
'scripts/send_osc.1',
'scripts/dump_osc.1',
]),
],
cmdclass = cmdclass,
ext_modules = ext_modules,
**args
)
pyliblo-0.10.0/README 0000644 0001750 0001750 00000001177 12501167470 013473 0 ustar das das 0000000 0000000 pyliblo - Python bindings for the liblo OSC library
Copyright (C) 2007-2015 Dominic Sacré
http://das.nasophon.de/pyliblo/
Requirements:
=============
* Python >= 2.6 (also works with 3.x) [http://www.python.org/]
* Cython [http://www.cython.org/]
* liblo >= 0.27 [http://liblo.sourceforge.net/]
Installation:
=============
./setup.py build
./setup.py install
This will install both the python module and the send_osc/dump_osc scripts.
Documentation:
==============
See http://dsacre.github.io/pyliblo/doc/ for API documentation.
The 'examples' directory in the source tree contains some example code.
pyliblo-0.10.0/src/ 0000775 0001750 0001750 00000000000 12513144230 013366 5 ustar das das 0000000 0000000 pyliblo-0.10.0/src/liblo.pyx 0000644 0001750 0001750 00000077777 12501173354 015266 0 ustar das das 0000000 0000000 #
# pyliblo - Python bindings for the liblo OSC library
#
# Copyright (C) 2007-2015 Dominic Sacré
#
# This program 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.
#
__version__ = '0.10.0'
from cpython cimport PY_VERSION_HEX
cdef extern from 'Python.h':
void PyEval_InitThreads()
from libc.stdlib cimport malloc, free
from libc.math cimport modf
from libc.stdint cimport int32_t, int64_t
from liblo cimport *
import inspect as _inspect
import weakref as _weakref
class _weakref_method:
"""
Weak reference to a function, including support for bound methods.
"""
__slots__ = ('_func', 'obj')
def __init__(self, f):
if _inspect.ismethod(f):
if PY_VERSION_HEX >= 0x03000000:
self._func = f.__func__
self.obj = _weakref.ref(f.__self__)
else:
self._func = f.im_func
self.obj = _weakref.ref(f.im_self)
else:
self._func = f
self.obj = None
@property
def func(self):
if self.obj:
return self._func.__get__(self.obj(), self.obj().__class__)
else:
return self._func
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
class struct:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
cdef str _decode(s):
# convert to standard string type, depending on python version
if PY_VERSION_HEX >= 0x03000000 and isinstance(s, bytes):
return s.decode()
else:
return s
cdef bytes _encode(s):
# convert unicode to bytestring
if isinstance(s, unicode):
return s.encode()
else:
return s
# forward declarations
cdef class _ServerBase
cdef class Address
cdef class Message
cdef class Bundle
# liblo protocol constants
UDP = LO_UDP
TCP = LO_TCP
UNIX = LO_UNIX
################################################################################
# timetag
################################################################################
cdef lo_timetag _double_to_timetag(double f):
cdef lo_timetag tt
cdef double intr, frac
frac = modf(f, &intr)
tt.sec = intr
tt.frac = (frac * 4294967296.0)
return tt
cdef double _timetag_to_double(lo_timetag tt):
return tt.sec + ((tt.frac) / 4294967296.0)
def time():
"""
Return the current time as a floating point number (seconds since
January 1, 1900).
"""
cdef lo_timetag tt
lo_timetag_now(&tt)
return _timetag_to_double(tt)
################################################################################
# send
################################################################################
cdef _send(target, _ServerBase src, args):
cdef lo_server from_server
cdef Address target_address
cdef int r
# convert target to Address object, if necessary
if isinstance(target, Address):
target_address = target
elif isinstance(target, tuple):
# unpack tuple
target_address = Address(*target)
else:
target_address = Address(target)
# 'from' parameter is NULL if no server was specified
from_server = src._server if src else NULL
if isinstance(args[0], (Message, Bundle)):
# args is already a list of Messages/Bundles
packets = args
else:
# make a single Message from all arguments
packets = [Message(*args)]
# send all packets
for p in packets:
if isinstance(p, Message):
message = p
r = lo_send_message_from(target_address._address,
from_server,
message._path,
message._message)
else:
bundle = p
r = lo_send_bundle_from(target_address._address,
from_server,
bundle._bundle)
if r == -1:
raise IOError("sending failed: %s" %
lo_address_errstr(target_address._address))
def send(target, *args):
"""
send(target, *messages)
send(target, path, *args)
Send messages to the the given target, without requiring a server.
Arguments may be one or more :class:`Message` or :class:`Bundle` objects,
or a single message given by its path and optional arguments.
:param target:
the address to send the message to; an :class:`Address` object,
a port number, a ``(hostname, port)`` tuple, or a URL.
:param messages:
one or more objects of type :class:`Message` or :class:`Bundle`.
:param path:
the path of the message to be sent.
:raises AddressError:
if the given target is invalid.
:raises IOError:
if the message couldn't be sent.
"""
_send(target, None, args)
################################################################################
# Server
################################################################################
class ServerError(Exception):
"""
Raised when creating a liblo OSC server fails.
"""
def __init__(self, num, msg, where):
self.num = num
self.msg = msg
self.where = where
def __str__(self):
s = "server error %d" % self.num
if self.where: s += " in %s" % self.where
s += ": %s" % self.msg
return s
cdef int _msg_callback(const_char *path, const_char *types, lo_arg **argv,
int argc, lo_message msg, void *cb_data) with gil:
cdef int i
cdef char t
cdef unsigned char *ptr
cdef uint32_t size, j
args = []
for i from 0 <= i < argc:
t = types[i]
if t == 'i': v = argv[i].i
elif t == 'h': v = argv[i].h
elif t == 'f': v = argv[i].f
elif t == 'd': v = argv[i].d
elif t == 'c': v = chr(argv[i].c)
elif t == 's': v = _decode(&argv[i].s)
elif t == 'S': v = _decode(&argv[i].s)
elif t == 'T': v = True
elif t == 'F': v = False
elif t == 'N': v = None
elif t == 'I': v = float('inf')
elif t == 'm': v = (argv[i].m[0], argv[i].m[1], argv[i].m[2], argv[i].m[3])
elif t == 't': v = _timetag_to_double(argv[i].t)
elif t == 'b':
if PY_VERSION_HEX >= 0x03000000:
v = bytes(lo_blob_dataptr(argv[i]))
else:
# convert binary data to python list
v = []
ptr = lo_blob_dataptr(argv[i])
size = lo_blob_datasize(argv[i])
for j from 0 <= j < size:
v.append(ptr[j])
else:
v = None # unhandled data type
args.append(v)
cdef char *url = lo_address_get_url(lo_message_get_source(msg))
src = Address(url)
free(url)
cb =