forked from Blinkenbunt/blup
Fr3deric
7 years ago
33 changed files with 0 additions and 2060 deletions
@ -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 @@ |
|||||||
<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 @@ |
|||||||
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 @@ |
|||||||
[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 @@ |
|||||||
#!/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 @@ |
|||||||
#!/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 @@ |
|||||||
#!/bin/bash |
|
||||||
|
|
||||||
python blphub.py -o blp:bastel0:4242 localhost:4242:1:1000 localhost:42421:2:3500 |
|
||||||
|
|
@ -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 @@ |
|||||||
# 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 @@ |
|||||||
|
|
||||||
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 @@ |
|||||||
|
|
||||||
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 @@ |
|||||||
# 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 @@ |
|||||||
#!/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 @@ |
|||||||
#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 @@ |
|||||||
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 @@ |
|||||||
#!/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 @@ |
|||||||
#!/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