ClearBits action
[naja.git] / naja / sound.py
1 """Sound utilities."""
2
3 import time
4
5 from pygame import mixer
6
7 from naja.options import options
8 from naja.resources import resources
9 from naja.constants import (
10     FREQ, BITSIZE, CHANNELS, BUFFER, DEFAULT_SOUND_VOLUME,
11     DEFAULT_MUSIC_VOLUME)
12
13
14 class DummySound(object):
15     def init(self):
16         self.playing_music = False
17
18     def play_sound(self, name, volume=DEFAULT_SOUND_VOLUME, foreground=False):
19         pass
20
21     def play_music(self, name, volume=DEFAULT_MUSIC_VOLUME):
22         pass
23
24     def pause_music(self):
25         pass
26
27     def resume_music(self):
28         pass
29
30     def stop(self):
31         pass
32
33
34 class PygameSound(object):
35     def __init__(self):
36         self._sounds = {}
37         self.playing_music = False
38
39     def init(self):
40         mixer.init(FREQ, BITSIZE, CHANNELS, BUFFER)
41         silence = self.load_sound("silence.ogg")
42         if silence.get_length() < 1:
43             raise RuntimeError("Sound load error - silence.ogg too short")
44         self.play_sound("silence.ogg")
45
46     def load_sound(self, name):
47         track_name = resources.get_resource_path("sounds", name)
48         sound = self._sounds.get(track_name)
49         if sound is None:
50             sound = self._sounds[track_name] = mixer.Sound(track_name)
51         return sound
52
53     def play_sound(self, name, volume=DEFAULT_SOUND_VOLUME, foreground=False):
54         sound = self.load_sound(name)
55         if sound is not None:
56             sound.set_volume(volume)
57             sound.play()
58             if foreground:
59                 time.sleep(sound.get_length())
60
61     def play_music(self, name, volume=DEFAULT_MUSIC_VOLUME):
62         if not options.music:
63             return
64         track_name = resources.get_resource_path("music", name)
65         mixer.music.load(track_name)
66         mixer.music.set_volume(volume)
67         mixer.music.play(-1)  # loop sound
68         self.playing_music = True
69
70     def pause_music(self):
71         mixer.music.pause()
72         self.playing_music = False
73
74     def unpause_music(self):
75         mixer.music.unpause()
76         self.playing_music = True
77
78     def stop(self):
79         mixer.fadeout(1000)
80         mixer.music.stop()
81         self.playing_music = False
82
83
84 class SoundProxy(object):
85     def __init__(self):
86         self._sound = DummySound()
87         self._sound.init()
88
89     def init(self):
90         """Attempt to initialize the sound system."""
91         if options.sound:
92             try:
93                 pyg_sound = PygameSound()
94                 pyg_sound.init()
95                 self._sound = pyg_sound
96             except Exception, err:
97                 print "Failed to enable sound: %r" % (err,)
98
99     def __getattr__(self, name):
100         return getattr(self._sound, name)
101
102
103 sound = SoundProxy()