-
-
Notifications
You must be signed in to change notification settings - Fork 193
pygame.Sound.copy
implementation
#3238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
532482a
40bacbb
1fd41e2
aec7da7
3be9a1c
726244d
4bfd1e8
446c2f1
cc67e0d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -831,6 +831,72 @@ snd_get_samples_address(PyObject *self, PyObject *closure) | |
#endif | ||
} | ||
|
||
static PyObject * | ||
snd_copy(pgSoundObject *self, PyObject *_null) | ||
{ | ||
Mix_Chunk *chunk = pgSound_AsChunk(self); | ||
pgSoundObject *new_sound; | ||
Mix_Chunk *new_chunk; | ||
|
||
// Validate the input chunk | ||
CHECK_CHUNK_VALID(chunk, NULL); | ||
|
||
// Create a new sound object | ||
new_sound = | ||
(pgSoundObject *)pgSound_Type.tp_new(Py_TYPE(self), NULL, NULL); | ||
if (!new_sound) { | ||
PyErr_SetString(PyExc_RuntimeError, | ||
damusss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"Failed to allocate memory for new sound object"); | ||
return NULL; | ||
} | ||
|
||
// Handle chunk allocation type | ||
if (chunk->allocated) { | ||
// Create a deep copy of the audio buffer for allocated chunks | ||
Uint8 *buffer_copy = (Uint8 *)malloc(chunk->alen); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this is a memory leak. This is allocated but never freed, and it can't be freed here because it needs to live as long as the chunk does. |
||
if (!buffer_copy) { | ||
Py_DECREF(new_sound); | ||
PyErr_SetString(PyExc_MemoryError, | ||
"Failed to allocate memory for sound buffer"); | ||
return NULL; | ||
} | ||
memcpy(buffer_copy, chunk->abuf, chunk->alen); | ||
|
||
// Create a new Mix_Chunk | ||
new_chunk = Mix_QuickLoad_RAW(buffer_copy, chunk->alen); | ||
if (!new_chunk) { | ||
free(buffer_copy); | ||
Py_DECREF(new_sound); | ||
PyErr_SetString(PyExc_RuntimeError, | ||
damusss marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"Failed to create new sound chunk"); | ||
return NULL; | ||
} | ||
new_chunk->volume = chunk->volume; | ||
new_sound->chunk = new_chunk; | ||
} | ||
else { | ||
// For non-allocated chunks (e.g., formats like .xm), create a full | ||
// copy | ||
new_chunk = (Mix_Chunk *)malloc(sizeof(Mix_Chunk)); | ||
if (!new_chunk) { | ||
Py_DECREF(new_sound); | ||
PyErr_SetString(PyExc_MemoryError, | ||
"Failed to allocate memory for sound chunk"); | ||
return NULL; | ||
} | ||
*new_chunk = *chunk; // Copy the entire structure | ||
Comment on lines
+880
to
+887
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copying an entire struct like this may work in this scenario but in my opinion is not something that is safe in general. From SDL's perspective these are all internal fields and they can do whatever they want with it. They're barely documented. |
||
|
||
// For safety, ensure the copied chunk doesn't share pointers | ||
new_chunk->abuf = | ||
NULL; // Prevent double-free if original gets deallocated | ||
new_chunk->allocated = 0; | ||
|
||
new_sound->chunk = new_chunk; | ||
} | ||
|
||
return (PyObject *)new_sound; | ||
} | ||
|
||
PyMethodDef sound_methods[] = { | ||
{"play", (PyCFunction)pgSound_Play, METH_VARARGS | METH_KEYWORDS, | ||
DOC_MIXER_SOUND_PLAY}, | ||
|
@@ -842,6 +908,7 @@ PyMethodDef sound_methods[] = { | |
{"get_volume", snd_get_volume, METH_NOARGS, DOC_MIXER_SOUND_GETVOLUME}, | ||
{"get_length", snd_get_length, METH_NOARGS, DOC_MIXER_SOUND_GETLENGTH}, | ||
{"get_raw", snd_get_raw, METH_NOARGS, DOC_MIXER_SOUND_GETRAW}, | ||
{"copy", snd_copy, METH_NOARGS, ""}, | ||
{NULL, NULL, 0, NULL}}; | ||
|
||
static PyGetSetDef sound_getset[] = { | ||
|
Uh oh!
There was an error while loading. Please reload this page.