Fix T99039: bpy.ops.sound.mixdown returns indecipherable error

Fix for {T99039}.

The problem was that `AUD_mixdown` and `AUD_mixdown_per_channel` were returning pointers to freed memory.

Two key changes are made:
1. The return value of those functions now simply return a bool as to whether the operation succeeded, instead of an optional error string pointer.
2. The error string buffer is now passed into the function to be filled in case an error occurs. In this way, the onus of memory ownership is unamibiguously on the caller.

Differential Revision: https://developer.blender.org/D15260
This commit is contained in:
Colin Basnett 2022-07-16 20:57:28 +02:00 committed by Jörg Müller
parent 0a8d21e0c9
commit 1e4c557d82
Notes: blender-bot 2023-02-14 02:08:37 +01:00
Referenced by issue #99039, Python command gives indecipherable error (bpy.ops.sound.mixdown)
3 changed files with 34 additions and 17 deletions

View File

@ -270,7 +270,7 @@ AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, int sampl
return length;
}
AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, void(*callback)(float, void*), void* data)
AUD_API int AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, void(*callback)(float, void*), void* data, char* error, size_t errorsize)
{
try
{
@ -282,15 +282,19 @@ AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned i
std::shared_ptr<IWriter> writer = FileWriter::createWriter(filename, convCToDSpec(specs), static_cast<Container>(format), static_cast<Codec>(codec), bitrate);
FileWriter::writeReader(reader, writer, length, buffersize, callback, data);
return nullptr;
return 1;
}
catch(Exception& e)
{
return e.getMessage().c_str();
if(error && errorsize) {
std::strncpy(error, e.getMessage().c_str(), errorsize);
error[errorsize - 1] = '\0';
}
return 0;
}
}
AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, void(*callback)(float, void*), void* data)
AUD_API int AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate, void(*callback)(float, void*), void* data, char* error, size_t errorsize)
{
try
{
@ -328,11 +332,15 @@ AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start
reader->seek(start);
FileWriter::writeReader(reader, writers, length, buffersize, callback, data);
return nullptr;
return 1;
}
catch(Exception& e)
{
return e.getMessage().c_str();
if(error && errorsize) {
std::strncpy(error, e.getMessage().c_str(), errorsize);
error[errorsize - 1] = '\0';
}
return 0;
}
}

View File

@ -70,13 +70,15 @@ extern AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, in
* \param bitrate The bitrate for encoding.
* \param callback A callback function that is called periodically during mixdown, reporting progress if length > 0. Can be NULL.
* \param data Pass through parameter that is passed to the callback.
* \return An error message or NULL in case of success.
* \param error String buffer to copy the error message to in case of failure.
* \param errorsize The size of the error buffer.
* \return Whether or not the operation succeeded.
*/
extern AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length,
extern AUD_API int AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length,
unsigned int buffersize, const char* filename,
AUD_DeviceSpecs specs, AUD_Container format,
AUD_Codec codec, unsigned int bitrate,
void(*callback)(float, void*), void* data);
void(*callback)(float, void*), void* data, char* error, size_t errorsize);
/**
* Mixes a sound down into multiple files.
@ -91,13 +93,15 @@ extern AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, uns
* \param bitrate The bitrate for encoding.
* \param callback A callback function that is called periodically during mixdown, reporting progress if length > 0. Can be NULL.
* \param data Pass through parameter that is passed to the callback.
* \return An error message or NULL in case of success.
* \param error String buffer to copy the error message to in case of failure.
* \param errorsize The size of the error buffer.
* \return Whether or not the operation succeeded.
*/
extern AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length,
extern AUD_API int AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length,
unsigned int buffersize, const char* filename,
AUD_DeviceSpecs specs, AUD_Container format,
AUD_Codec codec, unsigned int bitrate,
void(*callback)(float, void*), void* data);
void(*callback)(float, void*), void* data, char* error, size_t errorsize);
/**
* Opens a read device and prepares it for mixdown of the sound scene.

View File

@ -340,7 +340,8 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
AUD_DeviceSpecs specs;
AUD_Container container;
AUD_Codec codec;
const char *result;
int result;
char error_message[1024] = {'\0'};
sound_bake_animation_exec(C, op);
@ -372,7 +373,9 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
codec,
bitrate,
NULL,
NULL);
NULL,
error_message,
sizeof(error_message));
}
else {
result = AUD_mixdown(scene_eval->sound_scene,
@ -385,13 +388,15 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
codec,
bitrate,
NULL,
NULL);
NULL,
error_message,
sizeof(error_message));
}
BKE_sound_reset_scene_specs(scene_eval);
if (result) {
BKE_report(op->reports, RPT_ERROR, result);
if (!result) {
BKE_report(op->reports, RPT_ERROR, error_message);
return OPERATOR_CANCELLED;
}
#else /* WITH_AUDASPACE */