Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Edit/rm/NoteView.py
diff options
context:
space:
mode:
Diffstat (limited to 'Edit/rm/NoteView.py')
-rw-r--r--Edit/rm/NoteView.py253
1 files changed, 253 insertions, 0 deletions
diff --git a/Edit/rm/NoteView.py b/Edit/rm/NoteView.py
new file mode 100644
index 0000000..ac139a1
--- /dev/null
+++ b/Edit/rm/NoteView.py
@@ -0,0 +1,253 @@
+import pygtk
+pygtk.require( '2.0' )
+import gtk
+
+from Framework.Constants import Constants
+from Framework.CSound.CSoundConstants import CSoundConstants
+from GUI.GUIConstants import GUIConstants
+from GUI.Core.NoteParametersWindow import NoteParametersWindow
+
+from BackgroundView import SELECTNOTES
+
+#----------------------------------------------------------------------
+# TODO: currently we are only using CSoundNotes,
+# - this should updated to handle generic Note objects
+#----------------------------------------------------------------------
+
+#----------------------------------------------------------------------
+# A view for the (CSound)Note class
+#----------------------------------------------------------------------
+class NoteView:
+ #-----------------------------------
+ # initialization
+ # TODO: not sure if passing in beatsPerPageAdjustment is the best way to go about it
+ #-----------------------------------
+ def __init__( self, note, track, beatsPerPageAdjustment ):
+ self.note = note
+
+ self.track = track
+ self.beatsPerPageAdjustment = beatsPerPageAdjustment
+ self.posOffset = (0,0)
+
+ self.baseOnset = self.basePitch = self.baseDuration = self.lastDragX = self.lastDragY = self.lastDragW = 0 # note dragging properties
+
+ self.sampleNote = None
+
+ self.parentSize = False
+
+ self.selected = False
+ self.potentialDeselect = False
+
+
+ def getNoteParameters( self ):
+ self.note.pitch = self.noteParameters.pitchAdjust.value
+ self.note.amplitude = self.noteParameters.amplitudeAdjust.value
+ self.note.pan = self.noteParameters.panAdjust.value
+ self.note.attack = self.noteParameters.attackAdjust.value
+ self.note.decay = self.noteParameters.decayAdjust.value
+ self.note.reverbSend = self.noteParameters.reverbSendAdjust.value
+ self.note.filterType = self.noteParameters.filterType
+ self.note.filterCutoff = self.noteParameters.filterCutoff
+ self.note.tied = self.noteParameters.tied
+ self.note.overlap = self.noteParameters.overlap
+
+ def handleButtonPress( self, emitter, event ):
+ eX = event.x - self.x
+ eY = event.y - self.y
+
+ if eX < 0 or eX > self.width \
+ or eY < 0 or eY > self.height:
+ return False
+
+ if event.button == 3:
+ self.noteParameters = NoteParametersWindow( self.note, self.getNoteParameters )
+ return True
+
+ if event.type == gtk.gdk._2BUTTON_PRESS: # select bar
+ self.potentialDeselect = False
+ emitter.selectNotesByBar( self.track.getID(), self.x, self.x+self.width )
+ elif event.type == gtk.gdk._3BUTTON_PRESS: # select track
+ self.potentialDeselect = False
+ emitter.selectNotesByTrack( self.track.getID() )
+ else:
+ if self.getSelected(): # we already selected, might want to delected
+ self.potentialDeselect = True
+ else:
+ emitter.selectNotes( { self.track.getID(): [ self ] } )
+ self.updateSampleNote( self.note.pitch )
+
+ percent = eX/self.width
+ if percent < 0.3: emitter.setCurrentAction( "note-drag-onset", self )
+ elif percent > 0.7: emitter.setCurrentAction( "note-drag-duration", self )
+ else: emitter.setCurrentAction( "note-drag-pitch", self )
+
+
+ emitter.dirty()
+
+ return True
+
+ def handleButtonRelease( self, emitter, event, buttonPressCount ):
+
+ if self.potentialDeselect:
+ self.potentialDeselect = False
+ emitter.deselectNotes( { self.track.getID(): [ self ] } )
+
+ self.clearSampleNote()
+
+ emitter.doneCurrentAction()
+
+ return True
+
+ def noteDrag( self, emitter, dx, dy, dw ):
+ self.potentialDeselect = False
+
+ ticksPerPixel = (round( self.beatsPerPageAdjustment.value, 0 ) * Constants.TICKS_PER_BEAT) / self.parentSize[0]
+ stepPerPixel = (Constants.NUMBER_OF_POSSIBLE_PITCHES-1) / (self.parentSize[1] - self.height)
+ pitchPerStep = (Constants.MAXIMUM_PITCH-Constants.MINIMUM_PITCH)/(Constants.NUMBER_OF_POSSIBLE_PITCHES-1)
+
+ if dx != self.lastDragX:
+ self.lastDragX = dx
+ self.note.onset = self.baseOnset + int(dx*ticksPerPixel)
+
+ if dy != self.lastDragY:
+ self.lastDragY = dy
+ newPitch = self.basePitch + round(-dy*stepPerPixel)*pitchPerStep
+ self.note.pitch = newPitch
+ self.updateSampleNote( newPitch )
+
+ if dw != self.lastDragW:
+ self.lastDragW = dw
+ self.note.duration = self.baseDuration + int(dw*ticksPerPixel)
+
+ self.updateTransform( False )
+
+ def doneNoteDrag( self, emitter ):
+ self.baseOnset = self.note.onset
+ self.basePitch = self.note.pitch
+ self.baseDuration = self.note.duration
+
+ self.lastDragX = 0
+ self.lastDragY = 0
+ self.lastDragW = 0
+
+ self.clearSampleNote()
+
+
+ def handleMarqueeSelect( self, emitter, start, stop ):
+ intersectionY = [ max(start[1],self.y), min(stop[1],self.y+self.height) ]
+ if intersectionY[0] > intersectionY[1]:
+ return False
+
+ intersectionX = [ max(start[0],self.x), min(stop[0],self.x+self.width) ]
+ if intersectionX[0] > intersectionX[1]:
+ return False
+
+ return True
+
+ #-----------------------------------
+ # draw
+ #-----------------------------------
+
+ def setPositionOffset( self, offset ):
+ self.posOffset = offset
+ if self.parentSize: self.updateTransform( False )
+
+ def draw( self, context ):
+ lineW = GUIConstants.NOTE_BORDER_SIZE
+ lineWDIV2 = lineW/2.0
+ context.set_line_width( lineW )
+
+ context.move_to( self.x + lineWDIV2, self.y + lineWDIV2 )
+ context.rel_line_to( self.width - lineW, 0 )
+ context.rel_line_to( 0, self.height - lineW )
+ context.rel_line_to( -self.width + lineW, 0 )
+ context.close_path()
+
+ #background
+ colour = 1 - ( ( self.note.amplitude * 0.7 ) + 0.3 )
+ context.set_source_rgb( colour, colour, colour )
+ context.fill_preserve()
+
+ #border
+ if self.selected: context.set_source_rgb( 1, 1, 1 )
+ else: context.set_source_rgb( 0, 0, 0 )
+ context.stroke()
+
+ #-----------------------------------
+ # update
+ #-----------------------------------
+
+ def updateTransform( self, parentSize ):
+ if parentSize: self.parentSize = parentSize
+ self.width = int( self.parentSize[0] * self.note.duration / (round( self.beatsPerPageAdjustment.value, 0 ) * Constants.TICKS_PER_BEAT) )
+ self.height = round( max( GUIConstants.MINIMUM_NOTE_HEIGHT, self.parentSize[1] / (Constants.NUMBER_OF_POSSIBLE_PITCHES-1) ) )
+ self.x = int( self.parentSize[0] * self.note.onset / (round( self.beatsPerPageAdjustment.value, 0 ) * Constants.TICKS_PER_BEAT) ) \
+ + self.posOffset[0]
+ self.y = round( (self.parentSize[1]-self.height) * ( Constants.MAXIMUM_PITCH - self.note.pitch ) / (Constants.NUMBER_OF_POSSIBLE_PITCHES-1) ) \
+ + self.posOffset[1]
+
+ def checkX( self, startx, stopx ):
+ if self.x >= startx and self.x < stopx: return True
+ else: return False
+
+ def getStartTick( self ):
+ return self.note.onset
+
+ def getEndTick( self ):
+ return self.note.onset + self.note.duration
+
+ def updateDragLimits( self, dragLimits, leftBound, rightBound, widthBound ):
+ pixelsPerTick = self.parentSize[0] / (round( self.beatsPerPageAdjustment.value, 0 ) * Constants.TICKS_PER_BEAT)
+ pixelsPerPitch = (self.parentSize[1] - self.height) / (Constants.MAXIMUM_PITCH - Constants.MINIMUM_PITCH)
+ left = (leftBound - self.note.onset) * pixelsPerTick
+ right = (rightBound - self.note.duration - self.note.onset) * pixelsPerTick
+ up = (self.note.pitch - Constants.MAXIMUM_PITCH) * pixelsPerPitch
+ down = (self.note.pitch - Constants.MINIMUM_PITCH) * pixelsPerPitch
+ short = (Constants.MINIMUM_NOTE_DURATION - self.note.duration) * pixelsPerTick
+ long = (widthBound - self.note.duration - self.note.onset) * pixelsPerTick
+
+ if dragLimits[0][0] < left: dragLimits[0][0] = left
+ if dragLimits[0][1] > right: dragLimits[0][1] = right
+ if dragLimits[1][0] < up: dragLimits[1][0] = up
+ if dragLimits[1][1] > down: dragLimits[1][1] = down
+ if dragLimits[2][0] < short: dragLimits[2][0] = short
+ if dragLimits[2][1] > long: dragLimits[2][1] = long
+
+ # store the current loc as a reference point
+ self.baseOnset = self.note.onset
+ self.basePitch = self.note.pitch
+ self.baseDuration = self.note.duration
+
+ def updateSampleNote( self, pitch ):
+ if self.sampleNote == None:
+ self.sampleNote = self.note.clone()
+ #TODO clean this up:
+ if CSoundConstants.INSTRUMENTS[ self.sampleNote.instrumentFlag ].csoundInstrumentID == 103:
+ self.sampleNote.duration = 100
+ else:
+ self.sampleNote.duration = -1
+ self.sampleNote.play()
+
+ elif self.sampleNote.pitch != pitch:
+ self.sampleNote.pitch = pitch
+ self.sampleNote.play()
+
+ def clearSampleNote( self ):
+ if self.sampleNote != None:
+ self.sampleNote.duration = 0
+ self.sampleNote.play()
+ del self.sampleNote
+ self.sampleNote = None
+
+ #-----------------------------------
+ # Selection
+ #-----------------------------------
+
+ def setSelected( self, state ):
+ if self.selected != state:
+ self.selected = state
+ return True # state changed
+ return False # state is the same
+
+ def getSelected( self ):
+ return self.selected