-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e3b26b4
Showing
15 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.pyc | ||
zbap.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.
Empty file.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#!/bin/bash | ||
python Zbap.py & |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.