1 # -*- coding: utf-8 -*-
4 bandes arc-en-ciel représentant un clavier.
10 from cursors
import WarpingCursor
11 from column
import Column
13 from eventutils
import event_handler
, EventDispatcher
, EventHandlerMixin
15 from musicxml
import Tone
17 from config
import FRAMERATE
18 from config
import BORDER
19 from config
import FIRST_HUE
20 from config
import DEFAULT_MIDI_VELOCITY
22 from globals import BACKGROUND_LAYER
23 from globals import CURSOR_LAYER
24 from globals import PLAYING_MODES
26 class _PlayingScreenBase(pygame
.sprite
.LayeredDirty
, EventHandlerMixin
) :
28 def __init__(self
, synth
, distinctNotes
=[]) :
30 distinctNotes : notes disctinctes présentes dans la chanson
31 triées du plus grave au plus aigu.
33 super(_PlayingScreenBase
, self
).__init
__()
35 self
.distinctNotes
= distinctNotes
36 self
.keyboardLength
= 0
37 self
.keyboardRects
= []
43 self
.draw(pygame
.display
.get_surface())
47 def _initRects(self
) :
48 """ création des espaces réservés pour
49 afficher les colonnes.
51 #ambitus = self.distinctNotes[-1].midi - self.distinctNotes[0].midi
53 # self.keyboardLength = 8
55 # self.keyboardLength = 11
56 self
.keyboardLength
= len(self
.distinctNotes
)
58 screen
= pygame
.display
.get_surface()
60 # taille de la zone d'affichage utile (bordure autour)
61 dispWidth
= screen
.get_width() - 2 * BORDER
62 dispHeight
= screen
.get_height() - 2 * BORDER
64 columnWidth
= int(round(float(dispWidth
) / self
.keyboardLength
))
67 for i
in range(self
.keyboardLength
) :
68 upperLeftCorner
= (i
*columnWidth
+ BORDER
, BORDER
)
69 rect
= pygame
.Rect(upperLeftCorner
, (columnWidth
, dispHeight
))
72 self
.keyboardRects
= rects
74 def _initColumns(self
) :
76 hueStep
= FIRST_HUE
/ (self
.keyboardLength
- 1)
77 for i
, rect
in enumerate(self
.keyboardRects
) :
78 hue
= FIRST_HUE
- hueStep
* i
79 tone
= self
.distinctNotes
[i
]
80 c
= Column(self
, hue
, rect
, tone
)
81 self
.add(c
, layer
=BACKGROUND_LAYER
)
82 self
.columns
[tone
.midi
] = c
85 def _initCursor(self
) :
86 self
.cursor
= WarpingCursor(blinkMode
=True)
87 self
.add(self
.cursor
, layer
=CURSOR_LAYER
)
91 clock
= pygame
.time
.Clock()
93 pygame
.mouse
.set_visible(False)
95 EventDispatcher
.dispatchEvents()
96 dirty
= self
.draw(pygame
.display
.get_surface())
97 pygame
.display
.update(dirty
)
100 pygame
.mouse
.set_visible(True)
101 self
.cursor
._stopBlink
()
103 @event_handler(pygame
.KEYDOWN
)
104 def handleKeyDown(self
, event
) :
105 if event
.key
== pygame
.K_q
:
106 self
._running
= False
109 class PlayingScreen(_PlayingScreenBase
) :
110 "fenêtre de jeu pour improvisation"
112 scale
= [55, 57, 59, 60, 62, 64, 65, 67, 69, 71, 72]
114 def __init__(self
, synth
) :
116 for midi
in self
.scale
:
118 distinctNotes
.append(tone
)
120 super(PlayingScreen
, self
).__init
__(synth
, distinctNotes
)
122 @event_handler(events
.NOTEON
)
123 def noteon(self
, evt
) :
125 self
.synth
.noteon(0, tone
.midi
, DEFAULT_MIDI_VELOCITY
)
127 @event_handler(events
.NOTEOFF
)
128 def noteoff(self
, evt
) :
130 self
.synth
.noteoff(0, tone
.midi
)
133 class SongPlayingScreen(_PlayingScreenBase
) :
135 def __init__(self
, synth
, song
, mode
=PLAYING_MODES
['NORMAL']) :
136 super(SongPlayingScreen
, self
).__init
__(synth
, song
.distinctNotes
)
138 self
.currentColumn
= None
139 self
.noteIterator
= self
.song
.iterNotes()
142 def displayNext(self
) :
143 if self
.currentColumn
:
144 self
.currentColumn
.update(False)
145 note
, verseIndex
= self
.noteIterator
.next()
146 syllabus
= note
.lyrics
[verseIndex
].syllabus(encoding
="iso-8859-1")
147 column
= self
.columns
[note
.midi
]
148 column
.update(True, syllabus
)
149 self
.currentColumn
= column
151 @event_handler(events
.KEYDOWN
)
152 def handleKeyDown(self
, event
) :
154 if col
== self
.currentColumn
:
155 self
.synth
.noteon(0, col
.tone
.midi
, DEFAULT_MIDI_VELOCITY
)
157 @event_handler(events
.KEYUP
)
158 def handleKeyUp(self
, event
) :
159 self
.synth
.noteoff(0, self
.currentColumn
.tone
.midi
)