changeset 564:2f7aa3cad77c pyntnclick

Sound hackery
author Neil Muller <neil@dip.sun.ac.za>
date Sat, 11 Feb 2012 15:35:06 +0200
parents 18396b937647
children 88cffe418201
files pyntnclick/main.py pyntnclick/sound.py
diffstat 2 files changed, 99 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/pyntnclick/main.py	Sat Feb 11 15:22:16 2012 +0200
+++ b/pyntnclick/main.py	Sat Feb 11 15:35:06 2012 +0200
@@ -20,8 +20,8 @@
 from pyntnclick.gamescreen import GameScreen
 from pyntnclick.endscreen import EndScreen
 from pyntnclick.constants import (
-    SCREEN, FRAME_RATE, FREQ, BITSIZE, CHANNELS, BUFFER, DEBUG)
-from pyntnclick.sound import no_sound, disable_sound
+    SCREEN, FRAME_RATE)
+from pyntnclick.sound import Sound
 from pyntnclick import state, data
 
 
@@ -57,8 +57,8 @@
         self._scene_list = self.SCENE_LIST
         self._debug_rects = False
         # TODO: make these real objects
-        self.sound = object()
         self.resource = object()
+        self.sound = Sound(self.resource)
 
     def initial_state(self):
         """Create a copy of the initial game state."""
@@ -87,13 +87,9 @@
         pygame.display.init()
         pygame.font.init()
         if opts.sound:
-            try:
-                pygame.mixer.init(FREQ, BITSIZE, CHANNELS, BUFFER)
-            except pygame.error, exc:
-                no_sound(exc)
+            self.sound.enable_sound()
         else:
-            # Ensure get_sound returns nothing, so everything else just works
-            disable_sound()
+            self.sound.disable_sound()
         if DEBUG:
             if opts.scene is not None:
                 # debug the specified scene
--- a/pyntnclick/sound.py	Sat Feb 11 15:22:16 2012 +0200
+++ b/pyntnclick/sound.py	Sat Feb 11 15:35:06 2012 +0200
@@ -7,53 +7,109 @@
 import os
 
 import pygame
-from pygame.mixer import music
-from albow.resource import _resource_path, dummy_sound
+
+try:
+    from pygame.mixer import Sound as pygame_Sound
+    from pygame.mixer import music
+    pygame_import_error = None
+except ImportError, e:
+    # Save error, so we don't crash and can do the right thing later
+    pygame_import_error = e
+    pygame_Sound = None
+    music = None
+
+from pyntnclick.constants import FREQ, BITSIZE, CHANNELS, BUFFER
+from pyntnclick.resources import ResourceNotFound
+
 import albow.music
 
-sound_cache = {}
+
+class DummySound(object):
+    """A dummy sound object.
+
+       This is a placeholder object with the same API as
+       pygame.mixer.Sound which does nothing. Used when
+       sounds are disabled so scense don't need to worry
+       about the details.
+
+       Inpsired by the same idea in Albow (by Greg Ewing)"""
+
+   def play(self, *args):
+       pass
+
+   def stop(self):
+       pass
+
+   def get_length(self):
+       return 0.0
+
+   def get_num_channel(self):
+       return 0
+
+   def get_volume(self):
+       return 0.0
+
+   def fadeout(self, *args):
+       pass
 
 
-def get_sound(*names):
-    if sound_cache is None:
-        return dummy_sound
-    path = _resource_path("sounds", names)
-    sound = sound_cache.get(path)
-    if not sound:
-        if not os.path.isfile(path):
-            missing_sound("File does not exist", path)
-            return dummy_sound
+class Sound(object):
+    """Global sound management and similiar useful things"""
+
+    def __init__(self, resource_finder):
+        self.sound_enabled = False
+        self.sound_cache = {}
+        self._resource_finder = resource_finder
+
+    def enable_sound(self):
+        """Attempt to initialise the sound system"""
+        if pygame_Sound is None:
+            self.disable_sound(pygame_import_error)
+            return
         try:
-            from pygame.mixer import Sound
-        except ImportError, e:
-            no_sound(e)
-            return dummy_sound
-        try:
-            sound = Sound(path)
-        except pygame.error, e:
-            missing_sound(e, path)
+            pygame.mixer.init(FREQ, BITSIZE, CHANNELS, BUFFER)
+            self.sound_enabled = True
+        except pygame.error, exc:
+            self.disable_sound(exc)
+
+    def disable_sound(self, exc=None):
+        """Disable the sound system"""
+        self.sound_enabled = False
+        if exc is not None:
+            print 'Failed to initialise sound system'
+            print 'Error: %s' % exc
+            print 'Sound disabled'
+
+    def get_sound(self, *names):
+        if not self.sound_enabled:
             return dummy_sound
-        sound_cache[path] = sound
-    return sound
-
-
-def no_sound(e):
-    global sound_cache
-    print "get_sound: %s" % e
-    print "get_sound: Sound not available, continuing without it"
-    sound_cache = None
-    albow.music.music_enabled = False
+        soundfile = os.path.join(names)
+        sound = None
+        try:
+            path = self._resource_finder("sounds", soundfile)
+            sound = sound_cache.get(path, None)
+        except ResourceNotFound:
+            print "Sound file not found: %s" % soundfile
+            # Cache failed lookup
+            sound = DummySound()
+            self.sound_cache[path] = sound
+        if sound is None:
+            try:
+                sound = pygame_Sound(path)
+            except pygame.error, e:
+                print "Sound file not found: %s" % soundfile
+                sound = DummySound()
+            self.sound_cache[path] = sound
+        return sound
 
+    def get_playlist(self, pieces, random=False, repeat=False):
+        return albow.music.PlayList(pieces, random, repeat)
 
-def disable_sound():
-    global sound_cache
-    sound_cache = None
-    albow.music.music_enabled = False
+    def get_music(self, name, prefix):
+        return albow.music.get_music(name, prefix)
 
-
-def missing_sound(e, name):
-    print "albow.resource.get_sound: %s: %s" % (name, e)
-
+    def change_playlist(self, new_playlist):
+        albow.music.change_playlist(new_playlist)
 
 def start_next_music():
     """Start playing the next item from the current playlist immediately."""