Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
2m committed Feb 24, 2013
0 parents commit e3b26b4
Show file tree
Hide file tree
Showing 15 changed files with 212 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
zbap.log
36 changes: 36 additions & 0 deletions MpdActor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pykka, mpd, logging

class MpdActor(pykka.ThreadingActor):
def __init__(self):
super(MpdActor, self).__init__()

self.client = mpd.MPDClient()
self.client.timeout = 10
self.client.idletimeout = None
self.client.connect("localhost", 6600)

def getCurrentSong(self):
try:
name = self.client.currentsong()["file"]
elapsed = int(float(self.client.status()["elapsed"]))

return {"name": name, "elapsed": elapsed}
except KeyError:
return None

def playByNameFrom(self, name, playFrom):
try:
self.client.clear()
self.client.add(name)
self.client.play()

currentSong = self.client.currentsong()
if playFrom + 20 > int(currentSong['time']):
# play from start, if trying to play too close from the end
playFrom = 0

logging.getLogger('zbap').info('Playing %s from %s' % (name, playFrom))
self.client.seekid(currentSong['id'], playFrom)

except mpd.CommandError, e:
logging.getLogger('zbap').error('Exception: %s' % e.message)
52 changes: 52 additions & 0 deletions StateActor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import json

from TickActor import TickActor

STATE_FILE = 'data/state.json'

class StateActor(TickActor):
def __init__(self, mpdActor, sleepSeconds):
super(StateActor, self).__init__(sleepSeconds)

self.mpdActor = mpdActor

def doTick(self):

current = self.mpdActor.getCurrentSong().get()
if current == None:
return

state = self.loadState()
state["current"] = current
try:
state["played"][current["name"]] = current["elapsed"]
except KeyError:
state["played"] = {}
state["played"][current["name"]] = current["elapsed"]

self.saveState(state)

def playFromLastState(self, name=None, fromStart=False):
state = self.loadState()
if name == None:
name = state["current"]["name"]

elapsed = 0
if not fromStart:
try:
elapsed = state["played"][name]
except KeyError:
pass

self.mpdActor.playByNameFrom(name, elapsed)

def loadState(self):
try:
with open(STATE_FILE, 'r') as stateFile:
return json.load(stateFile)
except (IOError, ValueError) as e:
return {}

def saveState(self, state):
with open(STATE_FILE, 'w') as stateFile:
json.dump(state, stateFile)
21 changes: 21 additions & 0 deletions TagActor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pykka, logging
from pygame import mixer

import data.tags as tags

class TagActor(pykka.ThreadingActor):
def __init__(self, stateActor):
super(TagActor, self).__init__()

self.stateActor = stateActor

mixer.init()
self.ack = mixer.Sound('data/ack.wav')
self.ack.set_volume(1.0)

def playByTag(self, tag, fromStart=False):
try:
self.ack.play()
self.stateActor.playFromLastState(tags.tags[tag], fromStart)
except KeyError:
logging.getLogger('zbap').error('No such tag %s' % tag)
21 changes: 21 additions & 0 deletions TickActor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pykka

class TickActor(pykka.ThreadingActor):
def __init__(self, sleepSeconds):
super(TickActor, self).__init__()

self.sleepSeconds = sleepSeconds
self.intervalSeconds = 2
self.intervalCounter = 0

def tick(self):
self.intervalCounter += 1
if self.intervalSeconds / self.sleepSeconds <= self.intervalCounter:
try:
self.doTick()
finally:
self.intervalCounter = 0

def doTick(self):
pass

37 changes: 37 additions & 0 deletions WebActor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pykka, web

tagActor = None

urls = (
'/play/([0-9]*)', 'Play',
'/play/([0-9]*)/fromStart', 'FromStart'
)

class Play:
def GET(self, tag):
tagActor.playByTag(tag)
return 'Called tagActor with tag: %s\n' % tag

class FromStart:
def GET(self, tag):
tagActor.playByTag(tag, fromStart=True)
return 'Called tagActor with tag: %s and fromStart=True\n' % tag

def runInThread(function):
from threading import Thread
t = Thread(target=function)
t.setDaemon(True)
t.start()

def runWebApp():
app = web.application(urls, globals())
app.run()

class WebActor(pykka.ThreadingActor):
def __init__(self, tagAct):
super(WebActor, self).__init__()

global tagActor
tagActor = tagAct

runInThread(runWebApp)
33 changes: 33 additions & 0 deletions Zbap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import pykka, logging

from time import sleep

from WebActor import WebActor
from MpdActor import MpdActor
from StateActor import StateActor
from TagActor import TagActor

sleepSeconds = 0.5

if __name__ == "__main__":

logging.basicConfig(filename='zbap.log', format="%(asctime)s [%(module)s.%(funcName)s] %(levelname)s: %(message)s")
logging.getLogger('pykka').setLevel(logging.DEBUG)
logging.getLogger('zbap').setLevel(logging.DEBUG)

mpdActor = MpdActor.start().proxy()
stateActor = StateActor.start(mpdActor, sleepSeconds).proxy()

tagActor = TagActor.start(stateActor).proxy()
webActor = WebActor.start(tagActor).proxy()

stateActor.playFromLastState()

try:
while True:
stateActor.tick()
sleep(sleepSeconds)
except KeyboardInterrupt:
print "Exiting main loop."

pykka.ActorRegistry.stop_all()
Binary file added data/.tags.py.swp
Binary file not shown.
Empty file added data/__init__.py
Empty file.
Binary file added data/ack.wav
Binary file not shown.
1 change: 1 addition & 0 deletions data/state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"current": {"name": "cob_today.mp3", "elapsed": 279}, "played": {"cob_today.mp3": 279, "1.mp3": 8, "2.mp3": 31}}
5 changes: 5 additions & 0 deletions data/tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
tags = {
'001': 'cob_today.mp3',
'002': '1.mp3',
'003': '2.mp3',
}
2 changes: 2 additions & 0 deletions run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
python Zbap.py &
2 changes: 2 additions & 0 deletions stop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
ps a | grep "python Zbap.py" | cut -d" " -f 2 | xargs kill -9
Empty file added zbap.py
Empty file.

0 comments on commit e3b26b4

Please sign in to comment.