[gcompris] music activities, merge beth's master commit ffc32f9b
- From: Bruno Coudoin <bcoudoin src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcompris] music activities, merge beth's master commit ffc32f9b
- Date: Sun, 9 Sep 2012 21:33:46 +0000 (UTC)
commit 7b8064743e20823ae7e7626533089b867eec783c
Author: Bruno Coudoin <bruno coudoin free fr>
Date: Sun Sep 9 21:57:25 2012 +0200
music activities, merge beth's master commit ffc32f9b
added several additional melodies & more trebleClef notes,
added sound effects, attempted to add "ask before erase" feature
note_names: added sound effects, corrected z-order
https://github.com/bethmhadley/GCompris/commit/ffc32f9b717f13669a25d8a0bc33633893cdbc82
src/note_names-activity/note_names.py | 15 ++-
src/piano_composition-activity/gcomprismusic.py | 120 +++++++++++++++++---
.../piano_composition.py | 94 +++++++++++----
3 files changed, 183 insertions(+), 46 deletions(-)
---
diff --git a/src/note_names-activity/note_names.py b/src/note_names-activity/note_names.py
index c7e5c44..93698af 100644
--- a/src/note_names-activity/note_names.py
+++ b/src/note_names-activity/note_names.py
@@ -95,10 +95,11 @@ class Gcompris_note_names:
'''
if hasattr(self, 'staff'):
self.staff.eraseAllNotes()
- if self.rootitem:
- self.rootitem.remove()
if hasattr(self, 'noteButtonsRootItem'):
self.noteButtonsRootItem.remove()
+ if self.rootitem:
+ self.rootitem.remove()
+
self.rootitem = goocanvas.Group(parent=
self.gcomprisBoard.canvas.get_root_item())
@@ -324,7 +325,7 @@ They also form the C Major Scale. Notice that the note positions are different t
self.noteButtonsRootItem.remove()
self.noteButtonsRootItem = goocanvas.Group(parent=
- self.gcomprisBoard.canvas.get_root_item(), x=0, y=0)
+ self.rootitem, x=0, y=0)
def drawNoteButton(x, y, numID, play_sound_on_click):
@@ -337,7 +338,7 @@ They also form the C Major Scale. Notice that the note positions are different t
color = 'white'
text = getKeyNameFromID(numID, self.sharpNotation)
vars(self)[str(numID)] = goocanvas.Text(
- parent=self.noteButtonsRootItem,
+ parent=self.rootitem,
x=x,
y=y,
text=text,
@@ -354,7 +355,7 @@ They also form the C Major Scale. Notice that the note positions are different t
height=20,
line_width=.5,
fill_color=color)
-
+ vars(self)[str(numID)].raise_(None)
vars(self)[str(numID)].scale(2.0, 2.0)
vars(self)[str(numID)].translate(-250, -150)
rect.scale(2, 2)
@@ -411,15 +412,17 @@ They also form the C Major Scale. Notice that the note positions are different t
'''
self.master_is_not_ready = True
- self.timers.append(gobject.timeout_add(2000, self.readyToSoundAgain))
+ self.timers.append(gobject.timeout_add(1500, self.readyToSoundAgain))
g = self.selectedNoteObject.get_data('numID')
c = self.currentNote.numID
if g == c or (c == 8 and g == 1):
if not self.repeatThisNoteLaterPlease:
self.remainingNotesToIdentify.remove(c)
if self.remainingNotesToIdentify == []:
+ #gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.NOTE)
displayHappyNote(self, lambda: self.set_level(self.gcomprisBoard.level + 1))
else:
+ # gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.NOTE)
displayHappyNote(self, self.prepareGame)
self.repeatThisNoteLaterPlease = False
else:
diff --git a/src/piano_composition-activity/gcomprismusic.py b/src/piano_composition-activity/gcomprismusic.py
index e9b4c14..97ed3fe 100644
--- a/src/piano_composition-activity/gcomprismusic.py
+++ b/src/piano_composition-activity/gcomprismusic.py
@@ -31,6 +31,7 @@ import gcompris
import gcompris.utils
import gcompris.skin
import goocanvas
+import gcompris.bonus
import pango
import gcompris.sound
from gcompris import gcompris_gettext as _
@@ -57,7 +58,9 @@ NOTE_COLOR_SCHEME = {1:'#FF0000',
7:'#FF1493',
- 6: '#FF6347',
8:'#FF0000',
- 9:'#FF7F00'
+ 9:'#FF7F00',
+ 10:'#FFFF00',
+ 11:'#32CD32'
}
# this is unique to the English notation system
# translators must modify this dictionary for each language
@@ -246,6 +249,7 @@ class Staff():
>>> self.newStaff.drawNote(EighthNote(5, 'trebleClef', self.newStaff.rootitem))
>>> self.newStaff.drawNote(WholeNote(-3, 'trebleClef', self.newStaff.rootitem))
'''
+
if self.dynamicNoteSpacing:
if note.numID < 0:
self.noteSpacingX = 28
@@ -308,10 +312,32 @@ class Staff():
return
note1.flag.props.visibility = goocanvas.ITEM_INVISIBLE
note2.flag.props.visibility = goocanvas.ITEM_INVISIBLE
-
+ if (note1.numID > 8 and note2.numID > 8) or (note1.numID <= 8 and note2.numID <= 8) or (note1.numID > 8 and note2.numID < -5):
+ if note2.numID <= 8 and note2.numID >= -5:
+ x2 = note2.x + 7
+ y2 = note2.y - 34
+ if note1.numID <= 8:
+ x1 = note1.x + 7
+ y1 = note1.y - 34
+ if note2.numID > 8 or note2.numID < -5:
+ x2 = note2.x - 7
+ y2 = note2.y + 34
+ if note1.numID > 8:
+ x1 = note1.x - 7
+ y1 = note1.y + 34
+ else:
+ x2 = note2.x + 7
+ y2 = note2.y - 34
+ x1 = note1.x + 7
+ y1 = note1.y - 34
+ if note2.numID > 8 or note2.numID < -5:
+ goocanvas.Item.rotate(note2.noteHead, 180, note2.x, note2.y)
+ if note1.numID > 8:
+ goocanvas.Item.rotate(note1.noteHead, 180, note1.x, note1.y)
note1.tupleBar = goocanvas.polyline_new_line(note1.rootitem,
- note1.x + 7, note1.y - 34, note2.x + 7, note2.y - 34,
+ x1, y1, x2, y2,
stroke_color_rgba=0x121212D0, line_width=4)
+
note1.isTupleBound = True
note2.isTupleBound = True
@@ -388,7 +414,7 @@ class Staff():
else:
self.eraseAllNotes()
- def eraseAllNotes(self, widget=None, target=None, event=None):
+ def eraseAllNotes(self, widget=None, target=None, event=None, ask_user=False):
'''
remove all notes from staff, deleting them from self.noteList, and
restores self.currentLineNumto 1 and self.currentNoteXCoordinate to the
@@ -398,6 +424,7 @@ class Staff():
'''
#if not ready(self):
# return False
+
for o in self._beatNumLabels:
o.remove()
for n in self.noteList:
@@ -427,6 +454,13 @@ class Staff():
if hasattr(self, 'noteText'):
self.noteText.remove()
+ def setClefVisibility(self,visibile=True):
+ if visibile == True:
+ for o in self._staffImages:
+ o.props.visibility = goocanvas.ITEM_VISIBLE
+ else:
+ for o in self._staffImages:
+ o.props.visibility = goocanvas.ITEM_INVISIBLE
def play_it(self, noteIndexToPlay, playingLineOnly=False):
'''
NOT A PUBLIC METHOD
@@ -533,6 +567,8 @@ class Staff():
'''
if hasattr(self, 'newClef'):
self.newClef.clear()
+
+ self.eraseAllNotes()
self.clear()
keys = melodyString.split()
staffName = keys[0]
@@ -551,12 +587,18 @@ class Staff():
for exp in keys[1:]:
duration = int(exp[-1])
n = exp[0:-1]
+ # these are added rather hakishly just to accommodate some new melodies
+ # it's easy to improve this code...I just don't have time now
if n == '2C':
numID = 8
elif n == '2D':
numID = 9
elif n == '2C#':
numID = -6
+ elif n == '2E':
+ numID = 10
+ elif n == '2F':
+ numID = 11
else:
numID = getIDFromKeyName(str(exp[0:-1]))
if not numID:
@@ -694,6 +736,7 @@ class Staff():
def updateToEighth(self, widget=None, target=None, event=None):
self.currentNoteType = 8
self.drawFocusRect(256.5, 112, True)
+
def updateToQuarter(self, widget=None, target=None, event=None):
self.currentNoteType = 4
self.drawFocusRect(292, 112)
@@ -717,7 +760,7 @@ class TrebleStaff(Staff):
# for use in getNoteYCoordinateMethod
self.positionDict = {1:26, 2:22, 3:16, 4:9, 5:3,
- 6:-4, 7:-10, 8:-17, 9:-23}
+ 6:-4, 7:-10, 8:-17, 9:-23, 10:-29,11:-35}
def drawStaff(self):
self._drawClefs()
@@ -753,7 +796,7 @@ class BassStaff(Staff):
# for use in getNoteYCoordinateMethod
self.positionDict = {1:-4, 2:-11, 3:-17, 4:-24, 5:-30,
- 6:-36, 7:-42, 8:-48, 9:-52}
+ 6:-36, 7:-42, 8:-48, 9:-52, 10:-58, 11:-64}
def drawStaff(self, text=None):
self._drawClefs()
@@ -956,7 +999,7 @@ class EighthNote(Note):
stroke_color='black',
line_width=1.0
)
-
+ self.noteHead.raise_(None)
self._drawAlteration(x, y)
self._drawMidLine(x, y)
@@ -966,6 +1009,9 @@ class EighthNote(Note):
self.y = y
self.x = x
+ if self.numID > 8 or self.numID < -6:
+ goocanvas.Item.rotate(self.noteHead, 180, x, y)
+ goocanvas.Item.rotate(self.flag, 180, x, y)
def _drawFlag(self, x, y):
self.flag = goocanvas.Image(
parent=self.rootitem,
@@ -998,7 +1044,7 @@ class QuarterNote(Note):
stroke_color='black',
line_width=1.0
)
-
+ self.noteHead.raise_(None)
self._drawAlteration(x, y)
self._drawMidLine(x, y)
@@ -1006,6 +1052,9 @@ class QuarterNote(Note):
self.y = y
self.x = x
+ if self.numID > 8:
+ goocanvas.Item.rotate(self.noteHead, 180, x, y)
+
class HalfNote(Note):
'''
an object inherited from Note, of specific duration (half length)
@@ -1027,7 +1076,7 @@ class HalfNote(Note):
stroke_color='black',
line_width=1.0
)
-
+ self.noteHead.raise_(None)
self._drawAlteration(x, y)
self._drawMidLine(x, y)
@@ -1035,6 +1084,9 @@ class HalfNote(Note):
self.y = y
self.x = x
+ if self.numID > 8:
+ goocanvas.Item.rotate(self.noteHead, 180, x, y)
+
class WholeNote(Note):
'''
an object inherited from Note, of specific duration (whole length)
@@ -1053,7 +1105,7 @@ class WholeNote(Note):
stroke_color='black',
line_width=1.0
)
-
+ self.noteHead.raise_(None)
self._drawAlteration(x, y)
self._drawMidLine(x, y)
@@ -1100,7 +1152,7 @@ class PianoKeyboard():
self.height = height
self.key_callback = key_callback
#piano keyboard image
- goocanvas.Image(
+ self.image = goocanvas.Image(
parent=self.rootitem,
pixbuf=gcompris.utils.load_pixmap("piano_composition/keyboard.png"),
x=self.x,
@@ -1207,7 +1259,7 @@ class PianoKeyboard():
#
# ---------------------------------------------------------------------------
-def textButton(x, y, text, self, color='gray', width=100000):
+def textButton(x, y, text, self, color='gray', width=100000, includeText=False):
'''
Add a text button to the screen with the following parameters:
1. x: the x position of the button
@@ -1250,7 +1302,10 @@ def textButton(x, y, text, self, color='gray', width=100000):
gcompris.utils.item_focus_init(img, None)
self.textbox.raise_(img)
- return img
+ if includeText:
+ return img, self.textbox
+ else:
+ return img
def textBox(text, x, y , self, width=10000, fill_color=None, stroke_color=None, noRect=False, text_color="black"):
'''
@@ -1332,11 +1387,12 @@ def displayHappyNote(self, nextMethod):
'''
displays the happy note for 900 milliseconds
'''
+
if hasattr(self, 'responsePic'):
self.responsePic.remove()
if not hasattr(self, 'timers'):
self.timers = []
-
+ gcompris.sound.play_ogg("/piano_composition/bonus.wav")
self.responsePic = goocanvas.Image(
parent=self.rootitem,
pixbuf=gcompris.utils.load_pixmap('piano_composition/happyNote.png'),
@@ -1355,6 +1411,7 @@ def displaySadNote(self, nextMethod):
'''
displays the sad note for 900 milliseconds
'''
+
if hasattr(self, 'responsePic'):
self.responsePic.remove()
if not hasattr(self, 'timers'):
@@ -1367,6 +1424,7 @@ def displaySadNote(self, nextMethod):
height=300,
width=150
)
+ gcompris.sound.play_ogg("/piano_composition/bleep.wav")
self.responsePic.raise_(None)
self.timers.append(gobject.timeout_add(900, clearResponsePic, self))
self.timers.append(gobject.timeout_add(910, nextMethod))
@@ -1410,6 +1468,40 @@ def pianokeyBindings(keyval, self):
elif keyval == gtk.keysyms.F5:
self.keyboard_click(None, None, None, -5)
+def askUser(x, y, self):
+ self.text = goocanvas.Text(
+ parent=self.rootitem, x=x, y=y, width=1000,
+ text='<span size="30000" > Erase All? </span>',
+ fill_color='black', anchor=gtk.ANCHOR_CENTER,
+ alignment=pango.ALIGN_CENTER,
+ use_markup=True)
+ TG = 10
+ bounds = self.text.get_bounds()
+
+ self.rect = goocanvas.Rect(parent=self.rootitem,
+ x=bounds.x1 - TG,
+ y=bounds.y1 - TG,
+ width=bounds.x2 - bounds.x1 + TG * 2,
+ height=bounds.y2 - bounds.y1 + TG * 2,
+ line_width=3.0,
+ fill_color='gray')
+ self.rect.raise_(None)
+ self.text.raise_(None)
+ self.yesButton, self.txt1 = textButton(x - 50, y + 80, _('Yes'), self, color='green', includeText=True)
+ self.noButton, self.txt2 = textButton(x + 50, y + 80, _('No'), self, color='red', includeText=True)
+
+ return self.yesButton, self.noButton
+
+def eraseUserPrompt(x,y,z,self):
+ self.text.remove()
+ self.yesButton.remove()
+ self.noButton.remove()
+ self.text.remove()
+ self.rect.remove()
+ self.txt1.remove()
+ self.yesButton.remove()
+ self.txt2.remove()
+
def drawBasicPlayHomePagePart1(self):
'''
Method used in play activities (play-piano and play-rhythm)
diff --git a/src/piano_composition-activity/piano_composition.py b/src/piano_composition-activity/piano_composition.py
index 993ec1b..9981972 100644
--- a/src/piano_composition-activity/piano_composition.py
+++ b/src/piano_composition-activity/piano_composition.py
@@ -56,6 +56,7 @@ class Gcompris_piano_composition:
self.noClefDescription = False
+ self.melodyPageToDisplay = 0
def start(self):
# write the navigation bar to bottom left corner
gcompris.bar_set(gcompris.BAR_LEVEL)
@@ -89,6 +90,9 @@ class Gcompris_piano_composition:
6. load and save, only sharp notes, note duration choice, treble or bass choice
(7. , loads melodies)
'''
+ if hasattr(self,'staff'):
+ self.staff.eraseAllNotes()
+
if self.rootitem:
self.rootitem.remove()
@@ -141,7 +145,7 @@ class Gcompris_piano_composition:
if (level > 2):
- self.changeClefButton = textButton(100, 140, _("Change Staff Clef"), self, 'gray', 100)
+ self.changeClefButton = textButton(100, 140, _("Erase and Change Clef"), self, 'gray', 100)
if (level >= 3):
self.textbox = goocanvas.Text(
@@ -261,6 +265,7 @@ class Gcompris_piano_composition:
self.staff = BassStaff(370, 185, self.rootitem, 3)
self.staff.drawStaff()
self.staff.dynamicNoteSpacing = True
+
else:
self.staff = TrebleStaff(370, 185, self.rootitem, 3)
self.staff.drawStaff()
@@ -276,7 +281,7 @@ class Gcompris_piano_composition:
self.eraseNotesButton.connect("button_press_event", self.staff.eraseOneNote)
gcompris.utils.item_focus_init(self.eraseNotesButton, None)
- self.eraseAllButton.connect("button_press_event", self.staff.eraseAllNotes)
+ self.eraseAllButton.connect("button_press_event", self.askAndEraseStaff)
gcompris.utils.item_focus_init(self.eraseAllButton, None)
self.playCompositionButton.connect("button_press_event", self.staff.playComposition)
@@ -318,6 +323,7 @@ class Gcompris_piano_composition:
optionally specify to display the "black keys"
'''
self.keyboard = PianoKeyboard(50, 180, self.rootitem)
+
if level == 5:
self.keyboard.sharpNotation = False
self.keyboard.blackKeys = True
@@ -326,13 +332,14 @@ class Gcompris_piano_composition:
self.keyboard.sharpNotation = True
self.keyboard.draw(300, 200, self.keyboard_click)
-
Prop = gcompris.get_properties()
if not (Prop.fx):
gcompris.utils.dialog(_("Error: This activity cannot be \
played with the\nsound effects disabled.\nGo to the configuration \
dialogue to\nenable the sound."), stop_board)
+
+
def displayMelodySelection(self):
'''
parse the text file melodies.txt and display the melodies for selection
@@ -351,45 +358,65 @@ dialogue to\nenable the sound."), stop_board)
)
self.read_data()
+ if self.melodyPageToDisplay==0:
+ txt = _("Next Page")
+ else:
+ txt = _("Previous Page")
+ self.nextMelodiesButton = textButton(700,475,txt, self)
+ self.nextMelodiesButton.connect("button_press_event", self.nextMelodyPage)
+ gcompris.utils.item_focus_init(self.nextMelodiesButton, None)
self.writeDataToScreen()
+ def nextMelodyPage(self, x=None,y=None,z=None):
+ if self.melodyPageToDisplay == 0:
+ self.melodyPageToDisplay = 1
+
+ else:
+ self.melodyPageToDisplay = 0
+ self.display_level(8)
def writeDataToScreen(self):
def displayTitle(section, x, y):
-
+ newRoot = goocanvas.Group(parent=self.rootitem)
self.text = goocanvas.Text(
- parent=self.rootitem,
+ parent=newRoot,
x=x, y=y,
- text='<span size="10000"> ' + self.data.get(section, 'title') + '</span>',
+ text='<span size="13000"> ' + self.data.get(section, 'title') + '</span>',
fill_color="black",
use_markup=True
)
- goocanvas.Text(parent=self.rootitem,
+ self.origin = goocanvas.Text(parent=newRoot,
x=x + 30,
- y=y + 23,
- width=175,
- text='<span font_family="URW Gothic L" size="7000" \
+ y=y + 18,
+ width=250,
+ text='<span font_family="URW Gothic L" size="10000" \
weight="bold">' + _(self.data.get(section, '_origin')) + '</span>',
fill_color="black",
- use_markup=True,
- pointer_events="GOO_CANVAS_EVENTS_NONE"
+ use_markup=True
)
- goocanvas.Group()
- self.text.connect("button_press_event", self.melodySelected, section)
- gcompris.utils.item_focus_init(self.text, None)
+ self.text.connect("button_press_event", self.melodySelected, section)
+ self.origin.connect("button_press_event", self.melodySelected, section)
+ gcompris.utils.item_focus_init(newRoot, None)
- x = 75
+ x = 55
y = 75
- for section in self.data.sections():
+
+ if self.melodyPageToDisplay == 0:
+ lower = 0
+ upper = (len(self.data.sections())) / 2 - 1
+ else:
+ lower = (len(self.data.sections())) / 2 - 1
+ upper = len(self.data.sections())
+ for section in self.data.sections()[lower:upper]:
displayTitle(section, x, y)
if y > 400:
y = 75
- x += 250
+ x += 275
else:
- y += 45
+ y += 48
def read_data(self):
'''
@@ -422,6 +449,7 @@ dialogue to\nenable the sound."), stop_board)
called once a melody has been selected
writes the melody to the staff, and displayes the title and lyrics
'''
+
self.display_level(self.gcomprisBoard.level)
self.staff.stringToNotation(self.data.get(section, 'melody'))
self.staff.texts = []
@@ -491,6 +519,7 @@ dialogue to\nenable the sound."), stop_board)
if desired, but could confuse children if more than one clef
exists in the piece
'''
+ current_note_type = self.staff.currentNoteType
self.staff.clear()
if hasattr(self.staff, 'newClef'):
self.staff.newClef.clear()
@@ -502,12 +531,12 @@ dialogue to\nenable the sound."), stop_board)
self.staff = TrebleStaff(370, 185, self.rootitem, 3)
self.staff.drawStaff()
self.staff.dynamicNoteSpacing = True
-
+ self.staff.currentNoteType = current_note_type
#re-establish link to root
self.eraseNotesButton.connect("button_press_event", self.staff.eraseOneNote)
gcompris.utils.item_focus_init(self.eraseNotesButton, None)
- self.eraseAllButton.connect("button_press_event", self.staff.eraseAllNotes)
+ self.eraseAllButton.connect("button_press_event", self.askAndEraseStaff)
gcompris.utils.item_focus_init(self.eraseAllButton, None)
self.playCompositionButton.connect("button_press_event", self.staff.playComposition)
@@ -525,6 +554,20 @@ dialogue to\nenable the sound."), stop_board)
self.wholeNoteSelected.connect("button_press_event", self.staff.updateToWhole)
gcompris.utils.item_focus_init(self.wholeNoteSelected, None)
+ def askAndEraseStaff(self,x=None,y=None,z=None):
+ ask_user=False
+ if ask_user:
+ if self.staff.noteList:
+ (self.y, self.n) = askUser(450,300,self)
+ self.y.connect("button_press_event", self.erase)
+ self.n.connect("button_press_event", eraseUserPrompt,self)
+ else:
+ self.staff.eraseAllNotes()
+
+ def erase(self,x,y,z):
+ #self.staff.eraseAllNotes()
+ eraseUserPrompt(None, None, None,self)
+
def change_accidental_type(self, widget, target, event):
if not ready(self):
return False
@@ -546,7 +589,8 @@ dialogue to\nenable the sound."), stop_board)
if not ready(self):
return False
-
+ if hasattr(self.staff, 'locked') and self.staff.locked:
+ return
if not numID:
numID = target.numID
if numID < 0 and self.gcomprisBoard.level < 4:
@@ -697,13 +741,13 @@ dialogue to\nenable the sound."), stop_board)
self.staff.eraseOneNote()
elif keyval == gtk.keysyms.Delete:
if not ready(self, timeouttime=100): return False
- self.staff.eraseAllNotes()
+ self.askAndEraseStaff()
elif keyval == gtk.keysyms.space:
if not ready(self, timeouttime=100): return False
self.staff.playComposition()
else:
pianokeyBindings(keyval, self)
-
+ return True
def pause(self, x):
pass
@@ -713,12 +757,10 @@ dialogue to\nenable the sound."), stop_board)
left navigation bar to increment level
'''
self.noClefDescription = False
- self.staff.eraseAllNotes()
self.gcomprisBoard.level = level
gcompris.bar_set_level(self.gcomprisBoard)
self.display_level(self.gcomprisBoard.level)
-
def general_save(filename, filetype, staffInstance):
'''
called after file selection to save
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]