Skip to content

Commit ec3c184

Browse files
committed
fixes for GC
1 parent 45b57a1 commit ec3c184

File tree

4 files changed

+46
-51
lines changed

4 files changed

+46
-51
lines changed

openal/__init__.py

+40-45
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import ctypes
2+
import weakref
23

34
from . import _al
45
from . import _alc
56
from . import _alut
67

8+
_refs = {}
9+
def call_on_del(obj, func, *args, **kwargs):
10+
x = max(_refs.iterkeys()) + 1 if _refs else 0
11+
_refs[x] = weakref.ref(obj, lambda ref: (_refs.pop(x), func(*args, **kwargs)))
12+
713
def call_array_fill(atype, elements, func, *args):
814
x = (atype * len(elements))()
915
for k, v in enumerate(elements):
@@ -27,13 +33,8 @@ def __init__(self, name=None):
2733
#print repr(_alc.GetString(0, _alc.ALC_DEVICE_SPECIFIER))
2834
self._handle = _alc.OpenDevice(name)
2935
assert self._handle
30-
def __del__(self):
31-
if hasattr(self, "_handle"):
32-
try:
33-
_alc.CloseDevice(self._handle)
34-
except:
35-
pass
36-
del self._handle
36+
call_on_del(self, _alc.CloseDevice, self._handle)
37+
3738
def ContextListener(self, *args, **kwargs):
3839
return ContextListener(self, *args, **kwargs)
3940

@@ -43,14 +44,12 @@ def __init__(self, device, frequency=None, refresh=None, sync=None, mono_sources
4344
self._handle = _alc.CreateContext(self._device._handle, None) # XXX
4445
assert self._handle
4546
_alc.MakeContextCurrent(self._handle)
46-
def __del__(self):
47-
_alc.MakeContextCurrent(None)
48-
if hasattr(self, "_handle"):
49-
try:
50-
_alc.DestroyContext(self._handle)
51-
except:
52-
pass
53-
del self._handle
47+
48+
handle = self._handle
49+
call_on_del(self, lambda: (_alc.MakeContextCurrent(None), _alc.DestroyContext(handle)))
50+
51+
def get_source(self):
52+
return Source(self)
5453

5554
def process(self):
5655
_alc.ProcessContext(self._handle)
@@ -114,17 +113,14 @@ def is_enabled(self, target):
114113
) # forward, up
115114

116115
class Source(_NoSetAttr):
117-
def __init__(self):
116+
def __init__(self, cl):
117+
self._cl = cl
118+
self._buffer = None
119+
118120
x = ctypes.c_uint()
119121
_al.GenSources(1, ctypes.byref(x))
120122
self._handle = x.value
121-
def __del__(self):
122-
if hasattr(self, "_handle"):
123-
try:
124-
_al.DeleteSources(1, ctypes.byref(ctypes.c_uint(self._handle)))
125-
except:
126-
pass
127-
del self._handle
123+
call_on_del(self, _al.DeleteSources, 1, ctypes.byref(ctypes.c_uint(self._handle)))
128124

129125
def queue_buffers(self, buffers):
130126
raise NotImplementedError
@@ -164,10 +160,14 @@ def rewindy(self):
164160
lambda self: call_array(ctypes.c_int, 1, _al.GetSourcei, self._handle, _al.LOOPING)[0],
165161
lambda self, v: _al.Sourcei(self._handle, _al.LOOPING, v),
166162
)
167-
buffer = property(
168-
lambda self: call_array(ctypes.c_int, 1, _al.GetSourcei, self._handle, _al.BUFFER)[0], # XXX
169-
lambda self, v: _al.Sourcei(self._handle, _al.BUFFER, _al.NONE if v is None else v._handle),
170-
)
163+
164+
def _get_buffer(self):
165+
return self._buffer
166+
def _set_buffer(self, v):
167+
_al.Sourcei(self._handle, _al.BUFFER, _al.NONE if v is None else v._handle)
168+
self._buffer = v
169+
buffer = property(_get_buffer, _set_buffer)
170+
171171
buffers_queued = property(
172172
lambda self: call_array(ctypes.c_int, 1, _al.GetSourcei, self._handle, _al.BUFFERS_QUEUED)[0],
173173
)
@@ -224,32 +224,27 @@ def rewindy(self):
224224
)
225225

