Permalink
Browse files

Power button now makes the device enter/leave a special mode where

only the power button has any effect. RPC handling is still enabled
though, except that PlayItem results in an error response.
  • Loading branch information...
1 parent 6ff46ca commit 36ebf46ddbc71c8ff3a40691de9a6f53205cfc0d @Mysingen committed Jul 23, 2011
Showing with 60 additions and 20 deletions.
  1. +34 −6 device.py
  2. +9 −3 display.py
  3. +5 −0 protocol.py
  4. +12 −11 volume.py
View
@@ -16,7 +16,7 @@
from protocol import(Helo, Tactile, Stat, JsonResult, Terms, Dsco, Ping,
StrmStatus, Ls, GetItem, ID, JsonMessage)
-from display import Display, TRANSITION
+from display import Display, TRANSITION, BRIGHTNESS
from tactile import IR
from menu import Menu, CmFile, CmAudio, CmDir, make_item
from player import Player
@@ -26,6 +26,10 @@
from volume import Volume
from cm import CmConnection
+class POWER:
+ ON = True
+ OFF = False
+
# private message classes. only used to implement public API's
class AddCM:
def __init__(self, cm):
@@ -84,6 +88,7 @@ class Device(Thread):
playlist = None
volume = None # Volume object
watchdog = None
+ power = POWER.ON
def __init__(self, wire, out_queue):
#print 'Device __init__'
@@ -435,10 +440,12 @@ def run(self):
continue
if isinstance(msg, PlayItem):
+ if self.power == POWER.OFF:
+ msg.respond(4, u'Device is powered off', 0,False,False)
+ continue
#print 'dm PlayItem %s' % msg
if not self.player.play(msg.item, msg.seek):
- errstr = u'Unplayable item'
- msg.respond(4, errstr, 0, False, False)
+ msg.respond(4, u'Unplayable item', 0, False, False)
continue
if msg.item == self.menu.focused():
(guid, render) = self.player.ticker()
@@ -533,6 +540,11 @@ def handle_ls_r(msg_reg, response, orig_msg, user):
continue
if isinstance(msg, Tactile):
+ # is the device powered up? if not, discard all messages
+ # except POWER ON.
+ if self.power == POWER.OFF and msg.code != IR.POWER:
+ continue
+
# abort handling if the stress level isn't high enough.
# note that the stress is always "enough" if stress is
# zero or the event doesn't have a stress map at all.
@@ -747,9 +759,25 @@ def handle_ls_r(msg_reg, response, orig_msg, user):
self.volume.down()
render = self.volume.meter
- elif msg.code == IR.POWER or msg.code == IR.HARD_POWER:
- self.stop()
- pass
+ elif msg.code == IR.POWER:
+ if self.power == POWER.ON:
+ self.player.stop()
+ self.volume.mute(True)
+ self.display.set_brightness(BRIGHTNESS.OFF, False)
+ self.save_settings()
+ self.save_playlist()
+ self.power = POWER.OFF
+ else:
+ self.power = POWER.ON
+ self.volume.mute(False)
+ self.display.clear()
+ self.display.set_brightness(self.display.brightness)
+ self.menu.set_focus(self.menu.get_item('Playlist'))
+ (guid, render) = self.menu.ticker(curry=True)
+ transition = TRANSITION.SCROLL_UP
+
+ elif msg.code == IR.HARD_POWER:
+ print 'hard power'
elif msg.code in [IR.NUM_1, IR.NUM_2, IR.NUM_3,
IR.NUM_4, IR.NUM_5, IR.NUM_6,
View
@@ -81,12 +81,13 @@ def dump_settings(self):
'visualizer': all_visualizers.index(self.cur_visual)
}
- def set_brightness(self, brightness):
+ def set_brightness(self, brightness, remember=True):
if brightness < BRIGHTNESS.OFF or brightness > BRIGHTNESS.FULL:
raise Exception, 'Unknown brightness code %d' % brightness
- self.brightness = brightness
+ if remember:
+ self.brightness = brightness
grfb = Grfb()
- grfb.brightness = BRIGHTNESS.map[self.brightness]
+ grfb.brightness = BRIGHTNESS.map[brightness]
self.wire.send(grfb.serialize())
def next_brightness(self):
@@ -116,3 +117,8 @@ def show(self, transition):
grfe.transition = transition
grfe.bitmap = self.canvas.bitmap
self.wire.send(grfe.serialize())
+
+ def clear(self):
+ self.canvas.clear()
+ self.show(TRANSITION.NONE)
+
View
@@ -432,6 +432,11 @@ class Aude(Command):
analog = True
digital = True
+ def __init__(self, analog, digital):
+ assert type(analog) == type(digital) == bool
+ self.analog = analog
+ self.digital = digital
+
def serialize(self):
cmd = 'aude'
params = ( struct.pack('<B', self.analog)
View
@@ -6,14 +6,14 @@
class Volume:
wire = None
- mute = False
+ _mute = False
preamp = 0 # int 0-255
left = 0 # int 0-100
right = 0 # int 0-100
meter = None # VolumeMeter renderer
timeout = None # indicates how long the meter should be kept visible
- def __init__(self, wire, mute, preamp, left, right, visual):
+ def __init__(self, wire, preamp, left, right, visual, **ignore):
if not type(wire) == SlimWire:
raise Exception('Invalid Volume.wire object: %s' % str(wire))
if not type(preamp) == int or preamp < 0 or preamp > 255:
@@ -23,20 +23,18 @@ def __init__(self, wire, mute, preamp, left, right, visual):
if not type(right) == int or right < 0 or right > 100:
raise Exception('Invalid Volume.right value: %s' % str(right))
self.wire = wire
- self._mute = mute
self.preamp = preamp
self.left = left
self.right = right
if visual:
self.meter = VolumeMeter()
- self.mute(mute, mute)
+ self.mute(self._mute)
self.set_volume(left, right)
self.timeout = datetime.now()
@classmethod
def dump_defaults(cls):
return {
- 'mute' : False,
'preamp': 255,
'left' : 70,
'right' : 70,
@@ -45,20 +43,23 @@ def dump_defaults(cls):
def dump_settings(self):
return {
- 'mute' : self._mute,
'preamp': self.preamp,
'left' : self.left,
'right' : self.right,
'visual': self.meter != None
}
- def mute(self, analog, digital):
- aude = Aude()
- aude.analog = not analog # not mute == enable
- aude.digital = not digital
+ # TODO: figure out why the aude command has no effect on the Classic model.
+ # the outputs are always enabled. is it a firmware revision issue?
+ def mute(self, value):
+ self._mute = value
+ aude = Aude(not value, not value) # not mute == enable
self.wire.send(aude.serialize())
if self.meter:
- self.meter.curry(0)
+ if value:
+ self.meter.curry(0)
+ else:
+ self.meter.curry(self.left)
def up(self):
self.set_volume(self.left + 1, self.right + 1)

0 comments on commit 36ebf46

Please sign in to comment.