forked from mia/Aegisub
Use boost.interprocess's mmap wrapper in the PCM provider
This commit is contained in:
parent
3fa48281b0
commit
3222275750
12 changed files with 137 additions and 150 deletions
|
@ -52,6 +52,7 @@
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\color.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\color.h" />
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\dispatch.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\dispatch.h" />
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\exception.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\exception.h" />
|
||||||
|
<ClInclude Include="$(SrcDir)include\libaegisub\file_mapping.h" />
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\fs.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\fs.h" />
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\fs_fwd.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\fs_fwd.h" />
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\hotkey.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\hotkey.h" />
|
||||||
|
@ -77,7 +78,6 @@
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\time.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\time.h" />
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\util.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\util.h" />
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\util_osx.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\util_osx.h" />
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\util_win.h" />
|
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\vfr.h" />
|
<ClInclude Include="$(SrcDir)include\libaegisub\vfr.h" />
|
||||||
<ClInclude Include="$(SrcDir)lagi_pre.h" />
|
<ClInclude Include="$(SrcDir)lagi_pre.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -97,6 +97,7 @@
|
||||||
<ClCompile Include="$(SrcDir)common\charset_conv.cpp" />
|
<ClCompile Include="$(SrcDir)common\charset_conv.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)common\color.cpp" />
|
<ClCompile Include="$(SrcDir)common\color.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)common\dispatch.cpp" />
|
<ClCompile Include="$(SrcDir)common\dispatch.cpp" />
|
||||||
|
<ClCompile Include="$(SrcDir)common\file_mapping.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)common\fs.cpp" />
|
<ClCompile Include="$(SrcDir)common\fs.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)common\hotkey.cpp" />
|
<ClCompile Include="$(SrcDir)common\hotkey.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)common\io.cpp" />
|
<ClCompile Include="$(SrcDir)common\io.cpp" />
|
||||||
|
|
|
@ -80,9 +80,6 @@
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\util_osx.h">
|
<ClInclude Include="$(SrcDir)include\libaegisub\util_osx.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\util_win.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\vfr.h">
|
<ClInclude Include="$(SrcDir)include\libaegisub\vfr.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -167,6 +164,9 @@
|
||||||
<ClInclude Include="$(SrcDir)include\libaegisub\address_of_adaptor.h">
|
<ClInclude Include="$(SrcDir)include\libaegisub\address_of_adaptor.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="$(SrcDir)include\libaegisub\file_mapping.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="$(SrcDir)windows\lagi_pre.cpp">
|
<ClCompile Include="$(SrcDir)windows\lagi_pre.cpp">
|
||||||
|
@ -274,6 +274,9 @@
|
||||||
<ClCompile Include="$(SrcDir)common\karaoke_matcher.cpp">
|
<ClCompile Include="$(SrcDir)common\karaoke_matcher.cpp">
|
||||||
<Filter>Source Files\Common</Filter>
|
<Filter>Source Files\Common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(SrcDir)common\file_mapping.cpp">
|
||||||
|
<Filter>Source Files\Common</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="$(SrcDir)include\libaegisub\charsets.def">
|
<None Include="$(SrcDir)include\libaegisub\charsets.def">
|
||||||
|
|
|
@ -25,6 +25,7 @@ SRC += \
|
||||||
common/charset_conv.cpp \
|
common/charset_conv.cpp \
|
||||||
common/color.cpp \
|
common/color.cpp \
|
||||||
common/dispatch.cpp \
|
common/dispatch.cpp \
|
||||||
|
common/file_mapping.cpp \
|
||||||
common/fs.cpp \
|
common/fs.cpp \
|
||||||
common/hotkey.cpp \
|
common/hotkey.cpp \
|
||||||
common/io.cpp \
|
common/io.cpp \
|
||||||
|
|
66
libaegisub/common/file_mapping.cpp
Normal file
66
libaegisub/common/file_mapping.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
|
#include "libaegisub/file_mapping.h"
|
||||||
|
|
||||||
|
#include "libaegisub/fs.h"
|
||||||
|
#include "libaegisub/util.h"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
using namespace boost::interprocess;
|
||||||
|
|
||||||
|
namespace agi {
|
||||||
|
file_mapping::file_mapping(agi::fs::path const& filename, mode_t mode)
|
||||||
|
#ifdef _WIN32
|
||||||
|
: handle(CreateFileW(filename.wstring().c_str(), (unsigned int)mode, 0, nullptr, OPEN_EXISTING, 0, 0))
|
||||||
|
{
|
||||||
|
if (handle == ipcdetail::invalid_file()) {
|
||||||
|
switch (GetLastError()) {
|
||||||
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
case ERROR_PATH_NOT_FOUND:
|
||||||
|
throw fs::FileNotFound(filename);
|
||||||
|
case ERROR_ACCESS_DENIED:
|
||||||
|
throw fs::ReadDenied(filename);
|
||||||
|
default:
|
||||||
|
throw fs::FileSystemUnknownError(util::ErrorString(GetLastError()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
: handle(ipcdetail::open_existing_file(filename.string().c_str(), mode))
|
||||||
|
{
|
||||||
|
if (handle == ipcdetail::invalid_file()) {
|
||||||
|
switch (errno) {
|
||||||
|
case ENOENT:
|
||||||
|
throw fs::FileNotFound(filename);
|
||||||
|
case EACCES:
|
||||||
|
throw fs::ReadDenied(filename);
|
||||||
|
case EIO:
|
||||||
|
throw fs::FileSystemUnknownError("Fatal I/O opening path: " + filename.string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
file_mapping::~file_mapping() {
|
||||||
|
if (handle != ipcdetail::invalid_file()) {
|
||||||
|
ipcdetail::close_file(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2010, Amar Takhar <verm@aegisub.org>
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -11,18 +11,23 @@
|
||||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
/// @file util.h
|
#include <libaegisub/fs_fwd.h>
|
||||||
/// @brief Public interface for Windows utilities.
|
|
||||||
/// @ingroup libaegisub windows
|
|
||||||
|
|
||||||
#include <string>
|
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
namespace agi {
|
namespace agi {
|
||||||
namespace util {
|
// boost::interprocess::file_mapping is awesome and uses CreateFileA on Windows
|
||||||
std::string ErrorString(DWORD error);
|
class file_mapping {
|
||||||
} // namespace util
|
boost::interprocess::file_handle_t handle;
|
||||||
} // namespace agi
|
|
||||||
|
public:
|
||||||
|
file_mapping(fs::path const& filename, boost::interprocess::mode_t mode);
|
||||||
|
~file_mapping();
|
||||||
|
boost::interprocess::mapping_handle_t get_mapping_handle() const {
|
||||||
|
return boost::interprocess::ipcdetail::mapping_handle_from_file_handle(handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -72,5 +72,7 @@ namespace agi {
|
||||||
return std::any_of(std::begin(r), std::end(r), std::forward<Predicate>(p));
|
return std::any_of(std::begin(r), std::end(r), std::forward<Predicate>(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ErrorString(int error);
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
} // namespace agi
|
} // namespace agi
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include <libaegisub/fs.h>
|
#include <libaegisub/fs.h>
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include <libaegisub/util.h>
|
#include <libaegisub/util.h>
|
||||||
#include <libaegisub/util_win.h>
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "libaegisub/charset_conv_win.h"
|
#include "libaegisub/charset_conv_win.h"
|
||||||
#include "libaegisub/exception.h"
|
#include "libaegisub/exception.h"
|
||||||
#include "libaegisub/scoped_ptr.h"
|
#include "libaegisub/scoped_ptr.h"
|
||||||
#include "libaegisub/util_win.h"
|
#include "libaegisub/util.h"
|
||||||
|
|
||||||
using agi::charset::ConvertW;
|
using agi::charset::ConvertW;
|
||||||
using agi::charset::ConvertLocal;
|
using agi::charset::ConvertLocal;
|
||||||
|
@ -30,6 +30,8 @@ using agi::charset::ConvertLocal;
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
namespace bfs = boost::filesystem;
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
#include <versionhelpers.h>
|
#include <versionhelpers.h>
|
||||||
|
|
||||||
#undef CreateDirectory
|
#undef CreateDirectory
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include <libaegisub/path.h>
|
#include <libaegisub/path.h>
|
||||||
|
|
||||||
#include <libaegisub/util_win.h>
|
#include <libaegisub/util.h>
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
#include "libaegisub/util.h"
|
#include "libaegisub/util.h"
|
||||||
#include "libaegisub/util_win.h"
|
|
||||||
|
|
||||||
#include "libaegisub/charset_conv_win.h"
|
#include "libaegisub/charset_conv_win.h"
|
||||||
|
|
||||||
|
@ -33,7 +32,7 @@ namespace agi {
|
||||||
|
|
||||||
using agi::charset::ConvertW;
|
using agi::charset::ConvertW;
|
||||||
|
|
||||||
std::string ErrorString(DWORD error) {
|
std::string ErrorString(int error) {
|
||||||
LPWSTR lpstr = nullptr;
|
LPWSTR lpstr = nullptr;
|
||||||
|
|
||||||
if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error, 0, reinterpret_cast<LPWSTR>(&lpstr), 0, nullptr) == 0) {
|
if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error, 0, reinterpret_cast<LPWSTR>(&lpstr), 0, nullptr) == 0) {
|
||||||
|
|
|
@ -39,50 +39,21 @@
|
||||||
#include "audio_controller.h"
|
#include "audio_controller.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <libaegisub/file_mapping.h>
|
||||||
#include <libaegisub/fs.h>
|
#include <libaegisub/fs.h>
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include <libaegisub/util.h>
|
#include <libaegisub/util.h>
|
||||||
|
|
||||||
|
#include <boost/interprocess/file_mapping.hpp>
|
||||||
|
#include <boost/interprocess/mapped_region.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#ifndef _WIN32
|
|
||||||
#include <sys/fcntl.h>
|
using namespace boost::interprocess;
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PCMAudioProvider::PCMAudioProvider(agi::fs::path const& filename)
|
PCMAudioProvider::PCMAudioProvider(agi::fs::path const& filename)
|
||||||
#ifdef _WIN32
|
: file(agi::util::make_unique<agi::file_mapping>(filename, read_only))
|
||||||
: file_handle(0, CloseHandle)
|
|
||||||
, file_mapping(0, CloseHandle)
|
|
||||||
{
|
{
|
||||||
file_handle = CreateFile(
|
|
||||||
filename.c_str(),
|
|
||||||
FILE_READ_DATA,
|
|
||||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
|
||||||
0,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (file_handle == INVALID_HANDLE_VALUE)
|
|
||||||
throw agi::fs::FileNotFound(filename);
|
|
||||||
|
|
||||||
file_mapping = CreateFileMapping(
|
|
||||||
file_handle,
|
|
||||||
0,
|
|
||||||
PAGE_READONLY,
|
|
||||||
0, 0,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (file_mapping == 0)
|
|
||||||
throw agi::AudioProviderOpenError("Failed creating file mapping", 0);
|
|
||||||
#else
|
|
||||||
: file_handle(open(filename.c_str(), O_RDONLY), close)
|
|
||||||
{
|
|
||||||
if (file_handle == -1)
|
|
||||||
throw agi::fs::FileNotFound(filename.string());
|
|
||||||
#endif
|
|
||||||
float_samples = false;
|
float_samples = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -93,79 +64,36 @@ PCMAudioProvider::PCMAudioProvider(agi::fs::path const& filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PCMAudioProvider::~PCMAudioProvider() {
|
PCMAudioProvider::~PCMAudioProvider() { }
|
||||||
#ifdef _WIN32
|
|
||||||
if (current_mapping)
|
|
||||||
UnmapViewOfFile(current_mapping);
|
|
||||||
#else
|
|
||||||
if (current_mapping)
|
|
||||||
munmap(current_mapping, mapping_length);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t range_length) const {
|
char *PCMAudioProvider::EnsureRangeAccessible(int64_t start, int64_t length) const {
|
||||||
if (range_start + range_length > file_size)
|
if (start + length > file_size)
|
||||||
throw AudioDecodeError("Attempted to map beyond end of file");
|
throw AudioDecodeError("Attempted to map beyond end of file");
|
||||||
|
|
||||||
// Check whether the requested range is already visible
|
// Check if we can just use the current mapping
|
||||||
if (!current_mapping || range_start < mapping_start || range_start+range_length > mapping_start+(int64_t)mapping_length) {
|
if (region && start >= mapping_start && start + length <= mapping_start + region->get_size())
|
||||||
// It's not visible, change the current mapping
|
return static_cast<char *>(region->get_address()) + start - mapping_start;
|
||||||
if (current_mapping) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
UnmapViewOfFile(current_mapping);
|
|
||||||
#else
|
|
||||||
munmap(current_mapping, mapping_length);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Align range start on a 1 MB boundary and go 16 MB back
|
if (sizeof(size_t) == 4) {
|
||||||
mapping_start = (range_start & ~0xFFFFF) - 0x1000000;
|
mapping_start = start & ~0xFFFFFULL; // Align to 1 MB bondary
|
||||||
if (mapping_start < 0) mapping_start = 0;
|
length += static_cast<size_t>(start - mapping_start);
|
||||||
|
// Map 16 MB or length rounded up to the next MB
|
||||||
if (sizeof(void*) > 4)
|
length = std::min<size_t>(std::max<size_t>(0x1000000U, (length + 0xFFFFF) & ~0xFFFFF), file_size - mapping_start);
|
||||||
// Large address space, use a 2 GB mapping
|
}
|
||||||
mapping_length = 0x80000000;
|
else {
|
||||||
else
|
// Just map the whole file
|
||||||
// Small (32 bit) address space, use a 256 MB mapping
|
mapping_start = 0;
|
||||||
mapping_length = 0x10000000;
|
length = file_size;
|
||||||
|
|
||||||
// Make sure to always make a mapping at least as large as the requested range
|
|
||||||
if ((int64_t)mapping_length < range_length) {
|
|
||||||
if (range_length > (int64_t)(~(size_t)0))
|
|
||||||
throw AudioDecodeError("Requested range larger than max size_t, cannot create view of file");
|
|
||||||
mapping_length = range_length;
|
|
||||||
}
|
|
||||||
// But also make sure we don't try to make a mapping larger than the file
|
|
||||||
if (mapping_start + (int64_t)mapping_length > file_size)
|
|
||||||
mapping_length = (size_t)(file_size - mapping_start);
|
|
||||||
// We already checked that the requested range doesn't extend over the end of the file
|
|
||||||
// Hopefully this should ensure that small files are always mapped in their entirety
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
LARGE_INTEGER mapping_start_li;
|
|
||||||
mapping_start_li.QuadPart = mapping_start;
|
|
||||||
current_mapping = MapViewOfFile(
|
|
||||||
file_mapping, // Mapping handle
|
|
||||||
FILE_MAP_READ, // Access type
|
|
||||||
mapping_start_li.HighPart, // Offset high-part
|
|
||||||
mapping_start_li.LowPart, // Offset low-part
|
|
||||||
mapping_length); // Length of view
|
|
||||||
#else
|
|
||||||
current_mapping = mmap(nullptr, mapping_length, PROT_READ, MAP_PRIVATE, file_handle, mapping_start);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!current_mapping)
|
|
||||||
throw AudioDecodeError("Failed mapping a view of the file");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(current_mapping);
|
try {
|
||||||
assert(range_start >= mapping_start);
|
region = agi::util::make_unique<mapped_region>(*file, read_only, mapping_start, length);
|
||||||
|
}
|
||||||
|
catch (interprocess_exception const&) {
|
||||||
|
throw AudioDecodeError("Failed mapping a view of the file");
|
||||||
|
}
|
||||||
|
|
||||||
// Difference between actual current mapping start and requested range start
|
return static_cast<char *>(region->get_address()) + start - mapping_start;
|
||||||
ptrdiff_t rel_ofs = (ptrdiff_t)(range_start - mapping_start);
|
|
||||||
|
|
||||||
// Calculate a pointer into current mapping for the requested range
|
|
||||||
return ((char*)current_mapping) + rel_ofs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PCMAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const {
|
void PCMAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const {
|
||||||
|
|
|
@ -27,42 +27,23 @@
|
||||||
//
|
//
|
||||||
// Aegisub Project http://www.aegisub.org/
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
/// @file audio_provider_pcm.h
|
|
||||||
/// @see audio_provider_pcm.cpp
|
|
||||||
/// @ingroup audio_input
|
|
||||||
///
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "include/aegisub/audio_provider.h"
|
#include "include/aegisub/audio_provider.h"
|
||||||
|
|
||||||
#include <libaegisub/scoped_ptr.h>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace agi { class file_mapping; }
|
||||||
|
namespace boost { namespace interprocess { class mapped_region; } }
|
||||||
|
|
||||||
class PCMAudioProvider : public AudioProvider {
|
class PCMAudioProvider : public AudioProvider {
|
||||||
mutable void *current_mapping = nullptr;
|
std::unique_ptr<agi::file_mapping> file;
|
||||||
|
mutable std::unique_ptr<boost::interprocess::mapped_region> region;
|
||||||
#ifdef _WIN32
|
|
||||||
mutable int64_t mapping_start = 0;
|
mutable int64_t mapping_start = 0;
|
||||||
mutable size_t mapping_length = 0;
|
|
||||||
|
|
||||||
agi::scoped_holder<HANDLE, BOOL (__stdcall *)(HANDLE)> file_handle;
|
|
||||||
agi::scoped_holder<HANDLE, BOOL (__stdcall *)(HANDLE)> file_mapping;
|
|
||||||
#else
|
|
||||||
mutable off_t mapping_start = 0;
|
|
||||||
mutable size_t mapping_length = 0;
|
|
||||||
|
|
||||||
agi::scoped_holder<int, int(*)(int)> file_handle;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PCMAudioProvider(agi::fs::path const& filename); // Create base object and open the file mapping
|
PCMAudioProvider(agi::fs::path const& filename); // Create base object and open the file mapping
|
||||||
virtual ~PCMAudioProvider(); // Closes the file mapping
|
~PCMAudioProvider(); // Closes the file mapping
|
||||||
char * EnsureRangeAccessible(int64_t range_start, int64_t range_length) const; // Ensure that the given range of bytes are accessible in the file mapping and return a pointer to the first byte of the requested range
|
char *EnsureRangeAccessible(int64_t range_start, int64_t range_length) const; // Ensure that the given range of bytes are accessible in the file mapping and return a pointer to the first byte of the requested range
|
||||||
|
|
||||||
/// Size of the opened file
|
/// Size of the opened file
|
||||||
int64_t file_size = 0;
|
int64_t file_size = 0;
|
||||||
|
|
Loading…
Reference in a new issue