226226
class Buffer(_NoSetAttr):
227-
def __init__(self, filename=None, data=None):
228-
assert filename is None or data is None
227+
def __init__(self, filename=None, data=None, rawdata=None):
228+
assert (filename is not None) + (data is not None) + (rawdata is not None) == 1
229+
229230
if filename is not None:
230231
self._handle = _alut.CreateBufferFromFile(filename)
231232
elif data is not None:
232233
self._handle = _alut.CreateBufferFromFileImage(data, len(data))
233234
else:
235+
channels, bits, frequency, data2 = rawdata
234236
x = ctypes.c_uint()
235237
_al.GenBuffers(1, ctypes.byref(x))
236238
self._handle = x.value
237-
def __del__(self):
238-
if hasattr(self, "_handle"):
239-
try:
240-
_al.DeleteBuffers(1, ctypes.byref(ctypes.c_uint(self._handle)))
241-
except:
242-
pass
243-
del self._handle
244-
245-
def set_data(self, channels, bits, frequency, data):
246-
format = {
247-
(1, 8): _al.FORMAT_MONO8,
248-
(1, 16): _al.FORMAT_MONO16,
249-
(2, 8): _al.FORMAT_STEREO8,
250-
(2, 16): _al.FORMAT_STEREO16,
251-
}[channels, bits]
252-
_al.BufferData(self._handle, format, data, len(data), frequency)
239+
format = {
240+
(1, 8): _al.FORMAT_MONO8,
241+
(1, 16): _al.FORMAT_MONO16,
242+
(2, 8): _al.FORMAT_STEREO8,
243+
(2, 16): _al.FORMAT_STEREO16,
244+
}[channels, bits]
245+
_al.BufferData(self._handle, format, data2, len(data2), frequency)
246+
247+
call_on_del(self, _al.DeleteBuffers, 1, ctypes.byref(ctypes.c_uint(self._handle)))
253248

254249
frequency = property(
255250
lambda self: call_array(ctypes.c_int, 1, _al.GetBufferi, self._handle, _al.FREQUENCY)[0],

test.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
device = openal.Device()
1010
contextlistener = device.ContextListener()
11-
source = openal.Source()
12-
source2 = openal.Source()
13-
expsources = [openal.Source() for i in xrange(20)]
11+
source = contextlistener.get_source()
12+
source2 = contextlistener.get_source()
13+
expsources = [contextlistener.get_source() for i in xrange(20)]
1414
buffer = openal.Buffer(os.path.join('sounds', '440.wav'))
1515
buffer2 = openal.Buffer(os.path.join('sounds', 'water.wav'))
1616
expbuffers = [openal.Buffer(os.path.join('sounds', 'explodes', x)) for x in os.listdir(os.path.join('sounds', 'explodes')) if x[0] != '.']
@@ -37,7 +37,7 @@
3737
freq2 = 10
3838
explodetime = 0
3939
x = 0
40-
while True:
40+
for i in xrange(600):
4141
x = not x
4242
source2.position = 3, 3, 3*(2*x-1)
4343
while explodetime < 0:

test2.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
device = openal.Device()
1010
contextlistener = device.ContextListener()
11-
source = openal.Source()
11+
source = contextlistener.get_source()
1212
buffer = openal.Buffer(os.path.join('sounds', '440.wav'))
1313

1414
contextlistener.position = 0, 0, 0

test3.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def po(o):
2525
b = openal.Buffer(sys.argv[1])
2626
po(b)
2727

28-
s = openal.Source()
28+
s = cl.get_source()
2929
po(s)
3030

3131
s.buffer = b

0 commit comments

Comments
 (0)