Commit 5a87d809 authored by Frank Scholz's avatar Frank Scholz
Browse files

Initial import.

[[
This repository was converted from Subversion to Git on 2013-08-10 by
Hartmut Goebel <h.goebel@crazy-compilers.com>. Here and elsewhere,
conversion notes are enclosed in double square brackets.

The original Coherence multi-project repository has carefully been
split into separate repositories for each sub-project. Changes from
the intermediate multi-project Git-repository have been incorporated,
too.

Obvious garbage has been removed, esp. build-artefacts like .aux
files, .egg-info directories, .pyc files, tar files. Junk commits
generated by e.g. remote moves have been removed, commit references
have been mapped into a uniform VCS-independent syntax, and some
comments edited into summary-plus-continuation form.
]]
parents
#! /usr/bin/python
# -*- coding: utf-8 -*-
# Licensed under the MIT license
# http://opensource.org/licenses/mit-license.php
# Copyright 2009, Frank Scholz <fs@beebits.net>
""" Cadre is a PictureFrame application based on
the Coherence DLNA/UPnP framework
"""
import os, sys
import string
from twisted.python import usage, text
from cadre import __version__
from coherence.extern.simple_config import Config
"""
thankfully taken from twisted.scripts._twistd_unix.py
"""
def daemonize():
# See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16
if os.fork(): # launch child and...
os._exit(0) # kill off parent
os.setsid()
if os.fork(): # launch child and...
os._exit(0) # kill off parent again.
os.umask(077)
null=os.open('/dev/null', os.O_RDWR)
for i in range(3):
try:
os.dup2(null, i)
except OSError, e:
if e.errno != errno.EBADF:
raise
os.close(null)
"""
taken with minor adjustments from twisted.python.text.py
"""
def greedyWrap(inString, width=80):
"""Given a string and a column width, return a list of lines.
Caveat: I'm use a stupid greedy word-wrapping
algorythm. I won't put two spaces at the end
of a sentence. I don't do full justification.
And no, I've never even *heard* of hypenation.
"""
outLines = []
#eww, evil hacks to allow paragraphs delimited by two \ns :(
if inString.find('\n\n') >= 0:
paragraphs = inString.split('\n\n')
for para in paragraphs:
outLines.extend(greedyWrap(para, width) + [''])
return outLines
inWords = inString.split()
column = 0
ptr_line = 0
while inWords:
column = column + len(inWords[ptr_line])
ptr_line = ptr_line + 1
if (column > width):
if ptr_line == 1:
# This single word is too long, it will be the whole line.
pass
else:
# We've gone too far, stop the line one word back.
ptr_line = ptr_line - 1
(l, inWords) = (inWords[0:ptr_line], inWords[ptr_line:])
outLines.append(string.join(l,' '))
ptr_line = 0
column = 0
elif not (len(inWords) > ptr_line):
# Clean up the last bit.
outLines.append(' '.join(inWords))
del inWords[:]
else:
# Space
column = column + 1
# next word
return outLines
"""
taken with minor adjustments from twisted.python.usage.py
"""
def docMakeChunks(optList, width=80):
"""
Makes doc chunks for option declarations.
Takes a list of dictionaries, each of which may have one or more
of the keys 'long', 'short', 'doc', 'default', 'optType'.
Returns a list of strings.
The strings may be multiple lines,
all of them end with a newline.
"""
# XXX: sanity check to make sure we have a sane combination of keys.
maxOptLen = 0
for opt in optList:
optLen = len(opt.get('long', ''))
if optLen:
if opt.get('optType', None) == "parameter":
# these take up an extra character
optLen = optLen + 1
maxOptLen = max(optLen, maxOptLen)
colWidth1 = maxOptLen + len(" -s, -- ")
colWidth2 = width - colWidth1
# XXX - impose some sane minimum limit.
# Then if we don't have enough room for the option and the doc
# to share one line, they can take turns on alternating lines.
colFiller1 = " " * colWidth1
optChunks = []
seen = {}
for opt in optList:
if opt.get('short', None) in seen or opt.get('long', None) in seen:
continue
for x in opt.get('short', None), opt.get('long', None):
if x is not None:
seen[x] = 1
optLines = []
comma = " "
if opt.get('short', None):
short = "-%c" % (opt['short'],)
else:
short = ''
if opt.get('long', None):
long = opt['long']
if opt.get("optType", None) == "parameter":
long = long + '='
long = "%-*s" % (maxOptLen, long)
if short:
comma = ","
else:
long = " " * (maxOptLen + len('--'))
if opt.get('optType', None) == 'command':
column1 = ' %s ' % long
else:
column1 = " %2s%c --%s " % (short, comma, long)
if opt.get('doc', ''):
doc = opt['doc'].strip()
else:
doc = ''
if (opt.get("optType", None) == "parameter") \
and not (opt.get('default', None) is None):
doc = "%s [default: %s]" % (doc, opt['default'])
if (opt.get("optType", None) == "parameter") \
and opt.get('dispatch', None) is not None:
d = opt['dispatch']
if isinstance(d, usage.CoerceParameter) and d.doc:
doc = "%s. %s" % (doc, d.doc)
if doc:
column2_l = greedyWrap(doc, colWidth2)
else:
column2_l = ['']
optLines.append("%s%s\n" % (column1, column2_l.pop(0)))
for line in column2_l:
optLines.append("%s%s\n" % (colFiller1, line))
optChunks.append(''.join(optLines))
return optChunks
usage.docMakeChunks = docMakeChunks
def setConfigFile():
def findConfigDir():
try:
configDir = os.path.expanduser('~')
except:
configDir = os.getcwd()
return configDir
return os.path.join( findConfigDir(), '.cadre')
class Options(usage.Options):
optFlags = [['daemon','d', 'daemonize'],
['noconfig', None, 'ignore any configfile found'],
['version','v', 'print out version']
]
optParameters = [['configfile', 'c', setConfigFile(), 'configfile'],
['logfile', 'l', None, 'logfile'],
['option', 'o', None, 'activate option'],
]
def __init__(self):
usage.Options.__init__(self)
self['options'] = {}
def opt_version(self):
print "Cadre version:", __version__
sys.exit(0)
def opt_help(self):
sys.argv.remove('--help')
print self.__str__()
sys.exit(0)
def opt_option(self,option):
try:
key,value = option.split(':')
self['options'][key] = value
except:
pass
def main(config):
from cadre.base import Cadre
c = Cadre(config)
if __name__ == '__main__':
options = Options()
try:
options.parseOptions()
except usage.UsageError, errortext:
print '%s: %s' % (sys.argv[0], errortext)
print '%s: Try --help for usage details.' % (sys.argv[0])
sys.exit(0)
if options['daemon'] == 1:
daemonize()
config = {}
config['logging'] = {}
if options['noconfig'] != 1:
try:
config = Config(options['configfile'],root='config').config
except IOError:
print "no config file %r found" % options['configfile']
pass
for k,v in options['options'].items():
config[k] = v
if options['logfile'] != None:
config['logging'] = {}
config['logging']['logfile'] = options['logfile']
if options['daemon'] == 1:
if options['logfile'] == None:
config.get('logging').get('level','none')
try:
from twisted.internet import glib2reactor
glib2reactor.install()
except AssertionError:
print "error installing glib2reactor"
from twisted.internet import reactor
reactor.callWhenRunning(main, config)
reactor.run()
import platform
__version_info__ = (0,0,3)
__version__ = '%d.%d.%d' % (__version_info__[0],__version_info__[1],__version_info__[2],)
# Licensed under the MIT license
# http://opensource.org/licenses/mit-license.php
# Copyright 2009 Frank Scholz <coherence@beebits.net>
# Twisted
from twisted.internet import reactor
# Coherence
from coherence.base import Coherence
from coherence.upnp.devices.media_renderer import MediaRenderer
from coherence.upnp.core import DIDLLite
import coherence.extern.louie as louie
from coherence import log
from cadre.scribbling import Canvas
from cadre.renderer import PictureRenderer
class Cadre(log.Loggable):
logCategory = 'renderer'
def __init__(self, fullscreen=1):
self.canvas = Canvas(fullscreen)
config = {}
config['logmode'] = 'error'
config['controlpoint'] = 'yes'
louie.connect(self.media_server_found, 'Coherence.UPnP.ControlPoint.MediaServer.detected', louie.Any)
louie.connect(self.media_server_removed, 'Coherence.UPnP.ControlPoint.MediaServer.removed', louie.Any)
self.coherence = Coherence(config)
kwargs = {'version':1,
'no_thread_needed':True}
name = 'Cadre - Coherence Picture-Frame'
if name:
kwargs['name'] = name
self.canvas.set_title(name)
kwargs['controller'] = self
self.renderer = MediaRenderer(self.coherence,PictureRenderer,**kwargs)
def quit(self):
reactor.stop()
def media_server_found(self, client,udn):
print "media_server_found", client.device.get_friendly_name()
def media_server_removed(self, udn):
print "media_server_removed", udn
\ No newline at end of file
This diff is collapsed.
# Licensed under the MIT license
# http://opensource.org/licenses/mit-license.php
# Copyright 2009 Frank Scholz <coherence@beebits.net>
import os
# Twisted
from twisted.internet import reactor
# Clutter
import clutter
from clutter import cogl
class TextureReflection (clutter.Clone):
# taken from the reflection.py example of pyclutter
"""
TextureReflection (clutter.Clone)
An actor that paints a reflection of a texture. The
height of the reflection can be set in pixels. If set
to a negative value, the same size of the parent texture
will be used.
The size of the TextureReflection actor is by default
the same size of the parent texture.
"""
__gtype_name__ = 'TextureReflection'
def __init__ (self, parent):
clutter.Clone.__init__(self, parent)
self._reflection_height = -1
def set_reflection_height (self, height):
self._reflection_height = height
self.queue_redraw()
def get_reflection_height (self):
return self._reflection_height
def do_paint (self):
parent = self.get_source()
if (parent is None):
return
# get the cogl handle for the parent texture
cogl_tex = parent.get_cogl_texture()
if not cogl_tex:
return
(width, height) = self.get_size()
# clamp the reflection height if needed
r_height = self._reflection_height
if (r_height < 0 or r_height > height):
r_height = height
rty = float(r_height / height)
opacity = self.get_paint_opacity()
# the vertices are a 6-tuple composed of:
# x, y, z: coordinates inside Clutter modelview
# tx, ty: texture coordinates
# color: a clutter.Color for the vertex
#
# to paint the reflection of the parent texture we paint
# the texture using four vertices in clockwise order, with
# the upper left and the upper right at full opacity and
# the lower right and lower left and 0 opacity; OpenGL will
# do the gradient for us
color1 = cogl.color_premultiply((1, 1, 1, opacity/255.))
color2 = cogl.color_premultiply((1, 1, 1, 0))
vertices = ( \
( 0, 0, 0, 0.0, 1.0, color1), \
(width, 0, 0, 1.0, 1.0, color1), \
(width, r_height, 0, 1.0, 1.0-rty, color2), \
( 0, r_height, 0, 0.0, 1.0-rty, color2), \
)
cogl.push_matrix()
cogl.set_source_texture(cogl_tex)
cogl.polygon(vertices=vertices, use_color=True)
cogl.pop_matrix()
class Canvas(object):
def __init__(self, fullscreen=1):
self.fullscreen = fullscreen
self.stage = clutter.Stage()
if self.fullscreen == 1:
self.stage.set_fullscreen(True)
else:
self.stage.set_size(1200, 800)
size = self.stage.get_size()
print "%r" % (size,)
display_width = size[0]*0.7
display_height = size[1]*0.7
self.stage.set_color(clutter.Color(0,0,0))
if self.fullscreen == 1:
self.stage.connect('button-press-event', lambda x,y: reactor.stop())
self.stage.connect('destroy', lambda x: reactor.stop())
group = clutter.Group()
self.stage.add(group)
self.texture = clutter.Texture()
self.texture.set_keep_aspect_ratio(True)
self.texture.set_size(display_width,display_height)
reflect = TextureReflection(self.texture)
reflect.set_reflection_height(display_height/3)
reflect.set_opacity(100)
x_pos = float((self.stage.get_width() - self.texture.get_width()) / 2)
group.add(self.texture, reflect)
group.set_position(x_pos, 20.0)
reflect.set_position(0.0, (self.texture.get_height() + 20))
self.stage.show()
def set_title(self,title):
self.stage.set_title(title)
def show_image(self,image,title=''):
#FIXME - we have the image as data already, there has to be
# a better way to get it into the texture
from tempfile import mkstemp
fp,filename = mkstemp()
os.write(fp,image)
os.close(fp)
#self.texture.set_load_async(True)
self.texture.set_from_file(filename=filename)
self.set_title(title)
os.unlink(filename)
\ No newline at end of file
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
from cadre import __version__
packages = find_packages()
setup(
name="Cadre",
version=__version__,
description="""Cadre - a PictureFrame application based on the Coherence DLNA/UPnP framework""",
author="Frank Scholz",
author_email='fs@beebits.net',
packages=packages,
include_package_data = True,
zipfile = None,
scripts = ['bin/cadre'],
url = "http://coherence-project.org",
package_data = {
'cadre': []
},
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment