mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-13 14:13:32 +02:00
Translate exceptions to error codes in callback functions...
... That is what the library protocols allow, and libraries may be written in C and might corrupt their state if C++ exceptions pass through them.
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
#include <wx/intl.h> // needed for _("translated stings") even if we
|
||||
// don't have libflac available
|
||||
|
||||
#include "../AudacityException.h"
|
||||
#include "Import.h"
|
||||
#include "ImportPlugin.h"
|
||||
|
||||
@@ -252,35 +253,38 @@ void MyFLACFile::error_callback(FLAC__StreamDecoderErrorStatus WXUNUSED(status))
|
||||
FLAC__StreamDecoderWriteStatus MyFLACFile::write_callback(const FLAC__Frame *frame,
|
||||
const FLAC__int32 * const buffer[])
|
||||
{
|
||||
ArrayOf<short> tmp{ frame->header.blocksize };
|
||||
// Don't let C++ exceptions propagate through libflac
|
||||
return GuardedCall< FLAC__StreamDecoderWriteStatus > ( [&] {
|
||||
auto tmp = ArrayOf< short >{ frame->header.blocksize };
|
||||
|
||||
auto iter = mFile->mChannels.begin();
|
||||
for (unsigned int chn=0; chn<mFile->mNumChannels; ++iter, ++chn) {
|
||||
if (frame->header.bits_per_sample == 16) {
|
||||
for (unsigned int s=0; s<frame->header.blocksize; s++) {
|
||||
tmp[s]=buffer[chn][s];
|
||||
auto iter = mFile->mChannels.begin();
|
||||
for (unsigned int chn=0; chn<mFile->mNumChannels; ++iter, ++chn) {
|
||||
if (frame->header.bits_per_sample == 16) {
|
||||
for (unsigned int s=0; s<frame->header.blocksize; s++) {
|
||||
tmp[s]=buffer[chn][s];
|
||||
}
|
||||
|
||||
iter->get()->Append((samplePtr)tmp.get(),
|
||||
int16Sample,
|
||||
frame->header.blocksize);
|
||||
}
|
||||
else {
|
||||
iter->get()->Append((samplePtr)buffer[chn],
|
||||
int24Sample,
|
||||
frame->header.blocksize);
|
||||
}
|
||||
|
||||
iter->get()->Append((samplePtr)tmp.get(),
|
||||
int16Sample,
|
||||
frame->header.blocksize);
|
||||
}
|
||||
else {
|
||||
iter->get()->Append((samplePtr)buffer[chn],
|
||||
int24Sample,
|
||||
frame->header.blocksize);
|
||||
|
||||
mFile->mSamplesDone += frame->header.blocksize;
|
||||
|
||||
mFile->mUpdateResult = mFile->mProgress->Update((wxULongLong_t) mFile->mSamplesDone, mFile->mNumSamples != 0 ? (wxULongLong_t)mFile->mNumSamples : 1);
|
||||
if (mFile->mUpdateResult != ProgressResult::Success)
|
||||
{
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
mFile->mSamplesDone += frame->header.blocksize;
|
||||
|
||||
mFile->mUpdateResult = mFile->mProgress->Update((wxULongLong_t) mFile->mSamplesDone, mFile->mNumSamples != 0 ? (wxULongLong_t)mFile->mNumSamples : 1);
|
||||
if (mFile->mUpdateResult != ProgressResult::Success)
|
||||
{
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}, MakeSimpleGuard(FLAC__STREAM_DECODER_WRITE_STATUS_ABORT) );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -46,6 +46,7 @@ Licensed under the GNU General Public License v2 or later
|
||||
#endif
|
||||
|
||||
// all the includes live here by default
|
||||
#include "../AudacityException.h"
|
||||
#include "../SampleFormat.h"
|
||||
#include "../Tags.h"
|
||||
#include "../Internat.h"
|
||||
@@ -489,20 +490,23 @@ inline void GstSampleUnref(GstSample *p) { gst_sample_unref(p); } // I can't use
|
||||
static GstFlowReturn
|
||||
GStreamerNewSample(GstAppSink *appsink, gpointer data)
|
||||
{
|
||||
GStreamerImportFileHandle *handle = (GStreamerImportFileHandle *)data;
|
||||
static GMutex mutex;
|
||||
// Don't let C++ exceptions propagate through GStreamer
|
||||
return GuardedCall< GstFlowReturn > ( [&] {
|
||||
GStreamerImportFileHandle *handle = (GStreamerImportFileHandle *)data;
|
||||
static GMutex mutex;
|
||||
|
||||
// Get the sample
|
||||
std::unique_ptr < GstSample, Deleter< GstSample, GstSampleUnref> >
|
||||
sample{ gst_app_sink_pull_sample(appsink) };
|
||||
// Get the sample
|
||||
std::unique_ptr < GstSample, Deleter< GstSample, GstSampleUnref> >
|
||||
sample{ gst_app_sink_pull_sample(appsink) };
|
||||
|
||||
// We must single thread here to prevent concurrent use of the
|
||||
// Audacity track functions.
|
||||
g_mutex_locker locker{ mutex };
|
||||
// We must single thread here to prevent concurrent use of the
|
||||
// Audacity track functions.
|
||||
g_mutex_locker locker{ mutex };
|
||||
|
||||
handle->OnNewSample(GETCTX(appsink), sample.get());
|
||||
handle->OnNewSample(GETCTX(appsink), sample.get());
|
||||
|
||||
return GST_FLOW_OK;
|
||||
return GST_FLOW_OK;
|
||||
}, MakeSimpleGuard(GST_FLOW_ERROR) );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include <wx/defs.h>
|
||||
#include <wx/intl.h>
|
||||
|
||||
#include "../AudacityException.h"
|
||||
#include "../Prefs.h"
|
||||
#include "Import.h"
|
||||
#include "ImportPlugin.h"
|
||||
@@ -480,59 +481,61 @@ enum mad_flow output_cb(void *_data,
|
||||
struct mad_header const * WXUNUSED(header),
|
||||
struct mad_pcm *pcm)
|
||||
{
|
||||
int samplerate;
|
||||
struct private_data *data = (struct private_data *)_data;
|
||||
// Don't C++ exceptions propagate through mad
|
||||
return GuardedCall< mad_flow > ( [&] {
|
||||
int samplerate;
|
||||
struct private_data *data = (struct private_data *)_data;
|
||||
|
||||
samplerate= pcm->samplerate;
|
||||
auto channels = pcm->channels;
|
||||
const auto samples = pcm->length;
|
||||
samplerate= pcm->samplerate;
|
||||
auto channels = pcm->channels;
|
||||
const auto samples = pcm->length;
|
||||
|
||||
/* If this is the first run, we need to create the WaveTracks that
|
||||
* will hold the data. We do this now because now is the first
|
||||
* moment when we know how many channels there are. */
|
||||
/* If this is the first run, we need to create the WaveTracks that
|
||||
* will hold the data. We do this now because now is the first
|
||||
* moment when we know how many channels there are. */
|
||||
|
||||
if(data->channels.empty()) {
|
||||
data->channels.resize(channels);
|
||||
if(data->channels.empty()) {
|
||||
data->channels.resize(channels);
|
||||
|
||||
sampleFormat format = (sampleFormat) gPrefs->
|
||||
Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
sampleFormat format = (sampleFormat) gPrefs->
|
||||
Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
|
||||
|
||||
for(auto &channel: data->channels) {
|
||||
channel = data->trackFactory->NewWaveTrack(format, samplerate);
|
||||
channel->SetChannel(Track::MonoChannel);
|
||||
for(auto &channel: data->channels) {
|
||||
channel = data->trackFactory->NewWaveTrack(format, samplerate);
|
||||
channel->SetChannel(Track::MonoChannel);
|
||||
}
|
||||
|
||||
/* special case: 2 channels is understood to be stereo */
|
||||
if(channels == 2) {
|
||||
data->channels.begin()->get()->SetChannel(Track::LeftChannel);
|
||||
data->channels.rbegin()->get()->SetChannel(Track::RightChannel);
|
||||
data->channels.begin()->get()->SetLinked(true);
|
||||
}
|
||||
data->numChannels = channels;
|
||||
}
|
||||
else {
|
||||
// This is not the first run, protect us from libmad glitching
|
||||
// on the number of channels
|
||||
channels = data->numChannels;
|
||||
}
|
||||
|
||||
/* special case: 2 channels is understood to be stereo */
|
||||
if(channels == 2) {
|
||||
data->channels.begin()->get()->SetChannel(Track::LeftChannel);
|
||||
data->channels.rbegin()->get()->SetChannel(Track::RightChannel);
|
||||
data->channels.begin()->get()->SetLinked(true);
|
||||
}
|
||||
data->numChannels = channels;
|
||||
}
|
||||
else {
|
||||
// This is not the first run, protect us from libmad glitching
|
||||
// on the number of channels
|
||||
channels = data->numChannels;
|
||||
}
|
||||
/* TODO: get rid of this by adding fixed-point support to SampleFormat.
|
||||
* For now, we allocate temporary float buffers to convert the fixed
|
||||
* point samples into something we can feed to the WaveTrack. Allocating
|
||||
* big blocks of data like this isn't a great idea, but it's temporary.
|
||||
*/
|
||||
FloatBuffers channelBuffers{ channels, samples };
|
||||
for(size_t smpl = 0; smpl < samples; smpl++)
|
||||
for(int chn = 0; chn < channels; chn++)
|
||||
channelBuffers[chn][smpl] = scale(pcm->samples[chn][smpl]);
|
||||
|
||||
/* TODO: get rid of this by adding fixed-point support to SampleFormat.
|
||||
* For now, we allocate temporary float buffers to convert the fixed
|
||||
* point samples into something we can feed to the WaveTrack. Allocating
|
||||
* big blocks of data like this isn't a great idea, but it's temporary.
|
||||
*/
|
||||
FloatBuffers channelBuffers{ channels, samples };
|
||||
|
||||
for (size_t smpl = 0; smpl < samples; smpl++)
|
||||
for(int chn = 0; chn < channels; chn++)
|
||||
channelBuffers[chn][smpl] = scale(pcm->samples[chn][smpl]);
|
||||
data->channels[chn]->Append((samplePtr)channelBuffers[chn].get(),
|
||||
floatSample,
|
||||
samples);
|
||||
|
||||
for (int chn = 0; chn < channels; chn++)
|
||||
data->channels[chn]->Append((samplePtr)channelBuffers[chn].get(),
|
||||
floatSample,
|
||||
samples);
|
||||
|
||||
return MAD_FLOW_CONTINUE;
|
||||
return MAD_FLOW_CONTINUE;
|
||||
}, MakeSimpleGuard(MAD_FLOW_BREAK) );
|
||||
}
|
||||
|
||||
enum mad_flow error_cb(void * WXUNUSED(_data), struct mad_stream * WXUNUSED(stream),
|
||||
|
Reference in New Issue
Block a user