forked from Blinkenbunt/blup
Fr3deric
7 years ago
33 changed files with 0 additions and 2060 deletions
@ -1,152 +0,0 @@
@@ -1,152 +0,0 @@
|
||||
|
||||
SERVER_URL="http://volta:8080/do_request"; |
||||
UPLOAD_URL="http://volta:8080/do_upload"; |
||||
|
||||
function refreshStatus() { |
||||
|
||||
$.ajax({ |
||||
url: SERVER_URL, |
||||
dataType: "json", |
||||
type: "POST", |
||||
data: JSON.stringify({"cmd": "getcurrentfilename"}), |
||||
success: function(data) { |
||||
$.blayerwebif.newFilename = data.currentfilename; |
||||
if($.blayerwebif.oldFilename == $.blayerwebif.newFilename) |
||||
return; |
||||
$.blayerwebif.oldFilename = $.blayerwebif.newFilename; |
||||
|
||||
$("#tagtable").empty(); |
||||
$("#tagtable").append("<tr><td>filename</td><td>"+$.blayerwebif.newFilename+"</td></tr"); |
||||
$.ajax({ |
||||
url: SERVER_URL, |
||||
dataType: "json", |
||||
type: "POST", |
||||
data: JSON.stringify({"cmd": "getcurrentfileinfo"}), |
||||
success: function(data) { |
||||
$.each(data.currentfileinfo, function(key, value) { |
||||
$("#tagtable").append("<tr><td>"+key+"</td><td>"+value+"</td></tr"); |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
} |
||||
}); |
||||
|
||||
|
||||
|
||||
|
||||
}; |
||||
|
||||
function refreshFilenames() { |
||||
$.ajax({ |
||||
url: SERVER_URL, |
||||
dataType: "json", |
||||
type: "POST", |
||||
data: JSON.stringify({"cmd": "getallfilenames"}), |
||||
success: function(data) { |
||||
$("#filenames").empty(); |
||||
$.each(data.allfilenames, function(key, value) { |
||||
//alert("<li><a href=\"#\" onClick=\"playNext(\\\""+value+"\\\")\">"+value+"</a></li>");
|
||||
$("#filenames").append("<li><a href=\"#\" class=\"playNextLink\">"+value+"</a></li>"); |
||||
|
||||
}); |
||||
$("#animationcount").text(data.allfilenames.length); |
||||
$(".playNextLink").click(function() { |
||||
linkNode = this; |
||||
$.ajax({ |
||||
url: SERVER_URL, |
||||
dataType: "json", |
||||
type: "POST", |
||||
data: JSON.stringify({"cmd": "playnext", "filename": $(this).text()}), |
||||
success: function(data) { |
||||
if(data.playnext == "ok") |
||||
item = $("<span class=\"notificationtext\">queued...</span>"); |
||||
else |
||||
item = $("<span class=\"notificationtext\">queue full :(</span>"); |
||||
|
||||
$(linkNode).after(item); |
||||
$(item).delay(1000).fadeOut("slow"); |
||||
} |
||||
}); |
||||
}); |
||||
}, |
||||
}); |
||||
} |
||||
|
||||
function refreshStatusPeriodic() { |
||||
refreshStatus(); |
||||
setTimeout(refreshStatusPeriodic, 1000); |
||||
} |
||||
|
||||
$(document).ready(function() { |
||||
$.blayerwebif = {}; |
||||
$.blayerwebif.oldFilename = ""; |
||||
|
||||
setTimeout(refreshStatusPeriodic, 1000); |
||||
refreshFilenames(); |
||||
refreshStatus(); |
||||
|
||||
$("#uploadbutton").click(function() { |
||||
$.ajax({ |
||||
url: UPLOAD_URL, |
||||
type: "POST", |
||||
beforeSend: function() { |
||||
$("#uploadform").after("<span class=\"notificationtext\" id=\"uploadingnotification\">uploading...</span>"); |
||||
}, |
||||
success: function() { |
||||
$("#uploadingnotification").text("done! :)").delay(1000).fadeOut("slow"); |
||||
refreshFilenames(); |
||||
}, |
||||
error: function() { |
||||
$("#uploadingnotification").text("failed! :(").delay(1000).fadeOut("slow"); |
||||
}, |
||||
contentType: false, |
||||
cache: false, |
||||
processData: false, |
||||
data: new FormData($("#uploadform")[0]) |
||||
}); |
||||
}); |
||||
|
||||
$("#next").click(function() { |
||||
$.ajax({ |
||||
url: SERVER_URL, |
||||
dataType: "json", |
||||
type: "POST", |
||||
data: JSON.stringify({"cmd": "next"}), |
||||
success: function() { |
||||
refreshStatus(); |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
$("#pause").click(function() { |
||||
button = this; |
||||
$.ajax({ |
||||
url: SERVER_URL, |
||||
dataType: "json", |
||||
type: "POST", |
||||
data: JSON.stringify({"cmd": "togglepaused"}), |
||||
success: function(data) { |
||||
refreshStatus(); |
||||
|
||||
if(data.paused) |
||||
$(button).text("play"); |
||||
else |
||||
$(button).text("pause"); |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
$("#filtertext").keyup(function() { |
||||
keyword = $("#filtertext").val().toLowerCase(); |
||||
$("#filenames li").each(function(key, value) { |
||||
|
||||
if($(value).children("a").text().toLowerCase().indexOf(keyword) >= 0) |
||||
$(value).show(); |
||||
else |
||||
$(value).hide(); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
|
@ -1,53 +0,0 @@
@@ -1,53 +0,0 @@
|
||||
<html> |
||||
<head> |
||||
<title>blayer web interface</title> |
||||
<script src="jquery.js" type="text/javascript"></script> |
||||
<script src="blayerwebif.js" type="text/javascript"></script> |
||||
|
||||
<link rel="stylesheet" href="style.css" /> |
||||
</head> |
||||
<body> |
||||
|
||||
<div id="containerleft"> |
||||
<div class="box"> |
||||
<p class="boxhead">control</p> |
||||
|
||||
<p class="controlbuttons"> |
||||
<a href="#" id="next">next</a> |
||||
<a href="#" id="pause">play / pause</a> |
||||
</p> |
||||
</div> |
||||
|
||||
<div class="box"> |
||||
<p class="boxhead">upload</p> |
||||
<form action="#" method="post" id="uploadform"> |
||||
<input type="file" name="file" /> |
||||
<input type="button" value="upload" id="uploadbutton" /> |
||||
</form> |
||||
</div> |
||||
|
||||
<div class="box"> |
||||
<p class="boxhead">current animation</p> |
||||
|
||||
<!--<p><span class="label">Filename:</span><span id="filename"></span></p>--> |
||||
|
||||
<table id="tagtable"> |
||||
</table> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
<div id="containerleft"> |
||||
<div class="box"> |
||||
<p class="boxhead">animation database</p> |
||||
<p><span id="animationcount">###</span> animations in total</p> |
||||
|
||||
<p>filter: <input type="text" id="filtertext" /></p> |
||||
|
||||
<ul id="filenames"> |
||||
</ul> |
||||
|
||||
</div> |
||||
</div> |
||||
|
||||
</body></html> |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,87 +0,0 @@
@@ -1,87 +0,0 @@
|
||||
body { |
||||
background-color: #2f2f2f; |
||||
font-family: "lucida grande",tahoma, verdana, sans-serif; |
||||
font-size: 0.8em; |
||||
color: #cccccc; |
||||
} |
||||
|
||||
h1 { |
||||
font-size: 1.5em; |
||||
} |
||||
|
||||
#containerleft { |
||||
width: 46%; |
||||
margin-left: auto; |
||||
padding: 20px; |
||||
float: left; |
||||
} |
||||
#containerright { |
||||
width: 46%; |
||||
padding: 20px; |
||||
float: left; |
||||
} |
||||
|
||||
div.box { |
||||
border-radius: 10px; |
||||
border-color: #000000; |
||||
border-width: 1px; |
||||
border-style: solid; |
||||
/*width: 50%;*/ |
||||
background-color: #3d3d3d; |
||||
margin: auto; |
||||
margin-bottom: 30px; |
||||
padding: 10px; |
||||
box-shadow: 3px 3px 3px 3px #272727; |
||||
} |
||||
|
||||
p.boxhead { |
||||
color: #006483; |
||||
font-weight: bold; |
||||
margin-top: 0px; |
||||
} |
||||
|
||||
#tagtable td:first-child { |
||||
font-style: italic; |
||||
padding-right: 30px; |
||||
} |
||||
#tagtable td { |
||||
font-size: 0.8em; |
||||
} |
||||
|
||||
#filenames a, #filenames a:visited { |
||||
text-decoration: none; |
||||
color: #cccccc; |
||||
} |
||||
|
||||
.notificationtext { |
||||
padding-left: 20px; |
||||
color: #ffffff; |
||||
font-size: 0.7em; |
||||
} |
||||
|
||||
.controlbuttons { |
||||
padding: 10px; |
||||
} |
||||
.controlbuttons a, .controlbutton a:visited { |
||||
padding: 5px; |
||||
border: 1px solid #cccccc; |
||||
border-radius: 4px; |
||||
color: #cccccc; |
||||
text-decoration: none; |
||||
} |
||||
|
||||
.controlbuttons a:hover { |
||||
background: #006483; |
||||
} |
||||
|
||||
.label { |
||||
font-style: italic; |
||||
} |
||||
|
||||
.clear { |
||||
clear:both; |
||||
width: 0px; |
||||
height: 0px; |
||||
} |
||||
|
||||
|
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
[control] |
||||
bind_host = 0.0.0.0 |
||||
bind_port = 4243 |
||||
|
||||
[player] |
||||
animation_dir = /var/tmp/blup2/ |
||||
playlist = /var/tmp/blup2/playlist.txt |
||||
shuffle = true |
||||
autorefresh = true |
||||
looptime = 3 |
||||
maxplaynext = 3 |
||||
|
||||
[output] |
||||
output = blp:localhost:4242 |
||||
#output = blp:bastel0:4242 |
||||
#output = 'shell' |
||||
|
@ -1,428 +0,0 @@
@@ -1,428 +0,0 @@
|
||||
#!/usr/bin/python |
||||
|
||||
import threading |
||||
import random |
||||
import os.path |
||||
import os |
||||
import time |
||||
import socket |
||||
import asyncore |
||||
import asynchat |
||||
import cmd |
||||
import ConfigParser |
||||
import sys |
||||
import json |
||||
|
||||
import blup.animation as Animation |
||||
import blup.output as BlupOutput |
||||
import blup.frame as Frame |
||||
|
||||
|
||||
CONFIG_DEFAULTS = { |
||||
'output': 'shell', |
||||
'playlist': '', |
||||
'animation_dir': '.', |
||||
'enabled': False, |
||||
'shuffle': False, |
||||
'autorefresh': False |
||||
} |
||||
|
||||
def find(f, list): |
||||
for x in list: |
||||
if f(x): |
||||
return x |
||||
|
||||
class AnimationInfo(): |
||||
def __init__(self, filename): |
||||
self.__filename = filename |
||||
self.__tags = None |
||||
self.__valid = None |
||||
|
||||
@property |
||||
def filesize(self): |
||||
try: |
||||
statinfo = os.stat(self.__filename) |
||||
return statinfo.st_size |
||||
except OSError: |
||||
return -1 |
||||
|
||||
@property |
||||
def mtime(self): |
||||
try: |
||||
statinfo = os.stat(self.__filename) |
||||
return statinfo.st_mtime |
||||
except OSError: |
||||
return -1 |
||||
|
||||
@property |
||||
def tags(self): |
||||
return self.__tags |
||||
|
||||
@property |
||||
def valid(self): |
||||
if self.__valid == None: |
||||
try: |
||||
self.check() |
||||
except Animation.AnimationFileError: |
||||
pass |
||||
return self.__valid |
||||
|
||||
@property |
||||
def filename(self): |
||||
return self.__filename |
||||
|
||||
def check(self): |
||||
self.__valid = False |
||||
self.__tags = None |
||||
|
||||
anim = Animation.load(self.__filename) |
||||
|
||||
self.__valid = True |
||||
self.__tags = anim.tags |
||||
|
||||
|
||||
class AnimationDatabase(): |
||||
def __init__(self, animDir): |
||||
self.__animDir = animDir |
||||
self.__animInfos = [] |
||||
self.__lock = threading.Lock() |
||||
|
||||
def update(self): |
||||
with self.__lock: |
||||
oldAnimInfos = self.__animInfos |
||||
animInfos = [] |
||||
|
||||
for (dirpath, dirnames, filenames) in os.walk(self.__animDir): |
||||
files = map(lambda f: os.path.join(dirpath, f), filenames) |
||||
files = map(lambda f: os.path.relpath(os.path.join(dirpath, f), self.__animDir), filenames) |
||||
animInfos.extend(map(lambda f: AnimationInfo(f), files)) |
||||
#animInfos = filter(lambda a: a.valid, animInfos) |
||||
|
||||
newAnimInfos = [] |
||||
for animInfo in animInfos: |
||||
oldAnimInfo = find(lambda a: a.filename == animInfo.filename, oldAnimInfos) |
||||
if oldAnimInfo is not None and oldAnimInfo.mtime == animInfo.mtime: |
||||
newAnimInfos.append(oldAnimInfo) |
||||
else: |
||||
if animInfo.valid: |
||||
newAnimInfos.append(animInfo) |
||||
|
||||
self.__animInfos = newAnimInfos |
||||
|
||||
def findAnimation(self, filename): |
||||
with self.__lock: |
||||
animInfo = find(lambda a: a.filename == filename, self.__animInfos) |
||||
if animInfo is not None: |
||||
return animInfo |
||||
else: |
||||
raise Exception('animation not found!') |
||||
|
||||
def containsAnimation(self, filename): |
||||
with self.__lock: |
||||
animInfo = find(lambda a: a.filename == filename, self.__animInfos) |
||||
return (animInfo is not None) |
||||
|
||||
def getAllFilenames(self): |
||||
with self.__lock: |
||||
return map(lambda a: a.filename, self.__animInfos) |
||||
|
||||
|
||||
#class Playlist(list): |
||||
# def __init__(self, animationDatabase, filename=None): |
||||
# self.__animDb = animationDatabase |
||||
# self.__filename = filename |
||||
# if filename == None: |
||||
# self.append(self.__animDb.getAllFilenames()) |
||||
# else: |
||||
# f = open(filename, 'r') |
||||
# lines = f.read().split('\n') |
||||
# f.close() |
||||
# |
||||
# for line in lines: |
||||
# if self.__animDb.containsAnimation(line): |
||||
# self.append(line) |
||||
# |
||||
# def refresh(self): |
||||
# #f = open(filename, 'r') |
||||
# #lines = f.read().split('\n') |
||||
# #f.close() |
||||
# pass |
||||
# |
||||
# #for line in lines: |
||||
# # if self.__animDb.containsAnimation(line): |
||||
# # self.append(line) |
||||
|
||||
|
||||
|
||||
class PlayerThread(threading.Thread): |
||||
def __init__(self, database, output): |
||||
threading.Thread.__init__(self) |
||||
self.__playlist = [] |
||||
self.database = database |
||||
self.__playNext = [] |
||||
self.maxPlayNext = 3 |
||||
self.__output = output |
||||
self.shuffle = False |
||||
self.autoRefresh = True |
||||
self.loopTime = 10 |
||||
self.gap = 800 |
||||
self.__running = False |
||||
self.__player = Animation.AnimationPlayer() |
||||
self.__currentIndex = 0 |
||||
self.__currentFile = '' |
||||
self.__paused = False |
||||
|
||||
@property |
||||
def currentFile(self): |
||||
if not self.__paused: |
||||
return self.__currentFile |
||||
else: |
||||
return "" |
||||
|
||||
@property |
||||
def currentFileInfo(self): |
||||
if not self.__paused: |
||||
return self.database.findAnimation(self.__currentFile) |
||||
else: |
||||
# TODO: mhh... |
||||
return None |
||||
|
||||
@property |
||||
def paused(self): |
||||
return self.__paused |
||||
|
||||
def playNext(self, next): |
||||
if len(self.__playNext) < self.maxPlayNext: |
||||
self.__playNext.append(next) |
||||
else: |
||||
raise Exception |
||||
|
||||
def next(self): |
||||
self.__player.stop() |
||||
|
||||
def togglePaused(self): |
||||
self.__paused = not self.__paused |
||||
if self.__paused: |
||||
self.__player.stop() |
||||
|
||||
def refreshPlaylist(self): |
||||
self.database.update() |
||||
self.__playlist = self.database.getAllFilenames() |
||||
|
||||
def loadPlaylistFile(self): |
||||
raise Exception('not yet implemented :(') |
||||
|
||||
def terminate(self): |
||||
self.__player.stop() |
||||
self.__running = False |
||||
|
||||
def run(self): |
||||
self.__running = True |
||||
while self.__running: |
||||
anim = None |
||||
if self.autoRefresh: # and self.__currentIndex == len(self.__playlist) - 1: |
||||
self.refreshPlaylist() |
||||
|
||||
if len(self.__playNext) == 0: |
||||
if len(self.__playlist) == 0: |
||||
print 'busywait!!' |
||||
continue |
||||
|
||||
if self.shuffle: |
||||
self.__currentFile = self.__playlist[random.randint(0, len(self.__playlist) - 1)] |
||||
else: |
||||
if self.__currentIndex >= len(self.__playlist): |
||||
self.__currentIndex = 0 |
||||
self.__currentFile = self.__playlist[self.__currentIndex] |
||||
self.__currentIndex += 1 |
||||
else: |
||||
self.__currentFile = self.__playNext.pop(0) |
||||
anim = Animation.load(self.__currentFile) |
||||
|
||||
count = 1 |
||||
if anim.tags.has_key('loop') and anim.tags['loop'].lower() in ['yes', 'true']: |
||||
if anim.duration < self.loopTime * 1000: |
||||
count = (self.loopTime * 1000) / anim.duration |
||||
|
||||
|
||||
print 'playing:', anim |
||||
print 'tags:', anim.tags |
||||
self.__player.play(anim, self.__output, count=count) |
||||
print 'elapsed: ', self.__player.elapsed |
||||
|
||||
if self.__paused: |
||||
# TODO: use correct frame size |
||||
self.__output.sendFrame(Frame.Frame(18,8)) |
||||
while self.__paused: |
||||
time.sleep(1) |
||||
print 'busywait!!' |
||||
|
||||
if self.gap > 0 and self.__running: |
||||
# TODO: use correct frame size |
||||
self.__output.sendFrame(Frame.Frame(18,8)) |
||||
time.sleep(self.gap / 1000.0) |
||||
|
||||
|
||||
class PlayerControlClientHandler(asynchat.async_chat): |
||||
def __init__(self, sock, player): |
||||
asynchat.async_chat.__init__(self, sock=sock) |
||||
self.set_terminator('\n') |
||||
self.__buffer = '' |
||||
self.__player = player |
||||
|
||||
def collect_incoming_data(self, data): |
||||
self.__buffer += data |
||||
|
||||
def sendPacket(self, data): |
||||
self.send(json.dumps(data) + '\n') |
||||
|
||||
def found_terminator(self): |
||||
try: |
||||
data = json.loads(self.__buffer) |
||||
except ValueError: |
||||
self.sendPacket({'error': 'invalid json'}) |
||||
return |
||||
finally: |
||||
self.__buffer = '' |
||||
|
||||
try: |
||||
cmd = data['cmd'] |
||||
except (TypeError, KeyError): |
||||
self.sendPacket({'error': 'no command given'}) |
||||
return |
||||
|
||||
if cmd == 'refresh': |
||||
self.__player.refreshPlaylist() |
||||
self.sendPacket({'refresh': 'ok'}) |
||||
elif cmd == 'next': |
||||
self.__player.next() |
||||
self.sendPacket({'next': 'ok'}) |
||||
elif cmd == 'togglepaused': |
||||
self.__player.togglePaused() |
||||
self.sendPacket({'togglepaused': 'ok', 'paused': self.__player.paused}) |
||||
elif cmd == 'getpaused': |
||||
self.sendPacket({'paused': self.__player.paused}) |
||||
elif cmd == 'playnext': |
||||
if data.has_key('filename') and type(data['filename']) in [str, unicode]: |
||||
try: |
||||
self.__player.playNext(data['filename']) |
||||
except Exception: |
||||
self.sendPacket({'error':'too many animations queued'}) |
||||
else: |
||||
self.sendPacket({'playnext':'ok'}) |
||||
else: |
||||
self.sendPacket({'error': 'no or invalid animation file'}) |
||||
elif cmd == 'getallfilenames': |
||||
self.sendPacket({'allfilenames': self.__player.database.getAllFilenames()}) |
||||
elif cmd == 'getcurrentfileinfo': |
||||
if not self.__player.paused: |
||||
info = self.__player.currentFileInfo.tags |
||||
else: |
||||
info = {} |
||||
self.sendPacket({'currentfileinfo': info}) |
||||
elif cmd == 'getcurrentfilename': |
||||
self.sendPacket({'currentfilename': self.__player.currentFile}) |
||||
else: |
||||
self.sendPacket({'error': 'unknown command'}) |
||||
|
||||
|
||||
class PlayerControlServer(asyncore.dispatcher): |
||||
def __init__(self, host, port, player): |
||||
asyncore.dispatcher.__init__(self) |
||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM) |
||||
self.set_reuse_addr() |
||||
self.bind((host, port)) |
||||
self.listen(5) |
||||
self.__player = player |
||||
|
||||
def handle_accept(self): |
||||
pair = self.accept() |
||||
if pair is not None: |
||||
sock, addr = pair |
||||
print 'control connetcion from', addr |
||||
PlayerControlClientHandler(sock, self.__player) |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# |
||||
# main |
||||
# |
||||
|
||||
cfg = ConfigParser.SafeConfigParser(CONFIG_DEFAULTS) |
||||
cfg.read('/var/tmp/blup2/blayer.cfg') |
||||
|
||||
try: |
||||
out = BlupOutput.getOutput(cfg.get('output', 'output')) |
||||
except ConfigParser.NoSectionError: |
||||
sys.err.write('config error: missing \'output\' section') |
||||
except ConfigParser.NoOptionError: |
||||
sys.err.write('config error: missing \'output\' option in \'output\' section') |
||||
|
||||
try: |
||||
animation_dir = cfg.get('player', 'animation_dir') |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
animation_dir = '.' |
||||
|
||||
db = AnimationDatabase(animation_dir) |
||||
|
||||
print 'updating database...' |
||||
db.update() |
||||
print 'done with updating database...' |
||||
print 'updating database (again)...' |
||||
db.update() |
||||
print 'done with updating database...' |
||||
#print db.getAllFilenames() |
||||
|
||||
#try: |
||||
# playlist = Playlist(db, cfg.get('player', 'playlist')) |
||||
# print 'file-playluist:', playlist |
||||
#except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
# playlist = Playlist(db) |
||||
# print 'db-playluist:', playlist |
||||
|
||||
blayer = PlayerThread(db, out) |
||||
blayer.refreshPlaylist() |
||||
#sys.exit(0) |
||||
|
||||
try: |
||||
blayer.loopTime = cfg.getint('player', 'looptime') |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
pass |
||||
|
||||
try: |
||||
blayer.shuffle = cfg.getboolean('player', 'shuffle') |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
pass |
||||
|
||||
try: |
||||
blayer.autoRefresh = cfg.getboolean('player', 'autorefresh') |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
pass |
||||
|
||||
try: |
||||
blayer.maxPlayNext = cfg.getint('player', 'maxplaynext') |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
pass |
||||
|
||||
blayer.start() |
||||
|
||||
try: |
||||
cser = PlayerControlServer(cfg.get('control', 'bind_host'), cfg.getint('control', 'bind_port'), blayer) |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
cser = None |
||||
|
||||
|
||||
try: |
||||
|
||||
if cser is not None: |
||||
asyncore.loop() |
||||
else: |
||||
blayer.join() |
||||
except KeyboardInterrupt: |
||||
print 'nawk!!' |
||||
blayer.terminate() |
||||
|
||||
|
||||
|
@ -1,379 +0,0 @@
@@ -1,379 +0,0 @@
|
||||
#!/usr/bin/python |
||||
|
||||
import threading |
||||
import random |
||||
import os.path |
||||
import os |
||||
import time |
||||
import socket |
||||
import asyncore |
||||
import asynchat |
||||
import cmd |
||||
import ConfigParser |
||||
import sys |
||||
|
||||
import blup.animation as Animation |
||||
import blup.output as BlupOutput |
||||
import blup.frame as Frame |
||||
|
||||
|
||||
CONFIG_DEFAULTS = { |
||||
'output': 'shell', |
||||
'playlist': '', |
||||
'animation_dir': '.', |
||||
'enabled': False, |
||||
'shuffle': False, |
||||
'autorefresh': False |
||||
} |
||||
|
||||
def find(f, list): |
||||
for x in list: |
||||
if f(x): |
||||
return x |
||||
|
||||
class AnimationInfo(): |
||||
def __init__(self, filename): |
||||
self.__filename = filename |
||||
self.__tags = None |
||||
self.__valid = None |
||||
|
||||
@property |
||||
def filesize(self): |
||||
try: |
||||
statinfo = os.stat(self.__filename) |
||||
return statinfo.st_size |
||||
except OSError: |
||||
return -1 |
||||
|
||||
@property |
||||
def mtime(self): |
||||
try: |
||||
statinfo = os.stat(self.__filename) |
||||
return statinfo.st_mtime |
||||
except OSError: |
||||
return -1 |
||||
|
||||
@property |
||||
def tags(self): |
||||
return self.__tags |
||||
|
||||
@property |
||||
def valid(self): |
||||
if self.__valid == None: |
||||
try: |
||||
self.check() |
||||
except Animation.AnimationFileError: |
||||
pass |
||||
return self.__valid |
||||
|
||||
@property |
||||
def filename(self): |
||||
return self.__filename |
||||
|
||||
def check(self): |
||||
self.__valid = False |
||||
self.__tags = None |
||||
|
||||
anim = Animation.load(self.__filename) |
||||
|
||||
self.__valid = True |
||||
self.__tags = anim.tags |
||||
|
||||
|
||||
class AnimationDatabase(): |
||||
def __init__(self, animDir): |
||||
self.__animDir = animDir |
||||
self.__animInfos = [] |
||||
self.__lock = threading.Lock() |
||||
|
||||
def update(self): |
||||
with self.__lock: |
||||
oldAnimInfos = self.__animInfos |
||||
animInfos = [] |
||||
|
||||
for (dirpath, dirnames, filenames) in os.walk(self.__animDir): |
||||
files = map(lambda f: os.path.join(dirpath, f), filenames) |
||||
files = map(lambda f: os.path.relpath(os.path.join(dirpath, f), self.__animDir), filenames) |
||||
animInfos.extend(map(lambda f: AnimationInfo(f), files)) |
||||
#animInfos = filter(lambda a: a.valid, animInfos) |
||||
|
||||
newAnimInfos = [] |
||||
for animInfo in animInfos: |
||||
oldAnimInfo = find(lambda a: a.filename == animInfo.filename, oldAnimInfos) |
||||
if oldAnimInfo is not None and oldAnimInfo.mtime == animInfo.mtime: |
||||
newAnimInfos.append(oldAnimInfo) |
||||
else: |
||||
if animInfo.valid: |
||||
newAnimInfos.append(animInfo) |
||||
|
||||
self.__animInfos = newAnimInfos |
||||
|
||||
def findAnimation(self, filename): |
||||
with self.__lock: |
||||
animInfo = find(lambda a: a.filename == filename, self.__animInfos) |
||||
if animInfo is not None: |
||||
return animInfo |
||||
else: |
||||
raise Exception('animation not found!') |
||||
|
||||
def containsAnimation(self, filename): |
||||
with self.__lock: |
||||
animInfo = find(lambda a: a.filename == filename, self.__animInfos) |
||||
return (animInfo is not None) |
||||
|
||||
def getAllFilenames(self): |
||||
with self.__lock: |
||||
return map(lambda a: a.filename, self.__animInfos) |
||||
|
||||
|
||||
#class Playlist(list): |
||||
# def __init__(self, animationDatabase, filename=None): |
||||
# self.__animDb = animationDatabase |
||||
# self.__filename = filename |
||||
# if filename == None: |
||||
# self.append(self.__animDb.getAllFilenames()) |
||||
# else: |
||||
# f = open(filename, 'r') |
||||
# lines = f.read().split('\n') |
||||
# f.close() |
||||
# |
||||
# for line in lines: |
||||
# if self.__animDb.containsAnimation(line): |
||||
# self.append(line) |
||||
# |
||||
# def refresh(self): |
||||
# #f = open(filename, 'r') |
||||
# #lines = f.read().split('\n') |
||||
# #f.close() |
||||
# pass |
||||
# |
||||
# #for line in lines: |
||||
# # if self.__animDb.containsAnimation(line): |
||||
# # self.append(line) |
||||
|
||||
|
||||
|
||||
class PlayerThread(threading.Thread): |
||||
def __init__(self, database, playlist, output): |
||||
threading.Thread.__init__(self) |
||||
self.__playlist = playlist |
||||
self.__database = database |
||||
self.__playNext = [] |
||||
self.maxPlayNext = 3 |
||||
self.__output = output |
||||
self.shuffle = False |
||||
self.autoRefresh = True |
||||
self.loopTime = 10 |
||||
self.gap = 800 |
||||
self.__running = False |
||||
self.__player = Animation.AnimationPlayer() |
||||
self.__currentIndex = 0 |
||||
self.__currentFile = '' |
||||
|
||||
@property |
||||
def currentFile(self): |
||||
return self.__currentFile |
||||
|
||||
def playNext(self, next): |
||||
if len(self.__playNext) < self.__maxPlayNext: |
||||
self.__playNext.append(next) |
||||
else: |
||||
raise Exception |
||||
|
||||
def refreshPlaylist(self): |
||||
self.__database.update() |
||||
self.__playlist = self.__database.getAllFilenames() |
||||
|
||||
def loadPlaylistFile(self): |
||||
raise Exception('not yet implemented :(') |
||||
|
||||
def terminate(self): |
||||
self.__player.stop() |
||||
self.__running = False |
||||
|
||||
def run(self): |
||||
self.__running = True |
||||
while self.__running: |
||||
anim = None |
||||
if self.autoRefresh: # and self.__currentIndex == len(self.__playlist) - 1: |
||||
self.refreshPlaylist() |
||||
|
||||
if len(self.__playNext) == 0: |
||||
if len(self.__playlist) == 0: |
||||
print 'busywait!!' |
||||
continue |
||||
|
||||
if self.shuffle: |
||||
self.__currentFile = self.__playlist[random.randint(0, len(self.__playlist) - 1)] |
||||
else: |
||||
if self.__currentIndex >= len(self.__playlist): |
||||
self.__currentIndex = 0 |
||||
self.__currentFile = self.__playlist[self.__currentIndex] |
||||
self.__currentIndex += 1 |
||||
else: |
||||
self.__currentFile = self.__playNext.pop(0) |
||||
anim = Animation.load(self.__currentFile) |
||||
|
||||
count = 1 |
||||
if anim.tags.has_key('loop') and anim.tags['loop'].lower() in ['yes', 'true']: |
||||
if anim.duration < self.loopTime * 1000: |
||||
count = (self.loopTime * 1000) / anim.duration |
||||
|
||||
|
||||
print 'playing:', anim |
||||
print 'tags:', anim.tags |
||||
self.__player.play(anim, self.__output, count=count) |
||||
|
||||
if self.gap > 0 and self.__running: |
||||
self.__output.sendFrame(Frame.Frame(18,8)) |
||||
time.sleep(self.gap / 1000.0) |
||||
|
||||
|
||||
class PlayerControlClientHandler(asynchat.async_chat): |
||||
def __init__(self, sock, player): |
||||
asynchat.async_chat.__init__(self, sock=sock) |
||||
self.set_terminator('\n') |
||||
self.__buffer = '' |
||||
self.__player = player |
||||
|
||||
def collect_incoming_data(self, data): |
||||
self.__buffer += data |
||||
|
||||
def found_terminator(self): |
||||
args = self.__buffer.split(' ') |
||||
args = filter(lambda a: len(a) > 0, args) |
||||
if len(args) == 0: |
||||
return |
||||
self.__buffer = '' |
||||
cmd = args.pop(0) |
||||
|
||||
if cmd == 'refresh': |
||||
self.__playlist.refresh() |
||||
self.send('ok\n') |
||||
elif cmd == 'status': |
||||
self.send('playing %s\n' % (self.__player.getCurrentFile())) |
||||
elif cmd == 'getplaylist': |
||||
plist = '\n'.join(self.__playlist.getPlaylist()) |
||||
self.send(plist + '\n') |
||||
elif cmd == 'playnext' and len(args) == 1: |
||||
try: |
||||
self.__player.playNext(args[0]) |
||||
self.send('ok\n') |
||||
except Exception: |
||||
self.send('error\n') |
||||
elif cmd == 'loadplaylist' and len(args) == 1: |
||||
try: |
||||
if args[0] == '.': |
||||
self.__playlist.loadDir() |
||||
else: |
||||
self.__playlist.loadFile(args[0]) |
||||
self.send('ok\n') |
||||
except: |
||||
self.send('error\n') |
||||
elif cmd == 'quit': |
||||
self.send('bye\n') |
||||
self.close() |
||||
else: |
||||
self.send('unknown command\n') |
||||
|
||||
|
||||
class PlayerControlServer(asyncore.dispatcher): |
||||
def __init__(self, host, port, player, playlist): |
||||
asyncore.dispatcher.__init__(self) |
||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM) |
||||
self.set_reuse_addr() |
||||
self.bind((host, port)) |
||||
self.listen(5) |
||||
self.__player = player |
||||
self.__playlist = playlist |
||||
|
||||
def handle_accept(self): |
||||
pair = self.accept() |
||||
if pair is not None: |
||||
sock, addr = pair |
||||
print 'control connetcion from', addr |
||||
PlayerControlClientHandler(sock, self.__player, self.__playlist) |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# |
||||
# main |
||||
# |
||||
|
||||
cfg = ConfigParser.SafeConfigParser(CONFIG_DEFAULTS) |
||||
cfg.read('/var/tmp/blup2/blayer.cfg') |
||||
|
||||
try: |
||||
out = BlupOutput.getOutput(cfg.get('output', 'output')) |
||||
except ConfigParser.NoSectionError: |
||||
sys.err.write('config error: missing \'output\' section') |
||||
except ConfigParser.NoOptionError: |
||||
sys.err.write('config error: missing \'output\' option in \'output\' section') |
||||
|
||||
try: |
||||
animation_dir = cfg.get('player', 'animation_dir') |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
animation_dir = '.' |
||||
|
||||
db = AnimationDatabase(animation_dir) |
||||
|
||||
print 'updating database...' |
||||
db.update() |
||||
print 'done with updating database...' |
||||
print 'updating database (again)...' |
||||
db.update() |
||||
print 'done with updating database...' |
||||
#print db.getAllFilenames() |
||||
|
||||
try: |
||||
playlist = Playlist(db, cfg.get('player', 'playlist')) |
||||
print 'file-playluist:', playlist |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
playlist = Playlist(db) |
||||
print 'db-playluist:', playlist |
||||
|
||||
blayer = PlayerThread(db, playlist, out) |
||||
#sys.exit(0) |
||||
|
||||
try: |
||||
blayer.setLoopTime(cfg.getint('player', 'looptime')) |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
pass |
||||
|
||||
try: |
||||
blayer.setShuffle(cfg.getboolean('player', 'shuffle')) |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
pass |
||||
|
||||
try: |
||||
blayer.setAutoRefresh(cfg.getboolean('player', 'autorefresh')) |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
pass |
||||
|
||||
try: |
||||
blayer.setMaxPlayNext(cfg.getint('player', 'maxplaynext')) |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
pass |
||||
|
||||
blayer.start() |
||||
|
||||
try: |
||||
cser = PlayerControlServer(cfg.get('control', 'bind_host'), cfg.getint('control', 'bind_port'), blayer, playlist) |
||||
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError): |
||||
cser = None |
||||
|
||||
|
||||
try: |
||||
|
||||
if cser is not None: |
||||
asyncore.loop() |
||||
else: |
||||
blayer.join() |
||||
except KeyboardInterrupt: |
||||
print 'nawk!!' |
||||
blayer.terminate() |
||||
|
||||
|
||||
|
@ -1,4 +0,0 @@
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash |
||||
|
||||
python blphub.py -o blp:bastel0:4242 localhost:4242:1:1000 localhost:42421:2:3500 |
||||
|
@ -1,44 +0,0 @@
@@ -1,44 +0,0 @@
|
||||
#!/usr/bin/python |
||||
|
||||
import colorsys |
||||
import time |
||||
|
||||
import blup.output |
||||
import blup.frame |
||||
|
||||
dim = blup.frame.FrameDimension(18,8,16,3) |
||||
frame = blup.frame.Frame(dim) |
||||
|
||||
HEIGHT = 8 |
||||
WIDTH = 18 |
||||
|
||||
#h = 0.0 |
||||
#for y in range(HEIGHT): |
||||
# h += 1.0 / (HEIGHT * 1.0) |
||||
# v = 0 |
||||
# s = 0.7 |
||||
# for x in range(WIDTH): |
||||
# v += 1.0 / (WIDTH * 1.0) |
||||
# print s |
||||
# color = colorsys.hsv_to_rgb(h, s, v) |
||||
# color = tuple(map(lambda c: int(round(c * 15)), color)) |
||||
# print color |
||||
# frame.setPixel(x, y, color) |
||||
|
||||
for y in range(HEIGHT): |
||||
for x in range(WIDTH): |
||||
h = (x * 1.0) / (WIDTH - 1.0) |
||||
s = 1.0 - (y * 1.0) / (HEIGHT - 0.0) |
||||
v = 1.0 - (y * 1.0) / (HEIGHT - 0.0) |
||||
color = colorsys.hsv_to_rgb(h, s, v) |
||||
color = tuple(map(lambda c: int(round(c * 15)), color)) |
||||
frame.setPixel(x, y, color) |
||||
|
||||
out = blup.output.getOutput('e3blp') |
||||
while True: |
||||
out.sendFrame(frame) |
||||
time.sleep(0.4) |
||||
|
||||
|
||||
|
||||
|
@ -1,104 +0,0 @@
@@ -1,104 +0,0 @@
|
||||
# Major library imports |
||||
import atexit |
||||
import pyaudio |
||||
from numpy import zeros, short, fromstring, array |
||||
from numpy.fft import fft |
||||
|
||||
import colorsys |
||||
import time |
||||
import blup.frame |
||||
import blup.output |
||||
|
||||
#NUM_SAMPLES = 512 |
||||
NUM_SAMPLES = 36 |
||||
#NUM_SAMPLES = 18 |
||||
#NUM_SAMPLES = 16 |
||||
#SAMPLING_RATE = 11025 |
||||
#SAMPLING_RATE = 11024 / 2 |
||||
SAMPLING_RATE = 1100 |
||||
|
||||
_stream = None |
||||
|
||||
def read_fft(): |
||||
global _stream |
||||
pa = None |
||||
|
||||
def cleanup_audio(): |
||||
if _stream: |
||||
_stream.stop_stream() |
||||
_stream.close() |
||||
pa.terminate() |
||||
|
||||
if _stream is None: |
||||
pa = pyaudio.PyAudio() |
||||
_stream = pa.open(format=pyaudio.paInt16, channels=1, |
||||
rate=SAMPLING_RATE, |
||||
input=True, frames_per_buffer=NUM_SAMPLES) |
||||
atexit.register(cleanup_audio) |
||||
|
||||
audio_data = fromstring(_stream.read(NUM_SAMPLES), dtype=short) |
||||
normalized_data = audio_data / 32768.0 |
||||
|
||||
return fft(normalized_data)[1:1+NUM_SAMPLES/2] |
||||
|
||||
def flatten_fft(scale = 1.0): |
||||
""" |
||||
Produces a nicer graph, I'm not sure if this is correct |
||||
""" |
||||
for i, v in enumerate(read_fft()): |
||||
yield scale * (i * v) / NUM_SAMPLES |
||||
|
||||
|
||||
def makeColor(x): |
||||
hue = (7-x) / 7.0 / 3.0 -0.1 |
||||
if hue < 0: |
||||
hue += 1 |
||||
rgb = map(lambda x: int(round(x*7)), colorsys.hsv_to_rgb(hue, 1, 1)) |
||||
return rgb |
||||
def makeSpectrumFrame(spectrum): |
||||
f = blup.frame.Frame(blup.frame.FrameDimension(18,8,8,3)) |
||||
for x, y in enumerate(spectrum): |
||||
if y > 7: |
||||
y = 7 |
||||
y = int(y) |
||||
for i in range(y): |
||||
#val = (7,7,7) |
||||
val = makeColor(i) |
||||
f.setPixel(x, 7-i, val) |
||||
return f |
||||
|
||||
def draw(): |
||||
'''Draw 3 different colour graphs''' |
||||
global NUM_SAMPLES |
||||
audio = array(list(flatten_fft(scale = 80))) |
||||
freqs = len(audio) |
||||
bass, mid, treble = triple(audio) |
||||
|
||||
colours = (0.5, 1.0, 0.5), (1, 1, 0), (1, 0.2, 0.5) |
||||
|
||||
fill(0, 0, 1) |
||||
rect(0, 0, WIDTH, 400) |
||||
translate(50, 200) |
||||
|
||||
for spectrum, col in zip((bass, mid, treble), colours): |
||||
fill(col) |
||||
for i, s in enumerate(spectrum): |
||||
rect(i, 0, 1, -abs(s)) |
||||
else: |
||||
translate(i, 0) |
||||
|
||||
audio = array(list(flatten_fft(scale = 80))) |
||||
|
||||
|
||||
out = blup.output.getOutput('colorfulshell') |
||||
while True: |
||||
audio = array(list(flatten_fft(scale=80))) |
||||
#audio = map(abs, audio) |
||||
#print len(audio) |
||||
frame = makeSpectrumFrame([ int((x/18.0)*8) for x in range(18)]) |
||||
frame = makeSpectrumFrame(audio) |
||||
#print map(int,audio) |
||||
out.sendFrame(frame) |
||||
#time.sleep(0.1) |
||||
|
||||
|
@ -1,84 +0,0 @@
@@ -1,84 +0,0 @@
|
||||
|
||||
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler |
||||
import socket |
||||
import cgi |
||||
import json |
||||
import time |
||||
import os.path |
||||
import threading |
||||
|
||||
TELNET_HOST = 'localhost' |
||||
TELNET_PORT = 4243 |
||||
|
||||
DOCROOT = '/var/tmp/blup2/blayer-webif' |
||||
UPLOAD_DIR = '/var/tmp/blup2/blm/incoming' |
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
||||
sock.connect((TELNET_HOST, TELNET_PORT)) |
||||
socklock = threading.Lock() |
||||
|
||||
class HTTPRequestHandler(BaseHTTPRequestHandler): |
||||
def do_GET(self): |
||||
self.send_response(200) |
||||
self.send_header('Content-type', 'text/html') |
||||
self.end_headers() |
||||
print self.path |
||||
#self.wfile.write('<form action="bla" method="post"><input type="text" name="text" /><input type="submit" value="ok" /></form>') |
||||
|
||||
p = os.path.join(DOCROOT, self.path[1:]) |
||||
print p |
||||
if os.path.isfile(p): |
||||
f = open(p, 'r') |
||||
data = f.read() |
||||
f.close() |
||||
self.wfile.write(data) |
||||
|
||||
|
||||
|
||||
def do_POST(self): |
||||
|
||||
if self.path == '/do_upload': |
||||
formdata = cgi.FieldStorage( |
||||
fp=self.rfile, headers=self.headers, |
||||
environ={'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': self.headers['Content-Type']}) |
||||
|
||||
fileField = formdata['file'] |
||||
|
||||
f = open(os.path.join(UPLOAD_DIR, fileField.filename), 'w') |
||||
f.write(fileField.file.read()) |
||||
f.close() |
||||
|
||||
sock.send(json.dumps({"cmd": "refresh"}) + '\n') |
||||
print 'server answer to refresh cmd: ', sock.recv(1024) |
||||
|
||||
self.send_response(200); |
||||
self.end_headers(); |
||||
|
||||
return |
||||
|
||||
postdata = self.rfile.read(int(self.headers.getheader('content-length'))) |
||||
#self.wfile.write('test') |
||||
|
||||
if postdata[-1:] != '\n': |
||||
postdata += '\n' |
||||
print 'postdata:', postdata |
||||
|
||||
with socklock: |
||||
sock.send(postdata) |
||||
time.sleep(0.1) |
||||
resp = sock.recv(1024 * 10) |
||||
#sock.shutdown(socket.SHUT_RDWR) |
||||
#sock.close() |
||||
|
||||
self.send_response(200) |
||||
self.send_header('Content-type', 'text/html') |
||||
self.send_header('Content-length', len(resp)) |
||||
self.end_headers() |
||||
print 'resp:', resp |
||||
self.wfile.write(resp) |
||||
|
||||
|
||||
|
||||
server = HTTPServer(('0.0.0.0',8080), HTTPRequestHandler) |
||||
server.serve_forever() |
||||
|
@ -1,43 +0,0 @@
@@ -1,43 +0,0 @@
|
||||
|
||||
def loadBbm(filename): |
||||
""" Parse a bbm file and return an Animation object. """ |
||||
|
||||
def getint16(vals): |
||||
return (cals[2]>>8) + vals[3] |
||||
def getint32(vals): |
||||
return (vals[0]>>24) + (vals[1]>>16) + (cals[2]>>8) + vals[3] |
||||
|
||||
f = open(filename, 'r') |
||||
rawdata = f.read() |
||||
f.close() |
||||
|
||||
data = [ ord(x) for x in rawdata ] |
||||
|
||||
if getint32(data[0:4]) != 0x23542666: |
||||
raise ValueError('magic does not match') |
||||
|
||||
height = getint16(data[4:6]) |
||||
width = getint16(data[6:8]) |
||||
channels = getint16(data[8:10]) |
||||
maxval = getint16(data[10:12]) |
||||
|
||||
framecnt = getint32(data[10:14]) |
||||
duration = getint32(data[14:18]) |
||||
frameptr = getint32(data[18:22]) |
||||
|
||||
# TODO: parse additional headers |
||||
|
||||
if rawdata[frameptr:(frameptr+4)] != 'frms': |
||||
raise ValueError('frame pointer does not point to frame start marker') |
||||
|
||||
framedata = data[frameptr + 4:] |
||||
framesize = width*height*channels |
||||
|
||||
frames = [] |
||||
while True: |
||||
pass |
||||
|
||||
raise Exception('uarrgh!!') |
||||
|
||||
|
||||
|
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
# BlinkenLights Movie 18x8 |
||||
# loop = yes |
||||
|
||||
@200 |
||||
000000000000000000 |
||||
000011100011100000 |
||||
000111110111110000 |
||||
000111111111110000 |
||||
000011111111100000 |
||||
000000111110000000 |
||||
000000001000000000 |
||||
000000000000000000 |
||||
|
||||
@800 |
||||
000011100011100000 |
||||
000111110111110000 |
||||
001111111111111000 |
||||
001111111111111000 |
||||
000111111111110000 |
||||
000011111111100000 |
||||
000000111110000000 |
||||
000000001000000000 |
||||
|
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
#!/usr/bin/pyton |
||||
|
||||
import blup.frame |
||||
import blup.output |
||||
import blup.animation |
||||
|
||||
out = blup.output.getOutput('e3blp') |
||||
|
||||
points = [] |
||||
|
||||
|
||||
for i in |
||||
|
@ -1,147 +0,0 @@
@@ -1,147 +0,0 @@
|
||||
#heart.blm |
||||
#countdown.blm |
||||
test.blm |
||||
klonfish-dancing.blm |
||||
blm/invasion.blm |
||||
blm/torus.blm |
||||
blm/antiwar.blm |
||||
blm/billard.blm |
||||
blm/x-ball.blm |
||||
blm/game.blm |
||||
blm/tropfen.blm |
||||
blm/moewe_frontal.blm |
||||
blm/fireworks_2.blm |
||||
blm/thunderstorm.blm |
||||
blm/biker.blm |
||||
blm/fantasticspace.blm |
||||
blm/allyourbase.blm |
||||
blm/21st_century_man.blm |
||||
blm/dont_try_at_home.blm |
||||
blm/spin.blm |
||||
blm/heart.blm |
||||
blm/encyclops.blm |
||||
blm/fant.blm |
||||
blm/schnecke.blm |
||||
blm/peao.blm |
||||
blm/falling_pix.blm |
||||
blm/tetris.blm |
||||
blm/text.blm |
||||
blm/landing_zone.blm |
||||
blm/dance_micky_chickee.blm |
||||
blm/supermaennchen.blm |
||||
blm/allon.blm |
||||
blm/kame.blm |
||||
blm/kiss.blm |
||||
blm/fallingrows.blm |
||||
blm/jesus.blm |
||||
blm/vlhurg.blm |
||||
blm/wasserhahn.blm |
||||
blm/gewaber.blm |
||||
blm/tla_them.blm |
||||
blm/quix_glitter.blm |
||||
blm/herz.blm |
||||
blm/sanduhr.blm |
||||
blm/defect_car.blm |
||||
blm/peepshow.blm |
||||
blm/countdown.blm |
||||
blm/luftballoons.blm |
||||
blm/impaexpa.blm |
||||
blm/wein_trinken.blm |
||||
blm/coffee.blm |
||||
blm/camel.blm |
||||
blm/matrix.blm |
||||
blm/life.blm |
||||
blm/snake.blm |
||||
blm/windshield.blm |
||||
blm/raumschiff_enterprise.blm |
||||
blm/pumpkin.blm |
||||
blm/yeastman.blm |
||||
blm/genomix.blm |
||||
blm/bad_luck.blm |
||||
blm/om_sweet_om.blm |
||||
blm/invaders_andreas.blm |
||||
blm/manifesto5.blm |
||||
blm/chat_noir.blm |
||||
blm/rakete.blm |
||||
blm/manifesto3.blm |
||||
blm/relativity.blm |
||||
blm/fussballer.blm |
||||
blm/sinus.blm |
||||
blm/love_triangles.blm |
||||
blm/ascii_people.blm |
||||
blm/hanoi.blm |
||||
blm/monster.blm |
||||
blm/come_together.blm |
||||
blm/matrix_maennchen.blm |
||||
blm/silent_night.blm |
||||
blm/halt.blm |
||||
blm/das_leben_ist_schoen.blm |
||||
blm/moving_car.blm |
||||
blm/spirals.blm |
||||
blm/mandel.blm |
||||
blm/alloff.blm |
||||
blm/manifesto1.blm |
||||
blm/quantorenlyrik.blm |
||||
blm/manifesto4.blm |
||||
blm/warterad.blm |
||||
blm/surprise.blm |
||||
blm/oneon.blm |
||||
blm/manifesto7.blm |
||||
blm/fireworks.blm |
||||
blm/labyrinth.blm |
||||
blm/brainfuck.blm |
||||
blm/die_erde.blm |
||||
blm/klo.blm |
||||
blm/psychowarrior.blm |
||||
blm/timeless.blm |
||||
blm/auge.blm |
||||
blm/worm.blm |
||||
blm/colagoboom.blm |
||||
blm/musterbeispiel.blm |
||||
blm/fallingpixels.blm |
||||
blm/franknstoned.blm |
||||
blm/rollo_grow.blm |
||||
blm/illuminati.blm |
||||
blm/3rd_advent.blm |
||||
blm/chaosknoten.blm |
||||
blm/be_happy.blm |
||||
blm/binary_god.blm |
||||
blm/kingzilla.blm |
||||
blm/paradox.blm |
||||
blm/dj.blm |
||||
blm/hut.blm |
||||
blm/sortofselftest.blm |
||||
blm/blubb.blm |
||||
blm/bleeeh.blm |
||||
blm/rain.blm |
||||
blm/flash.blm |
||||
blm/femina_light.blm |
||||
blm/gator_rogat.blm |
||||
blm/speedit.blm |
||||
blm/scooter.blm |
||||
blm/pixie_in_the_box.blm |
||||
blm/zeichen.blm |
||||
blm/humanistic.blm |
||||
blm/pacman_saga.blm |
||||
blm/die_autobahn.blm |
||||
blm/mytest3.blm |
||||
blm/yin_yang.blm |
||||
blm/klettermensch.blm |
||||
blm/baustein.blm |
||||
blm/pwm.blm |
||||
blm/babelfish.blm |
||||
blm/mytest2.blm |
||||
blm/winslows.blm |
||||
blm/dance.blm |
||||
blm/martelo.blm |
||||
blm/raindrops.blm |
||||
blm/g.blm |
||||
blm/clear.blm |
||||
blm/sport_haelt_fit.blm |
||||
blm/kreise.blm |
||||
blm/railroad.blm |
||||
blm/3D_cube.blm |
||||
blm/balloon.blm |
||||
blm/flipp.blm |
||||
blm/mytest.blm |
||||
blm/tux.blm |
@ -1,143 +0,0 @@
@@ -1,143 +0,0 @@
|
||||
blm/invasion.blm |
||||
blm/torus.blm |
||||
blm/antiwar.blm |
||||
blm/billard.blm |
||||
blm/x-ball.blm |
||||
blm/game.blm |
||||
blm/tropfen.blm |
||||
blm/moewe_frontal.blm |
||||
blm/fireworks_2.blm |
||||
blm/thunderstorm.blm |
||||
blm/biker.blm |
||||
blm/fantasticspace.blm |
||||
blm/allyourbase.blm |
||||
blm/21st_century_man.blm |
||||
blm/dont_try_at_home.blm |
||||
blm/spin.blm |
||||
blm/heart.blm |
||||
blm/encyclops.blm |
||||
blm/fant.blm |
||||
blm/schnecke.blm |
||||
blm/peao.blm |
||||
blm/falling_pix.blm |
||||
blm/tetris.blm |
||||
blm/text.blm |
||||
blm/landing_zone.blm |
||||
blm/dance_micky_chickee.blm |
||||
blm/supermaennchen.blm |
||||
blm/allon.blm |
||||
blm/kame.blm |
||||
blm/kiss.blm |
||||
blm/fallingrows.blm |
||||
blm/jesus.blm |
||||
blm/vlhurg.blm |
||||
blm/wasserhahn.blm |
||||
blm/gewaber.blm |
||||
blm/tla_them.blm |
||||
blm/quix_glitter.blm |
||||
blm/herz.blm |
||||
blm/sanduhr.blm |
||||
blm/defect_car.blm |
||||
blm/peepshow.blm |
||||
blm/countdown.blm |
||||
blm/luftballoons.blm |
||||
blm/impaexpa.blm |
||||
blm/wein_trinken.blm |
||||
blm/coffee.blm |
||||
blm/camel.blm |
||||
blm/matrix.blm |
||||
blm/life.blm |
||||
blm/snake.blm |
||||
blm/windshield.blm |
||||
blm/raumschiff_enterprise.blm |
||||
blm/pumpkin.blm |
||||
blm/yeastman.blm |
||||
blm/genomix.blm |
||||
blm/bad_luck.blm |
||||
blm/om_sweet_om.blm |
||||
blm/invaders_andreas.blm |
||||
blm/manifesto5.blm |
||||
blm/chat_noir.blm |
||||
blm/rakete.blm |
||||
blm/manifesto3.blm |
||||
blm/relativity.blm |
||||
blm/fussballer.blm |
||||
blm/sinus.blm |
||||
blm/love_triangles.blm |
||||
blm/ascii_people.blm |
||||
blm/hanoi.blm |
||||
blm/monster.blm |
||||
blm/come_together.blm |
||||
blm/matrix_maennchen.blm |
||||
blm/silent_night.blm |
||||
blm/halt.blm |
||||
blm/das_leben_ist_schoen.blm |
||||
blm/moving_car.blm |
||||
blm/spirals.blm |
||||
blm/mandel.blm |
||||
blm/alloff.blm |
||||
blm/manifesto1.blm |
||||
blm/quantorenlyrik.blm |
||||
blm/manifesto4.blm |
||||
blm/warterad.blm |
||||
blm/surprise.blm |
||||
blm/oneon.blm |
||||
blm/manifesto7.blm |
||||
blm/fireworks.blm |
||||
blm/labyrinth.blm |
||||
blm/brainfuck.blm |
||||
blm/die_erde.blm |
||||
blm/klo.blm |
||||
blm/psychowarrior.blm |
||||
blm/timeless.blm |
||||
blm/auge.blm |
||||
blm/worm.blm |
||||
blm/colagoboom.blm |
||||
blm/musterbeispiel.blm |
||||
blm/fallingpixels.blm |
||||
blm/franknstoned.blm |
||||
blm/rollo_grow.blm |
||||
blm/illuminati.blm |
||||
blm/3rd_advent.blm |
||||
blm/chaosknoten.blm |
||||
blm/be_happy.blm |
||||
blm/binary_god.blm |
||||
blm/kingzilla.blm |
||||
blm/paradox.blm |
||||
blm/dj.blm |
||||
blm/hut.blm |
||||
blm/sortofselftest.blm |
||||
blm/blubb.blm |
||||
blm/bleeeh.blm |
||||
blm/rain.blm |
||||
blm/flash.blm |
||||
blm/femina_light.blm |
||||
blm/gator_rogat.blm |
||||
blm/speedit.blm |
||||
blm/scooter.blm |
||||
blm/pixie_in_the_box.blm |
||||
blm/zeichen.blm |
||||
blm/humanistic.blm |
||||
blm/pacman_saga.blm |
||||
blm/die_autobahn.blm |
||||
blm/mytest3.blm |
||||
blm/yin_yang.blm |
||||
blm/klettermensch.blm |
||||
blm/baustein.blm |
||||
blm/pwm.blm |
||||
blm/babelfish.blm |
||||
blm/mytest2.blm |
||||
blm/winslows.blm |
||||
blm/dance.blm |
||||
blm/martelo.blm |
||||
blm/raindrops.blm |
||||
blm/g.blm |
||||
blm/clear.blm |
||||
blm/sport_haelt_fit.blm |
||||
blm/kreise.blm |
||||
blm/railroad.blm |
||||
blm/3D_cube.blm |
||||
blm/balloon.blm |
||||
blm/flipp.blm |
||||
blm/mytest.blm |
||||
blm/tux.blm |
@ -1,178 +0,0 @@
@@ -1,178 +0,0 @@
|
||||
#!/usr/bin/python |
||||
|
||||
import time |
||||
import threading |
||||
import sys |
||||
|
||||
import blup.frame |
||||
import blup.output |
||||
sys.path.append('/var/tmp/r0ket/tools/game') |
||||
#sys.path.append('/var/tmp/r0ket_misc/game_noprint') |
||||
import r0ketrem0te.game |
||||
import pong |
||||
|
||||
logo = [ |
||||
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], |
||||
[1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0], |
||||
[1,0,1,0,1,0,0,1,0,1,1,0,1,0,1,0,0,1], |
||||
[1,0,1,0,1,0,0,1,0,1,0,1,1,0,1,0,0,0], |
||||
[1,1,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,1], |
||||
[1,0,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1], |
||||
[1,0,0,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0], |
||||
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] |
||||
] |
||||
onePlayer = [ |
||||
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], |
||||
[0,0,1,1,0,0,1,1,1,1,0,0,0,1,1,1,0,0], |
||||
[0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0], |
||||
[0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0], |
||||
[0,0,0,1,0,0,1,1,1,1,0,0,0,0,1,0,0,0], |
||||
[0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0], |
||||
[0,0,1,1,1,0,1,0,0,0,0,0,0,0,1,0,0,0], |
||||
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] |
||||
] |
||||
|
||||
def convertPixels(dimension, pixels): |
||||
p = [] |
||||
maxval = dimension.depth - 1 |
||||
for i in range(len(pixels)): |
||||
row = [] |
||||
for j in range(len(pixels[i])): |
||||
if pixels[i][j] == 1: |
||||
row.append((maxval, maxval, maxval)) |
||||
else: |
||||
row.append((0,0,0)) |
||||
p.append(row) |
||||
return p |
||||
|
||||
class R0ketPongPlayer(object): |
||||
def __init__(self, playground, ownPaddle, r0ketPlayer): |
||||
self.__playground = playground |
||||
self.__ownPaddle = ownPaddle |
||||
self.__r0ketPlayer = r0ketPlayer |
||||
self.__ready = False |
||||
|
||||
@property |
||||
def ownPaddle(self): |
||||
return self.__ownPaddle |
||||
|
||||
@property |
||||
def ready(self): |
||||
return self.__ready |
||||
|
||||
def receivedPacket(self, packet): |
||||
if self.__r0ketPlayer is not None: |
||||
if packet.id == self.__r0ketPlayer.id: |
||||
if isinstance(packet, r0ketrem0te.packets.Button): |
||||
print 'button=', packet.button |
||||
if packet.button == 1: |
||||
self.__ownPaddle.nextMoveUp() |
||||
print 'up' |
||||
if packet.button == 2: |
||||
self.__ownPaddle.nextMoveDown() |
||||
print 'down' |
||||
if packet.button == 16: |
||||
self.__ready = True |
||||
|
||||
class R0ketPong(object): |
||||
def __init__(self, out, color=False, port='/dev/ttyACM0', gameName='pong'): |
||||
self.__playground = None |
||||
self.__out = out |
||||
self.__rem0te = r0ketrem0te.game.Game(port, gameName, 83, 87, [ord(x) for x in 'REM0T'], 2, False) |
||||
self.__rem0te.registerPlayerCallback(self.playerCallback) |
||||
self.__color = color |
||||
|
||||
self.__players = [] |
||||
self.__playersChangedCondition = threading.Condition() |
||||
|
||||
if color: |
||||
self.__dimension = blup.frame.FrameDimension(18, 8, 8, 3) |
||||
else: |
||||
self.__dimension = blup.frame.FrameDimension(18, 8, 2, 1) |
||||
|
||||
def playerCallback(self, action, player): |
||||
if self.__playground is None: |
||||
return |
||||
print '\n\n\n\nplayer added',player,'\n\n\n\n' |
||||
if action == 'added' and len(self.__players) < 2: |
||||
if len(self.__players) == 0: |
||||
playerPaddle = self.__playground.leftPaddle |
||||
else: |
||||
playerPaddle = self.__playground.rightPaddle |
||||
player = R0ketPongPlayer(self.__playground, playerPaddle, player) |
||||
self.__rem0te.bridge.registerCallback(player.receivedPacket) |
||||
self.__players.append(player) |
||||
with self.__playersChangedCondition: |
||||
self.__playersChangedCondition.notifyAll() |
||||
|
||||
def runGame(self): |
||||
print 'starting a game...' |
||||
scoreLeft = 0 |
||||
scoreRight = 0 |
||||
|
||||
self.__playground = pong.Playground(18, 8) |
||||
pp = pong.PlaygroundPainter(out, self.__dimension, self.__playground) |
||||
|
||||
while len(self.__players) == 0: |
||||
print 'waiting for player...' |
||||
with self.__playersChangedCondition: |
||||
self.__playersChangedCondition.wait() |
||||
|
||||
frame = blup.frame.Frame(self.__dimension) |
||||
global onePlayer |
||||
if self.__color: |
||||
frame.pixels = convertPixels(self.__dimension, onePlayer) |
||||
else: |
||||
frame.pixels = onePlayer |
||||
self.__out.sendFrame(frame) |
||||
|
||||
while len(self.__players) == 1 and not self.__players[0].ready: |
||||
print 'waiting for another player...' |
||||
time.sleep(1) |
||||
self.__out.sendFrame(frame) |
||||
|
||||
frame = blup.frame.Frame(self.__dimension) |
||||
global logo |
||||
if self.__color: |
||||
frame.pixels = convertPixels(self.__dimension, logo) |
||||
else: |
||||
frame.pixels = logo |
||||
self.__out.sendFrame(frame) |
||||
time.sleep(1) |
||||
|
||||
if len(self.__players) == 1: |
||||
bot = pong.PongBot(self.__playground, self.__playground.rightPaddle, 2) |
||||
self.__players.append(bot) |
||||
|
||||
while max(scoreLeft, scoreRight) < 9: |
||||
winner = self.__playground.play() |
||||
if winner is self.__players[0].ownPaddle: |
||||
scoreLeft += 1 |
||||
else: |
||||
scoreRight += 1 |
||||
pong.displayScore(self.__out, self.__dimension, scoreLeft, scoreRight, 3000) |
||||
|
||||
for i in range(3): |
||||
frame = blup.frame.Frame(self.__dimension) |
||||
self.__out.sendFrame(frame) |
||||
time.sleep(0.5) |
||||
pong.displayScore(self.__out, self.__dimension, scoreLeft, scoreRight, 500) |
||||
frame = blup.frame.Frame(self.__dimension) |
||||
self.__out.sendFrame(frame) |
||||
|
||||
self.__playground = None |
||||
self.__players = [] |
||||
|
||||
|
||||
|
||||
out = blup.output.getOutput('e3blp:localhost:4242') |
||||
|
||||
|
||||
p0ng = R0ketPong(out, color=True) |
||||
while True: |
||||
p0ng.runGame() |
||||
|
||||
sys.exit(0) |
||||
|
||||
|
||||
|
@ -1,152 +0,0 @@
@@ -1,152 +0,0 @@
|
||||
#!/usr/bin/python |
||||
|
||||
# inspired by: |
||||
# http://lodev.org/cgtutor/plasma.html |
||||
|
||||
import sys |
||||
import time |
||||
import math |
||||
#import pygame |
||||
import colorsys |
||||
from neopixel import * |
||||
|
||||
|
||||
class Plasma(object): |
||||
def __init__(self, width, height): |
||||
self.width = width |
||||
self.height = height |
||||
|
||||
self.pixelvalues = [[0] * height for i in xrange(width)] |
||||
self.pixelsReady = False |
||||
self.offset = 0 |
||||
self.update() |
||||
|
||||
@property |
||||
def minValue(self): |
||||
return min(map(min, self.pixelvalues)) |
||||
|
||||
@property |
||||
def maxValue(self): |
||||
return max(map(max, self.pixelvalues)) |
||||
|
||||
def applyPalette(self, palette): |
||||
min = self.minValue |
||||
max = self.maxValue |
||||
norm = lambda x: ((x - min) / max) |
||||
|
||||
pixeldata = [ [None] * self.height for i in xrange(self.width) ] |
||||
|
||||
for x in xrange(self.width): |
||||
rowvalues = self.pixelvalues[x] |
||||
for y in xrange(self.height): |
||||
pixeldata[x][y] = palette.getColorValue(norm(rowvalues[y])) |
||||
|
||||
return pixeldata |
||||
|
||||
def update(self): |
||||
#if self.pixelsReady: |
||||
# return |
||||
self.offset += 1 |
||||
|
||||
for x in xrange(self.width): |
||||
for y in xrange(self.height): |
||||
xx = x+self.offset |
||||
yy = y+self.offset |
||||
#xx = 10*x+self.offset |
||||
#yy = 10*y+self.offset |
||||
p = 128 + 128 * math.sin(xx / 9.0) |
||||
p += 128 + 128 * math.sin(yy / 16.0) |
||||
p += 128 + 128 * math.sin((yy + xx) / 16.0) |
||||
p += 128 + 128 * math.sin(math.sqrt(yy*yy + xx*xx) / 16.0) |
||||
p += 128 + 8 * math.sin(math.sqrt(yy* xx) / 16.0) |
||||
self.pixelvalues[x][y] = p |
||||
self.pixelsReady = True |
||||
|
||||
class Palette(object): |
||||
def __init__(self): |
||||
self.offset = 0 |
||||
self.cache = {} |
||||
|
||||
def getColorValue(self, x): |
||||
x = round(x, 3) |
||||
if self.cache.has_key(x): |
||||
return self.cache[x] |
||||
c = colorsys.hsv_to_rgb((x + self.offset) % 1, 1, 1) |
||||
#c = map(lambda x: int(x * 7), c) |
||||
depth = 255 |
||||
c = map(lambda x: int(x * depth), c) |
||||
self.cache[x] = c |
||||
return c |
||||
|
||||
def update(self): |
||||
self.cache = {} |
||||
self.offset += 0.01 |
||||
if self.offset > 1: |
||||
self.offset -= 1 |
||||
|
||||
############################################## |
||||
|
||||
w = 22 |
||||
h = 16 |
||||
|
||||
#w = 80 |
||||
#h = 18 |
||||
|
||||
scalex = 30 |
||||
scaley = 60 |
||||
|
||||
plasma = Plasma(w,h) |
||||
palette= Palette() |
||||
|
||||
#screen = pygame.display.set_mode((w*scalex, h*scaley)) |
||||
#pygame.display.update() |
||||
|
||||
##dim = blup.frame.FrameDimension(w, h, 8, 3) |
||||
#dim = blup.frame.FrameDimension(w, h, 8, 3) |
||||
##out = blup.output.getOutput('serialblup:/dev/ttyUSB0:115200') |
||||
##out = blup.output.getOutput('colorfulshell') |
||||
##out = blup.output.getOutput('e3blp:bastel0:4242') |
||||
#out = blup.output.getOutput('e3blp') |
||||
|
||||
|
||||
# LED strip configuration: |
||||
LED_COUNT = 352 # Number of LED pixels. |
||||
LED_PIN = 13 # GPIO pin connected to the pixels (must support PWM!). |
||||
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) |
||||
LED_DMA = 5 # DMA channel to use for generating signal (try 5) |
||||
LED_BRIGHTNESS = 50 # Set to 0 for darkest and 255 for brightest |
||||
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) |
||||
LED_PWM = 1 |
||||
|
||||
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_PWM) |
||||
strip.begin() |
||||
|
||||
while True: |
||||
#screen.fill((0,0,0)) |
||||
|
||||
#print 'updating palette...' |
||||
palette.update() |
||||
#print 'updating plasma...' |
||||
plasma.update() |
||||
#print 'applying palette...' |
||||
pixeldata = plasma.applyPalette(palette) |
||||
|
||||
#print 'drawing...' |
||||
#f = blup.frame.Frame(dim) |
||||
for y in xrange(h): |
||||
for x in xrange(w): |
||||
if x%2 == 0: |
||||
lednum = x*h + y |
||||
else: |
||||
lednum = x*h - y + 15 |
||||
strip.setPixelColor(lednum, Color(*pixeldata[x][y])) |
||||
strip.show() |
||||
#print 'done drawing' |
||||
|
||||
#out.sendFrame(f) |
||||
|
||||
#pygame.display.update() |
||||
#print 'done updating' |
||||
#time.sleep(0.01) |
||||
|
||||
|
Loading…
Reference in new issue