Back to index

gcompris  8.2.2
melody.py
Go to the documentation of this file.
00001 #  gcompris - melody
00002 #
00003 # Time-stamp: <2005/03/05 jose>
00004 #
00005 # Copyright (C) 2003 Jose Jorge
00006 #
00007 #   This program is free software; you can redistribute it and/or modify
00008 #   it under the terms of the GNU General Public License as published by
00009 #   the Free Software Foundation; either version 2 of the License, or
00010 #   (at your option) any later version.
00011 #
00012 #   This program is distributed in the hope that it will be useful,
00013 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 #   GNU General Public License for more details.
00016 #
00017 #   You should have received a copy of the GNU General Public License
00018 #   along with this program; if not, write to the Free Software
00019 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 #
00021 import gnomecanvas
00022 import gcompris
00023 import gcompris.utils
00024 import gcompris.skin
00025 import gcompris.sound
00026 import gcompris.bonus
00027 import gtk
00028 import gtk.gdk
00029 import random
00030 
00031 from gcompris import gcompris_gettext as _
00032 
00033 class Gcompris_melody:
00034   """The melody activity"""
00035 
00036 
00037   def __init__(self, gcomprisBoard):
00038     self.gcomprisBoard = gcomprisBoard
00039 
00040     self.gcomprisBoard.disable_im_context = True
00041 
00042     #print("Gcompris_melody __init__.")
00043 
00044     # These are used to let us restart only after the bonux is displayed.
00045     # When the bonus is displayed, it call us first with pause(1) and then with pause(0)
00046     self.board_paused  = 0;
00047     self.gamewon       = 0;
00048 
00049 
00050   def start(self):
00051     self.saved_policy = gcompris.sound.policy_get()
00052     gcompris.sound.policy_set(gcompris.sound.PLAY_AND_INTERRUPT)
00053 
00054     self.gcomprisBoard.level=1
00055     self.gcomprisBoard.sublevel=1
00056     self.gcomprisBoard.number_of_sublevel=1
00057 
00058     # pause the bg music
00059     #print "pause sound"
00060     gcompris.sound.pause()
00061 
00062     self.timers = []
00063     self.solution = []
00064     self.kidstry = []
00065     self.in_repeat = 0
00066     self.theme = 0
00067 
00068     #
00069     # This list contains the 'theme' for each melody level.
00070     #
00071     self.melodylist = \
00072                       [
00073       # xylophon
00074       [
00075       {'theme': "xylofon", 'background': "melody/xylofon/background.png", 'hittool': "melody/xylofon/cursor.png", 'hitofset_x': 50, 'hitofset_y': 50},
00076       [ {'x': 150.0, 'y': 101.0,  'image': "melody/xylofon/son1.png", 'sound': "sounds/melody/xylofon/son1.ogg"},
00077         {'x': 284.0, 'y': 118.0,  'image': "melody/xylofon/son2.png", 'sound': "sounds/melody/xylofon/son2.ogg"},
00078         {'x': 412.0, 'y': 140.0, 'image': "melody/xylofon/son3.png", 'sound': "sounds/melody/xylofon/son3.ogg"},
00079         {'x': 546.0, 'y': 157.0, 'image': "melody/xylofon/son4.png", 'sound': "sounds/melody/xylofon/son4.ogg"} ] ],
00080 
00081       # guitar
00082       [
00083       {'theme': "guitar", 'background': "melody/guitar/background.jpg", 'hittool': "melody/guitar/cursor.png", 'hitofset_x': 400, 'hitofset_y': -5},
00084       [ {'x': 0, 'y': 170.0,  'image': "melody/guitar/son1.png", 'sound': "sounds/melody/guitar/son1.ogg"},
00085         {'x': 0, 'y': 230.0,  'image': "melody/guitar/son2.png", 'sound': "sounds/melody/guitar/son2.ogg"},
00086         {'x': 0, 'y': 290.0, 'image': "melody/guitar/son3.png", 'sound': "sounds/melody/guitar/son3.ogg"},
00087         {'x': 0, 'y': 350.0, 'image': "melody/guitar/son4.png", 'sound': "sounds/melody/guitar/son4.ogg"} ] ],
00088 
00089       # Kitchen
00090       [
00091       {'theme': "tachos", 'background': "melody/tachos/background.jpg", 'hittool': "melody/tachos/cursor.png", 'hitofset_x': 50, 'hitofset_y': 50},
00092       [ {'x': 150.0, 'y': 50.0,  'image': "melody/tachos/son1.png", 'sound': "sounds/melody/tachos/son1.ogg"},
00093         {'x': 550.0, 'y': 50.0,  'image': "melody/tachos/son2.png", 'sound': "sounds/melody/tachos/son2.ogg"},
00094         {'x': 150.0, 'y': 250.0, 'image': "melody/tachos/son3.png", 'sound': "sounds/melody/tachos/son3.ogg"},
00095         {'x': 550.0, 'y': 250.0, 'image': "melody/tachos/son4.png", 'sound': "sounds/melody/tachos/son4.ogg"} ] ] ]
00096 
00097     self.maxtheme = len(self.melodylist)-1
00098     self.gcomprisBoard.maxlevel = 9
00099 
00100     #
00101     pixmap = gcompris.utils.load_pixmap(gcompris.skin.image_to_skin("button_reload.png"))
00102     if(pixmap):
00103       gcompris.bar_set_repeat_icon(pixmap)
00104       gcompris.bar_set(gcompris.BAR_LEVEL|gcompris.BAR_REPEAT_ICON)
00105     else:
00106       gcompris.bar_set(gcompris.BAR_LEVEL|gcompris.BAR_REPEAT)
00107 
00108 
00109     self.pause(1);
00110     self.display_current_level()
00111 
00112     # Play an intro sound
00113     gcompris.sound.play_ogg_cb("sounds/melody/" + self.melodylist[self.theme][0]['theme'] + "/melody.ogg", self.intro_cb)
00114 
00115     Prop = gcompris.get_properties()
00116 
00117     if(not Prop.fx):
00118       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)
00119 
00120   def end(self):
00121     self.cleanup()
00122     #print("Gcompris_melody end.")
00123     gcompris.sound.policy_set(self.saved_policy)
00124     gcompris.sound.resume()
00125 
00126 
00127   def ok(self):
00128     #print("Gcompris_melody ok.")
00129     pass
00130 
00131   def cleanup(self):
00132 
00133     # Clear all timer
00134     for i in self.timers :
00135       gtk.timeout_remove(i)
00136 
00137     self.timers = []
00138 
00139     self.in_repeat = 0;
00140 
00141     # Remove the root item removes all the others inside it
00142     self.rootitem.destroy()
00143     self.rootitem = None
00144 
00145   def display_current_level(self):
00146 
00147     gcompris.set_background(self.gcomprisBoard.canvas.root(),
00148                             self.melodylist[self.theme][0]['background'])
00149     gcompris.bar_set_level(self.gcomprisBoard)
00150 
00151     gcompris.sound.policy_set(gcompris.sound.PLAY_AND_INTERRUPT)
00152 
00153     # Create our rootitem. We put each canvas item in it so at the end we
00154     # only have to kill it. The canvas deletes all the items it contains automaticaly.
00155     self.rootitem = self.gcomprisBoard.canvas.root().add(
00156       gnomecanvas.CanvasGroup,
00157       x=0.0,
00158       y=0.0
00159       )
00160 
00161     # Put the theme switcher button
00162     self.switch_item = self.rootitem.add(
00163         gnomecanvas.CanvasPixbuf,
00164         pixbuf = gcompris.utils.load_pixmap("melody/switch.png"),
00165         x=10,
00166         y=10
00167         )
00168     self.switch_item.connect("event", self.switch_item_event)
00169     # This item is clickeable and it must be seen
00170     self.switch_item.connect("event", gcompris.utils.item_event_focus)
00171 
00172 
00173     # Put the sound buttons
00174     self.sound_list = self.melodylist[self.theme][1]
00175 
00176     for i in self.sound_list:
00177       self.sound_item = self.rootitem.add(
00178         gnomecanvas.CanvasPixbuf,
00179         pixbuf = gcompris.utils.load_pixmap(i['image']),
00180         x=i['x'],
00181         y=i['y']
00182         )
00183       self.sound_item.connect("event", self.sound_item_event, i)
00184       # This item is clickeable and it must be seen
00185       self.sound_item.connect("event", gcompris.utils.item_event_focus)
00186 
00187 
00188     self.bang_item = self.rootitem.add(
00189       gnomecanvas.CanvasPixbuf,
00190       pixbuf = gcompris.utils.load_pixmap(self.melodylist[self.theme][0]['hittool']),
00191       x=0,
00192       y=0
00193       )
00194     self.bang_item.hide()
00195 
00196     self.hitofset_x = self.melodylist[self.theme][0]['hitofset_x']
00197     self.hitofset_y = self.melodylist[self.theme][0]['hitofset_y']
00198 
00199     self.populate(self.sound_list)
00200 
00201 
00202   # records the try of the child
00203   def tried(self, a):
00204     if len(self.kidstry) >= len(self.solution) :
00205       self.kidstry.pop(0)
00206     self.kidstry.append(a)
00207     #level finished?
00208     if self.kidstry == self.solution :
00209       if (self.increment_level() == 1):
00210         self.gamewon = 1
00211         gcompris.sound.policy_set(self.saved_policy)
00212         gcompris.bonus.display(1, gcompris.bonus.FLOWER)
00213 
00214 
00215   # Ready to play for the kid
00216   def ready(self):
00217 
00218     self.in_repeat = 0
00219     self.timers.pop(0)
00220 
00221 
00222   # Shows and plays the thing clicked
00223   def show_bang_stop(self, a):
00224 
00225     if self.board_paused or self.rootitem == None:
00226       return
00227 
00228     self.bang_item.hide()
00229     self.timers.pop(0)
00230 
00231   # Shows and plays the thing clicked
00232   def show_bang(self, a):
00233 
00234     if self.board_paused or self.rootitem == None:
00235       return
00236 
00237     self.bang_item.set(x=a['x'] + self.hitofset_x, y=a['y'] + self.hitofset_y)
00238 
00239     self.bang_item.show()
00240 
00241     gcompris.sound.play_ogg_cb(a['sound'], self.sound_played)
00242     self.timers.pop(0)
00243 
00244 
00245   def repeat(self):
00246     #print("Gcompris_melody repeat.")
00247     # Important to use a timer here to keep self.timers up todate
00248     self.timers.append(gtk.timeout_add(50, self.repeat_it))
00249 
00250   def repeat_it(self):
00251     #print("Gcompris_melody repeat it.")
00252     if self.in_repeat:
00253       return
00254 
00255     # We are like paused until the last sound is played
00256     self.in_repeat = 1;
00257 
00258     if self.timers :
00259       self.timers.pop(0)
00260 
00261     self.kidstry = []
00262     timer = 0
00263 
00264     for i in self.solution:
00265       self.timers.append(gtk.timeout_add(timer, self.show_bang, i))
00266       timer = timer + 1000
00267       self.timers.append(gtk.timeout_add(timer, self.show_bang_stop, i))
00268       timer = timer + 500
00269 
00270     self.timers.append(gtk.timeout_add(timer, self.ready))
00271 
00272 
00273   def config(self):
00274     #print("Gcompris_melody config.")
00275     pass
00276 
00277   #randomize the sequence and plays it one first time
00278   def populate(self, sound_struct):
00279     #print("Gcompris_melody populate.")
00280     self.solution = []
00281 
00282     for i in range(self.gcomprisBoard.level+2):
00283       self.solution.append(sound_struct[random.randint(0,len(sound_struct)-1)])
00284 
00285     self.timers.append(gtk.timeout_add(1300, self.repeat_it))
00286 
00287   def key_press(self, keyval, commit_str, preedit_str):
00288     #print("got key %i" % keyval)
00289     # Play sounds with the keys
00290     if ((keyval == gtk.keysyms.KP_1) or (keyval == gtk.keysyms._1)):
00291       #print "son1"
00292       self.sound_play(self.melodylist[self.theme][1][0])
00293       return True
00294     if ((keyval == gtk.keysyms.KP_2) or (keyval == gtk.keysyms._2)):
00295       #print "son2"
00296       self.sound_play(self.melodylist[self.theme][1][1])
00297       return True
00298     if ((keyval == gtk.keysyms.KP_3) or (keyval == gtk.keysyms._3)):
00299       #print "son3"
00300       self.sound_play(self.melodylist[self.theme][1][2])
00301       return True
00302     if ((keyval == gtk.keysyms.KP_4) or (keyval == gtk.keysyms._4)):
00303       #print "son4"
00304       self.sound_play(self.melodylist[self.theme][1][3])
00305       return True
00306 
00307     return False
00308 
00309 
00310   def pause(self, pause):
00311     self.board_paused = pause
00312 
00313     # When the bonus is displayed, it call us first with pause(1) and then with pause(0)
00314     # the game is won
00315     if(self.gamewon == 1 and pause == 0):
00316       self.cleanup()
00317       self.display_current_level()
00318       self.gamewon = 0
00319 
00320     return
00321 
00322 
00323   def set_level(self, level):
00324     #print("Gcompris_melody set level. %i" % level)
00325     self.gcomprisBoard.level=level;
00326     self.gcomprisBoard.sublevel=1;
00327     self.cleanup()
00328     self.display_current_level()
00329 
00330   # Code that increments the sublevel and level
00331   # And bail out if no more levels are available
00332   # return 1 if continue, 0 if bail out
00333   def increment_level(self):
00334     self.gcomprisBoard.sublevel += 1
00335 
00336     if(self.gcomprisBoard.sublevel>self.gcomprisBoard.number_of_sublevel):
00337       # Try the next level
00338       self.gcomprisBoard.sublevel=1
00339       self.gcomprisBoard.level += 1
00340       if(self.gcomprisBoard.level>self.gcomprisBoard.maxlevel):
00341         # the current board is finished : bail out
00342         gcompris.bonus.board_finished(gcompris.bonus.FINISHED_RANDOM)
00343         return 0
00344 
00345     return 1
00346 
00347 
00348   # ---------------- sound on click events -----------------------
00349   def sound_item_event(self, widget, event, sound_struct):
00350 
00351     if self.board_paused or self.in_repeat:
00352       return
00353 
00354     if event.type == gtk.gdk.BUTTON_PRESS:
00355       if event.button == 1:
00356           self.sound_play(sound_struct)
00357     return False
00358 
00359   # ---------------- sound is effectively played -----------------------
00360   def sound_play(self, sound_struct):
00361     gcompris.sound.play_ogg_cb(sound_struct['sound'], self.sound_played)
00362     self.tried(sound_struct)
00363     return
00364 
00365   # ---------------- theme change on switch events -----------------------
00366   def switch_item_event(self, widget, event):
00367 
00368     if self.board_paused or self.in_repeat:
00369       return
00370     # switch the theme
00371     if event.type == gtk.gdk.BUTTON_PRESS:
00372       if event.button == 1:
00373        if self.theme < self.maxtheme:
00374          self.theme += 1
00375        else:
00376          self.theme = 0
00377 
00378        #print("New melody theme : " + self.melodylist[self.theme][0]['theme'] + ".")
00379     # Apply the changes
00380        self.cleanup()
00381        self.display_current_level()
00382 
00383 
00384     return False
00385 
00386   def sound_played(self, file):
00387     #print "python sound played :", file
00388     pass
00389 
00390   def intro_cb(self, file):
00391     #print "intro passed. go play"
00392     self.pause(0)
00393     self.populate(self.sound_list)
00394 
00395 def stop_board():
00396   gcompris.bonus.board_finished(gcompris.bonus.FINISHED_RANDOM)
00397