2d61974a9bbc10dac235b41b236bc3a2a1238945
[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         pass
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
38     def init(self):
39         mixer.init(FREQ, BITSIZE, CHANNELS, BUFFER)
40         silence = self.load_sound("silence.ogg")
41         if silence.get_length() < 1:
42             raise RuntimeError("Sound load error - silence.ogg too short")
43         self.play_sound("silence.ogg")
44
45     def load_sound(self, name):
46         track_name = resources.get_resource_path("sounds", name)
47         sound = self._sounds.get(track_name)
48         if sound is None:
49             sound = self._sounds[track_name] = mixer.Sound(track_name)
50         return sound
51
52     def play_sound(self, name, volume=DEFAULT_SOUND_VOLUME, foreground=False):
53         sound = self.load_sound(name)
54         if sound is not None:
55             sound.set_volume(volume)
56             sound.play()
57             if foreground:
58                 time.sleep(sound.get_length())
59
60     def play_music(self, name, volume=DEFAULT_MUSIC_VOLUME):
61         if not options.music:
62             return
63         track_name = resources.get_resource_path("music", name)
64         mixer.music.load(track_name)
65         mixer.music.set_volume(volume)
66         mixer.music.play(-1)  # loop sound
67
68     def pause_music(self):
69         mixer.music.pause()
70
71     def unpause_music(self):
72         mixer.music.unpause()
73
74     def stop(self):
75         mixer.fadeout(1000)
76         mixer.music.stop()
77
78
79 class SoundProxy(object):
80     def __init__(self):
81         self._sound = DummySound()
82
83     def init(self):
84         """Attempt to initialize the sound system."""
85         if options.sound:
86             try:
87                 pyg_sound = PygameSound()
88                 pyg_sound.init()
89                 self._sound = pyg_sound
90             except Exception, err:
91                 print "Failed to enable sound: %r" % (err,)
92
93     def __getattr__(self, name):
94         return getattr(self._sound, name)
95
96
97 sound = SoundProxy()