Use unique_ptr for most non-wx owning pointers

This commit is contained in:
Thomas Goyne 2013-06-07 21:19:40 -07:00
parent d81dfc1e73
commit f21a72992b
74 changed files with 610 additions and 750 deletions

View file

@ -36,9 +36,6 @@
#include "ass_export_filter.h"
#include "utils.h"
#include <algorithm>
#include <boost/format.hpp>
static FilterList& filters() {
@ -53,7 +50,7 @@ AssExportFilter::AssExportFilter(std::string const& name, std::string const& des
{
}
void AssExportFilterChain::Register(AssExportFilter *filter) {
void AssExportFilterChain::Register(std::unique_ptr<AssExportFilter>&& filter) {
int filter_copy = 1;
std::string name = filter->name;
// Find a unique name
@ -64,36 +61,22 @@ void AssExportFilterChain::Register(AssExportFilter *filter) {
// Look for place to insert
auto begin(filters().begin()), end(filters().end());
while (begin != end && (*begin)->priority >= filter->priority) ++begin;
filters().insert(begin, filter);
while (begin != end && begin->priority >= filter->priority) ++begin;
filters().insert(begin, *filter.release());
}
void AssExportFilterChain::Unregister(AssExportFilter *filter) {
auto it = remove(begin(filters()), end(filters()), filter);
if (it == end(filters()))
throw wxString::Format("Unregister export filter: name \"%s\" is not registered.", filter->name);
filters().pop_back();
}
const FilterList *AssExportFilterChain::GetFilterList() {
FilterList *AssExportFilterChain::GetFilterList() {
return &filters();
}
void AssExportFilterChain::Clear() {
while (filters().size() > 0) {
AssExportFilter *f = filters().back();
delete f;
if (filters().size() && filters().back() == f)
filters().pop_back();
}
filters().clear_and_dispose([](AssExportFilter *f) { delete f; });
}
AssExportFilter *AssExportFilterChain::GetFilter(std::string const& name) {
for (auto filter : filters()) {
if (filter->name == name)
return filter;
for (auto& filter : filters()) {
if (filter.name == name)
return &filter;
}
return 0;
return nullptr;
}

View file

@ -34,34 +34,17 @@
#pragma once
#include <boost/intrusive/list.hpp>
#include <memory>
#include <string>
#include <vector>
class AssFile;
class AssExportFilter;
class AssExportFilterChain;
class wxWindow;
namespace agi { struct Context; }
typedef std::vector<AssExportFilter*> FilterList;
class AssExportFilterChain {
public:
/// Register an export filter
static void Register(AssExportFilter *filter);
/// Unregister an export filter; must have been registered
static void Unregister(AssExportFilter *filter);
/// Unregister and delete all export filters
static void Clear();
/// Get a filter by name or nullptr if it doesn't exist
static AssExportFilter *GetFilter(std::string const& name);
/// Get the list of registered filters
static const FilterList *GetFilterList();
};
class AssExportFilter {
class AssExportFilter : public boost::intrusive::make_list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>::type {
/// The filter chain needs to be able to muck around with filter names when
/// they're registered to avoid duplicates
friend class AssExportFilterChain;
@ -98,3 +81,18 @@ public:
/// @param c Project context
virtual void LoadSettings(bool is_default, agi::Context *c) { }
};
typedef boost::intrusive::make_list<AssExportFilter, boost::intrusive::constant_time_size<false>>::type FilterList;
class AssExportFilterChain {
public:
/// Register an export filter
static void Register(std::unique_ptr<AssExportFilter>&& filter);
/// Unregister and delete all export filters
static void Clear();
/// Get a filter by name or nullptr if it doesn't exist
static AssExportFilter *GetFilter(std::string const& name);
/// Get the list of registered filters
static FilterList *GetFilterList();
};

View file

@ -42,18 +42,9 @@
#include "include/aegisub/context.h"
#include "subtitle_format.h"
#include <algorithm>
#include <memory>
#include <wx/sizer.h>
static inline FilterList::const_iterator filter_list_begin() {
return AssExportFilterChain::GetFilterList()->begin();
}
static inline FilterList::const_iterator filter_list_end() {
return AssExportFilterChain::GetFilterList()->end();
}
AssExporter::AssExporter(agi::Context *c)
: c(c)
, is_default(true)
@ -62,16 +53,16 @@ AssExporter::AssExporter(agi::Context *c)
void AssExporter::DrawSettings(wxWindow *parent, wxSizer *target_sizer) {
is_default = false;
for (auto filter : *AssExportFilterChain::GetFilterList()) {
for (auto& filter : *AssExportFilterChain::GetFilterList()) {
// Make sure to construct static box sizer first, so it won't overlap
// the controls on wxMac.
wxSizer *box = new wxStaticBoxSizer(wxVERTICAL, parent, to_wx(filter->GetName()));
wxWindow *window = filter->GetConfigDialogWindow(parent, c);
wxSizer *box = new wxStaticBoxSizer(wxVERTICAL, parent, to_wx(filter.GetName()));
wxWindow *window = filter.GetConfigDialogWindow(parent, c);
if (window) {
box->Add(window, 0, wxEXPAND, 0);
target_sizer->Add(box, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
target_sizer->Show(box, false);
Sizers[filter->GetName()] = box;
Sizers[filter.GetName()] = box;
}
else {
delete box;
@ -80,7 +71,7 @@ void AssExporter::DrawSettings(wxWindow *parent, wxSizer *target_sizer) {
}
void AssExporter::AddFilter(std::string const& name) {
AssExportFilter *filter = AssExportFilterChain::GetFilter(name);
auto filter = AssExportFilterChain::GetFilter(name);
if (!filter) throw "Filter not found: " + name;
@ -89,29 +80,24 @@ void AssExporter::AddFilter(std::string const& name) {
std::vector<std::string> AssExporter::GetAllFilterNames() const {
std::vector<std::string> names;
transform(filter_list_begin(), filter_list_end(),
back_inserter(names), std::mem_fun(&AssExportFilter::GetName));
for (auto& filter : *AssExportFilterChain::GetFilterList())
names.emplace_back(filter.GetName());
return names;
}
AssFile *AssExporter::ExportTransform(wxWindow *export_dialog, bool copy) {
AssFile *subs = copy ? new AssFile(*c->ass) : c->ass;
void AssExporter::Export(agi::fs::path const& filename, std::string const& charset, wxWindow *export_dialog) {
AssFile subs(*c->ass);
for (auto filter : filters) {
filter->LoadSettings(is_default, c);
filter->ProcessSubs(subs, export_dialog);
filter->ProcessSubs(&subs, export_dialog);
}
return subs;
}
void AssExporter::Export(agi::fs::path const& filename, std::string const& charset, wxWindow *export_dialog) {
std::unique_ptr<AssFile> subs(ExportTransform(export_dialog, true));
const SubtitleFormat *writer = SubtitleFormat::GetWriter(filename);
if (!writer)
throw "Unknown file type.";
writer->WriteFile(subs.get(), filename, charset);
writer->WriteFile(&subs, filename, charset);
}
wxSizer *AssExporter::GetSettingsSizer(std::string const& name) {
@ -120,7 +106,7 @@ wxSizer *AssExporter::GetSettingsSizer(std::string const& name) {
}
std::string const& AssExporter::GetDescription(std::string const& name) const {
AssExportFilter *filter = AssExportFilterChain::GetFilter(name);
auto filter = AssExportFilterChain::GetFilter(name);
if (filter)
return filter->GetDescription();
throw "Filter not found: " + name;

View file

@ -44,16 +44,14 @@ namespace agi { struct Context; }
class wxSizer;
class wxWindow;
typedef std::vector<AssExportFilter*> FilterList;
class AssExporter {
typedef FilterList::const_iterator filter_iterator;
typedef std::vector<AssExportFilter*>::const_iterator filter_iterator;
/// Sizers for configuration panels
std::map<std::string, wxSizer*> Sizers;
/// Filters which will be applied to the subtitles
FilterList filters;
std::vector<AssExportFilter*> filters;
/// Input context
agi::Context *c;
@ -72,12 +70,6 @@ public:
/// @throws std::string if filter is not found
void AddFilter(std::string const& name);
/// Run all added export filters
/// @param parent_window Parent window the filters should use when opening dialogs
/// @param copy Should the file be copied rather than transformed in-place?
/// @return The new subtitle file (which is the old one if copy is false)
AssFile *ExportTransform(wxWindow *parent_window = 0, bool copy = false);
/// Apply selected export filters and save with the given charset
/// @param file Target filename
/// @param charset Target charset

View file

@ -46,9 +46,9 @@
#include <boost/algorithm/string/predicate.hpp>
#include <fstream>
AssStyleStorage::~AssStyleStorage() {
agi::util::delete_clear(style);
}
AssStyleStorage::~AssStyleStorage() { }
void AssStyleStorage::clear() { style.clear(); }
void AssStyleStorage::push_back( std::unique_ptr<AssStyle>&& new_style ) { style.emplace_back(std::move(new_style)); }
void AssStyleStorage::Save() const {
if (file.empty()) return;
@ -58,19 +58,19 @@ void AssStyleStorage::Save() const {
agi::io::Save out(file);
out.Get() << "\xEF\xBB\xBF";
for (const AssStyle *cur : style)
for (auto const& cur : style)
out.Get() << cur->GetEntryData() << std::endl;
}
void AssStyleStorage::Load(agi::fs::path const& filename) {
file = filename;
Clear();
clear();
try {
std::unique_ptr<std::ifstream> in(agi::io::Open(file));
for (auto const& line : agi::line_iterator<std::string>(*in)) {
try {
style.push_back(new AssStyle(line));
style.emplace_back(agi::util::make_unique<AssStyle>(line));
} catch(...) {
/* just ignore invalid lines for now */
}
@ -81,26 +81,21 @@ void AssStyleStorage::Load(agi::fs::path const& filename) {
}
}
void AssStyleStorage::Clear() {
agi::util::delete_clear(style);
}
void AssStyleStorage::Delete(int idx) {
delete style[idx];
style.erase(style.begin() + idx);
}
std::vector<std::string> AssStyleStorage::GetNames() {
std::vector<std::string> names;
for (const AssStyle *cur : style)
for (auto const& cur : style)
names.emplace_back(cur->name);
return names;
}
AssStyle *AssStyleStorage::GetStyle(std::string const& name) {
for (AssStyle *cur : style) {
for (auto& cur : style) {
if (boost::iequals(cur->name, name))
return cur;
return cur.get();
}
return 0;
}

View file

@ -35,7 +35,7 @@
#include <libaegisub/fs_fwd.h>
#include <boost/filesystem/path.hpp>
#include <deque>
#include <memory>
#include <string>
#include <vector>
@ -43,28 +43,26 @@ class AssStyle;
class AssStyleStorage {
agi::fs::path file;
std::deque<AssStyle*> style;
std::vector<std::unique_ptr<AssStyle>> style;
public:
~AssStyleStorage();
typedef std::deque<AssStyle*>::iterator iterator;
typedef std::deque<AssStyle*>::const_iterator const_iterator;
typedef std::vector<std::unique_ptr<AssStyle>>::iterator iterator;
typedef std::vector<std::unique_ptr<AssStyle>>::const_iterator const_iterator;
iterator begin() { return style.begin(); }
iterator end() { return style.end(); }
const_iterator begin() const { return style.begin(); }
const_iterator end() const { return style.end(); }
void push_back(AssStyle *new_style) { style.push_back(new_style); }
AssStyle *back() { return style.back(); }
AssStyle *operator[](size_t idx) const { return style[idx]; }
void push_back(std::unique_ptr<AssStyle>&& new_style);
AssStyle *back() { return style.back().get(); }
AssStyle *operator[](size_t idx) const { return style[idx].get(); }
size_t size() const { return style.size(); }
void clear();
/// Get the names of all styles in this storage
std::vector<std::string> GetNames();
/// Delete all styles in this storage
void Clear();
/// Delete the style at the given index
void Delete(int idx);

View file

@ -58,8 +58,6 @@
AudioController::AudioController(agi::Context *context)
: context(context)
, subtitle_save_slot(context->subsController->AddFileSaveListener(&AudioController::OnSubtitlesSave, this))
, player(0)
, provider(0)
, playback_mode(PM_NotPlaying)
, playback_timer(this)
{
@ -107,8 +105,7 @@ void AudioController::OnPlaybackTimer(wxTimerEvent &)
void AudioController::OnComputerSuspending(wxPowerEvent &)
{
Stop();
delete player;
player = 0;
player.reset();
}
void AudioController::OnComputerResuming(wxPowerEvent &)
@ -117,7 +114,7 @@ void AudioController::OnComputerResuming(wxPowerEvent &)
{
try
{
player = AudioPlayerFactory::GetAudioPlayer(provider);
player = AudioPlayerFactory::GetAudioPlayer(provider.get());
}
catch (...)
{
@ -133,11 +130,11 @@ void AudioController::OnAudioPlayerChanged()
Stop();
delete player;
player.reset();
try
{
player = AudioPlayerFactory::GetAudioPlayer(provider);
player = AudioPlayerFactory::GetAudioPlayer(provider.get());
}
catch (...)
{
@ -159,7 +156,7 @@ void AudioController::OpenAudio(agi::fs::path const& url)
if (url.empty())
throw agi::InternalError("AudioController::OpenAudio() was passed an empty string. This must not happen.", 0);
AudioProvider *new_provider = 0;
std::unique_ptr<AudioProvider> new_provider;
try {
new_provider = AudioProviderFactory::GetProvider(url);
config::path->SetToken("?audio", url);
@ -173,16 +170,15 @@ void AudioController::OpenAudio(agi::fs::path const& url)
}
CloseAudio();
provider = new_provider;
provider = std::move(new_provider);
try
{
player = AudioPlayerFactory::GetAudioPlayer(provider);
player = AudioPlayerFactory::GetAudioPlayer(provider.get());
}
catch (...)
{
delete provider;
provider = 0;
provider.reset();
throw;
}
@ -192,7 +188,7 @@ void AudioController::OpenAudio(agi::fs::path const& url)
try
{
AnnounceAudioOpen(provider);
AnnounceAudioOpen(provider.get());
}
catch (...)
{
@ -205,8 +201,8 @@ void AudioController::CloseAudio()
{
Stop();
delete player;
delete provider;
player.reset();
provider.reset();
player = 0;
provider = 0;

View file

@ -86,10 +86,10 @@ class AudioController : public wxEvtHandler {
agi::signal::Signal<> AnnounceTimingControllerChanged;
/// The audio output object
AudioPlayer *player;
std::unique_ptr<AudioPlayer> player;
/// The audio provider
AudioProvider *provider;
std::unique_ptr<AudioProvider> provider;
/// The current timing mode, if any; owned by the audio controller
std::unique_ptr<AudioTimingController> timing_controller;

View file

@ -37,12 +37,6 @@
#include "audio_display.h"
#include <algorithm>
#include <wx/dcbuffer.h>
#include <wx/dcclient.h>
#include <wx/mousestate.h>
#include "ass_time.h"
#include "audio_colorscheme.h"
#include "audio_controller.h"
@ -59,6 +53,14 @@
#include "utils.h"
#include "video_context.h"
#include <libaegisub/util.h>
#include <algorithm>
#include <wx/dcbuffer.h>
#include <wx/dcclient.h>
#include <wx/mousestate.h>
/// @brief Colourscheme-based UI colour provider
///
/// This class provides UI colours corresponding to the supplied audio colour
@ -729,7 +731,7 @@ void AudioDisplay::ReloadRenderingSettings()
if (OPT_GET("Audio/Spectrum")->GetBool())
{
colour_scheme_name = OPT_GET("Colour/Audio Display/Spectrum")->GetString();
AudioSpectrumRenderer *audio_spectrum_renderer = new AudioSpectrumRenderer(colour_scheme_name);
auto audio_spectrum_renderer = agi::util::make_unique<AudioSpectrumRenderer>(colour_scheme_name);
int64_t spectrum_quality = OPT_GET("Audio/Renderer/Spectrum/Quality")->GetInt();
#ifdef WITH_FFTW3
@ -746,12 +748,12 @@ void AudioDisplay::ReloadRenderingSettings()
spectrum_width[spectrum_quality],
spectrum_distance[spectrum_quality]);
audio_renderer_provider.reset(audio_spectrum_renderer);
audio_renderer_provider = std::move(audio_spectrum_renderer);
}
else
{
colour_scheme_name = OPT_GET("Colour/Audio Display/Waveform")->GetString();
audio_renderer_provider.reset(new AudioWaveformRenderer(colour_scheme_name));
audio_renderer_provider = agi::util::make_unique<AudioWaveformRenderer>(colour_scheme_name);
}
audio_renderer->SetRenderer(audio_renderer_provider.get());
@ -1061,7 +1063,7 @@ void AudioDisplay::OnMouseEvent(wxMouseEvent& event)
if (markers.size())
{
RemoveTrackCursor();
audio_marker.reset(new AudioMarkerInteractionObject(markers, timing, this, (wxMouseButton)event.GetButton()));
audio_marker = agi::util::make_unique<AudioMarkerInteractionObject>(markers, timing, this, (wxMouseButton)event.GetButton());
SetDraggedObject(audio_marker.get());
return;
}

View file

@ -33,16 +33,16 @@
/// @ingroup audio_ui
///
#include <cstdint>
#include <deque>
#include <map>
#include <cstdint>
#include <memory>
#include <wx/gdicmn.h>
#include <wx/string.h>
#include <wx/timer.h>
#include <wx/window.h>
#include <libaegisub/scoped_ptr.h>
#include <libaegisub/signal.h>
namespace agi { struct Context; }
@ -105,22 +105,22 @@ class AudioDisplay: public wxWindow {
agi::Context *context;
/// The audio renderer manager
agi::scoped_ptr<AudioRenderer> audio_renderer;
std::unique_ptr<AudioRenderer> audio_renderer;
/// The current audio renderer
agi::scoped_ptr<AudioRendererBitmapProvider> audio_renderer_provider;
std::unique_ptr<AudioRendererBitmapProvider> audio_renderer_provider;
/// The controller managing us
AudioController *controller;
/// Scrollbar helper object
agi::scoped_ptr<AudioDisplayScrollbar> scrollbar;
std::unique_ptr<AudioDisplayScrollbar> scrollbar;
/// Timeline helper object
agi::scoped_ptr<AudioDisplayTimeline> timeline;
std::unique_ptr<AudioDisplayTimeline> timeline;
/// The interaction object for the last-dragged audio marker
agi::scoped_ptr<AudioMarkerInteractionObject> audio_marker;
std::unique_ptr<AudioMarkerInteractionObject> audio_marker;
/// Current object on display being dragged, if any

View file

@ -28,6 +28,8 @@
#include "pen.h"
#include "video_context.h"
#include <libaegisub/util.h>
#include <algorithm>
class AudioMarkerKeyframe : public AudioMarker {
@ -123,7 +125,7 @@ void VideoPositionMarkerProvider::Update(int frame_number) {
void VideoPositionMarkerProvider::OptChanged(agi::OptionValue const& opt) {
if (opt.GetBool()) {
video_seek_slot.Unblock();
marker.reset(new VideoPositionMarker);
marker = agi::util::make_unique<VideoPositionMarker>();
marker->SetPosition(vc->GetFrameN());
}
else {

View file

@ -21,9 +21,9 @@
#pragma once
#include <libaegisub/scoped_ptr.h>
#include <libaegisub/signal.h>
#include <memory>
#include <vector>
#include <wx/string.h>
@ -135,7 +135,7 @@ class AudioMarkerProviderKeyframes : public AudioMarkerProvider {
std::vector<AudioMarkerKeyframe> markers;
/// Pen used for all keyframe markers, stored here for performance reasons
agi::scoped_ptr<Pen> style;
std::unique_ptr<Pen> style;
/// Regenerate the list of markers
void Update();
@ -158,7 +158,7 @@ public:
class VideoPositionMarkerProvider : public AudioMarkerProvider {
VideoContext *vc;
agi::scoped_ptr<VideoPositionMarker> marker;
std::unique_ptr<VideoPositionMarker> marker;
agi::signal::Connection video_seek_slot;
agi::signal::Connection enable_opt_changed_slot;
@ -188,7 +188,7 @@ class SecondsMarkerProvider : public AudioMarkerProvider {
};
/// Pen used by all seconds markers, here for performance
agi::scoped_ptr<Pen> pen;
std::unique_ptr<Pen> pen;
/// Markers returned from last call to GetMarkers
mutable std::vector<Marker> markers;

View file

@ -51,7 +51,7 @@ AudioPlayer::AudioPlayer(AudioProvider *provider)
{
}
AudioPlayer* AudioPlayerFactory::GetAudioPlayer(AudioProvider *provider) {
std::unique_ptr<AudioPlayer> AudioPlayerFactory::GetAudioPlayer(AudioProvider *provider) {
std::vector<std::string> list = GetClasses(OPT_GET("Audio/Player")->GetString());
if (list.empty()) throw agi::NoAudioPlayersError("No audio players are available.", 0);
@ -88,5 +88,3 @@ void AudioPlayerFactory::RegisterProviders() {
Register<OSSPlayer>("OSS");
#endif
}
template<> AudioPlayerFactory::map *FactoryBase<AudioPlayer *(*)(AudioProvider*)>::classes = nullptr;

View file

@ -35,12 +35,6 @@
#include "config.h"
#ifdef WITH_DIRECTSOUND
#include <mmsystem.h>
#include <process.h>
#include <dsound.h>
#include <libaegisub/log.h>
#include "audio_player_dsound2.h"
#include "audio_controller.h"
@ -50,6 +44,14 @@
#include "options.h"
#include "utils.h"
#include <libaegisub/scoped_ptr.h>
#include <libaegisub/log.h>
#include <libaegisub/util.h>
#include <mmsystem.h>
#include <process.h>
#include <dsound.h>
/// @brief RAII support class to init and de-init the COM library
struct COMInitialization {
@ -812,7 +814,7 @@ DirectSoundPlayer2::DirectSoundPlayer2(AudioProvider *provider)
try
{
thread.reset(new DirectSoundPlayer2Thread(provider, WantedLatency, BufferLength));
thread = agi::util::make_unique<DirectSoundPlayer2Thread>(provider, WantedLatency, BufferLength);
}
catch (const char *msg)
{

View file

@ -36,8 +36,6 @@
#include "include/aegisub/audio_player.h"
#include <libaegisub/scoped_ptr.h>
class DirectSoundPlayer2Thread;
/// @class DirectSoundPlayer2
@ -48,7 +46,7 @@ class DirectSoundPlayer2Thread;
/// send commands to the playback thread.
class DirectSoundPlayer2 : public AudioPlayer {
/// The playback thread
agi::scoped_ptr<DirectSoundPlayer2Thread> thread;
std::unique_ptr<DirectSoundPlayer2Thread> thread;
/// Desired length in milliseconds to write ahead of the playback cursor
int WantedLatency;

View file

@ -52,6 +52,7 @@
#include <libaegisub/fs.h>
#include <libaegisub/log.h>
#include <libaegisub/util.h>
void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count, double volume) const {
GetAudio(buf, start, count);
@ -116,9 +117,9 @@ struct provider_creator {
provider_creator() : found_file(false) , found_audio(false) { }
template<typename Factory>
AudioProvider *try_create(std::string const& name, Factory&& create) {
std::unique_ptr<AudioProvider> try_create(std::string const& name, Factory&& create) {
try {
AudioProvider *provider = create();
std::unique_ptr<AudioProvider> provider = create();
if (provider)
LOG_I("audio_provider") << "Using audio provider: " << name;
return provider;
@ -144,11 +145,13 @@ struct provider_creator {
};
}
AudioProvider *AudioProviderFactory::GetProvider(agi::fs::path const& filename) {
std::unique_ptr<AudioProvider> AudioProviderFactory::GetProvider(agi::fs::path const& filename) {
provider_creator creator;
AudioProvider *provider = nullptr;
std::unique_ptr<AudioProvider> provider;
provider = creator.try_create("Dummy audio provider", [&]() { return new DummyAudioProvider(filename); });
provider = creator.try_create("Dummy audio provider", [&]() {
return agi::util::make_unique<DummyAudioProvider>(filename);
});
// Try a PCM provider first
if (!provider && !OPT_GET("Provider/Audio/PCM/Disable")->GetBool())
@ -176,20 +179,20 @@ AudioProvider *AudioProviderFactory::GetProvider(agi::fs::path const& filename)
// Give it a converter if needed
if (provider->GetBytesPerSample() != 2 || provider->GetSampleRate() < 32000 || provider->GetChannels() != 1)
provider = CreateConvertAudioProvider(provider);
provider = CreateConvertAudioProvider(std::move(provider));
// Change provider to RAM/HD cache if needed
int cache = OPT_GET("Audio/Cache/Type")->GetInt();
if (!cache || !needsCache)
return new LockAudioProvider(provider);
return agi::util::make_unique<LockAudioProvider>(std::move(provider));
DialogProgress progress(wxGetApp().frame, _("Load audio"));
// Convert to RAM
if (cache == 1) return new RAMAudioProvider(provider, &progress);
if (cache == 1) return agi::util::make_unique<RAMAudioProvider>(std::move(provider), &progress);
// Convert to HD
if (cache == 2) return new HDAudioProvider(provider, &progress);
if (cache == 2) return agi::util::make_unique<HDAudioProvider>(std::move(provider), &progress);
throw agi::AudioCacheOpenError("Unknown caching method", 0);
}
@ -202,5 +205,3 @@ void AudioProviderFactory::RegisterProviders() {
Register<FFmpegSourceAudioProvider>("FFmpegSource");
#endif
}
template<> AudioProviderFactory::map *FactoryBase<AudioProvider *(*)(agi::fs::path)>::classes = nullptr;

View file

@ -27,17 +27,19 @@
#include "audio_controller.h"
#include "include/aegisub/audio_provider.h"
#include <libaegisub/scoped_ptr.h>
#include <libaegisub/log.h>
#include <libaegisub/util.h>
#include <limits>
/// Base class for all wrapping converters
class AudioProviderConverter : public AudioProvider {
protected:
agi::scoped_ptr<AudioProvider> source;
std::unique_ptr<AudioProvider> source;
public:
AudioProviderConverter(AudioProvider *src) : source(src) {
AudioProviderConverter(std::unique_ptr<AudioProvider>&& src)
: source(std::move(src))
{
channels = source->GetChannels();
num_samples = source->GetNumSamples();
sample_rate = source->GetSampleRate();
@ -55,11 +57,11 @@ class BitdepthConvertAudioProvider : public AudioProviderConverter {
int src_bytes_per_sample;
bool src_is_native_endian;
public:
BitdepthConvertAudioProvider(AudioProvider *src) : AudioProviderConverter(src) {
BitdepthConvertAudioProvider(std::unique_ptr<AudioProvider>&& src) : AudioProviderConverter(std::move(src)) {
if (bytes_per_sample > 8)
throw agi::AudioProviderOpenError("Audio format converter: audio with bitdepths greater than 64 bits/sample is currently unsupported", 0);
src_is_native_endian = src->AreSamplesNativeEndian();
src_is_native_endian = source->AreSamplesNativeEndian();
src_bytes_per_sample = bytes_per_sample;
bytes_per_sample = sizeof(Target);
}
@ -110,8 +112,8 @@ public:
template<class Source, class Target>
class FloatConvertAudioProvider : public AudioProviderConverter {
public:
FloatConvertAudioProvider(AudioProvider *src) : AudioProviderConverter(src) {
if (!src->AreSamplesNativeEndian())
FloatConvertAudioProvider(std::unique_ptr<AudioProvider>&& src) : AudioProviderConverter(std::move(src)) {
if (!source->AreSamplesNativeEndian())
throw agi::AudioProviderOpenError("Audio format converter: Float audio with non-native endianness is currently unsupported.", 0);
bytes_per_sample = sizeof(Target);
float_samples = false;
@ -144,7 +146,7 @@ public:
class DownmixAudioProvider : public AudioProviderConverter {
int src_channels;
public:
DownmixAudioProvider(AudioProvider *src) : AudioProviderConverter(src) {
DownmixAudioProvider(std::unique_ptr<AudioProvider>&& src) : AudioProviderConverter(std::move(src)) {
if (bytes_per_sample != 2)
throw agi::InternalError("DownmixAudioProvider requires 16-bit input", 0);
if (channels == 1)
@ -170,14 +172,14 @@ public:
}
};
/// Sample doubler with linear interpolation for the new samples
/// Sample doubler with linear interpolation for the agi::util::make_unique<samples>
/// Requires 16-bit mono input
class SampleDoublingAudioProvider : public AudioProviderConverter {
public:
SampleDoublingAudioProvider(AudioProvider *src) : AudioProviderConverter(src) {
if (src->GetBytesPerSample() != 2)
SampleDoublingAudioProvider(std::unique_ptr<AudioProvider>&& src) : AudioProviderConverter(std::move(src)) {
if (source->GetBytesPerSample() != 2)
throw agi::InternalError("UpsampleAudioProvider requires 16-bit input", 0);
if (src->GetChannels() != 1)
if (source->GetChannels() != 1)
throw agi::InternalError("UpsampleAudioProvider requires mono input", 0);
sample_rate *= 2;
@ -210,33 +212,31 @@ public:
}
};
AudioProvider *CreateConvertAudioProvider(AudioProvider *source_provider) {
AudioProvider *provider = source_provider;
std::unique_ptr<AudioProvider> CreateConvertAudioProvider(std::unique_ptr<AudioProvider>&& provider) {
// Ensure 16-bit audio with proper endianness
if (provider->AreSamplesFloat()) {
LOG_D("audio_provider") << "Converting float to S16";
if (provider->GetBytesPerSample() == sizeof(float))
provider = new FloatConvertAudioProvider<float, int16_t>(provider);
provider = agi::util::make_unique<FloatConvertAudioProvider<float, int16_t>>(std::move(provider));
else
provider = new FloatConvertAudioProvider<double, int16_t>(provider);
provider = agi::util::make_unique<FloatConvertAudioProvider<double, int16_t>>(std::move(provider));
}
if (provider->GetBytesPerSample() != 2 || !provider->AreSamplesNativeEndian()) {
LOG_D("audio_provider") << "Converting " << provider->GetBytesPerSample() << " bytes per sample or wrong endian to S16";
provider = new BitdepthConvertAudioProvider<int16_t>(provider);
provider = agi::util::make_unique<BitdepthConvertAudioProvider<int16_t>>(std::move(provider));
}
// We currently only support mono audio
if (provider->GetChannels() != 1) {
LOG_D("audio_provider") << "Downmixing to mono from " << provider->GetChannels() << " channels";
provider = new DownmixAudioProvider(provider);
provider = agi::util::make_unique<DownmixAudioProvider>(std::move(provider));
}
// Some players don't like low sample rate audio
while (provider->GetSampleRate() < 32000) {
LOG_D("audio_provider") << "Doubling sample rate";
provider = new SampleDoublingAudioProvider(provider);
provider = agi::util::make_unique<SampleDoublingAudioProvider>(std::move(provider));
}
return provider;
return std::move(provider);
}

View file

@ -19,7 +19,9 @@
/// @ingroup audio_input
///
#include <memory>
class AudioProvider;
/// Get an audio provider which supplies audio in a format supported by Aegisub's players
AudioProvider *CreateConvertAudioProvider(AudioProvider *source_provider);
std::unique_ptr<AudioProvider> CreateConvertAudioProvider(std::unique_ptr<AudioProvider>&& source_provider);

View file

@ -91,16 +91,15 @@ public:
}
HDAudioProvider::HDAudioProvider(AudioProvider *src, agi::BackgroundRunner *br) {
agi::scoped_ptr<AudioProvider> source(src);
HDAudioProvider::HDAudioProvider(std::unique_ptr<AudioProvider>&& src, agi::BackgroundRunner *br) {
assert(src->AreSamplesNativeEndian()); // Byteswapping should be done before caching
bytes_per_sample = source->GetBytesPerSample();
num_samples = source->GetNumSamples();
channels = source->GetChannels();
sample_rate = source->GetSampleRate();
filename = source->GetFilename();
float_samples = source->AreSamplesFloat();
bytes_per_sample = src->GetBytesPerSample();
num_samples = src->GetNumSamples();
channels = src->GetChannels();
sample_rate = src->GetSampleRate();
filename = src->GetFilename();
float_samples = src->AreSamplesFloat();
// Check free space
if ((uint64_t)num_samples * channels * bytes_per_sample > agi::fs::FreeSpace(cache_dir()))
@ -111,9 +110,9 @@ HDAudioProvider::HDAudioProvider(AudioProvider *src, agi::BackgroundRunner *br)
try {
{
agi::io::Save out(diskCacheFilename, true);
br->Run(bind(&HDAudioProvider::FillCache, this, src, &out.Get(), std::placeholders::_1));
br->Run(bind(&HDAudioProvider::FillCache, this, src.get(), &out.Get(), std::placeholders::_1));
}
cache_provider.reset(new RawAudioProvider(diskCacheFilename, src));
cache_provider = agi::util::make_unique<RawAudioProvider>(diskCacheFilename, src.get());
}
catch (...) {
agi::fs::Remove(diskCacheFilename);

View file

@ -34,8 +34,6 @@
#include "include/aegisub/audio_provider.h"
#include <libaegisub/scoped_ptr.h>
namespace agi {
class BackgroundRunner;
class ProgressSink;
@ -45,7 +43,7 @@ class HDAudioProvider : public AudioProvider {
/// Name of the file which the decoded audio is written to
agi::fs::path diskCacheFilename;
/// Audio provider which reads from the decoded cache
agi::scoped_ptr<AudioProvider> cache_provider;
std::unique_ptr<AudioProvider> cache_provider;
/// Fill the cache with all of the data from the source audio provider
/// @param src Audio data to cache
@ -56,7 +54,7 @@ class HDAudioProvider : public AudioProvider {
void FillBuffer(void *buf, int64_t start, int64_t count) const;
public:
HDAudioProvider(AudioProvider *source, agi::BackgroundRunner *br);
HDAudioProvider(std::unique_ptr<AudioProvider>&& source, agi::BackgroundRunner *br);
~HDAudioProvider();
bool AreSamplesNativeEndian() const { return true; }

View file

@ -20,7 +20,9 @@
#include "audio_provider_lock.h"
LockAudioProvider::LockAudioProvider(AudioProvider *source) : source(source) {
LockAudioProvider::LockAudioProvider(std::unique_ptr<AudioProvider>&& source)
: source(std::move(source))
{
channels = source->GetChannels();
num_samples = source->GetNumSamples();
sample_rate = source->GetSampleRate();

View file

@ -27,6 +27,6 @@ class LockAudioProvider : public AudioProvider {
void FillBuffer(void *buf, int64_t start, int64_t count) const;
public:
LockAudioProvider(AudioProvider *source);
LockAudioProvider(std::unique_ptr<AudioProvider>&& source);
bool AreSamplesNativeEndian() const { return source->AreSamplesNativeEndian(); }
};

View file

@ -42,6 +42,7 @@
#include <libaegisub/fs.h>
#include <libaegisub/log.h>
#include <libaegisub/util.h>
#include <cassert>
#include <cstdint>
@ -487,12 +488,12 @@ public:
}
};
AudioProvider *CreatePCMAudioProvider(agi::fs::path const& filename) {
std::unique_ptr<AudioProvider> CreatePCMAudioProvider(agi::fs::path const& filename) {
bool wrong_file_type = true;
std::string msg;
try {
return new RiffWavPCMAudioProvider(filename);
return agi::util::make_unique<RiffWavPCMAudioProvider>(filename);
}
catch (agi::AudioDataNotFoundError const& err) {
msg = "RIFF PCM WAV audio provider: " + err.GetMessage();
@ -503,7 +504,7 @@ AudioProvider *CreatePCMAudioProvider(agi::fs::path const& filename) {
}
try {
return new Wave64AudioProvider(filename);
return agi::util::make_unique<Wave64AudioProvider>(filename);
}
catch (agi::AudioDataNotFoundError const& err) {
msg += "\nWave64 audio provider: " + err.GetMessage();

View file

@ -81,4 +81,4 @@ protected:
};
// Construct the right PCM audio provider (if any) for the file
AudioProvider *CreatePCMAudioProvider(agi::fs::path const& filename);
std::unique_ptr<AudioProvider> CreatePCMAudioProvider(agi::fs::path const& filename);

View file

@ -42,14 +42,11 @@
#include "utils.h"
#include <libaegisub/background_runner.h>
#include <libaegisub/scoped_ptr.h>
#define CacheBits 22
#define CacheBlockSize (1 << CacheBits)
RAMAudioProvider::RAMAudioProvider(AudioProvider *src, agi::BackgroundRunner *br)
{
agi::scoped_ptr<AudioProvider> source(src);
RAMAudioProvider::RAMAudioProvider(std::unique_ptr<AudioProvider>&& src, agi::BackgroundRunner *br) {
try {
blockcache.resize((src->GetNumSamples() * src->GetBytesPerSample() + CacheBlockSize - 1) >> CacheBits);
@ -59,15 +56,15 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *src, agi::BackgroundRunner *br
}
// Copy parameters
samples_native_endian = source->AreSamplesNativeEndian();
bytes_per_sample = source->GetBytesPerSample();
num_samples = source->GetNumSamples();
channels = source->GetChannels();
sample_rate = source->GetSampleRate();
filename = source->GetFilename();
float_samples = source->AreSamplesFloat();
samples_native_endian = src->AreSamplesNativeEndian();
bytes_per_sample = src->GetBytesPerSample();
num_samples = src->GetNumSamples();
channels = src->GetChannels();
sample_rate = src->GetSampleRate();
filename = src->GetFilename();
float_samples = src->AreSamplesFloat();
br->Run(std::bind(&RAMAudioProvider::FillCache, this, src, std::placeholders::_1));
br->Run(std::bind(&RAMAudioProvider::FillCache, this, src.get(), std::placeholders::_1));
}
void RAMAudioProvider::FillCache(AudioProvider *source, agi::ProgressSink *ps) {

View file

@ -54,7 +54,7 @@ class RAMAudioProvider : public AudioProvider {
void FillBuffer(void *buf, int64_t start, int64_t count) const;
public:
RAMAudioProvider(AudioProvider *source, agi::BackgroundRunner *br);
RAMAudioProvider(std::unique_ptr<AudioProvider>&& source, agi::BackgroundRunner *br);
bool AreSamplesNativeEndian() const { return samples_native_endian; }
};

View file

@ -45,11 +45,6 @@
#include "include/aegisub/audio_provider.h"
template<class C, class F> static void for_each(C &container, F const& func)
{
std::for_each(container.begin(), container.end(), func);
}
using std::placeholders::_1;
AudioRendererBitmapCacheBitmapFactory::AudioRendererBitmapCacheBitmapFactory(AudioRenderer *renderer)
@ -176,7 +171,7 @@ void AudioRenderer::ResetBlockCount()
double duration = provider->GetNumSamples() * 1000.0 / provider->GetSampleRate();
size_t rendered_width = (size_t)ceil(duration / pixel_ms);
cache_numblocks = rendered_width / cache_bitmap_width;
for_each(bitmaps, std::bind(&AudioRendererBitmapCache::SetBlockCount, _1, cache_numblocks));
for (auto& bmp : bitmaps) bmp.SetBlockCount(cache_numblocks);
}
}
@ -247,7 +242,7 @@ void AudioRenderer::Render(wxDC &dc, wxPoint origin, int start, int length, Audi
void AudioRenderer::Invalidate()
{
for_each(bitmaps, std::bind(&AudioRendererBitmapCache::Age, _1, 0));
for (auto& bmp : bitmaps) bmp.Age(0);
needs_age = false;
}

View file

@ -50,6 +50,7 @@
#include <libaegisub/dispatch.h>
#include <libaegisub/fs.h>
#include <libaegisub/path.h>
#include <libaegisub/util.h>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/trim.hpp>
@ -178,12 +179,6 @@ namespace Automation4 {
ExportFilter::ExportFilter(std::string const& name, std::string const& description, int priority)
: AssExportFilter(name, description, priority)
{
AssExportFilterChain::Register(this);
}
ExportFilter::~ExportFilter()
{
AssExportFilterChain::Unregister(this);
}
std::string ExportFilter::GetScriptSettingsIdentifier()
@ -293,47 +288,41 @@ namespace Automation4 {
// ScriptManager
ScriptManager::~ScriptManager()
{
delete_clear(scripts);