--- /dev/null
+import os
+import sys
+
+try:
+ from pkg_resources import resource_filename
+except ImportError:
+ # OK, we're most likely running under py2exe, so this is safe
+ # (for values of safe that are unconcerned about py2exe being involved)
+ def resource_filename(mod, path):
+ # There are better ways of doing this, but I've spent too much
+ # time going down this rabbithole already
+ return os.path.join(os.path.dirname(__file__), '..', 'data', path)
+import pygame
+
+
+class ResourceNotFound(Exception):
+ pass
+
+
+class Resources(object):
+ CONVERT_ALPHA = True
+
+ def __init__(self, resource_module, language=None):
+ self.resource_module = resource_module
+ self.lang_dialect = language
+ self.language = language.split('_', 1)[0] if language else None
+ self._cache = {}
+
+ def create_resource_path(self, *path_fragments):
+ return resource_filename(self.resource_module,
+ os.path.join(*path_fragments))
+
+ def get_resource_path(self, *path_fragments):
+ for mod, full_path_fragments in self.lang_locations(path_fragments):
+ path = resource_filename(mod, os.path.join(*full_path_fragments))
+ if os.path.exists(path):
+ return path
+ raise ResourceNotFound(os.path.join(*path_fragments))
+
+ def lang_locations(self, path_fragments):
+ '''
+ For each resource module, yield:
+ * (<module>, (<lang>_<dialect>, <path>))
+ * (<module>, (<lang>, <path>))
+ * (<module>, (<path>, ))
+ '''
+ for module in (self.resource_module,):
+ if self.lang_dialect:
+ yield (module, (self.lang_dialect,) + path_fragments)
+ if self.language != self.lang_dialect:
+ yield (module, (self.language,) + path_fragments)
+ yield (module, path_fragments)
+
+ def get_file(self, *path_fragments, **kw):
+ mode = kw.get('mode', "rU")
+ try:
+ path = self.get_resource_path(*path_fragments)
+ except ResourceNotFound:
+ if 'w' in mode:
+ path = self.create_resource_path(*path_fragments)
+ else:
+ raise
+ return file(path, mode)
+
+ def get_image(self, *name_fragments, **kw):
+ transforms = kw.get('transforms', ())
+ basedir = kw.get('basedir', 'images')
+
+ path = (basedir,) + name_fragments
+
+ if path not in self._cache:
+ fn = self.get_resource_path(*path)
+ image = pygame.image.load(fn)
+ if self.CONVERT_ALPHA:
+ if not pygame.display.get_init():
+ print >> sys.stderr, ("Display not initialized, "
+ "image '%s' not loaded."
+ % os.path.join(*path))
+ return
+ image = image.convert_alpha(pygame.display.get_surface())
+ self._cache[path] = image
+
+ key = (path, transforms)
+ if key not in self._cache:
+ image = self._cache[path]
+ for mutator in transforms:
+ image = mutator(image)
+ self._cache[key] = image
+
+ return self._cache[key]
+
+ def get_font(self, file_name, font_size):
+ basedir = 'fonts'
+ key = (basedir, file_name, font_size)
+
+ if key not in self._cache:
+ fn = self.get_resource_path(basedir, file_name)
+ self._cache[key] = pygame.font.Font(fn, font_size)
+
+ return self._cache[key]
+
+
+resources = Resources('data')
--- /dev/null
+"""Sound utilities."""
+
+from pygame import mixer
+
+from naja.options import options
+from naja.resources import resources
+from naja.constants import (
+ FREQ, BITSIZE, CHANNELS, BUFFER, DEFAULT_SOUND_VOLUME,
+ DEFAULT_MUSIC_VOLUME)
+
+
+class DummySound(object):
+ def init(self):
+ pass
+
+ def play_sound(self, name, volume=DEFAULT_SOUND_VOLUME):
+ pass
+
+ def play_music(self, name, volume=DEFAULT_MUSIC_VOLUME):
+ pass
+
+ def pause_music(self):
+ pass
+
+ def resume_music(self):
+ pass
+
+ def stop(self):
+ pass
+
+
+class PygameSound(object):
+ def __init__(self):
+ self._sounds = {}
+
+ def init(self):
+ mixer.init(FREQ, BITSIZE, CHANNELS, BUFFER)
+ silence = self.load_sound("silence.ogg")
+ if silence.get_length() < 1:
+ raise RuntimeError("Sound load error - silence.ogg too short")
+ self.play_sound("silence.ogg")
+
+ def load_sound(self, name):
+ track_name = resources.get_resource_path("sounds", name)
+ sound = self._sounds.get(track_name)
+ if sound is None:
+ sound = self._sounds[track_name] = mixer.Sound(track_name)
+ return sound
+
+ def play_sound(self, name, volume=DEFAULT_SOUND_VOLUME):
+ sound = self.load_sound(name)
+ if sound is not None:
+ sound.set_volume(volume)
+ sound.play()
+
+ def play_music(self, name, volume=DEFAULT_MUSIC_VOLUME):
+ if not options.music:
+ return
+ track_name = resources.get_resource_path("music", name)
+ mixer.music.load(track_name)
+ mixer.music.set_volume(volume)
+ mixer.music.play(-1) # loop sound
+
+ def pause_music(self):
+ mixer.music.pause()
+
+ def unpause_music(self):
+ mixer.music.unpause()
+
+ def stop(self):
+ mixer.fadeout(1000)
+ mixer.music.stop()
+
+
+class SoundProxy(object):
+ def __init__(self):
+ self._sound = DummySound()
+
+ def init(self):
+ """Attempt to initialize the sound system."""
+ if options.sound:
+ try:
+ pyg_sound = PygameSound()
+ pyg_sound.init()
+ self._sound = pyg_sound
+ except Exception, err:
+ print "Failed to enable sound: %r" % (err,)
+
+ def __getattr__(self, name):
+ return getattr(self._sound, name)
+
+
+sound = SoundProxy()