Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Jam
diff options
context:
space:
mode:
authoramartin <olpc@xo-05-28-21.localdomain>2007-09-11 07:07:37 (GMT)
committer amartin <olpc@xo-05-28-21.localdomain>2007-09-11 07:07:37 (GMT)
commit4acb6bfbda5e60b7770feaf6dfb4a0d0197f8cc8 (patch)
tree22abca768ce201d2a2da5f57f9c0b7845b424348 /Jam
parentb5d19eaeb6ea59cb6564d64d4519e788d0985d74 (diff)
jam shortcuts
Diffstat (limited to 'Jam')
-rw-r--r--Jam/Block.py103
-rw-r--r--Jam/Desktop.py5
-rw-r--r--Jam/JamMain.py63
-rw-r--r--Jam/Popup.py47
4 files changed, 188 insertions, 30 deletions
diff --git a/Jam/Block.py b/Jam/Block.py
index 53048c2..f0789fd 100644
--- a/Jam/Block.py
+++ b/Jam/Block.py
@@ -23,7 +23,6 @@ class Block():
PAD = 4
KEYSIZE = 26
- KEYOFFSET = HEIGHT - PAD - PAD - KEYSIZE
KEYMASK_START = 309
def __init__( self, owner, data ):
@@ -157,6 +156,9 @@ class Block():
if self.parent: return self.parent.getRoot()
return self
+ def isActive( self ):
+ return self.active
+
def setActive( self, state ):
self.active = state
self.invalidate_rect( not self.dragging )
@@ -168,7 +170,16 @@ class Block():
self.data[ key ] = value
def testMouseOver( self, event ):
- if self.child: return self.child.testMouseOver( event )
+ if self.child:
+ ret = self.child.testMouseOver( event )
+ if ret: return ret
+
+ x = event.x - self.x
+ y = event.y - self.y
+
+ if 0 <= x <= self.width and 0 <= y <= self.height:
+ return -1
+
return False
def button_press( self, event ):
@@ -348,9 +359,12 @@ class Instrument(Block):
class Drum(Block):
MASK_START = 100
-
+
+ KEYRECT = [ Block.PAD - 1, Block.HEIGHT + 1 - Block.PAD - Block.KEYSIZE, Block.KEYSIZE, Block.KEYSIZE ]
+ KEYRECT += [ KEYRECT[0]+KEYRECT[2], KEYRECT[1]+KEYRECT[3] ]
+
#::: data format:
- # { "name": name, "id": instrumentId [ , "page": pageId, "volume": 0-1, "reverb": 0-1, "beats": 2-12, "regularity": 0-1 ] }
+ # { "name": name, "id": instrumentId [ , "page": pageId, "volume": 0-1, "reverb": 0-1, "beats": 2-12, "regularity": 0-1, "key": shortcut ] }
#:::
def __init__( self, owner, data ):
Block.__init__( self, owner, data )
@@ -369,6 +383,13 @@ class Drum(Block):
self.data["beats"] = random.randint(2, 12)
if not "regularity" in self.data.keys():
self.data["regularity"] = random.random()
+ if "key" not in self.data.keys():
+ self.data["key"] = None
+
+ self.owner.mapKey( self.data["key"], self )
+ self.keyImage = [ self.owner.getKeyImage( self.data["key"], False ),
+ self.owner.getKeyImage( self.data["key"], True ) ]
+
self.img = [ self.owner.getInstrumentImage( self.data["id"], False ),
self.owner.getInstrumentImage( self.data["id"], True ) ]
@@ -377,13 +398,26 @@ class Drum(Block):
self.regenerate()
def destroy( self ):
+ self.owner.mapKey( None, self, self.data["key"] )
self.owner.noteDB.deletePages( [ self.data["page"] ] )
Block.destroy( self )
def setData( self, key, value ):
- self.data[key] = value
if key == "beats":
+ self.data["beats"] = value
self.owner.noteDB.updatePage( self.data["page"], PARAMETER.PAGE_BEATS, value )
+
+ elif key == "key":
+ oldKey = self.data["key"]
+ self.data["key"] = value
+ self.keyImage = [ self.owner.getKeyImage( value, False ),
+ self.owner.getKeyImage( value, True ) ]
+ self.invalidate_rect()
+ self.owner.mapKey( value, self, oldKey )
+
+ else:
+ self.data[key] = value
+
if self.active:
self.owner.updateDrum( self )
@@ -415,6 +449,27 @@ class Drum(Block):
return False
+ def testMouseOver( self, event ):
+ ret = self.testWithinKey( event )
+ if ret: return ret
+
+ x = event.x - self.x
+ y = event.y - self.y
+
+ if 0 <= x <= self.width and 0 <= y <= self.height:
+ return -1
+
+ return False
+
+ def testWithinKey( self, event ):
+ x = event.x - self.x
+ y = event.y - self.y
+
+ if Drum.KEYRECT[0] <= x <= Drum.KEYRECT[4] and Drum.KEYRECT[1] <= y <= Drum.KEYRECT[5]:
+ return self
+
+ return False
+
def _doButtonPress( self, event ): # we were hit with a button press
pass
@@ -443,13 +498,22 @@ class Drum(Block):
# draw block
self.gc.set_clip_origin( self.x-Drum.MASK_START, self.y-self.height )
pixmap.draw_drawable( self.gc, self.img[self.active], x-self.x, y-self.y, x, y, width, height )
-
+
+ # draw key
+ self.gc.set_clip_origin( self.x+Drum.KEYRECT[0]-Block.KEYMASK_START, self.y+Drum.KEYRECT[1] )
+ pixmap.draw_drawable( self.gc, self.keyImage[ self.active ], 0, 0, self.x+Drum.KEYRECT[0], self.y+Drum.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE )
+
def drawHighlight( self, startX, startY, stopX, stopY, pixmap ):
self.gc.foreground = self.owner.colors["Border_Highlight"]
self.gc.set_clip_origin( self.x-Drum.MASK_START, self.y )
pixmap.draw_rectangle( self.gc, True, self.x, self.y, self.width, self.height )
+ def drawKeyHighlight( self, pixmap ):
+ self.gc.foreground = self.owner.colors["Border_Highlight"]
+ self.gc.set_clip_origin( self.x+Drum.KEYRECT[0]-Block.KEYMASK_START, self.y+Drum.KEYRECT[1]-Block.KEYSIZE )
+ pixmap.draw_rectangle( self.gc, True, self.x+Drum.KEYRECT[0], self.y+Drum.KEYRECT[1], Block.KEYSIZE, Block.KEYSIZE )
+
def regenerate( self ):
self.data["page"] = self.owner.owner._generateDrumLoop( self.data["id"], self.data["beats"], self.data["regularity"], self.data["reverb"], self.data["page"] )
if self.active:
@@ -472,7 +536,7 @@ class Loop(Block):
MASK_BEAT = MASK_START + HEAD
MASK_TAIL = MASK_START + HEAD + BEAT*3
- KEYRECT = [ HEAD + Block.PAD, Block.KEYOFFSET, Block.KEYSIZE, Block.KEYSIZE ]
+ KEYRECT = [ HEAD + Block.PAD, Block.HEIGHT - 2*Block.PAD - Block.KEYSIZE, Block.KEYSIZE, Block.KEYSIZE ]
KEYRECT += [ KEYRECT[0]+KEYRECT[2], KEYRECT[1]+KEYRECT[3] ]
#::: data format:
@@ -505,6 +569,8 @@ class Loop(Block):
self.owner.getLoopImage( self.data["id"], True ) ]
def destroy( self ):
+ if self.keyActive:
+ self.owner.mapKey( None, self, self.data["key"] )
self.owner.noteDB.deletePages( [ self.data["id"] ] )
Block.destroy( self )
@@ -535,16 +601,24 @@ class Loop(Block):
self.owner.getLoopImage( self.data["id"], True ) ]
def setData( self, key, value ):
- self.data[key] = value
if key == "beats":
self.owner.noteDB.updatePage( self.data["id"], PARAMETER.PAGE_BEATS, value )
self._updateWidth()
self.updateLoop()
+ self.data["beats"] = value
+
elif key == "key":
+ oldKey = self.data["key"]
+ self.data["key"] = value
self.keyImage = [ self.owner.getKeyImage( value, False ),
self.owner.getKeyImage( value, True ) ]
self.invalidate_rect()
+ if self.keyActive:
+ self.owner.mapKey( value, self, oldKey )
+
+ else:
+ self.data[key] = value
def substitute( self, block ):
self.invalidateBranch( True )
@@ -611,6 +685,7 @@ class Loop(Block):
if self.parent.type == Instrument:
self.keyActive = True
+ self.owner.mapKey( self.data["key"], self )
else:
root = self.getRoot()
if root.type == Instrument:
@@ -627,6 +702,7 @@ class Loop(Block):
loopRoot = None
self.keyActive = False
+ self.owner.mapKey( None, self, self.data["key"] )
Block._removeParent( self )
@@ -638,7 +714,16 @@ class Loop(Block):
self.owner.updateLoop( loopRoot )
def testMouseOver( self, event ):
- return self.testWithinKey( event )
+ ret = self.testWithinKey( event )
+ if ret: return ret
+
+ x = event.x - self.x
+ y = event.y - self.y
+
+ if 0 <= x <= self.width and 0 <= y <= self.height:
+ return -1
+
+ return False
def testWithinKey( self, event ):
if not self.keyActive:
diff --git a/Jam/Desktop.py b/Jam/Desktop.py
index e8a8afd..7b1acba 100644
--- a/Jam/Desktop.py
+++ b/Jam/Desktop.py
@@ -144,6 +144,9 @@ class Desktop( gtk.EventBox ):
for i in range( len(self.blocks)-1, -1, -1 ):
self.deleteBlock( self.blocks[i] )
+ def mapKey( self, key, block, oldKey = None ):
+ self.owner.mapKey( key, block, oldKey )
+
def getInstrumentImage( self, id, active = False ):
return self.owner.getInstrumentImage( id, active )
@@ -321,6 +324,8 @@ class Desktop( gtk.EventBox ):
return
for i in range(blockCount-1, -1, -1):
over = self.blocks[i].testMouseOver( event )
+ if over == -1:
+ break # over block but no hotspot
if over:
if self.overKey != self.blocks[i]:
if self.overKey:
diff --git a/Jam/JamMain.py b/Jam/JamMain.py
index 012aa21..c339ae6 100644
--- a/Jam/JamMain.py
+++ b/Jam/JamMain.py
@@ -2,6 +2,7 @@
import pygtk
pygtk.require( '2.0' )
import gtk
+import pango
from SubActivity import SubActivity
@@ -33,6 +34,8 @@ import xdrlib
import time
import gobject
import Util.Network as Net
+from sugar.presence import presenceservice
+from sugar.graphics.xocolor import XoColor
from math import sqrt
@@ -60,6 +63,9 @@ class JamMain(SubActivity):
self.paused = False
+ presenceService = presenceservice.get_instance()
+ self.xoOwner = presenceService.get_owner()
+
#-- Drawing -------------------------------------------
def darken( colormap, hex ):
hexToDec = { "0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9, "A":10, "B":11, "C":12, "D":13, "E":14, "F":15, "a":10, "b":11, "c":12, "d":13, "e":14, "f":15 }
@@ -74,20 +80,25 @@ class JamMain(SubActivity):
b = 255 - int( 0.7*(255-(16*hexToDec[hex[5]] + hexToDec[hex[6]])) )
return colormap.alloc_color( r*256, g*256, b*256 )
+ xoColorKey = self.xoOwner.props.color
+ if not xoColorKey:
+ xoColorKey = ( "#8D8D8D,#FFDDEA" )
+ xoColor = XoColor( xoColorKey )
+
win = gtk.gdk.get_default_root_window()
self.gc = gtk.gdk.GC( win )
colormap = gtk.gdk.colormap_get_system()
self.colors = { "bg": colormap.alloc_color( Config.PANEL_BCK_COLOR ),
"black": colormap.alloc_color( style.COLOR_BLACK.get_html() ),
- "Picker_Bg": colormap.alloc_color( "#404040" ),
- "Picker_Bg_Inactive": colormap.alloc_color( "#808080" ),
- #"Picker_Bg": colormap.alloc_color( style.COLOR_TOOLBAR_GREY.get_html() ),
- #"Picker_Bg_Inactive": colormap.alloc_color( style.COLOR_BUTTON_GREY.get_html() ),
+ #"Picker_Bg": colormap.alloc_color( "#404040" ),
+ #"Picker_Bg_Inactive": colormap.alloc_color( "#808080" ),
+ "Picker_Bg": colormap.alloc_color( style.COLOR_TOOLBAR_GREY.get_html() ),
+ "Picker_Bg_Inactive": colormap.alloc_color( style.COLOR_BUTTON_GREY.get_html() ),
"Picker_Fg": colormap.alloc_color( style.COLOR_WHITE.get_html() ),
- "Border_Active": colormap.alloc_color( "#590000" ),
+ "Border_Active": colormap.alloc_color( xoColor.get_stroke_color() ), #colormap.alloc_color( "#590000" ),
"Border_Inactive": colormap.alloc_color( "#8D8D8D" ),
"Border_Highlight": colormap.alloc_color( "#FFFFFF" ),
- "Bg_Active": colormap.alloc_color( "#FFDDEA" ),
+ "Bg_Active": colormap.alloc_color( xoColor.get_fill_color() ), #colormap.alloc_color( "#FFDDEA" ),
"Bg_Inactive": colormap.alloc_color( "#DBDBDB" ),
"Preview_Note_Fill": colormap.alloc_color( Config.BG_COLOR ),
"Preview_Note_Border": colormap.alloc_color( Config.FG_COLOR ),
@@ -176,7 +187,7 @@ class JamMain(SubActivity):
# use hardware key codes to work on any keyboard layout (hopefully)
self.valid_shortcuts = { 18:"9", 19:"0", 20:"-", 21:"=",
32:"O", 33:"P", 34:"[", 35:"]",
- 48:";", 51:"'",
+ 47:";", 48:"'", 51:"\\",
60:".", 61:"/",
None:" " }
for key in self.valid_shortcuts.keys():
@@ -248,6 +259,8 @@ class JamMain(SubActivity):
self.keyboardListener = None
self.recordingNote = None
+ self.keyMap = {}
+
# default instrument
self._updateInstrument( Config.INSTRUMENTS["kalimba"].instrumentId, 0.5 )
self.instrumentStack = []
@@ -326,6 +339,24 @@ class JamMain(SubActivity):
def onKeyPress( self, widget, event ):
key = event.hardware_keycode
+ if key in self.keyMap.keys():
+ activate = True
+ for block in self.keyMap[key]:
+ if block.isActive():
+ activate = False
+ break
+ if activate:
+ for block in self.keyMap[key]:
+ if not block.isActive():
+ if block.type == Block.Drum: self.desktop.activateDrum( block )
+ elif block.type == Block.Loop: self.desktop.activateLoop( block )
+ else:
+ for block in self.keyMap[key]:
+ if block.isActive():
+ if block.type == Block.Drum: self.desktop.deactivateDrum( block )
+ elif block.type == Block.Loop: self.desktop.deactivateLoop( block )
+ return
+
if self.key_dict.has_key( key ): # repeated press
return
@@ -732,6 +763,19 @@ class JamMain(SubActivity):
def setKeyboardListener( self, listener ):
self.keyboardListener = listener
+ def mapKey( self, key, block, oldKey = None ):
+ if oldKey != None and block in self.keyMap[oldKey]:
+ self.keyMap[oldKey].remove( block )
+
+ if key == None:
+ return
+
+ if key not in self.keyMap.keys():
+ self.keyMap[key] = []
+
+ if block not in self.keyMap[key]:
+ self.keyMap[key].append( block )
+
#==========================================================
# Pixmaps
@@ -788,6 +832,8 @@ class JamMain(SubActivity):
def prepareKeyImage( self, key ):
win = gtk.gdk.get_default_root_window()
pangolayout = self.create_pango_layout( _(self.valid_shortcuts[key]) )
+ fontDesc = pango.FontDescription( "bold" )
+ pangolayout.set_font_description( fontDesc )
extents = pangolayout.get_pixel_extents()
x = ( Block.Block.KEYSIZE - extents[1][2] ) // 2
y = ( Block.Block.KEYSIZE - extents[1][3] ) // 2
@@ -925,7 +971,8 @@ class JamMain(SubActivity):
except:
print "bad ip4_address"
if self.network.isHost():
- # TODO how do I figure out if this buddy is me?
+ if buddy == self.xoOwner:
+ return
if buddy.props.ip4_address:
self.network.introducePeer( buddy.props.ip4_address )
else:
diff --git a/Jam/Popup.py b/Jam/Popup.py
index 8bca64c..3d21e7f 100644
--- a/Jam/Popup.py
+++ b/Jam/Popup.py
@@ -1297,7 +1297,7 @@ class Shortcut( Popup ):
# match keycodes from JamMain.valid_shortcuts
layout = [ [ 0.0, [ 18, 19, 20, 21 ] ],
[ 0.3, [ 32, 33, 34, 35 ] ],
- [ 1.6, [ 48, 51 ] ],
+ [ 1.7, [ 47, 48, 51 ] ],
[ 1.1, [ 60, 61 ] ] ]
self.GUI["keyBox"] = gtk.VBox()
@@ -1335,10 +1335,7 @@ class Shortcut( Popup ):
self.key = None
def setBlock( self, block ):
- self.settingBlock = True
-
- if self.key != None:
- self.GUI[self.key].set_active( False )
+ self.ignoreToggle = True
self.block = block
self.key = self.block.getData( "key" )
@@ -1346,10 +1343,23 @@ class Shortcut( Popup ):
if self.key != None:
self.GUI[self.key].set_active( True )
- self.settingBlock = False
+ self.ignoreToggle = False
Popup.setBlock( self, block )
+ def on_key_press( self, widget, event ):
+ key = event.hardware_keycode
+ if key in self.owner.valid_shortcuts.keys():
+ self.block.setData( "key", key )
+ if self.key != None: # clear old key
+ self.ignoreToggle = True
+ self.GUI[self.key].set_active( False )
+ self.key = None
+ self.ignoreToggle = False
+ self.popdown( True )
+ else:
+ self.owner.onKeyPress( widget, event )
+
def keyExpose( self, widget, event ):
self.gc.set_clip_mask( self.owner.blockMask )
self.gc.set_clip_origin( event.area.x - Block.Block.KEYMASK_START, event.area.y )
@@ -1357,20 +1367,31 @@ class Shortcut( Popup ):
return True
def keyToggled( self, widget ):
- if widget.get_active() and not self.settingBlock:
- if self.key != None:
+ if self.ignoreToggle:
+ return
+
+ if widget.get_active():
+ self.block.setData( "key", widget.key )
+
+ self.ignoreToggle = True
+
+ if self.key != None: # clear old key
self.GUI[self.key].set_active( False )
+ self.key = None
- self.key = widget.key
+ widget.set_active( False )
- self.block.setData( "key", self.key )
-
- self.popdown( True )
+ self.ignoreToggle = False
+
+ self.popdown( True )
def handleNone( self, widget ):
if self.key != None:
+ self.ignoreToggle = True
self.GUI[self.key].set_active( False )
self.key = None
- self.block.setData( "key", self.key )
+ self.ignoreToggle = False
+
+ self.block.setData( "key", None )
self.popdown( True )