From 8a1945ba2fe1fcb50035598671cc72db80771c3c Mon Sep 17 00:00:00 2001 From: Alexey Pavlov Date: Fri, 2 Aug 2019 10:12:08 +0300 Subject: [PATCH] audaspace: New package, dependency for blender --- mingw-w64-audaspace/01-gcc7-build.patch | 51 ++ .../02-support-new-ffmpeg.patch | 708 ++++++++++++++++++ .../03-backport-from-blender.patch | 152 ++++ .../04-python-memory-leak.patch | 22 + .../05-openal-recreate-device.patch | 287 +++++++ mingw-w64-audaspace/10-mingw-relocate.patch | 135 ++++ mingw-w64-audaspace/PKGBUILD | 71 ++ 7 files changed, 1426 insertions(+) create mode 100644 mingw-w64-audaspace/01-gcc7-build.patch create mode 100644 mingw-w64-audaspace/02-support-new-ffmpeg.patch create mode 100644 mingw-w64-audaspace/03-backport-from-blender.patch create mode 100644 mingw-w64-audaspace/04-python-memory-leak.patch create mode 100644 mingw-w64-audaspace/05-openal-recreate-device.patch create mode 100644 mingw-w64-audaspace/10-mingw-relocate.patch create mode 100644 mingw-w64-audaspace/PKGBUILD diff --git a/mingw-w64-audaspace/01-gcc7-build.patch b/mingw-w64-audaspace/01-gcc7-build.patch new file mode 100644 index 0000000000..9952c44f89 --- /dev/null +++ b/mingw-w64-audaspace/01-gcc7-build.patch @@ -0,0 +1,51 @@ +From aa11968dbf60f7e329a53ed49f67a5849d58114a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= +Date: Fri, 31 Mar 2017 18:33:47 +0200 +Subject: [PATCH] Bugfix for building with gcc7. + +Thanks for reporting @ Dave Plater. +--- + include/util/ThreadPool.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/util/ThreadPool.h b/include/util/ThreadPool.h +index 2f62276..24ec089 100644 +--- a/include/util/ThreadPool.h ++++ b/include/util/ThreadPool.h +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + AUD_NAMESPACE_BEGIN + /** +@@ -115,4 +116,4 @@ class AUD_API ThreadPool + */ + void threadFunction(); + }; +-AUD_NAMESPACE_END +\ No newline at end of file ++AUD_NAMESPACE_END + +From 2fb9862bfd7dd953a51f9bf4763bf0b308ddee13 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= +Date: Fri, 10 May 2019 23:04:14 +0200 +Subject: [PATCH] Fix: Missing include in FileManager.h. + +--- + include/file/FileManager.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/file/FileManager.h b/include/file/FileManager.h +index 03943ea..5670860 100644 +--- a/include/file/FileManager.h ++++ b/include/file/FileManager.h +@@ -27,6 +27,7 @@ + + #include + #include ++#include + + AUD_NAMESPACE_BEGIN + diff --git a/mingw-w64-audaspace/02-support-new-ffmpeg.patch b/mingw-w64-audaspace/02-support-new-ffmpeg.patch new file mode 100644 index 0000000000..689c050d8e --- /dev/null +++ b/mingw-w64-audaspace/02-support-new-ffmpeg.patch @@ -0,0 +1,708 @@ +From 212b4b605d9a73b97a4bf95ec080731477b64741 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= +Date: Fri, 8 Jun 2018 18:18:09 +0200 +Subject: [PATCH] Support newer ffmpeg versions. + +--- + plugins/ffmpeg/FFMPEG.cpp | 2 + + plugins/ffmpeg/FFMPEGReader.cpp | 124 ++++++++++++++---- + plugins/ffmpeg/FFMPEGReader.h | 5 + + plugins/ffmpeg/FFMPEGWriter.cpp | 216 +++++++++++++++++++++++--------- + plugins/ffmpeg/FFMPEGWriter.h | 13 +- + 5 files changed, 274 insertions(+), 86 deletions(-) + +diff --git a/plugins/ffmpeg/FFMPEG.cpp b/plugins/ffmpeg/FFMPEG.cpp +index 7f9b762..3ffe963 100644 +--- a/plugins/ffmpeg/FFMPEG.cpp ++++ b/plugins/ffmpeg/FFMPEG.cpp +@@ -23,7 +23,9 @@ AUD_NAMESPACE_BEGIN + + FFMPEG::FFMPEG() + { ++#if LIBAVCODEC_VERSION_MAJOR < 58 + av_register_all(); ++#endif + } + + void FFMPEG::registerPlugin() +diff --git a/plugins/ffmpeg/FFMPEGReader.cpp b/plugins/ffmpeg/FFMPEGReader.cpp +index 6b79cc5..2da84ce 100644 +--- a/plugins/ffmpeg/FFMPEGReader.cpp ++++ b/plugins/ffmpeg/FFMPEGReader.cpp +@@ -22,37 +22,37 @@ + extern "C" { + #include + #include ++#include + } + + AUD_NAMESPACE_BEGIN + ++#if LIBAVCODEC_VERSION_MAJOR < 58 ++#define FFMPEG_OLD_CODE ++#endif ++ + int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer) + { +- AVFrame* frame = nullptr; ++ int buf_size = buffer.getSize(); ++ int buf_pos = 0; ++ ++#ifdef FFMPEG_OLD_CODE + int got_frame; + int read_length; + uint8_t* orig_data = packet.data; + int orig_size = packet.size; + +- int buf_size = buffer.getSize(); +- int buf_pos = 0; +- + while(packet.size > 0) + { + got_frame = 0; + +- if(!frame) +- frame = av_frame_alloc(); +- else +- av_frame_unref(frame); +- +- read_length = avcodec_decode_audio4(m_codecCtx, frame, &got_frame, &packet); ++ read_length = avcodec_decode_audio4(m_codecCtx, m_frame, &got_frame, &packet); + if(read_length < 0) + break; + + if(got_frame) + { +- int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, frame->nb_samples, m_codecCtx->sample_fmt, 1); ++ int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1); + + if(buf_size - buf_pos < data_size) + { +@@ -62,18 +62,18 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer) + + if(m_tointerleave) + { +- int single_size = data_size / m_codecCtx->channels / frame->nb_samples; ++ int single_size = data_size / m_codecCtx->channels / m_frame->nb_samples; + for(int channel = 0; channel < m_codecCtx->channels; channel++) + { +- for(int i = 0; i < frame->nb_samples; i++) ++ for(int i = 0; i < m_frame->nb_samples; i++) + { + std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size, +- frame->data[channel] + i * single_size, single_size); ++ m_frame->data[channel] + i * single_size, single_size); + } + } + } + else +- std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos, frame->data[0], data_size); ++ std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos, m_frame->data[0], data_size); + + buf_pos += data_size; + } +@@ -83,7 +83,42 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer) + + packet.data = orig_data; + packet.size = orig_size; +- av_free(frame); ++#else ++ avcodec_send_packet(m_codecCtx, &packet); ++ ++ while(true) ++ { ++ auto ret = avcodec_receive_frame(m_codecCtx, m_frame); ++ ++ if(ret != 0) ++ break; ++ ++ int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1); ++ ++ if(buf_size - buf_pos < data_size) ++ { ++ buffer.resize(buf_size + data_size, true); ++ buf_size += data_size; ++ } ++ ++ if(m_tointerleave) ++ { ++ int single_size = data_size / m_codecCtx->channels / m_frame->nb_samples; ++ for(int channel = 0; channel < m_codecCtx->channels; channel++) ++ { ++ for(int i = 0; i < m_frame->nb_samples; i++) ++ { ++ std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size, ++ m_frame->data[channel] + i * single_size, single_size); ++ } ++ } ++ } ++ else ++ std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos, m_frame->data[0], data_size); ++ ++ buf_pos += data_size; ++ } ++#endif + + return buf_pos; + } +@@ -101,7 +136,11 @@ void FFMPEGReader::init() + + for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) + { ++#ifdef FFMPEG_OLD_CODE + if((m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) ++#else ++ if((m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ++#endif + && (m_stream < 0)) + { + m_stream=i; +@@ -112,12 +151,34 @@ void FFMPEGReader::init() + if(m_stream == -1) + AUD_THROW(FileException, "File couldn't be read, no audio stream found by ffmpeg."); + +- m_codecCtx = m_formatCtx->streams[m_stream]->codec; +- + // get a decoder and open it +- AVCodec* aCodec = avcodec_find_decoder(m_codecCtx->codec_id); ++#ifndef FFMPEG_OLD_CODE ++ AVCodec* aCodec = avcodec_find_decoder(m_formatCtx->streams[m_stream]->codecpar->codec_id); ++ + if(!aCodec) + AUD_THROW(FileException, "File couldn't be read, no decoder found with ffmpeg."); ++#endif ++ ++ m_frame = av_frame_alloc(); ++ ++ if(!m_frame) ++ AUD_THROW(FileException, "File couldn't be read, ffmpeg frame couldn't be allocated."); ++ ++#ifdef FFMPEG_OLD_CODE ++ m_codecCtx = m_formatCtx->streams[m_stream]->codec; ++ ++ AVCodec* aCodec = avcodec_find_decoder(m_codecCtx->codec_id); ++#else ++ m_codecCtx = avcodec_alloc_context3(aCodec); ++#endif ++ ++ if(!m_codecCtx) ++ AUD_THROW(FileException, "File couldn't be read, ffmpeg context couldn't be allocated."); ++ ++#ifndef FFMPEG_OLD_CODE ++ if(avcodec_parameters_to_context(m_codecCtx, m_formatCtx->streams[m_stream]->codecpar) < 0) ++ AUD_THROW(FileException, "File couldn't be read, ffmpeg decoder parameters couldn't be copied to decoder context."); ++#endif + + if(avcodec_open2(m_codecCtx, aCodec, nullptr) < 0) + AUD_THROW(FileException, "File couldn't be read, ffmpeg codec couldn't be opened."); +@@ -157,6 +218,8 @@ void FFMPEGReader::init() + FFMPEGReader::FFMPEGReader(std::string filename) : + m_pkgbuf(), + m_formatCtx(nullptr), ++ m_codecCtx(nullptr), ++ m_frame(nullptr), + m_aviocontext(nullptr), + m_membuf(nullptr) + { +@@ -177,12 +240,14 @@ FFMPEGReader::FFMPEGReader(std::string filename) : + + FFMPEGReader::FFMPEGReader(std::shared_ptr buffer) : + m_pkgbuf(), ++ m_codecCtx(nullptr), ++ m_frame(nullptr), + m_membuffer(buffer), + m_membufferpos(0) + { +- m_membuf = reinterpret_cast(av_malloc(FF_MIN_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE)); ++ m_membuf = reinterpret_cast(av_malloc(AV_INPUT_BUFFER_MIN_SIZE + AV_INPUT_BUFFER_PADDING_SIZE)); + +- m_aviocontext = avio_alloc_context(m_membuf, FF_MIN_BUFFER_SIZE, 0, this, read_packet, nullptr, seek_packet); ++ m_aviocontext = avio_alloc_context(m_membuf, AV_INPUT_BUFFER_MIN_SIZE, 0, this, read_packet, nullptr, seek_packet); + + if(!m_aviocontext) + { +@@ -212,7 +277,14 @@ FFMPEGReader::FFMPEGReader(std::shared_ptr buffer) : + + FFMPEGReader::~FFMPEGReader() + { ++ if(m_frame) ++ av_frame_free(&m_frame); ++#ifdef FFMPEG_OLD_CODE + avcodec_close(m_codecCtx); ++#else ++ if(m_codecCtx) ++ avcodec_free_context(&m_codecCtx); ++#endif + avformat_close_input(&m_formatCtx); + } + +@@ -312,7 +384,7 @@ void FFMPEGReader::seek(int position) + } + } + } +- av_free_packet(&packet); ++ av_packet_unref(&packet); + } + } + else +@@ -343,7 +415,7 @@ Specs FFMPEGReader::getSpecs() const + void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer) + { + // read packages and decode them +- AVPacket packet; ++ AVPacket packet = {}; + int data_size = 0; + int pkgbuf_pos; + int left = length; +@@ -359,7 +431,7 @@ void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer) + data_size = std::min(pkgbuf_pos, left * sample_size); + m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format)); + buf += data_size / AUD_FORMAT_SIZE(m_specs.format); +- left -= data_size/sample_size; ++ left -= data_size / sample_size; + } + + // for each frame read as long as there isn't enough data already +@@ -375,9 +447,9 @@ void FFMPEGReader::read(int& length, bool& eos, sample_t* buffer) + data_size = std::min(pkgbuf_pos, left * sample_size); + m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format)); + buf += data_size / AUD_FORMAT_SIZE(m_specs.format); +- left -= data_size/sample_size; ++ left -= data_size / sample_size; + } +- av_free_packet(&packet); ++ av_packet_unref(&packet); + } + // read more data than necessary? + if(pkgbuf_pos > data_size) +diff --git a/plugins/ffmpeg/FFMPEGReader.h b/plugins/ffmpeg/FFMPEGReader.h +index e2ae959..a69ac77 100644 +--- a/plugins/ffmpeg/FFMPEGReader.h ++++ b/plugins/ffmpeg/FFMPEGReader.h +@@ -79,6 +79,11 @@ class AUD_PLUGIN_API FFMPEGReader : public IReader + */ + AVCodecContext* m_codecCtx; + ++ /** ++ * The AVFrame structure for using ffmpeg. ++ */ ++ AVFrame* m_frame; ++ + /** + * The AVIOContext to read the data from. + */ +diff --git a/plugins/ffmpeg/FFMPEGWriter.cpp b/plugins/ffmpeg/FFMPEGWriter.cpp +index f79f0f7..09b7089 100644 +--- a/plugins/ffmpeg/FFMPEGWriter.cpp ++++ b/plugins/ffmpeg/FFMPEGWriter.cpp +@@ -27,6 +27,10 @@ extern "C" { + + AUD_NAMESPACE_BEGIN + ++#if LIBAVCODEC_VERSION_MAJOR < 58 ++#define FFMPEG_OLD_CODE ++#endif ++ + void FFMPEGWriter::encode() + { + sample_t* data = m_input_buffer.getBuffer(); +@@ -58,82 +62,106 @@ void FFMPEGWriter::encode() + if(m_input_size) + m_convert(reinterpret_cast(data), reinterpret_cast(data), m_input_samples * m_specs.channels); + +- AVPacket packet; +- +- packet.data = nullptr; +- packet.size = 0; ++#ifdef FFMPEG_OLD_CODE ++ m_packet->data = nullptr; ++ m_packet->size = 0; + +- av_init_packet(&packet); ++ av_init_packet(m_packet); + +- AVFrame* frame = av_frame_alloc(); +- av_frame_unref(frame); ++ av_frame_unref(m_frame); + int got_packet; ++#endif + +- frame->nb_samples = m_input_samples; +- frame->format = m_codecCtx->sample_fmt; +- frame->channel_layout = m_codecCtx->channel_layout; ++ m_frame->nb_samples = m_input_samples; ++ m_frame->format = m_codecCtx->sample_fmt; ++ m_frame->channel_layout = m_codecCtx->channel_layout; + +- if(avcodec_fill_audio_frame(frame, m_specs.channels, m_codecCtx->sample_fmt, reinterpret_cast(data), m_input_buffer.getSize(), 0) < 0) ++ if(avcodec_fill_audio_frame(m_frame, m_specs.channels, m_codecCtx->sample_fmt, reinterpret_cast(data), m_input_buffer.getSize(), 0) < 0) + AUD_THROW(FileException, "File couldn't be written, filling the audio frame failed with ffmpeg."); + + AVRational sample_time = { 1, static_cast(m_specs.rate) }; +- frame->pts = av_rescale_q(m_position - m_input_samples, m_codecCtx->time_base, sample_time); ++ m_frame->pts = av_rescale_q(m_position - m_input_samples, m_codecCtx->time_base, sample_time); + +- if(avcodec_encode_audio2(m_codecCtx, &packet, frame, &got_packet)) ++#ifdef FFMPEG_OLD_CODE ++ if(avcodec_encode_audio2(m_codecCtx, m_packet, m_frame, &got_packet)) + { +- av_frame_free(&frame); + AUD_THROW(FileException, "File couldn't be written, audio encoding failed with ffmpeg."); + } + + if(got_packet) + { +- packet.flags |= AV_PKT_FLAG_KEY; +- packet.stream_index = m_stream->index; +- if(av_write_frame(m_formatCtx, &packet) < 0) ++ m_packet->flags |= AV_PKT_FLAG_KEY; ++ m_packet->stream_index = m_stream->index; ++ if(av_write_frame(m_formatCtx, m_packet) < 0) + { +- av_free_packet(&packet); +- av_frame_free(&frame); ++ av_free_packet(m_packet); + AUD_THROW(FileException, "Frame couldn't be writen to the file with ffmpeg."); + } +- av_free_packet(&packet); ++ av_free_packet(m_packet); + } ++#else ++ if(avcodec_send_frame(m_codecCtx, m_frame) < 0) ++ AUD_THROW(FileException, "File couldn't be written, audio encoding failed with ffmpeg."); ++ ++ while(avcodec_receive_packet(m_codecCtx, m_packet) == 0) ++ { ++ m_packet->stream_index = m_stream->index; + +- av_frame_free(&frame); ++ if(av_write_frame(m_formatCtx, m_packet) < 0) ++ AUD_THROW(FileException, "Frame couldn't be writen to the file with ffmpeg."); ++ } ++#endif + } + + void FFMPEGWriter::close() + { ++#ifdef FFMPEG_OLD_CODE + int got_packet = true; + + while(got_packet) + { +- AVPacket packet; ++ m_packet->data = nullptr; ++ m_packet->size = 0; + +- packet.data = nullptr; +- packet.size = 0; ++ av_init_packet(m_packet); + +- av_init_packet(&packet); +- +- if(avcodec_encode_audio2(m_codecCtx, &packet, nullptr, &got_packet)) ++ if(avcodec_encode_audio2(m_codecCtx, m_packet, nullptr, &got_packet)) + AUD_THROW(FileException, "File end couldn't be written, audio encoding failed with ffmpeg."); + + if(got_packet) + { +- packet.flags |= AV_PKT_FLAG_KEY; +- packet.stream_index = m_stream->index; +- if(av_write_frame(m_formatCtx, &packet)) ++ m_packet->flags |= AV_PKT_FLAG_KEY; ++ m_packet->stream_index = m_stream->index; ++ if(av_write_frame(m_formatCtx, m_packet)) + { +- av_free_packet(&packet); ++ av_free_packet(m_packet); + AUD_THROW(FileException, "Final frames couldn't be writen to the file with ffmpeg."); + } +- av_free_packet(&packet); ++ av_free_packet(m_packet); + } + } ++#else ++ if(avcodec_send_frame(m_codecCtx, nullptr) < 0) ++ AUD_THROW(FileException, "File couldn't be written, audio encoding failed with ffmpeg."); ++ ++ while(avcodec_receive_packet(m_codecCtx, m_packet) == 0) ++ { ++ m_packet->stream_index = m_stream->index; ++ ++ if(av_write_frame(m_formatCtx, m_packet) < 0) ++ AUD_THROW(FileException, "Frame couldn't be writen to the file with ffmpeg."); ++ } ++#endif + } + + FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container format, Codec codec, unsigned int bitrate) : + m_position(0), + m_specs(specs), ++ m_formatCtx(nullptr), ++ m_codecCtx(nullptr), ++ m_stream(nullptr), ++ m_packet(nullptr), ++ m_frame(nullptr), + m_input_samples(0), + m_deinterleave(false) + { +@@ -142,75 +170,105 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo + if(avformat_alloc_output_context2(&m_formatCtx, nullptr, formats[format], filename.c_str()) < 0) + AUD_THROW(FileException, "File couldn't be written, format couldn't be found with ffmpeg."); + +- m_outputFmt = m_formatCtx->oformat; ++ AVOutputFormat* outputFmt = m_formatCtx->oformat; + +- if(!m_outputFmt) { ++ if(!outputFmt) { + avformat_free_context(m_formatCtx); + AUD_THROW(FileException, "File couldn't be written, output format couldn't be found with ffmpeg."); + } + +- m_outputFmt->audio_codec = AV_CODEC_ID_NONE; ++ outputFmt->audio_codec = AV_CODEC_ID_NONE; + + switch(codec) + { + case CODEC_AAC: +- m_outputFmt->audio_codec = AV_CODEC_ID_AAC; ++ outputFmt->audio_codec = AV_CODEC_ID_AAC; + break; + case CODEC_AC3: +- m_outputFmt->audio_codec = AV_CODEC_ID_AC3; ++ outputFmt->audio_codec = AV_CODEC_ID_AC3; + break; + case CODEC_FLAC: +- m_outputFmt->audio_codec = AV_CODEC_ID_FLAC; ++ outputFmt->audio_codec = AV_CODEC_ID_FLAC; + break; + case CODEC_MP2: +- m_outputFmt->audio_codec = AV_CODEC_ID_MP2; ++ outputFmt->audio_codec = AV_CODEC_ID_MP2; + break; + case CODEC_MP3: +- m_outputFmt->audio_codec = AV_CODEC_ID_MP3; ++ outputFmt->audio_codec = AV_CODEC_ID_MP3; + break; + case CODEC_OPUS: +- m_outputFmt->audio_codec = AV_CODEC_ID_OPUS; ++ outputFmt->audio_codec = AV_CODEC_ID_OPUS; + break; + case CODEC_PCM: + switch(specs.format) + { + case FORMAT_U8: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_U8; ++ outputFmt->audio_codec = AV_CODEC_ID_PCM_U8; + break; + case FORMAT_S16: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_S16LE; ++ outputFmt->audio_codec = AV_CODEC_ID_PCM_S16LE; + break; + case FORMAT_S24: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_S24LE; ++ outputFmt->audio_codec = AV_CODEC_ID_PCM_S24LE; + break; + case FORMAT_S32: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_S32LE; ++ outputFmt->audio_codec = AV_CODEC_ID_PCM_S32LE; + break; + case FORMAT_FLOAT32: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_F32LE; ++ outputFmt->audio_codec = AV_CODEC_ID_PCM_F32LE; + break; + case FORMAT_FLOAT64: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_F64LE; ++ outputFmt->audio_codec = AV_CODEC_ID_PCM_F64LE; + break; + default: +- m_outputFmt->audio_codec = AV_CODEC_ID_NONE; ++ outputFmt->audio_codec = AV_CODEC_ID_NONE; + break; + } + break; + case CODEC_VORBIS: +- m_outputFmt->audio_codec = AV_CODEC_ID_VORBIS; ++ outputFmt->audio_codec = AV_CODEC_ID_VORBIS; + break; + default: +- m_outputFmt->audio_codec = AV_CODEC_ID_NONE; ++ outputFmt->audio_codec = AV_CODEC_ID_NONE; ++ break; ++ } ++ ++ uint64_t channel_layout = 0; ++ ++ switch(m_specs.channels) ++ { ++ case CHANNELS_MONO: ++ channel_layout = AV_CH_LAYOUT_MONO; ++ break; ++ case CHANNELS_STEREO: ++ channel_layout = AV_CH_LAYOUT_STEREO; ++ break; ++ case CHANNELS_STEREO_LFE: ++ channel_layout = AV_CH_LAYOUT_2POINT1; ++ break; ++ case CHANNELS_SURROUND4: ++ channel_layout = AV_CH_LAYOUT_QUAD; ++ break; ++ case CHANNELS_SURROUND5: ++ channel_layout = AV_CH_LAYOUT_5POINT0_BACK; ++ break; ++ case CHANNELS_SURROUND51: ++ channel_layout = AV_CH_LAYOUT_5POINT1_BACK; ++ break; ++ case CHANNELS_SURROUND61: ++ channel_layout = AV_CH_LAYOUT_6POINT1_BACK; ++ break; ++ case CHANNELS_SURROUND71: ++ channel_layout = AV_CH_LAYOUT_7POINT1; + break; + } + + try + { +- if(m_outputFmt->audio_codec == AV_CODEC_ID_NONE) ++ if(outputFmt->audio_codec == AV_CODEC_ID_NONE) + AUD_THROW(FileException, "File couldn't be written, audio codec not found with ffmpeg."); + +- AVCodec* codec = avcodec_find_encoder(m_outputFmt->audio_codec); ++ AVCodec* codec = avcodec_find_encoder(outputFmt->audio_codec); + if(!codec) + AUD_THROW(FileException, "File couldn't be written, audio encoder couldn't be found with ffmpeg."); + +@@ -220,7 +278,14 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo + + m_stream->id = m_formatCtx->nb_streams - 1; + ++#ifdef FFMPEG_OLD_CODE + m_codecCtx = m_stream->codec; ++#else ++ m_codecCtx = avcodec_alloc_context3(codec); ++#endif ++ ++ if(!m_codecCtx) ++ AUD_THROW(FileException, "File couldn't be written, context creation failed with ffmpeg."); + + switch(m_specs.format) + { +@@ -247,7 +312,7 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo + } + + if(m_formatCtx->oformat->flags & AVFMT_GLOBALHEADER) +- m_codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; ++ m_codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + + bool format_supported = false; + +@@ -328,9 +393,13 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo + + m_specs.rate = m_codecCtx->sample_rate; + +- m_codecCtx->codec_id = m_outputFmt->audio_codec; ++#ifdef FFMPEG_OLD_CODE ++ m_codecCtx->codec_id = outputFmt->audio_codec; ++#endif ++ + m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO; + m_codecCtx->bit_rate = bitrate; ++ m_codecCtx->channel_layout = channel_layout; + m_codecCtx->channels = m_specs.channels; + m_stream->time_base.num = m_codecCtx->time_base.num = 1; + m_stream->time_base.den = m_codecCtx->time_base.den = m_codecCtx->sample_rate; +@@ -338,6 +407,11 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo + if(avcodec_open2(m_codecCtx, codec, nullptr) < 0) + AUD_THROW(FileException, "File couldn't be written, encoder couldn't be opened with ffmpeg."); + ++#ifndef FFMPEG_OLD_CODE ++ if(avcodec_parameters_from_context(m_stream->codecpar, m_codecCtx) < 0) ++ AUD_THROW(FileException, "File couldn't be written, codec parameters couldn't be copied to the context."); ++#endif ++ + int samplesize = std::max(int(AUD_SAMPLE_SIZE(m_specs)), AUD_DEVICE_SAMPLE_SIZE(m_specs)); + + if((m_input_size = m_codecCtx->frame_size)) +@@ -346,13 +420,26 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo + if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_FLAG_WRITE)) + AUD_THROW(FileException, "File couldn't be written, file opening failed with ffmpeg."); + +- avformat_write_header(m_formatCtx, nullptr); ++ if(avformat_write_header(m_formatCtx, nullptr) < 0) ++ AUD_THROW(FileException, "File couldn't be written, writing the header failed."); + } + catch(Exception&) + { ++#ifndef FFMPEG_OLD_CODE ++ if(m_codecCtx) ++ avcodec_free_context(&m_codecCtx); ++#endif + avformat_free_context(m_formatCtx); + throw; + } ++ ++#ifdef FFMPEG_OLD_CODE ++ m_packet = new AVPacket({}); ++#else ++ m_packet = av_packet_alloc(); ++#endif ++ ++ m_frame = av_frame_alloc(); + } + + FFMPEGWriter::~FFMPEGWriter() +@@ -365,9 +452,26 @@ FFMPEGWriter::~FFMPEGWriter() + + av_write_trailer(m_formatCtx); + ++ if(m_frame) ++ av_frame_free(&m_frame); ++ ++ if(m_packet) ++ { ++#ifdef FFMPEG_OLD_CODE ++ delete m_packet; ++#else ++ av_packet_free(&m_packet); ++#endif ++ } ++ ++#ifdef FFMPEG_OLD_CODE + avcodec_close(m_codecCtx); ++#else ++ if(m_codecCtx) ++ avcodec_free_context(&m_codecCtx); ++#endif + +- avio_close(m_formatCtx->pb); ++ avio_closep(&m_formatCtx->pb); + avformat_free_context(m_formatCtx); + } + +diff --git a/plugins/ffmpeg/FFMPEGWriter.h b/plugins/ffmpeg/FFMPEGWriter.h +index 690185d..c22f479 100644 +--- a/plugins/ffmpeg/FFMPEGWriter.h ++++ b/plugins/ffmpeg/FFMPEGWriter.h +@@ -66,14 +66,19 @@ class AUD_PLUGIN_API FFMPEGWriter : public IWriter + AVCodecContext* m_codecCtx; + + /** +- * The AVOutputFormat structure for using ffmpeg. ++ * The AVStream structure for using ffmpeg. + */ +- AVOutputFormat* m_outputFmt; ++ AVStream* m_stream; + + /** +- * The AVStream structure for using ffmpeg. ++ * The AVPacket structure for using ffmpeg. + */ +- AVStream* m_stream; ++ AVPacket* m_packet; ++ ++ /** ++ * The AVFrame structure for using ffmpeg. ++ */ ++ AVFrame* m_frame; + + /** + * The input buffer for the format converted data before encoding. diff --git a/mingw-w64-audaspace/03-backport-from-blender.patch b/mingw-w64-audaspace/03-backport-from-blender.patch new file mode 100644 index 0000000000..b1e59caa7e --- /dev/null +++ b/mingw-w64-audaspace/03-backport-from-blender.patch @@ -0,0 +1,152 @@ +From 10413c522900d3aaadd5f5ae12163eee80ef18ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= +Date: Sun, 5 Mar 2017 12:22:00 +0100 +Subject: [PATCH] Fix for seeking with modified pitch. + +Check Blender bug report T50843: Pitched Audio renders incorrectly in VSE. +--- + src/devices/SoftwareDevice.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/devices/SoftwareDevice.cpp b/src/devices/SoftwareDevice.cpp +index 5fbb68c..c944b9e 100644 +--- a/src/devices/SoftwareDevice.cpp ++++ b/src/devices/SoftwareDevice.cpp +@@ -357,6 +357,7 @@ bool SoftwareDevice::SoftwareHandle::seek(float position) + if(!m_status) + return false; + ++ m_pitch->setPitch(m_user_pitch); + m_reader->seek((int)(position * m_reader->getSpecs().rate)); + + if(m_status == STATUS_STOPPED) + +From 9b38605bb1d2927bf9313ee7ac4c13654e2bb513 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= +Date: Fri, 8 Jun 2018 23:00:13 +0200 +Subject: [PATCH] Some fixes backported from Blender. + +--- + bindings/C/AUD_Sound.cpp | 7 +++++-- + bindings/C/AUD_Source.h | 4 ++-- + bindings/C/AUD_Types.h | 14 ++++++++++---- + src/fx/DynamicMusic.cpp | 2 +- + src/fx/PlaybackCategory.cpp | 2 +- + 5 files changed, 19 insertions(+), 10 deletions(-) + +diff --git a/bindings/C/AUD_Sound.cpp b/bindings/C/AUD_Sound.cpp +index 9c572cf..30860ac 100644 +--- a/bindings/C/AUD_Sound.cpp ++++ b/bindings/C/AUD_Sound.cpp +@@ -24,8 +24,6 @@ + #include "util/StreamBuffer.h" + #include "fx/Accumulator.h" + #include "fx/ADSR.h" +-#include "fx/BinauralSound.h" +-#include "fx/ConvolverSound.h" + #include "fx/Delay.h" + #include "fx/Envelope.h" + #include "fx/Fader.h" +@@ -52,6 +50,11 @@ + #include "util/Buffer.h" + #include "Exception.h" + ++#ifdef WITH_CONVOLUTION ++#include "fx/BinauralSound.h" ++#include "fx/ConvolverSound.h" ++#endif ++ + #include + #include + +diff --git a/bindings/C/AUD_Source.h b/bindings/C/AUD_Source.h +index e55d251..6ff045e 100644 +--- a/bindings/C/AUD_Source.h ++++ b/bindings/C/AUD_Source.h +@@ -33,7 +33,7 @@ extern AUD_API AUD_Source* AUD_Source_create(float azimuth, float elevation, flo + + /** + * Deletes a Source object. +-* \param hrtfs The Source object to be deleted. ++* \param source The Source object to be deleted. + */ + extern AUD_API void AUD_Source_free(AUD_Source* source); + +@@ -81,4 +81,4 @@ extern AUD_API void AUD_Source_setDistance(AUD_Source* source, float distance); + + #ifdef __cplusplus + } +-#endif +\ No newline at end of file ++#endif +diff --git a/bindings/C/AUD_Types.h b/bindings/C/AUD_Types.h +index 017843b..75e4ffa 100644 +--- a/bindings/C/AUD_Types.h ++++ b/bindings/C/AUD_Types.h +@@ -29,10 +29,12 @@ using namespace aud; + #include "sequence/SequenceEntry.h" + #include "fx/PlaybackManager.h" + #include "fx/DynamicMusic.h" +-#include "fx/ImpulseResponse.h" +-#include "fx/HRTF.h" + #include "fx/Source.h" + #include "util/ThreadPool.h" ++#ifdef WITH_CONVOLUTION ++#include "fx/ImpulseResponse.h" ++#include "fx/HRTF.h" ++#endif + + typedef std::shared_ptr AUD_Sound; + typedef std::shared_ptr AUD_Handle; +@@ -41,9 +43,11 @@ typedef std::shared_ptr AUD_SequenceEntry; + typedef std::shared_ptr AUD_PlaybackManager; + typedef std::shared_ptr AUD_DynamicMusic; + typedef std::shared_ptr AUD_ThreadPool; ++typedef std::shared_ptr AUD_Source; ++#ifdef WITH_CONVOLUTION + typedef std::shared_ptr AUD_ImpulseResponse; + typedef std::shared_ptr AUD_HRTF; +-typedef std::shared_ptr AUD_Source; ++#endif + #else + typedef void AUD_Sound; + typedef void AUD_Handle; +@@ -52,9 +56,11 @@ typedef void AUD_SequenceEntry; + typedef void AUD_PlaybackManager; + typedef void AUD_DynamicMusic; + typedef void AUD_ThreadPool; ++typedef void AUD_Source; ++#ifdef WITH_CONVOLUTION + typedef void AUD_ImpulseResponse; + typedef void AUD_HRTF; +-typedef void AUD_Source; ++#endif + #endif + + /// Container formats for writers. +diff --git a/src/fx/DynamicMusic.cpp b/src/fx/DynamicMusic.cpp +index b77cd74..2b0acc0 100644 +--- a/src/fx/DynamicMusic.cpp ++++ b/src/fx/DynamicMusic.cpp +@@ -25,7 +25,7 @@ + AUD_NAMESPACE_BEGIN + + DynamicMusic::DynamicMusic(std::shared_ptr device) : +-m_device(device), m_fadeTime(1.0f) ++m_fadeTime(1.0f), m_device(device) + { + m_id = 0; + m_transitioning = false; +diff --git a/src/fx/PlaybackCategory.cpp b/src/fx/PlaybackCategory.cpp +index e09a74c..1891be9 100644 +--- a/src/fx/PlaybackCategory.cpp ++++ b/src/fx/PlaybackCategory.cpp +@@ -25,7 +25,7 @@ struct HandleData { + }; + + PlaybackCategory::PlaybackCategory(std::shared_ptr device) : +- m_device(device), m_volumeStorage(std::make_shared(1.0f)), m_status(STATUS_PLAYING), m_currentID(0) ++ m_currentID(0), m_device(device), m_status(STATUS_PLAYING), m_volumeStorage(std::make_shared(1.0f)) + { + } + diff --git a/mingw-w64-audaspace/04-python-memory-leak.patch b/mingw-w64-audaspace/04-python-memory-leak.patch new file mode 100644 index 0000000000..644b8d16ae --- /dev/null +++ b/mingw-w64-audaspace/04-python-memory-leak.patch @@ -0,0 +1,22 @@ +From a2ff4e8c55199ec622d30dc2e5d49f01e37cd40e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= +Date: Thu, 17 Jan 2019 19:35:42 +0100 +Subject: [PATCH] Bugfix: memory leak in python API. + +--- + bindings/python/PySound.cpp | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/bindings/python/PySound.cpp b/bindings/python/PySound.cpp +index 2ab1974..82c6036 100644 +--- a/bindings/python/PySound.cpp ++++ b/bindings/python/PySound.cpp +@@ -140,8 +140,6 @@ Sound_data(Sound* self) + + std::memcpy(data, buffer->getBuffer(), buffer->getSize()); + +- Py_INCREF(array); +- + return reinterpret_cast(array); + } + diff --git a/mingw-w64-audaspace/05-openal-recreate-device.patch b/mingw-w64-audaspace/05-openal-recreate-device.patch new file mode 100644 index 0000000000..82e608c57b --- /dev/null +++ b/mingw-w64-audaspace/05-openal-recreate-device.patch @@ -0,0 +1,287 @@ +From 7ad99dfb7790dfa70434391656f14444201d5e4b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= +Date: Thu, 17 Jan 2019 20:53:36 +0100 +Subject: [PATCH] OpenAL: recreate device if disconnected. + +--- + plugins/openal/OpenALDevice.cpp | 153 +++++++++++++++++++++++++++++--- + plugins/openal/OpenALDevice.h | 15 ++++ + 2 files changed, 156 insertions(+), 12 deletions(-) + +diff --git a/plugins/openal/OpenALDevice.cpp b/plugins/openal/OpenALDevice.cpp +index 2a60978..6ad87c1 100644 +--- a/plugins/openal/OpenALDevice.cpp ++++ b/plugins/openal/OpenALDevice.cpp +@@ -61,10 +61,58 @@ bool OpenALDevice::OpenALHandle::pause(bool keep) + return false; + } + ++bool OpenALDevice::OpenALHandle::reinitialize() ++{ ++ DeviceSpecs specs = m_device->m_specs; ++ specs.specs = m_reader->getSpecs(); ++ ++ ALenum format; ++ ++ if(!m_device->getFormat(format, specs.specs)) ++ return true; ++ ++ m_format = format; ++ ++ // OpenAL playback code ++ alGenBuffers(CYCLE_BUFFERS, m_buffers); ++ if(alGetError() != AL_NO_ERROR) ++ return true; ++ ++ m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs)); ++ int length; ++ bool eos; ++ ++ for(m_current = 0; m_current < CYCLE_BUFFERS; m_current++) ++ { ++ length = m_device->m_buffersize; ++ m_reader->read(length, eos, m_device->m_buffer.getBuffer()); ++ ++ if(length == 0) ++ break; ++ ++ alBufferData(m_buffers[m_current], m_format, m_device->m_buffer.getBuffer(), length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); ++ ++ if(alGetError() != AL_NO_ERROR) ++ return true; ++ } ++ ++ alGenSources(1, &m_source); ++ if(alGetError() != AL_NO_ERROR) ++ return true; ++ ++ alSourceQueueBuffers(m_source, m_current, m_buffers); ++ if(alGetError() != AL_NO_ERROR) ++ return true; ++ ++ alSourcei(m_source, AL_SOURCE_RELATIVE, m_relative); ++ ++ return false; ++} ++ + OpenALDevice::OpenALHandle::OpenALHandle(OpenALDevice* device, ALenum format, std::shared_ptr reader, bool keep) : + m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), + m_eos(false), m_loopcount(0), m_stop(nullptr), m_stop_data(nullptr), m_status(STATUS_PLAYING), +- m_device(device) ++ m_relative(1), m_device(device) + { + DeviceSpecs specs = m_device->m_specs; + specs.specs = m_reader->getSpecs(); +@@ -162,6 +210,9 @@ bool OpenALDevice::OpenALHandle::stop() + if(!m_status) + return false; + ++ if(m_stop) ++ m_stop(m_stop_data); ++ + m_status = STATUS_INVALID; + + alDeleteSources(1, &m_source); +@@ -525,8 +576,6 @@ bool OpenALDevice::OpenALHandle::setOrientation(const Quaternion& orientation) + + bool OpenALDevice::OpenALHandle::isRelative() + { +- int result; +- + if(!m_status) + return false; + +@@ -535,9 +584,9 @@ bool OpenALDevice::OpenALHandle::isRelative() + if(!m_status) + return false; + +- alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result); ++ alGetSourcei(m_source, AL_SOURCE_RELATIVE, &m_relative); + +- return result; ++ return m_relative; + } + + bool OpenALDevice::OpenALHandle::setRelative(bool relative) +@@ -550,7 +599,9 @@ bool OpenALDevice::OpenALHandle::setRelative(bool relative) + if(!m_status) + return false; + +- alSourcei(m_source, AL_SOURCE_RELATIVE, relative); ++ m_relative = relative; ++ ++ alSourcei(m_source, AL_SOURCE_RELATIVE, m_relative); + + return true; + } +@@ -852,6 +903,80 @@ void OpenALDevice::updateStreams() + { + lock(); + ++ if(m_checkDisconnect) ++ { ++ ALCint connected; ++ alcGetIntegerv(m_device, alcGetEnumValue(m_device, "ALC_CONNECTED"), 1, &connected); ++ ++ if(!connected) ++ { ++ // quit OpenAL ++ alcMakeContextCurrent(nullptr); ++ alcDestroyContext(m_context); ++ alcCloseDevice(m_device); ++ ++ // restart ++ if(m_name.empty()) ++ m_device = alcOpenDevice(nullptr); ++ else ++ m_device = alcOpenDevice(m_name.c_str()); ++ ++ // if device opening failed, there's really nothing we can do ++ if(m_device) ++ { ++ // at least try to set the frequency ++ ++ ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 }; ++ ALCint* attributes = attribs; ++ if(specs.rate == RATE_INVALID) ++ attributes = nullptr; ++ ++ m_context = alcCreateContext(m_device, attributes); ++ alcMakeContextCurrent(m_context); ++ ++ m_checkDisconnect = alcIsExtensionPresent(m_device, "ALC_EXT_disconnect"); ++ ++ alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate); ++ ++ // check for specific formats and channel counts to be played back ++ if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE) ++ specs.format = FORMAT_FLOAT32; ++ else ++ specs.format = FORMAT_S16; ++ ++ // if the format of the device changed, all handles are invalidated ++ // this is unlikely to happen though ++ if(specs.format != m_specs.format) ++ stopAll(); ++ ++ m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE; ++ ++ if((!m_useMC && specs.channels > CHANNELS_STEREO) || ++ specs.channels == CHANNELS_STEREO_LFE || ++ specs.channels == CHANNELS_SURROUND5) ++ specs.channels = CHANNELS_STEREO; ++ ++ alGetError(); ++ alcGetError(m_device); ++ ++ m_specs = specs; ++ ++ std::list > stopSounds; ++ ++ for(auto& handle : m_playingSounds) ++ if(handle->reinitialize()) ++ stopSounds.push_back(handle); ++ ++ for(auto& handle : m_pausedSounds) ++ if(handle->reinitialize()) ++ stopSounds.push_back(handle); ++ ++ for(auto& sound : stopSounds) ++ sound->stop(); ++ } ++ } ++ } ++ + alcSuspendContext(m_context); + cerr = alcGetError(m_device); + if(cerr == ALC_NO_ERROR) +@@ -957,12 +1082,14 @@ void OpenALDevice::updateStreams() + // if it really stopped + if(sound->m_eos && info != AL_INITIAL) + { +- if(sound->m_stop) +- sound->m_stop(sound->m_stop_data); +- + // pause or + if(sound->m_keep) ++ { ++ if(sound->m_stop) ++ sound->m_stop(sound->m_stop_data); ++ + pauseSounds.push_back(sound); ++ } + // stop + else + stopSounds.push_back(sound); +@@ -1005,16 +1132,16 @@ void OpenALDevice::updateStreams() + /******************************************************************************/ + + OpenALDevice::OpenALDevice(DeviceSpecs specs, int buffersize, std::string name) : +- m_playing(false), m_buffersize(buffersize) ++ m_name(name), m_playing(false), m_buffersize(buffersize) + { + // cannot determine how many channels or which format OpenAL uses, but + // it at least is able to play 16 bit stereo audio + specs.format = FORMAT_S16; + +- if(name.empty()) ++ if(m_name.empty()) + m_device = alcOpenDevice(nullptr); + else +- m_device = alcOpenDevice(name.c_str()); ++ m_device = alcOpenDevice(m_name.c_str()); + + if(!m_device) + AUD_THROW(DeviceException, "The audio device couldn't be opened with OpenAL."); +@@ -1028,6 +1155,8 @@ OpenALDevice::OpenALDevice(DeviceSpecs specs, int buffersize, std::string name) + m_context = alcCreateContext(m_device, attributes); + alcMakeContextCurrent(m_context); + ++ m_checkDisconnect = alcIsExtensionPresent(m_device, "ALC_EXT_disconnect"); ++ + alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate); + + // check for specific formats and channel counts to be played back +diff --git a/plugins/openal/OpenALDevice.h b/plugins/openal/OpenALDevice.h +index b9b461a..c2bec44 100644 +--- a/plugins/openal/OpenALDevice.h ++++ b/plugins/openal/OpenALDevice.h +@@ -95,11 +95,16 @@ class AUD_PLUGIN_API OpenALDevice : public IDevice, public I3DDevice + /// Current status of the handle + Status m_status; + ++ /// Whether the source is relative or not. ++ ALint m_relative; ++ + /// Own device. + OpenALDevice* m_device; + + AUD_LOCAL bool pause(bool keep); + ++ AUD_LOCAL bool reinitialize(); ++ + // delete copy constructor and operator= + OpenALHandle(const OpenALHandle&) = delete; + OpenALHandle& operator=(const OpenALHandle&) = delete; +@@ -173,11 +178,21 @@ class AUD_PLUGIN_API OpenALDevice : public IDevice, public I3DDevice + */ + DeviceSpecs m_specs; + ++ /** ++ * The device name. ++ */ ++ std::string m_name; ++ + /** + * Whether the device has the AL_EXT_MCFORMATS extension. + */ + bool m_useMC; + ++ /** ++ * Whether the ALC_EXT_disconnect extension is present and device disconnect should be checked repeatedly. ++ */ ++ bool m_checkDisconnect; ++ + /** + * The list of sounds that are currently playing. + */ diff --git a/mingw-w64-audaspace/10-mingw-relocate.patch b/mingw-w64-audaspace/10-mingw-relocate.patch new file mode 100644 index 0000000000..821bf2f88a --- /dev/null +++ b/mingw-w64-audaspace/10-mingw-relocate.patch @@ -0,0 +1,135 @@ +--- audaspace-1.3.0/CMakeLists.txt.orig 2019-08-02 08:32:35.510699000 +0300 ++++ audaspace-1.3.0/CMakeLists.txt 2019-08-02 09:41:42.487481800 +0300 +@@ -292,9 +292,12 @@ + set(PACKAGE_OPTION REQUIRED) + endif() + +-if(WIN32) ++if(MSVC) + set(DEFAULT_PLUGIN_PATH "." CACHE STRING "Default plugin installation and loading path.") + set(DOCUMENTATION_INSTALL_PATH "doc" CACHE PATH "Path where the documentation is installed.") ++elseif(MINGW) ++ set(DEFAULT_PLUGIN_PATH "lib/audaspace" CACHE STRING "Default plugin installation and loading path.") ++ set(DOCUMENTATION_INSTALL_PATH "share/doc/audaspace" CACHE PATH "Path where the documentation is installed.") + else() + set(DEFAULT_PLUGIN_PATH "${CMAKE_INSTALL_PREFIX}/share/audaspace/plugins" CACHE STRING "Default plugin installation and loading path.") + set(DOCUMENTATION_INSTALL_PATH "share/doc/audaspace" CACHE PATH "Path where the documentation is installed.") +@@ -605,6 +608,11 @@ + endif() + endif() + ++add_definitions(-DWITH_CONVOLUTION) ++if (MINGW) ++ list(APPEND LIBRARIES -lshlwapi) ++endif() ++ + # library configuration + + if(SHARED_LIBRARY) +@@ -652,7 +659,7 @@ + + # install configuration + +-if(WIN32) ++if(MSVC) + set(BIN_DESTINATION ".") + else() + set(BIN_DESTINATION "bin") +@@ -676,7 +683,7 @@ + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Audaspace.h DESTINATION include/audaspace) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packages/pkgconfig/audaspace.pc.in ${CMAKE_CURRENT_BINARY_DIR}/audaspace.pc @ONLY) +-if(NOT WIN32 AND NOT APPLE) ++if(NOT MSVC AND NOT APPLE) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/audaspace.pc DESTINATION "lib${LIB_SUFFIX}/pkgconfig") + endif() + +@@ -733,7 +740,7 @@ + + # dlls + +-if(WIN32) ++if(MSVC) + if(DLLS) + install(FILES ${DLLS} DESTINATION ${BIN_DESTINATION}) + endif() +@@ -856,7 +863,7 @@ + + if(APPLE) + add_custom_command(OUTPUT build COMMAND MACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} ${PYTHON_EXECUTABLE} setup.py build DEPENDS ${PYTHON_SRC} ${PYTHON_HDR}) +- elseif(WIN32) ++ elseif(MSVC) + set(ENV{VS100COMNTOOLS} $ENV{VS120COMNTOOLS}) + add_custom_command(OUTPUT build COMMAND ${PYTHON_EXECUTABLE} setup.py build DEPENDS ${PYTHON_SRC} ${PYTHON_HDR}) + else() +--- audaspace-1.3.0/src/plugin/PluginManagerWindows.cpp.in.orig 2019-08-02 08:39:36.094244200 +0300 ++++ audaspace-1.3.0/src/plugin/PluginManagerWindows.cpp.in 2019-08-02 09:39:21.400834000 +0300 +@@ -17,6 +17,13 @@ + #include "plugin/PluginManager.h" + + #include ++#ifdef __MINGW32__ ++#include ++#endif ++ ++namespace { ++ char dummyChar; ++} + + AUD_NAMESPACE_BEGIN + +@@ -29,7 +36,7 @@ + + void *PluginManager::lookupLibrary(void *handle, const std::string &name) + { +- return GetProcAddress(reinterpret_cast(handle), name.c_str()); ++ return reinterpret_cast(GetProcAddress(reinterpret_cast(handle), name.c_str())); + } + + void PluginManager::closeLibrary(void *handle) +@@ -74,6 +81,28 @@ + if(path == "") + readpath = "@DEFAULT_PLUGIN_PATH@"; + ++#ifdef __MINGW32__ ++ char modPath[MAX_PATH]; ++ HMODULE hm = NULL; ++ ++ if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | ++ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, ++ (LPCSTR) &dummyChar, &hm)) ++ { ++ if (GetModuleFileNameA(hm, modPath, sizeof(modPath))) ++ { ++ PathRemoveFileSpecA(modPath); ++ std::string dllPath; ++ dllPath.append(modPath); ++ readpath = dllPath + "/../" + readpath; ++ } else { ++ int ret = GetLastError(); ++ } ++ } else { ++ int ret = GetLastError(); ++ } ++#endif ++ + WIN32_FIND_DATA entry; + bool found_file = true; + std::string search = readpath + "\\*"; +--- audaspace-1.3.0/bindings/python/setup.py.in.orig 2019-08-02 09:49:04.186804600 +0300 ++++ audaspace-1.3.0/bindings/python/setup.py.in 2019-08-02 09:51:46.304689500 +0300 +@@ -31,8 +31,12 @@ + extra_args = [] + + if sys.platform == 'win32': +- extra_args.append('/EHsc') +- extra_args.append('/DAUD_BUILD_SHARED_LIBRARY') ++ if 'GCC' in sys.version: ++ extra_args.append('-std=c++11') ++ extra_args.append('-DAUD_BUILD_SHARED_LIBRARY') ++ else: ++ extra_args.append('/EHsc') ++ extra_args.append('/DAUD_BUILD_SHARED_LIBRARY') + else: + extra_args.append('-std=c++11') + diff --git a/mingw-w64-audaspace/PKGBUILD b/mingw-w64-audaspace/PKGBUILD new file mode 100644 index 0000000000..36c67a8a2d --- /dev/null +++ b/mingw-w64-audaspace/PKGBUILD @@ -0,0 +1,71 @@ +# Maintainer: Alexey Pavlov + +_realname=audaspace +pkgbase=mingw-w64-${_realname} +pkgname="${MINGW_PACKAGE_PREFIX}-${_realname}" +pkgver=1.3.0 +pkgrel=1 +pkgdesc="A high level audio library written in C++ with language bindings for Python (mingw-w64)" +arch=('any') +license=('Apache') +depends=("${MINGW_PACKAGE_PREFIX}-ffmpeg" + "${MINGW_PACKAGE_PREFIX}-fftw" + "${MINGW_PACKAGE_PREFIX}-libsndfile" + "${MINGW_PACKAGE_PREFIX}-openal" + "${MINGW_PACKAGE_PREFIX}-python3" + "${MINGW_PACKAGE_PREFIX}-SDL2") +makedepends=("${MINGW_PACKAGE_PREFIX}-cmake" + "${MINGW_PACKAGE_PREFIX}-gcc" + "${MINGW_PACKAGE_PREFIX}-pkg-config") +url="https://audaspace.github.io/" +source=(${_realname}-${pkgver}.tar.gz::https://github.com/audaspace/audaspace/archive/v${pkgver}.tar.gz + 01-gcc7-build.patch + 02-support-new-ffmpeg.patch + 03-backport-from-blender.patch + 04-python-memory-leak.patch + 05-openal-recreate-device.patch + 10-mingw-relocate.patch) +options=('!strip' 'staticlibs') +sha256sums=('20f6669ca0b9403cdf0b21141a494315d153ad00afccaad72c2e4e86586591d2' + 'fe5dfc6b6bc59edddaf923f6713903a55783523c75cad93841db4e36a493cca4' + 'fb99e50be7313c8b82fe6a6bc47ef2f77efdab5b27d516576d3ff7a31a176b87' + '618873a31579427eba61529a14fad665285c9403c9e3196fc476605bf4e58cf3' + 'a490c4f2c4aaf2fa3c87ba623b0179b731d9fb390c38ce04113e01c7cec3c7b7' + 'b17869e66c784f96c01871ac06a519ef94804ec11ea367f4c9a2a95dbd5fabb1' + 'cc68bcc7154c1b06e96e86c587aeafbd6befa5538cf813ee5c42a3ccc13e357d') + +prepare() { + cd ${_realname}-${pkgver} + patch -p1 -i ${srcdir}/01-gcc7-build.patch + patch -p1 -i ${srcdir}/02-support-new-ffmpeg.patch + patch -p1 -i ${srcdir}/03-backport-from-blender.patch + patch -p1 -i ${srcdir}/04-python-memory-leak.patch + patch -p1 -i ${srcdir}/05-openal-recreate-device.patch + patch -p1 -i ${srcdir}/10-mingw-relocate.patch +} + +build() { + declare -a _btype + if check_option "debug" "y"; then + _btype=Debug + else + _btype=Release + fi + + [[ -d ${srcdir}/build-${MINGW_CHOST} ]] && rm -rf ${srcdir}/build-${MINGW_CHOST} + mkdir -p ${srcdir}/build-${MINGW_CHOST} && cd ${srcdir}/build-${MINGW_CHOST} + + MSYS2_ARG_CONV_EXCL="-DCMAKE_INSTALL_PREFIX=" \ + ${MINGW_PREFIX}/bin/cmake.exe \ + -G"MSYS Makefiles" \ + -DCMAKE_INSTALL_PREFIX=${MINGW_PREFIX} \ + -DCMAKE_BUILD_TYPE=${_btype} \ + ../${_realname}-${pkgver} + make +} + +package() { + cd "${srcdir}//build-${MINGW_CHOST}" + make DESTDIR=${pkgdir} -j1 install + install -Dm644 "${srcdir}/${_realname}-${pkgver}/LICENSE" "${pkgdir}${MINGW_PREFIX}/share/licenses/${_realname}/LICENSE" +}