diff options
author | Nat <natcl@hotmail.com> | 2007-08-17 17:18:16 (GMT) |
---|---|---|
committer | Nat <natcl@hotmail.com> | 2007-08-17 17:18:16 (GMT) |
commit | 6e89806275673d7785aab0e0a44355eee678aea2 (patch) | |
tree | bdffc4d1d45ac5fe6d501ce30accaeddf6444bb9 /Edit | |
parent | abc2fe2a2eb9cff483111756f994ae1f92daa883 (diff) | |
parent | 0c7820662df4a6b0ff2bd8a07018e44e6c3df765 (diff) |
Merge branch 'master' of git+ssh://natcl@dev.laptop.org/git/projects/tamtam
Diffstat (limited to 'Edit')
-rw-r--r-- | Edit/EditToolbars.py | 182 | ||||
-rw-r--r-- | Edit/MainWindow.py | 47 | ||||
-rw-r--r-- | Edit/NoteInterface.py | 2 | ||||
-rw-r--r-- | Edit/TuneInterface.py | 14 |
4 files changed, 210 insertions, 35 deletions
diff --git a/Edit/EditToolbars.py b/Edit/EditToolbars.py index 1f02c5f..24b0ab2 100644 --- a/Edit/EditToolbars.py +++ b/Edit/EditToolbars.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import gtk + import Config from sugar.graphics.toolbutton import ToolButton from sugar.graphics.toggletoolbutton import ToggleToolButton @@ -11,6 +12,7 @@ from Util.ThemeWidgets import * from gettext import gettext as _ #Generation palette +import gobject from Generation.Generator import GenerationParameters #Generation palette and Properties palette from Generation.GenerationConstants import GenerationConstants @@ -372,6 +374,13 @@ class generationPalette(Palette): self.slidersBox.pack_start(self.XYSlider2, False, False, padding = 5) self.slidersBox.pack_start(self.XYSlider3, False, False, padding = 5) + self.previewBox = gtk.HBox() + self.previewDA = gtk.DrawingArea() + self.previewDA.set_size_request( -1, 100 ) + self.previewDA.connect( "size-allocate", self.handlePreviewAlloc ) + self.previewDA.connect( "expose-event", self.handlePreviewExpose ) + self.previewBox.pack_start( self.previewDA, True, True, padding = 5 ) + self.scaleBoxHBox = gtk.HBox() self.scaleBoxLabel = gtk.Label(_('Scale: ')) self.scaleBox = BigComboBox() @@ -408,29 +417,87 @@ class generationPalette(Palette): self.decisionBox.pack_start(self.previewButton, False, False, padding = 5) self.mainBox.pack_start(self.slidersBox, False, False, padding = 5) + self.mainBox.pack_start( self.previewBox, False, False, padding = 5 ) self.mainBox.pack_start(self.scaleModeBox, False, False, padding = 5) self.mainBox.pack_start(self.decisionBox, False, False, padding = 5) self.mainBox.show_all() self.set_content(self.mainBox) + #-- preview drawing ----------------------------------- + win = gtk.gdk.get_default_root_window() + self.gc = gtk.gdk.GC( win ) + self.parametersDirty = False + self.drawingPreview = False + self.predrawTarget = 0 + self.predrawIdleAbort = False + # self.predrawBuffer is initialized in handlePreviewAlloc + pix = gtk.gdk.pixbuf_new_from_file( Config.IMAGE_ROOT+"sampleBG.png" ) + self.sampleBg = gtk.gdk.Pixmap( win, pix.get_width(), pix.get_height() ) + self.sampleBg.draw_pixbuf( self.gc, pix, 0, 0, 0, 0, pix.get_width(), pix.get_height(), gtk.gdk.RGB_DITHER_NONE ) + self.sampleBg.endOffset = pix.get_width()-5 + self.sampleNoteHeight = 7 + if True: # load clipmask + pix = gtk.gdk.pixbuf_new_from_file(Config.IMAGE_ROOT+'sampleNoteMask.png') + pixels = pix.get_pixels() + stride = pix.get_rowstride() + channels = pix.get_n_channels() + bitmap = "" + byte = 0 + shift = 0 + for j in range(pix.get_height()): + offset = stride*j + for i in range(pix.get_width()): + r = pixels[i*channels+offset] + if r != "\0": byte += 1 << shift + shift += 1 + if shift > 7: + bitmap += "%c" % byte + byte = 0 + shift = 0 + if shift > 0: + bitmap += "%c" % byte + byte = 0 + shift = 0 + self.sampleNoteMask = gtk.gdk.bitmap_create_from_data( None, bitmap, pix.get_width(), pix.get_height() ) + self.sampleNoteMask.endOffset = pix.get_width()-3 + + colormap = self.previewDA.get_colormap() + self.colors = { "Beat_Line": colormap.alloc_color( "#959595", True, True ), + "Note_Border": colormap.alloc_color( Config.BG_COLOR, True, True ), + "Note_Fill": colormap.alloc_color( Config.FG_COLOR, True, True ) } + def handleXAdjustment1( self, data ): self.rythmDensity = self.XAdjustment1.value * .01 + self.parametersChanged() def handleYAdjustment1( self, data ): self.rythmRegularity = self.YAdjustment1.value * .01 + self.parametersChanged() def handleXAdjustment2( self, data ): self.pitchRegularity = self.XAdjustment2.value * .01 + self.parametersChanged() def handleYAdjustment2( self, data ): self.pitchStep = self.YAdjustment2.value * .01 + self.parametersChanged() def handleXAdjustment3( self, data ): self.duration = self.XAdjustment3.value * .01 + self.parametersChanged() def handleYAdjustment3( self, data ): self.silence = self.YAdjustment3.value * .01 + self.parametersChanged() + + def handleScale(self, widget, data = None): + self.scale = widget.props.value + self.parametersChanged() + + def handleMode( self, widget, data = None ): + self.pattern = widget.props.value + self.parametersChanged() def getGenerationParameters( self ): return GenerationParameters( self.rythmDensity, @@ -444,12 +511,6 @@ class generationPalette(Palette): self.pattern, self.scale ) - def handleScale(self, widget, data = None): - self.scale = widget.props.value - - def handleMode( self, widget, data = None ): - self.pattern = widget.props.value - def cancel(self, widget, data = None): self.popdown(True) @@ -487,7 +548,8 @@ class generationPalette(Palette): for i in range(len(rythmSequence)): if random() > parameters.silence: trackNotes.append([rythmSequence[i], pitchSequence[i], gainSequence[i], durationSequence[i]]) - print trackNotes + #print "-------------------------------------------------------",trackNotes + return ( trackNotes, beat ) def makeGainSequence( self, onsetList ): gainSequence = [] @@ -513,6 +575,112 @@ class generationPalette(Palette): elif len( onsetList ) == 1: durationSequence.append( ( barLength - onsetList[0] ) * Utils.prob2( table_duration )) return durationSequence + + def parametersChanged( self ): + if not self.drawingPreview: + self.drawPreview() + else: + self.parametersDirty = True + + def drawPreview( self, force = False ): + if self.drawingPreview and not force: + return # should never happen + + notes, beats = self.previewGenerator( self.getGenerationParameters() ) + self.parametersDirty = False + + if force: + if self.drawingPreview: + self.predrawIdleAbort = True + self._idleDraw( notes, beats, True, True ) + else: + self.drawingPreview = True + gobject.idle_add( self._idleDraw, notes, beats, True, False ) + + def _idleDraw( self, notes, beats, fresh, force ): + if self.predrawIdleAbort and not force: + self.predrawIdleAbort = False + return False + + pixmap = self.predrawBuffer[self.predrawTarget] + + if fresh: + # draw bg + pixmap.draw_drawable( self.gc, self.sampleBg, 0, 0, 0, 0, self.previewDA.width-5, self.previewDA.height ) + pixmap.draw_drawable( self.gc, self.sampleBg, self.sampleBg.endOffset, 0, self.previewDA.width-5, 0, 5, self.previewDA.height ) + # draw beat lines + self.gc.set_line_attributes( Config.BEAT_LINE_SIZE, gtk.gdk.LINE_ON_OFF_DASH, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER ) + self.gc.foreground = self.colors["Beat_Line"] + for i in range(1,beats): + x = self.beatSpacing[beats][i] + pixmap.draw_line( self.gc, x, 1, x, self.previewDA.height-1 ) + + if not force: + gobject.idle_add( self._idleDraw, notes, beats, False, False ) + return False + + if force: N = len(notes) + else: N = min( 3, len( notes ) ) # adjust this value to get a reasonable response + + self.gc.set_clip_mask( self.sampleNoteMask ) + for i in range( N ): # draw N notes + note = notes.pop() + x = self.ticksToPixels( beats, note[0] ) + endX = self.ticksToPixels( beats, note[0] + note[3] ) - 3 # include end cap offset + width = endX - x + y = self.pitchToPixels( note[1] ) + # draw fill + self.gc.foreground = self.colors["Note_Fill"] + self.gc.set_clip_origin( x, y-self.sampleNoteHeight ) + pixmap.draw_rectangle( self.gc, True, x+1, y+1, width+1, self.sampleNoteHeight-2 ) + # draw border + self.gc.foreground = self.colors["Note_Border"] + self.gc.set_clip_origin( x, y ) + pixmap.draw_rectangle( self.gc, True, x, y, width, self.sampleNoteHeight ) + self.gc.set_clip_origin( endX-self.sampleNoteMask.endOffset, y ) + pixmap.draw_rectangle( self.gc, True, endX, y, 3, self.sampleNoteHeight ) + self.gc.set_clip_rectangle( self.clearClipMask ) + + if not len(notes): + self.predrawTarget = not self.predrawTarget + self.previewDA.queue_draw() + + self.drawingPreview = False + + if self.parametersDirty: + self.drawPreview() + + return False + + return True + + def handlePreviewAlloc( self, widget, allocation ): + win = gtk.gdk.get_default_root_window() + self.previewDA.width = allocation.width + self.previewDA.height = allocation.height + self.predrawBuffer = [ gtk.gdk.Pixmap( win, allocation.width, allocation.height ), + gtk.gdk.Pixmap( win, allocation.width, allocation.height ) ] + self.clearClipMask = gtk.gdk.Rectangle( 0, 0, allocation.width, allocation.height ) + + self.pitchPerPixel = float(Config.NUMBER_OF_POSSIBLE_PITCHES-1) / (self.previewDA.height - self.sampleNoteHeight) + self.pixelsPerPitch = float(self.previewDA.height - self.sampleNoteHeight)/(Config.MAXIMUM_PITCH - Config.MINIMUM_PITCH) + self.pixelsPerTick = [0] + [ self.previewDA.width/float(i*Config.TICKS_PER_BEAT) for i in range(1,Config.MAXIMUM_BEATS+1) ] + self.ticksPerPixel = [0] + [ 1.0/self.pixelsPerTick[i] for i in range(1,Config.MAXIMUM_BEATS+1) ] + + self.beatSpacing = [[0]] + for i in range(1,Config.MAXIMUM_BEATS+1): + self.beatSpacing.append( [ self.ticksToPixels( i, Config.TICKS_PER_BEAT*j ) for j in range(i) ] ) + + self.drawPreview( True ) + + def handlePreviewExpose( self, widget, event ): + widget.window.draw_drawable( self.gc, self.predrawBuffer[not self.predrawTarget], event.area.x, event.area.y, event.area.x, event.area.y, event.area.width, event.area.height ) + + def ticksToPixels( self, beats, ticks ): + return int(round( ticks * self.pixelsPerTick[beats] )) + def pitchToPixels( self, pitch ): + return int(round( ( Config.MAXIMUM_PITCH - pitch ) * self.pixelsPerPitch )) + class propertiesPalette(Palette): def __init__(self, label, edit): diff --git a/Edit/MainWindow.py b/Edit/MainWindow.py index 770d4b9..eedc3ff 100644 --- a/Edit/MainWindow.py +++ b/Edit/MainWindow.py @@ -52,7 +52,7 @@ class MainWindow( SubActivity ): for i in [6,7,8,9,10]: self.csnd.setTrackVolume(100, i) self.trackCount = 6 - + def init_data( ): TP.ProfileBegin("init_data") self._data = {} @@ -116,7 +116,7 @@ class MainWindow( SubActivity ): #------------------------------------------------------------------------ - # page + # page self.GUI["2page"] = gtk.HBox() self.GUI["2main"].pack_start( self.GUI["2page"], False ) if 1: # + instrument panel @@ -213,7 +213,7 @@ class MainWindow( SubActivity ): self.GUI["2instrumentPanel"].pack_start( self.GUI["2instrument4Box"] ) # + + drum box self.GUI["2drumBox"] = formatRoundBox( RoundHBox(), Config.BG_COLOR ) - self.GUI["2drumBox"].set_size_request( -1, 165 ) + self.GUI["2drumBox"].set_size_request( -1, 165 ) self.GUI["2drumVolBox"] = gtk.VBox() self.GUI["2drumvolumeAdjustment"] = gtk.Adjustment( self._data["track_volume"][4], 0, 100, 1, 1, 0 ) #self.GUI["2drumvolumeAdjustment"].connect( "value_changed", self.onTrackVolumeChanged, 4 ) @@ -241,7 +241,7 @@ class MainWindow( SubActivity ): self.GUI["2page"].pack_start( self.trackInterface, False, False ) #------------------------------------------------------------------------ - # tune interface + # tune interface if 1: # + tune interface self.GUI["2tuneHBox"] = RoundHBox( fillcolor = Config.TOOLBAR_BCK_COLOR, bordercolor = Config.TOOLBAR_BCK_COLOR, radius = 0 ) self.GUI["2tuneScrollLeftButton"] = ImageButton( Config.IMAGE_ROOT+"arrowEditLeft.png", Config.IMAGE_ROOT+"arrowEditLeftDown.png", Config.IMAGE_ROOT+"arrowEditLeftOver.png", backgroundFill = Config.TOOLBAR_BCK_COLOR ) @@ -377,7 +377,7 @@ class MainWindow( SubActivity ): first = self.noteDB.addPage( -1, NoteDB.Page(4, instruments = instrumentsIds) ) self.displayPage( first ) - + self.createNewTune( None ) # Toolbar @@ -386,7 +386,7 @@ class MainWindow( SubActivity ): self.activity.toolbox.add_toolbar(_('Compose'), self._mainToolbar) self.activity.toolbox.set_current_toolbar(1) self._mainToolbar.show() - + self.show_all() #gtk command self.setContext( CONTEXT.PAGE ) @@ -892,6 +892,8 @@ class MainWindow( SubActivity ): else: self.handleInstrumentChanged( ( id, None ), False ) btn.setSecondary( None ) + pages = self.tuneInterface.getSelectedIds() + self.noteDB.setInstrument2( pages, id, -1 ) # data is tuple ( trackId, instrumentName ) def handleInstrumentChanged( self, data, primary = True ): @@ -1336,11 +1338,11 @@ class MainWindow( SubActivity ): for i in range(Config.NUMBER_OF_TRACKS): if self.trackInstrument[i].instrumentId != page.instruments[i]: self.trackInstrument[i] = Config.INSTRUMENTSID[page.instruments[i]] - if i == Config.NUMBER_OF_TRACKS-1: + if i == Config.NUMBER_OF_TRACKS-1: btn = self.GUI["2drumButton"] btn.setImage( "main", self.GUI["2instrumentIcons"][self.trackInstrument[i].name] ) btn.setImage( "alt", self.GUI["2instrumentIcons"][self.trackInstrument[i].name] ) - else: + else: btn = self.GUI["2instrument%dButton"%(i+1)] btn.setPrimary( self.GUI["2instrumentIcons"][self.trackInstrument[i].name] ) if self.trackInstrument2[i] != None: @@ -1394,7 +1396,7 @@ class MainWindow( SubActivity ): self.GUI["9propertiesPopup"].move( balloc.x + winLoc[0] - 100, balloc.y - walloc.height + winLoc[1] ) else: self.GUI["9propertiesPopup"].hide() - + def pageDelete( self, pageIds = -1, instruments = False ): if pageIds == -1: @@ -1920,7 +1922,7 @@ class MainWindow( SubActivity ): class InstrumentButton( gtk.DrawingArea ): - + def __init__( self, owner, index, backgroundFill ): gtk.DrawingArea.__init__( self ) @@ -1929,13 +1931,13 @@ class InstrumentButton( gtk.DrawingArea ): self.win = gtk.gdk.get_default_root_window() self.gc = gtk.gdk.GC( self.win ) - + colormap = self.get_colormap() self.color = { "background": colormap.alloc_color( backgroundFill, True, True ), "divider": colormap.alloc_color( "#000", True, True ), - "+/-": colormap.alloc_color( "#818286", True, True ), + "+/-": colormap.alloc_color( Config.FG_COLOR, True, True ), "+/-Highlight": colormap.alloc_color( "#FFF", True, True ) } - + self.pixmap = None self.primary = None self.primaryWidth = self.primaryHeight = 1 @@ -1975,15 +1977,15 @@ class InstrumentButton( gtk.DrawingArea ): def button_press( self, widget, event ): - self.clicked = "PRIMARY" + self.clicked = "PRIMARY" self.hover = None - + if event.x >= self.hotspots[0][0] and event.x <= self.hotspots[0][2] \ and event.y >= self.hotspots[0][1] and event.y <= self.hotspots[0][3]: self.clicked = "HOTSPOT_0" elif self.secondary != None: - + if event.x >= self.hotspots[1][0] and event.x <= self.hotspots[1][2] \ and event.y >= self.hotspots[1][1] and event.y <= self.hotspots[1][3]: self.clicked = "HOTSPOT_1" @@ -2022,7 +2024,7 @@ class InstrumentButton( gtk.DrawingArea ): if self.hover != "HOTSPOT_0": self.hover = "HOTSPOT_0" self.queue_draw() - + elif self.secondary != None \ and event.x >= self.hotspots[1][0] and event.x <= self.hotspots[1][2] \ @@ -2037,7 +2039,7 @@ class InstrumentButton( gtk.DrawingArea ): def leave_notify( self, widget, event ): if event.mode != gtk.gdk.CROSSING_NORMAL: - return + return if self.hover != None: self.hover = None if self.clicked == None: @@ -2057,10 +2059,10 @@ class InstrumentButton( gtk.DrawingArea ): if img != None: self.secondaryWidth = img.get_width() self.secondaryHeight = img.get_height() - self.secondaryOffset = self.secondaryHeight//2 + self.secondaryOffset = self.secondaryHeight//2 if self.pixmap: self.secondaryX = (self.alloc.width - self.secondaryWidth) // 2 - self.secondaryY = self.alloc.height//2 + self.secondaryY = self.alloc.height//2 if self.pixmap: self._updatePixmap() @@ -2076,7 +2078,7 @@ class InstrumentButton( gtk.DrawingArea ): else: self.pixmap.draw_pixbuf( self.gc, self.primary, 0, 0, self.primaryX, self.primaryY, self.primaryWidth, self.primaryHeight, gtk.gdk.RGB_DITHER_NONE ) self.queue_draw() - + def expose( self, widget, event ): self.window.draw_drawable( self.gc, self.pixmap, 0, 0, 0, 0, self.alloc.width, self.alloc.height ) self.gc.set_line_attributes( 4, gtk.gdk.LINE_SOLID, gtk.gdk.CAP_ROUND, gtk.gdk.JOIN_MITER ) @@ -2092,10 +2094,9 @@ class InstrumentButton( gtk.DrawingArea ): self.gc.foreground = self.color["+/-"] self.window.draw_line( self.gc, self.hotspots[1][0], self.hotspots[1][5], self.hotspots[1][2], self.hotspots[1][5] ) else: - if self.clicked == "HOTSPOT_0" or self.hover == "HOTSPOT_0": + if self.clicked == "HOTSPOT_0" or self.hover == "HOTSPOT_0": self.gc.foreground = self.color["+/-Highlight"] else: self.gc.foreground = self.color["+/-"] self.window.draw_line( self.gc, self.hotspots[0][0], self.hotspots[0][5], self.hotspots[0][2], self.hotspots[0][5] ) self.window.draw_line( self.gc, self.hotspots[0][4], self.hotspots[0][1], self.hotspots[0][4], self.hotspots[0][3] ) - diff --git a/Edit/NoteInterface.py b/Edit/NoteInterface.py index a51fe2c..a5035dd 100644 --- a/Edit/NoteInterface.py +++ b/Edit/NoteInterface.py @@ -54,7 +54,7 @@ class NoteInterface: r = self.baseColors[0][0] + int(self.baseColors[1][0]*self.note.cs.amplitude) g = self.baseColors[0][1] + int(self.baseColors[1][1]*self.note.cs.amplitude) b = self.baseColors[0][2] + int(self.baseColors[1][2]*self.note.cs.amplitude) - self.color = self.colormap.alloc_color( r, g, b, True, True ) + self.color = self.colormap.alloc_color( r, g, b, True, True ) # TODO potential memory leak? self.oldAmplitude = self.note.cs.amplitude self.updateTransform() diff --git a/Edit/TuneInterface.py b/Edit/TuneInterface.py index 54095e6..63141a3 100644 --- a/Edit/TuneInterface.py +++ b/Edit/TuneInterface.py @@ -184,6 +184,7 @@ class TuneInterface( gtk.EventBox ): self.baseWidth = allocation.width self.visibleEndX = self.baseWidth self.baseHeight = allocation.height + self.updateSize() self.alloced = True self.width = allocation.width self.height = allocation.height @@ -205,11 +206,16 @@ class TuneInterface( gtk.EventBox ): self.visibleEndX = self.visibleX + self.baseWidth def updateSize( self ): - if not self.alloced: return - width = self.pageOffset + self.noteDB.getPageCount()*Config.PAGE_THUMBNAIL_WIDTH + width = self.noteDB.getPageCount()*Config.PAGE_THUMBNAIL_WIDTH + 5 # add extra 5 for the first page self.waitingForAlloc = True - self.set_size_request( max( self.baseWidth, width), -1 ) - self.invalidate_rect( self.visibleX, 0, self.baseWidth, self.height ) + if width < self.baseWidth: + self.pageOffset = ( self.baseWidth - width ) // 2 + 5 + else: + self.pageOffset = 5 + + if self.alloced: + self.set_size_request( max( self.baseWidth, width), -1 ) + self.invalidate_rect( self.visibleX, 0, self.baseWidth, self.height ) def handleButtonPress( self, widget, event ): if event.button != 1: |